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

J Decker d3ck0r at gmail.com
Sat Aug 29 17:10:23 CEST 2015


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


More information about the Libav-user mailing list