2014-09-29 172 views
1

我使用FFMPEG解码H264流,我的代码如下FFMPEG:解码H264流时无法释放AVPacket?

AVFormatContext *pFormatCtx = NULL; 
AVCodecContext *pCodecCtx = NULL; 
AVFrame   *pFrame = NULL; 
AVPacket  packet; 
packet.data = NULL; 

pFormatCtx = avformat_alloc_context(); 
avformat_open_input(&pFormatCtx, videoStreamPath, NULL, NULL); 
liveHeader.pCodecCtx = pFormatCtx->streams[videoStreamIndex]->codec; 

int bytesDecoded = 0; 
int frameFinished = 0; 
while (true) 
{ 
    while (packet.size > 0) 
    { 
     // Decode the next chunk of data 
     bytesDecoded = avcodec_decode_video2(pCodecCtx, pFrame, 
      &frameFinished, &packet); 

     // Was there an error? 
     if (bytesDecoded < 0) 
     { 
      printf(strErr, "Error while decoding frame\n"); 
      commonGlobal->WriteRuntimeRecLogs(strErr); 
      return RS_NOT_OK; 
     } 

     packet.size -= bytesDecoded; 
     packet.data += bytesDecoded; 
     if (frameFinished) 
     {    
      //av_free_packet(&packet); //(free 1) 
      return RS_OK; 
     } 
     // Did we finish the current frame? Then we can return 
    } 
    do 
    { 
     try 
     { 
      int ret = av_read_frame(pFormatCtx, &packet); 
      if (ret < 0) 
      { 
       char strErr[STR_LENGTH_256]; 
       if (ret == AVERROR_EOF || (pFormatCtx->pb && pFormatCtx->pb->eof_reached)) 
       { 
        sprintf(strErr, "Error end of file line %d", __LINE__); 
       } 
       if (pFormatCtx->pb && pFormatCtx->pb->error) 
       { 
        sprintf(strErr, "Error end of file line %d", __LINE__); 
       } 
       packet.data = NULL; 
       return RS_NOT_OK; 
      } 
     } 
     catch (...) 
     { 
      packet.data = NULL; 
      return RS_NOT_OK; 
     } 
    } while (packet.stream_index != videoStreamIndex); 
} 

//av_free_packet(&packet); //(free 2) 

的问题是我不知道如何正确释放的内存packet

我试图通过调用av_free_packet(&packet); (free 1)av_free_packet(&packet); (free 2)两个地方之一来删除数据包的数据。结果是应用程序崩溃了消息"Heap Corruption..."

如果我没有释放packet,则会发生内存泄漏。

注意,上面的代码是成功的,当解码H264流,主要的问题是内存泄漏和崩溃,当我尝试释放packet

有人可以告诉我在我的代码的问题。

非常感谢,

牛逼&牛逼

回答

2

av_free_packet将清除您的分组数据,这是内部av_read_frame分配相同的指针。但你改变了它在packet.data += bytesDecoded; =>崩溃。

的几点建议:

  • 不需要调用av_init_packet如果第一次使用你的包是av_read_frame(它是这个函数内完成)。但是,如果您保留代码,则需要将packet.size初始化为0(已测试,但未初始化)

  • 每次您完成分组数据时,只有当解码成功。在您的代码中,这意味着您必须在avcodec_decode_video2之后调用它,即使该框架未完成。

  • 一旦你的填充解码(即avcodec_decode_video2是确定的,不管​​是真的还是假的),你可以释放它。无需保留它并更改数据指针。这个过程是“读取数据包,解码它,释放它,读下一个数据包,解码它,释放它。” (请注意,这不适用于音频数据包)。

我建议简化您通过像主循环(读第一,经过解码):

while(true) 
{ 
    // Step 1: Read packet 
    while(true) 
    { 
     av_read_frame(pFormatCtx, &packet); 

     // todo: Error handling 

     if(packet.stream_index != videoStreamIndex) 
     { 
      av_free_packet(&packet); 
     } 
     else 
     { 
      break; 
     } 
    } while (packet.stream_index != videoStreamIndex); 

    // Step 2/3: Decode and free 
    avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet); 
    av_free_packet(&packet); 

    // todo: Error handling and checking frameFinished if needed 
    // Of course, if you need to use the packet now, move the av_free_packet() after this 
} 
+0

它的工作!非常感谢你^^ – TTGroup 2014-10-02 01:55:41

1

你应该初始化使用前你的包如下:

AVPacket  packet; 
av_init_packet(&packet); 

而且你不删除你的AVFormatContext实例。

avformat_free_context(pFormatCtx); 
+0

谢谢。此代码不完整,实际上我已经调用av_close_input_file(pFormatCtx)而不是avformat_free_context(pFormatCtx);有什么问题吗? – TTGroup 2014-09-29 08:30:01

+0

我想这也应该工作。 – 2014-09-29 08:34:46