1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
From c6f8a1affd650c917576b4019a9003717cb4ff22 Mon Sep 17 00:00:00 2001
From: John Stebbins <stebbins@jetheaddev.com>
Date: Sun, 19 Feb 2017 14:02:24 -0700
Subject: [PATCH] movenc: factor initial_padding into edit lists
initial_padding was getting added to the edit list indirectly due to
initial negative dts. But in cases where the audio is delayed,
all or part of initial_padding would be unaccounted for. This patch
makes initial_padding explicit.
---
libavformat/movenc.c | 58 +++++++++++++++++++++++++++++++++++++---------------
1 file changed, 42 insertions(+), 16 deletions(-)
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 689291d..b9e4f6e 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -1698,9 +1698,31 @@ static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov,
track->timescale, AV_ROUND_UP);
int version = duration < INT32_MAX ? 0 : 1;
int entry_size, entry_count, size;
- int64_t delay, start_ct = track->start_cts;
- delay = av_rescale_rnd(track->start_dts + start_ct, MOV_TIMESCALE,
- track->timescale, AV_ROUND_DOWN);
+ int64_t delay;
+ int64_t mediatime;
+ int64_t skip = 0;
+
+ delay = track->start_dts + track->start_cts;
+
+ if (track->par->codec_type == AVMEDIA_TYPE_AUDIO &&
+ track->par->initial_padding > 0) {
+ /* Adjust delay so that initial_padding gets recorded in the
+ * MediaTime of an edit list entry even in the case that
+ * delay is positive. I.e. we don't want initial_padding to be
+ * absorbed and hidden in the delay. MediaTime must contain
+ * initial_padding in order to know where the actual media
+ * timeline begins. A player should drop samples until MediaTime
+ * is reached */
+ delay += av_rescale_rnd(track->par->initial_padding, track->timescale,
+ track->par->sample_rate, AV_ROUND_UP);
+ skip = av_rescale_rnd(track->par->initial_padding,
+ track->timescale,
+ track->par->sample_rate, AV_ROUND_DOWN);
+ }
+ /* rescale delay, this was not done earlier to minimize rounding errors */
+ delay = av_rescale_rnd(delay, MOV_TIMESCALE,
+ track->timescale, AV_ROUND_NEAR_INF);
+
version |= delay < INT32_MAX ? 0 : 1;
entry_size = (version == 1) ? 20 : 12;
@@ -1731,33 +1753,37 @@ static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov,
}
avio_wb32(pb, 0x00010000);
} else {
- /* Avoid accidentally ending up with start_ct = -1 which has got a
- * special meaning. Normally start_ct should end up positive or zero
- * here, but use FFMIN in case dts is a a small positive integer
- * rounded to 0 when represented in MOV_TIMESCALE units. */
- start_ct = -FFMIN(track->start_dts, 0);
- /* Note, this delay is calculated from the pts of the first sample,
- * ensuring that we don't reduce the duration for cases with
- * dts<0 pts=0. */
- duration += delay;
+ /* Avoid accidentally ending up with mediatime = -1 which has got a
+ * special meaning. skip and -track->start_dts are guaranteed to be
+ * positive here, so it is not possible mediatime to be -1 */
+ skip = FFMAX(skip, -track->start_dts - track->start_cts);
}
+ mediatime = skip + track->start_cts;
+
+ /* skip is the duration of the media segment that will be dropped
+ * during playback when an edit entry is applied. The edit entry
+ * duration must be reduced by this amount. */
+ duration -= av_rescale_rnd(skip, MOV_TIMESCALE,
+ track->timescale, AV_ROUND_UP);
/* For fragmented files, we don't know the full length yet. Setting
* duration to 0 allows us to only specify the offset, including
* the rest of the content (from all future fragments) without specifying
* an explicit duration. */
- if (mov->flags & FF_MOV_FLAG_FRAGMENT)
+ if (mov->flags & FF_MOV_FLAG_FRAGMENT || duration < 0)
duration = 0;
- /* duration */
+ /* add edit entry that defines the presentation time of the first
+ * sample to render during playback and the duration of the segment */
if (version == 1) {
avio_wb64(pb, duration);
- avio_wb64(pb, start_ct);
+ avio_wb64(pb, mediatime);
} else {
avio_wb32(pb, duration);
- avio_wb32(pb, start_ct);
+ avio_wb32(pb, mediatime);
}
avio_wb32(pb, 0x00010000);
+
return size;
}
--
2.9.3
|