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/isom.h | 5 +++++
libavformat/mov.c | 14 +++++++-----
libavformat/movenc.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++-
libavformat/movenc.h | 1 +
4 files changed, 75 insertions(+), 7 deletions(-)
diff --git a/libavformat/isom.h b/libavformat/isom.h
index 932b1d0..94f1296 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -190,6 +190,11 @@ void ff_mp4_parse_es_descr(AVIOContext *pb, int *es_id);
#define MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO 0x02000000
#define MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES 0x01000000
+#define MOV_TKHD_FLAG_ENABLED 0x0001
+#define MOV_TKHD_FLAG_IN_MOVIE 0x0002
+#define MOV_TKHD_FLAG_IN_PREVIEW 0x0004
+#define MOV_TKHD_FLAG_IN_POSTER 0x0008
+
int ff_mov_read_esds(AVFormatContext *fc, AVIOContext *pb, MOVAtom atom);
enum AVCodecID ff_mov_get_lpcm_codec_id(int bps, int flags);
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 0c938cd..c644699 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -2125,6 +2125,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;
@@ -2132,13 +2133,14 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext
*pb, MOVAtom atom)
sc = st->priv_data;
version = avio_r8(pb);
- avio_rb24(pb); /* flags */
- /*
- MOV_TRACK_ENABLED 0x0001
- MOV_TRACK_IN_MOVIE 0x0002
- MOV_TRACK_IN_PREVIEW 0x0004
- MOV_TRACK_IN_POSTER 0x0008
+ flags = avio_rb24(pb);
+ /* flags
+ MOV_TKHD_FLAG_ENABLED 0x0001
+ MOV_TKHD_FLAG_IN_MOVIE 0x0002
+ MOV_TKHD_FLAG_IN_PREVIEW 0x0004
+ MOV_TKHD_FLAG_IN_POSTER 0x0008
*/
+ st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ?
AV_DISPOSITION_DEFAULT : 0;
if (version == 1) {
avio_rb64(pb);
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 8f3cd72..101767c 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -1380,7 +1380,15 @@ 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) ?
+ MOV_TKHD_FLAG_ENABLED | MOV_TKHD_FLAG_IN_MOVIE :
+ MOV_TKHD_FLAG_IN_MOVIE);
+ /* flags
+ MOV_TKHD_FLAG_ENABLED 0x0001
+ MOV_TKHD_FLAG_IN_MOVIE 0x0002
+ MOV_TKHD_FLAG_IN_PREVIEW 0x0004
+ MOV_TKHD_FLAG_IN_POSTER 0x0008
+ */
if (version == 1) {
avio_wb64(pb, track->time);
avio_wb64(pb, track->time);
@@ -3017,6 +3025,56 @@ static int mov_create_chapter_track(AVFormatContext *s,
int tracknum)
return 0;
}
+// 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;
@@ -3169,6 +3227,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 a6282e1..78001cc 100644
--- a/libavformat/movenc.h
+++ b/libavformat/movenc.h
@@ -85,6 +85,7 @@ typedef struct MOVTrack {
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.3.1
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel