2013-02-16 464 views
3

我开发了一个简单的库,用于修改我在互联网上找到的库。FFmpeg内存泄漏

让我感到害怕的是,当我播放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

你如何测量内存使用量? – 2013-02-16 19:51:55

+0

@stfrabbit我正在使用Windows的任务进程,并且我也使用PROCESS_MEMORY_COUNTERS(WIN32 API)的pmc.WorkingSetSize – Spamdark 2013-02-16 20:07:28

+0

代码在第一次需要时分配内存并不少见,然后保留内存以防万一需要再次。您可以通过多次调用该函数并查看每次调用时是否丢失内存来测试此功能。 – 2013-02-16 20:19:18

回答

0

我也有同样的问题。按照ffplay.c 你应该叫

av_frame_unref(pFrame); 
avcodec_get_frame_defaults(pFrame); 
sw_scale通话后

。这将在解码期间释放所有的malloc。

+0

根据[this](http://ffmpeg.org/doxygen/trunk/group__lavc__core.html#ga98e5e98abf54448b780c97888bbffade),你不应该应该都是,因为第二个是第一个已弃用的版本。 – JonesV 2014-03-20 17:09:50

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); 
0

我也有内存泄漏问题。对我来说,重新分配工作时,我包括下面的命令:

类成员:

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);