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

J Decker d3ck0r at gmail.com
Sat Aug 29 13:10:33 CEST 2015


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


More information about the Libav-user mailing list