[FFmpeg-devel] [PATCH+RFC] AVFrame for audio

Justin Ruggles justin.ruggles
Fri Oct 15 12:03:15 CEST 2010


Michael Niedermayer wrote:

> On Wed, Oct 13, 2010 at 07:52:12PM -0400, Justin Ruggles wrote:
>> Michael Niedermayer wrote:
>>
>>> On Wed, Oct 06, 2010 at 11:05:26AM -0400, Justin Ruggles wrote:
>>>> Michael Niedermayer wrote:
>>>>
>>>>> On Tue, Oct 05, 2010 at 04:55:12PM -0400, Justin Ruggles wrote:
>>>>>> Michael Niedermayer wrote:
>>>>>>
>>>>>>> On Wed, Sep 29, 2010 at 09:20:04PM -0400, Justin Ruggles wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> Peter Ross wrote:
>>>>>>>>
>>>>>>>>> On Thu, Sep 02, 2010 at 07:11:37PM -0400, Justin Ruggles wrote:
>>>>>>>>>> Hi,
>>> [...]
>>>>>>> [...]
>>>>>>>> @@ -644,29 +677,49 @@
>>>>>>>>  }
>>>>>>>>  #endif
>>>>>>>>  
>>>>>>>> +#if LIBAVCODEC_VERSION_MAJOR < 53
>>>>>>>>  int attribute_align_arg avcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples,
>>>>>>>>                           int *frame_size_ptr,
>>>>>>>>                           AVPacket *avpkt)
>>>>>>>>  {
>>>>>>>> +    AVFrame frame;
>>>>>>>> +    int ret, got_frame = 0;
>>>>>>>> +
>>>>>>>> +    avcodec_get_frame_defaults(&frame);
>>>>>>>> +
>>>>>>>> +    ret = avcodec_decode_audio4(avctx, &frame, &got_frame, avpkt);
>>>>>>>> +
>>>>>>>> +    if (ret >= 0 && got_frame) {
>>>>>>>> +        *frame_size_ptr = frame.nb_samples * avctx->channels *
>>>>>>>> +                          (av_get_bits_per_sample_format(avctx->sample_fmt) / 8);
>>>>>>>> +
>>>>>>>> +        /* ensure data will fit in the output buffer */
>>>>>>>> +        if (*frame_size_ptr > AVCODEC_MAX_AUDIO_FRAME_SIZE) {
>>>>>>>> +            av_log(avctx, AV_LOG_WARNING, "avcodec_decode_audio3 samples "
>>>>>>>> +                   "truncated to AVCODEC_MAX_AUDIO_FRAME_SIZE\n");
>>>>>>>> +            *frame_size_ptr = AVCODEC_MAX_AUDIO_FRAME_SIZE;
>>>>>>>> +        }
>>>>>>>> +
>>>>>>>> +        memcpy(samples, frame.data[0], *frame_size_ptr);
>>>>>>>  the default get_buffer() should return the appropriate
>>>>>>> buffer for this case.
>>>>>> I'm sorry, I don't understand your comment.
>>>>> i mean (non functional psseudocode below to explain the idea)
>>>>> avcodec_decode_audio3(){
>>>>>     avctx->foobar= samples;
>>>>>     ret = avcodec_decode_audio4(avctx, &frame, &got_frame, avpkt);
>>>>>     ...
>>>>>     assert(samples == frame.data[0]);
>>>>>
>>>>> -----
>>>>> default_get_buffer(){
>>>>>     if(avctx->foobar)
>>>>>         return avctx->foobar;
>>>>>
>>>>>
>>>>> (and yes this cannot work for all theoretical decoders)
>>>> I think I get it.  So avctx->foobar would be an optional user-supplied
>>>> buffer (avctx->user_buffer?) that default_get_buffer() would return if
>>>> it is non-NULL, right?
>>> yes
>>>
>>>
>>>> The problem I see is this:
>>>> avcodec_decode_audio3() would use avcodec_decode_audio4().
>>>> avcodec_decode_audio4() allocates as large a buffer as is needed through
>>>> get_buffer(), but the avcodec_decode_audio3() API only requires the
>>>> user-supplied buffer to be AVCODEC_MAX_AUDIO_FRAME_SIZE.  Couldn't this
>>>> lead to the decoder writing past the end of a user-supplied buffer if it
>>>> isn't large enough?  I guess we could also add a field
>>>> avctx->user_buffer_size?
>>> yes, of course
>>> it was just a rough idea ...
>> I'm running into some questions trying to implement the rough idea.  The
>> only way I can see this working smoothly is if avcodec_decode_audio3()
>> always sets get/release_buffer to default.  Also, either all audio
>> decoders will have to support CODEC_CAP_DR1 (i.e. they always use
>> get/release_buffer) or there needs to be a fallback that will memcpy
>> into the user buffer if CODEC_CAP_DR1 is not supported.
> 
> old API decoders surely dont need to copy with old API.
> old API decoders surely dont need to copy with new API if the api can provide
> a buffer to the decoder (this can be through function argument like its done
> currently)
> new API decoders surely dont need to copy with new API because otherwise the
> API sucks and needs more work
> whats left is new API decoders and used with old API and for this get_buffer()
> should return the user supplied buffer if its large enough and fail if its not
> large enough.
> The case where the user overrides get_buffer() and supplies a user specified
> buffer which its own code doesnt use is a case that id consider user error.

I think I might have been misinterpreting the API.  For video decoders,
what does it mean as far as buffer allocation when CODEC_CAP_DR1 is not set?

-Justin



More information about the ffmpeg-devel mailing list