[FFmpeg-trac] #4874(undetermined:new): AAC decoder frame->nb_samples & frame->channels is wrong at get_buffer2

FFmpeg trac at avcodec.org
Wed Sep 23 09:53:23 CEST 2015


#4874: AAC decoder frame->nb_samples & frame->channels is wrong at get_buffer2
-------------------------------------+-------------------------------------
             Reporter:  zylthinking  |                    Owner:
                 Type:  defect       |                   Status:  new
             Priority:  normal       |                Component:
              Version:  git-master   |  undetermined
             Keywords:  aac          |               Resolution:
             Blocking:               |               Blocked By:
Analyzed by developer:  0            |  Reproduced by developer:  0
-------------------------------------+-------------------------------------

Comment (by zylthinking):

 Replying to [comment:3 cehoyos]:
 Ok, the code:


 {{{
 static void ffmpeg_frame_put(void* opaque, uint8_t* data)
 {
     (void) data;
     struct my_buffer* mbuf = (struct my_buffer *) opaque;
     mbuf->mop->free(mbuf);
 }

 static int frame_buffer_get(struct AVCodecContext* s, AVFrame* frame, int
 flags)
 {
     my_assert(frame->format == AV_SAMPLE_FMT_FLTP);
     audio_format* fmt = (audio_format *) s->opaque;

     mark("frame->channels = %d, frame->nb_samples = %d\n",
 frame->channels, frame->nb_samples);

     // I know I should not set these, just testing...
     // in he-aac, need the line below
     // in lc-aac, must not
     frame->nb_samples /= 2;

     // the frame->channels changes in the first call and the next calls
     // set it with my correct value.
     frame->channels = fmt->pcm->channel;

     int channel_bytes = frame->nb_samples * sizeof(float);
     uintptr_t bytes = channel_bytes * frame->channels;
     frame->linesize[0] = (int) channel_bytes;
     // ffmpeg says some code may access extra 16 bytes
     // and cpu alignment should be honored.
     // arm64 require 4, however, some neon instruction like vst1
     // require alignment 32 at max.
     struct my_buffer* mbuf = mbuf_alloc_2((uint32_t) (sizeof(media_buffer)
 + bytes + 32 + 16));
     if (mbuf == NULL) {
         return -1;
     }

     media_buffer* media = (media_buffer *) mbuf->ptr[0];
     memset(media->vp, 0, sizeof(media->vp));
     media->angle = 0;
     gidx_field(media) = 0;
     group_field(media) = 1;

     mbuf->length = bytes;
     mbuf->ptr[1] += sizeof(media_buffer);
     mbuf->ptr[1] = (char *) roundup(((uintptr_t) mbuf->ptr[1]), 32);

     my_assert(frame->nb_extended_buf == 0);
     frame->extended_data = frame->data;
     frame->data[0] = (uint8_t *) mbuf->ptr[1];
     if (frame->channels) {
         frame->data[1] = (uint8_t *) (mbuf->ptr[1] + channel_bytes);
     }

     // because documents says buf reference chunk address than data entry
     // e.g. ffmpeg don't know which data[x] buf referenced exactly.
     // ok, it is another word of ffmpeg will never try to get data[x] from
     // buf, then it should use buf only to call addref/release things.
     // in this condition, passing mbuf than data[x] to av_buffer_create is
 safe.
     frame->buf[0] = av_buffer_create((uint8_t *) mbuf->ptr[1], (int)
 bytes, ffmpeg_frame_put, (uint8_t *) mbuf, 0);
     if (frame->buf[0] == NULL) {
         mbuf->mop->free(mbuf);
         return -1;
     }

     frame->extended_buf = NULL;
     frame->nb_extended_buf = 0;
     return 0;
 }

 static void* ffmpeg_open(fourcc** in, fourcc** out)
 {
     ffmpeg_wrapper_t* wrapper = (ffmpeg_wrapper_t *)
 my_malloc(sizeof(ffmpeg_wrapper_t));
     if (wrapper == NULL) {
         return NULL;
     }
     wrapper->bytes = 0;
     wrapper->nb_frame = 0;
     wrapper->seq = 0;
     wrapper->in = to_audio_format(in);
     wrapper->out = to_audio_format(out);

     avcodec_register_all();
     AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_AAC);
     if (codec == NULL) {
         my_free(wrapper);
         return NULL;
     }
     my_assert(codec->capabilities & CODEC_CAP_DR1);

     AVCodecContext* context = avcodec_alloc_context3(codec);
     if (context == NULL) {
         my_free(wrapper);
         return NULL;
     }
     wrapper->context = context;

     AVFrame* frame_buffer = av_frame_alloc();
     if(frame_buffer == NULL){
         avcodec_free_context(&context);
         my_free(wrapper);
         return NULL;
     }
     wrapper->frame = frame_buffer;
     context->channels = wrapper->in->pcm->channel;
     context->sample_rate = wrapper->in->pcm->samrate;
     context->refcounted_frames = 1;
     context->opaque = wrapper->out;
     context->get_buffer2 = frame_buffer_get;

     context->flags |= CODEC_FLAG_LOW_DELAY;
     if (codec->capabilities & CODEC_CAP_TRUNCATED) {
         context->flags |= CODEC_FLAG_TRUNCATED;
         context->flags2 |= CODEC_FLAG2_CHUNKS;
     }

     if (0 != avcodec_open2(context, codec, NULL)) {
         av_frame_free(&frame_buffer);
         avcodec_free_context(&context);
         my_free(wrapper);
         return NULL;
     }
     return wrapper;
 }
 }}}

--
Ticket URL: <https://trac.ffmpeg.org/ticket/4874#comment:4>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker


More information about the FFmpeg-trac mailing list