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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
From c2204c579c8411771b53a4bc66324c7c5d07698a Mon Sep 17 00:00:00 2001
From: John Stebbins <stebbins@jetheaddev.com>
Date: Thu, 16 Nov 2017 14:40:12 -0800
Subject: [PATCH] movenc: add sdtp (sample dependency) box to mp4
The AppleTV 4K requires this box in order to play 2160p60 video.
---
libavcodec/avcodec.h | 9 +++++++--
libavformat/movenc.c | 34 +++++++++++++++++++++++++++++++++-
libavformat/movenc.h | 6 ++++++
3 files changed, 46 insertions(+), 3 deletions(-)
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 5624835023..48e9d23679 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1161,8 +1161,13 @@ typedef struct AVPacket {
int64_t convergence_duration;
#endif
} AVPacket;
-#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe
-#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted
+#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe
+#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted
+/**
+ * Flag is used to indicate packets that contain frames that can
+ * be discarded by the decoder. I.e. Non-reference frames.
+ */
+#define AV_PKT_FLAG_DISPOSABLE 0x0004
enum AVSideDataParamChangeFlags {
AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001,
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index a546fdfead..d263f444f4 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -227,6 +227,30 @@ static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)
return update_size(pb, pos);
}
+/* Sample dependency atom */
+static int mov_write_sdtp_tag(AVIOContext *pb, MOVTrack *track)
+{
+ int i;
+ uint8_t leading, dependent, reference, redundancy;
+ int64_t pos = avio_tell(pb);
+ avio_wb32(pb, 0); // size
+ ffio_wfourcc(pb, "sdtp");
+ avio_wb32(pb, 0); // version & flags
+ for (i = 0; i < track->entry; i++) {
+ dependent = MOV_SAMPLE_DEPENDENCY_YES;
+ leading = reference = redundancy = MOV_SAMPLE_DEPENDENCY_UNKNOWN;
+ if (track->cluster[i].flags & MOV_DISPOSABLE_SAMPLE) {
+ reference = MOV_SAMPLE_DEPENDENCY_NO;
+ }
+ if (track->cluster[i].flags & MOV_SYNC_SAMPLE) {
+ dependent = MOV_SAMPLE_DEPENDENCY_NO;
+ }
+ avio_w8(pb, (leading << 6) | (dependent << 4) |
+ (reference << 2) | redundancy);
+ }
+ return update_size(pb, pos);
+}
+
static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
{
avio_wb32(pb, 0x11); /* size */
@@ -1211,8 +1235,12 @@ static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra
mov_write_stts_tag(pb, track);
if ((track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
track->par->codec_tag == MKTAG('r','t','p',' ')) &&
- track->has_keyframes && track->has_keyframes < track->entry)
+ track->has_keyframes && track->has_keyframes < track->entry) {
mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE);
+ }
+ if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && track->has_disposable) {
+ mov_write_sdtp_tag(pb, track);
+ }
if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS)
mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE);
if (track->par->codec_type == AVMEDIA_TYPE_VIDEO &&
@@ -3647,6 +3675,10 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE)
trk->has_keyframes++;
}
+ if (pkt->flags & AV_PKT_FLAG_DISPOSABLE) {
+ trk->cluster[trk->entry].flags |= MOV_DISPOSABLE_SAMPLE;
+ trk->has_disposable++;
+ }
trk->entry++;
trk->sample_count += samples_in_chunk;
mov->mdat_size += size;
diff --git a/libavformat/movenc.h b/libavformat/movenc.h
index 008f4671c6..f4eb4e8078 100644
--- a/libavformat/movenc.h
+++ b/libavformat/movenc.h
@@ -51,6 +51,7 @@ typedef struct MOVIentry {
int cts;
#define MOV_SYNC_SAMPLE 0x0001
#define MOV_PARTIAL_SYNC_SAMPLE 0x0002
+#define MOV_DISPOSABLE_SAMPLE 0x0004
uint32_t flags;
} MOVIentry;
@@ -85,6 +86,7 @@ typedef struct MOVTrack {
long sample_count;
long sample_size;
int has_keyframes;
+ int has_disposable;
#define MOV_TRACK_CTTS 0x0001
#define MOV_TRACK_STPS 0x0002
#define MOV_TRACK_ENABLED 0x0004
@@ -180,6 +182,10 @@ typedef struct MOVMuxContext {
int missing_duration_warned;
} MOVMuxContext;
+#define MOV_SAMPLE_DEPENDENCY_UNKNOWN 0x0
+#define MOV_SAMPLE_DEPENDENCY_YES 0x1
+#define MOV_SAMPLE_DEPENDENCY_NO 0x2
+
#define FF_MOV_FLAG_RTP_HINT (1 << 0)
#define FF_MOV_FLAG_FRAGMENT (1 << 1)
#define FF_MOV_FLAG_EMPTY_MOOV (1 << 2)
--
2.13.6
|