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

Polochon Street polochonstreet at gmx.fr
Thu Aug 27 22:21:57 CEST 2015


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 */

     avcodec_close(c);

     av_frame_unref(decoded_frame);

     av_frame_free(&decoded_frame);

     av_free_packet(&avpkt);

     avformat_close_input(&pFormatCtx);


     return 0;

}

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20150827/0c00df2d/attachment.html>


More information about the Libav-user mailing list