C++ 使用av_frame_get_buffer()时内存泄漏

C++ 使用av_frame_get_buffer()时内存泄漏,c++,c,windows,ffmpeg,libav,C++,C,Windows,Ffmpeg,Libav,我正在用ffmpeg制作一个简单的视频播放器。我注意到libavutil中有一个内存泄漏。因为ffmpeg是一个成熟的库,所以我假设我分配的新帧不正确。文档中关于释放在调用av\u frame\u get\u buffer()时创建的缓冲区的内容也很模糊。下面是我用来解码视频并将其排队显示在UI线程上的代码 DWORD WINAPI DecoderThread(LPVOID lpParam) { AVFrame *frame = NULL; AVPacket pkt;

我正在用ffmpeg制作一个简单的视频播放器。我注意到libavutil中有一个内存泄漏。因为ffmpeg是一个成熟的库,所以我假设我分配的新帧不正确。文档中关于释放在调用
av\u frame\u get\u buffer()
时创建的缓冲区的内容也很模糊。下面是我用来解码视频并将其排队显示在UI线程上的代码

DWORD WINAPI DecoderThread(LPVOID lpParam)
{
    AVFrame *frame = NULL;
    AVPacket pkt;

    SwsContext *swsCtx = NULL;
    UINT8 *buffer = NULL;
    INT iNumBytes = 0;

    INT result = 0;

    frame = av_frame_alloc();

    av_init_packet(&pkt);
    pkt.data = NULL;
    pkt.size = 0;

    // Create scaling context
    swsCtx = sws_getContext(codecCtx->width, codecCtx->height, codecCtx->pix_fmt, codecCtx->width, codecCtx->height, AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);

   while (av_read_frame(fmtCtx, &pkt) >= 0) {
        if (pkt.stream_index == videoStream) {
            result = avcodec_send_packet(codecCtx, &pkt);

            while (result >= 0) {
                result = avcodec_receive_frame(codecCtx, frame);
                if (result == AVERROR(EAGAIN) || result == AVERROR_EOF) {
                    break;
                } else if (result < 0) {
                    // another error.
                }
                // Create a new frame to store the RGB24 data.
                AVFrame *pFrameRGB = av_frame_alloc();
                // Allocate space for the new RGB image.
                //av_image_alloc(pFrameRGB->data, pFrameRGB->linesize, codecCtx->width, codecCtx->height, AV_PIX_FMT_BGR24, 1);
                // Copy all of the properties from the YUV420P frame.
                av_frame_copy_props(pFrameRGB, frame);
                pFrameRGB->width = frame->width;
                pFrameRGB->height = frame->height;
                pFrameRGB->format = AV_PIX_FMT_BGR24;
                av_frame_get_buffer(pFrameRGB, 0);

                // Convert fram from YUV420P to BGR24 for display.
                sws_scale(swsCtx, (const UINT8* const *) frame->data, frame->linesize, 0, codecCtx->height, pFrameRGB->data, pFrameRGB->linesize);

                // Queue thr BGR frame for drawing by the main thread.
                AddItemToFrameQueue(pFrameRGB);

                av_frame_unref(frame);
            }
        }
       while (GetQueueSize() > 100) {
            Sleep(10);
       }
   }

    CloseFrameQueue();

    av_frame_free(&frame);
   avcodec_close(codecCtx);
   avformat_close_input(&fmtCtx);

    return 0;
}
DWORD WINAPI解码读取(LPVOID lpParam)
{
AVFrame*frame=NULL;
AVPacket-pkt;
SwsContext*swsCtx=NULL;
UINT8*缓冲区=NULL;
INT单位=0;
INT结果=0;
frame=av_frame_alloc();
av_初始_数据包(&pkt);
pkt.data=NULL;
pkt.size=0;
//创建缩放上下文
swsCtx=sws_getContext(codecCtx->width,codecCtx->height,codecCtx->pix_fmt,codecCtx->width,codecCtx->height,AV_pix_fmt_BGR24,sws_双三次,NULL,NULL,NULL);
而(av读取帧(fmtCtx和pkt)>=0){
if(pkt.stream_index==videoStream){
结果=avcodec_发送_数据包(CODECTX和pkt);
而(结果>=0){
结果=avcodec_接收_帧(CODECTX,帧);
如果(结果==平均错误(EAGAIN)|结果==平均错误(EOF){
打破
}否则如果(结果<0){
//另一个错误。
}
//创建新帧以存储RGB24数据。
AVFrame*pFrameRGB=av_frame_alloc();
//为新的RGB图像分配空间。
//av_image_alloc(pFrameRGB->数据,pFrameRGB->线条大小,CODECTX->宽度,CODECTX->高度,av_PIX_FMT_BGR24,1);
//从YUV420P框架复制所有属性。
影音画面复制道具(pFrameRGB,画面);
pFrameRGB->宽度=帧->宽度;
pFrameRGB->高度=帧->高度;
pFrameRGB->format=AV_PIX_FMT_BGR24;
av帧获取缓冲区(pFrameRGB,0);
//将fram从YUV420P转换为BGR24进行显示。
sws_比例(swsCtx,(常数UINT8*常数*)帧->数据,帧->线宽,0,CODECTX->高度,pFrameRGB->数据,pFrameRGB->线宽);
//队列thr BGR框架,用于通过主线程绘制。
AddItemToFrameQueue(pFrameRGB);
av_帧_unref(帧);
}
}
而(GetQueueSize()>100){
睡眠(10);
}
}
CloseFrameQueue();
av_无帧(&帧);
avcodec_close(codecCtx);
AVU格式\关闭\输入(&fmtCtx);
返回0;
}
有没有更好的方法来分配一个新的框架来保存post
sws\u scale()
转换


有一种类似的方法,它使用的函数调用大多是折旧的。我在文档中似乎找不到任何符合ffmpeg新版本的答案。任何帮助都将不胜感激。

根据评论中提出的建议,我在解码循环中添加了一个
av\u packet\u unref()
调用,它阻止了我遇到的内存泄漏问题

                sws_scale(swsCtx, (const UINT8* const *) frame->data, frame->linesize, 0, codecCtx->height, pFrameRGB->data, pFrameRGB->linesize);

            // Queue thr BGR frame for drawing by the main thread.
            AddItemToFrameQueue(pFrameRGB);

            av_frame_unref(frame);
        }
        av_packet_unref(&pkt);
    }
    while (GetQueueSize() > 100) {
        Sleep(10);
    }

您需要为使用
av\u frame\u alloc()分配的每个帧调用
av\u frame\u free()
。您正在释放
frame
,但是
pFrameRGB
呢?您正在将每个
pFrameRGB
帧放入队列,但您没有显示它们离开队列时发生的情况。是的,在主窗口线程中显示帧后,该帧将被释放。如果队列中碰巧有任何剩余,它们也会在
CloseFrameQueue()
函数期间被释放。在每次成功调用
av\u read\u frame()
@RemyLebeau之后,您都不会调用
av\u packet\u unref()
,这是有意义的。我一定在例子中遗漏了这一点。明天我将有机会测试它,谢谢你的洞察力!