This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 579edeabecc4d645d52f7a92d99fb5c66ecf696d
Author:     James Almer <[email protected]>
AuthorDate: Sun Jun 21 02:29:37 2026 +0000
Commit:     James Almer <[email protected]>
CommitDate: Tue Jun 23 20:07:25 2026 -0300

    avformat/movenc: look for remainder samples in packet side data
    
    Sometimes the duration itself reflects the remainder samples by being set 
to a
    value lower than the frame size, but in other cases it's done only through
    a discard padding value in side data.
    Take the latter into account when calculating durations.
    
    Fixes issue #23532.
    
    Signed-off-by: James Almer <[email protected]>
---
 libavformat/movenc.c                    | 28 ++++++++++++++++++++--------
 tests/ref/fate/filter-meta-4560-rotate0 |  4 ++--
 tests/ref/fate/hevc-bsf-dts2pts-cra     |  2 +-
 tests/ref/fate/hevc-bsf-dts2pts-idr     |  2 +-
 tests/ref/fate/hevc-bsf-dts2pts-idr-cra |  2 +-
 tests/ref/fate/mov-cover-image          |  2 +-
 6 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 7b08f58977..c14f05ecc8 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -3854,20 +3854,20 @@ static int mov_write_minf_tag(AVFormatContext *s, 
AVIOContext *pb, MOVMuxContext
 }
 
 static void get_pts_range(MOVMuxContext *mov, MOVTrack *track,
-                          int64_t *start, int64_t *end, int elst)
+                          int64_t *start, int64_t *end, int elst, int mdhd)
 {
     if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd && 
track->nb_src_track) {
         // tmcd tracks gets track_duration set in mov_write_moov_tag from
         // another track's duration, while the end_pts may be left at zero.
         // Calculate the pts duration for that track instead.
-        get_pts_range(mov, &mov->tracks[*track->src_track], start, end, elst);
+        get_pts_range(mov, &mov->tracks[*track->src_track], start, end, elst, 
mdhd);
         *start = av_rescale(*start, track->timescale,
                             mov->tracks[*track->src_track].timescale);
         *end   = av_rescale(*end, track->timescale,
                             mov->tracks[*track->src_track].timescale);
         return;
     }
-    if (track->end_pts != AV_NOPTS_VALUE &&
+    if (!mdhd && track->end_pts != AV_NOPTS_VALUE &&
         track->start_dts != AV_NOPTS_VALUE &&
         track->start_cts != AV_NOPTS_VALUE) {
         *start = track->start_dts + track->start_cts;
@@ -3881,7 +3881,7 @@ static void get_pts_range(MOVMuxContext *mov, MOVTrack 
*track,
 static int64_t calc_samples_pts_duration(MOVMuxContext *mov, MOVTrack *track)
 {
     int64_t start, end;
-    get_pts_range(mov, track, &start, &end, 0);
+    get_pts_range(mov, track, &start, &end, 0, 1);
     return end - start;
 }
 
@@ -3893,7 +3893,7 @@ static int64_t calc_samples_pts_duration(MOVMuxContext 
*mov, MOVTrack *track)
 static int64_t calc_pts_duration(MOVMuxContext *mov, MOVTrack *track)
 {
     int64_t start, end;
-    get_pts_range(mov, track, &start, &end, 0);
+    get_pts_range(mov, track, &start, &end, 0, 0);
     if (mov->use_editlist != 0)
         start = 0;
     return end - start;
@@ -3902,7 +3902,7 @@ static int64_t calc_pts_duration(MOVMuxContext *mov, 
MOVTrack *track)
 static int64_t calc_elst_duration(MOVMuxContext *mov, MOVTrack *track)
 {
     int64_t start, end;
-    get_pts_range(mov, track, &start, &end, 1);
+    get_pts_range(mov, track, &start, &end, 1, 0);
     return end - start;
 }
 
@@ -6935,6 +6935,7 @@ 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;
@@ -7304,6 +7305,17 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket 
*pkt)
                    "this case.\n",
                    pkt->stream_index, pkt->dts);
     }
+
+    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) {
+        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;
+    }
+
     trk->track_duration = pkt->dts - trk->start_dts + pkt->duration;
     trk->last_sample_is_subtitle_end = 0;
 
@@ -7319,11 +7331,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 + pkt->duration;
+                       trk->cluster[trk->entry].cts + duration;
     else
         trk->end_pts = FFMAX(trk->end_pts, trk->cluster[trk->entry].dts +
                                            trk->cluster[trk->entry].cts +
-                                           pkt->duration);
+                                           duration);
     if (!(pkt->flags & AV_PKT_FLAG_DISCARD))
         trk->elst_end_pts = trk->end_pts;
 
