3 * Copyright (c) 2003 Thomas Raivio
4 * Copyright (c) 2004 Gildas Bazin <gbazin at videolan dot org>
5 * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
7 * This file is part of FFmpeg.
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 #include "avio_internal.h"
35 #include "libavcodec/ac3_parser_internal.h"
36 #include "libavcodec/dnxhddata.h"
37 #include "libavcodec/flac.h"
38 #include "libavcodec/get_bits.h"
40 #include "libavcodec/internal.h"
41 #include "libavcodec/put_bits.h"
42 #include "libavcodec/vc1_common.h"
43 #include "libavcodec/raw.h"
45 #include "libavutil/avstring.h"
46 #include "libavutil/intfloat.h"
47 #include "libavutil/mathematics.h"
48 #include "libavutil/libm.h"
49 #include "libavutil/opt.h"
50 #include "libavutil/dict.h"
51 #include "libavutil/pixdesc.h"
52 #include "libavutil/stereo3d.h"
53 #include "libavutil/timecode.h"
54 #include "libavutil/dovi_meta.h"
55 #include "libavutil/color_utils.h"
61 static const AVOption options
[] = {
62 { "movflags", "MOV muxer flags", offsetof(MOVMuxContext
, flags
), AV_OPT_TYPE_FLAGS
, {.i64
= 0}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
63 { "rtphint", "Add RTP hint tracks", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_RTP_HINT
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
64 { "moov_size", "maximum moov size so it can be placed at the begin", offsetof(MOVMuxContext
, reserved_moov_size
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, 0 },
65 { "empty_moov", "Make the initial moov atom empty", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_EMPTY_MOOV
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
66 { "frag_keyframe", "Fragment at video keyframes", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_FRAG_KEYFRAME
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
67 { "frag_every_frame", "Fragment at every frame", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_FRAG_EVERY_FRAME
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
68 { "separate_moof", "Write separate moof/mdat atoms for each track", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_SEPARATE_MOOF
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
69 { "frag_custom", "Flush fragments on caller requests", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_FRAG_CUSTOM
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
70 { "isml", "Create a live smooth streaming feed (for pushing to a publishing point)", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_ISML
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
71 { "faststart", "Run a second pass to put the index (moov atom) at the beginning of the file", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_FASTSTART
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
72 { "omit_tfhd_offset", "Omit the base data offset in tfhd atoms", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_OMIT_TFHD_OFFSET
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
73 { "disable_chpl", "Disable Nero chapter atom", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_DISABLE_CHPL
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
74 { "default_base_moof", "Set the default-base-is-moof flag in tfhd atoms", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_DEFAULT_BASE_MOOF
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
75 { "dash", "Write DASH compatible fragmented MP4", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_DASH
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
76 { "cmaf", "Write CMAF compatible fragmented MP4", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_CMAF
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
77 { "frag_discont", "Signal that the next fragment is discontinuous from earlier ones", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_FRAG_DISCONT
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
78 { "delay_moov", "Delay writing the initial moov until the first fragment is cut, or until the first fragment flush", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_DELAY_MOOV
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
79 { "global_sidx", "Write a global sidx index at the start of the file", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_GLOBAL_SIDX
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
80 { "skip_sidx", "Skip writing of sidx atom", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_SKIP_SIDX
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
81 { "write_colr", "Write colr atom (Experimental, may be renamed or changed, do not use from scripts)", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_WRITE_COLR
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
82 { "prefer_icc", "If writing colr atom prioritise usage of ICC profile if it exists in stream packet side data", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_PREFER_ICC
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
83 { "write_gama", "Write deprecated gama atom", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_WRITE_GAMA
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
84 { "use_metadata_tags", "Use mdta atom for metadata.", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_USE_MDTA
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
85 { "skip_trailer", "Skip writing the mfra/tfra/mfro trailer for fragmented files", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_SKIP_TRAILER
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
86 { "negative_cts_offsets", "Use negative CTS offsets (reducing the need for edit lists)", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
87 FF_RTP_FLAG_OPTS(MOVMuxContext
, rtp_flags
),
88 { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext
, iods_skip
), AV_OPT_TYPE_BOOL
, {.i64
= 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM
},
89 { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext
, iods_audio_profile
), AV_OPT_TYPE_INT
, {.i64
= -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM
},
90 { "iods_video_profile", "iods video profile atom.", offsetof(MOVMuxContext
, iods_video_profile
), AV_OPT_TYPE_INT
, {.i64
= -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM
},
91 { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext
, max_fragment_duration
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
},
92 { "min_frag_duration", "Minimum fragment duration", offsetof(MOVMuxContext
, min_fragment_duration
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
},
93 { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext
, max_fragment_size
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
},
94 { "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext
, ism_lookahead
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
},
95 { "video_track_timescale", "set timescale of all video tracks", offsetof(MOVMuxContext
, video_track_timescale
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
},
96 { "brand", "Override major brand", offsetof(MOVMuxContext
, major_brand
), AV_OPT_TYPE_STRING
, {.str
= NULL
}, .flags
= AV_OPT_FLAG_ENCODING_PARAM
},
97 { "use_editlist", "use edit list", offsetof(MOVMuxContext
, use_editlist
), AV_OPT_TYPE_BOOL
, {.i64
= -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM
},
98 { "fragment_index", "Fragment number of the next fragment", offsetof(MOVMuxContext
, fragments
), AV_OPT_TYPE_INT
, {.i64
= 1}, 1, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
},
99 { "mov_gamma", "gamma value for gama atom", offsetof(MOVMuxContext
, gamma
), AV_OPT_TYPE_FLOAT
, {.dbl
= 0.0 }, 0.0, 10, AV_OPT_FLAG_ENCODING_PARAM
},
100 { "frag_interleave", "Interleave samples within fragments (max number of consecutive samples, lower is tighter interleaving, but with more overhead)", offsetof(MOVMuxContext
, frag_interleave
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
},
101 { "encryption_scheme", "Configures the encryption scheme, allowed values are none, cenc-aes-ctr", offsetof(MOVMuxContext
, encryption_scheme_str
), AV_OPT_TYPE_STRING
, {.str
= NULL
}, .flags
= AV_OPT_FLAG_ENCODING_PARAM
},
102 { "encryption_key", "The media encryption key (hex)", offsetof(MOVMuxContext
, encryption_key
), AV_OPT_TYPE_BINARY
, .flags
= AV_OPT_FLAG_ENCODING_PARAM
},
103 { "encryption_kid", "The media encryption key identifier (hex)", offsetof(MOVMuxContext
, encryption_kid
), AV_OPT_TYPE_BINARY
, .flags
= AV_OPT_FLAG_ENCODING_PARAM
},
104 { "use_stream_ids_as_track_ids", "use stream ids as track ids", offsetof(MOVMuxContext
, use_stream_ids_as_track_ids
), AV_OPT_TYPE_BOOL
, {.i64
= 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM
},
105 { "write_tmcd", "force or disable writing tmcd", offsetof(MOVMuxContext
, write_tmcd
), AV_OPT_TYPE_BOOL
, {.i64
= -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM
},
106 { "write_prft", "Write producer reference time box with specified time source", offsetof(MOVMuxContext
, write_prft
), AV_OPT_TYPE_INT
, {.i64
= MOV_PRFT_NONE
}, 0, MOV_PRFT_NB
-1, AV_OPT_FLAG_ENCODING_PARAM
, "prft"},
107 { "wallclock", NULL
, 0, AV_OPT_TYPE_CONST
, {.i64
= MOV_PRFT_SRC_WALLCLOCK
}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM
, "prft"},
108 { "pts", NULL
, 0, AV_OPT_TYPE_CONST
, {.i64
= MOV_PRFT_SRC_PTS
}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM
, "prft"},
109 { "empty_hdlr_name", "write zero-length name string in hdlr atoms within mdia and minf atoms", offsetof(MOVMuxContext
, empty_hdlr_name
), AV_OPT_TYPE_BOOL
, {.i64
= 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM
},
113 #define MOV_CLASS(flavor)\
114 static const AVClass flavor ## _muxer_class = {\
115 .class_name = #flavor " muxer",\
116 .item_name = av_default_item_name,\
118 .version = LIBAVUTIL_VERSION_INT,\
121 static int get_moov_size(AVFormatContext
*s
);
123 static int utf8len(const uint8_t *b
)
128 GET_UTF8(val
, *b
++, return -1;)
134 //FIXME support 64 bit variant with wide placeholders
135 static int64_t update_size(AVIOContext
*pb
, int64_t pos
)
137 int64_t curpos
= avio_tell(pb
);
138 avio_seek(pb
, pos
, SEEK_SET
);
139 avio_wb32(pb
, curpos
- pos
); /* rewrite size */
140 avio_seek(pb
, curpos
, SEEK_SET
);
145 static int co64_required(const MOVTrack
*track
)
147 if (track
->entry
> 0 && track
->cluster
[track
->entry
- 1].pos
+ track
->data_offset
> UINT32_MAX
)
152 static int is_cover_image(const AVStream
*st
)
154 /* Eg. AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS
155 * is encoded as sparse video track */
156 return st
&& st
->disposition
== AV_DISPOSITION_ATTACHED_PIC
;
159 static int rtp_hinting_needed(const AVStream
*st
)
161 /* Add hint tracks for each real audio and video stream */
162 if (is_cover_image(st
))
164 return st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
||
165 st
->codecpar
->codec_type
== AVMEDIA_TYPE_AUDIO
;
168 /* Chunk offset atom */
169 static int mov_write_stco_tag(AVIOContext
*pb
, MOVTrack
*track
)
172 int mode64
= co64_required(track
); // use 32 bit size variant if possible
173 int64_t pos
= avio_tell(pb
);
174 avio_wb32(pb
, 0); /* size */
176 ffio_wfourcc(pb
, "co64");
178 ffio_wfourcc(pb
, "stco");
179 avio_wb32(pb
, 0); /* version & flags */
180 avio_wb32(pb
, track
->chunkCount
); /* entry count */
181 for (i
= 0; i
< track
->entry
; i
++) {
182 if (!track
->cluster
[i
].chunkNum
)
185 avio_wb64(pb
, track
->cluster
[i
].pos
+ track
->data_offset
);
187 avio_wb32(pb
, track
->cluster
[i
].pos
+ track
->data_offset
);
189 return update_size(pb
, pos
);
192 /* Sample size atom */
193 static int mov_write_stsz_tag(AVIOContext
*pb
, MOVTrack
*track
)
196 int i
, j
, entries
= 0, tst
= -1, oldtst
= -1;
198 int64_t pos
= avio_tell(pb
);
199 avio_wb32(pb
, 0); /* size */
200 ffio_wfourcc(pb
, "stsz");
201 avio_wb32(pb
, 0); /* version & flags */
203 for (i
= 0; i
< track
->entry
; i
++) {
204 tst
= track
->cluster
[i
].size
/ track
->cluster
[i
].entries
;
205 if (oldtst
!= -1 && tst
!= oldtst
)
208 entries
+= track
->cluster
[i
].entries
;
210 if (equalChunks
&& track
->entry
) {
211 int sSize
= track
->entry
? track
->cluster
[0].size
/ track
->cluster
[0].entries
: 0;
212 sSize
= FFMAX(1, sSize
); // adpcm mono case could make sSize == 0
213 avio_wb32(pb
, sSize
); // sample size
214 avio_wb32(pb
, entries
); // sample count
216 avio_wb32(pb
, 0); // sample size
217 avio_wb32(pb
, entries
); // sample count
218 for (i
= 0; i
< track
->entry
; i
++) {
219 for (j
= 0; j
< track
->cluster
[i
].entries
; j
++) {
220 avio_wb32(pb
, track
->cluster
[i
].size
/
221 track
->cluster
[i
].entries
);
225 return update_size(pb
, pos
);
228 /* Sample to chunk atom */
229 static int mov_write_stsc_tag(AVIOContext
*pb
, MOVTrack
*track
)
231 int index
= 0, oldval
= -1, i
;
232 int64_t entryPos
, curpos
;
234 int64_t pos
= avio_tell(pb
);
235 avio_wb32(pb
, 0); /* size */
236 ffio_wfourcc(pb
, "stsc");
237 avio_wb32(pb
, 0); // version & flags
238 entryPos
= avio_tell(pb
);
239 avio_wb32(pb
, track
->chunkCount
); // entry count
240 for (i
= 0; i
< track
->entry
; i
++) {
241 if (oldval
!= track
->cluster
[i
].samples_in_chunk
&& track
->cluster
[i
].chunkNum
) {
242 avio_wb32(pb
, track
->cluster
[i
].chunkNum
); // first chunk
243 avio_wb32(pb
, track
->cluster
[i
].samples_in_chunk
); // samples per chunk
244 avio_wb32(pb
, 0x1); // sample description index
245 oldval
= track
->cluster
[i
].samples_in_chunk
;
249 curpos
= avio_tell(pb
);
250 avio_seek(pb
, entryPos
, SEEK_SET
);
251 avio_wb32(pb
, index
); // rewrite size
252 avio_seek(pb
, curpos
, SEEK_SET
);
254 return update_size(pb
, pos
);
257 /* Sync sample atom */
258 static int mov_write_stss_tag(AVIOContext
*pb
, MOVTrack
*track
, uint32_t flag
)
260 int64_t curpos
, entryPos
;
262 int64_t pos
= avio_tell(pb
);
263 avio_wb32(pb
, 0); // size
264 ffio_wfourcc(pb
, flag
== MOV_SYNC_SAMPLE
? "stss" : "stps");
265 avio_wb32(pb
, 0); // version & flags
266 entryPos
= avio_tell(pb
);
267 avio_wb32(pb
, track
->entry
); // entry count
268 for (i
= 0; i
< track
->entry
; i
++) {
269 if (track
->cluster
[i
].flags
& flag
) {
270 avio_wb32(pb
, i
+ 1);
274 curpos
= avio_tell(pb
);
275 avio_seek(pb
, entryPos
, SEEK_SET
);
276 avio_wb32(pb
, index
); // rewrite size
277 avio_seek(pb
, curpos
, SEEK_SET
);
278 return update_size(pb
, pos
);
281 /* Sample dependency atom */
282 static int mov_write_sdtp_tag(AVIOContext
*pb
, MOVTrack
*track
)
285 uint8_t leading
, dependent
, reference
, redundancy
;
286 int64_t pos
= avio_tell(pb
);
287 avio_wb32(pb
, 0); // size
288 ffio_wfourcc(pb
, "sdtp");
289 avio_wb32(pb
, 0); // version & flags
290 for (i
= 0; i
< track
->entry
; i
++) {
291 dependent
= MOV_SAMPLE_DEPENDENCY_YES
;
292 leading
= reference
= redundancy
= MOV_SAMPLE_DEPENDENCY_UNKNOWN
;
293 if (track
->cluster
[i
].flags
& MOV_DISPOSABLE_SAMPLE
) {
294 reference
= MOV_SAMPLE_DEPENDENCY_NO
;
296 if (track
->cluster
[i
].flags
& MOV_SYNC_SAMPLE
) {
297 dependent
= MOV_SAMPLE_DEPENDENCY_NO
;
299 avio_w8(pb
, (leading
<< 6) | (dependent
<< 4) |
300 (reference
<< 2) | redundancy
);
302 return update_size(pb
, pos
);
305 static int mov_write_amr_tag(AVIOContext
*pb
, MOVTrack
*track
)
307 avio_wb32(pb
, 0x11); /* size */
308 if (track
->mode
== MODE_MOV
) ffio_wfourcc(pb
, "samr");
309 else ffio_wfourcc(pb
, "damr");
310 ffio_wfourcc(pb
, "FFMP");
311 avio_w8(pb
, 0); /* decoder version */
313 avio_wb16(pb
, 0x81FF); /* Mode set (all modes for AMR_NB) */
314 avio_w8(pb
, 0x00); /* Mode change period (no restriction) */
315 avio_w8(pb
, 0x01); /* Frames per sample */
319 static int mov_write_ac3_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
324 int fscod
, bsid
, bsmod
, acmod
, lfeon
, frmsizecod
;
326 if (track
->vos_len
< 7) {
327 av_log(s
, AV_LOG_ERROR
,
328 "Cannot write moov atom before AC3 packets."
329 " Set the delay_moov flag to fix this.\n");
330 return AVERROR(EINVAL
);
334 ffio_wfourcc(pb
, "dac3");
336 init_get_bits(&gbc
, track
->vos_data
+ 4, (track
->vos_len
- 4) * 8);
337 fscod
= get_bits(&gbc
, 2);
338 frmsizecod
= get_bits(&gbc
, 6);
339 bsid
= get_bits(&gbc
, 5);
340 bsmod
= get_bits(&gbc
, 3);
341 acmod
= get_bits(&gbc
, 3);
343 skip_bits(&gbc
, 2); // dsurmod
345 if ((acmod
& 1) && acmod
!= 1)
346 skip_bits(&gbc
, 2); // cmixlev
348 skip_bits(&gbc
, 2); // surmixlev
350 lfeon
= get_bits1(&gbc
);
352 init_put_bits(&pbc
, buf
, sizeof(buf
));
353 put_bits(&pbc
, 2, fscod
);
354 put_bits(&pbc
, 5, bsid
);
355 put_bits(&pbc
, 3, bsmod
);
356 put_bits(&pbc
, 3, acmod
);
357 put_bits(&pbc
, 1, lfeon
);
358 put_bits(&pbc
, 5, frmsizecod
>> 1); // bit_rate_code
359 put_bits(&pbc
, 5, 0); // reserved
361 flush_put_bits(&pbc
);
362 avio_write(pb
, buf
, sizeof(buf
));
372 /* Layout of the EC3SpecificBox */
373 /* maximum bitrate */
375 /* number of independent substreams */
378 /* sample rate code (see ff_ac3_sample_rate_tab) 2 bits */
380 /* bit stream identification 5 bits */
382 /* one bit reserved */
383 /* audio service mixing (not supported yet) 1 bit */
384 /* bit stream mode 3 bits */
386 /* audio coding mode 3 bits */
388 /* sub woofer on 1 bit */
390 /* 3 bits reserved */
391 /* number of dependent substreams associated with this substream 4 bits */
393 /* channel locations of the dependent substream(s), if any, 9 bits */
395 /* if there is no dependent substream, then one bit reserved instead */
396 } substream
[1]; /* TODO: support 8 independent substreams */
399 #if CONFIG_AC3_PARSER
400 static int handle_eac3(MOVMuxContext
*mov
, AVPacket
*pkt
, MOVTrack
*track
)
402 AC3HeaderInfo
*hdr
= NULL
;
403 struct eac3_info
*info
;
406 if (!track
->eac3_priv
&& !(track
->eac3_priv
= av_mallocz(sizeof(*info
))))
407 return AVERROR(ENOMEM
);
408 info
= track
->eac3_priv
;
410 if (avpriv_ac3_parse_header(&hdr
, pkt
->data
, pkt
->size
) < 0) {
411 /* drop the packets until we see a good one */
413 av_log(mov
->fc
, AV_LOG_WARNING
, "Dropping invalid packet from start of the stream\n");
416 ret
= AVERROR_INVALIDDATA
;
420 info
->data_rate
= FFMAX(info
->data_rate
, hdr
->bit_rate
/ 1000);
421 num_blocks
= hdr
->num_blocks
;
423 if (!info
->ec3_done
) {
424 /* AC-3 substream must be the first one */
425 if (hdr
->bitstream_id
<= 10 && hdr
->substreamid
!= 0) {
426 ret
= AVERROR(EINVAL
);
430 /* this should always be the case, given that our AC-3 parser
431 * concatenates dependent frames to their independent parent */
432 if (hdr
->frame_type
== EAC3_FRAME_TYPE_INDEPENDENT
) {
433 /* substream ids must be incremental */
434 if (hdr
->substreamid
> info
->num_ind_sub
+ 1) {
435 ret
= AVERROR(EINVAL
);
439 if (hdr
->substreamid
== info
->num_ind_sub
+ 1) {
440 //info->num_ind_sub++;
441 avpriv_request_sample(mov
->fc
, "Multiple independent substreams");
442 ret
= AVERROR_PATCHWELCOME
;
444 } else if (hdr
->substreamid
< info
->num_ind_sub
||
445 hdr
->substreamid
== 0 && info
->substream
[0].bsid
) {
450 if (hdr
->substreamid
!= 0) {
451 avpriv_request_sample(mov
->fc
, "Multiple non EAC3 independent substreams");
452 ret
= AVERROR_PATCHWELCOME
;
457 /* fill the info needed for the "dec3" atom */
458 info
->substream
[hdr
->substreamid
].fscod
= hdr
->sr_code
;
459 info
->substream
[hdr
->substreamid
].bsid
= hdr
->bitstream_id
;
460 info
->substream
[hdr
->substreamid
].bsmod
= hdr
->bitstream_mode
;
461 info
->substream
[hdr
->substreamid
].acmod
= hdr
->channel_mode
;
462 info
->substream
[hdr
->substreamid
].lfeon
= hdr
->lfe_on
;
464 /* Parse dependent substream(s), if any */
465 if (pkt
->size
!= hdr
->frame_size
) {
466 int cumul_size
= hdr
->frame_size
;
467 int parent
= hdr
->substreamid
;
469 while (cumul_size
!= pkt
->size
) {
472 ret
= avpriv_ac3_parse_header(&hdr
, pkt
->data
+ cumul_size
, pkt
->size
- cumul_size
);
475 if (hdr
->frame_type
!= EAC3_FRAME_TYPE_DEPENDENT
) {
476 ret
= AVERROR(EINVAL
);
479 info
->substream
[parent
].num_dep_sub
++;
482 /* header is parsed up to lfeon, but custom channel map may be needed */
483 init_get_bits8(&gbc
, pkt
->data
+ cumul_size
+ ret
, pkt
->size
- cumul_size
- ret
);
486 /* skip volume control params */
487 for (i
= 0; i
< (hdr
->channel_mode
? 1 : 2); i
++) {
488 skip_bits(&gbc
, 5); // skip dialog normalization
489 if (get_bits1(&gbc
)) {
490 skip_bits(&gbc
, 8); // skip compression gain word
493 /* get the dependent stream channel map, if exists */
495 info
->substream
[parent
].chan_loc
|= (get_bits(&gbc
, 16) >> 5) & 0x1f;
497 info
->substream
[parent
].chan_loc
|= hdr
->channel_mode
;
498 cumul_size
+= hdr
->frame_size
;
504 if (!info
->num_blocks
&& num_blocks
== 6) {
508 else if (info
->num_blocks
+ num_blocks
> 6) {
509 ret
= AVERROR_INVALIDDATA
;
513 if (!info
->num_blocks
) {
514 ret
= av_packet_ref(&info
->pkt
, pkt
);
516 info
->num_blocks
= num_blocks
;
519 if ((ret
= av_grow_packet(&info
->pkt
, pkt
->size
)) < 0)
521 memcpy(info
->pkt
.data
+ info
->pkt
.size
- pkt
->size
, pkt
->data
, pkt
->size
);
522 info
->num_blocks
+= num_blocks
;
523 info
->pkt
.duration
+= pkt
->duration
;
524 if (info
->num_blocks
!= 6)
526 av_packet_unref(pkt
);
527 av_packet_move_ref(pkt
, &info
->pkt
);
528 info
->num_blocks
= 0;
539 static int mov_write_eac3_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
543 struct eac3_info
*info
;
546 if (!track
->eac3_priv
) {
547 av_log(s
, AV_LOG_ERROR
,
548 "Cannot write moov atom before EAC3 packets parsed.\n");
549 return AVERROR(EINVAL
);
552 info
= track
->eac3_priv
;
553 size
= 2 + ((34 * (info
->num_ind_sub
+ 1) + 7) >> 3);
554 buf
= av_malloc(size
);
556 return AVERROR(ENOMEM
);
559 init_put_bits(&pbc
, buf
, size
);
560 put_bits(&pbc
, 13, info
->data_rate
);
561 put_bits(&pbc
, 3, info
->num_ind_sub
);
562 for (i
= 0; i
<= info
->num_ind_sub
; i
++) {
563 put_bits(&pbc
, 2, info
->substream
[i
].fscod
);
564 put_bits(&pbc
, 5, info
->substream
[i
].bsid
);
565 put_bits(&pbc
, 1, 0); /* reserved */
566 put_bits(&pbc
, 1, 0); /* asvc */
567 put_bits(&pbc
, 3, info
->substream
[i
].bsmod
);
568 put_bits(&pbc
, 3, info
->substream
[i
].acmod
);
569 put_bits(&pbc
, 1, info
->substream
[i
].lfeon
);
570 put_bits(&pbc
, 5, 0); /* reserved */
571 put_bits(&pbc
, 4, info
->substream
[i
].num_dep_sub
);
572 if (!info
->substream
[i
].num_dep_sub
) {
573 put_bits(&pbc
, 1, 0); /* reserved */
575 put_bits(&pbc
, 9, info
->substream
[i
].chan_loc
);
578 flush_put_bits(&pbc
);
579 size
= put_bits_count(&pbc
) >> 3;
581 avio_wb32(pb
, size
+ 8);
582 ffio_wfourcc(pb
, "dec3");
583 avio_write(pb
, buf
, size
);
591 * This function writes extradata "as is".
592 * Extradata must be formatted like a valid atom (with size and tag).
594 static int mov_write_extradata_tag(AVIOContext
*pb
, MOVTrack
*track
)
596 avio_write(pb
, track
->par
->extradata
, track
->par
->extradata_size
);
597 return track
->par
->extradata_size
;
600 static int mov_write_enda_tag(AVIOContext
*pb
)
603 ffio_wfourcc(pb
, "enda");
604 avio_wb16(pb
, 1); /* little endian */
608 static int mov_write_enda_tag_be(AVIOContext
*pb
)
611 ffio_wfourcc(pb
, "enda");
612 avio_wb16(pb
, 0); /* big endian */
616 static void put_descr(AVIOContext
*pb
, int tag
, unsigned int size
)
621 avio_w8(pb
, (size
>> (7 * i
)) | 0x80);
622 avio_w8(pb
, size
& 0x7F);
625 static unsigned compute_avg_bitrate(MOVTrack
*track
)
629 if (!track
->track_duration
)
631 for (i
= 0; i
< track
->entry
; i
++)
632 size
+= track
->cluster
[i
].size
;
633 return size
* 8 * track
->timescale
/ track
->track_duration
;
636 static int mov_write_esds_tag(AVIOContext
*pb
, MOVTrack
*track
) // Basic
638 AVCPBProperties
*props
;
639 int64_t pos
= avio_tell(pb
);
640 int decoder_specific_info_len
= track
->vos_len
? 5 + track
->vos_len
: 0;
641 unsigned avg_bitrate
;
643 avio_wb32(pb
, 0); // size
644 ffio_wfourcc(pb
, "esds");
645 avio_wb32(pb
, 0); // Version
648 put_descr(pb
, 0x03, 3 + 5+13 + decoder_specific_info_len
+ 5+1);
649 avio_wb16(pb
, track
->track_id
);
650 avio_w8(pb
, 0x00); // flags (= no flags)
652 // DecoderConfig descriptor
653 put_descr(pb
, 0x04, 13 + decoder_specific_info_len
);
655 // Object type indication
656 if ((track
->par
->codec_id
== AV_CODEC_ID_MP2
||
657 track
->par
->codec_id
== AV_CODEC_ID_MP3
) &&
658 track
->par
->sample_rate
> 24000)
659 avio_w8(pb
, 0x6B); // 11172-3
661 avio_w8(pb
, ff_codec_get_tag(ff_mp4_obj_type
, track
->par
->codec_id
));
663 // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
664 // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
665 if (track
->par
->codec_id
== AV_CODEC_ID_DVD_SUBTITLE
)
666 avio_w8(pb
, (0x38 << 2) | 1); // flags (= NeroSubpicStream)
667 else if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
)
668 avio_w8(pb
, 0x15); // flags (= Audiostream)
670 avio_w8(pb
, 0x11); // flags (= Visualstream)
672 props
= (AVCPBProperties
*)av_stream_get_side_data(track
->st
, AV_PKT_DATA_CPB_PROPERTIES
,
675 avio_wb24(pb
, props
? props
->buffer_size
/ 8 : 0); // Buffersize DB
677 avg_bitrate
= compute_avg_bitrate(track
);
678 avio_wb32(pb
, props
? FFMAX3(props
->max_bitrate
, props
->avg_bitrate
, avg_bitrate
) : FFMAX(track
->par
->bit_rate
, avg_bitrate
)); // maxbitrate (FIXME should be max rate in any 1 sec window)
679 avio_wb32(pb
, avg_bitrate
);
681 if (track
->vos_len
) {
682 // DecoderSpecific info descriptor
683 put_descr(pb
, 0x05, track
->vos_len
);
684 avio_write(pb
, track
->vos_data
, track
->vos_len
);
688 put_descr(pb
, 0x06, 1);
690 return update_size(pb
, pos
);
693 static int mov_pcm_le_gt16(enum AVCodecID codec_id
)
695 return codec_id
== AV_CODEC_ID_PCM_S24LE
||
696 codec_id
== AV_CODEC_ID_PCM_S32LE
||
697 codec_id
== AV_CODEC_ID_PCM_F32LE
||
698 codec_id
== AV_CODEC_ID_PCM_F64LE
;
701 static int mov_pcm_be_gt16(enum AVCodecID codec_id
)
703 return codec_id
== AV_CODEC_ID_PCM_S24BE
||
704 codec_id
== AV_CODEC_ID_PCM_S32BE
||
705 codec_id
== AV_CODEC_ID_PCM_F32BE
||
706 codec_id
== AV_CODEC_ID_PCM_F64BE
;
709 static int mov_write_ms_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
712 int64_t pos
= avio_tell(pb
);
714 avio_wl32(pb
, track
->tag
); // store it byteswapped
715 track
->par
->codec_tag
= av_bswap16(track
->tag
>> 16);
716 if ((ret
= ff_put_wav_header(s
, pb
, track
->par
, 0)) < 0)
718 return update_size(pb
, pos
);
721 static int mov_write_wfex_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
724 int64_t pos
= avio_tell(pb
);
726 ffio_wfourcc(pb
, "wfex");
727 if ((ret
= ff_put_wav_header(s
, pb
, track
->st
->codecpar
, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX
)) < 0)
729 return update_size(pb
, pos
);
732 static int mov_write_dfla_tag(AVIOContext
*pb
, MOVTrack
*track
)
734 int64_t pos
= avio_tell(pb
);
736 ffio_wfourcc(pb
, "dfLa");
737 avio_w8(pb
, 0); /* version */
738 avio_wb24(pb
, 0); /* flags */
740 /* Expect the encoder to pass a METADATA_BLOCK_TYPE_STREAMINFO. */
741 if (track
->par
->extradata_size
!= FLAC_STREAMINFO_SIZE
)
742 return AVERROR_INVALIDDATA
;
744 /* TODO: Write other METADATA_BLOCK_TYPEs if the encoder makes them available. */
745 avio_w8(pb
, 1 << 7 | FLAC_METADATA_TYPE_STREAMINFO
); /* LastMetadataBlockFlag << 7 | BlockType */
746 avio_wb24(pb
, track
->par
->extradata_size
); /* Length */
747 avio_write(pb
, track
->par
->extradata
, track
->par
->extradata_size
); /* BlockData[Length] */
749 return update_size(pb
, pos
);
752 static int mov_write_dops_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
754 int64_t pos
= avio_tell(pb
);
756 ffio_wfourcc(pb
, "dOps");
757 avio_w8(pb
, 0); /* Version */
758 if (track
->par
->extradata_size
< 19) {
759 av_log(s
, AV_LOG_ERROR
, "invalid extradata size\n");
760 return AVERROR_INVALIDDATA
;
762 /* extradata contains an Ogg OpusHead, other than byte-ordering and
763 OpusHead's preceeding magic/version, OpusSpecificBox is currently
765 avio_w8(pb
, AV_RB8(track
->par
->extradata
+ 9)); /* OuputChannelCount */
766 avio_wb16(pb
, AV_RL16(track
->par
->extradata
+ 10)); /* PreSkip */
767 avio_wb32(pb
, AV_RL32(track
->par
->extradata
+ 12)); /* InputSampleRate */
768 avio_wb16(pb
, AV_RL16(track
->par
->extradata
+ 16)); /* OutputGain */
769 /* Write the rest of the header out without byte-swapping. */
770 avio_write(pb
, track
->par
->extradata
+ 18, track
->par
->extradata_size
- 18);
772 return update_size(pb
, pos
);
775 static int mov_write_dmlp_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
777 int64_t pos
= avio_tell(pb
);
780 ffio_wfourcc(pb
, "dmlp");
782 if (track
->vos_len
< 20) {
783 av_log(s
, AV_LOG_ERROR
,
784 "Cannot write moov atom before TrueHD packets."
785 " Set the delay_moov flag to fix this.\n");
786 return AVERROR(EINVAL
);
789 length
= (AV_RB16(track
->vos_data
) & 0xFFF) * 2;
790 if (length
< 20 || length
> track
->vos_len
)
791 return AVERROR_INVALIDDATA
;
793 // Only TrueHD is supported
794 if (AV_RB32(track
->vos_data
+ 4) != 0xF8726FBA)
795 return AVERROR_INVALIDDATA
;
797 avio_wb32(pb
, AV_RB32(track
->vos_data
+ 8)); /* format_info */
798 avio_wb16(pb
, AV_RB16(track
->vos_data
+ 18) << 1); /* peak_data_rate */
799 avio_wb32(pb
, 0); /* reserved */
801 return update_size(pb
, pos
);
804 static int mov_write_chan_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
806 uint32_t layout_tag
, bitmap
;
807 int64_t pos
= avio_tell(pb
);
809 layout_tag
= ff_mov_get_channel_layout_tag(track
->par
->codec_id
,
810 track
->par
->channel_layout
,
813 av_log(s
, AV_LOG_WARNING
, "not writing 'chan' tag due to "
814 "lack of channel information\n");
818 if (track
->multichannel_as_mono
)
821 avio_wb32(pb
, 0); // Size
822 ffio_wfourcc(pb
, "chan"); // Type
823 avio_w8(pb
, 0); // Version
824 avio_wb24(pb
, 0); // Flags
825 avio_wb32(pb
, layout_tag
); // mChannelLayoutTag
826 avio_wb32(pb
, bitmap
); // mChannelBitmap
827 avio_wb32(pb
, 0); // mNumberChannelDescriptions
829 return update_size(pb
, pos
);
832 static int mov_write_wave_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
834 int64_t pos
= avio_tell(pb
);
836 avio_wb32(pb
, 0); /* size */
837 ffio_wfourcc(pb
, "wave");
839 if (track
->par
->codec_id
!= AV_CODEC_ID_QDM2
) {
840 avio_wb32(pb
, 12); /* size */
841 ffio_wfourcc(pb
, "frma");
842 avio_wl32(pb
, track
->tag
);
845 if (track
->par
->codec_id
== AV_CODEC_ID_AAC
) {
846 /* useless atom needed by mplayer, ipod, not needed by quicktime */
847 avio_wb32(pb
, 12); /* size */
848 ffio_wfourcc(pb
, "mp4a");
850 mov_write_esds_tag(pb
, track
);
851 } else if (mov_pcm_le_gt16(track
->par
->codec_id
)) {
852 mov_write_enda_tag(pb
);
853 } else if (mov_pcm_be_gt16(track
->par
->codec_id
)) {
854 mov_write_enda_tag_be(pb
);
855 } else if (track
->par
->codec_id
== AV_CODEC_ID_AMR_NB
) {
856 mov_write_amr_tag(pb
, track
);
857 } else if (track
->par
->codec_id
== AV_CODEC_ID_AC3
) {
858 mov_write_ac3_tag(s
, pb
, track
);
859 } else if (track
->par
->codec_id
== AV_CODEC_ID_EAC3
) {
860 mov_write_eac3_tag(s
, pb
, track
);
861 } else if (track
->par
->codec_id
== AV_CODEC_ID_ALAC
||
862 track
->par
->codec_id
== AV_CODEC_ID_QDM2
) {
863 mov_write_extradata_tag(pb
, track
);
864 } else if (track
->par
->codec_id
== AV_CODEC_ID_ADPCM_MS
||
865 track
->par
->codec_id
== AV_CODEC_ID_ADPCM_IMA_WAV
) {
866 mov_write_ms_tag(s
, pb
, track
);
869 avio_wb32(pb
, 8); /* size */
870 avio_wb32(pb
, 0); /* null tag */
872 return update_size(pb
, pos
);
875 static int mov_write_dvc1_structs(MOVTrack
*track
, uint8_t *buf
)
878 const uint8_t *start
, *next
, *end
= track
->vos_data
+ track
->vos_len
;
879 int unescaped_size
, seq_found
= 0;
880 int level
= 0, interlace
= 0;
881 int packet_seq
= track
->vc1_info
.packet_seq
;
882 int packet_entry
= track
->vc1_info
.packet_entry
;
883 int slices
= track
->vc1_info
.slices
;
886 if (track
->start_dts
== AV_NOPTS_VALUE
) {
887 /* No packets written yet, vc1_info isn't authoritative yet. */
888 /* Assume inline sequence and entry headers. */
889 packet_seq
= packet_entry
= 1;
890 av_log(NULL
, AV_LOG_WARNING
,
891 "moov atom written before any packets, unable to write correct "
892 "dvc1 atom. Set the delay_moov flag to fix this.\n");
895 unescaped
= av_mallocz(track
->vos_len
+ AV_INPUT_BUFFER_PADDING_SIZE
);
897 return AVERROR(ENOMEM
);
898 start
= find_next_marker(track
->vos_data
, end
);
899 for (next
= start
; next
< end
; start
= next
) {
902 next
= find_next_marker(start
+ 4, end
);
903 size
= next
- start
- 4;
906 unescaped_size
= vc1_unescape_buffer(start
+ 4, size
, unescaped
);
907 init_get_bits(&gb
, unescaped
, 8 * unescaped_size
);
908 if (AV_RB32(start
) == VC1_CODE_SEQHDR
) {
909 int profile
= get_bits(&gb
, 2);
910 if (profile
!= PROFILE_ADVANCED
) {
912 return AVERROR(ENOSYS
);
915 level
= get_bits(&gb
, 3);
916 /* chromaformat, frmrtq_postproc, bitrtq_postproc, postprocflag,
918 skip_bits_long(&gb
, 2 + 3 + 5 + 1 + 2*12);
919 skip_bits(&gb
, 1); /* broadcast */
920 interlace
= get_bits1(&gb
);
921 skip_bits(&gb
, 4); /* tfcntrflag, finterpflag, reserved, psf */
926 return AVERROR(ENOSYS
);
929 init_put_bits(&pbc
, buf
, 7);
930 /* VC1DecSpecStruc */
931 put_bits(&pbc
, 4, 12); /* profile - advanced */
932 put_bits(&pbc
, 3, level
);
933 put_bits(&pbc
, 1, 0); /* reserved */
934 /* VC1AdvDecSpecStruc */
935 put_bits(&pbc
, 3, level
);
936 put_bits(&pbc
, 1, 0); /* cbr */
937 put_bits(&pbc
, 6, 0); /* reserved */
938 put_bits(&pbc
, 1, !interlace
); /* no interlace */
939 put_bits(&pbc
, 1, !packet_seq
); /* no multiple seq */
940 put_bits(&pbc
, 1, !packet_entry
); /* no multiple entry */
941 put_bits(&pbc
, 1, !slices
); /* no slice code */
942 put_bits(&pbc
, 1, 0); /* no bframe */
943 put_bits(&pbc
, 1, 0); /* reserved */
946 if (track
->st
->avg_frame_rate
.num
> 0 && track
->st
->avg_frame_rate
.den
> 0)
947 put_bits32(&pbc
, track
->st
->avg_frame_rate
.num
/ track
->st
->avg_frame_rate
.den
);
949 put_bits32(&pbc
, 0xffffffff);
951 flush_put_bits(&pbc
);
958 static int mov_write_dvc1_tag(AVIOContext
*pb
, MOVTrack
*track
)
960 uint8_t buf
[7] = { 0 };
963 if ((ret
= mov_write_dvc1_structs(track
, buf
)) < 0)
966 avio_wb32(pb
, track
->vos_len
+ 8 + sizeof(buf
));
967 ffio_wfourcc(pb
, "dvc1");
968 avio_write(pb
, buf
, sizeof(buf
));
969 avio_write(pb
, track
->vos_data
, track
->vos_len
);
974 static int mov_write_glbl_tag(AVIOContext
*pb
, MOVTrack
*track
)
976 avio_wb32(pb
, track
->vos_len
+ 8);
977 ffio_wfourcc(pb
, "glbl");
978 avio_write(pb
, track
->vos_data
, track
->vos_len
);
979 return 8 + track
->vos_len
;
983 * Compute flags for 'lpcm' tag.
984 * See CoreAudioTypes and AudioStreamBasicDescription at Apple.
986 static int mov_get_lpcm_flags(enum AVCodecID codec_id
)
989 case AV_CODEC_ID_PCM_F32BE
:
990 case AV_CODEC_ID_PCM_F64BE
:
992 case AV_CODEC_ID_PCM_F32LE
:
993 case AV_CODEC_ID_PCM_F64LE
:
995 case AV_CODEC_ID_PCM_U8
:
997 case AV_CODEC_ID_PCM_S16BE
:
998 case AV_CODEC_ID_PCM_S24BE
:
999 case AV_CODEC_ID_PCM_S32BE
:
1001 case AV_CODEC_ID_PCM_S8
:
1002 case AV_CODEC_ID_PCM_S16LE
:
1003 case AV_CODEC_ID_PCM_S24LE
:
1004 case AV_CODEC_ID_PCM_S32LE
:
1011 static int get_cluster_duration(MOVTrack
*track
, int cluster_idx
)
1015 if (cluster_idx
>= track
->entry
)
1018 if (cluster_idx
+ 1 == track
->entry
)
1019 next_dts
= track
->track_duration
+ track
->start_dts
;
1021 next_dts
= track
->cluster
[cluster_idx
+ 1].dts
;
1023 next_dts
-= track
->cluster
[cluster_idx
].dts
;
1025 av_assert0(next_dts
>= 0);
1026 av_assert0(next_dts
<= INT_MAX
);
1031 static int get_samples_per_packet(MOVTrack
*track
)
1033 int i
, first_duration
;
1035 // return track->par->frame_size;
1037 /* use 1 for raw PCM */
1038 if (!track
->audio_vbr
)
1041 /* check to see if duration is constant for all clusters */
1044 first_duration
= get_cluster_duration(track
, 0);
1045 for (i
= 1; i
< track
->entry
; i
++) {
1046 if (get_cluster_duration(track
, i
) != first_duration
)
1049 return first_duration
;
1052 static int mov_write_audio_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVMuxContext
*mov
, MOVTrack
*track
)
1054 int64_t pos
= avio_tell(pb
);
1056 uint32_t tag
= track
->tag
;
1059 if (track
->mode
== MODE_MOV
) {
1060 if (track
->timescale
> UINT16_MAX
|| !track
->par
->channels
) {
1061 if (mov_get_lpcm_flags(track
->par
->codec_id
))
1062 tag
= AV_RL32("lpcm");
1064 } else if (track
->audio_vbr
|| mov_pcm_le_gt16(track
->par
->codec_id
) ||
1065 mov_pcm_be_gt16(track
->par
->codec_id
) ||
1066 track
->par
->codec_id
== AV_CODEC_ID_ADPCM_MS
||
1067 track
->par
->codec_id
== AV_CODEC_ID_ADPCM_IMA_WAV
||
1068 track
->par
->codec_id
== AV_CODEC_ID_QDM2
) {
1073 avio_wb32(pb
, 0); /* size */
1074 if (mov
->encryption_scheme
!= MOV_ENC_NONE
) {
1075 ffio_wfourcc(pb
, "enca");
1077 avio_wl32(pb
, tag
); // store it byteswapped
1079 avio_wb32(pb
, 0); /* Reserved */
1080 avio_wb16(pb
, 0); /* Reserved */
1081 avio_wb16(pb
, 1); /* Data-reference index, XXX == 1 */
1083 /* SoundDescription */
1084 avio_wb16(pb
, version
); /* Version */
1085 avio_wb16(pb
, 0); /* Revision level */
1086 avio_wb32(pb
, 0); /* Reserved */
1091 avio_wb16(pb
, 0xfffe);
1093 avio_wb32(pb
, 0x00010000);
1095 avio_wb64(pb
, av_double2int(track
->par
->sample_rate
));
1096 avio_wb32(pb
, track
->par
->channels
);
1097 avio_wb32(pb
, 0x7F000000);
1098 avio_wb32(pb
, av_get_bits_per_sample(track
->par
->codec_id
));
1099 avio_wb32(pb
, mov_get_lpcm_flags(track
->par
->codec_id
));
1100 avio_wb32(pb
, track
->sample_size
);
1101 avio_wb32(pb
, get_samples_per_packet(track
));
1103 if (track
->mode
== MODE_MOV
) {
1104 avio_wb16(pb
, track
->par
->channels
);
1105 if (track
->par
->codec_id
== AV_CODEC_ID_PCM_U8
||
1106 track
->par
->codec_id
== AV_CODEC_ID_PCM_S8
)
1107 avio_wb16(pb
, 8); /* bits per sample */
1108 else if (track
->par
->codec_id
== AV_CODEC_ID_ADPCM_G726
)
1109 avio_wb16(pb
, track
->par
->bits_per_coded_sample
);
1112 avio_wb16(pb
, track
->audio_vbr
? -2 : 0); /* compression ID */
1113 } else { /* reserved for mp4/3gp */
1114 if (track
->par
->codec_id
== AV_CODEC_ID_FLAC
||
1115 track
->par
->codec_id
== AV_CODEC_ID_ALAC
||
1116 track
->par
->codec_id
== AV_CODEC_ID_OPUS
) {
1117 avio_wb16(pb
, track
->par
->channels
);
1121 if (track
->par
->codec_id
== AV_CODEC_ID_FLAC
||
1122 track
->par
->codec_id
== AV_CODEC_ID_ALAC
) {
1123 avio_wb16(pb
, track
->par
->bits_per_raw_sample
);
1130 avio_wb16(pb
, 0); /* packet size (= 0) */
1131 if (track
->par
->codec_id
== AV_CODEC_ID_OPUS
)
1132 avio_wb16(pb
, 48000);
1133 else if (track
->par
->codec_id
== AV_CODEC_ID_TRUEHD
)
1134 avio_wb32(pb
, track
->par
->sample_rate
);
1136 avio_wb16(pb
, track
->par
->sample_rate
<= UINT16_MAX
?
1137 track
->par
->sample_rate
: 0);
1139 if (track
->par
->codec_id
!= AV_CODEC_ID_TRUEHD
)
1140 avio_wb16(pb
, 0); /* Reserved */
1143 if (version
== 1) { /* SoundDescription V1 extended info */
1144 if (mov_pcm_le_gt16(track
->par
->codec_id
) ||
1145 mov_pcm_be_gt16(track
->par
->codec_id
))
1146 avio_wb32(pb
, 1); /* must be 1 for uncompressed formats */
1148 avio_wb32(pb
, track
->par
->frame_size
); /* Samples per packet */
1149 avio_wb32(pb
, track
->sample_size
/ track
->par
->channels
); /* Bytes per packet */
1150 avio_wb32(pb
, track
->sample_size
); /* Bytes per frame */
1151 avio_wb32(pb
, 2); /* Bytes per sample */
1154 if (track
->mode
== MODE_MOV
&&
1155 (track
->par
->codec_id
== AV_CODEC_ID_AAC
||
1156 track
->par
->codec_id
== AV_CODEC_ID_AC3
||
1157 track
->par
->codec_id
== AV_CODEC_ID_EAC3
||
1158 track
->par
->codec_id
== AV_CODEC_ID_AMR_NB
||
1159 track
->par
->codec_id
== AV_CODEC_ID_ALAC
||
1160 track
->par
->codec_id
== AV_CODEC_ID_ADPCM_MS
||
1161 track
->par
->codec_id
== AV_CODEC_ID_ADPCM_IMA_WAV
||
1162 track
->par
->codec_id
== AV_CODEC_ID_QDM2
||
1163 (mov_pcm_le_gt16(track
->par
->codec_id
) && version
==1) ||
1164 (mov_pcm_be_gt16(track
->par
->codec_id
) && version
==1)))
1165 ret
= mov_write_wave_tag(s
, pb
, track
);
1166 else if (track
->tag
== MKTAG('m','p','4','a'))
1167 ret
= mov_write_esds_tag(pb
, track
);
1168 else if (track
->par
->codec_id
== AV_CODEC_ID_AMR_NB
)
1169 ret
= mov_write_amr_tag(pb
, track
);
1170 else if (track
->par
->codec_id
== AV_CODEC_ID_AC3
)
1171 ret
= mov_write_ac3_tag(s
, pb
, track
);
1172 else if (track
->par
->codec_id
== AV_CODEC_ID_EAC3
)
1173 ret
= mov_write_eac3_tag(s
, pb
, track
);
1174 else if (track
->par
->codec_id
== AV_CODEC_ID_ALAC
)
1175 ret
= mov_write_extradata_tag(pb
, track
);
1176 else if (track
->par
->codec_id
== AV_CODEC_ID_WMAPRO
)
1177 ret
= mov_write_wfex_tag(s
, pb
, track
);
1178 else if (track
->par
->codec_id
== AV_CODEC_ID_FLAC
)
1179 ret
= mov_write_dfla_tag(pb
, track
);
1180 else if (track
->par
->codec_id
== AV_CODEC_ID_OPUS
)
1181 ret
= mov_write_dops_tag(s
, pb
, track
);
1182 else if (track
->par
->codec_id
== AV_CODEC_ID_TRUEHD
)
1183 ret
= mov_write_dmlp_tag(s
, pb
, track
);
1184 else if (track
->vos_len
> 0)
1185 ret
= mov_write_glbl_tag(pb
, track
);
1190 if (track
->mode
== MODE_MOV
&& track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
1191 && ((ret
= mov_write_chan_tag(s
, pb
, track
)) < 0)) {
1195 if (mov
->encryption_scheme
!= MOV_ENC_NONE
1196 && ((ret
= ff_mov_cenc_write_sinf_tag(track
, pb
, mov
->encryption_kid
)) < 0)) {
1200 ret
= update_size(pb
, pos
);
1204 static int mov_write_d263_tag(AVIOContext
*pb
)
1206 avio_wb32(pb
, 0xf); /* size */
1207 ffio_wfourcc(pb
, "d263");
1208 ffio_wfourcc(pb
, "FFMP");
1209 avio_w8(pb
, 0); /* decoder version */
1210 /* FIXME use AVCodecContext level/profile, when encoder will set values */
1211 avio_w8(pb
, 0xa); /* level */
1212 avio_w8(pb
, 0); /* profile */
1216 static int mov_write_av1c_tag(AVIOContext
*pb
, MOVTrack
*track
)
1218 int64_t pos
= avio_tell(pb
);
1221 ffio_wfourcc(pb
, "av1C");
1222 ff_isom_write_av1c(pb
, track
->vos_data
, track
->vos_len
);
1223 return update_size(pb
, pos
);
1226 static int mov_write_avcc_tag(AVIOContext
*pb
, MOVTrack
*track
)
1228 int64_t pos
= avio_tell(pb
);
1231 ffio_wfourcc(pb
, "avcC");
1232 ff_isom_write_avcc(pb
, track
->vos_data
, track
->vos_len
);
1233 return update_size(pb
, pos
);
1236 static int mov_write_vpcc_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
1238 int64_t pos
= avio_tell(pb
);
1241 ffio_wfourcc(pb
, "vpcC");
1242 avio_w8(pb
, 1); /* version */
1243 avio_wb24(pb
, 0); /* flags */
1244 ff_isom_write_vpcc(s
, pb
, track
->par
);
1245 return update_size(pb
, pos
);
1248 static int mov_write_hvcc_tag(AVIOContext
*pb
, MOVTrack
*track
)
1250 int64_t pos
= avio_tell(pb
);
1253 ffio_wfourcc(pb
, "hvcC");
1254 if (track
->tag
== MKTAG('h','v','c','1'))
1255 ff_isom_write_hvcc(pb
, track
->vos_data
, track
->vos_len
, 1);
1257 ff_isom_write_hvcc(pb
, track
->vos_data
, track
->vos_len
, 0);
1258 return update_size(pb
, pos
);
1261 /* also used by all avid codecs (dv, imx, meridien) and their variants */
1262 static int mov_write_avid_tag(AVIOContext
*pb
, MOVTrack
*track
)
1267 int display_width
= track
->par
->width
;
1269 if (track
->vos_data
&& track
->vos_len
> 0x29) {
1270 if (ff_dnxhd_parse_header_prefix(track
->vos_data
) != 0) {
1271 /* looks like a DNxHD bit stream */
1272 interlaced
= (track
->vos_data
[5] & 2);
1273 cid
= AV_RB32(track
->vos_data
+ 0x28);
1275 av_log(NULL
, AV_LOG_WARNING
, "Could not locate DNxHD bit stream in vos_data\n");
1279 av_log(NULL
, AV_LOG_WARNING
, "Could not locate DNxHD bit stream, vos_data too small\n");
1283 avio_wb32(pb
, 24); /* size */
1284 ffio_wfourcc(pb
, "ACLR");
1285 ffio_wfourcc(pb
, "ACLR");
1286 ffio_wfourcc(pb
, "0001");
1287 if (track
->par
->color_range
== AVCOL_RANGE_MPEG
|| /* Legal range (16-235) */
1288 track
->par
->color_range
== AVCOL_RANGE_UNSPECIFIED
) {
1289 avio_wb32(pb
, 1); /* Corresponds to 709 in official encoder */
1290 } else { /* Full range (0-255) */
1291 avio_wb32(pb
, 2); /* Corresponds to RGB in official encoder */
1293 avio_wb32(pb
, 0); /* unknown */
1295 if (track
->tag
== MKTAG('A','V','d','h')) {
1297 ffio_wfourcc(pb
, "ADHR");
1298 ffio_wfourcc(pb
, "0001");
1300 avio_wb32(pb
, 0); /* unknown */
1301 avio_wb32(pb
, 1); /* unknown */
1302 avio_wb32(pb
, 0); /* unknown */
1303 avio_wb32(pb
, 0); /* unknown */
1307 avio_wb32(pb
, 24); /* size */
1308 ffio_wfourcc(pb
, "APRG");
1309 ffio_wfourcc(pb
, "APRG");
1310 ffio_wfourcc(pb
, "0001");
1311 avio_wb32(pb
, 1); /* unknown */
1312 avio_wb32(pb
, 0); /* unknown */
1314 avio_wb32(pb
, 120); /* size */
1315 ffio_wfourcc(pb
, "ARES");
1316 ffio_wfourcc(pb
, "ARES");
1317 ffio_wfourcc(pb
, "0001");
1318 avio_wb32(pb
, cid
); /* dnxhd cid, some id ? */
1319 if ( track
->par
->sample_aspect_ratio
.num
> 0
1320 && track
->par
->sample_aspect_ratio
.den
> 0)
1321 display_width
= display_width
* track
->par
->sample_aspect_ratio
.num
/ track
->par
->sample_aspect_ratio
.den
;
1322 avio_wb32(pb
, display_width
);
1323 /* values below are based on samples created with quicktime and avid codecs */
1325 avio_wb32(pb
, track
->par
->height
/ 2);
1326 avio_wb32(pb
, 2); /* unknown */
1327 avio_wb32(pb
, 0); /* unknown */
1328 avio_wb32(pb
, 4); /* unknown */
1330 avio_wb32(pb
, track
->par
->height
);
1331 avio_wb32(pb
, 1); /* unknown */
1332 avio_wb32(pb
, 0); /* unknown */
1333 if (track
->par
->height
== 1080)
1334 avio_wb32(pb
, 5); /* unknown */
1336 avio_wb32(pb
, 6); /* unknown */
1339 for (i
= 0; i
< 10; i
++)
1345 static int mov_write_dpxe_tag(AVIOContext
*pb
, MOVTrack
*track
)
1348 ffio_wfourcc(pb
, "DpxE");
1349 if (track
->par
->extradata_size
>= 12 &&
1350 !memcmp(&track
->par
->extradata
[4], "DpxE", 4)) {
1351 avio_wb32(pb
, track
->par
->extradata
[11]);
1358 static int mov_get_dv_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
1362 if (track
->par
->width
== 720) { /* SD */
1363 if (track
->par
->height
== 480) { /* NTSC */
1364 if (track
->par
->format
== AV_PIX_FMT_YUV422P
) tag
= MKTAG('d','v','5','n');
1365 else tag
= MKTAG('d','v','c',' ');
1366 }else if (track
->par
->format
== AV_PIX_FMT_YUV422P
) tag
= MKTAG('d','v','5','p');
1367 else if (track
->par
->format
== AV_PIX_FMT_YUV420P
) tag
= MKTAG('d','v','c','p');
1368 else tag
= MKTAG('d','v','p','p');
1369 } else if (track
->par
->height
== 720) { /* HD 720 line */
1370 if (track
->st
->time_base
.den
== 50) tag
= MKTAG('d','v','h','q');
1371 else tag
= MKTAG('d','v','h','p');
1372 } else if (track
->par
->height
== 1080) { /* HD 1080 line */
1373 if (track
->st
->time_base
.den
== 25) tag
= MKTAG('d','v','h','5');
1374 else tag
= MKTAG('d','v','h','6');
1376 av_log(s
, AV_LOG_ERROR
, "unsupported height for dv codec\n");
1383 static AVRational
find_fps(AVFormatContext
*s
, AVStream
*st
)
1385 AVRational rate
= st
->avg_frame_rate
;
1387 #if FF_API_LAVF_AVCTX
1388 FF_DISABLE_DEPRECATION_WARNINGS
1389 rate
= av_inv_q(st
->codec
->time_base
);
1390 if (av_timecode_check_frame_rate(rate
) < 0) {
1391 av_log(s
, AV_LOG_DEBUG
, "timecode: tbc=%d/%d invalid, fallback on %d/%d\n",
1392 rate
.num
, rate
.den
, st
->avg_frame_rate
.num
, st
->avg_frame_rate
.den
);
1393 rate
= st
->avg_frame_rate
;
1395 FF_ENABLE_DEPRECATION_WARNINGS
1401 static int defined_frame_rate(AVFormatContext
*s
, AVStream
*st
)
1403 AVRational rational_framerate
= find_fps(s
, st
);
1405 if (rational_framerate
.den
!= 0)
1406 rate
= av_q2d(rational_framerate
);
1410 static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
1412 int tag
= track
->par
->codec_tag
;
1413 int interlaced
= track
->par
->field_order
> AV_FIELD_PROGRESSIVE
;
1414 AVStream
*st
= track
->st
;
1415 int rate
= defined_frame_rate(s
, st
);
1418 tag
= MKTAG('m', '2', 'v', '1'); //fallback tag
1420 if (track
->par
->format
== AV_PIX_FMT_YUV420P
) {
1421 if (track
->par
->width
== 1280 && track
->par
->height
== 720) {
1423 if (rate
== 24) tag
= MKTAG('x','d','v','4');
1424 else if (rate
== 25) tag
= MKTAG('x','d','v','5');
1425 else if (rate
== 30) tag
= MKTAG('x','d','v','1');
1426 else if (rate
== 50) tag
= MKTAG('x','d','v','a');
1427 else if (rate
== 60) tag
= MKTAG('x','d','v','9');
1429 } else if (track
->par
->width
== 1440 && track
->par
->height
== 1080) {
1431 if (rate
== 24) tag
= MKTAG('x','d','v','6');
1432 else if (rate
== 25) tag
= MKTAG('x','d','v','7');
1433 else if (rate
== 30) tag
= MKTAG('x','d','v','8');
1435 if (rate
== 25) tag
= MKTAG('x','d','v','3');
1436 else if (rate
== 30) tag
= MKTAG('x','d','v','2');
1438 } else if (track
->par
->width
== 1920 && track
->par
->height
== 1080) {
1440 if (rate
== 24) tag
= MKTAG('x','d','v','d');
1441 else if (rate
== 25) tag
= MKTAG('x','d','v','e');
1442 else if (rate
== 30) tag
= MKTAG('x','d','v','f');
1444 if (rate
== 25) tag
= MKTAG('x','d','v','c');
1445 else if (rate
== 30) tag
= MKTAG('x','d','v','b');
1448 } else if (track
->par
->format
== AV_PIX_FMT_YUV422P
) {
1449 if (track
->par
->width
== 1280 && track
->par
->height
== 720) {
1451 if (rate
== 24) tag
= MKTAG('x','d','5','4');
1452 else if (rate
== 25) tag
= MKTAG('x','d','5','5');
1453 else if (rate
== 30) tag
= MKTAG('x','d','5','1');
1454 else if (rate
== 50) tag
= MKTAG('x','d','5','a');
1455 else if (rate
== 60) tag
= MKTAG('x','d','5','9');
1457 } else if (track
->par
->width
== 1920 && track
->par
->height
== 1080) {
1459 if (rate
== 24) tag
= MKTAG('x','d','5','d');
1460 else if (rate
== 25) tag
= MKTAG('x','d','5','e');
1461 else if (rate
== 30) tag
= MKTAG('x','d','5','f');
1463 if (rate
== 25) tag
= MKTAG('x','d','5','c');
1464 else if (rate
== 30) tag
= MKTAG('x','d','5','b');
1472 static int mov_get_h264_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
1474 int tag
= track
->par
->codec_tag
;
1475 int interlaced
= track
->par
->field_order
> AV_FIELD_PROGRESSIVE
;
1476 AVStream
*st
= track
->st
;
1477 int rate
= defined_frame_rate(s
, st
);
1480 tag
= MKTAG('a', 'v', 'c', 'i'); //fallback tag
1482 if (track
->par
->format
== AV_PIX_FMT_YUV420P10
) {
1483 if (track
->par
->width
== 960 && track
->par
->height
== 720) {
1485 if (rate
== 24) tag
= MKTAG('a','i','5','p');
1486 else if (rate
== 25) tag
= MKTAG('a','i','5','q');
1487 else if (rate
== 30) tag
= MKTAG('a','i','5','p');
1488 else if (rate
== 50) tag
= MKTAG('a','i','5','q');
1489 else if (rate
== 60) tag
= MKTAG('a','i','5','p');
1491 } else if (track
->par
->width
== 1440 && track
->par
->height
== 1080) {
1493 if (rate
== 24) tag
= MKTAG('a','i','5','3');
1494 else if (rate
== 25) tag
= MKTAG('a','i','5','2');
1495 else if (rate
== 30) tag
= MKTAG('a','i','5','3');
1497 if (rate
== 50) tag
= MKTAG('a','i','5','5');
1498 else if (rate
== 60) tag
= MKTAG('a','i','5','6');
1501 } else if (track
->par
->format
== AV_PIX_FMT_YUV422P10
) {
1502 if (track
->par
->width
== 1280 && track
->par
->height
== 720) {
1504 if (rate
== 24) tag
= MKTAG('a','i','1','p');
1505 else if (rate
== 25) tag
= MKTAG('a','i','1','q');
1506 else if (rate
== 30) tag
= MKTAG('a','i','1','p');
1507 else if (rate
== 50) tag
= MKTAG('a','i','1','q');
1508 else if (rate
== 60) tag
= MKTAG('a','i','1','p');
1510 } else if (track
->par
->width
== 1920 && track
->par
->height
== 1080) {
1512 if (rate
== 24) tag
= MKTAG('a','i','1','3');
1513 else if (rate
== 25) tag
= MKTAG('a','i','1','2');
1514 else if (rate
== 30) tag
= MKTAG('a','i','1','3');
1516 if (rate
== 25) tag
= MKTAG('a','i','1','5');
1517 else if (rate
== 50) tag
= MKTAG('a','i','1','5');
1518 else if (rate
== 60) tag
= MKTAG('a','i','1','6');
1520 } else if ( track
->par
->width
== 4096 && track
->par
->height
== 2160
1521 || track
->par
->width
== 3840 && track
->par
->height
== 2160
1522 || track
->par
->width
== 2048 && track
->par
->height
== 1080) {
1523 tag
= MKTAG('a','i','v','x');
1530 static const struct {
1531 enum AVPixelFormat pix_fmt
;
1534 } mov_pix_fmt_tags
[] = {
1535 { AV_PIX_FMT_YUYV422
, MKTAG('y','u','v','2'), 0 },
1536 { AV_PIX_FMT_YUYV422
, MKTAG('y','u','v','s'), 0 },
1537 { AV_PIX_FMT_UYVY422
, MKTAG('2','v','u','y'), 0 },
1538 { AV_PIX_FMT_RGB555BE
,MKTAG('r','a','w',' '), 16 },
1539 { AV_PIX_FMT_RGB555LE
,MKTAG('L','5','5','5'), 16 },
1540 { AV_PIX_FMT_RGB565LE
,MKTAG('L','5','6','5'), 16 },
1541 { AV_PIX_FMT_RGB565BE
,MKTAG('B','5','6','5'), 16 },
1542 { AV_PIX_FMT_GRAY16BE
,MKTAG('b','1','6','g'), 16 },
1543 { AV_PIX_FMT_RGB24
, MKTAG('r','a','w',' '), 24 },
1544 { AV_PIX_FMT_BGR24
, MKTAG('2','4','B','G'), 24 },
1545 { AV_PIX_FMT_ARGB
, MKTAG('r','a','w',' '), 32 },
1546 { AV_PIX_FMT_BGRA
, MKTAG('B','G','R','A'), 32 },
1547 { AV_PIX_FMT_RGBA
, MKTAG('R','G','B','A'), 32 },
1548 { AV_PIX_FMT_ABGR
, MKTAG('A','B','G','R'), 32 },
1549 { AV_PIX_FMT_RGB48BE
, MKTAG('b','4','8','r'), 48 },
1552 static int mov_get_dnxhd_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
1554 int tag
= MKTAG('A','V','d','n');
1555 if (track
->par
->profile
!= FF_PROFILE_UNKNOWN
&&
1556 track
->par
->profile
!= FF_PROFILE_DNXHD
)
1557 tag
= MKTAG('A','V','d','h');
1561 static int mov_get_rawvideo_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
1563 int tag
= track
->par
->codec_tag
;
1565 enum AVPixelFormat pix_fmt
;
1567 for (i
= 0; i
< FF_ARRAY_ELEMS(mov_pix_fmt_tags
); i
++) {
1568 if (track
->par
->format
== mov_pix_fmt_tags
[i
].pix_fmt
) {
1569 tag
= mov_pix_fmt_tags
[i
].tag
;
1570 track
->par
->bits_per_coded_sample
= mov_pix_fmt_tags
[i
].bps
;
1571 if (track
->par
->codec_tag
== mov_pix_fmt_tags
[i
].tag
)
1576 pix_fmt
= avpriv_find_pix_fmt(avpriv_pix_fmt_bps_mov
,
1577 track
->par
->bits_per_coded_sample
);
1578 if (tag
== MKTAG('r','a','w',' ') &&
1579 track
->par
->format
!= pix_fmt
&&
1580 track
->par
->format
!= AV_PIX_FMT_GRAY8
&&
1581 track
->par
->format
!= AV_PIX_FMT_NONE
)
1582 av_log(s
, AV_LOG_ERROR
, "%s rawvideo cannot be written to mov, output file will be unreadable\n",
1583 av_get_pix_fmt_name(track
->par
->format
));
1587 static unsigned int mov_get_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
1589 unsigned int tag
= track
->par
->codec_tag
;
1591 // "rtp " is used to distinguish internally created RTP-hint tracks
1592 // (with rtp_ctx) from other tracks.
1593 if (tag
== MKTAG('r','t','p',' '))
1595 if (!tag
|| (s
->strict_std_compliance
>= FF_COMPLIANCE_NORMAL
&&
1596 (track
->par
->codec_id
== AV_CODEC_ID_DVVIDEO
||
1597 track
->par
->codec_id
== AV_CODEC_ID_RAWVIDEO
||
1598 track
->par
->codec_id
== AV_CODEC_ID_H263
||
1599 track
->par
->codec_id
== AV_CODEC_ID_H264
||
1600 track
->par
->codec_id
== AV_CODEC_ID_DNXHD
||
1601 track
->par
->codec_id
== AV_CODEC_ID_MPEG2VIDEO
||
1602 av_get_bits_per_sample(track
->par
->codec_id
)))) { // pcm audio
1603 if (track
->par
->codec_id
== AV_CODEC_ID_DVVIDEO
)
1604 tag
= mov_get_dv_codec_tag(s
, track
);
1605 else if (track
->par
->codec_id
== AV_CODEC_ID_RAWVIDEO
)
1606 tag
= mov_get_rawvideo_codec_tag(s
, track
);
1607 else if (track
->par
->codec_id
== AV_CODEC_ID_MPEG2VIDEO
)
1608 tag
= mov_get_mpeg2_xdcam_codec_tag(s
, track
);
1609 else if (track
->par
->codec_id
== AV_CODEC_ID_H264
)
1610 tag
= mov_get_h264_codec_tag(s
, track
);
1611 else if (track
->par
->codec_id
== AV_CODEC_ID_DNXHD
)
1612 tag
= mov_get_dnxhd_codec_tag(s
, track
);
1613 else if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
1614 tag
= ff_codec_get_tag(ff_codec_movvideo_tags
, track
->par
->codec_id
);
1615 if (!tag
) { // if no mac fcc found, try with Microsoft tags
1616 tag
= ff_codec_get_tag(ff_codec_bmp_tags
, track
->par
->codec_id
);
1618 av_log(s
, AV_LOG_WARNING
, "Using MS style video codec tag, "
1619 "the file may be unplayable!\n");
1621 } else if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
1622 tag
= ff_codec_get_tag(ff_codec_movaudio_tags
, track
->par
->codec_id
);
1623 if (!tag
) { // if no mac fcc found, try with Microsoft tags
1624 int ms_tag
= ff_codec_get_tag(ff_codec_wav_tags
, track
->par
->codec_id
);
1626 tag
= MKTAG('m', 's', ((ms_tag
>> 8) & 0xff), (ms_tag
& 0xff));
1627 av_log(s
, AV_LOG_WARNING
, "Using MS style audio codec tag, "
1628 "the file may be unplayable!\n");
1631 } else if (track
->par
->codec_type
== AVMEDIA_TYPE_SUBTITLE
)
1632 tag
= ff_codec_get_tag(ff_codec_movsubtitle_tags
, track
->par
->codec_id
);
1638 static const AVCodecTag codec_cover_image_tags
[] = {
1639 { AV_CODEC_ID_MJPEG
, 0xD },
1640 { AV_CODEC_ID_PNG
, 0xE },
1641 { AV_CODEC_ID_BMP
, 0x1B },
1642 { AV_CODEC_ID_NONE
, 0 },
1645 static unsigned int validate_codec_tag(const AVCodecTag
*const *tags
,
1646 unsigned int tag
, int codec_id
)
1651 * Check that tag + id is in the table
1653 for (i
= 0; tags
&& tags
[i
]; i
++) {
1654 const AVCodecTag
*codec_tags
= tags
[i
];
1655 while (codec_tags
->id
!= AV_CODEC_ID_NONE
) {
1656 if (avpriv_toupper4(codec_tags
->tag
) == avpriv_toupper4(tag
) &&
1657 codec_tags
->id
== codec_id
)
1658 return codec_tags
->tag
;
1665 static unsigned int mov_find_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
1667 if (is_cover_image(track
->st
))
1668 return ff_codec_get_tag(codec_cover_image_tags
, track
->par
->codec_id
);
1670 if (track
->mode
== MODE_IPOD
)
1671 if (!av_match_ext(s
->url
, "m4a") &&
1672 !av_match_ext(s
->url
, "m4v") &&
1673 !av_match_ext(s
->url
, "m4b"))
1674 av_log(s
, AV_LOG_WARNING
, "Warning, extension is not .m4a nor .m4v "
1675 "Quicktime/Ipod might not play the file\n");
1677 if (track
->mode
== MODE_MOV
) {
1678 return mov_get_codec_tag(s
, track
);
1680 return validate_codec_tag(s
->oformat
->codec_tag
, track
->par
->codec_tag
,
1681 track
->par
->codec_id
);
1684 /** Write uuid atom.
1685 * Needed to make file play in iPods running newest firmware
1686 * goes after avcC atom in moov.trak.mdia.minf.stbl.stsd.avc1
1688 static int mov_write_uuid_tag_ipod(AVIOContext
*pb
)
1691 ffio_wfourcc(pb
, "uuid");
1692 avio_wb32(pb
, 0x6b6840f2);
1693 avio_wb32(pb
, 0x5f244fc5);
1694 avio_wb32(pb
, 0xba39a51b);
1695 avio_wb32(pb
, 0xcf0323f3);
1700 static const uint16_t fiel_data
[] = {
1701 0x0000, 0x0100, 0x0201, 0x0206, 0x0209, 0x020e
1704 static int mov_write_fiel_tag(AVIOContext
*pb
, MOVTrack
*track
, int field_order
)
1706 unsigned mov_field_order
= 0;
1707 if (field_order
< FF_ARRAY_ELEMS(fiel_data
))
1708 mov_field_order
= fiel_data
[field_order
];
1712 ffio_wfourcc(pb
, "fiel");
1713 avio_wb16(pb
, mov_field_order
);
1717 static int mov_write_subtitle_tag(AVIOContext
*pb
, MOVTrack
*track
)
1719 int64_t pos
= avio_tell(pb
);
1720 avio_wb32(pb
, 0); /* size */
1721 avio_wl32(pb
, track
->tag
); // store it byteswapped
1722 avio_wb32(pb
, 0); /* Reserved */
1723 avio_wb16(pb
, 0); /* Reserved */
1724 avio_wb16(pb
, 1); /* Data-reference index */
1726 if (track
->par
->codec_id
== AV_CODEC_ID_DVD_SUBTITLE
)
1727 mov_write_esds_tag(pb
, track
);
1728 else if (track
->par
->extradata_size
)
1729 avio_write(pb
, track
->par
->extradata
, track
->par
->extradata_size
);
1731 return update_size(pb
, pos
);
1734 static int mov_write_st3d_tag(AVFormatContext
*s
, AVIOContext
*pb
, AVStereo3D
*stereo_3d
)
1738 if (stereo_3d
->flags
!= 0) {
1739 av_log(s
, AV_LOG_WARNING
, "Unsupported stereo_3d flags %x. st3d not written.\n", stereo_3d
->flags
);
1743 switch (stereo_3d
->type
) {
1744 case AV_STEREO3D_2D
:
1747 case AV_STEREO3D_TOPBOTTOM
:
1750 case AV_STEREO3D_SIDEBYSIDE
:
1754 av_log(s
, AV_LOG_WARNING
, "Unsupported stereo_3d type %s. st3d not written.\n", av_stereo3d_type_name(stereo_3d
->type
));
1757 avio_wb32(pb
, 13); /* size */
1758 ffio_wfourcc(pb
, "st3d");
1759 avio_wb32(pb
, 0); /* version = 0 & flags = 0 */
1760 avio_w8(pb
, stereo_mode
);
1764 static int mov_write_sv3d_tag(AVFormatContext
*s
, AVIOContext
*pb
, AVSphericalMapping
*spherical_mapping
)
1766 int64_t sv3d_pos
, svhd_pos
, proj_pos
;
1767 const char* metadata_source
= s
->flags
& AVFMT_FLAG_BITEXACT
? "Lavf" : LIBAVFORMAT_IDENT
;
1769 if (spherical_mapping
->projection
!= AV_SPHERICAL_EQUIRECTANGULAR
&&
1770 spherical_mapping
->projection
!= AV_SPHERICAL_EQUIRECTANGULAR_TILE
&&
1771 spherical_mapping
->projection
!= AV_SPHERICAL_CUBEMAP
) {
1772 av_log(s
, AV_LOG_WARNING
, "Unsupported projection %d. sv3d not written.\n", spherical_mapping
->projection
);
1776 sv3d_pos
= avio_tell(pb
);
1777 avio_wb32(pb
, 0); /* size */
1778 ffio_wfourcc(pb
, "sv3d");
1780 svhd_pos
= avio_tell(pb
);
1781 avio_wb32(pb
, 0); /* size */
1782 ffio_wfourcc(pb
, "svhd");
1783 avio_wb32(pb
, 0); /* version = 0 & flags = 0 */
1784 avio_put_str(pb
, metadata_source
);
1785 update_size(pb
, svhd_pos
);
1787 proj_pos
= avio_tell(pb
);
1788 avio_wb32(pb
, 0); /* size */
1789 ffio_wfourcc(pb
, "proj");
1791 avio_wb32(pb
, 24); /* size */
1792 ffio_wfourcc(pb
, "prhd");
1793 avio_wb32(pb
, 0); /* version = 0 & flags = 0 */
1794 avio_wb32(pb
, spherical_mapping
->yaw
);
1795 avio_wb32(pb
, spherical_mapping
->pitch
);
1796 avio_wb32(pb
, spherical_mapping
->roll
);
1798 switch (spherical_mapping
->projection
) {
1799 case AV_SPHERICAL_EQUIRECTANGULAR
:
1800 case AV_SPHERICAL_EQUIRECTANGULAR_TILE
:
1801 avio_wb32(pb
, 28); /* size */
1802 ffio_wfourcc(pb
, "equi");
1803 avio_wb32(pb
, 0); /* version = 0 & flags = 0 */
1804 avio_wb32(pb
, spherical_mapping
->bound_top
);
1805 avio_wb32(pb
, spherical_mapping
->bound_bottom
);
1806 avio_wb32(pb
, spherical_mapping
->bound_left
);
1807 avio_wb32(pb
, spherical_mapping
->bound_right
);
1809 case AV_SPHERICAL_CUBEMAP
:
1810 avio_wb32(pb
, 20); /* size */
1811 ffio_wfourcc(pb
, "cbmp");
1812 avio_wb32(pb
, 0); /* version = 0 & flags = 0 */
1813 avio_wb32(pb
, 0); /* layout */
1814 avio_wb32(pb
, spherical_mapping
->padding
); /* padding */
1817 update_size(pb
, proj_pos
);
1819 return update_size(pb
, sv3d_pos
);
1822 static int mov_write_dvcc_dvvc_tag(AVFormatContext
*s
, AVIOContext
*pb
, AVDOVIDecoderConfigurationRecord
*dovi
)
1824 avio_wb32(pb
, 32); /* size = 8 + 24 */
1825 if (dovi
->dv_profile
> 7)
1826 ffio_wfourcc(pb
, "dvvC");
1828 ffio_wfourcc(pb
, "dvcC");
1829 avio_w8(pb
, dovi
->dv_version_major
);
1830 avio_w8(pb
, dovi
->dv_version_minor
);
1831 avio_wb16(pb
, (dovi
->dv_profile
<< 9) | (dovi
->dv_level
<< 3) |
1832 (dovi
->rpu_present_flag
<< 2) | (dovi
->el_present_flag
<< 1) |
1833 dovi
->bl_present_flag
);
1834 avio_wb32(pb
, (dovi
->dv_bl_signal_compatibility_id
<< 28) | 0);
1836 avio_wb32(pb
, 0); /* reserved */
1837 avio_wb32(pb
, 0); /* reserved */
1838 avio_wb32(pb
, 0); /* reserved */
1839 avio_wb32(pb
, 0); /* reserved */
1840 av_log(s
, AV_LOG_DEBUG
, "DOVI in %s box, version: %d.%d, profile: %d, level: %d, "
1841 "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n",
1842 dovi
->dv_profile
> 7 ? "dvvC" : "dvcC",
1843 dovi
->dv_version_major
, dovi
->dv_version_minor
,
1844 dovi
->dv_profile
, dovi
->dv_level
,
1845 dovi
->rpu_present_flag
,
1846 dovi
->el_present_flag
,
1847 dovi
->bl_present_flag
,
1848 dovi
->dv_bl_signal_compatibility_id
);
1849 return 32; /* 8 + 24 */
1852 static int mov_write_clap_tag(AVIOContext
*pb
, MOVTrack
*track
)
1855 ffio_wfourcc(pb
, "clap");
1856 avio_wb32(pb
, track
->par
->width
); /* apertureWidth_N */
1857 avio_wb32(pb
, 1); /* apertureWidth_D (= 1) */
1858 avio_wb32(pb
, track
->height
); /* apertureHeight_N */
1859 avio_wb32(pb
, 1); /* apertureHeight_D (= 1) */
1860 avio_wb32(pb
, 0); /* horizOff_N (= 0) */
1861 avio_wb32(pb
, 1); /* horizOff_D (= 1) */
1862 avio_wb32(pb
, 0); /* vertOff_N (= 0) */
1863 avio_wb32(pb
, 1); /* vertOff_D (= 1) */
1867 static int mov_write_pasp_tag(AVIOContext
*pb
, MOVTrack
*track
)
1870 av_reduce(&sar
.num
, &sar
.den
, track
->par
->sample_aspect_ratio
.num
,
1871 track
->par
->sample_aspect_ratio
.den
, INT_MAX
);
1874 ffio_wfourcc(pb
, "pasp");
1875 avio_wb32(pb
, sar
.num
);
1876 avio_wb32(pb
, sar
.den
);
1880 static int mov_write_gama_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
, double gamma
)
1884 gamma
= avpriv_get_gamma_from_trc(track
->par
->color_trc
);
1886 av_log(s
, AV_LOG_DEBUG
, "gamma value %g\n", gamma
);
1889 gama
= (uint32_t)lrint((double)(1<<16) * gamma
);
1890 av_log(s
, AV_LOG_DEBUG
, "writing gama value %"PRId32
"\n", gama
);
1892 av_assert0(track
->mode
== MODE_MOV
);
1894 ffio_wfourcc(pb
, "gama");
1895 avio_wb32(pb
, gama
);
1898 av_log(s
, AV_LOG_WARNING
, "gamma value unknown, unable to write gama atom\n");
1903 static int mov_write_colr_tag(AVIOContext
*pb
, MOVTrack
*track
, int prefer_icc
)
1905 int64_t pos
= avio_tell(pb
);
1907 // Ref (MOV): https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9
1908 // Ref (MP4): ISO/IEC 14496-12:2012
1910 const uint8_t *icc_profile
;
1911 int icc_profile_size
;
1914 icc_profile
= av_stream_get_side_data(track
->st
, AV_PKT_DATA_ICC_PROFILE
, &icc_profile_size
);
1917 avio_wb32(pb
, 12 + icc_profile_size
);
1918 ffio_wfourcc(pb
, "colr");
1919 ffio_wfourcc(pb
, "prof");
1920 avio_write(pb
, icc_profile
, icc_profile_size
);
1921 return 12 + icc_profile_size
;
1924 av_log(NULL
, AV_LOG_INFO
, "no ICC profile found, will write nclx/nclc colour info instead\n");
1928 /* We should only ever be called by MOV or MP4. */
1929 av_assert0(track
->mode
== MODE_MOV
|| track
->mode
== MODE_MP4
);
1931 avio_wb32(pb
, 0); /* size */
1932 ffio_wfourcc(pb
, "colr");
1933 if (track
->mode
== MODE_MP4
)
1934 ffio_wfourcc(pb
, "nclx");
1936 ffio_wfourcc(pb
, "nclc");
1937 // Do not try to guess the color info if it is AVCOL_PRI_UNSPECIFIED.
1938 // e.g., Dolby Vision for Apple devices should be set to AVCOL_PRI_UNSPECIFIED. See
1939 // https://developer.apple.com/av-foundation/High-Dynamic-Range-Metadata-for-Apple-Devices.pdf
1940 avio_wb16(pb
, track
->par
->color_primaries
);
1941 avio_wb16(pb
, track
->par
->color_trc
);
1942 avio_wb16(pb
, track
->par
->color_space
);
1943 if (track
->mode
== MODE_MP4
) {
1944 int full_range
= track
->par
->color_range
== AVCOL_RANGE_JPEG
;
1945 avio_w8(pb
, full_range
<< 7);
1948 return update_size(pb
, pos
);
1951 static int mov_write_clli_tag(AVIOContext
*pb
, MOVTrack
*track
)
1953 const uint8_t *side_data
;
1954 const AVContentLightMetadata
*content_light_metadata
;
1956 side_data
= av_stream_get_side_data(track
->st
, AV_PKT_DATA_CONTENT_LIGHT_LEVEL
, NULL
);
1958 av_log(NULL
, AV_LOG_VERBOSE
, "Not writing 'clli' atom. No content light level info.\n");
1961 content_light_metadata
= (const AVContentLightMetadata
*)side_data
;
1963 avio_wb32(pb
, 12); // size
1964 ffio_wfourcc(pb
, "clli");
1965 avio_wb16(pb
, content_light_metadata
->MaxCLL
);
1966 avio_wb16(pb
, content_light_metadata
->MaxFALL
);
1970 static inline int64_t rescale_mdcv(AVRational q
, int b
)
1972 return av_rescale(q
.num
, b
, q
.den
);
1975 static int mov_write_mdcv_tag(AVIOContext
*pb
, MOVTrack
*track
)
1977 const int chroma_den
= 50000;
1978 const int luma_den
= 10000;
1979 const uint8_t *side_data
;
1980 const AVMasteringDisplayMetadata
*metadata
;
1982 side_data
= av_stream_get_side_data(track
->st
, AV_PKT_DATA_MASTERING_DISPLAY_METADATA
, NULL
);
1983 metadata
= (const AVMasteringDisplayMetadata
*)side_data
;
1984 if (!metadata
|| !metadata
->has_primaries
|| !metadata
->has_luminance
) {
1985 av_log(NULL
, AV_LOG_VERBOSE
, "Not writing 'mdcv' atom. Missing mastering metadata.\n");
1989 avio_wb32(pb
, 32); // size
1990 ffio_wfourcc(pb
, "mdcv");
1991 avio_wb16(pb
, rescale_mdcv(metadata
->display_primaries
[1][0], chroma_den
));
1992 avio_wb16(pb
, rescale_mdcv(metadata
->display_primaries
[1][1], chroma_den
));
1993 avio_wb16(pb
, rescale_mdcv(metadata
->display_primaries
[2][0], chroma_den
));
1994 avio_wb16(pb
, rescale_mdcv(metadata
->display_primaries
[2][1], chroma_den
));
1995 avio_wb16(pb
, rescale_mdcv(metadata
->display_primaries
[0][0], chroma_den
));
1996 avio_wb16(pb
, rescale_mdcv(metadata
->display_primaries
[0][1], chroma_den
));
1997 avio_wb16(pb
, rescale_mdcv(metadata
->white_point
[0], chroma_den
));
1998 avio_wb16(pb
, rescale_mdcv(metadata
->white_point
[1], chroma_den
));
1999 avio_wb32(pb
, rescale_mdcv(metadata
->max_luminance
, luma_den
));
2000 avio_wb32(pb
, rescale_mdcv(metadata
->min_luminance
, luma_den
));
2004 static void find_compressor(char * compressor_name
, int len
, MOVTrack
*track
)
2006 AVDictionaryEntry
*encoder
;
2007 int xdcam_res
= (track
->par
->width
== 1280 && track
->par
->height
== 720)
2008 || (track
->par
->width
== 1440 && track
->par
->height
== 1080)
2009 || (track
->par
->width
== 1920 && track
->par
->height
== 1080);
2011 if (track
->mode
== MODE_MOV
&&
2012 (encoder
= av_dict_get(track
->st
->metadata
, "encoder", NULL
, 0))) {
2013 av_strlcpy(compressor_name
, encoder
->value
, 32);
2014 } else if (track
->par
->codec_id
== AV_CODEC_ID_MPEG2VIDEO
&& xdcam_res
) {
2015 int interlaced
= track
->par
->field_order
> AV_FIELD_PROGRESSIVE
;
2016 AVStream
*st
= track
->st
;
2017 int rate
= defined_frame_rate(NULL
, st
);
2018 av_strlcatf(compressor_name
, len
, "XDCAM");
2019 if (track
->par
->format
== AV_PIX_FMT_YUV422P
) {
2020 av_strlcatf(compressor_name
, len
, " HD422");
2021 } else if(track
->par
->width
== 1440) {
2022 av_strlcatf(compressor_name
, len
, " HD");
2024 av_strlcatf(compressor_name
, len
, " EX");
2026 av_strlcatf(compressor_name
, len
, " %d%c", track
->par
->height
, interlaced
? 'i' : 'p');
2028 av_strlcatf(compressor_name
, len
, "%d", rate
* (interlaced
+ 1));
2032 static int mov_write_video_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVMuxContext
*mov
, MOVTrack
*track
)
2034 int64_t pos
= avio_tell(pb
);
2035 char compressor_name
[32] = { 0 };
2038 int uncompressed_ycbcr
= ((track
->par
->codec_id
== AV_CODEC_ID_RAWVIDEO
&& track
->par
->format
== AV_PIX_FMT_UYVY422
)
2039 || (track
->par
->codec_id
== AV_CODEC_ID_RAWVIDEO
&& track
->par
->format
== AV_PIX_FMT_YUYV422
)
2040 || track
->par
->codec_id
== AV_CODEC_ID_V308
2041 || track
->par
->codec_id
== AV_CODEC_ID_V408
2042 || track
->par
->codec_id
== AV_CODEC_ID_V410
2043 || track
->par
->codec_id
== AV_CODEC_ID_V210
);
2045 avio_wb32(pb
, 0); /* size */
2046 if (mov
->encryption_scheme
!= MOV_ENC_NONE
) {
2047 ffio_wfourcc(pb
, "encv");
2049 avio_wl32(pb
, track
->tag
); // store it byteswapped
2051 avio_wb32(pb
, 0); /* Reserved */
2052 avio_wb16(pb
, 0); /* Reserved */
2053 avio_wb16(pb
, 1); /* Data-reference index */
2055 if (uncompressed_ycbcr
) {
2056 avio_wb16(pb
, 2); /* Codec stream version */
2058 avio_wb16(pb
, 0); /* Codec stream version */
2060 avio_wb16(pb
, 0); /* Codec stream revision (=0) */
2061 if (track
->mode
== MODE_MOV
) {
2062 ffio_wfourcc(pb
, "FFMP"); /* Vendor */
2063 if (track
->par
->codec_id
== AV_CODEC_ID_RAWVIDEO
|| uncompressed_ycbcr
) {
2064 avio_wb32(pb
, 0); /* Temporal Quality */
2065 avio_wb32(pb
, 0x400); /* Spatial Quality = lossless*/
2067 avio_wb32(pb
, 0x200); /* Temporal Quality = normal */
2068 avio_wb32(pb
, 0x200); /* Spatial Quality = normal */
2071 avio_wb32(pb
, 0); /* Reserved */
2072 avio_wb32(pb
, 0); /* Reserved */
2073 avio_wb32(pb
, 0); /* Reserved */
2075 avio_wb16(pb
, track
->par
->width
); /* Video width */
2076 avio_wb16(pb
, track
->height
); /* Video height */
2077 avio_wb32(pb
, 0x00480000); /* Horizontal resolution 72dpi */
2078 avio_wb32(pb
, 0x00480000); /* Vertical resolution 72dpi */
2079 avio_wb32(pb
, 0); /* Data size (= 0) */
2080 avio_wb16(pb
, 1); /* Frame count (= 1) */
2082 /* FIXME not sure, ISO 14496-1 draft where it shall be set to 0 */
2083 find_compressor(compressor_name
, 32, track
);
2084 avio_w8(pb
, strlen(compressor_name
));
2085 avio_write(pb
, compressor_name
, 31);
2087 if (track
->mode
== MODE_MOV
&&
2088 (track
->par
->codec_id
== AV_CODEC_ID_V410
|| track
->par
->codec_id
== AV_CODEC_ID_V210
))
2089 avio_wb16(pb
, 0x18);
2090 else if (track
->mode
== MODE_MOV
&& track
->par
->bits_per_coded_sample
)
2091 avio_wb16(pb
, track
->par
->bits_per_coded_sample
|
2092 (track
->par
->format
== AV_PIX_FMT_GRAY8
? 0x20 : 0));
2094 avio_wb16(pb
, 0x18); /* Reserved */
2096 if (track
->mode
== MODE_MOV
&& track
->par
->format
== AV_PIX_FMT_PAL8
) {
2098 avio_wb16(pb
, 0); /* Color table ID */
2099 avio_wb32(pb
, 0); /* Color table seed */
2100 avio_wb16(pb
, 0x8000); /* Color table flags */
2101 if (track
->par
->bits_per_coded_sample
< 0 || track
->par
->bits_per_coded_sample
> 8)
2102 return AVERROR(EINVAL
);
2103 pal_size
= 1 << track
->par
->bits_per_coded_sample
;
2104 avio_wb16(pb
, pal_size
- 1); /* Color table size (zero-relative) */
2105 for (i
= 0; i
< pal_size
; i
++) {
2106 uint32_t rgb
= track
->palette
[i
];
2107 uint16_t r
= (rgb
>> 16) & 0xff;
2108 uint16_t g
= (rgb
>> 8) & 0xff;
2109 uint16_t b
= rgb
& 0xff;
2111 avio_wb16(pb
, (r
<< 8) | r
);
2112 avio_wb16(pb
, (g
<< 8) | g
);
2113 avio_wb16(pb
, (b
<< 8) | b
);
2116 avio_wb16(pb
, 0xffff); /* Reserved */
2118 if (track
->tag
== MKTAG('m','p','4','v'))
2119 mov_write_esds_tag(pb
, track
);
2120 else if (track
->par
->codec_id
== AV_CODEC_ID_H263
)
2121 mov_write_d263_tag(pb
);
2122 else if (track
->par
->codec_id
== AV_CODEC_ID_AVUI
||
2123 track
->par
->codec_id
== AV_CODEC_ID_SVQ3
) {
2124 mov_write_extradata_tag(pb
, track
);
2126 } else if (track
->par
->codec_id
== AV_CODEC_ID_DNXHD
) {
2127 mov_write_avid_tag(pb
, track
);
2129 } else if (track
->par
->codec_id
== AV_CODEC_ID_HEVC
)
2130 mov_write_hvcc_tag(pb
, track
);
2131 else if (track
->par
->codec_id
== AV_CODEC_ID_H264
&& !TAG_IS_AVCI(track
->tag
)) {
2132 mov_write_avcc_tag(pb
, track
);
2133 if (track
->mode
== MODE_IPOD
)
2134 mov_write_uuid_tag_ipod(pb
);
2135 } else if (track
->par
->codec_id
== AV_CODEC_ID_VP9
) {
2136 mov_write_vpcc_tag(mov
->fc
, pb
, track
);
2137 } else if (track
->par
->codec_id
== AV_CODEC_ID_AV1
) {
2138 mov_write_av1c_tag(pb
, track
);
2139 } else if (track
->par
->codec_id
== AV_CODEC_ID_VC1
&& track
->vos_len
> 0)
2140 mov_write_dvc1_tag(pb
, track
);
2141 else if (track
->par
->codec_id
== AV_CODEC_ID_VP6F
||
2142 track
->par
->codec_id
== AV_CODEC_ID_VP6A
) {
2143 /* Don't write any potential extradata here - the cropping
2144 * is signalled via the normal width/height fields. */
2145 } else if (track
->par
->codec_id
== AV_CODEC_ID_R10K
) {
2146 if (track
->par
->codec_tag
== MKTAG('R','1','0','k'))
2147 mov_write_dpxe_tag(pb
, track
);
2148 } else if (track
->vos_len
> 0)
2149 mov_write_glbl_tag(pb
, track
);
2151 if (track
->par
->codec_id
!= AV_CODEC_ID_H264
&&
2152 track
->par
->codec_id
!= AV_CODEC_ID_MPEG4
&&
2153 track
->par
->codec_id
!= AV_CODEC_ID_DNXHD
) {
2154 int field_order
= track
->par
->field_order
;
2156 #if FF_API_LAVF_AVCTX
2157 FF_DISABLE_DEPRECATION_WARNINGS
2158 if (field_order
!= track
->st
->codec
->field_order
&& track
->st
->codec
->field_order
!= AV_FIELD_UNKNOWN
)
2159 field_order
= track
->st
->codec
->field_order
;
2160 FF_ENABLE_DEPRECATION_WARNINGS
2163 if (field_order
!= AV_FIELD_UNKNOWN
)
2164 mov_write_fiel_tag(pb
, track
, field_order
);
2167 if (mov
->flags
& FF_MOV_FLAG_WRITE_GAMA
) {
2168 if (track
->mode
== MODE_MOV
)
2169 mov_write_gama_tag(s
, pb
, track
, mov
->gamma
);
2171 av_log(mov
->fc
, AV_LOG_WARNING
, "Not writing 'gama' atom. Format is not MOV.\n");
2173 if (mov
->flags
& FF_MOV_FLAG_WRITE_COLR
) {
2174 if (track
->mode
== MODE_MOV
|| track
->mode
== MODE_MP4
)
2175 mov_write_colr_tag(pb
, track
, mov
->flags
& FF_MOV_FLAG_PREFER_ICC
);
2177 av_log(mov
->fc
, AV_LOG_WARNING
, "Not writing 'colr' atom. Format is not MOV or MP4.\n");
2179 if (track
->mode
== MODE_MOV
|| track
->mode
== MODE_MP4
) {
2180 mov_write_clli_tag(pb
, track
);
2181 mov_write_mdcv_tag(pb
, track
);
2184 if (track
->mode
== MODE_MP4
&& mov
->fc
->strict_std_compliance
<= FF_COMPLIANCE_UNOFFICIAL
) {
2185 AVStereo3D
* stereo_3d
= (AVStereo3D
*) av_stream_get_side_data(track
->st
, AV_PKT_DATA_STEREO3D
, NULL
);
2186 AVSphericalMapping
* spherical_mapping
= (AVSphericalMapping
*)av_stream_get_side_data(track
->st
, AV_PKT_DATA_SPHERICAL
, NULL
);
2187 AVDOVIDecoderConfigurationRecord
*dovi
= (AVDOVIDecoderConfigurationRecord
*)
2188 av_stream_get_side_data(track
->st
, AV_PKT_DATA_DOVI_CONF
, NULL
);;
2191 mov_write_st3d_tag(s
, pb
, stereo_3d
);
2192 if (spherical_mapping
)
2193 mov_write_sv3d_tag(mov
->fc
, pb
, spherical_mapping
);
2195 mov_write_dvcc_dvvc_tag(s
, pb
, dovi
);
2198 if (track
->par
->sample_aspect_ratio
.den
&& track
->par
->sample_aspect_ratio
.num
) {
2199 mov_write_pasp_tag(pb
, track
);
2202 if (uncompressed_ycbcr
){
2203 mov_write_clap_tag(pb
, track
);
2206 if (mov
->encryption_scheme
!= MOV_ENC_NONE
) {
2207 ff_mov_cenc_write_sinf_tag(track
, pb
, mov
->encryption_kid
);
2210 /* extra padding for avid stsd */
2211 /* https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-61112 */
2215 return update_size(pb
, pos
);
2218 static int mov_write_rtp_tag(AVIOContext
*pb
, MOVTrack
*track
)
2220 int64_t pos
= avio_tell(pb
);
2221 avio_wb32(pb
, 0); /* size */
2222 ffio_wfourcc(pb
, "rtp ");
2223 avio_wb32(pb
, 0); /* Reserved */
2224 avio_wb16(pb
, 0); /* Reserved */
2225 avio_wb16(pb
, 1); /* Data-reference index */
2227 avio_wb16(pb
, 1); /* Hint track version */
2228 avio_wb16(pb
, 1); /* Highest compatible version */
2229 avio_wb32(pb
, track
->max_packet_size
); /* Max packet size */
2231 avio_wb32(pb
, 12); /* size */
2232 ffio_wfourcc(pb
, "tims");
2233 avio_wb32(pb
, track
->timescale
);
2235 return update_size(pb
, pos
);
2238 static int mov_write_source_reference_tag(AVIOContext
*pb
, MOVTrack
*track
, const char *reel_name
)
2240 uint64_t str_size
=strlen(reel_name
);
2241 int64_t pos
= avio_tell(pb
);
2243 if (str_size
>= UINT16_MAX
){
2244 av_log(NULL
, AV_LOG_ERROR
, "reel_name length %"PRIu64
" is too large\n", str_size
);
2246 return AVERROR(EINVAL
);
2249 avio_wb32(pb
, 0); /* size */
2250 ffio_wfourcc(pb
, "name"); /* Data format */
2251 avio_wb16(pb
, str_size
); /* string size */
2252 avio_wb16(pb
, track
->language
); /* langcode */
2253 avio_write(pb
, reel_name
, str_size
); /* reel name */
2254 return update_size(pb
,pos
);
2257 static int mov_write_tmcd_tag(AVIOContext
*pb
, MOVTrack
*track
)
2259 int64_t pos
= avio_tell(pb
);
2263 AVDictionaryEntry
*t
= NULL
;
2265 if (!track
->st
->avg_frame_rate
.num
|| !track
->st
->avg_frame_rate
.den
) {
2266 #if FF_API_LAVF_AVCTX
2267 FF_DISABLE_DEPRECATION_WARNINGS
2268 frame_duration
= av_rescale(track
->timescale
, track
->st
->codec
->time_base
.num
, track
->st
->codec
->time_base
.den
);
2269 nb_frames
= ROUNDED_DIV(track
->st
->codec
->time_base
.den
, track
->st
->codec
->time_base
.num
);
2270 FF_ENABLE_DEPRECATION_WARNINGS
2272 av_log(NULL
, AV_LOG_ERROR
, "avg_frame_rate not set for tmcd track.\n");
2273 return AVERROR(EINVAL
);
2276 frame_duration
= av_rescale(track
->timescale
, track
->st
->avg_frame_rate
.num
, track
->st
->avg_frame_rate
.den
);
2277 nb_frames
= ROUNDED_DIV(track
->st
->avg_frame_rate
.den
, track
->st
->avg_frame_rate
.num
);
2280 if (nb_frames
> 255) {
2281 av_log(NULL
, AV_LOG_ERROR
, "fps %d is too large\n", nb_frames
);
2282 return AVERROR(EINVAL
);
2285 avio_wb32(pb
, 0); /* size */
2286 ffio_wfourcc(pb
, "tmcd"); /* Data format */
2287 avio_wb32(pb
, 0); /* Reserved */
2288 avio_wb32(pb
, 1); /* Data reference index */
2289 avio_wb32(pb
, 0); /* Flags */
2290 avio_wb32(pb
, track
->timecode_flags
); /* Flags (timecode) */
2291 avio_wb32(pb
, track
->timescale
); /* Timescale */
2292 avio_wb32(pb
, frame_duration
); /* Frame duration */
2293 avio_w8(pb
, nb_frames
); /* Number of frames */
2294 avio_w8(pb
, 0); /* Reserved */
2296 t
= av_dict_get(track
->st
->metadata
, "reel_name", NULL
, 0);
2297 if (t
&& utf8len(t
->value
) && track
->mode
!= MODE_MP4
)
2298 mov_write_source_reference_tag(pb
, track
, t
->value
);
2300 avio_wb16(pb
, 0); /* zero size */
2303 avio_wb32(pb
, 0); /* size */
2304 ffio_wfourcc(pb
, "tmcd"); /* Data format */
2305 avio_wb32(pb
, 0); /* Reserved */
2306 avio_wb32(pb
, 1); /* Data reference index */
2307 if (track
->par
->extradata_size
)
2308 avio_write(pb
, track
->par
->extradata
, track
->par
->extradata_size
);
2310 return update_size(pb
, pos
);
2313 static int mov_write_gpmd_tag(AVIOContext
*pb
, const MOVTrack
*track
)
2315 int64_t pos
= avio_tell(pb
);
2316 avio_wb32(pb
, 0); /* size */
2317 ffio_wfourcc(pb
, "gpmd");
2318 avio_wb32(pb
, 0); /* Reserved */
2319 avio_wb16(pb
, 0); /* Reserved */
2320 avio_wb16(pb
, 1); /* Data-reference index */
2321 avio_wb32(pb
, 0); /* Reserved */
2322 return update_size(pb
, pos
);
2325 static int mov_write_stsd_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVMuxContext
*mov
, MOVTrack
*track
)
2327 int64_t pos
= avio_tell(pb
);
2329 avio_wb32(pb
, 0); /* size */
2330 ffio_wfourcc(pb
, "stsd");
2331 avio_wb32(pb
, 0); /* version & flags */
2332 avio_wb32(pb
, 1); /* entry count */
2333 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
)
2334 ret
= mov_write_video_tag(s
, pb
, mov
, track
);
2335 else if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
)
2336 ret
= mov_write_audio_tag(s
, pb
, mov
, track
);
2337 else if (track
->par
->codec_type
== AVMEDIA_TYPE_SUBTITLE
)
2338 ret
= mov_write_subtitle_tag(pb
, track
);
2339 else if (track
->par
->codec_tag
== MKTAG('r','t','p',' '))
2340 ret
= mov_write_rtp_tag(pb
, track
);
2341 else if (track
->par
->codec_tag
== MKTAG('t','m','c','d'))
2342 ret
= mov_write_tmcd_tag(pb
, track
);
2343 else if (track
->par
->codec_tag
== MKTAG('g','p','m','d'))
2344 ret
= mov_write_gpmd_tag(pb
, track
);
2349 return update_size(pb
, pos
);
2352 static int mov_write_ctts_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
2354 MOVMuxContext
*mov
= s
->priv_data
;
2355 MOVStts
*ctts_entries
;
2356 uint32_t entries
= 0;
2360 ctts_entries
= av_malloc_array((track
->entry
+ 1), sizeof(*ctts_entries
)); /* worst case */
2362 return AVERROR(ENOMEM
);
2363 ctts_entries
[0].count
= 1;
2364 ctts_entries
[0].duration
= track
->cluster
[0].cts
;
2365 for (i
= 1; i
< track
->entry
; i
++) {
2366 if (track
->cluster
[i
].cts
== ctts_entries
[entries
].duration
) {
2367 ctts_entries
[entries
].count
++; /* compress */
2370 ctts_entries
[entries
].duration
= track
->cluster
[i
].cts
;
2371 ctts_entries
[entries
].count
= 1;
2374 entries
++; /* last one */
2375 atom_size
= 16 + (entries
* 8);
2376 avio_wb32(pb
, atom_size
); /* size */
2377 ffio_wfourcc(pb
, "ctts");
2378 if (mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
)
2379 avio_w8(pb
, 1); /* version */
2381 avio_w8(pb
, 0); /* version */
2382 avio_wb24(pb
, 0); /* flags */
2383 avio_wb32(pb
, entries
); /* entry count */
2384 for (i
= 0; i
< entries
; i
++) {
2385 avio_wb32(pb
, ctts_entries
[i
].count
);
2386 avio_wb32(pb
, ctts_entries
[i
].duration
);
2388 av_free(ctts_entries
);
2392 /* Time to sample atom */
2393 static int mov_write_stts_tag(AVIOContext
*pb
, MOVTrack
*track
)
2395 MOVStts
*stts_entries
= NULL
;
2396 uint32_t entries
= -1;
2400 if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
&& !track
->audio_vbr
) {
2401 stts_entries
= av_malloc(sizeof(*stts_entries
)); /* one entry */
2403 return AVERROR(ENOMEM
);
2404 stts_entries
[0].count
= track
->sample_count
;
2405 stts_entries
[0].duration
= 1;
2409 stts_entries
= av_malloc_array(track
->entry
, sizeof(*stts_entries
)); /* worst case */
2411 return AVERROR(ENOMEM
);
2413 for (i
= 0; i
< track
->entry
; i
++) {
2414 int duration
= get_cluster_duration(track
, i
);
2415 if (i
&& duration
== stts_entries
[entries
].duration
) {
2416 stts_entries
[entries
].count
++; /* compress */
2419 stts_entries
[entries
].duration
= duration
;
2420 stts_entries
[entries
].count
= 1;
2423 entries
++; /* last one */
2425 atom_size
= 16 + (entries
* 8);
2426 avio_wb32(pb
, atom_size
); /* size */
2427 ffio_wfourcc(pb
, "stts");
2428 avio_wb32(pb
, 0); /* version & flags */
2429 avio_wb32(pb
, entries
); /* entry count */
2430 for (i
= 0; i
< entries
; i
++) {
2431 avio_wb32(pb
, stts_entries
[i
].count
);
2432 avio_wb32(pb
, stts_entries
[i
].duration
);
2434 av_free(stts_entries
);
2438 static int mov_write_dref_tag(AVIOContext
*pb
)
2440 avio_wb32(pb
, 28); /* size */
2441 ffio_wfourcc(pb
, "dref");
2442 avio_wb32(pb
, 0); /* version & flags */
2443 avio_wb32(pb
, 1); /* entry count */
2445 avio_wb32(pb
, 0xc); /* size */
2446 //FIXME add the alis and rsrc atom
2447 ffio_wfourcc(pb
, "url ");
2448 avio_wb32(pb
, 1); /* version & flags */
2453 static int mov_preroll_write_stbl_atoms(AVIOContext
*pb
, MOVTrack
*track
)
2457 int16_t roll_distance
;
2458 int group_description_index
;
2461 struct sgpd_entry
*sgpd_entries
= NULL
;
2466 const int OPUS_SEEK_PREROLL_MS
= 80;
2467 int roll_samples
= av_rescale_q(OPUS_SEEK_PREROLL_MS
,
2468 (AVRational
){1, 1000},
2469 (AVRational
){1, 48000});
2474 sgpd_entries
= av_malloc_array(track
->entry
, sizeof(*sgpd_entries
));
2476 return AVERROR(ENOMEM
);
2478 av_assert0(track
->par
->codec_id
== AV_CODEC_ID_OPUS
|| track
->par
->codec_id
== AV_CODEC_ID_AAC
);
2480 if (track
->par
->codec_id
== AV_CODEC_ID_OPUS
) {
2481 for (i
= 0; i
< track
->entry
; i
++) {
2482 int roll_samples_remaining
= roll_samples
;
2484 for (j
= i
- 1; j
>= 0; j
--) {
2485 roll_samples_remaining
-= get_cluster_duration(track
, j
);
2487 if (roll_samples_remaining
<= 0)
2490 /* We don't have enough preceeding samples to compute a valid
2491 roll_distance here, so this sample can't be independently
2493 if (roll_samples_remaining
> 0)
2495 /* Verify distance is a maximum of 32 (2.5ms) packets. */
2497 return AVERROR_INVALIDDATA
;
2498 if (i
&& distance
== sgpd_entries
[entries
].roll_distance
) {
2499 sgpd_entries
[entries
].count
++;
2502 sgpd_entries
[entries
].count
= 1;
2503 sgpd_entries
[entries
].roll_distance
= distance
;
2504 sgpd_entries
[entries
].group_description_index
= distance
? ++group
: 0;
2509 sgpd_entries
[entries
].count
= track
->sample_count
;
2510 sgpd_entries
[entries
].roll_distance
= 1;
2511 sgpd_entries
[entries
].group_description_index
= ++group
;
2516 av_free(sgpd_entries
);
2520 /* Write sgpd tag */
2521 avio_wb32(pb
, 24 + (group
* 2)); /* size */
2522 ffio_wfourcc(pb
, "sgpd");
2523 avio_wb32(pb
, 1 << 24); /* fullbox */
2524 ffio_wfourcc(pb
, "roll");
2525 avio_wb32(pb
, 2); /* default_length */
2526 avio_wb32(pb
, group
); /* entry_count */
2527 for (i
= 0; i
< entries
; i
++) {
2528 if (sgpd_entries
[i
].group_description_index
) {
2529 avio_wb16(pb
, -sgpd_entries
[i
].roll_distance
); /* roll_distance */
2533 /* Write sbgp tag */
2534 avio_wb32(pb
, 20 + (entries
* 8)); /* size */
2535 ffio_wfourcc(pb
, "sbgp");
2536 avio_wb32(pb
, 0); /* fullbox */
2537 ffio_wfourcc(pb
, "roll");
2538 avio_wb32(pb
, entries
); /* entry_count */
2539 for (i
= 0; i
< entries
; i
++) {
2540 avio_wb32(pb
, sgpd_entries
[i
].count
); /* sample_count */
2541 avio_wb32(pb
, sgpd_entries
[i
].group_description_index
); /* group_description_index */
2544 av_free(sgpd_entries
);
2548 static int mov_write_stbl_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVMuxContext
*mov
, MOVTrack
*track
)
2550 int64_t pos
= avio_tell(pb
);
2553 avio_wb32(pb
, 0); /* size */
2554 ffio_wfourcc(pb
, "stbl");
2555 if ((ret
= mov_write_stsd_tag(s
, pb
, mov
, track
)) < 0)
2557 mov_write_stts_tag(pb
, track
);
2558 if ((track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
||
2559 track
->par
->codec_id
== AV_CODEC_ID_TRUEHD
||
2560 track
->par
->codec_id
== AV_CODEC_ID_MPEGH_3D_AUDIO
||
2561 track
->par
->codec_tag
== MKTAG('r','t','p',' ')) &&
2562 track
->has_keyframes
&& track
->has_keyframes
< track
->entry
)
2563 mov_write_stss_tag(pb
, track
, MOV_SYNC_SAMPLE
);
2564 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
&& track
->has_disposable
)
2565 mov_write_sdtp_tag(pb
, track
);
2566 if (track
->mode
== MODE_MOV
&& track
->flags
& MOV_TRACK_STPS
)
2567 mov_write_stss_tag(pb
, track
, MOV_PARTIAL_SYNC_SAMPLE
);
2568 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
&&
2569 track
->flags
& MOV_TRACK_CTTS
&& track
->entry
) {
2571 if ((ret
= mov_write_ctts_tag(s
, pb
, track
)) < 0)
2574 mov_write_stsc_tag(pb
, track
);
2575 mov_write_stsz_tag(pb
, track
);
2576 mov_write_stco_tag(pb
, track
);
2577 if (track
->cenc
.aes_ctr
) {
2578 ff_mov_cenc_write_stbl_atoms(&track
->cenc
, pb
);
2580 if (track
->par
->codec_id
== AV_CODEC_ID_OPUS
|| track
->par
->codec_id
== AV_CODEC_ID_AAC
) {
2581 mov_preroll_write_stbl_atoms(pb
, track
);
2583 return update_size(pb
, pos
);
2586 static int mov_write_dinf_tag(AVIOContext
*pb
)
2588 int64_t pos
= avio_tell(pb
);
2589 avio_wb32(pb
, 0); /* size */
2590 ffio_wfourcc(pb
, "dinf");
2591 mov_write_dref_tag(pb
);
2592 return update_size(pb
, pos
);
2595 static int mov_write_nmhd_tag(AVIOContext
*pb
)
2598 ffio_wfourcc(pb
, "nmhd");
2603 static int mov_write_tcmi_tag(AVIOContext
*pb
, MOVTrack
*track
)
2605 int64_t pos
= avio_tell(pb
);
2606 const char *font
= "Lucida Grande";
2607 avio_wb32(pb
, 0); /* size */
2608 ffio_wfourcc(pb
, "tcmi"); /* timecode media information atom */
2609 avio_wb32(pb
, 0); /* version & flags */
2610 avio_wb16(pb
, 0); /* text font */
2611 avio_wb16(pb
, 0); /* text face */
2612 avio_wb16(pb
, 12); /* text size */
2613 avio_wb16(pb
, 0); /* (unknown, not in the QT specs...) */
2614 avio_wb16(pb
, 0x0000); /* text color (red) */
2615 avio_wb16(pb
, 0x0000); /* text color (green) */
2616 avio_wb16(pb
, 0x0000); /* text color (blue) */
2617 avio_wb16(pb
, 0xffff); /* background color (red) */
2618 avio_wb16(pb
, 0xffff); /* background color (green) */
2619 avio_wb16(pb
, 0xffff); /* background color (blue) */
2620 avio_w8(pb
, strlen(font
)); /* font len (part of the pascal string) */
2621 avio_write(pb
, font
, strlen(font
)); /* font name */
2622 return update_size(pb
, pos
);
2625 static int mov_write_gmhd_tag(AVIOContext
*pb
, MOVTrack
*track
)
2627 int64_t pos
= avio_tell(pb
);
2628 avio_wb32(pb
, 0); /* size */
2629 ffio_wfourcc(pb
, "gmhd");
2630 avio_wb32(pb
, 0x18); /* gmin size */
2631 ffio_wfourcc(pb
, "gmin");/* generic media info */
2632 avio_wb32(pb
, 0); /* version & flags */
2633 avio_wb16(pb
, 0x40); /* graphics mode = */
2634 avio_wb16(pb
, 0x8000); /* opColor (r?) */
2635 avio_wb16(pb
, 0x8000); /* opColor (g?) */
2636 avio_wb16(pb
, 0x8000); /* opColor (b?) */
2637 avio_wb16(pb
, 0); /* balance */
2638 avio_wb16(pb
, 0); /* reserved */
2641 * This special text atom is required for
2642 * Apple Quicktime chapters. The contents
2643 * don't appear to be documented, so the
2644 * bytes are copied verbatim.
2646 if (track
->tag
!= MKTAG('c','6','0','8')) {
2647 avio_wb32(pb
, 0x2C); /* size */
2648 ffio_wfourcc(pb
, "text");
2649 avio_wb16(pb
, 0x01);
2650 avio_wb32(pb
, 0x00);
2651 avio_wb32(pb
, 0x00);
2652 avio_wb32(pb
, 0x00);
2653 avio_wb32(pb
, 0x01);
2654 avio_wb32(pb
, 0x00);
2655 avio_wb32(pb
, 0x00);
2656 avio_wb32(pb
, 0x00);
2657 avio_wb32(pb
, 0x00004000);
2658 avio_wb16(pb
, 0x0000);
2661 if (track
->par
->codec_tag
== MKTAG('t','m','c','d')) {
2662 int64_t tmcd_pos
= avio_tell(pb
);
2663 avio_wb32(pb
, 0); /* size */
2664 ffio_wfourcc(pb
, "tmcd");
2665 mov_write_tcmi_tag(pb
, track
);
2666 update_size(pb
, tmcd_pos
);
2667 } else if (track
->par
->codec_tag
== MKTAG('g','p','m','d')) {
2668 int64_t gpmd_pos
= avio_tell(pb
);
2669 avio_wb32(pb
, 0); /* size */
2670 ffio_wfourcc(pb
, "gpmd");
2671 avio_wb32(pb
, 0); /* version */
2672 update_size(pb
, gpmd_pos
);
2674 return update_size(pb
, pos
);
2677 static int mov_write_smhd_tag(AVIOContext
*pb
)
2679 avio_wb32(pb
, 16); /* size */
2680 ffio_wfourcc(pb
, "smhd");
2681 avio_wb32(pb
, 0); /* version & flags */
2682 avio_wb16(pb
, 0); /* reserved (balance, normally = 0) */
2683 avio_wb16(pb
, 0); /* reserved */
2687 static int mov_write_vmhd_tag(AVIOContext
*pb
)
2689 avio_wb32(pb
, 0x14); /* size (always 0x14) */
2690 ffio_wfourcc(pb
, "vmhd");
2691 avio_wb32(pb
, 0x01); /* version & flags */
2692 avio_wb64(pb
, 0); /* reserved (graphics mode = copy) */
2696 static int is_clcp_track(MOVTrack
*track
)
2698 return track
->tag
== MKTAG('c','7','0','8') ||
2699 track
->tag
== MKTAG('c','6','0','8');
2702 static int mov_write_hdlr_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
2704 MOVMuxContext
*mov
= s
->priv_data
;
2705 const char *hdlr
, *descr
= NULL
, *hdlr_type
= NULL
;
2706 int64_t pos
= avio_tell(pb
);
2710 descr
= "DataHandler";
2713 hdlr
= (track
->mode
== MODE_MOV
) ? "mhlr" : "\0\0\0\0";
2714 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
2716 descr
= "VideoHandler";
2717 } else if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
2719 descr
= "SoundHandler";
2720 } else if (track
->par
->codec_type
== AVMEDIA_TYPE_SUBTITLE
) {
2721 if (is_clcp_track(track
)) {
2723 descr
= "ClosedCaptionHandler";
2725 if (track
->tag
== MKTAG('t','x','3','g')) {
2727 } else if (track
->tag
== MKTAG('m','p','4','s')) {
2732 descr
= "SubtitleHandler";
2734 } else if (track
->par
->codec_tag
== MKTAG('r','t','p',' ')) {
2736 descr
= "HintHandler";
2737 } else if (track
->par
->codec_tag
== MKTAG('t','m','c','d')) {
2739 descr
= "TimeCodeHandler";
2740 } else if (track
->par
->codec_tag
== MKTAG('g','p','m','d')) {
2742 descr
= "GoPro MET"; // GoPro Metadata
2744 av_log(s
, AV_LOG_WARNING
,
2745 "Unknown hldr_type for %s, writing dummy values\n",
2746 av_fourcc2str(track
->par
->codec_tag
));
2749 // hdlr.name is used by some players to identify the content title
2750 // of the track. So if an alternate handler description is
2751 // specified, use it.
2752 AVDictionaryEntry
*t
;
2753 t
= av_dict_get(track
->st
->metadata
, "handler_name", NULL
, 0);
2754 if (t
&& utf8len(t
->value
))
2759 if (mov
->empty_hdlr_name
) /* expressly allowed by QTFF and not prohibited in ISO 14496-12 8.4.3.3 */
2762 avio_wb32(pb
, 0); /* size */
2763 ffio_wfourcc(pb
, "hdlr");
2764 avio_wb32(pb
, 0); /* Version & flags */
2765 avio_write(pb
, hdlr
, 4); /* handler */
2766 ffio_wfourcc(pb
, hdlr_type
); /* handler type */
2767 avio_wb32(pb
, 0); /* reserved */
2768 avio_wb32(pb
, 0); /* reserved */
2769 avio_wb32(pb
, 0); /* reserved */
2770 if (!track
|| track
->mode
== MODE_MOV
)
2771 avio_w8(pb
, strlen(descr
)); /* pascal string */
2772 avio_write(pb
, descr
, strlen(descr
)); /* handler description */
2773 if (track
&& track
->mode
!= MODE_MOV
)
2774 avio_w8(pb
, 0); /* c string */
2775 return update_size(pb
, pos
);
2778 static int mov_write_hmhd_tag(AVIOContext
*pb
)
2780 /* This atom must be present, but leaving the values at zero
2781 * seems harmless. */
2782 avio_wb32(pb
, 28); /* size */
2783 ffio_wfourcc(pb
, "hmhd");
2784 avio_wb32(pb
, 0); /* version, flags */
2785 avio_wb16(pb
, 0); /* maxPDUsize */
2786 avio_wb16(pb
, 0); /* avgPDUsize */
2787 avio_wb32(pb
, 0); /* maxbitrate */
2788 avio_wb32(pb
, 0); /* avgbitrate */
2789 avio_wb32(pb
, 0); /* reserved */
2793 static int mov_write_minf_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVMuxContext
*mov
, MOVTrack
*track
)
2795 int64_t pos
= avio_tell(pb
);
2798 avio_wb32(pb
, 0); /* size */
2799 ffio_wfourcc(pb
, "minf");
2800 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
)
2801 mov_write_vmhd_tag(pb
);
2802 else if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
)
2803 mov_write_smhd_tag(pb
);
2804 else if (track
->par
->codec_type
== AVMEDIA_TYPE_SUBTITLE
) {
2805 if (track
->tag
== MKTAG('t','e','x','t') || is_clcp_track(track
)) {
2806 mov_write_gmhd_tag(pb
, track
);
2808 mov_write_nmhd_tag(pb
);
2810 } else if (track
->tag
== MKTAG('r','t','p',' ')) {
2811 mov_write_hmhd_tag(pb
);
2812 } else if (track
->tag
== MKTAG('t','m','c','d')) {
2813 if (track
->mode
!= MODE_MOV
)
2814 mov_write_nmhd_tag(pb
);
2816 mov_write_gmhd_tag(pb
, track
);
2817 } else if (track
->tag
== MKTAG('g','p','m','d')) {
2818 mov_write_gmhd_tag(pb
, track
);
2820 if (track
->mode
== MODE_MOV
) /* ISO 14496-12 8.4.3.1 specifies hdlr only within mdia or meta boxes */
2821 mov_write_hdlr_tag(s
, pb
, NULL
);
2822 mov_write_dinf_tag(pb
);
2823 if ((ret
= mov_write_stbl_tag(s
, pb
, mov
, track
)) < 0)
2825 return update_size(pb
, pos
);
2828 static int64_t calc_pts_duration(MOVMuxContext
*mov
, MOVTrack
*track
)
2830 if (track
->tag
== MKTAG('t','m','c','d') && mov
->nb_meta_tmcd
) {
2831 // tmcd tracks gets track_duration set in mov_write_moov_tag from
2832 // another track's duration, while the end_pts may be left at zero.
2833 // Calculate the pts duration for that track instead.
2834 return av_rescale(calc_pts_duration(mov
, &mov
->tracks
[track
->src_track
]),
2835 track
->timescale
, mov
->tracks
[track
->src_track
].timescale
);
2837 if (track
->end_pts
!= AV_NOPTS_VALUE
&&
2838 track
->start_dts
!= AV_NOPTS_VALUE
&&
2839 track
->start_cts
!= AV_NOPTS_VALUE
) {
2840 return track
->end_pts
- (track
->start_dts
+ track
->start_cts
);
2842 return track
->track_duration
;
2845 static int mov_write_mdhd_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
2848 int64_t duration
= calc_pts_duration(mov
, track
);
2849 int version
= duration
< INT32_MAX
? 0 : 1;
2851 if (track
->mode
== MODE_ISM
)
2854 (version
== 1) ? avio_wb32(pb
, 44) : avio_wb32(pb
, 32); /* size */
2855 ffio_wfourcc(pb
, "mdhd");
2856 avio_w8(pb
, version
);
2857 avio_wb24(pb
, 0); /* flags */
2859 avio_wb64(pb
, track
->time
);
2860 avio_wb64(pb
, track
->time
);
2862 avio_wb32(pb
, track
->time
); /* creation time */
2863 avio_wb32(pb
, track
->time
); /* modification time */
2865 avio_wb32(pb
, track
->timescale
); /* time scale (sample rate for audio) */
2866 if (!track
->entry
&& mov
->mode
== MODE_ISM
)
2867 (version
== 1) ? avio_wb64(pb
, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb
, 0xffffffff);
2868 else if (!track
->entry
)
2869 (version
== 1) ? avio_wb64(pb
, 0) : avio_wb32(pb
, 0);
2871 (version
== 1) ? avio_wb64(pb
, duration
) : avio_wb32(pb
, duration
); /* duration */
2872 avio_wb16(pb
, track
->language
); /* language */
2873 avio_wb16(pb
, 0); /* reserved (quality) */
2875 if (version
!= 0 && track
->mode
== MODE_MOV
) {
2876 av_log(NULL
, AV_LOG_ERROR
,
2877 "FATAL error, file duration too long for timebase, this file will not be\n"
2878 "playable with QuickTime. Choose a different timebase with "
2879 "-video_track_timescale or a different container format\n");
2885 static int mov_write_mdia_tag(AVFormatContext
*s
, AVIOContext
*pb
,
2886 MOVMuxContext
*mov
, MOVTrack
*track
)
2888 int64_t pos
= avio_tell(pb
);
2891 avio_wb32(pb
, 0); /* size */
2892 ffio_wfourcc(pb
, "mdia");
2893 mov_write_mdhd_tag(pb
, mov
, track
);
2894 mov_write_hdlr_tag(s
, pb
, track
);
2895 if ((ret
= mov_write_minf_tag(s
, pb
, mov
, track
)) < 0)
2897 return update_size(pb
, pos
);
2900 /* transformation matrix
2904 static void write_matrix(AVIOContext
*pb
, int16_t a
, int16_t b
, int16_t c
,
2905 int16_t d
, int16_t tx
, int16_t ty
)
2907 avio_wb32(pb
, a
<< 16); /* 16.16 format */
2908 avio_wb32(pb
, b
<< 16); /* 16.16 format */
2909 avio_wb32(pb
, 0); /* u in 2.30 format */
2910 avio_wb32(pb
, c
<< 16); /* 16.16 format */
2911 avio_wb32(pb
, d
<< 16); /* 16.16 format */
2912 avio_wb32(pb
, 0); /* v in 2.30 format */
2913 avio_wb32(pb
, tx
<< 16); /* 16.16 format */
2914 avio_wb32(pb
, ty
<< 16); /* 16.16 format */
2915 avio_wb32(pb
, 1 << 30); /* w in 2.30 format */
2918 static int mov_write_tkhd_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
2919 MOVTrack
*track
, AVStream
*st
)
2921 int64_t duration
= av_rescale_rnd(calc_pts_duration(mov
, track
),
2922 MOV_TIMESCALE
, track
->timescale
,
2924 int version
= duration
< INT32_MAX
? 0 : 1;
2925 int flags
= MOV_TKHD_FLAG_IN_MOVIE
;
2929 uint32_t *display_matrix
= NULL
;
2930 int display_matrix_size
, i
;
2933 if (mov
->per_stream_grouping
)
2936 group
= st
->codecpar
->codec_type
;
2938 display_matrix
= (uint32_t*)av_stream_get_side_data(st
, AV_PKT_DATA_DISPLAYMATRIX
,
2939 &display_matrix_size
);
2940 if (display_matrix
&& display_matrix_size
< 9 * sizeof(*display_matrix
))
2941 display_matrix
= NULL
;
2944 if (track
->flags
& MOV_TRACK_ENABLED
)
2945 flags
|= MOV_TKHD_FLAG_ENABLED
;
2947 if (track
->mode
== MODE_ISM
)
2950 (version
== 1) ? avio_wb32(pb
, 104) : avio_wb32(pb
, 92); /* size */
2951 ffio_wfourcc(pb
, "tkhd");
2952 avio_w8(pb
, version
);
2953 avio_wb24(pb
, flags
);
2955 avio_wb64(pb
, track
->time
);
2956 avio_wb64(pb
, track
->time
);
2958 avio_wb32(pb
, track
->time
); /* creation time */
2959 avio_wb32(pb
, track
->time
); /* modification time */
2961 avio_wb32(pb
, track
->track_id
); /* track-id */
2962 avio_wb32(pb
, 0); /* reserved */
2963 if (!track
->entry
&& mov
->mode
== MODE_ISM
)
2964 (version
== 1) ? avio_wb64(pb
, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb
, 0xffffffff);
2965 else if (!track
->entry
)
2966 (version
== 1) ? avio_wb64(pb
, 0) : avio_wb32(pb
, 0);
2968 (version
== 1) ? avio_wb64(pb
, duration
) : avio_wb32(pb
, duration
);
2970 avio_wb32(pb
, 0); /* reserved */
2971 avio_wb32(pb
, 0); /* reserved */
2972 avio_wb16(pb
, 0); /* layer */
2973 avio_wb16(pb
, group
); /* alternate group) */
2974 /* Volume, only for audio */
2975 if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
)
2976 avio_wb16(pb
, 0x0100);
2979 avio_wb16(pb
, 0); /* reserved */
2981 /* Matrix structure */
2982 #if FF_API_OLD_ROTATE_API
2983 if (st
&& st
->metadata
) {
2984 AVDictionaryEntry
*rot
= av_dict_get(st
->metadata
, "rotate", NULL
, 0);
2985 rotation
= (rot
&& rot
->value
) ? atoi(rot
->value
) : 0;
2988 if (display_matrix
) {
2989 for (i
= 0; i
< 9; i
++)
2990 avio_wb32(pb
, display_matrix
[i
]);
2991 #if FF_API_OLD_ROTATE_API
2992 } else if (rotation
== 90) {
2993 write_matrix(pb
, 0, 1, -1, 0, track
->par
->height
, 0);
2994 } else if (rotation
== 180) {
2995 write_matrix(pb
, -1, 0, 0, -1, track
->par
->width
, track
->par
->height
);
2996 } else if (rotation
== 270) {
2997 write_matrix(pb
, 0, -1, 1, 0, 0, track
->par
->width
);
3000 write_matrix(pb
, 1, 0, 0, 1, 0, 0);
3002 /* Track width and height, for visual only */
3003 if (st
&& (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
||
3004 track
->par
->codec_type
== AVMEDIA_TYPE_SUBTITLE
)) {
3005 int64_t track_width_1616
;
3006 if (track
->mode
== MODE_MOV
) {
3007 track_width_1616
= track
->par
->width
* 0x10000ULL
;
3009 track_width_1616
= av_rescale(st
->sample_aspect_ratio
.num
,
3010 track
->par
->width
* 0x10000LL
,
3011 st
->sample_aspect_ratio
.den
);
3012 if (!track_width_1616
||
3013 track
->height
!= track
->par
->height
||
3014 track_width_1616
> UINT32_MAX
)
3015 track_width_1616
= track
->par
->width
* 0x10000ULL
;
3017 if (track_width_1616
> UINT32_MAX
) {
3018 av_log(mov
->fc
, AV_LOG_WARNING
, "track width is too large\n");
3019 track_width_1616
= 0;
3021 avio_wb32(pb
, track_width_1616
);
3022 if (track
->height
> 0xFFFF) {
3023 av_log(mov
->fc
, AV_LOG_WARNING
, "track height is too large\n");
3026 avio_wb32(pb
, track
->height
* 0x10000U
);
3034 static int mov_write_tapt_tag(AVIOContext
*pb
, MOVTrack
*track
)
3036 int32_t width
= av_rescale(track
->par
->sample_aspect_ratio
.num
, track
->par
->width
,
3037 track
->par
->sample_aspect_ratio
.den
);
3039 int64_t pos
= avio_tell(pb
);
3041 avio_wb32(pb
, 0); /* size */
3042 ffio_wfourcc(pb
, "tapt");
3045 ffio_wfourcc(pb
, "clef");
3047 avio_wb32(pb
, width
<< 16);
3048 avio_wb32(pb
, track
->par
->height
<< 16);
3051 ffio_wfourcc(pb
, "prof");
3053 avio_wb32(pb
, width
<< 16);
3054 avio_wb32(pb
, track
->par
->height
<< 16);
3057 ffio_wfourcc(pb
, "enof");
3059 avio_wb32(pb
, track
->par
->width
<< 16);
3060 avio_wb32(pb
, track
->par
->height
<< 16);
3062 return update_size(pb
, pos
);
3065 // This box seems important for the psp playback ... without it the movie seems to hang
3066 static int mov_write_edts_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3069 int64_t duration
= av_rescale_rnd(calc_pts_duration(mov
, track
),
3070 MOV_TIMESCALE
, track
->timescale
,
3072 int version
= duration
< INT32_MAX
? 0 : 1;
3073 int entry_size
, entry_count
, size
;
3074 int64_t delay
, start_ct
= track
->start_cts
;
3075 int64_t start_dts
= track
->start_dts
;
3078 if (start_dts
!= track
->cluster
[0].dts
|| start_ct
!= track
->cluster
[0].cts
) {
3080 av_log(mov
->fc
, AV_LOG_DEBUG
,
3081 "EDTS using dts:%"PRId64
" cts:%d instead of dts:%"PRId64
" cts:%"PRId64
" tid:%d\n",
3082 track
->cluster
[0].dts
, track
->cluster
[0].cts
,
3083 start_dts
, start_ct
, track
->track_id
);
3084 start_dts
= track
->cluster
[0].dts
;
3085 start_ct
= track
->cluster
[0].cts
;
3089 delay
= av_rescale_rnd(start_dts
+ start_ct
, MOV_TIMESCALE
,
3090 track
->timescale
, AV_ROUND_DOWN
);
3091 version
|= delay
< INT32_MAX
? 0 : 1;
3093 entry_size
= (version
== 1) ? 20 : 12;
3094 entry_count
= 1 + (delay
> 0);
3095 size
= 24 + entry_count
* entry_size
;
3097 /* write the atom data */
3098 avio_wb32(pb
, size
);
3099 ffio_wfourcc(pb
, "edts");
3100 avio_wb32(pb
, size
- 8);
3101 ffio_wfourcc(pb
, "elst");
3102 avio_w8(pb
, version
);
3103 avio_wb24(pb
, 0); /* flags */
3105 avio_wb32(pb
, entry_count
);
3106 if (delay
> 0) { /* add an empty edit to delay presentation */
3107 /* In the positive delay case, the delay includes the cts
3108 * offset, and the second edit list entry below trims out
3109 * the same amount from the actual content. This makes sure
3110 * that the offset last sample is included in the edit
3111 * list duration as well. */
3113 avio_wb64(pb
, delay
);
3116 avio_wb32(pb
, delay
);
3119 avio_wb32(pb
, 0x00010000);
3121 /* Avoid accidentally ending up with start_ct = -1 which has got a
3122 * special meaning. Normally start_ct should end up positive or zero
3123 * here, but use FFMIN in case dts is a small positive integer
3124 * rounded to 0 when represented in MOV_TIMESCALE units. */
3125 av_assert0(av_rescale_rnd(start_dts
, MOV_TIMESCALE
, track
->timescale
, AV_ROUND_DOWN
) <= 0);
3126 start_ct
= -FFMIN(start_dts
, 0);
3127 /* Note, this delay is calculated from the pts of the first sample,
3128 * ensuring that we don't reduce the duration for cases with
3133 /* For fragmented files, we don't know the full length yet. Setting
3134 * duration to 0 allows us to only specify the offset, including
3135 * the rest of the content (from all future fragments) without specifying
3136 * an explicit duration. */
3137 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
)
3142 avio_wb64(pb
, duration
);
3143 avio_wb64(pb
, start_ct
);
3145 avio_wb32(pb
, duration
);
3146 avio_wb32(pb
, start_ct
);
3148 avio_wb32(pb
, 0x00010000);
3152 static int mov_write_tref_tag(AVIOContext
*pb
, MOVTrack
*track
)
3154 avio_wb32(pb
, 20); // size
3155 ffio_wfourcc(pb
, "tref");
3156 avio_wb32(pb
, 12); // size (subatom)
3157 avio_wl32(pb
, track
->tref_tag
);
3158 avio_wb32(pb
, track
->tref_id
);
3162 // goes at the end of each track! ... Critical for PSP playback ("Incompatible data" without it)
3163 static int mov_write_uuid_tag_psp(AVIOContext
*pb
, MOVTrack
*mov
)
3165 avio_wb32(pb
, 0x34); /* size ... reports as 28 in mp4box! */
3166 ffio_wfourcc(pb
, "uuid");
3167 ffio_wfourcc(pb
, "USMT");
3168 avio_wb32(pb
, 0x21d24fce);
3169 avio_wb32(pb
, 0xbb88695c);
3170 avio_wb32(pb
, 0xfac9c740);
3171 avio_wb32(pb
, 0x1c); // another size here!
3172 ffio_wfourcc(pb
, "MTDT");
3173 avio_wb32(pb
, 0x00010012);
3174 avio_wb32(pb
, 0x0a);
3175 avio_wb32(pb
, 0x55c40000);
3181 static int mov_write_udta_sdp(AVIOContext
*pb
, MOVTrack
*track
)
3183 AVFormatContext
*ctx
= track
->rtp_ctx
;
3184 char buf
[1000] = "";
3187 ff_sdp_write_media(buf
, sizeof(buf
), ctx
->streams
[0], track
->src_track
,
3188 NULL
, NULL
, 0, 0, ctx
);
3189 av_strlcatf(buf
, sizeof(buf
), "a=control:streamid=%d\r\n", track
->track_id
);
3192 avio_wb32(pb
, len
+ 24);
3193 ffio_wfourcc(pb
, "udta");
3194 avio_wb32(pb
, len
+ 16);
3195 ffio_wfourcc(pb
, "hnti");
3196 avio_wb32(pb
, len
+ 8);
3197 ffio_wfourcc(pb
, "sdp ");
3198 avio_write(pb
, buf
, len
);
3202 static int mov_write_track_metadata(AVIOContext
*pb
, AVStream
*st
,
3203 const char *tag
, const char *str
)
3205 int64_t pos
= avio_tell(pb
);
3206 AVDictionaryEntry
*t
= av_dict_get(st
->metadata
, str
, NULL
, 0);
3207 if (!t
|| !utf8len(t
->value
))
3210 avio_wb32(pb
, 0); /* size */
3211 ffio_wfourcc(pb
, tag
); /* type */
3212 avio_write(pb
, t
->value
, strlen(t
->value
)); /* UTF8 string value */
3213 return update_size(pb
, pos
);
3216 static int mov_write_track_udta_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3219 AVIOContext
*pb_buf
;
3226 ret
= avio_open_dyn_buf(&pb_buf
);
3230 if (mov
->mode
& (MODE_MP4
|MODE_MOV
))
3231 mov_write_track_metadata(pb_buf
, st
, "name", "title");
3233 if ((size
= avio_get_dyn_buf(pb_buf
, &buf
)) > 0) {
3234 avio_wb32(pb
, size
+ 8);
3235 ffio_wfourcc(pb
, "udta");
3236 avio_write(pb
, buf
, size
);
3238 ffio_free_dyn_buf(&pb_buf
);
3243 static int mov_write_trak_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVMuxContext
*mov
,
3244 MOVTrack
*track
, AVStream
*st
)
3246 int64_t pos
= avio_tell(pb
);
3247 int entry_backup
= track
->entry
;
3248 int chunk_backup
= track
->chunkCount
;
3251 /* If we want to have an empty moov, but some samples already have been
3252 * buffered (delay_moov), pretend that no samples have been written yet. */
3253 if (mov
->flags
& FF_MOV_FLAG_EMPTY_MOOV
)
3254 track
->chunkCount
= track
->entry
= 0;
3256 avio_wb32(pb
, 0); /* size */
3257 ffio_wfourcc(pb
, "trak");
3258 mov_write_tkhd_tag(pb
, mov
, track
, st
);
3260 av_assert2(mov
->use_editlist
>= 0);
3262 if (track
->start_dts
!= AV_NOPTS_VALUE
) {
3263 if (mov
->use_editlist
)
3264 mov_write_edts_tag(pb
, mov
, track
); // PSP Movies and several other cases require edts box
3265 else if ((track
->entry
&& track
->cluster
[0].dts
) || track
->mode
== MODE_PSP
|| is_clcp_track(track
))
3266 av_log(mov
->fc
, AV_LOG_WARNING
,
3267 "Not writing any edit list even though one would have been required\n");
3270 if (track
->tref_tag
)
3271 mov_write_tref_tag(pb
, track
);
3273 if ((ret
= mov_write_mdia_tag(s
, pb
, mov
, track
)) < 0)
3275 if (track
->mode
== MODE_PSP
)
3276 mov_write_uuid_tag_psp(pb
, track
); // PSP Movies require this uuid box
3277 if (track
->tag
== MKTAG('r','t','p',' '))
3278 mov_write_udta_sdp(pb
, track
);
3279 if (track
->mode
== MODE_MOV
) {
3280 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
3281 double sample_aspect_ratio
= av_q2d(st
->sample_aspect_ratio
);
3282 if (st
->sample_aspect_ratio
.num
&& 1.0 != sample_aspect_ratio
) {
3283 mov_write_tapt_tag(pb
, track
);
3286 if (is_clcp_track(track
) && st
->sample_aspect_ratio
.num
) {
3287 mov_write_tapt_tag(pb
, track
);
3290 mov_write_track_udta_tag(pb
, mov
, st
);
3291 track
->entry
= entry_backup
;
3292 track
->chunkCount
= chunk_backup
;
3293 return update_size(pb
, pos
);
3296 static int mov_write_iods_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
3298 int i
, has_audio
= 0, has_video
= 0;
3299 int64_t pos
= avio_tell(pb
);
3300 int audio_profile
= mov
->iods_audio_profile
;
3301 int video_profile
= mov
->iods_video_profile
;
3302 for (i
= 0; i
< mov
->nb_streams
; i
++) {
3303 if (mov
->tracks
[i
].entry
> 0 || mov
->flags
& FF_MOV_FLAG_EMPTY_MOOV
) {
3304 has_audio
|= mov
->tracks
[i
].par
->codec_type
== AVMEDIA_TYPE_AUDIO
;
3305 has_video
|= mov
->tracks
[i
].par
->codec_type
== AVMEDIA_TYPE_VIDEO
;
3308 if (audio_profile
< 0)
3309 audio_profile
= 0xFF - has_audio
;
3310 if (video_profile
< 0)
3311 video_profile
= 0xFF - has_video
;
3312 avio_wb32(pb
, 0x0); /* size */
3313 ffio_wfourcc(pb
, "iods");
3314 avio_wb32(pb
, 0); /* version & flags */
3315 put_descr(pb
, 0x10, 7);
3316 avio_wb16(pb
, 0x004f);
3319 avio_w8(pb
, audio_profile
);
3320 avio_w8(pb
, video_profile
);
3322 return update_size(pb
, pos
);
3325 static int mov_write_trex_tag(AVIOContext
*pb
, MOVTrack
*track
)
3327 avio_wb32(pb
, 0x20); /* size */
3328 ffio_wfourcc(pb
, "trex");
3329 avio_wb32(pb
, 0); /* version & flags */
3330 avio_wb32(pb
, track
->track_id
); /* track ID */
3331 avio_wb32(pb
, 1); /* default sample description index */
3332 avio_wb32(pb
, 0); /* default sample duration */
3333 avio_wb32(pb
, 0); /* default sample size */
3334 avio_wb32(pb
, 0); /* default sample flags */
3338 static int mov_write_mvex_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
3340 int64_t pos
= avio_tell(pb
);
3342 avio_wb32(pb
, 0x0); /* size */
3343 ffio_wfourcc(pb
, "mvex");
3344 for (i
= 0; i
< mov
->nb_streams
; i
++)
3345 mov_write_trex_tag(pb
, &mov
->tracks
[i
]);
3346 return update_size(pb
, pos
);
3349 static int mov_write_mvhd_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
3351 int max_track_id
= 1, i
;
3352 int64_t max_track_len
= 0;
3355 for (i
= 0; i
< mov
->nb_streams
; i
++) {
3356 if (mov
->tracks
[i
].entry
> 0 && mov
->tracks
[i
].timescale
) {
3357 int64_t max_track_len_temp
= av_rescale_rnd(
3358 calc_pts_duration(mov
, &mov
->tracks
[i
]),
3360 mov
->tracks
[i
].timescale
,
3362 if (max_track_len
< max_track_len_temp
)
3363 max_track_len
= max_track_len_temp
;
3364 if (max_track_id
< mov
->tracks
[i
].track_id
)
3365 max_track_id
= mov
->tracks
[i
].track_id
;
3368 /* If using delay_moov, make sure the output is the same as if no
3369 * samples had been written yet. */
3370 if (mov
->flags
& FF_MOV_FLAG_EMPTY_MOOV
) {
3375 version
= max_track_len
< UINT32_MAX
? 0 : 1;
3376 avio_wb32(pb
, version
== 1 ? 120 : 108); /* size */
3378 ffio_wfourcc(pb
, "mvhd");
3379 avio_w8(pb
, version
);
3380 avio_wb24(pb
, 0); /* flags */
3382 avio_wb64(pb
, mov
->time
);
3383 avio_wb64(pb
, mov
->time
);
3385 avio_wb32(pb
, mov
->time
); /* creation time */
3386 avio_wb32(pb
, mov
->time
); /* modification time */
3388 avio_wb32(pb
, MOV_TIMESCALE
);
3389 (version
== 1) ? avio_wb64(pb
, max_track_len
) : avio_wb32(pb
, max_track_len
); /* duration of longest track */
3391 avio_wb32(pb
, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
3392 avio_wb16(pb
, 0x0100); /* reserved (preferred volume) 1.0 = normal */
3393 avio_wb16(pb
, 0); /* reserved */
3394 avio_wb32(pb
, 0); /* reserved */
3395 avio_wb32(pb
, 0); /* reserved */
3397 /* Matrix structure */
3398 write_matrix(pb
, 1, 0, 0, 1, 0, 0);
3400 avio_wb32(pb
, 0); /* reserved (preview time) */
3401 avio_wb32(pb
, 0); /* reserved (preview duration) */
3402 avio_wb32(pb
, 0); /* reserved (poster time) */
3403 avio_wb32(pb
, 0); /* reserved (selection time) */
3404 avio_wb32(pb
, 0); /* reserved (selection duration) */
3405 avio_wb32(pb
, 0); /* reserved (current time) */
3406 avio_wb32(pb
, max_track_id
+ 1); /* Next track id */
3410 static int mov_write_itunes_hdlr_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3413 avio_wb32(pb
, 33); /* size */
3414 ffio_wfourcc(pb
, "hdlr");
3417 ffio_wfourcc(pb
, "mdir");
3418 ffio_wfourcc(pb
, "appl");
3425 /* helper function to write a data tag with the specified string as data */
3426 static int mov_write_string_data_tag(AVIOContext
*pb
, const char *data
, int lang
, int long_style
)
3429 int size
= 16 + strlen(data
);
3430 avio_wb32(pb
, size
); /* size */
3431 ffio_wfourcc(pb
, "data");
3434 avio_write(pb
, data
, strlen(data
));
3438 lang
= ff_mov_iso639_to_lang("und", 1);
3439 avio_wb16(pb
, strlen(data
)); /* string length */
3440 avio_wb16(pb
, lang
);
3441 avio_write(pb
, data
, strlen(data
));
3442 return strlen(data
) + 4;
3446 static int mov_write_string_tag(AVIOContext
*pb
, const char *name
,
3447 const char *value
, int lang
, int long_style
)
3450 if (value
&& value
[0]) {
3451 int64_t pos
= avio_tell(pb
);
3452 avio_wb32(pb
, 0); /* size */
3453 ffio_wfourcc(pb
, name
);
3454 mov_write_string_data_tag(pb
, value
, lang
, long_style
);
3455 size
= update_size(pb
, pos
);
3460 static AVDictionaryEntry
*get_metadata_lang(AVFormatContext
*s
,
3461 const char *tag
, int *lang
)
3464 AVDictionaryEntry
*t
, *t2
= NULL
;
3469 if (!(t
= av_dict_get(s
->metadata
, tag
, NULL
, 0)))
3472 len
= strlen(t
->key
);
3473 snprintf(tag2
, sizeof(tag2
), "%s-", tag
);
3474 while ((t2
= av_dict_get(s
->metadata
, tag2
, t2
, AV_DICT_IGNORE_SUFFIX
))) {
3475 len2
= strlen(t2
->key
);
3476 if (len2
== len
+ 4 && !strcmp(t
->value
, t2
->value
)
3477 && (l
= ff_mov_iso639_to_lang(&t2
->key
[len2
- 3], 1)) >= 0) {
3485 static int mov_write_string_metadata(AVFormatContext
*s
, AVIOContext
*pb
,
3486 const char *name
, const char *tag
,
3490 AVDictionaryEntry
*t
= get_metadata_lang(s
, tag
, &lang
);
3493 return mov_write_string_tag(pb
, name
, t
->value
, lang
, long_style
);
3496 /* iTunes bpm number */
3497 static int mov_write_tmpo_tag(AVIOContext
*pb
, AVFormatContext
*s
)
3499 AVDictionaryEntry
*t
= av_dict_get(s
->metadata
, "tmpo", NULL
, 0);
3500 int size
= 0, tmpo
= t
? atoi(t
->value
) : 0;
3503 avio_wb32(pb
, size
);
3504 ffio_wfourcc(pb
, "tmpo");
3505 avio_wb32(pb
, size
-8); /* size */
3506 ffio_wfourcc(pb
, "data");
3507 avio_wb32(pb
, 0x15); //type specifier
3509 avio_wb16(pb
, tmpo
); // data
3514 /* 3GPP TS 26.244 */
3515 static int mov_write_loci_tag(AVFormatContext
*s
, AVIOContext
*pb
)
3518 int64_t pos
= avio_tell(pb
);
3519 double latitude
, longitude
, altitude
;
3520 int32_t latitude_fix
, longitude_fix
, altitude_fix
;
3521 AVDictionaryEntry
*t
= get_metadata_lang(s
, "location", &lang
);
3522 const char *ptr
, *place
= "";
3524 static const char *astronomical_body
= "earth";
3529 longitude
= strtod(ptr
, &end
);
3531 av_log(s
, AV_LOG_WARNING
, "malformed location metadata\n");
3535 latitude
= strtod(ptr
, &end
);
3537 av_log(s
, AV_LOG_WARNING
, "malformed location metadata\n");
3541 altitude
= strtod(ptr
, &end
);
3542 /* If no altitude was present, the default 0 should be fine */
3546 latitude_fix
= (int32_t) ((1 << 16) * latitude
);
3547 longitude_fix
= (int32_t) ((1 << 16) * longitude
);
3548 altitude_fix
= (int32_t) ((1 << 16) * altitude
);
3550 avio_wb32(pb
, 0); /* size */
3551 ffio_wfourcc(pb
, "loci"); /* type */
3552 avio_wb32(pb
, 0); /* version + flags */
3553 avio_wb16(pb
, lang
);
3554 avio_write(pb
, place
, strlen(place
) + 1);
3555 avio_w8(pb
, 0); /* role of place (0 == shooting location, 1 == real location, 2 == fictional location) */
3556 avio_wb32(pb
, latitude_fix
);
3557 avio_wb32(pb
, longitude_fix
);
3558 avio_wb32(pb
, altitude_fix
);
3559 avio_write(pb
, astronomical_body
, strlen(astronomical_body
) + 1);
3560 avio_w8(pb
, 0); /* additional notes, null terminated string */
3562 return update_size(pb
, pos
);
3565 /* iTunes track or disc number */
3566 static int mov_write_trkn_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3567 AVFormatContext
*s
, int disc
)
3569 AVDictionaryEntry
*t
= av_dict_get(s
->metadata
,
3570 disc
? "disc" : "track",
3572 int size
= 0, track
= t
? atoi(t
->value
) : 0;
3575 char *slash
= strchr(t
->value
, '/');
3577 tracks
= atoi(slash
+ 1);
3578 avio_wb32(pb
, 32); /* size */
3579 ffio_wfourcc(pb
, disc
? "disk" : "trkn");
3580 avio_wb32(pb
, 24); /* size */
3581 ffio_wfourcc(pb
, "data");
3582 avio_wb32(pb
, 0); // 8 bytes empty
3584 avio_wb16(pb
, 0); // empty
3585 avio_wb16(pb
, track
); // track / disc number
3586 avio_wb16(pb
, tracks
); // total track / disc number
3587 avio_wb16(pb
, 0); // empty
3593 static int mov_write_int8_metadata(AVFormatContext
*s
, AVIOContext
*pb
,
3594 const char *name
, const char *tag
,
3597 AVDictionaryEntry
*t
= NULL
;
3599 int size
= 24 + len
;
3601 if (len
!= 1 && len
!= 4)
3604 if (!(t
= av_dict_get(s
->metadata
, tag
, NULL
, 0)))
3606 num
= atoi(t
->value
);
3608 avio_wb32(pb
, size
);
3609 ffio_wfourcc(pb
, name
);
3610 avio_wb32(pb
, size
- 8);
3611 ffio_wfourcc(pb
, "data");
3612 avio_wb32(pb
, 0x15);
3614 if (len
==4) avio_wb32(pb
, num
);
3615 else avio_w8 (pb
, num
);
3620 static int mov_write_covr(AVIOContext
*pb
, AVFormatContext
*s
)
3622 MOVMuxContext
*mov
= s
->priv_data
;
3626 for (i
= 0; i
< s
->nb_streams
; i
++) {
3627 MOVTrack
*trk
= &mov
->tracks
[i
];
3629 if (!is_cover_image(trk
->st
) || trk
->cover_image
.size
<= 0)
3633 pos
= avio_tell(pb
);
3635 ffio_wfourcc(pb
, "covr");
3637 avio_wb32(pb
, 16 + trk
->cover_image
.size
);
3638 ffio_wfourcc(pb
, "data");
3639 avio_wb32(pb
, trk
->tag
);
3641 avio_write(pb
, trk
->cover_image
.data
, trk
->cover_image
.size
);
3644 return pos
? update_size(pb
, pos
) : 0;
3647 /* iTunes meta data list */
3648 static int mov_write_ilst_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3651 int64_t pos
= avio_tell(pb
);
3652 avio_wb32(pb
, 0); /* size */
3653 ffio_wfourcc(pb
, "ilst");
3654 mov_write_string_metadata(s
, pb
, "\251nam", "title" , 1);
3655 mov_write_string_metadata(s
, pb
, "\251ART", "artist" , 1);
3656 mov_write_string_metadata(s
, pb
, "aART", "album_artist", 1);
3657 mov_write_string_metadata(s
, pb
, "\251wrt", "composer" , 1);
3658 mov_write_string_metadata(s
, pb
, "\251alb", "album" , 1);
3659 mov_write_string_metadata(s
, pb
, "\251day", "date" , 1);
3660 if (!mov_write_string_metadata(s
, pb
, "\251too", "encoding_tool", 1)) {
3661 if (!(s
->flags
& AVFMT_FLAG_BITEXACT
))
3662 mov_write_string_tag(pb
, "\251too", LIBAVFORMAT_IDENT
, 0, 1);
3664 mov_write_string_metadata(s
, pb
, "\251cmt", "comment" , 1);
3665 mov_write_string_metadata(s
, pb
, "\251gen", "genre" , 1);
3666 mov_write_string_metadata(s
, pb
, "cprt", "copyright", 1);
3667 mov_write_string_metadata(s
, pb
, "\251grp", "grouping" , 1);
3668 mov_write_string_metadata(s
, pb
, "\251lyr", "lyrics" , 1);
3669 mov_write_string_metadata(s
, pb
, "desc", "description",1);
3670 mov_write_string_metadata(s
, pb
, "ldes", "synopsis" , 1);
3671 mov_write_string_metadata(s
, pb
, "tvsh", "show" , 1);
3672 mov_write_string_metadata(s
, pb
, "tven", "episode_id",1);
3673 mov_write_string_metadata(s
, pb
, "tvnn", "network" , 1);
3674 mov_write_string_metadata(s
, pb
, "keyw", "keywords" , 1);
3675 mov_write_int8_metadata (s
, pb
, "tves", "episode_sort",4);
3676 mov_write_int8_metadata (s
, pb
, "tvsn", "season_number",4);
3677 mov_write_int8_metadata (s
, pb
, "stik", "media_type",1);
3678 mov_write_int8_metadata (s
, pb
, "hdvd", "hd_video", 1);
3679 mov_write_int8_metadata (s
, pb
, "pgap", "gapless_playback",1);
3680 mov_write_int8_metadata (s
, pb
, "cpil", "compilation", 1);
3681 mov_write_covr(pb
, s
);
3682 mov_write_trkn_tag(pb
, mov
, s
, 0); // track number
3683 mov_write_trkn_tag(pb
, mov
, s
, 1); // disc number
3684 mov_write_tmpo_tag(pb
, s
);
3685 return update_size(pb
, pos
);
3688 static int mov_write_mdta_hdlr_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3691 avio_wb32(pb
, 33); /* size */
3692 ffio_wfourcc(pb
, "hdlr");
3695 ffio_wfourcc(pb
, "mdta");
3703 static int mov_write_mdta_keys_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3706 AVDictionaryEntry
*t
= NULL
;
3707 int64_t pos
= avio_tell(pb
);
3708 int64_t curpos
, entry_pos
;
3711 avio_wb32(pb
, 0); /* size */
3712 ffio_wfourcc(pb
, "keys");
3714 entry_pos
= avio_tell(pb
);
3715 avio_wb32(pb
, 0); /* entry count */
3717 while (t
= av_dict_get(s
->metadata
, "", t
, AV_DICT_IGNORE_SUFFIX
)) {
3718 avio_wb32(pb
, strlen(t
->key
) + 8);
3719 ffio_wfourcc(pb
, "mdta");
3720 avio_write(pb
, t
->key
, strlen(t
->key
));
3723 curpos
= avio_tell(pb
);
3724 avio_seek(pb
, entry_pos
, SEEK_SET
);
3725 avio_wb32(pb
, count
); // rewrite entry count
3726 avio_seek(pb
, curpos
, SEEK_SET
);
3728 return update_size(pb
, pos
);
3731 static int mov_write_mdta_ilst_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3734 AVDictionaryEntry
*t
= NULL
;
3735 int64_t pos
= avio_tell(pb
);
3736 int count
= 1; /* keys are 1-index based */
3738 avio_wb32(pb
, 0); /* size */
3739 ffio_wfourcc(pb
, "ilst");
3741 while (t
= av_dict_get(s
->metadata
, "", t
, AV_DICT_IGNORE_SUFFIX
)) {
3742 int64_t entry_pos
= avio_tell(pb
);
3743 avio_wb32(pb
, 0); /* size */
3744 avio_wb32(pb
, count
); /* key */
3745 mov_write_string_data_tag(pb
, t
->value
, 0, 1);
3746 update_size(pb
, entry_pos
);
3749 return update_size(pb
, pos
);
3752 /* meta data tags */
3753 static int mov_write_meta_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3757 int64_t pos
= avio_tell(pb
);
3758 avio_wb32(pb
, 0); /* size */
3759 ffio_wfourcc(pb
, "meta");
3761 if (mov
->flags
& FF_MOV_FLAG_USE_MDTA
) {
3762 mov_write_mdta_hdlr_tag(pb
, mov
, s
);
3763 mov_write_mdta_keys_tag(pb
, mov
, s
);
3764 mov_write_mdta_ilst_tag(pb
, mov
, s
);
3767 /* iTunes metadata tag */
3768 mov_write_itunes_hdlr_tag(pb
, mov
, s
);
3769 mov_write_ilst_tag(pb
, mov
, s
);
3771 size
= update_size(pb
, pos
);
3775 static int mov_write_raw_metadata_tag(AVFormatContext
*s
, AVIOContext
*pb
,
3776 const char *name
, const char *key
)
3779 AVDictionaryEntry
*t
;
3781 if (!(t
= av_dict_get(s
->metadata
, key
, NULL
, 0)))
3784 len
= strlen(t
->value
);
3787 avio_wb32(pb
, size
);
3788 ffio_wfourcc(pb
, name
);
3789 avio_write(pb
, t
->value
, len
);
3795 static int ascii_to_wc(AVIOContext
*pb
, const uint8_t *b
)
3799 GET_UTF8(val
, *b
++, return -1;)
3802 avio_wb16(pb
, 0x00);
3806 static uint16_t language_code(const char *str
)
3808 return (((str
[0] - 0x60) & 0x1F) << 10) +
3809 (((str
[1] - 0x60) & 0x1F) << 5) +
3810 (( str
[2] - 0x60) & 0x1F);
3813 static int mov_write_3gp_udta_tag(AVIOContext
*pb
, AVFormatContext
*s
,
3814 const char *tag
, const char *str
)
3816 int64_t pos
= avio_tell(pb
);
3817 AVDictionaryEntry
*t
= av_dict_get(s
->metadata
, str
, NULL
, 0);
3818 if (!t
|| !utf8len(t
->value
))
3820 avio_wb32(pb
, 0); /* size */
3821 ffio_wfourcc(pb
, tag
); /* type */
3822 avio_wb32(pb
, 0); /* version + flags */
3823 if (!strcmp(tag
, "yrrc"))
3824 avio_wb16(pb
, atoi(t
->value
));
3826 avio_wb16(pb
, language_code("eng")); /* language */
3827 avio_write(pb
, t
->value
, strlen(t
->value
) + 1); /* UTF8 string value */
3828 if (!strcmp(tag
, "albm") &&
3829 (t
= av_dict_get(s
->metadata
, "track", NULL
, 0)))
3830 avio_w8(pb
, atoi(t
->value
));
3832 return update_size(pb
, pos
);
3835 static int mov_write_chpl_tag(AVIOContext
*pb
, AVFormatContext
*s
)
3837 int64_t pos
= avio_tell(pb
);
3838 int i
, nb_chapters
= FFMIN(s
->nb_chapters
, 255);
3840 avio_wb32(pb
, 0); // size
3841 ffio_wfourcc(pb
, "chpl");
3842 avio_wb32(pb
, 0x01000000); // version + flags
3843 avio_wb32(pb
, 0); // unknown
3844 avio_w8(pb
, nb_chapters
);
3846 for (i
= 0; i
< nb_chapters
; i
++) {
3847 AVChapter
*c
= s
->chapters
[i
];
3848 AVDictionaryEntry
*t
;
3849 avio_wb64(pb
, av_rescale_q(c
->start
, c
->time_base
, (AVRational
){1,10000000}));
3851 if ((t
= av_dict_get(c
->metadata
, "title", NULL
, 0))) {
3852 int len
= FFMIN(strlen(t
->value
), 255);
3854 avio_write(pb
, t
->value
, len
);
3858 return update_size(pb
, pos
);
3861 static int mov_write_udta_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3864 AVIOContext
*pb_buf
;
3868 ret
= avio_open_dyn_buf(&pb_buf
);
3872 if (mov
->mode
& MODE_3GP
) {
3873 mov_write_3gp_udta_tag(pb_buf
, s
, "perf", "artist");
3874 mov_write_3gp_udta_tag(pb_buf
, s
, "titl", "title");
3875 mov_write_3gp_udta_tag(pb_buf
, s
, "auth", "author");
3876 mov_write_3gp_udta_tag(pb_buf
, s
, "gnre", "genre");
3877 mov_write_3gp_udta_tag(pb_buf
, s
, "dscp", "comment");
3878 mov_write_3gp_udta_tag(pb_buf
, s
, "albm", "album");
3879 mov_write_3gp_udta_tag(pb_buf
, s
, "cprt", "copyright");
3880 mov_write_3gp_udta_tag(pb_buf
, s
, "yrrc", "date");
3881 mov_write_loci_tag(s
, pb_buf
);
3882 } else if (mov
->mode
== MODE_MOV
&& !(mov
->flags
& FF_MOV_FLAG_USE_MDTA
)) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4
3883 mov_write_string_metadata(s
, pb_buf
, "\251ART", "artist", 0);
3884 mov_write_string_metadata(s
, pb_buf
, "\251nam", "title", 0);
3885 mov_write_string_metadata(s
, pb_buf
, "\251aut", "author", 0);
3886 mov_write_string_metadata(s
, pb_buf
, "\251alb", "album", 0);
3887 mov_write_string_metadata(s
, pb_buf
, "\251day", "date", 0);
3888 mov_write_string_metadata(s
, pb_buf
, "\251swr", "encoder", 0);
3889 // currently ignored by mov.c
3890 mov_write_string_metadata(s
, pb_buf
, "\251des", "comment", 0);
3891 // add support for libquicktime, this atom is also actually read by mov.c
3892 mov_write_string_metadata(s
, pb_buf
, "\251cmt", "comment", 0);
3893 mov_write_string_metadata(s
, pb_buf
, "\251gen", "genre", 0);
3894 mov_write_string_metadata(s
, pb_buf
, "\251cpy", "copyright", 0);
3895 mov_write_string_metadata(s
, pb_buf
, "\251mak", "make", 0);
3896 mov_write_string_metadata(s
, pb_buf
, "\251mod", "model", 0);
3897 mov_write_string_metadata(s
, pb_buf
, "\251xyz", "location", 0);
3898 mov_write_string_metadata(s
, pb_buf
, "\251key", "keywords", 0);
3899 mov_write_raw_metadata_tag(s
, pb_buf
, "XMP_", "xmp");
3901 /* iTunes meta data */
3902 mov_write_meta_tag(pb_buf
, mov
, s
);
3903 mov_write_loci_tag(s
, pb_buf
);
3906 if (s
->nb_chapters
&& !(mov
->flags
& FF_MOV_FLAG_DISABLE_CHPL
))
3907 mov_write_chpl_tag(pb_buf
, s
);
3909 if ((size
= avio_get_dyn_buf(pb_buf
, &buf
)) > 0) {
3910 avio_wb32(pb
, size
+ 8);
3911 ffio_wfourcc(pb
, "udta");
3912 avio_write(pb
, buf
, size
);
3914 ffio_free_dyn_buf(&pb_buf
);
3919 static void mov_write_psp_udta_tag(AVIOContext
*pb
,
3920 const char *str
, const char *lang
, int type
)
3922 int len
= utf8len(str
) + 1;
3925 avio_wb16(pb
, len
* 2 + 10); /* size */
3926 avio_wb32(pb
, type
); /* type */
3927 avio_wb16(pb
, language_code(lang
)); /* language */
3928 avio_wb16(pb
, 0x01); /* ? */
3929 ascii_to_wc(pb
, str
);
3932 static int mov_write_uuidusmt_tag(AVIOContext
*pb
, AVFormatContext
*s
)
3934 AVDictionaryEntry
*title
= av_dict_get(s
->metadata
, "title", NULL
, 0);
3938 pos
= avio_tell(pb
);
3939 avio_wb32(pb
, 0); /* size placeholder*/
3940 ffio_wfourcc(pb
, "uuid");
3941 ffio_wfourcc(pb
, "USMT");
3942 avio_wb32(pb
, 0x21d24fce); /* 96 bit UUID */
3943 avio_wb32(pb
, 0xbb88695c);
3944 avio_wb32(pb
, 0xfac9c740);
3946 pos2
= avio_tell(pb
);
3947 avio_wb32(pb
, 0); /* size placeholder*/
3948 ffio_wfourcc(pb
, "MTDT");
3952 avio_wb16(pb
, 0x0C); /* size */
3953 avio_wb32(pb
, 0x0B); /* type */
3954 avio_wb16(pb
, language_code("und")); /* language */
3955 avio_wb16(pb
, 0x0); /* ? */
3956 avio_wb16(pb
, 0x021C); /* data */
3958 if (!(s
->flags
& AVFMT_FLAG_BITEXACT
))
3959 mov_write_psp_udta_tag(pb
, LIBAVCODEC_IDENT
, "eng", 0x04);
3960 mov_write_psp_udta_tag(pb
, title
->value
, "eng", 0x01);
3961 mov_write_psp_udta_tag(pb
, "2006/04/01 11:11:11", "und", 0x03);
3963 update_size(pb
, pos2
);
3964 return update_size(pb
, pos
);
3970 static void build_chunks(MOVTrack
*trk
)
3973 MOVIentry
*chunk
= &trk
->cluster
[0];
3974 uint64_t chunkSize
= chunk
->size
;
3975 chunk
->chunkNum
= 1;
3976 if (trk
->chunkCount
)
3978 trk
->chunkCount
= 1;
3979 for (i
= 1; i
<trk
->entry
; i
++){
3980 if (chunk
->pos
+ chunkSize
== trk
->cluster
[i
].pos
&&
3981 chunkSize
+ trk
->cluster
[i
].size
< (1<<20)){
3982 chunkSize
+= trk
->cluster
[i
].size
;
3983 chunk
->samples_in_chunk
+= trk
->cluster
[i
].entries
;
3985 trk
->cluster
[i
].chunkNum
= chunk
->chunkNum
+1;
3986 chunk
=&trk
->cluster
[i
];
3987 chunkSize
= chunk
->size
;
3994 * Assign track ids. If option "use_stream_ids_as_track_ids" is set,
3995 * the stream ids are used as track ids.
3997 * This assumes mov->tracks and s->streams are in the same order and
3998 * there are no gaps in either of them (so mov->tracks[n] refers to
4001 * As an exception, there can be more entries in
4002 * s->streams than in mov->tracks, in which case new track ids are
4003 * generated (starting after the largest found stream id).
4005 static int mov_setup_track_ids(MOVMuxContext
*mov
, AVFormatContext
*s
)
4009 if (mov
->track_ids_ok
)
4012 if (mov
->use_stream_ids_as_track_ids
) {
4013 int next_generated_track_id
= 0;
4014 for (i
= 0; i
< s
->nb_streams
; i
++) {
4015 if (s
->streams
[i
]->id
> next_generated_track_id
)
4016 next_generated_track_id
= s
->streams
[i
]->id
;
4019 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4020 if (mov
->tracks
[i
].entry
<= 0 && !(mov
->flags
& FF_MOV_FLAG_FRAGMENT
))
4023 mov
->tracks
[i
].track_id
= i
>= s
->nb_streams
? ++next_generated_track_id
: s
->streams
[i
]->id
;
4026 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4027 if (mov
->tracks
[i
].entry
<= 0 && !(mov
->flags
& FF_MOV_FLAG_FRAGMENT
))
4030 mov
->tracks
[i
].track_id
= i
+ 1;
4034 mov
->track_ids_ok
= 1;
4039 static int mov_write_moov_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
4043 int64_t pos
= avio_tell(pb
);
4044 avio_wb32(pb
, 0); /* size placeholder*/
4045 ffio_wfourcc(pb
, "moov");
4047 mov_setup_track_ids(mov
, s
);
4049 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4050 if (mov
->tracks
[i
].entry
<= 0 && !(mov
->flags
& FF_MOV_FLAG_FRAGMENT
))
4053 mov
->tracks
[i
].time
= mov
->time
;
4055 if (mov
->tracks
[i
].entry
)
4056 build_chunks(&mov
->tracks
[i
]);
4059 if (mov
->chapter_track
)
4060 for (i
= 0; i
< s
->nb_streams
; i
++) {
4061 mov
->tracks
[i
].tref_tag
= MKTAG('c','h','a','p');
4062 mov
->tracks
[i
].tref_id
= mov
->tracks
[mov
->chapter_track
].track_id
;
4064 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4065 MOVTrack
*track
= &mov
->tracks
[i
];
4066 if (track
->tag
== MKTAG('r','t','p',' ')) {
4067 track
->tref_tag
= MKTAG('h','i','n','t');
4068 track
->tref_id
= mov
->tracks
[track
->src_track
].track_id
;
4069 } else if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
4070 int * fallback
, size
;
4071 fallback
= (int*)av_stream_get_side_data(track
->st
,
4072 AV_PKT_DATA_FALLBACK_TRACK
,
4074 if (fallback
!= NULL
&& size
== sizeof(int)) {
4075 if (*fallback
>= 0 && *fallback
< mov
->nb_streams
) {
4076 track
->tref_tag
= MKTAG('f','a','l','l');
4077 track
->tref_id
= mov
->tracks
[*fallback
].track_id
;
4082 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4083 if (mov
->tracks
[i
].tag
== MKTAG('t','m','c','d')) {
4084 int src_trk
= mov
->tracks
[i
].src_track
;
4085 mov
->tracks
[src_trk
].tref_tag
= mov
->tracks
[i
].tag
;
4086 mov
->tracks
[src_trk
].tref_id
= mov
->tracks
[i
].track_id
;
4087 //src_trk may have a different timescale than the tmcd track
4088 mov
->tracks
[i
].track_duration
= av_rescale(mov
->tracks
[src_trk
].track_duration
,
4089 mov
->tracks
[i
].timescale
,
4090 mov
->tracks
[src_trk
].timescale
);
4094 mov_write_mvhd_tag(pb
, mov
);
4095 if (mov
->mode
!= MODE_MOV
&& !mov
->iods_skip
)
4096 mov_write_iods_tag(pb
, mov
);
4097 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4098 if (mov
->tracks
[i
].entry
> 0 || mov
->flags
& FF_MOV_FLAG_FRAGMENT
) {
4099 int ret
= mov_write_trak_tag(s
, pb
, mov
, &(mov
->tracks
[i
]), i
< s
->nb_streams
? s
->streams
[i
] : NULL
);
4104 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
)
4105 mov_write_mvex_tag(pb
, mov
); /* QuickTime requires trak to precede this */
4107 if (mov
->mode
== MODE_PSP
)
4108 mov_write_uuidusmt_tag(pb
, s
);
4110 mov_write_udta_tag(pb
, mov
, s
);
4112 return update_size(pb
, pos
);
4115 static void param_write_int(AVIOContext
*pb
, const char *name
, int value
)
4117 avio_printf(pb
, "<param name=\"%s\" value=\"%d\" valuetype=\"data\"/>\n", name
, value
);
4120 static void param_write_string(AVIOContext
*pb
, const char *name
, const char *value
)
4122 avio_printf(pb
, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name
, value
);
4125 static void param_write_hex(AVIOContext
*pb
, const char *name
, const uint8_t *value
, int len
)
4128 len
= FFMIN(sizeof(buf
) / 2 - 1, len
);
4129 ff_data_to_hex(buf
, value
, len
, 0);
4130 buf
[2 * len
] = '\0';
4131 avio_printf(pb
, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name
, buf
);
4134 static int mov_write_isml_manifest(AVIOContext
*pb
, MOVMuxContext
*mov
, AVFormatContext
*s
)
4136 int64_t pos
= avio_tell(pb
);
4138 int64_t manifest_bit_rate
= 0;
4139 AVCPBProperties
*props
= NULL
;
4141 static const uint8_t uuid
[] = {
4142 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
4143 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
4147 ffio_wfourcc(pb
, "uuid");
4148 avio_write(pb
, uuid
, sizeof(uuid
));
4151 avio_printf(pb
, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
4152 avio_printf(pb
, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
4153 avio_printf(pb
, "<head>\n");
4154 if (!(mov
->fc
->flags
& AVFMT_FLAG_BITEXACT
))
4155 avio_printf(pb
, "<meta name=\"creator\" content=\"%s\" />\n",
4157 avio_printf(pb
, "</head>\n");
4158 avio_printf(pb
, "<body>\n");
4159 avio_printf(pb
, "<switch>\n");
4161 mov_setup_track_ids(mov
, s
);
4163 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4164 MOVTrack
*track
= &mov
->tracks
[i
];
4166 int track_id
= track
->track_id
;
4167 char track_name_buf
[32] = { 0 };
4169 AVStream
*st
= track
->st
;
4170 AVDictionaryEntry
*lang
= av_dict_get(st
->metadata
, "language", NULL
,0);
4172 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
&& !is_cover_image(st
)) {
4174 } else if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
4180 props
= (AVCPBProperties
*)av_stream_get_side_data(track
->st
, AV_PKT_DATA_CPB_PROPERTIES
, NULL
);
4182 if (track
->par
->bit_rate
) {
4183 manifest_bit_rate
= track
->par
->bit_rate
;
4185 manifest_bit_rate
= props
->max_bitrate
;
4188 avio_printf(pb
, "<%s systemBitrate=\"%"PRId64
"\">\n", type
,
4190 param_write_int(pb
, "systemBitrate", manifest_bit_rate
);
4191 param_write_int(pb
, "trackID", track_id
);
4192 param_write_string(pb
, "systemLanguage", lang
? lang
->value
: "und");
4194 /* Build track name piece by piece: */
4196 av_strlcat(track_name_buf
, type
, sizeof(track_name_buf
));
4197 /* 2. track language, if available */
4199 av_strlcatf(track_name_buf
, sizeof(track_name_buf
),
4200 "_%s", lang
->value
);
4201 /* 3. special type suffix */
4202 /* "_cc" = closed captions, "_ad" = audio_description */
4203 if (st
->disposition
& AV_DISPOSITION_HEARING_IMPAIRED
)
4204 av_strlcat(track_name_buf
, "_cc", sizeof(track_name_buf
));
4205 else if (st
->disposition
& AV_DISPOSITION_VISUAL_IMPAIRED
)
4206 av_strlcat(track_name_buf
, "_ad", sizeof(track_name_buf
));
4208 param_write_string(pb
, "trackName", track_name_buf
);
4210 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
4211 if (track
->par
->codec_id
== AV_CODEC_ID_H264
) {
4213 int size
= track
->par
->extradata_size
;
4214 if (!ff_avc_write_annexb_extradata(track
->par
->extradata
, &ptr
,
4216 param_write_hex(pb
, "CodecPrivateData",
4217 ptr
? ptr
: track
->par
->extradata
,
4221 param_write_string(pb
, "FourCC", "H264");
4222 } else if (track
->par
->codec_id
== AV_CODEC_ID_VC1
) {
4223 param_write_string(pb
, "FourCC", "WVC1");
4224 param_write_hex(pb
, "CodecPrivateData", track
->par
->extradata
,
4225 track
->par
->extradata_size
);
4227 param_write_int(pb
, "MaxWidth", track
->par
->width
);
4228 param_write_int(pb
, "MaxHeight", track
->par
->height
);
4229 param_write_int(pb
, "DisplayWidth", track
->par
->width
);
4230 param_write_int(pb
, "DisplayHeight", track
->par
->height
);
4232 if (track
->par
->codec_id
== AV_CODEC_ID_AAC
) {
4233 switch (track
->par
->profile
)
4235 case FF_PROFILE_AAC_HE_V2
:
4236 param_write_string(pb
, "FourCC", "AACP");
4238 case FF_PROFILE_AAC_HE
:
4239 param_write_string(pb
, "FourCC", "AACH");
4242 param_write_string(pb
, "FourCC", "AACL");
4244 } else if (track
->par
->codec_id
== AV_CODEC_ID_WMAPRO
) {
4245 param_write_string(pb
, "FourCC", "WMAP");
4247 param_write_hex(pb
, "CodecPrivateData", track
->par
->extradata
,
4248 track
->par
->extradata_size
);
4249 param_write_int(pb
, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags
,
4250 track
->par
->codec_id
));
4251 param_write_int(pb
, "Channels", track
->par
->channels
);
4252 param_write_int(pb
, "SamplingRate", track
->par
->sample_rate
);
4253 param_write_int(pb
, "BitsPerSample", 16);
4254 param_write_int(pb
, "PacketSize", track
->par
->block_align
?
4255 track
->par
->block_align
: 4);
4257 avio_printf(pb
, "</%s>\n", type
);
4259 avio_printf(pb
, "</switch>\n");
4260 avio_printf(pb
, "</body>\n");
4261 avio_printf(pb
, "</smil>\n");
4263 return update_size(pb
, pos
);
4266 static int mov_write_mfhd_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
4269 ffio_wfourcc(pb
, "mfhd");
4271 avio_wb32(pb
, mov
->fragments
);
4275 static uint32_t get_sample_flags(MOVTrack
*track
, MOVIentry
*entry
)
4277 return entry
->flags
& MOV_SYNC_SAMPLE
? MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO
:
4278 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES
| MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC
);
4281 static int mov_write_tfhd_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
4282 MOVTrack
*track
, int64_t moof_offset
)
4284 int64_t pos
= avio_tell(pb
);
4285 uint32_t flags
= MOV_TFHD_DEFAULT_SIZE
| MOV_TFHD_DEFAULT_DURATION
|
4286 MOV_TFHD_BASE_DATA_OFFSET
;
4287 if (!track
->entry
) {
4288 flags
|= MOV_TFHD_DURATION_IS_EMPTY
;
4290 flags
|= MOV_TFHD_DEFAULT_FLAGS
;
4292 if (mov
->flags
& FF_MOV_FLAG_OMIT_TFHD_OFFSET
)
4293 flags
&= ~MOV_TFHD_BASE_DATA_OFFSET
;
4294 if (mov
->flags
& FF_MOV_FLAG_DEFAULT_BASE_MOOF
) {
4295 flags
&= ~MOV_TFHD_BASE_DATA_OFFSET
;
4296 flags
|= MOV_TFHD_DEFAULT_BASE_IS_MOOF
;
4298 /* CMAF requires all values to be explicit in tfhd atoms */
4299 if (mov
->flags
& FF_MOV_FLAG_CMAF
)
4300 flags
|= MOV_TFHD_STSD_ID
;
4302 /* Don't set a default sample size, the silverlight player refuses
4303 * to play files with that set. Don't set a default sample duration,
4304 * WMP freaks out if it is set. Don't set a base data offset, PIFF
4305 * file format says it MUST NOT be set. */
4306 if (track
->mode
== MODE_ISM
)
4307 flags
&= ~(MOV_TFHD_DEFAULT_SIZE
| MOV_TFHD_DEFAULT_DURATION
|
4308 MOV_TFHD_BASE_DATA_OFFSET
| MOV_TFHD_STSD_ID
);
4310 avio_wb32(pb
, 0); /* size placeholder */
4311 ffio_wfourcc(pb
, "tfhd");
4312 avio_w8(pb
, 0); /* version */
4313 avio_wb24(pb
, flags
);
4315 avio_wb32(pb
, track
->track_id
); /* track-id */
4316 if (flags
& MOV_TFHD_BASE_DATA_OFFSET
)
4317 avio_wb64(pb
, moof_offset
);
4318 if (flags
& MOV_TFHD_STSD_ID
) {
4321 if (flags
& MOV_TFHD_DEFAULT_DURATION
) {
4322 track
->default_duration
= get_cluster_duration(track
, 0);
4323 avio_wb32(pb
, track
->default_duration
);
4325 if (flags
& MOV_TFHD_DEFAULT_SIZE
) {
4326 track
->default_size
= track
->entry
? track
->cluster
[0].size
: 1;
4327 avio_wb32(pb
, track
->default_size
);
4329 track
->default_size
= -1;
4331 if (flags
& MOV_TFHD_DEFAULT_FLAGS
) {
4332 /* Set the default flags based on the second sample, if available.
4333 * If the first sample is different, that can be signaled via a separate field. */
4334 if (track
->entry
> 1)
4335 track
->default_sample_flags
= get_sample_flags(track
, &track
->cluster
[1]);
4337 track
->default_sample_flags
=
4338 track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
?
4339 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES
| MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC
) :
4340 MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO
;
4341 avio_wb32(pb
, track
->default_sample_flags
);
4344 return update_size(pb
, pos
);
4347 static int mov_write_trun_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
4348 MOVTrack
*track
, int moof_size
,
4351 int64_t pos
= avio_tell(pb
);
4352 uint32_t flags
= MOV_TRUN_DATA_OFFSET
;
4355 for (i
= first
; i
< end
; i
++) {
4356 if (get_cluster_duration(track
, i
) != track
->default_duration
)
4357 flags
|= MOV_TRUN_SAMPLE_DURATION
;
4358 if (track
->cluster
[i
].size
!= track
->default_size
)
4359 flags
|= MOV_TRUN_SAMPLE_SIZE
;
4360 if (i
> first
&& get_sample_flags(track
, &track
->cluster
[i
]) != track
->default_sample_flags
)
4361 flags
|= MOV_TRUN_SAMPLE_FLAGS
;
4363 if (!(flags
& MOV_TRUN_SAMPLE_FLAGS
) && track
->entry
> 0 &&
4364 get_sample_flags(track
, &track
->cluster
[0]) != track
->default_sample_flags
)
4365 flags
|= MOV_TRUN_FIRST_SAMPLE_FLAGS
;
4366 if (track
->flags
& MOV_TRACK_CTTS
)
4367 flags
|= MOV_TRUN_SAMPLE_CTS
;
4369 avio_wb32(pb
, 0); /* size placeholder */
4370 ffio_wfourcc(pb
, "trun");
4371 if (mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
)
4372 avio_w8(pb
, 1); /* version */
4374 avio_w8(pb
, 0); /* version */
4375 avio_wb24(pb
, flags
);
4377 avio_wb32(pb
, end
- first
); /* sample count */
4378 if (mov
->flags
& FF_MOV_FLAG_OMIT_TFHD_OFFSET
&&
4379 !(mov
->flags
& FF_MOV_FLAG_DEFAULT_BASE_MOOF
) &&
4381 avio_wb32(pb
, 0); /* Later tracks follow immediately after the previous one */
4383 avio_wb32(pb
, moof_size
+ 8 + track
->data_offset
+
4384 track
->cluster
[first
].pos
); /* data offset */
4385 if (flags
& MOV_TRUN_FIRST_SAMPLE_FLAGS
)
4386 avio_wb32(pb
, get_sample_flags(track
, &track
->cluster
[first
]));
4388 for (i
= first
; i
< end
; i
++) {
4389 if (flags
& MOV_TRUN_SAMPLE_DURATION
)
4390 avio_wb32(pb
, get_cluster_duration(track
, i
));
4391 if (flags
& MOV_TRUN_SAMPLE_SIZE
)
4392 avio_wb32(pb
, track
->cluster
[i
].size
);
4393 if (flags
& MOV_TRUN_SAMPLE_FLAGS
)
4394 avio_wb32(pb
, get_sample_flags(track
, &track
->cluster
[i
]));
4395 if (flags
& MOV_TRUN_SAMPLE_CTS
)
4396 avio_wb32(pb
, track
->cluster
[i
].cts
);
4399 mov
->first_trun
= 0;
4400 return update_size(pb
, pos
);
4403 static int mov_write_tfxd_tag(AVIOContext
*pb
, MOVTrack
*track
)
4405 int64_t pos
= avio_tell(pb
);
4406 static const uint8_t uuid
[] = {
4407 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
4408 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
4411 avio_wb32(pb
, 0); /* size placeholder */
4412 ffio_wfourcc(pb
, "uuid");
4413 avio_write(pb
, uuid
, sizeof(uuid
));
4416 avio_wb64(pb
, track
->start_dts
+ track
->frag_start
+
4417 track
->cluster
[0].cts
);
4418 avio_wb64(pb
, track
->end_pts
-
4419 (track
->cluster
[0].dts
+ track
->cluster
[0].cts
));
4421 return update_size(pb
, pos
);
4424 static int mov_write_tfrf_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
4425 MOVTrack
*track
, int entry
)
4427 int n
= track
->nb_frag_info
- 1 - entry
, i
;
4428 int size
= 8 + 16 + 4 + 1 + 16*n
;
4429 static const uint8_t uuid
[] = {
4430 0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95,
4431 0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f
4437 avio_seek(pb
, track
->frag_info
[entry
].tfrf_offset
, SEEK_SET
);
4438 avio_wb32(pb
, size
);
4439 ffio_wfourcc(pb
, "uuid");
4440 avio_write(pb
, uuid
, sizeof(uuid
));
4444 for (i
= 0; i
< n
; i
++) {
4445 int index
= entry
+ 1 + i
;
4446 avio_wb64(pb
, track
->frag_info
[index
].time
);
4447 avio_wb64(pb
, track
->frag_info
[index
].duration
);
4449 if (n
< mov
->ism_lookahead
) {
4450 int free_size
= 16 * (mov
->ism_lookahead
- n
);
4451 avio_wb32(pb
, free_size
);
4452 ffio_wfourcc(pb
, "free");
4453 ffio_fill(pb
, 0, free_size
- 8);
4459 static int mov_write_tfrf_tags(AVIOContext
*pb
, MOVMuxContext
*mov
,
4462 int64_t pos
= avio_tell(pb
);
4464 for (i
= 0; i
< mov
->ism_lookahead
; i
++) {
4465 /* Update the tfrf tag for the last ism_lookahead fragments,
4466 * nb_frag_info - 1 is the next fragment to be written. */
4467 mov_write_tfrf_tag(pb
, mov
, track
, track
->nb_frag_info
- 2 - i
);
4469 avio_seek(pb
, pos
, SEEK_SET
);
4473 static int mov_add_tfra_entries(AVIOContext
*pb
, MOVMuxContext
*mov
, int tracks
,
4477 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4478 MOVTrack
*track
= &mov
->tracks
[i
];
4479 MOVFragmentInfo
*info
;
4480 if ((tracks
>= 0 && i
!= tracks
) || !track
->entry
)
4482 track
->nb_frag_info
++;
4483 if (track
->nb_frag_info
>= track
->frag_info_capacity
) {
4484 unsigned new_capacity
= track
->nb_frag_info
+ MOV_FRAG_INFO_ALLOC_INCREMENT
;
4485 if (av_reallocp_array(&track
->frag_info
,
4487 sizeof(*track
->frag_info
)))
4488 return AVERROR(ENOMEM
);
4489 track
->frag_info_capacity
= new_capacity
;
4491 info
= &track
->frag_info
[track
->nb_frag_info
- 1];
4492 info
->offset
= avio_tell(pb
);
4494 // Try to recreate the original pts for the first packet
4495 // from the fields we have stored
4496 info
->time
= track
->start_dts
+ track
->frag_start
+
4497 track
->cluster
[0].cts
;
4498 info
->duration
= track
->end_pts
-
4499 (track
->cluster
[0].dts
+ track
->cluster
[0].cts
);
4500 // If the pts is less than zero, we will have trimmed
4501 // away parts of the media track using an edit list,
4502 // and the corresponding start presentation time is zero.
4503 if (info
->time
< 0) {
4504 info
->duration
+= info
->time
;
4507 info
->tfrf_offset
= 0;
4508 mov_write_tfrf_tags(pb
, mov
, track
);
4513 static void mov_prune_frag_info(MOVMuxContext
*mov
, int tracks
, int max
)
4516 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4517 MOVTrack
*track
= &mov
->tracks
[i
];
4518 if ((tracks
>= 0 && i
!= tracks
) || !track
->entry
)
4520 if (track
->nb_frag_info
> max
) {
4521 memmove(track
->frag_info
, track
->frag_info
+ (track
->nb_frag_info
- max
), max
* sizeof(*track
->frag_info
));
4522 track
->nb_frag_info
= max
;
4527 static int mov_write_tfdt_tag(AVIOContext
*pb
, MOVTrack
*track
)
4529 int64_t pos
= avio_tell(pb
);
4531 avio_wb32(pb
, 0); /* size */
4532 ffio_wfourcc(pb
, "tfdt");
4533 avio_w8(pb
, 1); /* version */
4535 avio_wb64(pb
, track
->frag_start
);
4536 return update_size(pb
, pos
);
4539 static int mov_write_traf_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
4540 MOVTrack
*track
, int64_t moof_offset
,
4543 int64_t pos
= avio_tell(pb
);
4545 avio_wb32(pb
, 0); /* size placeholder */
4546 ffio_wfourcc(pb
, "traf");
4548 mov_write_tfhd_tag(pb
, mov
, track
, moof_offset
);
4549 if (mov
->mode
!= MODE_ISM
)
4550 mov_write_tfdt_tag(pb
, track
);
4551 for (i
= 1; i
< track
->entry
; i
++) {
4552 if (track
->cluster
[i
].pos
!= track
->cluster
[i
- 1].pos
+ track
->cluster
[i
- 1].size
) {
4553 mov_write_trun_tag(pb
, mov
, track
, moof_size
, start
, i
);
4557 mov_write_trun_tag(pb
, mov
, track
, moof_size
, start
, track
->entry
);
4558 if (mov
->mode
== MODE_ISM
) {
4559 mov_write_tfxd_tag(pb
, track
);
4561 if (mov
->ism_lookahead
) {
4562 int i
, size
= 16 + 4 + 1 + 16 * mov
->ism_lookahead
;
4564 if (track
->nb_frag_info
> 0) {
4565 MOVFragmentInfo
*info
= &track
->frag_info
[track
->nb_frag_info
- 1];
4566 if (!info
->tfrf_offset
)
4567 info
->tfrf_offset
= avio_tell(pb
);
4569 avio_wb32(pb
, 8 + size
);
4570 ffio_wfourcc(pb
, "free");
4571 for (i
= 0; i
< size
; i
++)
4576 return update_size(pb
, pos
);
4579 static int mov_write_moof_tag_internal(AVIOContext
*pb
, MOVMuxContext
*mov
,
4580 int tracks
, int moof_size
)
4582 int64_t pos
= avio_tell(pb
);
4585 avio_wb32(pb
, 0); /* size placeholder */
4586 ffio_wfourcc(pb
, "moof");
4587 mov
->first_trun
= 1;
4589 mov_write_mfhd_tag(pb
, mov
);
4590 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4591 MOVTrack
*track
= &mov
->tracks
[i
];
4592 if (tracks
>= 0 && i
!= tracks
)
4596 mov_write_traf_tag(pb
, mov
, track
, pos
, moof_size
);
4599 return update_size(pb
, pos
);
4602 static int mov_write_sidx_tag(AVIOContext
*pb
,
4603 MOVTrack
*track
, int ref_size
, int total_sidx_size
)
4605 int64_t pos
= avio_tell(pb
), offset_pos
, end_pos
;
4606 int64_t presentation_time
, duration
, offset
;
4607 unsigned starts_with_SAP
;
4612 presentation_time
= track
->start_dts
+ track
->frag_start
+
4613 track
->cluster
[0].cts
;
4614 duration
= track
->end_pts
-
4615 (track
->cluster
[0].dts
+ track
->cluster
[0].cts
);
4616 starts_with_SAP
= track
->cluster
[0].flags
& MOV_SYNC_SAMPLE
;
4618 // pts<0 should be cut away using edts
4619 if (presentation_time
< 0) {
4620 duration
+= presentation_time
;
4621 presentation_time
= 0;
4624 entries
= track
->nb_frag_info
;
4627 presentation_time
= track
->frag_info
[0].time
;
4630 avio_wb32(pb
, 0); /* size */
4631 ffio_wfourcc(pb
, "sidx");
4632 avio_w8(pb
, 1); /* version */
4634 avio_wb32(pb
, track
->track_id
); /* reference_ID */
4635 avio_wb32(pb
, track
->timescale
); /* timescale */
4636 avio_wb64(pb
, presentation_time
); /* earliest_presentation_time */
4637 offset_pos
= avio_tell(pb
);
4638 avio_wb64(pb
, 0); /* first_offset (offset to referenced moof) */
4639 avio_wb16(pb
, 0); /* reserved */
4641 avio_wb16(pb
, entries
); /* reference_count */
4642 for (i
= 0; i
< entries
; i
++) {
4643 if (!track
->entry
) {
4644 if (i
> 1 && track
->frag_info
[i
].offset
!= track
->frag_info
[i
- 1].offset
+ track
->frag_info
[i
- 1].size
) {
4645 av_log(NULL
, AV_LOG_ERROR
, "Non-consecutive fragments, writing incorrect sidx\n");
4647 duration
= track
->frag_info
[i
].duration
;
4648 ref_size
= track
->frag_info
[i
].size
;
4649 starts_with_SAP
= 1;
4651 avio_wb32(pb
, (0 << 31) | (ref_size
& 0x7fffffff)); /* reference_type (0 = media) | referenced_size */
4652 avio_wb32(pb
, duration
); /* subsegment_duration */
4653 avio_wb32(pb
, (starts_with_SAP
<< 31) | (0 << 28) | 0); /* starts_with_SAP | SAP_type | SAP_delta_time */
4656 end_pos
= avio_tell(pb
);
4657 offset
= pos
+ total_sidx_size
- end_pos
;
4658 avio_seek(pb
, offset_pos
, SEEK_SET
);
4659 avio_wb64(pb
, offset
);
4660 avio_seek(pb
, end_pos
, SEEK_SET
);
4661 return update_size(pb
, pos
);
4664 static int mov_write_sidx_tags(AVIOContext
*pb
, MOVMuxContext
*mov
,
4665 int tracks
, int ref_size
)
4668 AVIOContext
*avio_buf
;
4670 for (round
= 0; round
< 2; round
++) {
4671 // First run one round to calculate the total size of all
4673 // This would be much simpler if we'd only write one sidx
4674 // atom, for the first track in the moof.
4676 if ((ret
= ffio_open_null_buf(&avio_buf
)) < 0)
4681 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4682 MOVTrack
*track
= &mov
->tracks
[i
];
4683 if (tracks
>= 0 && i
!= tracks
)
4685 // When writing a sidx for the full file, entry is 0, but
4686 // we want to include all tracks. ref_size is 0 in this case,
4687 // since we read it from frag_info instead.
4688 if (!track
->entry
&& ref_size
> 0)
4690 total_size
-= mov_write_sidx_tag(avio_buf
, track
, ref_size
,
4694 total_size
= ffio_close_null_buf(avio_buf
);
4699 static int mov_write_prft_tag(AVIOContext
*pb
, MOVMuxContext
*mov
, int tracks
)
4701 int64_t pos
= avio_tell(pb
), pts_us
, ntp_ts
;
4702 MOVTrack
*first_track
;
4705 /* PRFT should be associated with at most one track. So, choosing only the
4709 first_track
= &(mov
->tracks
[0]);
4711 if (!first_track
->entry
) {
4712 av_log(mov
->fc
, AV_LOG_WARNING
, "Unable to write PRFT, no entries in the track\n");
4716 if (first_track
->cluster
[0].pts
== AV_NOPTS_VALUE
) {
4717 av_log(mov
->fc
, AV_LOG_WARNING
, "Unable to write PRFT, first PTS is invalid\n");
4721 if (mov
->write_prft
== MOV_PRFT_SRC_WALLCLOCK
) {
4722 if (first_track
->cluster
[0].prft
.wallclock
) {
4723 /* Round the NTP time to whole milliseconds. */
4724 ntp_ts
= ff_get_formatted_ntp_time((first_track
->cluster
[0].prft
.wallclock
/ 1000) * 1000 +
4726 flags
= first_track
->cluster
[0].prft
.flags
;
4728 ntp_ts
= ff_get_formatted_ntp_time(ff_ntp_time());
4729 } else if (mov
->write_prft
== MOV_PRFT_SRC_PTS
) {
4730 pts_us
= av_rescale_q(first_track
->cluster
[0].pts
,
4731 first_track
->st
->time_base
, AV_TIME_BASE_Q
);
4732 ntp_ts
= ff_get_formatted_ntp_time(pts_us
+ NTP_OFFSET_US
);
4734 av_log(mov
->fc
, AV_LOG_WARNING
, "Unsupported PRFT box configuration: %d\n",
4739 avio_wb32(pb
, 0); // Size place holder
4740 ffio_wfourcc(pb
, "prft"); // Type
4741 avio_w8(pb
, 1); // Version
4742 avio_wb24(pb
, flags
); // Flags
4743 avio_wb32(pb
, first_track
->track_id
); // reference track ID
4744 avio_wb64(pb
, ntp_ts
); // NTP time stamp
4745 avio_wb64(pb
, first_track
->cluster
[0].pts
); //media time
4746 return update_size(pb
, pos
);
4749 static int mov_write_moof_tag(AVIOContext
*pb
, MOVMuxContext
*mov
, int tracks
,
4752 AVIOContext
*avio_buf
;
4755 if ((ret
= ffio_open_null_buf(&avio_buf
)) < 0)
4757 mov_write_moof_tag_internal(avio_buf
, mov
, tracks
, 0);
4758 moof_size
= ffio_close_null_buf(avio_buf
);
4760 if (mov
->flags
& FF_MOV_FLAG_DASH
&&
4761 !(mov
->flags
& (FF_MOV_FLAG_GLOBAL_SIDX
| FF_MOV_FLAG_SKIP_SIDX
)))
4762 mov_write_sidx_tags(pb
, mov
, tracks
, moof_size
+ 8 + mdat_size
);
4764 if (mov
->write_prft
> MOV_PRFT_NONE
&& mov
->write_prft
< MOV_PRFT_NB
)
4765 mov_write_prft_tag(pb
, mov
, tracks
);
4767 if (mov
->flags
& FF_MOV_FLAG_GLOBAL_SIDX
||
4768 !(mov
->flags
& FF_MOV_FLAG_SKIP_TRAILER
) ||
4769 mov
->ism_lookahead
) {
4770 if ((ret
= mov_add_tfra_entries(pb
, mov
, tracks
, moof_size
+ 8 + mdat_size
)) < 0)
4772 if (!(mov
->flags
& FF_MOV_FLAG_GLOBAL_SIDX
) &&
4773 mov
->flags
& FF_MOV_FLAG_SKIP_TRAILER
) {
4774 mov_prune_frag_info(mov
, tracks
, mov
->ism_lookahead
+ 1);
4778 return mov_write_moof_tag_internal(pb
, mov
, tracks
, moof_size
);
4781 static int mov_write_tfra_tag(AVIOContext
*pb
, MOVTrack
*track
)
4783 int64_t pos
= avio_tell(pb
);
4786 avio_wb32(pb
, 0); /* size placeholder */
4787 ffio_wfourcc(pb
, "tfra");
4788 avio_w8(pb
, 1); /* version */
4791 avio_wb32(pb
, track
->track_id
);
4792 avio_wb32(pb
, 0); /* length of traf/trun/sample num */
4793 avio_wb32(pb
, track
->nb_frag_info
);
4794 for (i
= 0; i
< track
->nb_frag_info
; i
++) {
4795 avio_wb64(pb
, track
->frag_info
[i
].time
);
4796 avio_wb64(pb
, track
->frag_info
[i
].offset
+ track
->data_offset
);
4797 avio_w8(pb
, 1); /* traf number */
4798 avio_w8(pb
, 1); /* trun number */
4799 avio_w8(pb
, 1); /* sample number */
4802 return update_size(pb
, pos
);
4805 static int mov_write_mfra_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
4807 int64_t pos
= avio_tell(pb
);
4810 avio_wb32(pb
, 0); /* size placeholder */
4811 ffio_wfourcc(pb
, "mfra");
4812 /* An empty mfra atom is enough to indicate to the publishing point that
4813 * the stream has ended. */
4814 if (mov
->flags
& FF_MOV_FLAG_ISML
)
4815 return update_size(pb
, pos
);
4817 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4818 MOVTrack
*track
= &mov
->tracks
[i
];
4819 if (track
->nb_frag_info
)
4820 mov_write_tfra_tag(pb
, track
);
4824 ffio_wfourcc(pb
, "mfro");
4825 avio_wb32(pb
, 0); /* version + flags */
4826 avio_wb32(pb
, avio_tell(pb
) + 4 - pos
);
4828 return update_size(pb
, pos
);
4831 static int mov_write_mdat_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
4833 avio_wb32(pb
, 8); // placeholder for extended size field (64 bit)
4834 ffio_wfourcc(pb
, mov
->mode
== MODE_MOV
? "wide" : "free");
4836 mov
->mdat_pos
= avio_tell(pb
);
4837 avio_wb32(pb
, 0); /* size placeholder*/
4838 ffio_wfourcc(pb
, "mdat");
4842 static void mov_write_ftyp_tag_internal(AVIOContext
*pb
, AVFormatContext
*s
,
4843 int has_h264
, int has_video
, int write_minor
)
4845 MOVMuxContext
*mov
= s
->priv_data
;
4848 if (mov
->major_brand
&& strlen(mov
->major_brand
) >= 4)
4849 ffio_wfourcc(pb
, mov
->major_brand
);
4850 else if (mov
->mode
== MODE_3GP
) {
4851 ffio_wfourcc(pb
, has_h264
? "3gp6" : "3gp4");
4852 minor
= has_h264
? 0x100 : 0x200;
4853 } else if (mov
->mode
& MODE_3G2
) {
4854 ffio_wfourcc(pb
, has_h264
? "3g2b" : "3g2a");
4855 minor
= has_h264
? 0x20000 : 0x10000;
4856 } else if (mov
->mode
== MODE_PSP
)
4857 ffio_wfourcc(pb
, "MSNV");
4858 else if (mov
->mode
== MODE_MP4
&& mov
->flags
& FF_MOV_FLAG_FRAGMENT
&&
4859 mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
)
4860 ffio_wfourcc(pb
, "iso6"); // Required when using signed CTS offsets in trun boxes
4861 else if (mov
->mode
== MODE_MP4
&& mov
->flags
& FF_MOV_FLAG_DEFAULT_BASE_MOOF
)
4862 ffio_wfourcc(pb
, "iso5"); // Required when using default-base-is-moof
4863 else if (mov
->mode
== MODE_MP4
&& mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
)
4864 ffio_wfourcc(pb
, "iso4");
4865 else if (mov
->mode
== MODE_MP4
)
4866 ffio_wfourcc(pb
, "isom");
4867 else if (mov
->mode
== MODE_IPOD
)
4868 ffio_wfourcc(pb
, has_video
? "M4V ":"M4A ");
4869 else if (mov
->mode
== MODE_ISM
)
4870 ffio_wfourcc(pb
, "isml");
4871 else if (mov
->mode
== MODE_F4V
)
4872 ffio_wfourcc(pb
, "f4v ");
4874 ffio_wfourcc(pb
, "qt ");
4877 avio_wb32(pb
, minor
);
4880 static int mov_write_ftyp_tag(AVIOContext
*pb
, AVFormatContext
*s
)
4882 MOVMuxContext
*mov
= s
->priv_data
;
4883 int64_t pos
= avio_tell(pb
);
4884 int has_h264
= 0, has_video
= 0;
4887 for (i
= 0; i
< s
->nb_streams
; i
++) {
4888 AVStream
*st
= s
->streams
[i
];
4889 if (is_cover_image(st
))
4891 if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
)
4893 if (st
->codecpar
->codec_id
== AV_CODEC_ID_H264
)
4897 avio_wb32(pb
, 0); /* size */
4898 ffio_wfourcc(pb
, "ftyp");
4900 // Write major brand
4901 mov_write_ftyp_tag_internal(pb
, s
, has_h264
, has_video
, 1);
4902 // Write the major brand as the first compatible brand as well
4903 mov_write_ftyp_tag_internal(pb
, s
, has_h264
, has_video
, 0);
4905 // Write compatible brands, ensuring that we don't write the major brand as a
4906 // compatible brand a second time.
4907 if (mov
->mode
== MODE_ISM
) {
4908 ffio_wfourcc(pb
, "piff");
4909 } else if (mov
->mode
!= MODE_MOV
) {
4910 // We add tfdt atoms when fragmenting, signal this with the iso6 compatible
4911 // brand, if not already the major brand. This is compatible with users that
4912 // don't understand tfdt.
4913 if (mov
->mode
== MODE_MP4
) {
4914 if (mov
->flags
& FF_MOV_FLAG_CMAF
)
4915 ffio_wfourcc(pb
, "cmfc");
4916 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
&& !(mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
))
4917 ffio_wfourcc(pb
, "iso6");
4919 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
)
4920 ffio_wfourcc(pb
, "iso6");
4921 if (mov
->flags
& FF_MOV_FLAG_DEFAULT_BASE_MOOF
)
4922 ffio_wfourcc(pb
, "iso5");
4923 else if (mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
)
4924 ffio_wfourcc(pb
, "iso4");
4926 // Brands prior to iso5 can't be signaled when using default-base-is-moof
4927 if (!(mov
->flags
& FF_MOV_FLAG_DEFAULT_BASE_MOOF
)) {
4928 // write isom for mp4 only if it it's not the major brand already.
4929 if (mov
->mode
!= MODE_MP4
|| mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
)
4930 ffio_wfourcc(pb
, "isom");
4931 ffio_wfourcc(pb
, "iso2");
4933 ffio_wfourcc(pb
, "avc1");
4937 if (mov
->mode
== MODE_MP4
)
4938 ffio_wfourcc(pb
, "mp41");
4940 if (mov
->flags
& FF_MOV_FLAG_DASH
&& mov
->flags
& FF_MOV_FLAG_GLOBAL_SIDX
)
4941 ffio_wfourcc(pb
, "dash");
4943 return update_size(pb
, pos
);
4946 static int mov_write_uuidprof_tag(AVIOContext
*pb
, AVFormatContext
*s
)
4948 AVStream
*video_st
= s
->streams
[0];
4949 AVCodecParameters
*video_par
= s
->streams
[0]->codecpar
;
4950 AVCodecParameters
*audio_par
= s
->streams
[1]->codecpar
;
4951 int audio_rate
= audio_par
->sample_rate
;
4952 int64_t frame_rate
= video_st
->avg_frame_rate
.den
?
4953 (video_st
->avg_frame_rate
.num
* 0x10000LL
) / video_st
->avg_frame_rate
.den
:
4955 int audio_kbitrate
= audio_par
->bit_rate
/ 1000;
4956 int video_kbitrate
= FFMIN(video_par
->bit_rate
/ 1000, 800 - audio_kbitrate
);
4958 if (frame_rate
< 0 || frame_rate
> INT32_MAX
) {
4959 av_log(s
, AV_LOG_ERROR
, "Frame rate %f outside supported range\n", frame_rate
/ (double)0x10000);
4960 return AVERROR(EINVAL
);
4963 avio_wb32(pb
, 0x94); /* size */
4964 ffio_wfourcc(pb
, "uuid");
4965 ffio_wfourcc(pb
, "PROF");
4967 avio_wb32(pb
, 0x21d24fce); /* 96 bit UUID */
4968 avio_wb32(pb
, 0xbb88695c);
4969 avio_wb32(pb
, 0xfac9c740);
4971 avio_wb32(pb
, 0x0); /* ? */
4972 avio_wb32(pb
, 0x3); /* 3 sections ? */
4974 avio_wb32(pb
, 0x14); /* size */
4975 ffio_wfourcc(pb
, "FPRF");
4976 avio_wb32(pb
, 0x0); /* ? */
4977 avio_wb32(pb
, 0x0); /* ? */
4978 avio_wb32(pb
, 0x0); /* ? */
4980 avio_wb32(pb
, 0x2c); /* size */
4981 ffio_wfourcc(pb
, "APRF"); /* audio */
4983 avio_wb32(pb
, 0x2); /* TrackID */
4984 ffio_wfourcc(pb
, "mp4a");
4985 avio_wb32(pb
, 0x20f);
4987 avio_wb32(pb
, audio_kbitrate
);
4988 avio_wb32(pb
, audio_kbitrate
);
4989 avio_wb32(pb
, audio_rate
);
4990 avio_wb32(pb
, audio_par
->channels
);
4992 avio_wb32(pb
, 0x34); /* size */
4993 ffio_wfourcc(pb
, "VPRF"); /* video */
4995 avio_wb32(pb
, 0x1); /* TrackID */
4996 if (video_par
->codec_id
== AV_CODEC_ID_H264
) {
4997 ffio_wfourcc(pb
, "avc1");
4998 avio_wb16(pb
, 0x014D);
4999 avio_wb16(pb
, 0x0015);
5001 ffio_wfourcc(pb
, "mp4v");
5002 avio_wb16(pb
, 0x0000);
5003 avio_wb16(pb
, 0x0103);
5006 avio_wb32(pb
, video_kbitrate
);
5007 avio_wb32(pb
, video_kbitrate
);
5008 avio_wb32(pb
, frame_rate
);
5009 avio_wb32(pb
, frame_rate
);
5010 avio_wb16(pb
, video_par
->width
);
5011 avio_wb16(pb
, video_par
->height
);
5012 avio_wb32(pb
, 0x010001); /* ? */
5017 static int mov_write_identification(AVIOContext
*pb
, AVFormatContext
*s
)
5019 MOVMuxContext
*mov
= s
->priv_data
;
5022 mov_write_ftyp_tag(pb
,s
);
5023 if (mov
->mode
== MODE_PSP
) {
5024 int video_streams_nb
= 0, audio_streams_nb
= 0, other_streams_nb
= 0;
5025 for (i
= 0; i
< s
->nb_streams
; i
++) {
5026 AVStream
*st
= s
->streams
[i
];
5027 if (is_cover_image(st
))
5029 if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
)
5031 else if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_AUDIO
)
5037 if (video_streams_nb
!= 1 || audio_streams_nb
!= 1 || other_streams_nb
) {
5038 av_log(s
, AV_LOG_ERROR
, "PSP mode need one video and one audio stream\n");
5039 return AVERROR(EINVAL
);
5041 return mov_write_uuidprof_tag(pb
, s
);
5046 static int mov_parse_mpeg2_frame(AVPacket
*pkt
, uint32_t *flags
)
5049 int i
, closed_gop
= 0;
5051 for (i
= 0; i
< pkt
->size
- 4; i
++) {
5052 c
= (c
<< 8) + pkt
->data
[i
];
5053 if (c
== 0x1b8) { // gop
5054 closed_gop
= pkt
->data
[i
+ 4] >> 6 & 0x01;
5055 } else if (c
== 0x100) { // pic
5056 int temp_ref
= (pkt
->data
[i
+ 1] << 2) | (pkt
->data
[i
+ 2] >> 6);
5057 if (!temp_ref
|| closed_gop
) // I picture is not reordered
5058 *flags
= MOV_SYNC_SAMPLE
;
5060 *flags
= MOV_PARTIAL_SYNC_SAMPLE
;
5067 static void mov_parse_vc1_frame(AVPacket
*pkt
, MOVTrack
*trk
)
5069 const uint8_t *start
, *next
, *end
= pkt
->data
+ pkt
->size
;
5070 int seq
= 0, entry
= 0;
5071 int key
= pkt
->flags
& AV_PKT_FLAG_KEY
;
5072 start
= find_next_marker(pkt
->data
, end
);
5073 for (next
= start
; next
< end
; start
= next
) {
5074 next
= find_next_marker(start
+ 4, end
);
5075 switch (AV_RB32(start
)) {
5076 case VC1_CODE_SEQHDR
:
5079 case VC1_CODE_ENTRYPOINT
:
5082 case VC1_CODE_SLICE
:
5083 trk
->vc1_info
.slices
= 1;
5087 if (!trk
->entry
&& trk
->vc1_info
.first_packet_seen
)
5088 trk
->vc1_info
.first_frag_written
= 1;
5089 if (!trk
->entry
&& !trk
->vc1_info
.first_frag_written
) {
5090 /* First packet in first fragment */
5091 trk
->vc1_info
.first_packet_seq
= seq
;
5092 trk
->vc1_info
.first_packet_entry
= entry
;
5093 trk
->vc1_info
.first_packet_seen
= 1;
5094 } else if ((seq
&& !trk
->vc1_info
.packet_seq
) ||
5095 (entry
&& !trk
->vc1_info
.packet_entry
)) {
5097 for (i
= 0; i
< trk
->entry
; i
++)
5098 trk
->cluster
[i
].flags
&= ~MOV_SYNC_SAMPLE
;
5099 trk
->has_keyframes
= 0;
5101 trk
->vc1_info
.packet_seq
= 1;
5103 trk
->vc1_info
.packet_entry
= 1;
5104 if (!trk
->vc1_info
.first_frag_written
) {
5105 /* First fragment */
5106 if ((!seq
|| trk
->vc1_info
.first_packet_seq
) &&
5107 (!entry
|| trk
->vc1_info
.first_packet_entry
)) {
5108 /* First packet had the same headers as this one, readd the
5109 * sync sample flag. */
5110 trk
->cluster
[0].flags
|= MOV_SYNC_SAMPLE
;
5111 trk
->has_keyframes
= 1;
5115 if (trk
->vc1_info
.packet_seq
&& trk
->vc1_info
.packet_entry
)
5117 else if (trk
->vc1_info
.packet_seq
)
5119 else if (trk
->vc1_info
.packet_entry
)
5122 trk
->cluster
[trk
->entry
].flags
|= MOV_SYNC_SAMPLE
;
5123 trk
->has_keyframes
++;
5127 static void mov_parse_truehd_frame(AVPacket
*pkt
, MOVTrack
*trk
)
5134 length
= (AV_RB16(pkt
->data
) & 0xFFF) * 2;
5135 if (length
< 8 || length
> pkt
->size
)
5138 if (AV_RB32(pkt
->data
+ 4) == 0xF8726FBA) {
5139 trk
->cluster
[trk
->entry
].flags
|= MOV_SYNC_SAMPLE
;
5140 trk
->has_keyframes
++;
5146 static int mov_flush_fragment_interleaving(AVFormatContext
*s
, MOVTrack
*track
)
5148 MOVMuxContext
*mov
= s
->priv_data
;
5153 if (!track
->mdat_buf
)
5155 if (!mov
->mdat_buf
) {
5156 if ((ret
= avio_open_dyn_buf(&mov
->mdat_buf
)) < 0)
5159 buf_size
= avio_get_dyn_buf(track
->mdat_buf
, &buf
);
5161 offset
= avio_tell(mov
->mdat_buf
);
5162 avio_write(mov
->mdat_buf
, buf
, buf_size
);
5163 ffio_free_dyn_buf(&track
->mdat_buf
);
5165 for (i
= track
->entries_flushed
; i
< track
->entry
; i
++)
5166 track
->cluster
[i
].pos
+= offset
;
5167 track
->entries_flushed
= track
->entry
;
5171 static int mov_flush_fragment(AVFormatContext
*s
, int force
)
5173 MOVMuxContext
*mov
= s
->priv_data
;
5174 int i
, first_track
= -1;
5175 int64_t mdat_size
= 0;
5177 int has_video
= 0, starts_with_key
= 0, first_video_track
= 1;
5179 if (!(mov
->flags
& FF_MOV_FLAG_FRAGMENT
))
5182 // Try to fill in the duration of the last packet in each stream
5183 // from queued packets in the interleave queues. If the flushing
5184 // of fragments was triggered automatically by an AVPacket, we
5185 // already have reliable info for the end of that track, but other
5186 // tracks may need to be filled in.
5187 for (i
= 0; i
< s
->nb_streams
; i
++) {
5188 MOVTrack
*track
= &mov
->tracks
[i
];
5189 if (!track
->end_reliable
) {
5191 if (!ff_interleaved_peek(s
, i
, &pkt
, 1)) {
5192 if (track
->dts_shift
!= AV_NOPTS_VALUE
)
5193 pkt
.dts
+= track
->dts_shift
;
5194 track
->track_duration
= pkt
.dts
- track
->start_dts
;
5195 if (pkt
.pts
!= AV_NOPTS_VALUE
)
5196 track
->end_pts
= pkt
.pts
;
5198 track
->end_pts
= pkt
.dts
;
5203 for (i
= 0; i
< mov
->nb_streams
; i
++) {
5204 MOVTrack
*track
= &mov
->tracks
[i
];
5205 if (track
->entry
<= 1)
5207 // Sample durations are calculated as the diff of dts values,
5208 // but for the last sample in a fragment, we don't know the dts
5209 // of the first sample in the next fragment, so we have to rely
5210 // on what was set as duration in the AVPacket. Not all callers
5211 // set this though, so we might want to replace it with an
5212 // estimate if it currently is zero.
5213 if (get_cluster_duration(track
, track
->entry
- 1) != 0)
5215 // Use the duration (i.e. dts diff) of the second last sample for
5216 // the last one. This is a wild guess (and fatal if it turns out
5217 // to be too long), but probably the best we can do - having a zero
5218 // duration is bad as well.
5219 track
->track_duration
+= get_cluster_duration(track
, track
->entry
- 2);
5220 track
->end_pts
+= get_cluster_duration(track
, track
->entry
- 2);
5221 if (!mov
->missing_duration_warned
) {
5222 av_log(s
, AV_LOG_WARNING
,
5223 "Estimating the duration of the last packet in a "
5224 "fragment, consider setting the duration field in "
5225 "AVPacket instead.\n");
5226 mov
->missing_duration_warned
= 1;
5230 if (!mov
->moov_written
) {
5231 int64_t pos
= avio_tell(s
->pb
);
5233 int buf_size
, moov_size
;
5235 for (i
= 0; i
< mov
->nb_streams
; i
++)
5236 if (!mov
->tracks
[i
].entry
&& !is_cover_image(mov
->tracks
[i
].st
))
5238 /* Don't write the initial moov unless all tracks have data */
5239 if (i
< mov
->nb_streams
&& !force
)
5242 moov_size
= get_moov_size(s
);
5243 for (i
= 0; i
< mov
->nb_streams
; i
++)
5244 mov
->tracks
[i
].data_offset
= pos
+ moov_size
+ 8;
5246 avio_write_marker(s
->pb
, AV_NOPTS_VALUE
, AVIO_DATA_MARKER_HEADER
);
5247 if (mov
->flags
& FF_MOV_FLAG_DELAY_MOOV
)
5248 mov_write_identification(s
->pb
, s
);
5249 if ((ret
= mov_write_moov_tag(s
->pb
, mov
, s
)) < 0)
5252 if (mov
->flags
& FF_MOV_FLAG_DELAY_MOOV
) {
5253 if (mov
->flags
& FF_MOV_FLAG_GLOBAL_SIDX
)
5254 mov
->reserved_header_pos
= avio_tell(s
->pb
);
5255 avio_write_marker(s
->pb
, AV_NOPTS_VALUE
, AVIO_DATA_MARKER_FLUSH_POINT
);
5256 mov
->moov_written
= 1;
5260 buf_size
= avio_get_dyn_buf(mov
->mdat_buf
, &buf
);
5261 avio_wb32(s
->pb
, buf_size
+ 8);
5262 ffio_wfourcc(s
->pb
, "mdat");
5263 avio_write(s
->pb
, buf
, buf_size
);
5264 ffio_free_dyn_buf(&mov
->mdat_buf
);
5266 if (mov
->flags
& FF_MOV_FLAG_GLOBAL_SIDX
)
5267 mov
->reserved_header_pos
= avio_tell(s
->pb
);
5269 mov
->moov_written
= 1;
5271 for (i
= 0; i
< mov
->nb_streams
; i
++) {
5272 if (mov
->tracks
[i
].entry
)
5273 mov
->tracks
[i
].frag_start
+= mov
->tracks
[i
].start_dts
+
5274 mov
->tracks
[i
].track_duration
-
5275 mov
->tracks
[i
].cluster
[0].dts
;
5276 mov
->tracks
[i
].entry
= 0;
5277 mov
->tracks
[i
].end_reliable
= 0;
5279 avio_write_marker(s
->pb
, AV_NOPTS_VALUE
, AVIO_DATA_MARKER_FLUSH_POINT
);
5283 if (mov
->frag_interleave
) {
5284 for (i
= 0; i
< mov
->nb_streams
; i
++) {
5285 MOVTrack
*track
= &mov
->tracks
[i
];
5287 if ((ret
= mov_flush_fragment_interleaving(s
, track
)) < 0)
5293 mdat_size
= avio_tell(mov
->mdat_buf
);
5296 for (i
= 0; i
< mov
->nb_streams
; i
++) {
5297 MOVTrack
*track
= &mov
->tracks
[i
];
5298 if (mov
->flags
& FF_MOV_FLAG_SEPARATE_MOOF
|| mov
->frag_interleave
)
5299 track
->data_offset
= 0;
5301 track
->data_offset
= mdat_size
;
5302 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
5304 if (first_video_track
) {
5306 starts_with_key
= track
->cluster
[0].flags
& MOV_SYNC_SAMPLE
;
5307 first_video_track
= 0;
5312 if (track
->mdat_buf
)
5313 mdat_size
+= avio_tell(track
->mdat_buf
);
5314 if (first_track
< 0)
5321 avio_write_marker(s
->pb
,
5322 av_rescale(mov
->tracks
[first_track
].cluster
[0].dts
, AV_TIME_BASE
, mov
->tracks
[first_track
].timescale
),
5323 (has_video
? starts_with_key
: mov
->tracks
[first_track
].cluster
[0].flags
& MOV_SYNC_SAMPLE
) ? AVIO_DATA_MARKER_SYNC_POINT
: AVIO_DATA_MARKER_BOUNDARY_POINT
);
5325 for (i
= 0; i
< mov
->nb_streams
; i
++) {
5326 MOVTrack
*track
= &mov
->tracks
[i
];
5327 int buf_size
, write_moof
= 1, moof_tracks
= -1;
5329 int64_t duration
= 0;
5332 duration
= track
->start_dts
+ track
->track_duration
-
5333 track
->cluster
[0].dts
;
5334 if (mov
->flags
& FF_MOV_FLAG_SEPARATE_MOOF
) {
5335 if (!track
->mdat_buf
)
5337 mdat_size
= avio_tell(track
->mdat_buf
);
5340 write_moof
= i
== first_track
;
5344 avio_write_marker(s
->pb
, AV_NOPTS_VALUE
, AVIO_DATA_MARKER_FLUSH_POINT
);
5346 mov_write_moof_tag(s
->pb
, mov
, moof_tracks
, mdat_size
);
5349 avio_wb32(s
->pb
, mdat_size
+ 8);
5350 ffio_wfourcc(s
->pb
, "mdat");
5354 track
->frag_start
+= duration
;
5356 track
->entries_flushed
= 0;
5357 track
->end_reliable
= 0;
5358 if (!mov
->frag_interleave
) {
5359 if (!track
->mdat_buf
)
5361 buf_size
= avio_close_dyn_buf(track
->mdat_buf
, &buf
);
5362 track
->mdat_buf
= NULL
;
5366 buf_size
= avio_close_dyn_buf(mov
->mdat_buf
, &buf
);
5367 mov
->mdat_buf
= NULL
;
5370 avio_write(s
->pb
, buf
, buf_size
);
5376 avio_write_marker(s
->pb
, AV_NOPTS_VALUE
, AVIO_DATA_MARKER_FLUSH_POINT
);
5380 static int mov_auto_flush_fragment(AVFormatContext
*s
, int force
)
5382 MOVMuxContext
*mov
= s
->priv_data
;
5383 int had_moov
= mov
->moov_written
;
5384 int ret
= mov_flush_fragment(s
, force
);
5387 // If using delay_moov, the first flush only wrote the moov,
5388 // not the actual moof+mdat pair, thus flush once again.
5389 if (!had_moov
&& mov
->flags
& FF_MOV_FLAG_DELAY_MOOV
)
5390 ret
= mov_flush_fragment(s
, force
);
5394 static int check_pkt(AVFormatContext
*s
, AVPacket
*pkt
)
5396 MOVMuxContext
*mov
= s
->priv_data
;
5397 MOVTrack
*trk
= &mov
->tracks
[pkt
->stream_index
];
5402 ref
= trk
->cluster
[trk
->entry
- 1].dts
;
5403 } else if ( trk
->start_dts
!= AV_NOPTS_VALUE
5404 && !trk
->frag_discont
) {
5405 ref
= trk
->start_dts
+ trk
->track_duration
;
5407 ref
= pkt
->dts
; // Skip tests for the first packet
5409 if (trk
->dts_shift
!= AV_NOPTS_VALUE
) {
5410 /* With negative CTS offsets we have set an offset to the DTS,
5411 * reverse this for the check. */
5412 ref
-= trk
->dts_shift
;
5415 duration
= pkt
->dts
- ref
;
5416 if (pkt
->dts
< ref
|| duration
>= INT_MAX
) {
5417 av_log(s
, AV_LOG_ERROR
, "Application provided duration: %"PRId64
" / timestamp: %"PRId64
" is out of range for mov/mp4 format\n",
5422 pkt
->pts
= AV_NOPTS_VALUE
;
5425 if (pkt
->duration
< 0 || pkt
->duration
> INT_MAX
) {
5426 av_log(s
, AV_LOG_ERROR
, "Application provided duration: %"PRId64
" is invalid\n", pkt
->duration
);
5427 return AVERROR(EINVAL
);
5432 int ff_mov_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
5434 MOVMuxContext
*mov
= s
->priv_data
;
5435 AVIOContext
*pb
= s
->pb
;
5436 MOVTrack
*trk
= &mov
->tracks
[pkt
->stream_index
];
5437 AVCodecParameters
*par
= trk
->par
;
5438 AVProducerReferenceTime
*prft
;
5439 unsigned int samples_in_chunk
= 0;
5440 int size
= pkt
->size
, ret
= 0, offset
= 0;
5442 uint8_t *reformatted_data
= NULL
;
5444 ret
= check_pkt(s
, pkt
);
5448 if (pkt
->pts
!= AV_NOPTS_VALUE
&&
5449 (uint64_t)pkt
->dts
- pkt
->pts
!= (int32_t)((uint64_t)pkt
->dts
- pkt
->pts
)) {
5450 av_log(s
, AV_LOG_WARNING
, "pts/dts pair unsupported\n");
5451 return AVERROR_PATCHWELCOME
;
5454 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
) {
5456 if (mov
->moov_written
|| mov
->flags
& FF_MOV_FLAG_EMPTY_MOOV
) {
5457 if (mov
->frag_interleave
&& mov
->fragments
> 0) {
5458 if (trk
->entry
- trk
->entries_flushed
>= mov
->frag_interleave
) {
5459 if ((ret
= mov_flush_fragment_interleaving(s
, trk
)) < 0)
5464 if (!trk
->mdat_buf
) {
5465 if ((ret
= avio_open_dyn_buf(&trk
->mdat_buf
)) < 0)
5470 if (!mov
->mdat_buf
) {
5471 if ((ret
= avio_open_dyn_buf(&mov
->mdat_buf
)) < 0)
5478 if (par
->codec_id
== AV_CODEC_ID_AMR_NB
) {
5479 /* We must find out how many AMR blocks there are in one packet */
5480 static const uint16_t packed_size
[16] =
5481 {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
5484 while (len
< size
&& samples_in_chunk
< 100) {
5485 len
+= packed_size
[(pkt
->data
[len
] >> 3) & 0x0F];
5488 if (samples_in_chunk
> 1) {
5489 av_log(s
, AV_LOG_ERROR
, "fatal error, input is not a single packet, implement a AVParser for it\n");
5492 } else if (par
->codec_id
== AV_CODEC_ID_ADPCM_MS
||
5493 par
->codec_id
== AV_CODEC_ID_ADPCM_IMA_WAV
) {
5494 samples_in_chunk
= trk
->par
->frame_size
;
5495 } else if (trk
->sample_size
)
5496 samples_in_chunk
= size
/ trk
->sample_size
;
5498 samples_in_chunk
= 1;
5500 if (samples_in_chunk
< 1) {
5501 av_log(s
, AV_LOG_ERROR
, "fatal error, input packet contains no samples\n");
5502 return AVERROR_PATCHWELCOME
;
5505 /* copy extradata if it exists */
5506 if (trk
->vos_len
== 0 && par
->extradata_size
> 0 &&
5507 !TAG_IS_AVCI(trk
->tag
) &&
5508 (par
->codec_id
!= AV_CODEC_ID_DNXHD
)) {
5509 trk
->vos_len
= par
->extradata_size
;
5510 trk
->vos_data
= av_malloc(trk
->vos_len
+ AV_INPUT_BUFFER_PADDING_SIZE
);
5511 if (!trk
->vos_data
) {
5512 ret
= AVERROR(ENOMEM
);
5515 memcpy(trk
->vos_data
, par
->extradata
, trk
->vos_len
);
5516 memset(trk
->vos_data
+ trk
->vos_len
, 0, AV_INPUT_BUFFER_PADDING_SIZE
);
5519 if ((par
->codec_id
== AV_CODEC_ID_DNXHD
||
5520 par
->codec_id
== AV_CODEC_ID_H264
||
5521 par
->codec_id
== AV_CODEC_ID_HEVC
||
5522 par
->codec_id
== AV_CODEC_ID_TRUEHD
||
5523 par
->codec_id
== AV_CODEC_ID_AC3
) && !trk
->vos_len
&&
5524 !TAG_IS_AVCI(trk
->tag
)) {
5525 /* copy frame to create needed atoms */
5526 trk
->vos_len
= size
;
5527 trk
->vos_data
= av_malloc(size
+ AV_INPUT_BUFFER_PADDING_SIZE
);
5528 if (!trk
->vos_data
) {
5529 ret
= AVERROR(ENOMEM
);
5532 memcpy(trk
->vos_data
, pkt
->data
, size
);
5533 memset(trk
->vos_data
+ size
, 0, AV_INPUT_BUFFER_PADDING_SIZE
);
5536 if (par
->codec_id
== AV_CODEC_ID_AAC
&& pkt
->size
> 2 &&
5537 (AV_RB16(pkt
->data
) & 0xfff0) == 0xfff0) {
5538 if (!s
->streams
[pkt
->stream_index
]->nb_frames
) {
5539 av_log(s
, AV_LOG_ERROR
, "Malformed AAC bitstream detected: "
5540 "use the audio bitstream filter 'aac_adtstoasc' to fix it "
5541 "('-bsf:a aac_adtstoasc' option with ffmpeg)\n");
5544 av_log(s
, AV_LOG_WARNING
, "aac bitstream error\n");
5546 if (par
->codec_id
== AV_CODEC_ID_H264
&& trk
->vos_len
> 0 && *(uint8_t *)trk
->vos_data
!= 1 && !TAG_IS_AVCI(trk
->tag
)) {
5547 /* from x264 or from bytestream H.264 */
5548 /* NAL reformatting needed */
5549 if (trk
->hint_track
>= 0 && trk
->hint_track
< mov
->nb_streams
) {
5550 ret
= ff_avc_parse_nal_units_buf(pkt
->data
, &reformatted_data
,
5554 avio_write(pb
, reformatted_data
, size
);
5556 if (trk
->cenc
.aes_ctr
) {
5557 size
= ff_mov_cenc_avc_parse_nal_units(&trk
->cenc
, pb
, pkt
->data
, size
);
5563 size
= ff_avc_parse_nal_units(pb
, pkt
->data
, pkt
->size
);
5566 } else if (par
->codec_id
== AV_CODEC_ID_HEVC
&& trk
->vos_len
> 6 &&
5567 (AV_RB24(trk
->vos_data
) == 1 || AV_RB32(trk
->vos_data
) == 1)) {
5568 /* extradata is Annex B, assume the bitstream is too and convert it */
5569 if (trk
->hint_track
>= 0 && trk
->hint_track
< mov
->nb_streams
) {
5570 ret
= ff_hevc_annexb2mp4_buf(pkt
->data
, &reformatted_data
,
5574 avio_write(pb
, reformatted_data
, size
);
5576 size
= ff_hevc_annexb2mp4(pb
, pkt
->data
, pkt
->size
, 0, NULL
);
5578 } else if (par
->codec_id
== AV_CODEC_ID_AV1
) {
5579 if (trk
->hint_track
>= 0 && trk
->hint_track
< mov
->nb_streams
) {
5580 ret
= ff_av1_filter_obus_buf(pkt
->data
, &reformatted_data
,
5584 avio_write(pb
, reformatted_data
, size
);
5586 size
= ff_av1_filter_obus(pb
, pkt
->data
, pkt
->size
);
5588 #if CONFIG_AC3_PARSER
5589 } else if (par
->codec_id
== AV_CODEC_ID_EAC3
) {
5590 size
= handle_eac3(mov
, pkt
, trk
);
5595 avio_write(pb
, pkt
->data
, size
);
5598 if (trk
->cenc
.aes_ctr
) {
5599 if (par
->codec_id
== AV_CODEC_ID_H264
&& par
->extradata_size
> 4) {
5600 int nal_size_length
= (par
->extradata
[4] & 0x3) + 1;
5601 ret
= ff_mov_cenc_avc_write_nal_units(s
, &trk
->cenc
, nal_size_length
, pb
, pkt
->data
, size
);
5603 ret
= ff_mov_cenc_write_packet(&trk
->cenc
, pb
, pkt
->data
, size
);
5610 avio_write(pb
, pkt
->data
, size
);
5614 if (trk
->entry
>= trk
->cluster_capacity
) {
5615 unsigned new_capacity
= trk
->entry
+ MOV_INDEX_CLUSTER_SIZE
;
5616 void *cluster
= av_realloc_array(trk
->cluster
, new_capacity
, sizeof(*trk
->cluster
));
5618 ret
= AVERROR(ENOMEM
);
5621 trk
->cluster
= cluster
;
5622 trk
->cluster_capacity
= new_capacity
;
5625 trk
->cluster
[trk
->entry
].pos
= avio_tell(pb
) - size
;
5626 trk
->cluster
[trk
->entry
].samples_in_chunk
= samples_in_chunk
;
5627 trk
->cluster
[trk
->entry
].chunkNum
= 0;
5628 trk
->cluster
[trk
->entry
].size
= size
;
5629 trk
->cluster
[trk
->entry
].entries
= samples_in_chunk
;
5630 trk
->cluster
[trk
->entry
].dts
= pkt
->dts
;
5631 trk
->cluster
[trk
->entry
].pts
= pkt
->pts
;
5632 if (!trk
->entry
&& trk
->start_dts
!= AV_NOPTS_VALUE
) {
5633 if (!trk
->frag_discont
) {
5634 /* First packet of a new fragment. We already wrote the duration
5635 * of the last packet of the previous fragment based on track_duration,
5636 * which might not exactly match our dts. Therefore adjust the dts
5637 * of this packet to be what the previous packets duration implies. */
5638 trk
->cluster
[trk
->entry
].dts
= trk
->start_dts
+ trk
->track_duration
;
5639 /* We also may have written the pts and the corresponding duration
5640 * in sidx/tfrf/tfxd tags; make sure the sidx pts and duration match up with
5641 * the next fragment. This means the cts of the first sample must
5642 * be the same in all fragments, unless end_pts was updated by
5643 * the packet causing the fragment to be written. */
5644 if ((mov
->flags
& FF_MOV_FLAG_DASH
&&
5645 !(mov
->flags
& (FF_MOV_FLAG_GLOBAL_SIDX
| FF_MOV_FLAG_SKIP_SIDX
))) ||
5646 mov
->mode
== MODE_ISM
)
5647 pkt
->pts
= pkt
->dts
+ trk
->end_pts
- trk
->cluster
[trk
->entry
].dts
;
5649 /* New fragment, but discontinuous from previous fragments.
5650 * Pretend the duration sum of the earlier fragments is
5651 * pkt->dts - trk->start_dts. */
5652 trk
->frag_start
= pkt
->dts
- trk
->start_dts
;
5653 trk
->end_pts
= AV_NOPTS_VALUE
;
5654 trk
->frag_discont
= 0;
5658 if (!trk
->entry
&& trk
->start_dts
== AV_NOPTS_VALUE
&& !mov
->use_editlist
&&
5659 s
->avoid_negative_ts
== AVFMT_AVOID_NEG_TS_MAKE_ZERO
) {
5660 /* Not using edit lists and shifting the first track to start from zero.
5661 * If the other streams start from a later timestamp, we won't be able
5662 * to signal the difference in starting time without an edit list.
5663 * Thus move the timestamp for this first sample to 0, increasing
5664 * its duration instead. */
5665 trk
->cluster
[trk
->entry
].dts
= trk
->start_dts
= 0;
5667 if (trk
->start_dts
== AV_NOPTS_VALUE
) {
5668 trk
->start_dts
= pkt
->dts
;
5669 if (trk
->frag_discont
) {
5670 if (mov
->use_editlist
) {
5671 /* Pretend the whole stream started at pts=0, with earlier fragments
5672 * already written. If the stream started at pts=0, the duration sum
5673 * of earlier fragments would have been pkt->pts. */
5674 trk
->frag_start
= pkt
->pts
;
5675 trk
->start_dts
= pkt
->dts
- pkt
->pts
;
5677 /* Pretend the whole stream started at dts=0, with earlier fragments
5678 * already written, with a duration summing up to pkt->dts. */
5679 trk
->frag_start
= pkt
->dts
;
5682 trk
->frag_discont
= 0;
5683 } else if (pkt
->dts
&& mov
->moov_written
)
5684 av_log(s
, AV_LOG_WARNING
,
5685 "Track %d starts with a nonzero dts %"PRId64
", while the moov "
5686 "already has been written. Set the delay_moov flag to handle "
5688 pkt
->stream_index
, pkt
->dts
);
5690 trk
->track_duration
= pkt
->dts
- trk
->start_dts
+ pkt
->duration
;
5691 trk
->last_sample_is_subtitle_end
= 0;
5693 if (pkt
->pts
== AV_NOPTS_VALUE
) {
5694 av_log(s
, AV_LOG_WARNING
, "pts has no value\n");
5695 pkt
->pts
= pkt
->dts
;
5697 if (pkt
->dts
!= pkt
->pts
)
5698 trk
->flags
|= MOV_TRACK_CTTS
;
5699 trk
->cluster
[trk
->entry
].cts
= pkt
->pts
- pkt
->dts
;
5700 trk
->cluster
[trk
->entry
].flags
= 0;
5701 if (trk
->start_cts
== AV_NOPTS_VALUE
)
5702 trk
->start_cts
= pkt
->pts
- pkt
->dts
;
5703 if (trk
->end_pts
== AV_NOPTS_VALUE
)
5704 trk
->end_pts
= trk
->cluster
[trk
->entry
].dts
+
5705 trk
->cluster
[trk
->entry
].cts
+ pkt
->duration
;
5707 trk
->end_pts
= FFMAX(trk
->end_pts
, trk
->cluster
[trk
->entry
].dts
+
5708 trk
->cluster
[trk
->entry
].cts
+
5711 if (par
->codec_id
== AV_CODEC_ID_VC1
) {
5712 mov_parse_vc1_frame(pkt
, trk
);
5713 } else if (par
->codec_id
== AV_CODEC_ID_TRUEHD
) {
5714 mov_parse_truehd_frame(pkt
, trk
);
5715 } else if (pkt
->flags
& AV_PKT_FLAG_KEY
) {
5716 if (mov
->mode
== MODE_MOV
&& par
->codec_id
== AV_CODEC_ID_MPEG2VIDEO
&&
5717 trk
->entry
> 0) { // force sync sample for the first key frame
5718 mov_parse_mpeg2_frame(pkt
, &trk
->cluster
[trk
->entry
].flags
);
5719 if (trk
->cluster
[trk
->entry
].flags
& MOV_PARTIAL_SYNC_SAMPLE
)
5720 trk
->flags
|= MOV_TRACK_STPS
;
5722 trk
->cluster
[trk
->entry
].flags
= MOV_SYNC_SAMPLE
;
5724 if (trk
->cluster
[trk
->entry
].flags
& MOV_SYNC_SAMPLE
)
5725 trk
->has_keyframes
++;
5727 if (pkt
->flags
& AV_PKT_FLAG_DISPOSABLE
) {
5728 trk
->cluster
[trk
->entry
].flags
|= MOV_DISPOSABLE_SAMPLE
;
5729 trk
->has_disposable
++;
5732 prft
= (AVProducerReferenceTime
*)av_packet_get_side_data(pkt
, AV_PKT_DATA_PRFT
, &prft_size
);
5733 if (prft
&& prft_size
== sizeof(AVProducerReferenceTime
))
5734 memcpy(&trk
->cluster
[trk
->entry
].prft
, prft
, prft_size
);
5736 memset(&trk
->cluster
[trk
->entry
].prft
, 0, sizeof(AVProducerReferenceTime
));
5739 trk
->sample_count
+= samples_in_chunk
;
5740 mov
->mdat_size
+= size
;
5742 if (trk
->hint_track
>= 0 && trk
->hint_track
< mov
->nb_streams
)
5743 ff_mov_add_hinted_packet(s
, pkt
, trk
->hint_track
, trk
->entry
,
5744 reformatted_data
? reformatted_data
+ offset
5750 if (pkt
->data
!= reformatted_data
)
5751 av_free(reformatted_data
);
5755 static int mov_write_single_packet(AVFormatContext
*s
, AVPacket
*pkt
)
5757 MOVMuxContext
*mov
= s
->priv_data
;
5758 MOVTrack
*trk
= &mov
->tracks
[pkt
->stream_index
];
5759 AVCodecParameters
*par
= trk
->par
;
5760 int64_t frag_duration
= 0;
5761 int size
= pkt
->size
;
5763 int ret
= check_pkt(s
, pkt
);
5767 if (mov
->flags
& FF_MOV_FLAG_FRAG_DISCONT
) {
5769 for (i
= 0; i
< s
->nb_streams
; i
++)
5770 mov
->tracks
[i
].frag_discont
= 1;
5771 mov
->flags
&= ~FF_MOV_FLAG_FRAG_DISCONT
;
5774 if (mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
) {
5775 if (trk
->dts_shift
== AV_NOPTS_VALUE
)
5776 trk
->dts_shift
= pkt
->pts
- pkt
->dts
;
5777 pkt
->dts
+= trk
->dts_shift
;
5780 if (trk
->par
->codec_id
== AV_CODEC_ID_MP4ALS
||
5781 trk
->par
->codec_id
== AV_CODEC_ID_AAC
||
5782 trk
->par
->codec_id
== AV_CODEC_ID_AV1
||
5783 trk
->par
->codec_id
== AV_CODEC_ID_FLAC
) {
5785 uint8_t *side
= av_packet_get_side_data(pkt
, AV_PKT_DATA_NEW_EXTRADATA
, &side_size
);
5786 if (side
&& side_size
> 0 && (side_size
!= par
->extradata_size
|| memcmp(side
, par
->extradata
, side_size
))) {
5787 void *newextra
= av_mallocz(side_size
+ AV_INPUT_BUFFER_PADDING_SIZE
);
5789 return AVERROR(ENOMEM
);
5790 av_free(par
->extradata
);
5791 par
->extradata
= newextra
;
5792 memcpy(par
->extradata
, side
, side_size
);
5793 par
->extradata_size
= side_size
;
5794 if (!pkt
->size
) // Flush packet
5795 mov
->need_rewrite_extradata
= 1;
5800 if (trk
->start_dts
== AV_NOPTS_VALUE
&& trk
->frag_discont
) {
5801 trk
->start_dts
= pkt
->dts
;
5802 if (pkt
->pts
!= AV_NOPTS_VALUE
)
5803 trk
->start_cts
= pkt
->pts
- pkt
->dts
;
5808 return 0; /* Discard 0 sized packets */
5811 if (trk
->entry
&& pkt
->stream_index
< s
->nb_streams
)
5812 frag_duration
= av_rescale_q(pkt
->dts
- trk
->cluster
[0].dts
,
5813 s
->streams
[pkt
->stream_index
]->time_base
,
5815 if ((mov
->max_fragment_duration
&&
5816 frag_duration
>= mov
->max_fragment_duration
) ||
5817 (mov
->max_fragment_size
&& mov
->mdat_size
+ size
>= mov
->max_fragment_size
) ||
5818 (mov
->flags
& FF_MOV_FLAG_FRAG_KEYFRAME
&&
5819 par
->codec_type
== AVMEDIA_TYPE_VIDEO
&&
5820 trk
->entry
&& pkt
->flags
& AV_PKT_FLAG_KEY
) ||
5821 (mov
->flags
& FF_MOV_FLAG_FRAG_EVERY_FRAME
)) {
5822 if (frag_duration
>= mov
->min_fragment_duration
) {
5823 // Set the duration of this track to line up with the next
5824 // sample in this track. This avoids relying on AVPacket
5825 // duration, but only helps for this particular track, not
5826 // for the other ones that are flushed at the same time.
5827 trk
->track_duration
= pkt
->dts
- trk
->start_dts
;
5828 if (pkt
->pts
!= AV_NOPTS_VALUE
)
5829 trk
->end_pts
= pkt
->pts
;
5831 trk
->end_pts
= pkt
->dts
;
5832 trk
->end_reliable
= 1;
5833 mov_auto_flush_fragment(s
, 0);
5837 return ff_mov_write_packet(s
, pkt
);
5840 static int mov_write_subtitle_end_packet(AVFormatContext
*s
,
5844 uint8_t data
[2] = {0};
5847 av_init_packet(&end
);
5848 end
.size
= sizeof(data
);
5853 end
.stream_index
= stream_index
;
5855 ret
= mov_write_single_packet(s
, &end
);
5856 av_packet_unref(&end
);
5861 static int mov_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
5863 MOVMuxContext
*mov
= s
->priv_data
;
5867 mov_flush_fragment(s
, 1);
5871 trk
= &mov
->tracks
[pkt
->stream_index
];
5873 if (is_cover_image(trk
->st
)) {
5876 if (trk
->st
->nb_frames
>= 1) {
5877 if (trk
->st
->nb_frames
== 1)
5878 av_log(s
, AV_LOG_WARNING
, "Got more than one picture in stream %d,"
5879 " ignoring.\n", pkt
->stream_index
);
5883 if ((ret
= av_packet_ref(&trk
->cover_image
, pkt
)) < 0)
5891 return mov_write_single_packet(s
, pkt
); /* Passthrough. */
5894 * Subtitles require special handling.
5896 * 1) For full complaince, every track must have a sample at
5897 * dts == 0, which is rarely true for subtitles. So, as soon
5898 * as we see any packet with dts > 0, write an empty subtitle
5899 * at dts == 0 for any subtitle track with no samples in it.
5901 * 2) For each subtitle track, check if the current packet's
5902 * dts is past the duration of the last subtitle sample. If
5903 * so, we now need to write an end sample for that subtitle.
5905 * This must be done conditionally to allow for subtitles that
5906 * immediately replace each other, in which case an end sample
5907 * is not needed, and is, in fact, actively harmful.
5909 * 3) See mov_write_trailer for how the final end sample is
5912 for (i
= 0; i
< mov
->nb_streams
; i
++) {
5913 MOVTrack
*trk
= &mov
->tracks
[i
];
5916 if (trk
->par
->codec_id
== AV_CODEC_ID_MOV_TEXT
&&
5917 trk
->track_duration
< pkt
->dts
&&
5918 (trk
->entry
== 0 || !trk
->last_sample_is_subtitle_end
)) {
5919 ret
= mov_write_subtitle_end_packet(s
, i
, trk
->track_duration
);
5920 if (ret
< 0) return ret
;
5921 trk
->last_sample_is_subtitle_end
= 1;
5925 if (trk
->mode
== MODE_MOV
&& trk
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
5926 AVPacket
*opkt
= pkt
;
5927 int reshuffle_ret
, ret
;
5928 if (trk
->is_unaligned_qt_rgb
) {
5929 int64_t bpc
= trk
->par
->bits_per_coded_sample
!= 15 ? trk
->par
->bits_per_coded_sample
: 16;
5930 int expected_stride
= ((trk
->par
->width
* bpc
+ 15) >> 4)*2;
5931 reshuffle_ret
= ff_reshuffle_raw_rgb(s
, &pkt
, trk
->par
, expected_stride
);
5932 if (reshuffle_ret
< 0)
5933 return reshuffle_ret
;
5936 if (trk
->par
->format
== AV_PIX_FMT_PAL8
&& !trk
->pal_done
) {
5937 ret
= ff_get_packet_palette(s
, opkt
, reshuffle_ret
, trk
->palette
);
5942 } else if (trk
->par
->codec_id
== AV_CODEC_ID_RAWVIDEO
&&
5943 (trk
->par
->format
== AV_PIX_FMT_GRAY8
||
5944 trk
->par
->format
== AV_PIX_FMT_MONOBLACK
)) {
5945 for (i
= 0; i
< pkt
->size
; i
++)
5946 pkt
->data
[i
] = ~pkt
->data
[i
];
5948 if (reshuffle_ret
) {
5949 ret
= mov_write_single_packet(s
, pkt
);
5952 av_packet_free(&pkt
);
5957 return mov_write_single_packet(s
, pkt
);
5961 // QuickTime chapters involve an additional text track with the chapter names
5962 // as samples, and a tref pointing from the other tracks to the chapter one.
5963 static int mov_create_chapter_track(AVFormatContext
*s
, int tracknum
)
5967 MOVMuxContext
*mov
= s
->priv_data
;
5968 MOVTrack
*track
= &mov
->tracks
[tracknum
];
5969 AVPacket pkt
= { .stream_index
= tracknum
, .flags
= AV_PKT_FLAG_KEY
};
5972 track
->mode
= mov
->mode
;
5973 track
->tag
= MKTAG('t','e','x','t');
5974 track
->timescale
= MOV_TIMESCALE
;
5975 track
->par
= avcodec_parameters_alloc();
5977 return AVERROR(ENOMEM
);
5978 track
->par
->codec_type
= AVMEDIA_TYPE_SUBTITLE
;
5980 // These properties are required to make QT recognize the chapter track
5981 uint8_t chapter_properties
[43] = { 0, 0, 0, 0, 0, 0, 0, 1, };
5982 if (ff_alloc_extradata(track
->par
, sizeof(chapter_properties
)))
5983 return AVERROR(ENOMEM
);
5984 memcpy(track
->par
->extradata
, chapter_properties
, sizeof(chapter_properties
));
5986 if (avio_open_dyn_buf(&pb
) >= 0) {
5990 /* Stub header (usually for Quicktime chapter track) */
5992 avio_wb32(pb
, 0x01); // displayFlags
5993 avio_w8(pb
, 0x00); // horizontal justification
5994 avio_w8(pb
, 0x00); // vertical justification
5995 avio_w8(pb
, 0x00); // bgColourRed
5996 avio_w8(pb
, 0x00); // bgColourGreen
5997 avio_w8(pb
, 0x00); // bgColourBlue
5998 avio_w8(pb
, 0x00); // bgColourAlpha
6000 avio_wb16(pb
, 0x00); // defTextBoxTop
6001 avio_wb16(pb
, 0x00); // defTextBoxLeft
6002 avio_wb16(pb
, 0x00); // defTextBoxBottom
6003 avio_wb16(pb
, 0x00); // defTextBoxRight
6005 avio_wb16(pb
, 0x00); // startChar
6006 avio_wb16(pb
, 0x00); // endChar
6007 avio_wb16(pb
, 0x01); // fontID
6008 avio_w8(pb
, 0x00); // fontStyleFlags
6009 avio_w8(pb
, 0x00); // fontSize
6010 avio_w8(pb
, 0x00); // fgColourRed
6011 avio_w8(pb
, 0x00); // fgColourGreen
6012 avio_w8(pb
, 0x00); // fgColourBlue
6013 avio_w8(pb
, 0x00); // fgColourAlpha
6015 avio_wb32(pb
, 0x0D); // box size
6016 ffio_wfourcc(pb
, "ftab"); // box atom name
6017 avio_wb16(pb
, 0x01); // entry count
6019 avio_wb16(pb
, 0x01); // font ID
6020 avio_w8(pb
, 0x00); // font name length
6022 if ((size
= avio_close_dyn_buf(pb
, &buf
)) > 0) {
6023 track
->par
->extradata
= buf
;
6024 track
->par
->extradata_size
= size
;
6031 for (i
= 0; i
< s
->nb_chapters
; i
++) {
6032 AVChapter
*c
= s
->chapters
[i
];
6033 AVDictionaryEntry
*t
;
6035 int64_t end
= av_rescale_q(c
->end
, c
->time_base
, (AVRational
){1,MOV_TIMESCALE
});
6036 pkt
.pts
= pkt
.dts
= av_rescale_q(c
->start
, c
->time_base
, (AVRational
){1,MOV_TIMESCALE
});
6037 pkt
.duration
= end
- pkt
.dts
;
6039 if ((t
= av_dict_get(c
->metadata
, "title", NULL
, 0))) {
6040 static const char encd
[12] = {
6041 0x00, 0x00, 0x00, 0x0C,
6043 0x00, 0x00, 0x01, 0x00 };
6044 len
= strlen(t
->value
);
6045 pkt
.size
= len
+ 2 + 12;
6046 pkt
.data
= av_malloc(pkt
.size
);
6048 return AVERROR(ENOMEM
);
6049 AV_WB16(pkt
.data
, len
);
6050 memcpy(pkt
.data
+ 2, t
->value
, len
);
6051 memcpy(pkt
.data
+ len
+ 2, encd
, sizeof(encd
));
6052 ff_mov_write_packet(s
, &pkt
);
6053 av_freep(&pkt
.data
);
6061 static int mov_check_timecode_track(AVFormatContext
*s
, AVTimecode
*tc
, int src_index
, const char *tcstr
)
6065 /* compute the frame number */
6066 ret
= av_timecode_init_from_string(tc
, find_fps(s
, s
->streams
[src_index
]), tcstr
, s
);
6070 static int mov_create_timecode_track(AVFormatContext
*s
, int index
, int src_index
, AVTimecode tc
)
6073 MOVMuxContext
*mov
= s
->priv_data
;
6074 MOVTrack
*track
= &mov
->tracks
[index
];
6075 AVStream
*src_st
= s
->streams
[src_index
];
6076 AVPacket pkt
= {.stream_index
= index
, .flags
= AV_PKT_FLAG_KEY
, .size
= 4};
6077 AVRational rate
= find_fps(s
, src_st
);
6079 /* tmcd track based on video stream */
6080 track
->mode
= mov
->mode
;
6081 track
->tag
= MKTAG('t','m','c','d');
6082 track
->src_track
= src_index
;
6083 track
->timescale
= mov
->tracks
[src_index
].timescale
;
6084 if (tc
.flags
& AV_TIMECODE_FLAG_DROPFRAME
)
6085 track
->timecode_flags
|= MOV_TIMECODE_FLAG_DROPFRAME
;
6087 /* set st to src_st for metadata access*/
6090 /* encode context: tmcd data stream */
6091 track
->par
= avcodec_parameters_alloc();
6093 return AVERROR(ENOMEM
);
6094 track
->par
->codec_type
= AVMEDIA_TYPE_DATA
;
6095 track
->par
->codec_tag
= track
->tag
;
6096 track
->st
->avg_frame_rate
= av_inv_q(rate
);
6098 /* the tmcd track just contains one packet with the frame number */
6099 pkt
.data
= av_malloc(pkt
.size
);
6101 return AVERROR(ENOMEM
);
6102 AV_WB32(pkt
.data
, tc
.start
);
6103 ret
= ff_mov_write_packet(s
, &pkt
);
6109 * st->disposition controls the "enabled" flag in the tkhd tag.
6110 * QuickTime will not play a track if it is not enabled. So make sure
6111 * that one track of each type (audio, video, subtitle) is enabled.
6113 * Subtitles are special. For audio and video, setting "enabled" also
6114 * makes the track "default" (i.e. it is rendered when played). For
6115 * subtitles, an "enabled" subtitle is not rendered by default, but
6116 * if no subtitle is enabled, the subtitle menu in QuickTime will be
6119 static void enable_tracks(AVFormatContext
*s
)
6121 MOVMuxContext
*mov
= s
->priv_data
;
6123 int enabled
[AVMEDIA_TYPE_NB
];
6124 int first
[AVMEDIA_TYPE_NB
];
6126 for (i
= 0; i
< AVMEDIA_TYPE_NB
; i
++) {
6131 for (i
= 0; i
< s
->nb_streams
; i
++) {
6132 AVStream
*st
= s
->streams
[i
];
6134 if (st
->codecpar
->codec_type
<= AVMEDIA_TYPE_UNKNOWN
||
6135 st
->codecpar
->codec_type
>= AVMEDIA_TYPE_NB
||
6139 if (first
[st
->codecpar
->codec_type
] < 0)
6140 first
[st
->codecpar
->codec_type
] = i
;
6141 if (st
->disposition
& AV_DISPOSITION_DEFAULT
) {
6142 mov
->tracks
[i
].flags
|= MOV_TRACK_ENABLED
;
6143 enabled
[st
->codecpar
->codec_type
]++;
6147 for (i
= 0; i
< AVMEDIA_TYPE_NB
; i
++) {
6149 case AVMEDIA_TYPE_VIDEO
:
6150 case AVMEDIA_TYPE_AUDIO
:
6151 case AVMEDIA_TYPE_SUBTITLE
:
6153 mov
->per_stream_grouping
= 1;
6154 if (!enabled
[i
] && first
[i
] >= 0)
6155 mov
->tracks
[first
[i
]].flags
|= MOV_TRACK_ENABLED
;
6161 static void mov_free(AVFormatContext
*s
)
6163 MOVMuxContext
*mov
= s
->priv_data
;
6169 if (mov
->chapter_track
) {
6170 if (mov
->tracks
[mov
->chapter_track
].par
)
6171 av_freep(&mov
->tracks
[mov
->chapter_track
].par
->extradata
);
6172 av_freep(&mov
->tracks
[mov
->chapter_track
].par
);
6175 for (i
= 0; i
< mov
->nb_streams
; i
++) {
6176 if (mov
->tracks
[i
].tag
== MKTAG('r','t','p',' '))
6177 ff_mov_close_hinting(&mov
->tracks
[i
]);
6178 else if (mov
->tracks
[i
].tag
== MKTAG('t','m','c','d') && mov
->nb_meta_tmcd
)
6179 av_freep(&mov
->tracks
[i
].par
);
6180 av_freep(&mov
->tracks
[i
].cluster
);
6181 av_freep(&mov
->tracks
[i
].frag_info
);
6182 av_packet_unref(&mov
->tracks
[i
].cover_image
);
6184 if (mov
->tracks
[i
].eac3_priv
) {
6185 struct eac3_info
*info
= mov
->tracks
[i
].eac3_priv
;
6186 av_packet_unref(&info
->pkt
);
6187 av_freep(&mov
->tracks
[i
].eac3_priv
);
6189 if (mov
->tracks
[i
].vos_len
)
6190 av_freep(&mov
->tracks
[i
].vos_data
);
6192 ff_mov_cenc_free(&mov
->tracks
[i
].cenc
);
6193 ffio_free_dyn_buf(&mov
->tracks
[i
].mdat_buf
);
6196 av_freep(&mov
->tracks
);
6197 ffio_free_dyn_buf(&mov
->mdat_buf
);
6200 static uint32_t rgb_to_yuv(uint32_t rgb
)
6205 r
= (rgb
>> 16) & 0xFF;
6206 g
= (rgb
>> 8) & 0xFF;
6209 y
= av_clip_uint8(( 16000 + 257 * r
+ 504 * g
+ 98 * b
)/1000);
6210 cb
= av_clip_uint8((128000 - 148 * r
- 291 * g
+ 439 * b
)/1000);
6211 cr
= av_clip_uint8((128000 + 439 * r
- 368 * g
- 71 * b
)/1000);
6213 return (y
<< 16) | (cr
<< 8) | cb
;
6216 static int mov_create_dvd_sub_decoder_specific_info(MOVTrack
*track
,
6219 int i
, width
= 720, height
= 480;
6220 int have_palette
= 0, have_size
= 0;
6221 uint32_t palette
[16];
6222 char *cur
= st
->codecpar
->extradata
;
6224 while (cur
&& *cur
) {
6225 if (strncmp("palette:", cur
, 8) == 0) {
6227 count
= sscanf(cur
+ 8,
6228 "%06"PRIx32
", %06"PRIx32
", %06"PRIx32
", %06"PRIx32
", "
6229 "%06"PRIx32
", %06"PRIx32
", %06"PRIx32
", %06"PRIx32
", "
6230 "%06"PRIx32
", %06"PRIx32
", %06"PRIx32
", %06"PRIx32
", "
6231 "%06"PRIx32
", %06"PRIx32
", %06"PRIx32
", %06"PRIx32
"",
6232 &palette
[ 0], &palette
[ 1], &palette
[ 2], &palette
[ 3],
6233 &palette
[ 4], &palette
[ 5], &palette
[ 6], &palette
[ 7],
6234 &palette
[ 8], &palette
[ 9], &palette
[10], &palette
[11],
6235 &palette
[12], &palette
[13], &palette
[14], &palette
[15]);
6237 for (i
= 0; i
< count
; i
++) {
6238 palette
[i
] = rgb_to_yuv(palette
[i
]);
6241 } else if (!strncmp("size:", cur
, 5)) {
6242 sscanf(cur
+ 5, "%dx%d", &width
, &height
);
6245 if (have_palette
&& have_size
)
6247 cur
+= strcspn(cur
, "\n\r");
6248 cur
+= strspn(cur
, "\n\r");
6251 track
->vos_data
= av_malloc(16*4 + AV_INPUT_BUFFER_PADDING_SIZE
);
6252 if (!track
->vos_data
)
6253 return AVERROR(ENOMEM
);
6254 for (i
= 0; i
< 16; i
++) {
6255 AV_WB32(track
->vos_data
+ i
* 4, palette
[i
]);
6257 memset(track
->vos_data
+ 16*4, 0, AV_INPUT_BUFFER_PADDING_SIZE
);
6258 track
->vos_len
= 16 * 4;
6260 st
->codecpar
->width
= width
;
6261 st
->codecpar
->height
= track
->height
= height
;
6266 static int mov_init(AVFormatContext
*s
)
6268 MOVMuxContext
*mov
= s
->priv_data
;
6269 AVDictionaryEntry
*global_tcr
= av_dict_get(s
->metadata
, "timecode", NULL
, 0);
6274 /* Default mode == MP4 */
6275 mov
->mode
= MODE_MP4
;
6278 if (!strcmp("3gp", s
->oformat
->name
)) mov
->mode
= MODE_3GP
;
6279 else if (!strcmp("3g2", s
->oformat
->name
)) mov
->mode
= MODE_3GP
|MODE_3G2
;
6280 else if (!strcmp("mov", s
->oformat
->name
)) mov
->mode
= MODE_MOV
;
6281 else if (!strcmp("psp", s
->oformat
->name
)) mov
->mode
= MODE_PSP
;
6282 else if (!strcmp("ipod",s
->oformat
->name
)) mov
->mode
= MODE_IPOD
;
6283 else if (!strcmp("ismv",s
->oformat
->name
)) mov
->mode
= MODE_ISM
;
6284 else if (!strcmp("f4v", s
->oformat
->name
)) mov
->mode
= MODE_F4V
;
6287 if (mov
->flags
& FF_MOV_FLAG_DELAY_MOOV
)
6288 mov
->flags
|= FF_MOV_FLAG_EMPTY_MOOV
;
6290 /* Set the FRAGMENT flag if any of the fragmentation methods are
6292 if (mov
->max_fragment_duration
|| mov
->max_fragment_size
||
6293 mov
->flags
& (FF_MOV_FLAG_EMPTY_MOOV
|
6294 FF_MOV_FLAG_FRAG_KEYFRAME
|
6295 FF_MOV_FLAG_FRAG_CUSTOM
|
6296 FF_MOV_FLAG_FRAG_EVERY_FRAME
))
6297 mov
->flags
|= FF_MOV_FLAG_FRAGMENT
;
6299 /* Set other implicit flags immediately */
6300 if (mov
->mode
== MODE_ISM
)
6301 mov
->flags
|= FF_MOV_FLAG_EMPTY_MOOV
| FF_MOV_FLAG_SEPARATE_MOOF
|
6302 FF_MOV_FLAG_FRAGMENT
| FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
;
6303 if (mov
->flags
& FF_MOV_FLAG_DASH
)
6304 mov
->flags
|= FF_MOV_FLAG_FRAGMENT
| FF_MOV_FLAG_EMPTY_MOOV
|
6305 FF_MOV_FLAG_DEFAULT_BASE_MOOF
;
6306 if (mov
->flags
& FF_MOV_FLAG_CMAF
)
6307 mov
->flags
|= FF_MOV_FLAG_FRAGMENT
| FF_MOV_FLAG_EMPTY_MOOV
|
6308 FF_MOV_FLAG_DEFAULT_BASE_MOOF
| FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
;
6310 if (mov
->flags
& FF_MOV_FLAG_EMPTY_MOOV
&& s
->flags
& AVFMT_FLAG_AUTO_BSF
) {
6311 av_log(s
, AV_LOG_VERBOSE
, "Empty MOOV enabled; disabling automatic bitstream filtering\n");
6312 s
->flags
&= ~AVFMT_FLAG_AUTO_BSF
;
6315 if (mov
->flags
& FF_MOV_FLAG_GLOBAL_SIDX
&& mov
->flags
& FF_MOV_FLAG_SKIP_SIDX
) {
6316 av_log(s
, AV_LOG_WARNING
, "Global SIDX enabled; Ignoring skip_sidx option\n");
6317 mov
->flags
&= ~FF_MOV_FLAG_SKIP_SIDX
;
6320 if (mov
->flags
& FF_MOV_FLAG_FASTSTART
) {
6321 mov
->reserved_moov_size
= -1;
6324 if (mov
->use_editlist
< 0) {
6325 mov
->use_editlist
= 1;
6326 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
&&
6327 !(mov
->flags
& FF_MOV_FLAG_DELAY_MOOV
)) {
6328 // If we can avoid needing an edit list by shifting the
6329 // tracks, prefer that over (trying to) write edit lists
6330 // in fragmented output.
6331 if (s
->avoid_negative_ts
== AVFMT_AVOID_NEG_TS_AUTO
||
6332 s
->avoid_negative_ts
== AVFMT_AVOID_NEG_TS_MAKE_ZERO
)
6333 mov
->use_editlist
= 0;
6335 if (mov
->flags
& FF_MOV_FLAG_CMAF
) {
6336 // CMAF Track requires negative cts offsets without edit lists
6337 mov
->use_editlist
= 0;
6340 if (mov
->flags
& FF_MOV_FLAG_EMPTY_MOOV
&&
6341 !(mov
->flags
& FF_MOV_FLAG_DELAY_MOOV
) && mov
->use_editlist
)
6342 av_log(s
, AV_LOG_WARNING
, "No meaningful edit list will be written when using empty_moov without delay_moov\n");
6344 if (mov
->flags
& FF_MOV_FLAG_CMAF
&& mov
->use_editlist
) {
6345 av_log(s
, AV_LOG_WARNING
, "Edit list enabled; Assuming writing CMAF Track File\n");
6346 mov
->flags
&= ~FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
;
6348 if (!mov
->use_editlist
&& s
->avoid_negative_ts
== AVFMT_AVOID_NEG_TS_AUTO
&&
6349 !(mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
))
6350 s
->avoid_negative_ts
= AVFMT_AVOID_NEG_TS_MAKE_ZERO
;
6352 /* Clear the omit_tfhd_offset flag if default_base_moof is set;
6353 * if the latter is set that's enough and omit_tfhd_offset doesn't
6354 * add anything extra on top of that. */
6355 if (mov
->flags
& FF_MOV_FLAG_OMIT_TFHD_OFFSET
&&
6356 mov
->flags
& FF_MOV_FLAG_DEFAULT_BASE_MOOF
)
6357 mov
->flags
&= ~FF_MOV_FLAG_OMIT_TFHD_OFFSET
;
6359 if (mov
->frag_interleave
&&
6360 mov
->flags
& (FF_MOV_FLAG_OMIT_TFHD_OFFSET
| FF_MOV_FLAG_SEPARATE_MOOF
)) {
6361 av_log(s
, AV_LOG_ERROR
,
6362 "Sample interleaving in fragments is mutually exclusive with "
6363 "omit_tfhd_offset and separate_moof\n");
6364 return AVERROR(EINVAL
);
6367 /* Non-seekable output is ok if using fragmentation. If ism_lookahead
6368 * is enabled, we don't support non-seekable output at all. */
6369 if (!(s
->pb
->seekable
& AVIO_SEEKABLE_NORMAL
) &&
6370 (!(mov
->flags
& FF_MOV_FLAG_FRAGMENT
) || mov
->ism_lookahead
)) {
6371 av_log(s
, AV_LOG_ERROR
, "muxer does not support non seekable output\n");
6372 return AVERROR(EINVAL
);
6375 mov
->nb_streams
= s
->nb_streams
;
6376 if (mov
->mode
& (MODE_MP4
|MODE_MOV
|MODE_IPOD
) && s
->nb_chapters
)
6377 mov
->chapter_track
= mov
->nb_streams
++;
6379 if (mov
->flags
& FF_MOV_FLAG_RTP_HINT
) {
6380 for (i
= 0; i
< s
->nb_streams
; i
++)
6381 if (rtp_hinting_needed(s
->streams
[i
]))
6385 if ( mov
->write_tmcd
== -1 && (mov
->mode
== MODE_MOV
|| mov
->mode
== MODE_MP4
)
6386 || mov
->write_tmcd
== 1) {
6387 /* +1 tmcd track for each video stream with a timecode */
6388 for (i
= 0; i
< s
->nb_streams
; i
++) {
6389 AVStream
*st
= s
->streams
[i
];
6390 AVDictionaryEntry
*t
= global_tcr
;
6391 if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
&&
6392 (t
|| (t
=av_dict_get(st
->metadata
, "timecode", NULL
, 0)))) {
6394 ret
= mov_check_timecode_track(s
, &tc
, i
, t
->value
);
6396 mov
->nb_meta_tmcd
++;
6400 /* check if there is already a tmcd track to remux */
6401 if (mov
->nb_meta_tmcd
) {
6402 for (i
= 0; i
< s
->nb_streams
; i
++) {
6403 AVStream
*st
= s
->streams
[i
];
6404 if (st
->codecpar
->codec_tag
== MKTAG('t','m','c','d')) {
6405 av_log(s
, AV_LOG_WARNING
, "You requested a copy of the original timecode track "
6406 "so timecode metadata are now ignored\n");
6407 mov
->nb_meta_tmcd
= 0;
6412 mov
->nb_streams
+= mov
->nb_meta_tmcd
;
6415 // Reserve an extra stream for chapters for the case where chapters
6416 // are written in the trailer
6417 mov
->tracks
= av_mallocz_array((mov
->nb_streams
+ 1), sizeof(*mov
->tracks
));
6419 return AVERROR(ENOMEM
);
6421 if (mov
->encryption_scheme_str
!= NULL
&& strcmp(mov
->encryption_scheme_str
, "none") != 0) {
6422 if (strcmp(mov
->encryption_scheme_str
, "cenc-aes-ctr") == 0) {
6423 mov
->encryption_scheme
= MOV_ENC_CENC_AES_CTR
;
6425 if (mov
->encryption_key_len
!= AES_CTR_KEY_SIZE
) {
6426 av_log(s
, AV_LOG_ERROR
, "Invalid encryption key len %d expected %d\n",
6427 mov
->encryption_key_len
, AES_CTR_KEY_SIZE
);
6428 return AVERROR(EINVAL
);
6431 if (mov
->encryption_kid_len
!= CENC_KID_SIZE
) {
6432 av_log(s
, AV_LOG_ERROR
, "Invalid encryption kid len %d expected %d\n",
6433 mov
->encryption_kid_len
, CENC_KID_SIZE
);
6434 return AVERROR(EINVAL
);
6437 av_log(s
, AV_LOG_ERROR
, "unsupported encryption scheme %s\n",
6438 mov
->encryption_scheme_str
);
6439 return AVERROR(EINVAL
);
6443 for (i
= 0; i
< s
->nb_streams
; i
++) {
6444 AVStream
*st
= s
->streams
[i
];
6445 MOVTrack
*track
= &mov
->tracks
[i
];
6446 AVDictionaryEntry
*lang
= av_dict_get(st
->metadata
, "language", NULL
,0);
6449 track
->par
= st
->codecpar
;
6450 track
->language
= ff_mov_iso639_to_lang(lang
?lang
->value
:"und", mov
->mode
!=MODE_MOV
);
6451 if (track
->language
< 0)
6452 track
->language
= 32767; // Unspecified Macintosh language code
6453 track
->mode
= mov
->mode
;
6454 track
->tag
= mov_find_codec_tag(s
, track
);
6456 av_log(s
, AV_LOG_ERROR
, "Could not find tag for codec %s in stream #%d, "
6457 "codec not currently supported in container\n",
6458 avcodec_get_name(st
->codecpar
->codec_id
), i
);
6459 return AVERROR(EINVAL
);
6461 /* If hinting of this track is enabled by a later hint track,
6462 * this is updated. */
6463 track
->hint_track
= -1;
6464 track
->start_dts
= AV_NOPTS_VALUE
;
6465 track
->start_cts
= AV_NOPTS_VALUE
;
6466 track
->end_pts
= AV_NOPTS_VALUE
;
6467 track
->dts_shift
= AV_NOPTS_VALUE
;
6468 if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
6469 if (track
->tag
== MKTAG('m','x','3','p') || track
->tag
== MKTAG('m','x','3','n') ||
6470 track
->tag
== MKTAG('m','x','4','p') || track
->tag
== MKTAG('m','x','4','n') ||
6471 track
->tag
== MKTAG('m','x','5','p') || track
->tag
== MKTAG('m','x','5','n')) {
6472 if (st
->codecpar
->width
!= 720 || (st
->codecpar
->height
!= 608 && st
->codecpar
->height
!= 512)) {
6473 av_log(s
, AV_LOG_ERROR
, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
6474 return AVERROR(EINVAL
);
6476 track
->height
= track
->tag
>> 24 == 'n' ? 486 : 576;
6478 if (mov
->video_track_timescale
) {
6479 track
->timescale
= mov
->video_track_timescale
;
6480 if (mov
->mode
== MODE_ISM
&& mov
->video_track_timescale
!= 10000000)
6481 av_log(s
, AV_LOG_WARNING
, "Warning: some tools, like mp4split, assume a timescale of 10000000 for ISMV.\n");
6483 track
->timescale
= st
->time_base
.den
;
6484 while(track
->timescale
< 10000)
6485 track
->timescale
*= 2;
6487 if (st
->codecpar
->width
> 65535 || st
->codecpar
->height
> 65535) {
6488 av_log(s
, AV_LOG_ERROR
, "Resolution %dx%d too large for mov/mp4\n", st
->codecpar
->width
, st
->codecpar
->height
);
6489 return AVERROR(EINVAL
);
6491 if (track
->mode
== MODE_MOV
&& track
->timescale
> 100000)
6492 av_log(s
, AV_LOG_WARNING
,
6493 "WARNING codec timebase is very high. If duration is too long,\n"
6494 "file may not be playable by quicktime. Specify a shorter timebase\n"
6495 "or choose different container.\n");
6496 if (track
->mode
== MODE_MOV
&&
6497 track
->par
->codec_id
== AV_CODEC_ID_RAWVIDEO
&&
6498 track
->tag
== MKTAG('r','a','w',' ')) {
6499 enum AVPixelFormat pix_fmt
= track
->par
->format
;
6500 if (pix_fmt
== AV_PIX_FMT_NONE
&& track
->par
->bits_per_coded_sample
== 1)
6501 pix_fmt
= AV_PIX_FMT_MONOWHITE
;
6502 track
->is_unaligned_qt_rgb
=
6503 pix_fmt
== AV_PIX_FMT_RGB24
||
6504 pix_fmt
== AV_PIX_FMT_BGR24
||
6505 pix_fmt
== AV_PIX_FMT_PAL8
||
6506 pix_fmt
== AV_PIX_FMT_GRAY8
||
6507 pix_fmt
== AV_PIX_FMT_MONOWHITE
||
6508 pix_fmt
== AV_PIX_FMT_MONOBLACK
;
6510 if (track
->par
->codec_id
== AV_CODEC_ID_VP9
||
6511 track
->par
->codec_id
== AV_CODEC_ID_AV1
) {
6512 if (track
->mode
!= MODE_MP4
) {
6513 av_log(s
, AV_LOG_ERROR
, "%s only supported in MP4.\n", avcodec_get_name(track
->par
->codec_id
));
6514 return AVERROR(EINVAL
);
6516 } else if (track
->par
->codec_id
== AV_CODEC_ID_VP8
) {
6517 /* altref frames handling is not defined in the spec as of version v1.0,
6518 * so just forbid muxing VP8 streams altogether until a new version does */
6519 av_log(s
, AV_LOG_ERROR
, "VP8 muxing is currently not supported.\n");
6520 return AVERROR_PATCHWELCOME
;
6522 } else if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
6523 track
->timescale
= st
->codecpar
->sample_rate
;
6524 if (!st
->codecpar
->frame_size
&& !av_get_bits_per_sample(st
->codecpar
->codec_id
)) {
6525 av_log(s
, AV_LOG_WARNING
, "track %d: codec frame size is not set\n", i
);
6526 track
->audio_vbr
= 1;
6527 }else if (st
->codecpar
->codec_id
== AV_CODEC_ID_ADPCM_MS
||
6528 st
->codecpar
->codec_id
== AV_CODEC_ID_ADPCM_IMA_WAV
||
6529 st
->codecpar
->codec_id
== AV_CODEC_ID_ILBC
){
6530 if (!st
->codecpar
->block_align
) {
6531 av_log(s
, AV_LOG_ERROR
, "track %d: codec block align is not set for adpcm\n", i
);
6532 return AVERROR(EINVAL
);
6534 track
->sample_size
= st
->codecpar
->block_align
;
6535 }else if (st
->codecpar
->frame_size
> 1){ /* assume compressed audio */
6536 track
->audio_vbr
= 1;
6538 track
->sample_size
= (av_get_bits_per_sample(st
->codecpar
->codec_id
) >> 3) * st
->codecpar
->channels
;
6540 if (st
->codecpar
->codec_id
== AV_CODEC_ID_ILBC
||
6541 st
->codecpar
->codec_id
== AV_CODEC_ID_ADPCM_IMA_QT
) {
6542 track
->audio_vbr
= 1;
6544 if (track
->mode
!= MODE_MOV
&&
6545 track
->par
->codec_id
== AV_CODEC_ID_MP3
&& track
->timescale
< 16000) {
6546 if (s
->strict_std_compliance
>= FF_COMPLIANCE_NORMAL
) {
6547 av_log(s
, AV_LOG_ERROR
, "track %d: muxing mp3 at %dhz is not standard, to mux anyway set strict to -1\n",
6548 i
, track
->par
->sample_rate
);
6549 return AVERROR(EINVAL
);
6551 av_log(s
, AV_LOG_WARNING
, "track %d: muxing mp3 at %dhz is not standard in MP4\n",
6552 i
, track
->par
->sample_rate
);
6555 if (track
->par
->codec_id
== AV_CODEC_ID_FLAC
||
6556 track
->par
->codec_id
== AV_CODEC_ID_TRUEHD
||
6557 track
->par
->codec_id
== AV_CODEC_ID_OPUS
) {
6558 if (track
->mode
!= MODE_MP4
) {
6559 av_log(s
, AV_LOG_ERROR
, "%s only supported in MP4.\n", avcodec_get_name(track
->par
->codec_id
));
6560 return AVERROR(EINVAL
);
6562 if (track
->par
->codec_id
!= AV_CODEC_ID_OPUS
&&
6563 s
->strict_std_compliance
> FF_COMPLIANCE_EXPERIMENTAL
) {
6564 av_log(s
, AV_LOG_ERROR
,
6565 "%s in MP4 support is experimental, add "
6566 "'-strict %d' if you want to use it.\n",
6567 avcodec_get_name(track
->par
->codec_id
), FF_COMPLIANCE_EXPERIMENTAL
);
6568 return AVERROR_EXPERIMENTAL
;
6571 } else if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_SUBTITLE
) {
6572 track
->timescale
= st
->time_base
.den
;
6573 } else if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_DATA
) {
6574 track
->timescale
= st
->time_base
.den
;
6576 track
->timescale
= MOV_TIMESCALE
;
6579 track
->height
= st
->codecpar
->height
;
6580 /* The Protected Interoperable File Format (PIFF) standard, used by ISMV recommends but
6581 doesn't mandate a track timescale of 10,000,000. The muxer allows a custom timescale
6582 for video tracks, so if user-set, it isn't overwritten */
6583 if (mov
->mode
== MODE_ISM
&&
6584 (st
->codecpar
->codec_type
!= AVMEDIA_TYPE_VIDEO
||
6585 (st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
&& !mov
->video_track_timescale
))) {
6586 track
->timescale
= 10000000;
6589 avpriv_set_pts_info(st
, 64, 1, track
->timescale
);
6591 if (mov
->encryption_scheme
== MOV_ENC_CENC_AES_CTR
) {
6592 ret
= ff_mov_cenc_init(&track
->cenc
, mov
->encryption_key
,
6593 track
->par
->codec_id
== AV_CODEC_ID_H264
, s
->flags
& AVFMT_FLAG_BITEXACT
);
6603 static int mov_write_header(AVFormatContext
*s
)
6605 AVIOContext
*pb
= s
->pb
;
6606 MOVMuxContext
*mov
= s
->priv_data
;
6607 AVDictionaryEntry
*t
, *global_tcr
= av_dict_get(s
->metadata
, "timecode", NULL
, 0);
6608 int i
, ret
, hint_track
= 0, tmcd_track
= 0, nb_tracks
= s
->nb_streams
;
6610 if (mov
->mode
& (MODE_MP4
|MODE_MOV
|MODE_IPOD
) && s
->nb_chapters
)
6613 if (mov
->flags
& FF_MOV_FLAG_RTP_HINT
) {
6614 hint_track
= nb_tracks
;
6615 for (i
= 0; i
< s
->nb_streams
; i
++)
6616 if (rtp_hinting_needed(s
->streams
[i
]))
6620 if (mov
->nb_meta_tmcd
)
6621 tmcd_track
= nb_tracks
;
6623 for (i
= 0; i
< s
->nb_streams
; i
++) {
6625 AVStream
*st
= s
->streams
[i
];
6626 MOVTrack
*track
= &mov
->tracks
[i
];
6628 /* copy extradata if it exists */
6629 if (st
->codecpar
->extradata_size
) {
6630 if (st
->codecpar
->codec_id
== AV_CODEC_ID_DVD_SUBTITLE
)
6631 mov_create_dvd_sub_decoder_specific_info(track
, st
);
6632 else if (!TAG_IS_AVCI(track
->tag
) && st
->codecpar
->codec_id
!= AV_CODEC_ID_DNXHD
) {
6633 track
->vos_len
= st
->codecpar
->extradata_size
;
6634 track
->vos_data
= av_malloc(track
->vos_len
+ AV_INPUT_BUFFER_PADDING_SIZE
);
6635 if (!track
->vos_data
) {
6636 return AVERROR(ENOMEM
);
6638 memcpy(track
->vos_data
, st
->codecpar
->extradata
, track
->vos_len
);
6639 memset(track
->vos_data
+ track
->vos_len
, 0, AV_INPUT_BUFFER_PADDING_SIZE
);
6643 if (st
->codecpar
->codec_type
!= AVMEDIA_TYPE_AUDIO
||
6644 track
->par
->channel_layout
!= AV_CH_LAYOUT_MONO
)
6647 for (j
= 0; j
< s
->nb_streams
; j
++) {
6648 AVStream
*stj
= s
->streams
[j
];
6649 MOVTrack
*trackj
= &mov
->tracks
[j
];
6653 if (stj
->codecpar
->codec_type
!= AVMEDIA_TYPE_AUDIO
||
6654 trackj
->par
->channel_layout
!= AV_CH_LAYOUT_MONO
||
6655 trackj
->language
!= track
->language
||
6656 trackj
->tag
!= track
->tag
6659 track
->multichannel_as_mono
++;
6663 if (!(mov
->flags
& FF_MOV_FLAG_DELAY_MOOV
)) {
6664 if ((ret
= mov_write_identification(pb
, s
)) < 0)
6668 if (mov
->reserved_moov_size
){
6669 mov
->reserved_header_pos
= avio_tell(pb
);
6670 if (mov
->reserved_moov_size
> 0)
6671 avio_skip(pb
, mov
->reserved_moov_size
);
6674 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
) {
6675 /* If no fragmentation options have been set, set a default. */
6676 if (!(mov
->flags
& (FF_MOV_FLAG_FRAG_KEYFRAME
|
6677 FF_MOV_FLAG_FRAG_CUSTOM
|
6678 FF_MOV_FLAG_FRAG_EVERY_FRAME
)) &&
6679 !mov
->max_fragment_duration
&& !mov
->max_fragment_size
)
6680 mov
->flags
|= FF_MOV_FLAG_FRAG_KEYFRAME
;
6682 if (mov
->flags
& FF_MOV_FLAG_FASTSTART
)
6683 mov
->reserved_header_pos
= avio_tell(pb
);
6684 mov_write_mdat_tag(pb
, mov
);
6687 ff_parse_creation_time_metadata(s
, &mov
->time
, 1);
6689 mov
->time
+= 0x7C25B080; // 1970 based -> 1904 based
6691 if (mov
->chapter_track
)
6692 if ((ret
= mov_create_chapter_track(s
, mov
->chapter_track
)) < 0)
6695 if (mov
->flags
& FF_MOV_FLAG_RTP_HINT
) {
6696 for (i
= 0; i
< s
->nb_streams
; i
++) {
6697 if (rtp_hinting_needed(s
->streams
[i
])) {
6698 if ((ret
= ff_mov_init_hinting(s
, hint_track
, i
)) < 0)
6705 if (mov
->nb_meta_tmcd
) {
6706 /* Initialize the tmcd tracks */
6707 for (i
= 0; i
< s
->nb_streams
; i
++) {
6708 AVStream
*st
= s
->streams
[i
];
6711 if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
6714 t
= av_dict_get(st
->metadata
, "timecode", NULL
, 0);
6717 if (mov_check_timecode_track(s
, &tc
, i
, t
->value
) < 0)
6719 if ((ret
= mov_create_timecode_track(s
, tmcd_track
, i
, tc
)) < 0)
6728 if (mov
->flags
& FF_MOV_FLAG_ISML
)
6729 mov_write_isml_manifest(pb
, mov
, s
);
6731 if (mov
->flags
& FF_MOV_FLAG_EMPTY_MOOV
&&
6732 !(mov
->flags
& FF_MOV_FLAG_DELAY_MOOV
)) {
6733 if ((ret
= mov_write_moov_tag(pb
, mov
, s
)) < 0)
6735 mov
->moov_written
= 1;
6736 if (mov
->flags
& FF_MOV_FLAG_GLOBAL_SIDX
)
6737 mov
->reserved_header_pos
= avio_tell(pb
);
6743 static int get_moov_size(AVFormatContext
*s
)
6746 AVIOContext
*moov_buf
;
6747 MOVMuxContext
*mov
= s
->priv_data
;
6749 if ((ret
= ffio_open_null_buf(&moov_buf
)) < 0)
6751 if ((ret
= mov_write_moov_tag(moov_buf
, mov
, s
)) < 0)
6753 return ffio_close_null_buf(moov_buf
);
6756 static int get_sidx_size(AVFormatContext
*s
)
6760 MOVMuxContext
*mov
= s
->priv_data
;
6762 if ((ret
= ffio_open_null_buf(&buf
)) < 0)
6764 mov_write_sidx_tags(buf
, mov
, -1, 0);
6765 return ffio_close_null_buf(buf
);
6769 * This function gets the moov size if moved to the top of the file: the chunk
6770 * offset table can switch between stco (32-bit entries) to co64 (64-bit
6771 * entries) when the moov is moved to the beginning, so the size of the moov
6772 * would change. It also updates the chunk offset tables.
6774 static int compute_moov_size(AVFormatContext
*s
)
6776 int i
, moov_size
, moov_size2
;
6777 MOVMuxContext
*mov
= s
->priv_data
;
6779 moov_size
= get_moov_size(s
);
6783 for (i
= 0; i
< mov
->nb_streams
; i
++)
6784 mov
->tracks
[i
].data_offset
+= moov_size
;
6786 moov_size2
= get_moov_size(s
);
6790 /* if the size changed, we just switched from stco to co64 and need to
6791 * update the offsets */
6792 if (moov_size2
!= moov_size
)
6793 for (i
= 0; i
< mov
->nb_streams
; i
++)
6794 mov
->tracks
[i
].data_offset
+= moov_size2
- moov_size
;
6799 static int compute_sidx_size(AVFormatContext
*s
)
6802 MOVMuxContext
*mov
= s
->priv_data
;
6804 sidx_size
= get_sidx_size(s
);
6808 for (i
= 0; i
< mov
->nb_streams
; i
++)
6809 mov
->tracks
[i
].data_offset
+= sidx_size
;
6814 static int shift_data(AVFormatContext
*s
)
6816 int ret
= 0, moov_size
;
6817 MOVMuxContext
*mov
= s
->priv_data
;
6818 int64_t pos
, pos_end
;
6819 uint8_t *buf
, *read_buf
[2];
6820 int read_buf_id
= 0;
6822 AVIOContext
*read_pb
;
6824 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
)
6825 moov_size
= compute_sidx_size(s
);
6827 moov_size
= compute_moov_size(s
);
6831 buf
= av_malloc(moov_size
* 2);
6833 return AVERROR(ENOMEM
);
6835 read_buf
[1] = buf
+ moov_size
;
6837 /* Shift the data: the AVIO context of the output can only be used for
6838 * writing, so we re-open the same output, but for reading. It also avoids
6839 * a read/seek/write/seek back and forth. */
6841 ret
= s
->io_open(s
, &read_pb
, s
->url
, AVIO_FLAG_READ
, NULL
);
6843 av_log(s
, AV_LOG_ERROR
, "Unable to re-open %s output file for "
6844 "the second pass (faststart)\n", s
->url
);
6848 /* mark the end of the shift to up to the last data we wrote, and get ready
6850 pos_end
= avio_tell(s
->pb
);
6851 avio_seek(s
->pb
, mov
->reserved_header_pos
+ moov_size
, SEEK_SET
);
6853 /* start reading at where the new moov will be placed */
6854 avio_seek(read_pb
, mov
->reserved_header_pos
, SEEK_SET
);
6855 pos
= avio_tell(read_pb
);
6857 #define READ_BLOCK do { \
6858 read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], moov_size); \
6862 /* shift data by chunk of at most moov_size */
6867 n
= read_size
[read_buf_id
];
6870 avio_write(s
->pb
, read_buf
[read_buf_id
], n
);
6872 } while (pos
< pos_end
);
6873 ff_format_io_close(s
, &read_pb
);
6880 static int mov_write_trailer(AVFormatContext
*s
)
6882 MOVMuxContext
*mov
= s
->priv_data
;
6883 AVIOContext
*pb
= s
->pb
;
6888 if (mov
->need_rewrite_extradata
) {
6889 for (i
= 0; i
< s
->nb_streams
; i
++) {
6890 MOVTrack
*track
= &mov
->tracks
[i
];
6891 AVCodecParameters
*par
= track
->par
;
6893 track
->vos_len
= par
->extradata_size
;
6894 av_freep(&track
->vos_data
);
6895 track
->vos_data
= av_malloc(track
->vos_len
+ AV_INPUT_BUFFER_PADDING_SIZE
);
6896 if (!track
->vos_data
)
6897 return AVERROR(ENOMEM
);
6898 memcpy(track
->vos_data
, par
->extradata
, track
->vos_len
);
6899 memset(track
->vos_data
+ track
->vos_len
, 0, AV_INPUT_BUFFER_PADDING_SIZE
);
6901 mov
->need_rewrite_extradata
= 0;
6905 * Before actually writing the trailer, make sure that there are no
6906 * dangling subtitles, that need a terminating sample.
6908 for (i
= 0; i
< mov
->nb_streams
; i
++) {
6909 MOVTrack
*trk
= &mov
->tracks
[i
];
6910 if (trk
->par
->codec_id
== AV_CODEC_ID_MOV_TEXT
&&
6911 !trk
->last_sample_is_subtitle_end
) {
6912 mov_write_subtitle_end_packet(s
, i
, trk
->track_duration
);
6913 trk
->last_sample_is_subtitle_end
= 1;
6917 // If there were no chapters when the header was written, but there
6918 // are chapters now, write them in the trailer. This only works
6919 // when we are not doing fragments.
6920 if (!mov
->chapter_track
&& !(mov
->flags
& FF_MOV_FLAG_FRAGMENT
)) {
6921 if (mov
->mode
& (MODE_MP4
|MODE_MOV
|MODE_IPOD
) && s
->nb_chapters
) {
6922 mov
->chapter_track
= mov
->nb_streams
++;
6923 if ((res
= mov_create_chapter_track(s
, mov
->chapter_track
)) < 0)
6928 if (!(mov
->flags
& FF_MOV_FLAG_FRAGMENT
)) {
6929 moov_pos
= avio_tell(pb
);
6931 /* Write size of mdat tag */
6932 if (mov
->mdat_size
+ 8 <= UINT32_MAX
) {
6933 avio_seek(pb
, mov
->mdat_pos
, SEEK_SET
);
6934 avio_wb32(pb
, mov
->mdat_size
+ 8);
6936 /* overwrite 'wide' placeholder atom */
6937 avio_seek(pb
, mov
->mdat_pos
- 8, SEEK_SET
);
6938 /* special value: real atom size will be 64 bit value after
6941 ffio_wfourcc(pb
, "mdat");
6942 avio_wb64(pb
, mov
->mdat_size
+ 16);
6944 avio_seek(pb
, mov
->reserved_moov_size
> 0 ? mov
->reserved_header_pos
: moov_pos
, SEEK_SET
);
6946 if (mov
->flags
& FF_MOV_FLAG_FASTSTART
) {
6947 av_log(s
, AV_LOG_INFO
, "Starting second pass: moving the moov atom to the beginning of the file\n");
6948 res
= shift_data(s
);
6951 avio_seek(pb
, mov
->reserved_header_pos
, SEEK_SET
);
6952 if ((res
= mov_write_moov_tag(pb
, mov
, s
)) < 0)
6954 } else if (mov
->reserved_moov_size
> 0) {
6956 if ((res
= mov_write_moov_tag(pb
, mov
, s
)) < 0)
6958 size
= mov
->reserved_moov_size
- (avio_tell(pb
) - mov
->reserved_header_pos
);
6960 av_log(s
, AV_LOG_ERROR
, "reserved_moov_size is too small, needed %"PRId64
" additional\n", 8-size
);
6961 return AVERROR(EINVAL
);
6963 avio_wb32(pb
, size
);
6964 ffio_wfourcc(pb
, "free");
6965 ffio_fill(pb
, 0, size
- 8);
6966 avio_seek(pb
, moov_pos
, SEEK_SET
);
6968 if ((res
= mov_write_moov_tag(pb
, mov
, s
)) < 0)
6973 mov_auto_flush_fragment(s
, 1);
6974 for (i
= 0; i
< mov
->nb_streams
; i
++)
6975 mov
->tracks
[i
].data_offset
= 0;
6976 if (mov
->flags
& FF_MOV_FLAG_GLOBAL_SIDX
) {
6978 av_log(s
, AV_LOG_INFO
, "Starting second pass: inserting sidx atoms\n");
6979 res
= shift_data(s
);
6982 end
= avio_tell(pb
);
6983 avio_seek(pb
, mov
->reserved_header_pos
, SEEK_SET
);
6984 mov_write_sidx_tags(pb
, mov
, -1, 0);
6985 avio_seek(pb
, end
, SEEK_SET
);
6987 if (!(mov
->flags
& FF_MOV_FLAG_SKIP_TRAILER
)) {
6988 avio_write_marker(s
->pb
, AV_NOPTS_VALUE
, AVIO_DATA_MARKER_TRAILER
);
6989 mov_write_mfra_tag(pb
, mov
);
6996 static int mov_check_bitstream(struct AVFormatContext
*s
, const AVPacket
*pkt
)
6999 AVStream
*st
= s
->streams
[pkt
->stream_index
];
7001 if (st
->codecpar
->codec_id
== AV_CODEC_ID_AAC
) {
7002 if (pkt
->size
> 2 && (AV_RB16(pkt
->data
) & 0xfff0) == 0xfff0)
7003 ret
= ff_stream_add_bitstream_filter(st
, "aac_adtstoasc", NULL
);
7004 } else if (st
->codecpar
->codec_id
== AV_CODEC_ID_VP9
) {
7005 ret
= ff_stream_add_bitstream_filter(st
, "vp9_superframe", NULL
);
7011 static const AVCodecTag codec_3gp_tags
[] = {
7012 { AV_CODEC_ID_H263
, MKTAG('s','2','6','3') },
7013 { AV_CODEC_ID_H264
, MKTAG('a','v','c','1') },
7014 { AV_CODEC_ID_MPEG4
, MKTAG('m','p','4','v') },
7015 { AV_CODEC_ID_AAC
, MKTAG('m','p','4','a') },
7016 { AV_CODEC_ID_AMR_NB
, MKTAG('s','a','m','r') },
7017 { AV_CODEC_ID_AMR_WB
, MKTAG('s','a','w','b') },
7018 { AV_CODEC_ID_MOV_TEXT
, MKTAG('t','x','3','g') },
7019 { AV_CODEC_ID_NONE
, 0 },
7022 const AVCodecTag codec_mp4_tags
[] = {
7023 { AV_CODEC_ID_MPEG4
, MKTAG('m', 'p', '4', 'v') },
7024 { AV_CODEC_ID_H264
, MKTAG('a', 'v', 'c', '1') },
7025 { AV_CODEC_ID_H264
, MKTAG('a', 'v', 'c', '3') },
7026 { AV_CODEC_ID_HEVC
, MKTAG('h', 'e', 'v', '1') },
7027 { AV_CODEC_ID_HEVC
, MKTAG('h', 'v', 'c', '1') },
7028 { AV_CODEC_ID_MPEG2VIDEO
, MKTAG('m', 'p', '4', 'v') },
7029 { AV_CODEC_ID_MPEG1VIDEO
, MKTAG('m', 'p', '4', 'v') },
7030 { AV_CODEC_ID_MJPEG
, MKTAG('m', 'p', '4', 'v') },
7031 { AV_CODEC_ID_PNG
, MKTAG('m', 'p', '4', 'v') },
7032 { AV_CODEC_ID_JPEG2000
, MKTAG('m', 'p', '4', 'v') },
7033 { AV_CODEC_ID_VC1
, MKTAG('v', 'c', '-', '1') },
7034 { AV_CODEC_ID_DIRAC
, MKTAG('d', 'r', 'a', 'c') },
7035 { AV_CODEC_ID_TSCC2
, MKTAG('m', 'p', '4', 'v') },
7036 { AV_CODEC_ID_VP9
, MKTAG('v', 'p', '0', '9') },
7037 { AV_CODEC_ID_AV1
, MKTAG('a', 'v', '0', '1') },
7038 { AV_CODEC_ID_AAC
, MKTAG('m', 'p', '4', 'a') },
7039 { AV_CODEC_ID_MP4ALS
, MKTAG('m', 'p', '4', 'a') },
7040 { AV_CODEC_ID_MP3
, MKTAG('m', 'p', '4', 'a') },
7041 { AV_CODEC_ID_MP2
, MKTAG('m', 'p', '4', 'a') },
7042 { AV_CODEC_ID_AC3
, MKTAG('a', 'c', '-', '3') },
7043 { AV_CODEC_ID_EAC3
, MKTAG('e', 'c', '-', '3') },
7044 { AV_CODEC_ID_DTS
, MKTAG('m', 'p', '4', 'a') },
7045 { AV_CODEC_ID_TRUEHD
, MKTAG('m', 'l', 'p', 'a') },
7046 { AV_CODEC_ID_FLAC
, MKTAG('f', 'L', 'a', 'C') },
7047 { AV_CODEC_ID_OPUS
, MKTAG('O', 'p', 'u', 's') },
7048 { AV_CODEC_ID_VORBIS
, MKTAG('m', 'p', '4', 'a') },
7049 { AV_CODEC_ID_QCELP
, MKTAG('m', 'p', '4', 'a') },
7050 { AV_CODEC_ID_EVRC
, MKTAG('m', 'p', '4', 'a') },
7051 { AV_CODEC_ID_DVD_SUBTITLE
, MKTAG('m', 'p', '4', 's') },
7052 { AV_CODEC_ID_MOV_TEXT
, MKTAG('t', 'x', '3', 'g') },
7053 { AV_CODEC_ID_BIN_DATA
, MKTAG('g', 'p', 'm', 'd') },
7054 { AV_CODEC_ID_MPEGH_3D_AUDIO
, MKTAG('m', 'h', 'm', '1') },
7055 { AV_CODEC_ID_NONE
, 0 },
7058 const AVCodecTag codec_ism_tags
[] = {
7059 { AV_CODEC_ID_WMAPRO
, MKTAG('w', 'm', 'a', ' ') },
7060 { AV_CODEC_ID_NONE
, 0 },
7063 static const AVCodecTag codec_ipod_tags
[] = {
7064 { AV_CODEC_ID_H264
, MKTAG('a','v','c','1') },
7065 { AV_CODEC_ID_MPEG4
, MKTAG('m','p','4','v') },
7066 { AV_CODEC_ID_AAC
, MKTAG('m','p','4','a') },
7067 { AV_CODEC_ID_ALAC
, MKTAG('a','l','a','c') },
7068 { AV_CODEC_ID_AC3
, MKTAG('a','c','-','3') },
7069 { AV_CODEC_ID_MOV_TEXT
, MKTAG('t','x','3','g') },
7070 { AV_CODEC_ID_MOV_TEXT
, MKTAG('t','e','x','t') },
7071 { AV_CODEC_ID_NONE
, 0 },
7074 static const AVCodecTag codec_f4v_tags
[] = {
7075 { AV_CODEC_ID_MP3
, MKTAG('.','m','p','3') },
7076 { AV_CODEC_ID_AAC
, MKTAG('m','p','4','a') },
7077 { AV_CODEC_ID_H264
, MKTAG('a','v','c','1') },
7078 { AV_CODEC_ID_VP6A
, MKTAG('V','P','6','A') },
7079 { AV_CODEC_ID_VP6F
, MKTAG('V','P','6','F') },
7080 { AV_CODEC_ID_NONE
, 0 },
7083 #if CONFIG_MOV_MUXER
7085 AVOutputFormat ff_mov_muxer
= {
7087 .long_name
= NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
7088 .extensions
= "mov",
7089 .priv_data_size
= sizeof(MOVMuxContext
),
7090 .audio_codec
= AV_CODEC_ID_AAC
,
7091 .video_codec
= CONFIG_LIBX264_ENCODER
?
7092 AV_CODEC_ID_H264
: AV_CODEC_ID_MPEG4
,
7094 .write_header
= mov_write_header
,
7095 .write_packet
= mov_write_packet
,
7096 .write_trailer
= mov_write_trailer
,
7098 .flags
= AVFMT_GLOBALHEADER
| AVFMT_ALLOW_FLUSH
| AVFMT_TS_NEGATIVE
,
7099 .codec_tag
= (const AVCodecTag
* const []){
7100 ff_codec_movvideo_tags
, ff_codec_movaudio_tags
, ff_codec_movsubtitle_tags
, 0
7102 .check_bitstream
= mov_check_bitstream
,
7103 .priv_class
= &mov_muxer_class
,
7106 #if CONFIG_TGP_MUXER
7108 AVOutputFormat ff_tgp_muxer
= {
7110 .long_name
= NULL_IF_CONFIG_SMALL("3GP (3GPP file format)"),
7111 .extensions
= "3gp",
7112 .priv_data_size
= sizeof(MOVMuxContext
),
7113 .audio_codec
= AV_CODEC_ID_AMR_NB
,
7114 .video_codec
= AV_CODEC_ID_H263
,
7116 .write_header
= mov_write_header
,
7117 .write_packet
= mov_write_packet
,
7118 .write_trailer
= mov_write_trailer
,
7120 .flags
= AVFMT_GLOBALHEADER
| AVFMT_ALLOW_FLUSH
| AVFMT_TS_NEGATIVE
,
7121 .codec_tag
= (const AVCodecTag
* const []){ codec_3gp_tags
, 0 },
7122 .check_bitstream
= mov_check_bitstream
,
7123 .priv_class
= &tgp_muxer_class
,
7126 #if CONFIG_MP4_MUXER
7128 AVOutputFormat ff_mp4_muxer
= {
7130 .long_name
= NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"),
7131 .mime_type
= "video/mp4",
7132 .extensions
= "mp4",
7133 .priv_data_size
= sizeof(MOVMuxContext
),
7134 .audio_codec
= AV_CODEC_ID_AAC
,
7135 .video_codec
= CONFIG_LIBX264_ENCODER
?
7136 AV_CODEC_ID_H264
: AV_CODEC_ID_MPEG4
,
7138 .write_header
= mov_write_header
,
7139 .write_packet
= mov_write_packet
,
7140 .write_trailer
= mov_write_trailer
,
7142 .flags
= AVFMT_GLOBALHEADER
| AVFMT_ALLOW_FLUSH
| AVFMT_TS_NEGATIVE
,
7143 .codec_tag
= (const AVCodecTag
* const []){ codec_mp4_tags
, 0 },
7144 .check_bitstream
= mov_check_bitstream
,
7145 .priv_class
= &mp4_muxer_class
,
7148 #if CONFIG_PSP_MUXER
7150 AVOutputFormat ff_psp_muxer
= {
7152 .long_name
= NULL_IF_CONFIG_SMALL("PSP MP4 (MPEG-4 Part 14)"),
7153 .extensions
= "mp4,psp",
7154 .priv_data_size
= sizeof(MOVMuxContext
),
7155 .audio_codec
= AV_CODEC_ID_AAC
,
7156 .video_codec
= CONFIG_LIBX264_ENCODER
?
7157 AV_CODEC_ID_H264
: AV_CODEC_ID_MPEG4
,
7159 .write_header
= mov_write_header
,
7160 .write_packet
= mov_write_packet
,
7161 .write_trailer
= mov_write_trailer
,
7163 .flags
= AVFMT_GLOBALHEADER
| AVFMT_ALLOW_FLUSH
| AVFMT_TS_NEGATIVE
,
7164 .codec_tag
= (const AVCodecTag
* const []){ codec_mp4_tags
, 0 },
7165 .check_bitstream
= mov_check_bitstream
,
7166 .priv_class
= &psp_muxer_class
,
7169 #if CONFIG_TG2_MUXER
7171 AVOutputFormat ff_tg2_muxer
= {
7173 .long_name
= NULL_IF_CONFIG_SMALL("3GP2 (3GPP2 file format)"),
7174 .extensions
= "3g2",
7175 .priv_data_size
= sizeof(MOVMuxContext
),
7176 .audio_codec
= AV_CODEC_ID_AMR_NB
,
7177 .video_codec
= AV_CODEC_ID_H263
,
7179 .write_header
= mov_write_header
,
7180 .write_packet
= mov_write_packet
,
7181 .write_trailer
= mov_write_trailer
,
7183 .flags
= AVFMT_GLOBALHEADER
| AVFMT_ALLOW_FLUSH
| AVFMT_TS_NEGATIVE
,
7184 .codec_tag
= (const AVCodecTag
* const []){ codec_3gp_tags
, 0 },
7185 .check_bitstream
= mov_check_bitstream
,
7186 .priv_class
= &tg2_muxer_class
,
7189 #if CONFIG_IPOD_MUXER
7191 AVOutputFormat ff_ipod_muxer
= {
7193 .long_name
= NULL_IF_CONFIG_SMALL("iPod H.264 MP4 (MPEG-4 Part 14)"),
7194 .mime_type
= "video/mp4",
7195 .extensions
= "m4v,m4a,m4b",
7196 .priv_data_size
= sizeof(MOVMuxContext
),
7197 .audio_codec
= AV_CODEC_ID_AAC
,
7198 .video_codec
= AV_CODEC_ID_H264
,
7200 .write_header
= mov_write_header
,
7201 .write_packet
= mov_write_packet
,
7202 .write_trailer
= mov_write_trailer
,
7204 .flags
= AVFMT_GLOBALHEADER
| AVFMT_ALLOW_FLUSH
| AVFMT_TS_NEGATIVE
,
7205 .codec_tag
= (const AVCodecTag
* const []){ codec_ipod_tags
, 0 },
7206 .check_bitstream
= mov_check_bitstream
,
7207 .priv_class
= &ipod_muxer_class
,
7210 #if CONFIG_ISMV_MUXER
7212 AVOutputFormat ff_ismv_muxer
= {
7214 .long_name
= NULL_IF_CONFIG_SMALL("ISMV/ISMA (Smooth Streaming)"),
7215 .mime_type
= "video/mp4",
7216 .extensions
= "ismv,isma",
7217 .priv_data_size
= sizeof(MOVMuxContext
),
7218 .audio_codec
= AV_CODEC_ID_AAC
,
7219 .video_codec
= AV_CODEC_ID_H264
,
7221 .write_header
= mov_write_header
,
7222 .write_packet
= mov_write_packet
,
7223 .write_trailer
= mov_write_trailer
,
7225 .flags
= AVFMT_GLOBALHEADER
| AVFMT_ALLOW_FLUSH
| AVFMT_TS_NEGATIVE
,
7226 .codec_tag
= (const AVCodecTag
* const []){
7227 codec_mp4_tags
, codec_ism_tags
, 0 },
7228 .check_bitstream
= mov_check_bitstream
,
7229 .priv_class
= &ismv_muxer_class
,
7232 #if CONFIG_F4V_MUXER
7234 AVOutputFormat ff_f4v_muxer
= {
7236 .long_name
= NULL_IF_CONFIG_SMALL("F4V Adobe Flash Video"),
7237 .mime_type
= "application/f4v",
7238 .extensions
= "f4v",
7239 .priv_data_size
= sizeof(MOVMuxContext
),
7240 .audio_codec
= AV_CODEC_ID_AAC
,
7241 .video_codec
= AV_CODEC_ID_H264
,
7243 .write_header
= mov_write_header
,
7244 .write_packet
= mov_write_packet
,
7245 .write_trailer
= mov_write_trailer
,
7247 .flags
= AVFMT_GLOBALHEADER
| AVFMT_ALLOW_FLUSH
,
7248 .codec_tag
= (const AVCodecTag
* const []){ codec_f4v_tags
, 0 },
7249 .check_bitstream
= mov_check_bitstream
,
7250 .priv_class
= &f4v_muxer_class
,