summaryrefslogtreecommitdiffstats
path: root/contrib/ffmpeg/A21-mp4-sdtp.patch
blob: 5d2221c477cdee073460e5e9fc2b44d57d335c9e (plain)
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