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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
From 25a0ee27bb5d2bb46781ea4a2a3c88581ad75fde Mon Sep 17 00:00:00 2001
From: John Stebbins <jstebbins.hb@gmail.com>
Date: Fri, 10 May 2013 09:16:08 -0700
Subject: [PATCH 8/9] movenc: Make tkhd "enabled" flag QuickTime compatible
QuickTime will play multiple audio tracks concurrently if this flag is
set for multiple audio tracks. And if no subtitle track has this flag
set QuickTime will show no subtitles in the subtitle menu.
---
libavformat/mov.c | 4 +++-
libavformat/movenc.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++-
libavformat/movenc.h | 1 +
3 files changed, 63 insertions(+), 2 deletions(-)
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 7fe0548..cb0e395 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -2129,6 +2129,7 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
AVStream *st;
MOVStreamContext *sc;
int version;
+ int flags;
if (c->fc->nb_streams < 1)
return 0;
@@ -2136,13 +2137,14 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
sc = st->priv_data;
version = avio_r8(pb);
- avio_rb24(pb); /* flags */
+ flags = avio_rb24(pb); /* flags */
/*
MOV_TRACK_ENABLED 0x0001
MOV_TRACK_IN_MOVIE 0x0002
MOV_TRACK_IN_PREVIEW 0x0004
MOV_TRACK_IN_POSTER 0x0008
*/
+ st->disposition |= (flags & 0x1) ? AV_DISPOSITION_DEFAULT : 0;
if (version == 1) {
avio_rb64(pb);
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 2f6c003..bc77a6f 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -1387,7 +1387,13 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVTrack *track, AVStream *st)
(version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */
ffio_wfourcc(pb, "tkhd");
avio_w8(pb, version);
- avio_wb24(pb, 0xf); /* flags (track enabled) */
+ avio_wb24(pb, (track->flags & MOV_TRACK_ENABLED) ? 0x3 : 0x2); /* flags */
+ /*
+ MOV_TRACK_ENABLED 0x0001
+ MOV_TRACK_IN_MOVIE 0x0002
+ MOV_TRACK_IN_PREVIEW 0x0004
+ MOV_TRACK_IN_POSTER 0x0008
+ */
if (version == 1) {
avio_wb64(pb, track->time);
avio_wb64(pb, track->time);
@@ -3003,6 +3009,56 @@ static void mov_create_chapter_track(AVFormatContext *s, int tracknum)
}
}
+// st->disposition controls the "enabled" flag in the tkhd tag.
+// QuickTime will not play a track if it is not enabled. So make sure
+// that one track of each type (audio, video, subtitle) is enabled.
+//
+// Subtitles are special. For audio and video, setting "enabled" also
+// makes the track "default" (i.e. it is rendered when played). For
+// subtitles, an "enabled" subtitle is not rendered by default, but
+// if no subtitle is enabled, the subtitle menu in QuickTime will be
+// empty!
+static void enable_tracks(AVFormatContext *s)
+{
+ MOVMuxContext *mov = s->priv_data;
+ int i;
+ uint8_t enabled[AVMEDIA_TYPE_NB];
+ int first[AVMEDIA_TYPE_NB];
+
+ for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
+ enabled[i] = 0;
+ first[i] = -1;
+ }
+
+ for (i = 0; i < s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+
+ if (st->codec->codec_type <= AVMEDIA_TYPE_UNKNOWN ||
+ st->codec->codec_type >= AVMEDIA_TYPE_NB)
+ continue;
+
+ if (first[st->codec->codec_type] < 0)
+ first[st->codec->codec_type] = i;
+ if (st->disposition & AV_DISPOSITION_DEFAULT) {
+ mov->tracks[i].flags |= MOV_TRACK_ENABLED;
+ enabled[st->codec->codec_type] = 1;
+ }
+ }
+
+ for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
+ switch (i) {
+ case AVMEDIA_TYPE_VIDEO:
+ case AVMEDIA_TYPE_AUDIO:
+ case AVMEDIA_TYPE_SUBTITLE:
+ if (!enabled[i] && first[i] >= 0)
+ mov->tracks[first[i]].flags |= MOV_TRACK_ENABLED;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
static int mov_write_header(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
@@ -3156,6 +3212,8 @@ static int mov_write_header(AVFormatContext *s)
}
}
+ enable_tracks(s);
+
if (mov->mode == MODE_ISM) {
/* If no fragmentation options have been set, set a default. */
if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME |
diff --git a/libavformat/movenc.h b/libavformat/movenc.h
index 3ea0dd5..9bb8a78 100644
--- a/libavformat/movenc.h
+++ b/libavformat/movenc.h
@@ -84,6 +84,7 @@ typedef struct MOVIndex {
int has_keyframes;
#define MOV_TRACK_CTTS 0x0001
#define MOV_TRACK_STPS 0x0002
+#define MOV_TRACK_ENABLED 0x0004
uint32_t flags;
int language;
int track_id;
--
1.8.1.4
|