PR #23602 opened by Rodeo URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23602 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23602.patch
#23534 stores pkt->duration in a local variable upon entering ff_mov_write_packet and assumes pkt->duration remains unchanged until checking the packet side data. But handle_eac3() buffers and concatenates "short" frames until 6 blocks (1536 samples) are reached, and updates pkt->duration as it does so, and the above change basically "overwrites" such updates with the initial value of pkt->duration, possibly (probably?) causing issue #23600 It seems easier (and possibly safer) to eliminate the local variable at the root of the function and ensure the side data code block uses the latest pkt->duration than to check the whole function to determine which functions might update pkt->duration and pass the local variable to them for updating instead. --- This patch fixes src.wav from 23600 for me. Some fate test results are changed and I have no had the time to check whether the changes are expected, hence the WIP. --- In addition, the Tears of Steel sample referenced in 23600 still has a different duration in the edit list when short eac3 frames are used, but I suspect this may be because the encoder is producing an odd number of frames and movenc is just dropping one of the short frames (but I haven't fully ascertained that's what happens yet). >From d5c71f318bc4b3a8ccda7ca65e41629f3ee1066d Mon Sep 17 00:00:00 2001 From: Tim Walker <[email protected]> Date: Fri, 26 Jun 2026 07:31:03 +0200 Subject: [PATCH] avformat/movenc: don't override changes to pkt->duration ff_mov_write_packet may call other functions that update it; so storing its value in a variable upon entry is unreliable. --- libavformat/movenc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index c14f05ecc8..56f8f393d9 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -6935,7 +6935,6 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) AVCodecParameters *par; AVProducerReferenceTime *prft; unsigned int samples_in_chunk = 0; - int64_t duration = pkt->duration; int size = pkt->size, ret = 0, offset = 0; size_t prft_size; uint8_t *reformatted_data = NULL; @@ -7308,12 +7307,16 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) sd = av_packet_side_data_get(pkt->side_data, pkt->side_data_elems, AV_PKT_DATA_SKIP_SAMPLES); if (sd && sd->size >= 10 && trk->par->frame_size) { + // pkt->duration may have changed since ff_mov_write_packet was entered + // it is e.g. updated by handle_eac3() when concatenating "short" frames + int64_t duration = pkt->duration; duration = FFMAX(av_rescale_q(trk->par->frame_size, (AVRational){ 1, trk->par->sample_rate }, trk->st->time_base), duration); duration -= av_rescale_q(AV_RL32(sd->data + 4), (AVRational){ 1, trk->par->sample_rate }, trk->st->time_base); if (duration < 0) return AVERROR_INVALIDDATA; + pkt->duration = duration; } trk->track_duration = pkt->dts - trk->start_dts + pkt->duration; @@ -7331,11 +7334,11 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) trk->start_cts = pkt->pts - pkt->dts; if (trk->end_pts == AV_NOPTS_VALUE) trk->end_pts = trk->cluster[trk->entry].dts + - trk->cluster[trk->entry].cts + duration; + trk->cluster[trk->entry].cts + pkt->duration; else trk->end_pts = FFMAX(trk->end_pts, trk->cluster[trk->entry].dts + trk->cluster[trk->entry].cts + - duration); + pkt->duration); if (!(pkt->flags & AV_PKT_FLAG_DISCARD)) trk->elst_end_pts = trk->end_pts; -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
