[PR] WIP: avformat/movenc: don't override changes to pkt->duration (PR #23602)

Rodeo via ffmpeg-devel <[email protected]>
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <178245483111.59.14153642637116787505@29965ddac10e>
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]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.