This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch release/8.0 in repository ffmpeg.
commit e56c86abe8d2b0f10dc5c39817808e45a9b32b27 Author: James Almer <[email protected]> AuthorDate: Tue Sep 15 22:35:25 2026 -0300 Commit: ffmpeg-devel <[email protected]> CommitDate: Sun Sep 20 00:10:55 2026 +0000 avcodec/libfdk-aacdec: properly handle decoder delay Shift timestamps when available, and take into account the caller requested samples to be discarded alongside the decoder delay. Should fix issue #24526. Signed-off-by: James Almer <[email protected]> (cherry picked from commit c8595be8e62afd720dadaf72bc8be170b07477e9) --- libavcodec/libfdk-aacdec.c | 78 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 7 deletions(-) diff --git a/libavcodec/libfdk-aacdec.c b/libavcodec/libfdk-aacdec.c index 9c597c24fc..e49f3214d3 100644 --- a/libavcodec/libfdk-aacdec.c +++ b/libavcodec/libfdk-aacdec.c @@ -21,6 +21,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/common.h" +#include "libavutil/intreadwrite.h" #include "libavutil/mem.h" #include "libavutil/opt.h" #include "avcodec.h" @@ -63,7 +64,12 @@ typedef struct FDKAACDecContext { #if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 int output_delay_set; int flush_samples; + int skip_samples; int delay_samples; + int output_delay; + int discard_padding; + int64_t last_pts; + int64_t last_dts; #endif AVChannelLayout downmix_layout; } FDKAACDecContext; @@ -138,6 +144,10 @@ static int get_stream_info(AVCodecContext *avctx, AVFrame *frame) // Set this only once. s->flush_samples = info->outputDelay; s->delay_samples = info->outputDelay; + s->skip_samples = info->outputDelay; + s->output_delay = info->outputDelay; + s->last_pts = AV_NOPTS_VALUE; + s->last_dts = AV_NOPTS_VALUE; s->output_delay_set = 1; } #endif @@ -420,19 +430,76 @@ static int fdk_aac_decode_frame(AVCodecContext *avctx, AVFrame *frame, goto end; frame->nb_samples = avctx->frame_size; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + goto end; + #if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 if (flags & AACDEC_FLUSH) { + if (s->last_pts != AV_NOPTS_VALUE) + frame->pts = av_sat_add64(s->last_pts, + av_rescale_q(frame->nb_samples, avctx->time_base, + (AVRational){ 1, avctx->sample_rate })); + if (s->last_dts != AV_NOPTS_VALUE) + frame->pkt_dts = av_sat_add64(s->last_dts, + av_rescale_q(frame->nb_samples, avctx->time_base, + (AVRational){ 1, avctx->sample_rate })); + // Only return the right amount of samples at the end; if calling the // decoder with AACDEC_FLUSH, it will keep returning frames indefinitely. frame->nb_samples = FFMIN(s->flush_samples, frame->nb_samples); av_log(s, AV_LOG_DEBUG, "Returning %d/%d delayed samples.\n", frame->nb_samples, s->flush_samples); + if (s->skip_samples || s->discard_padding) { + AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES); + if (!sd) { + sd = av_frame_new_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES, 10); + if (sd) + memset(sd->data, 0, 10); + } + if (sd && sd->size >= 10) { + AV_WL32(sd->data, s->skip_samples); + AV_WL32(sd->data + 4, s->discard_padding); + } + s->skip_samples = 0; + s->discard_padding = 0; + } s->flush_samples -= frame->nb_samples; + s->last_pts = frame->pts; + s->last_dts = frame->pkt_dts; } else { - // Trim off samples from the start to compensate for extra decoder - // delay. We could also just adjust the pts, but this avoids - // including the extra samples in the output altogether. - if (s->delay_samples) { + AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES); + if (!sd && s->skip_samples) { + sd = av_frame_new_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES, 10); + if (sd) + memset(sd->data, 0, 10); + } + if (sd && sd->size >= 10) { + int skip_samples = AV_RL32(sd->data); + s->discard_padding = AV_RL32(sd->data + 4); + if (s->discard_padding >= s->output_delay) { + AV_WL32(sd->data + 4, s->discard_padding - s->output_delay); + s->discard_padding = s->output_delay; + } else + AV_WL32(sd->data + 4, 0); + AV_WL32(sd->data, skip_samples + s->skip_samples); + s->skip_samples = 0; + } + if (frame->pts != AV_NOPTS_VALUE && s->output_delay) { + frame->pts = av_sat_sub64(frame->pts, + av_rescale_q(s->output_delay, + (AVRational){ 1, avctx->sample_rate }, + avctx->time_base)); + if (frame->pkt_dts != AV_NOPTS_VALUE && s->output_delay) + frame->pkt_dts = av_sat_sub64(frame->pkt_dts, + av_rescale_q(s->output_delay, + (AVRational){ 1, avctx->sample_rate }, + avctx->time_base)); + s->delay_samples = 0; + s->last_pts = frame->pts; + s->last_dts = frame->pkt_dts; + } else if (s->delay_samples) { + // Trim off samples from the start to compensate for extra decoder + // delay, in the absense of timestamps. int drop_samples = FFMIN(s->delay_samples, frame->nb_samples); av_log(s, AV_LOG_DEBUG, "Dropping %d/%d delayed samples.\n", drop_samples, s->delay_samples); @@ -445,9 +512,6 @@ static int fdk_aac_decode_frame(AVCodecContext *avctx, AVFrame *frame, } #endif - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - goto end; - memcpy(frame->extended_data[0], s->decoder_buffer + input_offset, avctx->ch_layout.nb_channels * frame->nb_samples * av_get_bytes_per_sample(avctx->sample_fmt)); -- To stop receiving notification emails like this one, please contact [email protected]. _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
