2

我在 avcodec_find_encoder 中出现内存泄漏。尽管我正在正确清理资源,但我仍然无法摆脱泄漏。通过连续注释代码,我发现只有在调用 avcodec_find_encoder() 之后才会发生内存泄漏。我用不同的视频文件尝试了我的代码,我发现内存泄漏块总是相同的。此外,如果我只打开音频或视频,那么我只会得到一个内存泄漏块。下面是应用程序的初始化和清理代码的一部分。请注意,这只是包含初始化和资源释放的代码的一部分。

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. 

我在 Visual Studio 2012 上使用最新版本的 ffmpeg。请建议我在哪里失踪。

谢谢普拉迪普

4

1 回答 1

1

这里有很多重要的事情

首先你需要关闭io

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

你也应该打电话

avformat_free_context(ctx->oc);

由于在 ffmpeg 的 libavcodec/utils.c 中分配 pthread_mutex,我的系统总是存在 24 字节的内存泄漏,并且没有办法释放该内存。至少在我或有人修复代码之前。

于 2014-01-22T08:52:54.393 回答