2013-05-14 61 views
1

我在avcodec_find_encoder中收到內存泄漏。雖然我正在清理資源 仍然無法擺脫泄漏。通過連續評論代碼,我發現只有在調用avcodec_find_encoder()之後纔會發生內存泄漏。我用不同的視頻文件試過我的代碼,發現內存泄漏塊總是相同的。此外,如果我只打開音頻或視頻,那麼我只能得到一個內存泄漏塊。 以下是應用程序中初始化和清理代碼的一部分。 請注意,這只是包含初始化和資源釋放的代碼的一部分。在ffmpeg中打開編碼器時發生內存泄漏

AVFormatContext *m_informat; 
AVFormatContext *m_outformat; 
AVStream *m_in_vid_strm, *m_out_vid_strm; 
AVStream *m_in_aud_strm, *m_out_aud_strm; 


int VideoClipper::Init(const wxString& filename) 
{ 
    int ret = 0; 
    char errbuf[64]; 

    av_register_all(); 
    if ((ret = avformat_open_input(&m_informat, filename.mb_str(), 0, 0)) != 0) 
    { 
     av_strerror(ret,errbuf,sizeof(errbuf)); 
     PRINT_VAL("Not able to Open file;; ", errbuf) 
     ret = -1; 
     return ret; 
    } 
    else 
    { 
     PRINT_MSG("Opened File ") 
    } 

    if ((ret = avformat_find_stream_info(m_informat, 0))< 0) 
    { 

     av_strerror(ret,errbuf,sizeof(errbuf)); 
     PRINT_VAL("Not Able to find stream info:: ", errbuf) 
     ret = -1; 
     return ret; 
    } 
    else 
    { 
     PRINT_MSG("Got stream Info ") 
    } 

    for(unsigned int i = 0; i<m_informat->nb_streams; i++) 
    { 
     if(m_informat->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 
     { 

      PRINT_MSG("Found Video Stream ") 
      m_in_vid_strm_idx = i; 
      m_in_vid_strm = m_informat->streams[i]; 
     } 

     if(m_informat->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) 
     { 
      PRINT_MSG("Found Audio Stream ") 
      m_in_aud_strm_idx = i; 
      m_in_aud_strm = m_informat->streams[i]; 
     } 
    } 

    AVOutputFormat *outfmt = NULL; 
    std::string outfile = std::string(filename) + "clip_out.avi"; 
    outfmt = av_guess_format(NULL,outfile.c_str(),NULL); 

    if(outfmt == NULL) 
    { 
     ret = -1; 
     return ret; 
    } 
    else 
    { 
     m_outformat = avformat_alloc_context(); 
     if(m_outformat) 
     { 
      m_outformat->oformat = outfmt; 
      _snprintf(m_outformat->filename, sizeof(m_outformat->filename), "%s", outfile.c_str());  
     } 
     else 
     { 
      ret = -1; 
      return ret; 
     } 
    } 

    AVCodec *out_vid_codec,*out_aud_codec; 
    out_vid_codec = out_aud_codec = NULL; 

    if(outfmt->video_codec != AV_CODEC_ID_NONE && m_in_vid_strm != NULL) 
    { 
     out_vid_codec = avcodec_find_encoder(outfmt->video_codec); 
     if(NULL == out_vid_codec) 
     { 
      PRINT_MSG("Could Not Find Vid Encoder") 
      ret = -1; 
      return ret; 
     } 
     else 
     { 
      PRINT_MSG("Found Out Vid Encoder ") 
      m_out_vid_strm = avformat_new_stream(m_outformat, out_vid_codec); 
      if(NULL == m_out_vid_strm) 
      { 
       PRINT_MSG("Failed to Allocate Output Vid Strm ") 
       ret = -1; 
       return ret; 
      } 
      else 
      { 
       PRINT_MSG("Allocated Video Stream ") 
       if(avcodec_copy_context(m_out_vid_strm->codec, m_informat->streams[m_in_vid_strm_idx]->codec) != 0) 
       { 
        PRINT_MSG("Failed to Copy Context ") 
        ret = -1; 
        return ret; 
       } 
       } 
      } 
     } 

    if(outfmt->audio_codec != AV_CODEC_ID_NONE && m_in_aud_strm != NULL) 
    { 
     out_aud_codec = avcodec_find_encoder(outfmt->audio_codec); 
     if(NULL == out_aud_codec) 
     { 
      PRINT_MSG("Could Not Find Out Aud Encoder ") 
      ret = -1; 
      return ret; 
     } 
     else 
     { 
      PRINT_MSG("Found Out Aud Encoder ") 
      m_out_aud_strm = avformat_new_stream(m_outformat, out_aud_codec); 
      if(NULL == m_out_aud_strm) 
      { 
       PRINT_MSG("Failed to Allocate Out Vid Strm ") 
       ret = -1; 
       return ret; 
      } 
      else 
      { 
       if(avcodec_copy_context(m_out_aud_strm->codec, m_informat->streams[m_in_aud_strm_idx]->codec) != 0) 
       { 
        PRINT_MSG("Failed to Copy Context ") 
        ret = -1; 
        return ret; 
       } 
      } 
     } 
     } 

     if (!(outfmt->flags & AVFMT_NOFILE)) 
     { 
     if (avio_open2(&m_outformat->pb, outfile.c_str(), AVIO_FLAG_WRITE,NULL, NULL) < 0) 
     { 
       PRINT_VAL("Could Not Open File ", outfile) 
       ret = -1; 
       return ret; 
     } 
     } 
     /* Write the stream header, if any. */ 
     if (avformat_write_header(m_outformat, NULL) < 0) 
     { 
      PRINT_VAL("Error Occurred While Writing Header ", outfile) 
      ret = -1; 
      return ret; 
     } 
     else 
     { 
      PRINT_MSG("Written Output header ") 
      m_init_done = true; 
     } 

    return ret; 
} 

這裏是清理部分

void VideoClipper::ReleaseResource(void) 
{ 
    if(m_in_aud_strm && m_in_aud_strm->codec) 
    { 
     avcodec_close(m_in_aud_strm->codec); 
     PRINT_MSG("Closed Input Audio Codec ") 
    } 

    if(m_in_vid_strm && m_in_vid_strm->codec) 
    { 
     avcodec_close(m_in_vid_strm->codec); 
     PRINT_MSG("Closed Input Video Codec ") 
    } 

    if(m_informat) 
    { 
     avformat_close_input(&m_informat); 
     PRINT_MSG("Freed Input Format Contex ") 
    } 

    if(m_out_aud_strm && m_out_aud_strm->codec) 
    { 
     avcodec_close(m_out_aud_strm->codec); 
     PRINT_MSG("Closed Output Audio Codec ") 
    } 

    if(m_out_vid_strm && m_out_vid_strm->codec) 
    { 
     avcodec_close(m_out_vid_strm->codec); 
     PRINT_MSG("Closed Output Audio Codec ") 
    } 

    if(m_outformat) 
    { 
     avformat_close_input(&m_outformat); 
     m_outformat = NULL; 
     PRINT_MSG("Closed Output Format ") 
    } 

} 

內存泄漏消息

Detected memory leaks! 
Dumping objects -> 
{13691} normal block at 0x01046A60, 4479 bytes long. 
Data: <    > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
{13685} normal block at 0x01043FD0, 10831 bytes long. 
Data: <   ?  > CD CD CD CD CD CD CD CD D0 3F 04 01 ED ED ED ED 
Object dump complete. 

我使用的是最新版本的ffmpeg上的Visual Studio 2012 請建議,我」失蹤。

感謝 普拉迪普

+0

'm_outformat = avformat_alloc_context();''''和'avformat_close_input(&m_outformat); ' – 2013-05-14 15:15:42

+0

我沒有收到您的評論。你的意思是說我不應該使用avformat_close_input來通過avformat_alloc_context()分配AVFormatContext。但是,如果我不使用avformat_close_input那麼內存泄漏增加:(。 – praks411 2013-05-14 15:39:04

回答

0

有很多的事情,第一重要的位置

你需要關閉IO

if (!(fmt->flags & AVFMT_NOFILE)) 
{ 
    /* Close the output file. */ 
    avio_close(ctx->oc->pb); 
} 

你也應該叫

avformat_free_context(ctx->oc); 

總是有由於allo,我的系統有24字節的內存泄漏陽離子pthread_mutex在ffmpeg的libavcodec/utils.c中,並且無法釋放該內存。至少在我或某人修復代碼之前。