2014-09-29 53 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