diff mbox series

[FFmpeg-devel] movenc: Present durations in mvhd/tkhd/mdhd as they are after edits

Message ID 20201219231319.56995-1-martin@martin.st
State Accepted
Commit c2424b1f35a1c6c06f1f9fe5f77a7157ed84e1cd
Headers show
Series [FFmpeg-devel] movenc: Present durations in mvhd/tkhd/mdhd as they are after edits | expand

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Martin Storsjö Dec. 19, 2020, 11:13 p.m. UTC
If the edit lists remove parts of the output timeline, or add a
delay to it, this should be included in the mvhd/tkhd/mdhd durations,
which should correspond to the edit lists.

For tracks starting with pts < 0, the edit list trims out the segment
before pts=0. For tracks starting with pts > 0, a delay element is
added in the edit list, delaying the start of the track data.

In both cases, the practical effect is that the post-edit output
is as if the track had started with pts = 0. Thus calculate the range
from pts=0 to end_pts, for the purposes of mvhd/tkhd/mdhd, unless
edit lists explicitly are disabled.

mov_write_edts_tag needs to operate on the actual pts duration of
the track samples, not the duration that already takes the edit
list effect into account.
---
 libavformat/movenc.c                         | 41 +++++++++++++++++---
 tests/ref/fate/copy-trac3074                 |  2 +-
 tests/ref/fate/gaplessenc-itunes-to-ipod-aac |  2 +-
 tests/ref/fate/gaplessenc-pcm-to-mov-aac     |  2 +-
 tests/ref/fate/movenc                        |  2 +-
 5 files changed, 39 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 18fa3f9b5e..372c04295d 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -2904,21 +2904,50 @@  static int mov_write_minf_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext
     return update_size(pb, pos);
 }
 
-static int64_t calc_pts_duration(MOVMuxContext *mov, MOVTrack *track)
+static void get_pts_range(MOVMuxContext *mov, MOVTrack *track,
+                          int64_t *start, int64_t *end)
 {
     if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) {
         // 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.
-        return av_rescale(calc_pts_duration(mov, &mov->tracks[track->src_track]),
-                          track->timescale, mov->tracks[track->src_track].timescale);
+        get_pts_range(mov, &mov->tracks[track->src_track], start, end);
+        *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 &&
         track->start_dts != AV_NOPTS_VALUE &&
         track->start_cts != AV_NOPTS_VALUE) {
-        return track->end_pts - (track->start_dts + track->start_cts);
+        *start = track->start_dts + track->start_cts;
+        *end   = track->end_pts;
+        return;
     }
-    return track->track_duration;
+    *start = 0;
+    *end   = track->track_duration;
+}
+
+static int64_t calc_samples_pts_duration(MOVMuxContext *mov, MOVTrack *track)
+{
+    int64_t start, end;
+    get_pts_range(mov, track, &start, &end);
+    return end - start;
+}
+
+// Calculate the actual duration of the track, after edits.
+// If it starts with a pts < 0, that is removed by the edit list.
+// If it starts with a pts > 0, the edit list adds a delay before that.
+// Thus, with edit lists enabled, the post-edit output of the file is
+// starting with pts=0.
+static int64_t calc_pts_duration(MOVMuxContext *mov, MOVTrack *track)
+{
+    int64_t start, end;
+    get_pts_range(mov, track, &start, &end);
+    if (mov->use_editlist != 0)
+        start = 0;
+    return end - start;
 }
 
 static int mov_write_mdhd_tag(AVIOContext *pb, MOVMuxContext *mov,
@@ -3145,7 +3174,7 @@  static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
 static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov,
                               MOVTrack *track)
 {
-    int64_t duration = av_rescale_rnd(calc_pts_duration(mov, track),
+    int64_t duration = av_rescale_rnd(calc_samples_pts_duration(mov, track),
                                       MOV_TIMESCALE, track->timescale,
                                       AV_ROUND_UP);
     int version = duration < INT32_MAX ? 0 : 1;
diff --git a/tests/ref/fate/copy-trac3074 b/tests/ref/fate/copy-trac3074
index b5b0b6a60b..78b6015ae8 100644
--- a/tests/ref/fate/copy-trac3074
+++ b/tests/ref/fate/copy-trac3074
@@ -1,4 +1,4 @@ 
-620e3ab4ee6241bec55ea2ec4ef42908 *tests/data/fate/copy-trac3074.mp4
+da6122873fb83ce4340cf5d0ab8d475e *tests/data/fate/copy-trac3074.mp4
 334012 tests/data/fate/copy-trac3074.mp4
 #tb 0: 1/48000
 #media_type 0: audio
diff --git a/tests/ref/fate/gaplessenc-itunes-to-ipod-aac b/tests/ref/fate/gaplessenc-itunes-to-ipod-aac
index 76cbf22358..95b167bda6 100644
--- a/tests/ref/fate/gaplessenc-itunes-to-ipod-aac
+++ b/tests/ref/fate/gaplessenc-itunes-to-ipod-aac
@@ -5,7 +5,7 @@  duration_ts=103326
 [/STREAM]
 [FORMAT]
 start_time=0.000000
-duration=2.367000
+duration=2.344000
 [/FORMAT]
 packet|pts=-1024|dts=-1024|duration=1024|flags=KDside_data|
 
diff --git a/tests/ref/fate/gaplessenc-pcm-to-mov-aac b/tests/ref/fate/gaplessenc-pcm-to-mov-aac
index 2b17956e2b..bfd47be10f 100644
--- a/tests/ref/fate/gaplessenc-pcm-to-mov-aac
+++ b/tests/ref/fate/gaplessenc-pcm-to-mov-aac
@@ -5,7 +5,7 @@  duration_ts=529200
 [/STREAM]
 [FORMAT]
 start_time=0.000000
-duration=12.024000
+duration=12.000000
 [/FORMAT]
 packet|pts=-1024|dts=-1024|duration=1024|flags=KDside_data|
 
diff --git a/tests/ref/fate/movenc b/tests/ref/fate/movenc
index 602639106d..81ea75f372 100644
--- a/tests/ref/fate/movenc
+++ b/tests/ref/fate/movenc
@@ -7,7 +7,7 @@  write_data len 36, time nopts, type header atom ftyp
 write_data len 2761, time nopts, type header atom -
 write_data len 908, time 966667, type sync atom moof
 write_data len 110, time nopts, type trailer atom -
-5b6e4211a45cd5dac99c8b90752a03d7 3815 non-empty-moov-elst
+caf0876986b5f033efc0958c338289cc 3815 non-empty-moov-elst
 write_data len 36, time nopts, type header atom ftyp
 write_data len 2669, time nopts, type header atom -
 write_data len 908, time 1000000, type sync atom moof