diff --git a/tests/ref/fate/filter-meta-4560-rotate0 
b/tests/ref/fate/filter-meta-4560-rotate0
index 7ebd52092d..8606137e45 100644
--- a/tests/ref/fate/filter-meta-4560-rotate0
+++ b/tests/ref/fate/filter-meta-4560-rotate0
@@ -1,4 +1,4 @@
-8718876acc3ffd74610daba770900b40 *tests/data/fate/filter-meta-4560-rotate0.mov
+796b09d860affeeed44b95d622c214f1 *tests/data/fate/filter-meta-4560-rotate0.mov
 347425 tests/data/fate/filter-meta-4560-rotate0.mov
 #tb 0: 1/30
 #media_type 0: video
@@ -265,4 +265,4 @@
 1,     151552,     151552,     1024,     2048, 0x473a05a3
 1,     152576,     152576,     1024,     2048, 0x26721b75
 0,        104,        104,        1,   195840, 0x46851b87
-1,     153600,     153600,     1024,     2048, 0x97a2f42c
+1,     153600,     153600,       89,      178, 0x94b35030
diff --git a/tests/ref/fate/hevc-bsf-dts2pts-cra 
b/tests/ref/fate/hevc-bsf-dts2pts-cra
index 5d91e7538b..cd70cde3a6 100644
--- a/tests/ref/fate/hevc-bsf-dts2pts-cra
+++ b/tests/ref/fate/hevc-bsf-dts2pts-cra
@@ -1,4 +1,4 @@
-07052bab1eb3066536daef8bd51901a8 *tests/data/fate/hevc-bsf-dts2pts-cra.mov
+72722d11426fe39218dc59f111a353d0 *tests/data/fate/hevc-bsf-dts2pts-cra.mov
 103067 tests/data/fate/hevc-bsf-dts2pts-cra.mov
 #extradata 0:      118, 0x25f51994
 #tb 0: 1/1200000
diff --git a/tests/ref/fate/hevc-bsf-dts2pts-idr 
b/tests/ref/fate/hevc-bsf-dts2pts-idr
index 6b46ad1fff..3a339e8d6d 100644
--- a/tests/ref/fate/hevc-bsf-dts2pts-idr
+++ b/tests/ref/fate/hevc-bsf-dts2pts-idr
@@ -1,4 +1,4 @@
-8bf0d529d144cfd08a7e62e8b2025352 *tests/data/fate/hevc-bsf-dts2pts-idr.mov
+773de1cf5d3424da867453e8c2473500 *tests/data/fate/hevc-bsf-dts2pts-idr.mov
 346603 tests/data/fate/hevc-bsf-dts2pts-idr.mov
 #extradata 0:      699, 0x9c810c10
 #tb 0: 1/1200000
diff --git a/tests/ref/fate/hevc-bsf-dts2pts-idr-cra 
b/tests/ref/fate/hevc-bsf-dts2pts-idr-cra
index 3612ca1555..b424a8ba99 100644
--- a/tests/ref/fate/hevc-bsf-dts2pts-idr-cra
+++ b/tests/ref/fate/hevc-bsf-dts2pts-idr-cra
@@ -1,4 +1,4 @@
-e2374650488cf8f905c441d6f4a3cff4 *tests/data/fate/hevc-bsf-dts2pts-idr-cra.mov
+81d05ed8ec426d7732ce4f73176c50fe *tests/data/fate/hevc-bsf-dts2pts-idr-cra.mov
 375266 tests/data/fate/hevc-bsf-dts2pts-idr-cra.mov
 #extradata 0:      648, 0x30a7fa5c
 #tb 0: 1/1200000
diff --git a/tests/ref/fate/mov-cover-image b/tests/ref/fate/mov-cover-image
index b0db8f9dd2..6c6607c39c 100644
--- a/tests/ref/fate/mov-cover-image
+++ b/tests/ref/fate/mov-cover-image
@@ -1,4 +1,4 @@
-017a372d92c59971c2ddee95298e745a *tests/data/fate/mov-cover-image.mp4
+124d92893a4a6dc8e0b5a6c384536e2e *tests/data/fate/mov-cover-image.mp4
 1024065 tests/data/fate/mov-cover-image.mp4
 #extradata 0:        2, 0x00340022
 #tb 0: 1/44100

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to