[Libav-user] Closing codec properly after an audio decoding

Polochon Street polochonstreet at gmx.fr
Sat Aug 29 17:25:03 CEST 2015


Okay thanks for your help; I changed my code with what you wrote, but I 
still have a more important leak.
I also found that I have an indirect memory leak when decoding songs 
with a embedded album picture tag (which appears as Stream #0:1: Video: 
mjpeg, yuvj420p(pc, bt470bg/unknown/unknown), 160x160 [SAR 1:1 DAR 1:1], 
90k tbr, 90k tbn, 90k tbc):
Indirect leak of 8686 byte(s) in 2 object(s) allocated from:
     #0 0x7f7877199386 in __interceptor_posix_memalign 
/build/gcc-multilib/src/gcc-5.2.0/libsanitizer/asan/asan_malloc_linux.cc:105
     #1 0x7f78767c743f in av_malloc (/usr/lib/libavutil.so.54+0x2343f)

Maybe I should open another thread for this one? Now that we've seen 
that the leak does not come from the codec closing, do you have a clue 
where I could search?

The 29/08/2015 17:10, J Decker wrote :
> On Sat, Aug 29, 2015 at 5:02 AM, Polochon Street <polochonstreet at gmx.fr> wrote:
>> So, what should I do? Set avpkt.data to NULL and avpkt.size to 0, and then
>> close the codec?
>> I tried to add at the end of the loop:
> somethign more like...
>           avpkt.data = NULL;
>           avpkt.size = 0;
> // just use your existing buffer here...
>           decoded_frame = av_frame_alloc();
>     do {
>           avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt);
>       } while (got_frame);
>           av_frame_unref(decoded_frame);
>           av_free_packet(&avpkt);
>
>> But now I'm leaking more memory...
>>
>>
>> The 29/08/2015 13:10, J Decker wrote :
>>> You didn't pass a null packet to flush the codec at the end and get
>>> the remaining packets from the stream.
>>>
>>> On Thu, Aug 27, 2015 at 1:21 PM, Polochon Street <polochonstreet at gmx.fr>
>>> wrote:
>>>> Hi!
>>>> I use the following code (see below) in order to decode an audio file
>>>> into
>>>> an array, and I'm having a memory leak of 24kb:
>>>> Direct leak of 24 byte(s) in 1 object(s) allocated from:
>>>>       #0 0x7f80c449e386 in __interceptor_posix_memalign
>>>>
>>>> /build/gcc-multilib/src/gcc-5.2.0/libsanitizer/asan/asan_malloc_linux.cc:105
>>>>       #1 0x7f80c3acc43f in av_malloc (/usr/lib/libavutil.so.54+0x2343f)
>>>>
>>>> So I'm thinking that it's due to some libav-specific things that I didn't
>>>> close properly, and so here's my question: is avcodec_close(context);
>>>> sufficient to free a codec context and a codec? This example
>>>> (http://ffmpeg.org/doxygen/trunk/decoding_encoding_8c-example.html) does
>>>> an
>>>> av_free(context), but my program crashes when I try to do it...
>>>>
>>>> Thanks by advance!
>>>> Polochon_street
>>>>
>>>> #define INBUF_SIZE 4096
>>>>
>>>> #define AUDIO_INBUF_SIZE 20480
>>>>
>>>> #define AUDIO_REFILL_THRESH 4096
>>>>
>>>>
>>>> #include "analyze.h"
>>>>
>>>>
>>>> int audio_decode(const char *filename, struct song *song) { // decode the
>>>> track
>>>>
>>>>       AVCodec *codec = NULL;
>>>>
>>>>       AVCodecContext *c = NULL;
>>>>
>>>>       AVFormatContext *pFormatCtx;
>>>>
>>>>
>>>>
>>>>       int i, d, e;
>>>>
>>>>       int len;
>>>>
>>>>       int planar;
>>>>
>>>>       AVPacket avpkt;
>>>>
>>>>       AVFrame *decoded_frame = NULL;
>>>>
>>>>       int8_t *beginning;
>>>>
>>>>       int got_frame;
>>>>
>>>>       int audioStream;
>>>>
>>>>       size_t index;
>>>>
>>>>
>>>>       av_register_all();
>>>>
>>>>       av_init_packet(&avpkt);
>>>>
>>>>
>>>>       pFormatCtx = avformat_alloc_context();
>>>>
>>>>
>>>>       if(avformat_open_input(&pFormatCtx, filename, NULL, NULL) < 0) {
>>>>
>>>>           printf("Couldn't open file: %s, %d\n", filename, errno);
>>>>
>>>>           song->nSamples = 0;
>>>>
>>>>           return 1;
>>>>
>>>>       }
>>>>
>>>>
>>>>       if(avformat_find_stream_info(pFormatCtx, NULL) < 0) {
>>>>
>>>>           printf("Couldn't find stream information\n");
>>>>
>>>>           song->nSamples = 0;
>>>>
>>>>           return 1;
>>>>
>>>>       }
>>>>
>>>>
>>>>       audioStream = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_AUDIO,
>>>> -1,
>>>> -1, &codec, 0);
>>>>
>>>>       c = pFormatCtx->streams[audioStream]->codec;
>>>>
>>>>
>>>>
>>>>       if (!codec) {
>>>>
>>>>           printf("Codec not found!\n");
>>>>
>>>>           song->nSamples = 0;
>>>>
>>>>           return 1;
>>>>
>>>>       }
>>>>
>>>>
>>>>       if(avcodec_open2(c, codec, NULL) < 0) {
>>>>
>>>>           printf("Could not open codec\n");
>>>>
>>>>           song->nSamples = 0;
>>>>
>>>>           return 1;
>>>>
>>>>       }
>>>>
>>>>
>>>>
>>>>       song->sample_rate = c->sample_rate;
>>>>
>>>>       song->duration = pFormatCtx->duration/AV_TIME_BASE;
>>>>
>>>>       size =
>>>>
>>>> (((uint64_t)(pFormatCtx->duration)*(uint64_t)song->sample_rate)/(uint64_t)AV_TIME_BASE)*c->channels*av_get_bytes_per_sample(c->sample_fmt);
>>>>
>>>>       song->nSamples =
>>>>
>>>> (((uint64_t)(pFormatCtx->duration)*(uint64_t)song->sample_rate)/(uint64_t)AV_TIME_BASE)*c->channels;
>>>>
>>>>       song->sample_array = malloc(size);
>>>>
>>>>
>>>>       for(i = 0; i < size; ++i)
>>>>
>>>>           song->sample_array[i] = 0;
>>>>
>>>>
>>>>       beginning = song->sample_array;
>>>>
>>>>       index = 0;
>>>>
>>>>
>>>>       planar = av_sample_fmt_is_planar(c->sample_fmt);
>>>>
>>>>       song->nb_bytes_per_sample = av_get_bytes_per_sample(c->sample_fmt);
>>>>
>>>>
>>>>       song->channels = c->channels;
>>>>
>>>>
>>>>
>>>> /* End of codec init */
>>>>
>>>>       while(av_read_frame(pFormatCtx, &avpkt) >= 0) {
>>>>
>>>>           if(avpkt.stream_index == audioStream) {
>>>>
>>>>               got_frame = 0;
>>>>
>>>>
>>>>
>>>>               if(!decoded_frame) {
>>>>
>>>>                   if(!(decoded_frame = av_frame_alloc())) {
>>>>
>>>>                       printf("Could not allocate audio frame\n");
>>>>
>>>>                       exit(1);
>>>>
>>>>                   }
>>>>
>>>>               }
>>>>
>>>>               else
>>>>
>>>>                   av_frame_unref(decoded_frame);
>>>>
>>>>
>>>>               len = avcodec_decode_audio4(c, decoded_frame, &got_frame,
>>>> &avpkt);
>>>>
>>>>
>>>>
>>>>               if(len < 0)
>>>>
>>>>                   avpkt.size = 0;
>>>>
>>>>
>>>>               av_free_packet(&avpkt);
>>>>
>>>>
>>>>               /* interesting part: copying decoded data into a huge array
>>>> */
>>>>
>>>>               /* flac has a different behaviour from mp3, hence the planar
>>>> condition */
>>>>
>>>>               if(got_frame) {
>>>>
>>>>                   size_t data_size = av_samples_get_buffer_size(NULL,
>>>> c->channels, decoded_frame->nb_samples, c->sample_fmt, 1);
>>>>
>>>>
>>>>                   if(index*song->nb_bytes_per_sample + data_size > size) {
>>>>
>>>>                       beginning = realloc(beginning, (size += data_size));
>>>>
>>>>                       song->nSamples +=
>>>> data_size/song->nb_bytes_per_sample;
>>>>
>>>>                   }
>>>>
>>>>                   int8_t *p = beginning+index*song->nb_bytes_per_sample;
>>>>
>>>>                   if(planar == 1) {
>>>>
>>>>                       for(i = 0; i <
>>>> decoded_frame->nb_samples*song->nb_bytes_per_sample; i +=
>>>> song->nb_bytes_per_sample) {
>>>>
>>>>                           for(e = 0; e < c->channels; ++e)
>>>>
>>>>                               for(d = 0; d < song->nb_bytes_per_sample;
>>>> ++d)
>>>>
>>>>                                   *(p++) =
>>>> ((int8_t*)(decoded_frame->extended_data[e]))[i+d];
>>>>
>>>>                       }
>>>>
>>>>                       index += data_size/song->nb_bytes_per_sample;
>>>>
>>>>                   }
>>>>
>>>>                   else if(planar == 0) {
>>>>
>>>>                       memcpy(index*song->nb_bytes_per_sample + beginning,
>>>> decoded_frame->extended_data[0], data_size);
>>>>
>>>>                       index += data_size/song->nb_bytes_per_sample;
>>>>
>>>>                   }
>>>>
>>>>               }
>>>>
>>>>           }
>>>>
>>>>       }
>
>
>
>>>>       song->sample_array = beginning;
>>>>
>>>>
>>>>       /* cleaning memory */
>>>>
>
>           avpkt.data = NULL;
>           avpkt.size = 0;
> // just use your existing buffer here...
>           decoded_frame = av_frame_alloc();
>     do {
>           avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt);
>       } while (got_frame);
>
>>>>
>>>>       avcodec_close(c);
>>>>
>>>>       av_frame_unref(decoded_frame);
>>>>
>>>>       av_frame_free(&decoded_frame);
>>>>
>>>>       av_free_packet(&avpkt);
>>>>
>>>>       avformat_close_input(&pFormatCtx);
>>>>
>>>>
>>>>       return 0;
>>>>
>>>> }
>>>>
>>>>
>>>> _______________________________________________
>>>> Libav-user mailing list
>>>> Libav-user at ffmpeg.org
>>>> http://ffmpeg.org/mailman/listinfo/libav-user
>>>>
>>> _______________________________________________
>>> Libav-user mailing list
>>> Libav-user at ffmpeg.org
>>> http://ffmpeg.org/mailman/listinfo/libav-user
>>
>> _______________________________________________
>> Libav-user mailing list
>> Libav-user at ffmpeg.org
>> http://ffmpeg.org/mailman/listinfo/libav-user
> _______________________________________________
> Libav-user mailing list
> Libav-user at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/libav-user



More information about the Libav-user mailing list