praks411
praks411

Reputation: 1992

Memory leak while opening encoders in ffmpeg

I'm getting memory leaks in avcodec_find_encoder. Although I'm cleaning the resources properly still I'm not able to get rid of the leak. By successive commenting the code I found that memory leaks happen only after the call of avcodec_find_encoder(). I've tried my code with different video files and I found that memory leaks blocks are always same. Also if I open only audio or video then I get just one memory leaks block. Below is the part of Init and Clean-up code from the application. Note that this is just part of code which contains initialization and resource release.

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

Here is the Clean-up part

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 ") 
    } 

} 

Memory Leaks message

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. 

I'm using latest version of ffmpeg on Visual Studio 2012. Please suggest where I'm missing.

Thanks Pradeep

Upvotes: 2

Views: 2560

Answers (1)

Anshul
Anshul

Reputation: 360

There are lots of thing that matters here

first you need to close io

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

you should also call

avformat_free_context(ctx->oc);

There is always 24 bytes memory leakage at my system due to allocation pthread_mutex in libavcodec/utils.c of ffmpeg, and there is no way to free that memory.atleast till I or someone fix the code.

Upvotes: 1

Related Questions