FFmpeg内存泄漏

5
我已经开发了一个简单的库,修改了我在互联网上找到的一个库。
让我感到担心的是,当我播放 AVI 文件时,它会在视频结束时播放并释放内存,但当我播放视频时,它就像一个内存泄漏! 它增长到 138MB,尽管视频已经结束,并且已经调用了 FreeAll 方法(一个删除上下文等的函数)。
以下是导致内存泄漏的方法代码:
int VideoGL::NextVideoFrame(){
int frameDone = 0;
int result = 0;
double pts = 0;

if(!this->ended){

if (!_started) return 0;
AVPacket* packet;

// Get the number of milliseconds passed and see if we should display a new frame
int64_t msPassed = (1000 * (clock() - _baseTime)) / CLOCKS_PER_SEC;
if (msPassed >= _currentPts)
{
    // If this is not the current frame, copy it to the buffer
    if (_currentFramePts != _currentPts){
        _currentFramePts = _currentPts;
        memcpy(buffer_a,buffer, 3 * _codec_context_video->width * _codec_context_video->height);
        result = 1;
    }

    // Try to load a new frame from the video packet queue
    bool goodop=false;
    AVFrame *_n_frame = avcodec_alloc_frame();
    while (!frameDone && (packet = this->DEQUEUE(VIDEO)) != NULL)
    {
        if (packet == (AVPacket*)-1) return -1;

        goodop=true;

        _s_pts = packet->pts;
        avcodec_decode_video2(_codec_context_video, _n_frame, &frameDone, packet);
        av_free_packet(packet);

        if (packet->dts == AV_NOPTS_VALUE)
        {
            if (_n_frame->opaque && *(uint64_t*)_n_frame->opaque != AV_NOPTS_VALUE) pts = (double) *(uint64_t*)_n_frame->opaque;
            else pts = 0;
        }
        else pts = (double) packet->dts;

        pts *= av_q2d(_codec_context_video->time_base);

    }

    if (frameDone)
    {
        // if a frame was loaded scale it to the current texture frame buffer, but also set the pts so that it won't be copied to the texture until it's time
        sws_scale(sws_ctx,_n_frame->data, _n_frame->linesize, 0, _codec_context_video->height, _rgb_frame->data, _rgb_frame->linesize);


        double nts = 1.0/av_q2d(_codec_context_video->time_base);
        _currentPts = (uint64_t) (pts*nts);

    }

    avcodec_free_frame(&_n_frame);
    av_free(_n_frame);

    if(!goodop){
        ended=true;
    }
}
}

return result;
}

我会等待回答,谢谢。

(内容已翻译)

3
你是如何衡量内存使用情况的? - Joseph Mansfield
@stfrabbit 我正在使用Windows的任务处理程序,并且我也在使用PROCESS_MEMORY_COUNTERS(WIN32 API)中的pmc.WorkingSetSize。 - Spamdark
代码在第一次需要时分配内存并保留内存以备后用并不罕见。您可以通过多次调用该函数并观察每次调用是否丢失内存来测试此功能。 - Drew Dormann
那么,我如何释放那块内存,我已经调用了av_free_packet、avcodec_free_frame等函数... - Spamdark
3个回答

2

我也曾遇到过内存泄漏的问题。对我来说,当我包含以下命令时,释放内存才有效:

类成员:

AVPacket avpkt;
AVFrame *frame;
AVCodecContext *avctx;
AVCodec *codec;

构造函数:

av_init_packet(&avpkt);
avcodec_open2(avctx, codec, NULL);
frame = avcodec_alloc_frame();

析构函数:

av_free_packet(&avpkt);
avcodec_free_frame(&frame);
av_free(frame);
avcodec_close(avctx);

avcodec_free_frame 现已被弃用/移除。 - Antonio

1
我曾经使用FFmpeg编写了类似的例程,但会出现内存泄漏问题。我通过为每次调用avcodec_decode_video2释放帧和包对象的内存来解决这个问题。
在您的代码中,包对象已被释放,但是帧没有。在avcodec_decode_video2之前添加以下代码可以解决内存泄漏问题。我发现安全地调用已释放的帧对象上的avcodec_free_frame。您可以在while循环之前删除对帧的分配。
avcodec_free_frame(&_n_frame);
_n_frame = avcodec_alloc_frame();
avcodec_decode_video2(_codec_context_video, _n_frame, &frameDone, packet);

1
我也遇到了同样的问题。根据ffplay.c文件,你应该调用


av_frame_unref(pFrame);
avcodec_get_frame_defaults(pFrame);

在每个sw_scale调用之后,这将释放解码期间的所有动态内存。


1
根据 这里 的说明,你不应该同时使用两个函数,因为第二个是第一个被弃用的版本。 - JonasVautherin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接