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"
30 #include "dovi_isom.h"
36 #include "libavcodec/ac3_parser_internal.h"
37 #include "libavcodec/dnxhddata.h"
38 #include "libavcodec/flac.h"
39 #include "libavcodec/get_bits.h"
41 #include "libavcodec/internal.h"
42 #include "libavcodec/put_bits.h"
43 #include "libavcodec/vc1_common.h"
44 #include "libavcodec/raw.h"
46 #include "libavutil/avstring.h"
47 #include "libavutil/channel_layout.h"
48 #include "libavutil/intfloat.h"
49 #include "libavutil/mathematics.h"
50 #include "libavutil/libm.h"
51 #include "libavutil/opt.h"
52 #include "libavutil/dict.h"
53 #include "libavutil/pixdesc.h"
54 #include "libavutil/stereo3d.h"
55 #include "libavutil/timecode.h"
56 #include "libavutil/dovi_meta.h"
57 #include "libavutil/color_utils.h"
61 #include "movenc_ttml.h"
65 static const AVOption options
[] = {
66 { "movflags", "MOV muxer flags", offsetof(MOVMuxContext
, flags
), AV_OPT_TYPE_FLAGS
, {.i64
= 0}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
67 { "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" },
68 { "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 },
69 { "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" },
70 { "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" },
71 { "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" },
72 { "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" },
73 { "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" },
74 { "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" },
75 { "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" },
76 { "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" },
77 { "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" },
78 { "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" },
79 { "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" },
80 { "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" },
81 { "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" },
82 { "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" },
83 { "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" },
84 { "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" },
85 { "write_colr", "Write colr atom even if the color info is unspecified (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" },
86 { "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" },
87 { "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" },
88 { "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" },
89 { "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" },
90 { "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" },
91 FF_RTP_FLAG_OPTS(MOVMuxContext
, rtp_flags
),
92 { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext
, iods_skip
), AV_OPT_TYPE_BOOL
, {.i64
= 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM
},
93 { "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
},
94 { "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
},
95 { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext
, max_fragment_duration
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
},
96 { "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
},
97 { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext
, max_fragment_size
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
},
98 { "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext
, ism_lookahead
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, 255, AV_OPT_FLAG_ENCODING_PARAM
},
99 { "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
},
100 { "brand", "Override major brand", offsetof(MOVMuxContext
, major_brand
), AV_OPT_TYPE_STRING
, {.str
= NULL
}, .flags
= AV_OPT_FLAG_ENCODING_PARAM
},
101 { "use_editlist", "use edit list", offsetof(MOVMuxContext
, use_editlist
), AV_OPT_TYPE_BOOL
, {.i64
= -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM
},
102 { "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
},
103 { "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
},
104 { "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
},
105 { "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
},
106 { "encryption_key", "The media encryption key (hex)", offsetof(MOVMuxContext
, encryption_key
), AV_OPT_TYPE_BINARY
, .flags
= AV_OPT_FLAG_ENCODING_PARAM
},
107 { "encryption_kid", "The media encryption key identifier (hex)", offsetof(MOVMuxContext
, encryption_kid
), AV_OPT_TYPE_BINARY
, .flags
= AV_OPT_FLAG_ENCODING_PARAM
},
108 { "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
},
109 { "write_tmcd", "force or disable writing tmcd", offsetof(MOVMuxContext
, write_tmcd
), AV_OPT_TYPE_BOOL
, {.i64
= -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM
},
110 { "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"},
111 { "wallclock", NULL
, 0, AV_OPT_TYPE_CONST
, {.i64
= MOV_PRFT_SRC_WALLCLOCK
}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM
, "prft"},
112 { "pts", NULL
, 0, AV_OPT_TYPE_CONST
, {.i64
= MOV_PRFT_SRC_PTS
}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM
, "prft"},
113 { "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
},
114 { "movie_timescale", "set movie timescale", offsetof(MOVMuxContext
, movie_timescale
), AV_OPT_TYPE_INT
, {.i64
= MOV_TIMESCALE
}, 1, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
},
118 static const AVClass mov_isobmff_muxer_class
= {
119 .class_name
= "mov/mp4/tgp/psp/tg2/ipod/ismv/f4v muxer",
120 .item_name
= av_default_item_name
,
122 .version
= LIBAVUTIL_VERSION_INT
,
125 static int get_moov_size(AVFormatContext
*s
);
126 static int mov_write_single_packet(AVFormatContext
*s
, AVPacket
*pkt
);
128 static int utf8len(const uint8_t *b
)
133 GET_UTF8(val
, *b
++, return -1;)
139 //FIXME support 64 bit variant with wide placeholders
140 static int64_t update_size(AVIOContext
*pb
, int64_t pos
)
142 int64_t curpos
= avio_tell(pb
);
143 avio_seek(pb
, pos
, SEEK_SET
);
144 avio_wb32(pb
, curpos
- pos
); /* rewrite size */
145 avio_seek(pb
, curpos
, SEEK_SET
);
150 static int co64_required(const MOVTrack
*track
)
152 if (track
->entry
> 0 && track
->cluster
[track
->entry
- 1].pos
+ track
->data_offset
> UINT32_MAX
)
157 static int is_cover_image(const AVStream
*st
)
159 /* Eg. AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS
160 * is encoded as sparse video track */
161 return st
&& st
->disposition
== AV_DISPOSITION_ATTACHED_PIC
;
164 static int rtp_hinting_needed(const AVStream
*st
)
166 /* Add hint tracks for each real audio and video stream */
167 if (is_cover_image(st
))
169 return st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
||
170 st
->codecpar
->codec_type
== AVMEDIA_TYPE_AUDIO
;
173 /* Chunk offset atom */
174 static int mov_write_stco_tag(AVIOContext
*pb
, MOVTrack
*track
)
177 int mode64
= co64_required(track
); // use 32 bit size variant if possible
178 int64_t pos
= avio_tell(pb
);
179 avio_wb32(pb
, 0); /* size */
181 ffio_wfourcc(pb
, "co64");
183 ffio_wfourcc(pb
, "stco");
184 avio_wb32(pb
, 0); /* version & flags */
185 avio_wb32(pb
, track
->chunkCount
); /* entry count */
186 for (i
= 0; i
< track
->entry
; i
++) {
187 if (!track
->cluster
[i
].chunkNum
)
190 avio_wb64(pb
, track
->cluster
[i
].pos
+ track
->data_offset
);
192 avio_wb32(pb
, track
->cluster
[i
].pos
+ track
->data_offset
);
194 return update_size(pb
, pos
);
197 /* Sample size atom */
198 static int mov_write_stsz_tag(AVIOContext
*pb
, MOVTrack
*track
)
201 int i
, j
, entries
= 0, tst
= -1, oldtst
= -1;
203 int64_t pos
= avio_tell(pb
);
204 avio_wb32(pb
, 0); /* size */
205 ffio_wfourcc(pb
, "stsz");
206 avio_wb32(pb
, 0); /* version & flags */
208 for (i
= 0; i
< track
->entry
; i
++) {
209 tst
= track
->cluster
[i
].size
/ track
->cluster
[i
].entries
;
210 if (oldtst
!= -1 && tst
!= oldtst
)
213 entries
+= track
->cluster
[i
].entries
;
215 if (equalChunks
&& track
->entry
) {
216 int sSize
= track
->entry
? track
->cluster
[0].size
/ track
->cluster
[0].entries
: 0;
217 sSize
= FFMAX(1, sSize
); // adpcm mono case could make sSize == 0
218 avio_wb32(pb
, sSize
); // sample size
219 avio_wb32(pb
, entries
); // sample count
221 avio_wb32(pb
, 0); // sample size
222 avio_wb32(pb
, entries
); // sample count
223 for (i
= 0; i
< track
->entry
; i
++) {
224 for (j
= 0; j
< track
->cluster
[i
].entries
; j
++) {
225 avio_wb32(pb
, track
->cluster
[i
].size
/
226 track
->cluster
[i
].entries
);
230 return update_size(pb
, pos
);
233 /* Sample to chunk atom */
234 static int mov_write_stsc_tag(AVIOContext
*pb
, MOVTrack
*track
)
236 int index
= 0, oldval
= -1, i
;
237 int64_t entryPos
, curpos
;
239 int64_t pos
= avio_tell(pb
);
240 avio_wb32(pb
, 0); /* size */
241 ffio_wfourcc(pb
, "stsc");
242 avio_wb32(pb
, 0); // version & flags
243 entryPos
= avio_tell(pb
);
244 avio_wb32(pb
, track
->chunkCount
); // entry count
245 for (i
= 0; i
< track
->entry
; i
++) {
246 if (oldval
!= track
->cluster
[i
].samples_in_chunk
&& track
->cluster
[i
].chunkNum
) {
247 avio_wb32(pb
, track
->cluster
[i
].chunkNum
); // first chunk
248 avio_wb32(pb
, track
->cluster
[i
].samples_in_chunk
); // samples per chunk
249 avio_wb32(pb
, 0x1); // sample description index
250 oldval
= track
->cluster
[i
].samples_in_chunk
;
254 curpos
= avio_tell(pb
);
255 avio_seek(pb
, entryPos
, SEEK_SET
);
256 avio_wb32(pb
, index
); // rewrite size
257 avio_seek(pb
, curpos
, SEEK_SET
);
259 return update_size(pb
, pos
);
262 /* Sync sample atom */
263 static int mov_write_stss_tag(AVIOContext
*pb
, MOVTrack
*track
, uint32_t flag
)
265 int64_t curpos
, entryPos
;
267 int64_t pos
= avio_tell(pb
);
268 avio_wb32(pb
, 0); // size
269 ffio_wfourcc(pb
, flag
== MOV_SYNC_SAMPLE
? "stss" : "stps");
270 avio_wb32(pb
, 0); // version & flags
271 entryPos
= avio_tell(pb
);
272 avio_wb32(pb
, track
->entry
); // entry count
273 for (i
= 0; i
< track
->entry
; i
++) {
274 if (track
->cluster
[i
].flags
& flag
) {
275 avio_wb32(pb
, i
+ 1);
279 curpos
= avio_tell(pb
);
280 avio_seek(pb
, entryPos
, SEEK_SET
);
281 avio_wb32(pb
, index
); // rewrite size
282 avio_seek(pb
, curpos
, SEEK_SET
);
283 return update_size(pb
, pos
);
286 /* Sample dependency atom */
287 static int mov_write_sdtp_tag(AVIOContext
*pb
, MOVTrack
*track
)
290 uint8_t leading
, dependent
, reference
, redundancy
;
291 int64_t pos
= avio_tell(pb
);
292 avio_wb32(pb
, 0); // size
293 ffio_wfourcc(pb
, "sdtp");
294 avio_wb32(pb
, 0); // version & flags
295 for (i
= 0; i
< track
->entry
; i
++) {
296 dependent
= MOV_SAMPLE_DEPENDENCY_YES
;
297 leading
= reference
= redundancy
= MOV_SAMPLE_DEPENDENCY_UNKNOWN
;
298 if (track
->cluster
[i
].flags
& MOV_DISPOSABLE_SAMPLE
) {
299 reference
= MOV_SAMPLE_DEPENDENCY_NO
;
301 if (track
->cluster
[i
].flags
& MOV_SYNC_SAMPLE
) {
302 dependent
= MOV_SAMPLE_DEPENDENCY_NO
;
304 avio_w8(pb
, (leading
<< 6) | (dependent
<< 4) |
305 (reference
<< 2) | redundancy
);
307 return update_size(pb
, pos
);
310 static int mov_write_amr_tag(AVIOContext
*pb
, MOVTrack
*track
)
312 avio_wb32(pb
, 0x11); /* size */
313 if (track
->mode
== MODE_MOV
) ffio_wfourcc(pb
, "samr");
314 else ffio_wfourcc(pb
, "damr");
315 ffio_wfourcc(pb
, "FFMP");
316 avio_w8(pb
, 0); /* decoder version */
318 avio_wb16(pb
, 0x81FF); /* Mode set (all modes for AMR_NB) */
319 avio_w8(pb
, 0x00); /* Mode change period (no restriction) */
320 avio_w8(pb
, 0x01); /* Frames per sample */
324 static int mov_write_ac3_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
329 int fscod
, bsid
, bsmod
, acmod
, lfeon
, frmsizecod
;
331 if (track
->vos_len
< 7) {
332 av_log(s
, AV_LOG_ERROR
,
333 "Cannot write moov atom before AC3 packets."
334 " Set the delay_moov flag to fix this.\n");
335 return AVERROR(EINVAL
);
339 ffio_wfourcc(pb
, "dac3");
341 init_get_bits(&gbc
, track
->vos_data
+ 4, (track
->vos_len
- 4) * 8);
342 fscod
= get_bits(&gbc
, 2);
343 frmsizecod
= get_bits(&gbc
, 6);
344 bsid
= get_bits(&gbc
, 5);
345 bsmod
= get_bits(&gbc
, 3);
346 acmod
= get_bits(&gbc
, 3);
348 skip_bits(&gbc
, 2); // dsurmod
350 if ((acmod
& 1) && acmod
!= 1)
351 skip_bits(&gbc
, 2); // cmixlev
353 skip_bits(&gbc
, 2); // surmixlev
355 lfeon
= get_bits1(&gbc
);
357 init_put_bits(&pbc
, buf
, sizeof(buf
));
358 put_bits(&pbc
, 2, fscod
);
359 put_bits(&pbc
, 5, bsid
);
360 put_bits(&pbc
, 3, bsmod
);
361 put_bits(&pbc
, 3, acmod
);
362 put_bits(&pbc
, 1, lfeon
);
363 put_bits(&pbc
, 5, frmsizecod
>> 1); // bit_rate_code
364 put_bits(&pbc
, 5, 0); // reserved
366 flush_put_bits(&pbc
);
367 avio_write(pb
, buf
, sizeof(buf
));
377 /* Layout of the EC3SpecificBox */
378 /* maximum bitrate */
380 /* number of independent substreams */
383 /* sample rate code (see ff_ac3_sample_rate_tab) 2 bits */
385 /* bit stream identification 5 bits */
387 /* one bit reserved */
388 /* audio service mixing (not supported yet) 1 bit */
389 /* bit stream mode 3 bits */
391 /* audio coding mode 3 bits */
393 /* sub woofer on 1 bit */
395 /* 3 bits reserved */
396 /* number of dependent substreams associated with this substream 4 bits */
398 /* channel locations of the dependent substream(s), if any, 9 bits */
400 /* if there is no dependent substream, then one bit reserved instead */
401 } substream
[1]; /* TODO: support 8 independent substreams */
404 #if CONFIG_AC3_PARSER
405 static int handle_eac3(MOVMuxContext
*mov
, AVPacket
*pkt
, MOVTrack
*track
)
407 AC3HeaderInfo
*hdr
= NULL
;
408 struct eac3_info
*info
;
411 if (!track
->eac3_priv
&& !(track
->eac3_priv
= av_mallocz(sizeof(*info
))))
412 return AVERROR(ENOMEM
);
413 info
= track
->eac3_priv
;
415 if (!info
->pkt
&& !(info
->pkt
= av_packet_alloc()))
416 return AVERROR(ENOMEM
);
418 if (avpriv_ac3_parse_header(&hdr
, pkt
->data
, pkt
->size
) < 0) {
419 /* drop the packets until we see a good one */
421 av_log(mov
->fc
, AV_LOG_WARNING
, "Dropping invalid packet from start of the stream\n");
424 ret
= AVERROR_INVALIDDATA
;
428 info
->data_rate
= FFMAX(info
->data_rate
, hdr
->bit_rate
/ 1000);
429 num_blocks
= hdr
->num_blocks
;
431 if (!info
->ec3_done
) {
432 /* AC-3 substream must be the first one */
433 if (hdr
->bitstream_id
<= 10 && hdr
->substreamid
!= 0) {
434 ret
= AVERROR(EINVAL
);
438 /* this should always be the case, given that our AC-3 parser
439 * concatenates dependent frames to their independent parent */
440 if (hdr
->frame_type
== EAC3_FRAME_TYPE_INDEPENDENT
) {
441 /* substream ids must be incremental */
442 if (hdr
->substreamid
> info
->num_ind_sub
+ 1) {
443 ret
= AVERROR(EINVAL
);
447 if (hdr
->substreamid
== info
->num_ind_sub
+ 1) {
448 //info->num_ind_sub++;
449 avpriv_request_sample(mov
->fc
, "Multiple independent substreams");
450 ret
= AVERROR_PATCHWELCOME
;
452 } else if (hdr
->substreamid
< info
->num_ind_sub
||
453 hdr
->substreamid
== 0 && info
->substream
[0].bsid
) {
458 if (hdr
->substreamid
!= 0) {
459 avpriv_request_sample(mov
->fc
, "Multiple non EAC3 independent substreams");
460 ret
= AVERROR_PATCHWELCOME
;
465 /* fill the info needed for the "dec3" atom */
466 info
->substream
[hdr
->substreamid
].fscod
= hdr
->sr_code
;
467 info
->substream
[hdr
->substreamid
].bsid
= hdr
->bitstream_id
;
468 info
->substream
[hdr
->substreamid
].bsmod
= hdr
->bitstream_mode
;
469 info
->substream
[hdr
->substreamid
].acmod
= hdr
->channel_mode
;
470 info
->substream
[hdr
->substreamid
].lfeon
= hdr
->lfe_on
;
472 /* Parse dependent substream(s), if any */
473 if (pkt
->size
!= hdr
->frame_size
) {
474 int cumul_size
= hdr
->frame_size
;
475 int parent
= hdr
->substreamid
;
477 while (cumul_size
!= pkt
->size
) {
480 ret
= avpriv_ac3_parse_header(&hdr
, pkt
->data
+ cumul_size
, pkt
->size
- cumul_size
);
483 if (hdr
->frame_type
!= EAC3_FRAME_TYPE_DEPENDENT
) {
484 ret
= AVERROR(EINVAL
);
487 info
->substream
[parent
].num_dep_sub
++;
490 /* header is parsed up to lfeon, but custom channel map may be needed */
491 init_get_bits8(&gbc
, pkt
->data
+ cumul_size
+ ret
, pkt
->size
- cumul_size
- ret
);
494 /* skip volume control params */
495 for (i
= 0; i
< (hdr
->channel_mode
? 1 : 2); i
++) {
496 skip_bits(&gbc
, 5); // skip dialog normalization
497 if (get_bits1(&gbc
)) {
498 skip_bits(&gbc
, 8); // skip compression gain word
501 /* get the dependent stream channel map, if exists */
503 info
->substream
[parent
].chan_loc
|= (get_bits(&gbc
, 16) >> 5) & 0x1f;
505 info
->substream
[parent
].chan_loc
|= hdr
->channel_mode
;
506 cumul_size
+= hdr
->frame_size
;
512 if (!info
->num_blocks
&& num_blocks
== 6) {
516 else if (info
->num_blocks
+ num_blocks
> 6) {
517 ret
= AVERROR_INVALIDDATA
;
521 if (!info
->num_blocks
) {
522 ret
= av_packet_ref(info
->pkt
, pkt
);
524 info
->num_blocks
= num_blocks
;
527 if ((ret
= av_grow_packet(info
->pkt
, pkt
->size
)) < 0)
529 memcpy(info
->pkt
->data
+ info
->pkt
->size
- pkt
->size
, pkt
->data
, pkt
->size
);
530 info
->num_blocks
+= num_blocks
;
531 info
->pkt
->duration
+= pkt
->duration
;
532 if (info
->num_blocks
!= 6)
534 av_packet_unref(pkt
);
535 av_packet_move_ref(pkt
, info
->pkt
);
536 info
->num_blocks
= 0;
547 static int mov_write_eac3_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
551 struct eac3_info
*info
;
554 if (!track
->eac3_priv
) {
555 av_log(s
, AV_LOG_ERROR
,
556 "Cannot write moov atom before EAC3 packets parsed.\n");
557 return AVERROR(EINVAL
);
560 info
= track
->eac3_priv
;
561 size
= 2 + ((34 * (info
->num_ind_sub
+ 1) + 7) >> 3);
562 buf
= av_malloc(size
);
564 return AVERROR(ENOMEM
);
567 init_put_bits(&pbc
, buf
, size
);
568 put_bits(&pbc
, 13, info
->data_rate
);
569 put_bits(&pbc
, 3, info
->num_ind_sub
);
570 for (i
= 0; i
<= info
->num_ind_sub
; i
++) {
571 put_bits(&pbc
, 2, info
->substream
[i
].fscod
);
572 put_bits(&pbc
, 5, info
->substream
[i
].bsid
);
573 put_bits(&pbc
, 1, 0); /* reserved */
574 put_bits(&pbc
, 1, 0); /* asvc */
575 put_bits(&pbc
, 3, info
->substream
[i
].bsmod
);
576 put_bits(&pbc
, 3, info
->substream
[i
].acmod
);
577 put_bits(&pbc
, 1, info
->substream
[i
].lfeon
);
578 put_bits(&pbc
, 5, 0); /* reserved */
579 put_bits(&pbc
, 4, info
->substream
[i
].num_dep_sub
);
580 if (!info
->substream
[i
].num_dep_sub
) {
581 put_bits(&pbc
, 1, 0); /* reserved */
583 put_bits(&pbc
, 9, info
->substream
[i
].chan_loc
);
586 flush_put_bits(&pbc
);
587 size
= put_bytes_output(&pbc
);
589 avio_wb32(pb
, size
+ 8);
590 ffio_wfourcc(pb
, "dec3");
591 avio_write(pb
, buf
, size
);
599 * This function writes extradata "as is".
600 * Extradata must be formatted like a valid atom (with size and tag).
602 static int mov_write_extradata_tag(AVIOContext
*pb
, MOVTrack
*track
)
604 avio_write(pb
, track
->par
->extradata
, track
->par
->extradata_size
);
605 return track
->par
->extradata_size
;
608 static int mov_write_enda_tag(AVIOContext
*pb
)
611 ffio_wfourcc(pb
, "enda");
612 avio_wb16(pb
, 1); /* little endian */
616 static int mov_write_enda_tag_be(AVIOContext
*pb
)
619 ffio_wfourcc(pb
, "enda");
620 avio_wb16(pb
, 0); /* big endian */
624 static void put_descr(AVIOContext
*pb
, int tag
, unsigned int size
)
629 avio_w8(pb
, (size
>> (7 * i
)) | 0x80);
630 avio_w8(pb
, size
& 0x7F);
633 static unsigned compute_avg_bitrate(MOVTrack
*track
)
637 if (!track
->track_duration
)
639 for (i
= 0; i
< track
->entry
; i
++)
640 size
+= track
->cluster
[i
].size
;
641 return size
* 8 * track
->timescale
/ track
->track_duration
;
644 struct mpeg4_bit_rate_values
{
645 uint32_t buffer_size
; ///< Size of the decoding buffer for the elementary stream in bytes.
646 uint32_t max_bit_rate
; ///< Maximum rate in bits/second over any window of one second.
647 uint32_t avg_bit_rate
; ///< Average rate in bits/second over the entire presentation.
650 static struct mpeg4_bit_rate_values
calculate_mpeg4_bit_rates(MOVTrack
*track
)
652 AVCPBProperties
*props
= track
->st
?
653 (AVCPBProperties
*)av_stream_get_side_data(track
->st
,
654 AV_PKT_DATA_CPB_PROPERTIES
,
657 struct mpeg4_bit_rate_values bit_rates
= { 0 };
659 bit_rates
.avg_bit_rate
= compute_avg_bitrate(track
);
660 if (!bit_rates
.avg_bit_rate
) {
661 // if the average bit rate cannot be calculated at this point, such as
662 // in the case of fragmented MP4, utilize the following values as
663 // fall-back in priority order:
665 // 1. average bit rate property
666 // 2. bit rate (usually average over the whole clip)
667 // 3. maximum bit rate property
669 if (props
&& props
->avg_bitrate
) {
670 bit_rates
.avg_bit_rate
= props
->avg_bitrate
;
671 } else if (track
->par
->bit_rate
) {
672 bit_rates
.avg_bit_rate
= track
->par
->bit_rate
;
673 } else if (props
&& props
->max_bitrate
) {
674 bit_rates
.avg_bit_rate
= props
->max_bitrate
;
678 // (FIXME should be max rate in any 1 sec window)
679 bit_rates
.max_bit_rate
= FFMAX(track
->par
->bit_rate
,
680 bit_rates
.avg_bit_rate
);
682 // utilize values from properties if we have them available
684 bit_rates
.max_bit_rate
= FFMAX(bit_rates
.max_bit_rate
,
686 bit_rates
.buffer_size
= props
->buffer_size
/ 8;
692 static int mov_write_esds_tag(AVIOContext
*pb
, MOVTrack
*track
) // Basic
694 struct mpeg4_bit_rate_values bit_rates
= calculate_mpeg4_bit_rates(track
);
695 int64_t pos
= avio_tell(pb
);
696 int decoder_specific_info_len
= track
->vos_len
? 5 + track
->vos_len
: 0;
698 avio_wb32(pb
, 0); // size
699 ffio_wfourcc(pb
, "esds");
700 avio_wb32(pb
, 0); // Version
703 put_descr(pb
, 0x03, 3 + 5+13 + decoder_specific_info_len
+ 5+1);
704 avio_wb16(pb
, track
->track_id
);
705 avio_w8(pb
, 0x00); // flags (= no flags)
707 // DecoderConfig descriptor
708 put_descr(pb
, 0x04, 13 + decoder_specific_info_len
);
710 // Object type indication
711 if ((track
->par
->codec_id
== AV_CODEC_ID_MP2
||
712 track
->par
->codec_id
== AV_CODEC_ID_MP3
) &&
713 track
->par
->sample_rate
> 24000)
714 avio_w8(pb
, 0x6B); // 11172-3
716 avio_w8(pb
, ff_codec_get_tag(ff_mp4_obj_type
, track
->par
->codec_id
));
718 // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
719 // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
720 if (track
->par
->codec_id
== AV_CODEC_ID_DVD_SUBTITLE
)
721 avio_w8(pb
, (0x38 << 2) | 1); // flags (= NeroSubpicStream)
722 else if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
)
723 avio_w8(pb
, 0x15); // flags (= Audiostream)
725 avio_w8(pb
, 0x11); // flags (= Visualstream)
727 avio_wb24(pb
, bit_rates
.buffer_size
); // Buffersize DB
728 avio_wb32(pb
, bit_rates
.max_bit_rate
); // maxbitrate
729 avio_wb32(pb
, bit_rates
.avg_bit_rate
);
731 if (track
->vos_len
) {
732 // DecoderSpecific info descriptor
733 put_descr(pb
, 0x05, track
->vos_len
);
734 avio_write(pb
, track
->vos_data
, track
->vos_len
);
738 put_descr(pb
, 0x06, 1);
740 return update_size(pb
, pos
);
743 static int mov_pcm_le_gt16(enum AVCodecID codec_id
)
745 return codec_id
== AV_CODEC_ID_PCM_S24LE
||
746 codec_id
== AV_CODEC_ID_PCM_S32LE
||
747 codec_id
== AV_CODEC_ID_PCM_F32LE
||
748 codec_id
== AV_CODEC_ID_PCM_F64LE
;
751 static int mov_pcm_be_gt16(enum AVCodecID codec_id
)
753 return codec_id
== AV_CODEC_ID_PCM_S24BE
||
754 codec_id
== AV_CODEC_ID_PCM_S32BE
||
755 codec_id
== AV_CODEC_ID_PCM_F32BE
||
756 codec_id
== AV_CODEC_ID_PCM_F64BE
;
759 static int mov_write_ms_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
762 int64_t pos
= avio_tell(pb
);
764 avio_wl32(pb
, track
->tag
); // store it byteswapped
765 track
->par
->codec_tag
= av_bswap16(track
->tag
>> 16);
766 if ((ret
= ff_put_wav_header(s
, pb
, track
->par
, 0)) < 0)
768 return update_size(pb
, pos
);
771 static int mov_write_wfex_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
774 int64_t pos
= avio_tell(pb
);
776 ffio_wfourcc(pb
, "wfex");
777 if ((ret
= ff_put_wav_header(s
, pb
, track
->st
->codecpar
, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX
)) < 0)
779 return update_size(pb
, pos
);
782 static int mov_write_dfla_tag(AVIOContext
*pb
, MOVTrack
*track
)
784 int64_t pos
= avio_tell(pb
);
786 ffio_wfourcc(pb
, "dfLa");
787 avio_w8(pb
, 0); /* version */
788 avio_wb24(pb
, 0); /* flags */
790 /* Expect the encoder to pass a METADATA_BLOCK_TYPE_STREAMINFO. */
791 if (track
->par
->extradata_size
!= FLAC_STREAMINFO_SIZE
)
792 return AVERROR_INVALIDDATA
;
794 /* TODO: Write other METADATA_BLOCK_TYPEs if the encoder makes them available. */
795 avio_w8(pb
, 1 << 7 | FLAC_METADATA_TYPE_STREAMINFO
); /* LastMetadataBlockFlag << 7 | BlockType */
796 avio_wb24(pb
, track
->par
->extradata_size
); /* Length */
797 avio_write(pb
, track
->par
->extradata
, track
->par
->extradata_size
); /* BlockData[Length] */
799 return update_size(pb
, pos
);
802 static int mov_write_dops_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
804 int64_t pos
= avio_tell(pb
);
805 int channels
, channel_map
;
807 ffio_wfourcc(pb
, "dOps");
808 avio_w8(pb
, 0); /* Version */
809 if (track
->par
->extradata_size
< 19) {
810 av_log(s
, AV_LOG_ERROR
, "invalid extradata size\n");
811 return AVERROR_INVALIDDATA
;
813 /* extradata contains an Ogg OpusHead, other than byte-ordering and
814 OpusHead's preceeding magic/version, OpusSpecificBox is currently
816 channels
= AV_RB8(track
->par
->extradata
+ 9);
817 channel_map
= AV_RB8(track
->par
->extradata
+ 18);
819 avio_w8(pb
, channels
); /* OuputChannelCount */
820 avio_wb16(pb
, AV_RL16(track
->par
->extradata
+ 10)); /* PreSkip */
821 avio_wb32(pb
, AV_RL32(track
->par
->extradata
+ 12)); /* InputSampleRate */
822 avio_wb16(pb
, AV_RL16(track
->par
->extradata
+ 16)); /* OutputGain */
823 avio_w8(pb
, channel_map
); /* ChannelMappingFamily */
824 /* Write the rest of the header out without byte-swapping. */
826 if (track
->par
->extradata_size
< 21 + channels
) {
827 av_log(s
, AV_LOG_ERROR
, "invalid extradata size\n");
828 return AVERROR_INVALIDDATA
;
830 avio_write(pb
, track
->par
->extradata
+ 19, 2 + channels
); /* ChannelMappingTable */
833 return update_size(pb
, pos
);
836 static int mov_write_dmlp_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
838 int64_t pos
= avio_tell(pb
);
841 ffio_wfourcc(pb
, "dmlp");
843 if (track
->vos_len
< 20) {
844 av_log(s
, AV_LOG_ERROR
,
845 "Cannot write moov atom before TrueHD packets."
846 " Set the delay_moov flag to fix this.\n");
847 return AVERROR(EINVAL
);
850 length
= (AV_RB16(track
->vos_data
) & 0xFFF) * 2;
851 if (length
< 20 || length
> track
->vos_len
)
852 return AVERROR_INVALIDDATA
;
854 // Only TrueHD is supported
855 if (AV_RB32(track
->vos_data
+ 4) != 0xF8726FBA)
856 return AVERROR_INVALIDDATA
;
858 avio_wb32(pb
, AV_RB32(track
->vos_data
+ 8)); /* format_info */
859 avio_wb16(pb
, AV_RB16(track
->vos_data
+ 18) << 1); /* peak_data_rate */
860 avio_wb32(pb
, 0); /* reserved */
862 return update_size(pb
, pos
);
865 static int mov_write_chan_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
867 uint32_t layout_tag
, bitmap
;
868 int64_t pos
= avio_tell(pb
);
870 layout_tag
= ff_mov_get_channel_layout_tag(track
->par
->codec_id
,
871 track
->par
->channel_layout
,
874 av_log(s
, AV_LOG_WARNING
, "not writing 'chan' tag due to "
875 "lack of channel information\n");
879 if (track
->multichannel_as_mono
)
882 avio_wb32(pb
, 0); // Size
883 ffio_wfourcc(pb
, "chan"); // Type
884 avio_w8(pb
, 0); // Version
885 avio_wb24(pb
, 0); // Flags
886 avio_wb32(pb
, layout_tag
); // mChannelLayoutTag
887 avio_wb32(pb
, bitmap
); // mChannelBitmap
888 avio_wb32(pb
, 0); // mNumberChannelDescriptions
890 return update_size(pb
, pos
);
893 static int mov_write_wave_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
895 int64_t pos
= avio_tell(pb
);
897 avio_wb32(pb
, 0); /* size */
898 ffio_wfourcc(pb
, "wave");
900 if (track
->par
->codec_id
!= AV_CODEC_ID_QDM2
) {
901 avio_wb32(pb
, 12); /* size */
902 ffio_wfourcc(pb
, "frma");
903 avio_wl32(pb
, track
->tag
);
906 if (track
->par
->codec_id
== AV_CODEC_ID_AAC
) {
907 /* useless atom needed by mplayer, ipod, not needed by quicktime */
908 avio_wb32(pb
, 12); /* size */
909 ffio_wfourcc(pb
, "mp4a");
911 mov_write_esds_tag(pb
, track
);
912 } else if (mov_pcm_le_gt16(track
->par
->codec_id
)) {
913 mov_write_enda_tag(pb
);
914 } else if (mov_pcm_be_gt16(track
->par
->codec_id
)) {
915 mov_write_enda_tag_be(pb
);
916 } else if (track
->par
->codec_id
== AV_CODEC_ID_AMR_NB
) {
917 mov_write_amr_tag(pb
, track
);
918 } else if (track
->par
->codec_id
== AV_CODEC_ID_AC3
) {
919 mov_write_ac3_tag(s
, pb
, track
);
920 } else if (track
->par
->codec_id
== AV_CODEC_ID_EAC3
) {
921 mov_write_eac3_tag(s
, pb
, track
);
922 } else if (track
->par
->codec_id
== AV_CODEC_ID_ALAC
||
923 track
->par
->codec_id
== AV_CODEC_ID_QDM2
) {
924 mov_write_extradata_tag(pb
, track
);
925 } else if (track
->par
->codec_id
== AV_CODEC_ID_ADPCM_MS
||
926 track
->par
->codec_id
== AV_CODEC_ID_ADPCM_IMA_WAV
) {
927 mov_write_ms_tag(s
, pb
, track
);
930 avio_wb32(pb
, 8); /* size */
931 avio_wb32(pb
, 0); /* null tag */
933 return update_size(pb
, pos
);
936 static int mov_write_dvc1_structs(MOVTrack
*track
, uint8_t *buf
)
939 const uint8_t *start
, *next
, *end
= track
->vos_data
+ track
->vos_len
;
940 int unescaped_size
, seq_found
= 0;
941 int level
= 0, interlace
= 0;
942 int packet_seq
= track
->vc1_info
.packet_seq
;
943 int packet_entry
= track
->vc1_info
.packet_entry
;
944 int slices
= track
->vc1_info
.slices
;
947 if (track
->start_dts
== AV_NOPTS_VALUE
) {
948 /* No packets written yet, vc1_info isn't authoritative yet. */
949 /* Assume inline sequence and entry headers. */
950 packet_seq
= packet_entry
= 1;
951 av_log(NULL
, AV_LOG_WARNING
,
952 "moov atom written before any packets, unable to write correct "
953 "dvc1 atom. Set the delay_moov flag to fix this.\n");
956 unescaped
= av_mallocz(track
->vos_len
+ AV_INPUT_BUFFER_PADDING_SIZE
);
958 return AVERROR(ENOMEM
);
959 start
= find_next_marker(track
->vos_data
, end
);
960 for (next
= start
; next
< end
; start
= next
) {
963 next
= find_next_marker(start
+ 4, end
);
964 size
= next
- start
- 4;
967 unescaped_size
= vc1_unescape_buffer(start
+ 4, size
, unescaped
);
968 init_get_bits(&gb
, unescaped
, 8 * unescaped_size
);
969 if (AV_RB32(start
) == VC1_CODE_SEQHDR
) {
970 int profile
= get_bits(&gb
, 2);
971 if (profile
!= PROFILE_ADVANCED
) {
973 return AVERROR(ENOSYS
);
976 level
= get_bits(&gb
, 3);
977 /* chromaformat, frmrtq_postproc, bitrtq_postproc, postprocflag,
979 skip_bits_long(&gb
, 2 + 3 + 5 + 1 + 2*12);
980 skip_bits(&gb
, 1); /* broadcast */
981 interlace
= get_bits1(&gb
);
982 skip_bits(&gb
, 4); /* tfcntrflag, finterpflag, reserved, psf */
987 return AVERROR(ENOSYS
);
990 init_put_bits(&pbc
, buf
, 7);
991 /* VC1DecSpecStruc */
992 put_bits(&pbc
, 4, 12); /* profile - advanced */
993 put_bits(&pbc
, 3, level
);
994 put_bits(&pbc
, 1, 0); /* reserved */
995 /* VC1AdvDecSpecStruc */
996 put_bits(&pbc
, 3, level
);
997 put_bits(&pbc
, 1, 0); /* cbr */
998 put_bits(&pbc
, 6, 0); /* reserved */
999 put_bits(&pbc
, 1, !interlace
); /* no interlace */
1000 put_bits(&pbc
, 1, !packet_seq
); /* no multiple seq */
1001 put_bits(&pbc
, 1, !packet_entry
); /* no multiple entry */
1002 put_bits(&pbc
, 1, !slices
); /* no slice code */
1003 put_bits(&pbc
, 1, 0); /* no bframe */
1004 put_bits(&pbc
, 1, 0); /* reserved */
1007 if (track
->st
->avg_frame_rate
.num
> 0 && track
->st
->avg_frame_rate
.den
> 0)
1008 put_bits32(&pbc
, track
->st
->avg_frame_rate
.num
/ track
->st
->avg_frame_rate
.den
);
1010 put_bits32(&pbc
, 0xffffffff);
1012 flush_put_bits(&pbc
);
1019 static int mov_write_dvc1_tag(AVIOContext
*pb
, MOVTrack
*track
)
1021 uint8_t buf
[7] = { 0 };
1024 if ((ret
= mov_write_dvc1_structs(track
, buf
)) < 0)
1027 avio_wb32(pb
, track
->vos_len
+ 8 + sizeof(buf
));
1028 ffio_wfourcc(pb
, "dvc1");
1029 avio_write(pb
, buf
, sizeof(buf
));
1030 avio_write(pb
, track
->vos_data
, track
->vos_len
);
1035 static int mov_write_glbl_tag(AVIOContext
*pb
, MOVTrack
*track
)
1037 avio_wb32(pb
, track
->vos_len
+ 8);
1038 ffio_wfourcc(pb
, "glbl");
1039 avio_write(pb
, track
->vos_data
, track
->vos_len
);
1040 return 8 + track
->vos_len
;
1044 * Compute flags for 'lpcm' tag.
1045 * See CoreAudioTypes and AudioStreamBasicDescription at Apple.
1047 static int mov_get_lpcm_flags(enum AVCodecID codec_id
)
1050 case AV_CODEC_ID_PCM_F32BE
:
1051 case AV_CODEC_ID_PCM_F64BE
:
1053 case AV_CODEC_ID_PCM_F32LE
:
1054 case AV_CODEC_ID_PCM_F64LE
:
1056 case AV_CODEC_ID_PCM_U8
:
1058 case AV_CODEC_ID_PCM_S16BE
:
1059 case AV_CODEC_ID_PCM_S24BE
:
1060 case AV_CODEC_ID_PCM_S32BE
:
1062 case AV_CODEC_ID_PCM_S8
:
1063 case AV_CODEC_ID_PCM_S16LE
:
1064 case AV_CODEC_ID_PCM_S24LE
:
1065 case AV_CODEC_ID_PCM_S32LE
:
1072 static int get_cluster_duration(MOVTrack
*track
, int cluster_idx
)
1076 if (cluster_idx
>= track
->entry
)
1079 if (cluster_idx
+ 1 == track
->entry
)
1080 next_dts
= track
->track_duration
+ track
->start_dts
;
1082 next_dts
= track
->cluster
[cluster_idx
+ 1].dts
;
1084 next_dts
-= track
->cluster
[cluster_idx
].dts
;
1086 av_assert0(next_dts
>= 0);
1087 av_assert0(next_dts
<= INT_MAX
);
1092 static int get_samples_per_packet(MOVTrack
*track
)
1094 int i
, first_duration
;
1096 // return track->par->frame_size;
1098 /* use 1 for raw PCM */
1099 if (!track
->audio_vbr
)
1102 /* check to see if duration is constant for all clusters */
1105 first_duration
= get_cluster_duration(track
, 0);
1106 for (i
= 1; i
< track
->entry
; i
++) {
1107 if (get_cluster_duration(track
, i
) != first_duration
)
1110 return first_duration
;
1113 static int mov_write_btrt_tag(AVIOContext
*pb
, MOVTrack
*track
)
1115 int64_t pos
= avio_tell(pb
);
1116 struct mpeg4_bit_rate_values bit_rates
= calculate_mpeg4_bit_rates(track
);
1117 if (!bit_rates
.max_bit_rate
&& !bit_rates
.avg_bit_rate
&&
1118 !bit_rates
.buffer_size
)
1119 // no useful data to be written, skip
1122 avio_wb32(pb
, 0); /* size */
1123 ffio_wfourcc(pb
, "btrt");
1125 avio_wb32(pb
, bit_rates
.buffer_size
);
1126 avio_wb32(pb
, bit_rates
.max_bit_rate
);
1127 avio_wb32(pb
, bit_rates
.avg_bit_rate
);
1129 return update_size(pb
, pos
);
1132 static int mov_write_audio_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVMuxContext
*mov
, MOVTrack
*track
)
1134 int64_t pos
= avio_tell(pb
);
1136 uint32_t tag
= track
->tag
;
1139 if (track
->mode
== MODE_MOV
) {
1140 if (track
->timescale
> UINT16_MAX
|| !track
->par
->channels
) {
1141 if (mov_get_lpcm_flags(track
->par
->codec_id
))
1142 tag
= AV_RL32("lpcm");
1144 } else if (track
->audio_vbr
|| mov_pcm_le_gt16(track
->par
->codec_id
) ||
1145 mov_pcm_be_gt16(track
->par
->codec_id
) ||
1146 track
->par
->codec_id
== AV_CODEC_ID_ADPCM_MS
||
1147 track
->par
->codec_id
== AV_CODEC_ID_ADPCM_IMA_WAV
||
1148 track
->par
->codec_id
== AV_CODEC_ID_QDM2
) {
1153 avio_wb32(pb
, 0); /* size */
1154 if (mov
->encryption_scheme
!= MOV_ENC_NONE
) {
1155 ffio_wfourcc(pb
, "enca");
1157 avio_wl32(pb
, tag
); // store it byteswapped
1159 avio_wb32(pb
, 0); /* Reserved */
1160 avio_wb16(pb
, 0); /* Reserved */
1161 avio_wb16(pb
, 1); /* Data-reference index, XXX == 1 */
1163 /* SoundDescription */
1164 avio_wb16(pb
, version
); /* Version */
1165 avio_wb16(pb
, 0); /* Revision level */
1166 avio_wb32(pb
, 0); /* Reserved */
1171 avio_wb16(pb
, 0xfffe);
1173 avio_wb32(pb
, 0x00010000);
1175 avio_wb64(pb
, av_double2int(track
->par
->sample_rate
));
1176 avio_wb32(pb
, track
->par
->channels
);
1177 avio_wb32(pb
, 0x7F000000);
1178 avio_wb32(pb
, av_get_bits_per_sample(track
->par
->codec_id
));
1179 avio_wb32(pb
, mov_get_lpcm_flags(track
->par
->codec_id
));
1180 avio_wb32(pb
, track
->sample_size
);
1181 avio_wb32(pb
, get_samples_per_packet(track
));
1183 if (track
->mode
== MODE_MOV
) {
1184 avio_wb16(pb
, track
->par
->channels
);
1185 if (track
->par
->codec_id
== AV_CODEC_ID_PCM_U8
||
1186 track
->par
->codec_id
== AV_CODEC_ID_PCM_S8
)
1187 avio_wb16(pb
, 8); /* bits per sample */
1188 else if (track
->par
->codec_id
== AV_CODEC_ID_ADPCM_G726
)
1189 avio_wb16(pb
, track
->par
->bits_per_coded_sample
);
1192 avio_wb16(pb
, track
->audio_vbr
? -2 : 0); /* compression ID */
1193 } else { /* reserved for mp4/3gp */
1194 if (track
->par
->codec_id
== AV_CODEC_ID_FLAC
||
1195 track
->par
->codec_id
== AV_CODEC_ID_ALAC
||
1196 track
->par
->codec_id
== AV_CODEC_ID_OPUS
) {
1197 avio_wb16(pb
, track
->par
->channels
);
1201 if (track
->par
->codec_id
== AV_CODEC_ID_FLAC
||
1202 track
->par
->codec_id
== AV_CODEC_ID_ALAC
) {
1203 avio_wb16(pb
, track
->par
->bits_per_raw_sample
);
1210 avio_wb16(pb
, 0); /* packet size (= 0) */
1211 if (track
->par
->codec_id
== AV_CODEC_ID_OPUS
)
1212 avio_wb16(pb
, 48000);
1213 else if (track
->par
->codec_id
== AV_CODEC_ID_TRUEHD
)
1214 avio_wb32(pb
, track
->par
->sample_rate
);
1216 avio_wb16(pb
, track
->par
->sample_rate
<= UINT16_MAX
?
1217 track
->par
->sample_rate
: 0);
1219 if (track
->par
->codec_id
!= AV_CODEC_ID_TRUEHD
)
1220 avio_wb16(pb
, 0); /* Reserved */
1223 if (version
== 1) { /* SoundDescription V1 extended info */
1224 if (mov_pcm_le_gt16(track
->par
->codec_id
) ||
1225 mov_pcm_be_gt16(track
->par
->codec_id
))
1226 avio_wb32(pb
, 1); /* must be 1 for uncompressed formats */
1228 avio_wb32(pb
, track
->par
->frame_size
); /* Samples per packet */
1229 avio_wb32(pb
, track
->sample_size
/ track
->par
->channels
); /* Bytes per packet */
1230 avio_wb32(pb
, track
->sample_size
); /* Bytes per frame */
1231 avio_wb32(pb
, 2); /* Bytes per sample */
1234 if (track
->mode
== MODE_MOV
&&
1235 (track
->par
->codec_id
== AV_CODEC_ID_AAC
||
1236 track
->par
->codec_id
== AV_CODEC_ID_AC3
||
1237 track
->par
->codec_id
== AV_CODEC_ID_EAC3
||
1238 track
->par
->codec_id
== AV_CODEC_ID_AMR_NB
||
1239 track
->par
->codec_id
== AV_CODEC_ID_ALAC
||
1240 track
->par
->codec_id
== AV_CODEC_ID_ADPCM_MS
||
1241 track
->par
->codec_id
== AV_CODEC_ID_ADPCM_IMA_WAV
||
1242 track
->par
->codec_id
== AV_CODEC_ID_QDM2
||
1243 (mov_pcm_le_gt16(track
->par
->codec_id
) && version
==1) ||
1244 (mov_pcm_be_gt16(track
->par
->codec_id
) && version
==1)))
1245 ret
= mov_write_wave_tag(s
, pb
, track
);
1246 else if (track
->tag
== MKTAG('m','p','4','a'))
1247 ret
= mov_write_esds_tag(pb
, track
);
1248 else if (track
->par
->codec_id
== AV_CODEC_ID_AMR_NB
)
1249 ret
= mov_write_amr_tag(pb
, track
);
1250 else if (track
->par
->codec_id
== AV_CODEC_ID_AC3
)
1251 ret
= mov_write_ac3_tag(s
, pb
, track
);
1252 else if (track
->par
->codec_id
== AV_CODEC_ID_EAC3
)
1253 ret
= mov_write_eac3_tag(s
, pb
, track
);
1254 else if (track
->par
->codec_id
== AV_CODEC_ID_ALAC
)
1255 ret
= mov_write_extradata_tag(pb
, track
);
1256 else if (track
->par
->codec_id
== AV_CODEC_ID_WMAPRO
)
1257 ret
= mov_write_wfex_tag(s
, pb
, track
);
1258 else if (track
->par
->codec_id
== AV_CODEC_ID_FLAC
)
1259 ret
= mov_write_dfla_tag(pb
, track
);
1260 else if (track
->par
->codec_id
== AV_CODEC_ID_OPUS
)
1261 ret
= mov_write_dops_tag(s
, pb
, track
);
1262 else if (track
->par
->codec_id
== AV_CODEC_ID_TRUEHD
)
1263 ret
= mov_write_dmlp_tag(s
, pb
, track
);
1264 else if (track
->vos_len
> 0)
1265 ret
= mov_write_glbl_tag(pb
, track
);
1270 if (track
->mode
== MODE_MOV
&& track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
1271 && ((ret
= mov_write_chan_tag(s
, pb
, track
)) < 0)) {
1275 if (mov
->encryption_scheme
!= MOV_ENC_NONE
1276 && ((ret
= ff_mov_cenc_write_sinf_tag(track
, pb
, mov
->encryption_kid
)) < 0)) {
1280 if (track
->mode
== MODE_MP4
&&
1281 ((ret
= mov_write_btrt_tag(pb
, track
)) < 0))
1284 ret
= update_size(pb
, pos
);
1288 static int mov_write_d263_tag(AVIOContext
*pb
)
1290 avio_wb32(pb
, 0xf); /* size */
1291 ffio_wfourcc(pb
, "d263");
1292 ffio_wfourcc(pb
, "FFMP");
1293 avio_w8(pb
, 0); /* decoder version */
1294 /* FIXME use AVCodecContext level/profile, when encoder will set values */
1295 avio_w8(pb
, 0xa); /* level */
1296 avio_w8(pb
, 0); /* profile */
1300 static int mov_write_av1c_tag(AVIOContext
*pb
, MOVTrack
*track
)
1302 int64_t pos
= avio_tell(pb
);
1305 ffio_wfourcc(pb
, "av1C");
1306 ff_isom_write_av1c(pb
, track
->vos_data
, track
->vos_len
);
1307 return update_size(pb
, pos
);
1310 static int mov_write_avcc_tag(AVIOContext
*pb
, MOVTrack
*track
)
1312 int64_t pos
= avio_tell(pb
);
1315 ffio_wfourcc(pb
, "avcC");
1316 ff_isom_write_avcc(pb
, track
->vos_data
, track
->vos_len
);
1317 return update_size(pb
, pos
);
1320 static int mov_write_vpcc_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
1322 int64_t pos
= avio_tell(pb
);
1325 ffio_wfourcc(pb
, "vpcC");
1326 avio_w8(pb
, 1); /* version */
1327 avio_wb24(pb
, 0); /* flags */
1328 ff_isom_write_vpcc(s
, pb
, track
->par
);
1329 return update_size(pb
, pos
);
1332 static int mov_write_hvcc_tag(AVIOContext
*pb
, MOVTrack
*track
)
1334 int64_t pos
= avio_tell(pb
);
1337 ffio_wfourcc(pb
, "hvcC");
1338 if (track
->tag
== MKTAG('h','v','c','1'))
1339 ff_isom_write_hvcc(pb
, track
->vos_data
, track
->vos_len
, 1);
1341 ff_isom_write_hvcc(pb
, track
->vos_data
, track
->vos_len
, 0);
1342 return update_size(pb
, pos
);
1345 /* also used by all avid codecs (dv, imx, meridien) and their variants */
1346 static int mov_write_avid_tag(AVIOContext
*pb
, MOVTrack
*track
)
1350 int display_width
= track
->par
->width
;
1352 if (track
->vos_data
&& track
->vos_len
> 0x29) {
1353 if (ff_dnxhd_parse_header_prefix(track
->vos_data
) != 0) {
1354 /* looks like a DNxHD bit stream */
1355 interlaced
= (track
->vos_data
[5] & 2);
1356 cid
= AV_RB32(track
->vos_data
+ 0x28);
1358 av_log(NULL
, AV_LOG_WARNING
, "Could not locate DNxHD bit stream in vos_data\n");
1362 av_log(NULL
, AV_LOG_WARNING
, "Could not locate DNxHD bit stream, vos_data too small\n");
1366 avio_wb32(pb
, 24); /* size */
1367 ffio_wfourcc(pb
, "ACLR");
1368 ffio_wfourcc(pb
, "ACLR");
1369 ffio_wfourcc(pb
, "0001");
1370 if (track
->par
->color_range
== AVCOL_RANGE_MPEG
|| /* Legal range (16-235) */
1371 track
->par
->color_range
== AVCOL_RANGE_UNSPECIFIED
) {
1372 avio_wb32(pb
, 1); /* Corresponds to 709 in official encoder */
1373 } else { /* Full range (0-255) */
1374 avio_wb32(pb
, 2); /* Corresponds to RGB in official encoder */
1376 avio_wb32(pb
, 0); /* unknown */
1378 if (track
->tag
== MKTAG('A','V','d','h')) {
1380 ffio_wfourcc(pb
, "ADHR");
1381 ffio_wfourcc(pb
, "0001");
1383 avio_wb32(pb
, 0); /* unknown */
1384 avio_wb32(pb
, 1); /* unknown */
1385 avio_wb32(pb
, 0); /* unknown */
1386 avio_wb32(pb
, 0); /* unknown */
1390 avio_wb32(pb
, 24); /* size */
1391 ffio_wfourcc(pb
, "APRG");
1392 ffio_wfourcc(pb
, "APRG");
1393 ffio_wfourcc(pb
, "0001");
1394 avio_wb32(pb
, 1); /* unknown */
1395 avio_wb32(pb
, 0); /* unknown */
1397 avio_wb32(pb
, 120); /* size */
1398 ffio_wfourcc(pb
, "ARES");
1399 ffio_wfourcc(pb
, "ARES");
1400 ffio_wfourcc(pb
, "0001");
1401 avio_wb32(pb
, cid
); /* dnxhd cid, some id ? */
1402 if ( track
->par
->sample_aspect_ratio
.num
> 0
1403 && track
->par
->sample_aspect_ratio
.den
> 0)
1404 display_width
= display_width
* track
->par
->sample_aspect_ratio
.num
/ track
->par
->sample_aspect_ratio
.den
;
1405 avio_wb32(pb
, display_width
);
1406 /* values below are based on samples created with quicktime and avid codecs */
1408 avio_wb32(pb
, track
->par
->height
/ 2);
1409 avio_wb32(pb
, 2); /* unknown */
1410 avio_wb32(pb
, 0); /* unknown */
1411 avio_wb32(pb
, 4); /* unknown */
1413 avio_wb32(pb
, track
->par
->height
);
1414 avio_wb32(pb
, 1); /* unknown */
1415 avio_wb32(pb
, 0); /* unknown */
1416 if (track
->par
->height
== 1080)
1417 avio_wb32(pb
, 5); /* unknown */
1419 avio_wb32(pb
, 6); /* unknown */
1422 ffio_fill(pb
, 0, 10 * 8);
1427 static int mov_write_dpxe_tag(AVIOContext
*pb
, MOVTrack
*track
)
1430 ffio_wfourcc(pb
, "DpxE");
1431 if (track
->par
->extradata_size
>= 12 &&
1432 !memcmp(&track
->par
->extradata
[4], "DpxE", 4)) {
1433 avio_wb32(pb
, track
->par
->extradata
[11]);
1440 static int mov_get_dv_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
1444 if (track
->par
->width
== 720) { /* SD */
1445 if (track
->par
->height
== 480) { /* NTSC */
1446 if (track
->par
->format
== AV_PIX_FMT_YUV422P
) tag
= MKTAG('d','v','5','n');
1447 else tag
= MKTAG('d','v','c',' ');
1448 }else if (track
->par
->format
== AV_PIX_FMT_YUV422P
) tag
= MKTAG('d','v','5','p');
1449 else if (track
->par
->format
== AV_PIX_FMT_YUV420P
) tag
= MKTAG('d','v','c','p');
1450 else tag
= MKTAG('d','v','p','p');
1451 } else if (track
->par
->height
== 720) { /* HD 720 line */
1452 if (track
->st
->time_base
.den
== 50) tag
= MKTAG('d','v','h','q');
1453 else tag
= MKTAG('d','v','h','p');
1454 } else if (track
->par
->height
== 1080) { /* HD 1080 line */
1455 if (track
->st
->time_base
.den
== 25) tag
= MKTAG('d','v','h','5');
1456 else tag
= MKTAG('d','v','h','6');
1458 av_log(s
, AV_LOG_ERROR
, "unsupported height for dv codec\n");
1465 static int defined_frame_rate(AVFormatContext
*s
, AVStream
*st
)
1467 AVRational rational_framerate
= st
->avg_frame_rate
;
1469 if (rational_framerate
.den
!= 0)
1470 rate
= av_q2d(rational_framerate
);
1474 static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
1476 int tag
= track
->par
->codec_tag
;
1477 int interlaced
= track
->par
->field_order
> AV_FIELD_PROGRESSIVE
;
1478 AVStream
*st
= track
->st
;
1479 int rate
= defined_frame_rate(s
, st
);
1482 tag
= MKTAG('m', '2', 'v', '1'); //fallback tag
1484 if (track
->par
->format
== AV_PIX_FMT_YUV420P
) {
1485 if (track
->par
->width
== 1280 && track
->par
->height
== 720) {
1487 if (rate
== 24) tag
= MKTAG('x','d','v','4');
1488 else if (rate
== 25) tag
= MKTAG('x','d','v','5');
1489 else if (rate
== 30) tag
= MKTAG('x','d','v','1');
1490 else if (rate
== 50) tag
= MKTAG('x','d','v','a');
1491 else if (rate
== 60) tag
= MKTAG('x','d','v','9');
1493 } else if (track
->par
->width
== 1440 && track
->par
->height
== 1080) {
1495 if (rate
== 24) tag
= MKTAG('x','d','v','6');
1496 else if (rate
== 25) tag
= MKTAG('x','d','v','7');
1497 else if (rate
== 30) tag
= MKTAG('x','d','v','8');
1499 if (rate
== 25) tag
= MKTAG('x','d','v','3');
1500 else if (rate
== 30) tag
= MKTAG('x','d','v','2');
1502 } else if (track
->par
->width
== 1920 && track
->par
->height
== 1080) {
1504 if (rate
== 24) tag
= MKTAG('x','d','v','d');
1505 else if (rate
== 25) tag
= MKTAG('x','d','v','e');
1506 else if (rate
== 30) tag
= MKTAG('x','d','v','f');
1508 if (rate
== 25) tag
= MKTAG('x','d','v','c');
1509 else if (rate
== 30) tag
= MKTAG('x','d','v','b');
1512 } else if (track
->par
->format
== AV_PIX_FMT_YUV422P
) {
1513 if (track
->par
->width
== 1280 && track
->par
->height
== 720) {
1515 if (rate
== 24) tag
= MKTAG('x','d','5','4');
1516 else if (rate
== 25) tag
= MKTAG('x','d','5','5');
1517 else if (rate
== 30) tag
= MKTAG('x','d','5','1');
1518 else if (rate
== 50) tag
= MKTAG('x','d','5','a');
1519 else if (rate
== 60) tag
= MKTAG('x','d','5','9');
1521 } else if (track
->par
->width
== 1920 && track
->par
->height
== 1080) {
1523 if (rate
== 24) tag
= MKTAG('x','d','5','d');
1524 else if (rate
== 25) tag
= MKTAG('x','d','5','e');
1525 else if (rate
== 30) tag
= MKTAG('x','d','5','f');
1527 if (rate
== 25) tag
= MKTAG('x','d','5','c');
1528 else if (rate
== 30) tag
= MKTAG('x','d','5','b');
1536 static int mov_get_h264_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
1538 int tag
= track
->par
->codec_tag
;
1539 int interlaced
= track
->par
->field_order
> AV_FIELD_PROGRESSIVE
;
1540 AVStream
*st
= track
->st
;
1541 int rate
= defined_frame_rate(s
, st
);
1544 tag
= MKTAG('a', 'v', 'c', 'i'); //fallback tag
1546 if (track
->par
->format
== AV_PIX_FMT_YUV420P10
) {
1547 if (track
->par
->width
== 960 && track
->par
->height
== 720) {
1549 if (rate
== 24) tag
= MKTAG('a','i','5','p');
1550 else if (rate
== 25) tag
= MKTAG('a','i','5','q');
1551 else if (rate
== 30) tag
= MKTAG('a','i','5','p');
1552 else if (rate
== 50) tag
= MKTAG('a','i','5','q');
1553 else if (rate
== 60) tag
= MKTAG('a','i','5','p');
1555 } else if (track
->par
->width
== 1440 && track
->par
->height
== 1080) {
1557 if (rate
== 24) tag
= MKTAG('a','i','5','3');
1558 else if (rate
== 25) tag
= MKTAG('a','i','5','2');
1559 else if (rate
== 30) tag
= MKTAG('a','i','5','3');
1561 if (rate
== 50) tag
= MKTAG('a','i','5','5');
1562 else if (rate
== 60) tag
= MKTAG('a','i','5','6');
1565 } else if (track
->par
->format
== AV_PIX_FMT_YUV422P10
) {
1566 if (track
->par
->width
== 1280 && track
->par
->height
== 720) {
1568 if (rate
== 24) tag
= MKTAG('a','i','1','p');
1569 else if (rate
== 25) tag
= MKTAG('a','i','1','q');
1570 else if (rate
== 30) tag
= MKTAG('a','i','1','p');
1571 else if (rate
== 50) tag
= MKTAG('a','i','1','q');
1572 else if (rate
== 60) tag
= MKTAG('a','i','1','p');
1574 } else if (track
->par
->width
== 1920 && track
->par
->height
== 1080) {
1576 if (rate
== 24) tag
= MKTAG('a','i','1','3');
1577 else if (rate
== 25) tag
= MKTAG('a','i','1','2');
1578 else if (rate
== 30) tag
= MKTAG('a','i','1','3');
1580 if (rate
== 25) tag
= MKTAG('a','i','1','5');
1581 else if (rate
== 50) tag
= MKTAG('a','i','1','5');
1582 else if (rate
== 60) tag
= MKTAG('a','i','1','6');
1584 } else if ( track
->par
->width
== 4096 && track
->par
->height
== 2160
1585 || track
->par
->width
== 3840 && track
->par
->height
== 2160
1586 || track
->par
->width
== 2048 && track
->par
->height
== 1080) {
1587 tag
= MKTAG('a','i','v','x');
1594 static const struct {
1595 enum AVPixelFormat pix_fmt
;
1598 } mov_pix_fmt_tags
[] = {
1599 { AV_PIX_FMT_YUYV422
, MKTAG('y','u','v','2'), 0 },
1600 { AV_PIX_FMT_YUYV422
, MKTAG('y','u','v','s'), 0 },
1601 { AV_PIX_FMT_UYVY422
, MKTAG('2','v','u','y'), 0 },
1602 { AV_PIX_FMT_RGB555BE
,MKTAG('r','a','w',' '), 16 },
1603 { AV_PIX_FMT_RGB555LE
,MKTAG('L','5','5','5'), 16 },
1604 { AV_PIX_FMT_RGB565LE
,MKTAG('L','5','6','5'), 16 },
1605 { AV_PIX_FMT_RGB565BE
,MKTAG('B','5','6','5'), 16 },
1606 { AV_PIX_FMT_GRAY16BE
,MKTAG('b','1','6','g'), 16 },
1607 { AV_PIX_FMT_RGB24
, MKTAG('r','a','w',' '), 24 },
1608 { AV_PIX_FMT_BGR24
, MKTAG('2','4','B','G'), 24 },
1609 { AV_PIX_FMT_ARGB
, MKTAG('r','a','w',' '), 32 },
1610 { AV_PIX_FMT_BGRA
, MKTAG('B','G','R','A'), 32 },
1611 { AV_PIX_FMT_RGBA
, MKTAG('R','G','B','A'), 32 },
1612 { AV_PIX_FMT_ABGR
, MKTAG('A','B','G','R'), 32 },
1613 { AV_PIX_FMT_RGB48BE
, MKTAG('b','4','8','r'), 48 },
1616 static int mov_get_dnxhd_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
1618 int tag
= MKTAG('A','V','d','n');
1619 if (track
->par
->profile
!= FF_PROFILE_UNKNOWN
&&
1620 track
->par
->profile
!= FF_PROFILE_DNXHD
)
1621 tag
= MKTAG('A','V','d','h');
1625 static int mov_get_rawvideo_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
1627 int tag
= track
->par
->codec_tag
;
1629 enum AVPixelFormat pix_fmt
;
1631 for (i
= 0; i
< FF_ARRAY_ELEMS(mov_pix_fmt_tags
); i
++) {
1632 if (track
->par
->format
== mov_pix_fmt_tags
[i
].pix_fmt
) {
1633 tag
= mov_pix_fmt_tags
[i
].tag
;
1634 track
->par
->bits_per_coded_sample
= mov_pix_fmt_tags
[i
].bps
;
1635 if (track
->par
->codec_tag
== mov_pix_fmt_tags
[i
].tag
)
1640 pix_fmt
= avpriv_pix_fmt_find(PIX_FMT_LIST_MOV
,
1641 track
->par
->bits_per_coded_sample
);
1642 if (tag
== MKTAG('r','a','w',' ') &&
1643 track
->par
->format
!= pix_fmt
&&
1644 track
->par
->format
!= AV_PIX_FMT_GRAY8
&&
1645 track
->par
->format
!= AV_PIX_FMT_NONE
)
1646 av_log(s
, AV_LOG_ERROR
, "%s rawvideo cannot be written to mov, output file will be unreadable\n",
1647 av_get_pix_fmt_name(track
->par
->format
));
1651 static unsigned int mov_get_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
1653 unsigned int tag
= track
->par
->codec_tag
;
1655 // "rtp " is used to distinguish internally created RTP-hint tracks
1656 // (with rtp_ctx) from other tracks.
1657 if (tag
== MKTAG('r','t','p',' '))
1659 if (!tag
|| (s
->strict_std_compliance
>= FF_COMPLIANCE_NORMAL
&&
1660 (track
->par
->codec_id
== AV_CODEC_ID_DVVIDEO
||
1661 track
->par
->codec_id
== AV_CODEC_ID_RAWVIDEO
||
1662 track
->par
->codec_id
== AV_CODEC_ID_H263
||
1663 track
->par
->codec_id
== AV_CODEC_ID_H264
||
1664 track
->par
->codec_id
== AV_CODEC_ID_DNXHD
||
1665 track
->par
->codec_id
== AV_CODEC_ID_MPEG2VIDEO
||
1666 av_get_bits_per_sample(track
->par
->codec_id
)))) { // pcm audio
1667 if (track
->par
->codec_id
== AV_CODEC_ID_DVVIDEO
)
1668 tag
= mov_get_dv_codec_tag(s
, track
);
1669 else if (track
->par
->codec_id
== AV_CODEC_ID_RAWVIDEO
)
1670 tag
= mov_get_rawvideo_codec_tag(s
, track
);
1671 else if (track
->par
->codec_id
== AV_CODEC_ID_MPEG2VIDEO
)
1672 tag
= mov_get_mpeg2_xdcam_codec_tag(s
, track
);
1673 else if (track
->par
->codec_id
== AV_CODEC_ID_H264
)
1674 tag
= mov_get_h264_codec_tag(s
, track
);
1675 else if (track
->par
->codec_id
== AV_CODEC_ID_DNXHD
)
1676 tag
= mov_get_dnxhd_codec_tag(s
, track
);
1677 else if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
1678 tag
= ff_codec_get_tag(ff_codec_movvideo_tags
, track
->par
->codec_id
);
1679 if (!tag
) { // if no mac fcc found, try with Microsoft tags
1680 tag
= ff_codec_get_tag(ff_codec_bmp_tags
, track
->par
->codec_id
);
1682 av_log(s
, AV_LOG_WARNING
, "Using MS style video codec tag, "
1683 "the file may be unplayable!\n");
1685 } else if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
1686 tag
= ff_codec_get_tag(ff_codec_movaudio_tags
, track
->par
->codec_id
);
1687 if (!tag
) { // if no mac fcc found, try with Microsoft tags
1688 int ms_tag
= ff_codec_get_tag(ff_codec_wav_tags
, track
->par
->codec_id
);
1690 tag
= MKTAG('m', 's', ((ms_tag
>> 8) & 0xff), (ms_tag
& 0xff));
1691 av_log(s
, AV_LOG_WARNING
, "Using MS style audio codec tag, "
1692 "the file may be unplayable!\n");
1695 } else if (track
->par
->codec_type
== AVMEDIA_TYPE_SUBTITLE
)
1696 tag
= ff_codec_get_tag(ff_codec_movsubtitle_tags
, track
->par
->codec_id
);
1702 static const AVCodecTag codec_cover_image_tags
[] = {
1703 { AV_CODEC_ID_MJPEG
, 0xD },
1704 { AV_CODEC_ID_PNG
, 0xE },
1705 { AV_CODEC_ID_BMP
, 0x1B },
1706 { AV_CODEC_ID_NONE
, 0 },
1709 static unsigned int validate_codec_tag(const AVCodecTag
*const *tags
,
1710 unsigned int tag
, int codec_id
)
1715 * Check that tag + id is in the table
1717 for (i
= 0; tags
&& tags
[i
]; i
++) {
1718 const AVCodecTag
*codec_tags
= tags
[i
];
1719 while (codec_tags
->id
!= AV_CODEC_ID_NONE
) {
1720 if (ff_toupper4(codec_tags
->tag
) == ff_toupper4(tag
) &&
1721 codec_tags
->id
== codec_id
)
1722 return codec_tags
->tag
;
1729 static unsigned int mov_find_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
1731 if (is_cover_image(track
->st
))
1732 return ff_codec_get_tag(codec_cover_image_tags
, track
->par
->codec_id
);
1734 if (track
->mode
== MODE_IPOD
)
1735 if (!av_match_ext(s
->url
, "m4a") &&
1736 !av_match_ext(s
->url
, "m4v") &&
1737 !av_match_ext(s
->url
, "m4b"))
1738 av_log(s
, AV_LOG_WARNING
, "Warning, extension is not .m4a nor .m4v "
1739 "Quicktime/Ipod might not play the file\n");
1741 if (track
->mode
== MODE_MOV
) {
1742 return mov_get_codec_tag(s
, track
);
1744 return validate_codec_tag(s
->oformat
->codec_tag
, track
->par
->codec_tag
,
1745 track
->par
->codec_id
);
1748 /** Write uuid atom.
1749 * Needed to make file play in iPods running newest firmware
1750 * goes after avcC atom in moov.trak.mdia.minf.stbl.stsd.avc1
1752 static int mov_write_uuid_tag_ipod(AVIOContext
*pb
)
1755 ffio_wfourcc(pb
, "uuid");
1756 avio_wb32(pb
, 0x6b6840f2);
1757 avio_wb32(pb
, 0x5f244fc5);
1758 avio_wb32(pb
, 0xba39a51b);
1759 avio_wb32(pb
, 0xcf0323f3);
1764 static const uint16_t fiel_data
[] = {
1765 0x0000, 0x0100, 0x0201, 0x0206, 0x0209, 0x020e
1768 static int mov_write_fiel_tag(AVIOContext
*pb
, MOVTrack
*track
, int field_order
)
1770 unsigned mov_field_order
= 0;
1771 if (field_order
< FF_ARRAY_ELEMS(fiel_data
))
1772 mov_field_order
= fiel_data
[field_order
];
1776 ffio_wfourcc(pb
, "fiel");
1777 avio_wb16(pb
, mov_field_order
);
1781 static int mov_write_subtitle_tag(AVIOContext
*pb
, MOVTrack
*track
)
1783 int ret
= AVERROR_BUG
;
1784 int64_t pos
= avio_tell(pb
);
1785 avio_wb32(pb
, 0); /* size */
1786 avio_wl32(pb
, track
->tag
); // store it byteswapped
1787 avio_wb32(pb
, 0); /* Reserved */
1788 avio_wb16(pb
, 0); /* Reserved */
1789 avio_wb16(pb
, 1); /* Data-reference index */
1791 if (track
->par
->codec_id
== AV_CODEC_ID_DVD_SUBTITLE
)
1792 mov_write_esds_tag(pb
, track
);
1793 else if (track
->par
->codec_id
== AV_CODEC_ID_TTML
) {
1794 switch (track
->par
->codec_tag
) {
1795 case MOV_ISMV_TTML_TAG
:
1796 // ISMV dfxp requires no extradata.
1798 case MOV_MP4_TTML_TAG
:
1799 // As specified in 14496-30, XMLSubtitleSampleEntry
1801 avio_put_str(pb
, "http://www.w3.org/ns/ttml");
1802 // Empty schema_location
1804 // Empty auxiliary_mime_types
1808 av_log(NULL
, AV_LOG_ERROR
,
1809 "Unknown codec tag '%s' utilized for TTML stream with "
1810 "index %d (track id %d)!\n",
1811 av_fourcc2str(track
->par
->codec_tag
), track
->st
->index
,
1813 return AVERROR(EINVAL
);
1815 } else if (track
->par
->extradata_size
)
1816 avio_write(pb
, track
->par
->extradata
, track
->par
->extradata_size
);
1818 if (track
->mode
== MODE_MP4
&&
1819 ((ret
= mov_write_btrt_tag(pb
, track
)) < 0))
1822 return update_size(pb
, pos
);
1825 static int mov_write_st3d_tag(AVFormatContext
*s
, AVIOContext
*pb
, AVStereo3D
*stereo_3d
)
1829 if (stereo_3d
->flags
!= 0) {
1830 av_log(s
, AV_LOG_WARNING
, "Unsupported stereo_3d flags %x. st3d not written.\n", stereo_3d
->flags
);
1834 switch (stereo_3d
->type
) {
1835 case AV_STEREO3D_2D
:
1838 case AV_STEREO3D_TOPBOTTOM
:
1841 case AV_STEREO3D_SIDEBYSIDE
:
1845 av_log(s
, AV_LOG_WARNING
, "Unsupported stereo_3d type %s. st3d not written.\n", av_stereo3d_type_name(stereo_3d
->type
));
1848 avio_wb32(pb
, 13); /* size */
1849 ffio_wfourcc(pb
, "st3d");
1850 avio_wb32(pb
, 0); /* version = 0 & flags = 0 */
1851 avio_w8(pb
, stereo_mode
);
1855 static int mov_write_sv3d_tag(AVFormatContext
*s
, AVIOContext
*pb
, AVSphericalMapping
*spherical_mapping
)
1857 int64_t sv3d_pos
, svhd_pos
, proj_pos
;
1858 const char* metadata_source
= s
->flags
& AVFMT_FLAG_BITEXACT
? "Lavf" : LIBAVFORMAT_IDENT
;
1860 if (spherical_mapping
->projection
!= AV_SPHERICAL_EQUIRECTANGULAR
&&
1861 spherical_mapping
->projection
!= AV_SPHERICAL_EQUIRECTANGULAR_TILE
&&
1862 spherical_mapping
->projection
!= AV_SPHERICAL_CUBEMAP
) {
1863 av_log(s
, AV_LOG_WARNING
, "Unsupported projection %d. sv3d not written.\n", spherical_mapping
->projection
);
1867 sv3d_pos
= avio_tell(pb
);
1868 avio_wb32(pb
, 0); /* size */
1869 ffio_wfourcc(pb
, "sv3d");
1871 svhd_pos
= avio_tell(pb
);
1872 avio_wb32(pb
, 0); /* size */
1873 ffio_wfourcc(pb
, "svhd");
1874 avio_wb32(pb
, 0); /* version = 0 & flags = 0 */
1875 avio_put_str(pb
, metadata_source
);
1876 update_size(pb
, svhd_pos
);
1878 proj_pos
= avio_tell(pb
);
1879 avio_wb32(pb
, 0); /* size */
1880 ffio_wfourcc(pb
, "proj");
1882 avio_wb32(pb
, 24); /* size */
1883 ffio_wfourcc(pb
, "prhd");
1884 avio_wb32(pb
, 0); /* version = 0 & flags = 0 */
1885 avio_wb32(pb
, spherical_mapping
->yaw
);
1886 avio_wb32(pb
, spherical_mapping
->pitch
);
1887 avio_wb32(pb
, spherical_mapping
->roll
);
1889 switch (spherical_mapping
->projection
) {
1890 case AV_SPHERICAL_EQUIRECTANGULAR
:
1891 case AV_SPHERICAL_EQUIRECTANGULAR_TILE
:
1892 avio_wb32(pb
, 28); /* size */
1893 ffio_wfourcc(pb
, "equi");
1894 avio_wb32(pb
, 0); /* version = 0 & flags = 0 */
1895 avio_wb32(pb
, spherical_mapping
->bound_top
);
1896 avio_wb32(pb
, spherical_mapping
->bound_bottom
);
1897 avio_wb32(pb
, spherical_mapping
->bound_left
);
1898 avio_wb32(pb
, spherical_mapping
->bound_right
);
1900 case AV_SPHERICAL_CUBEMAP
:
1901 avio_wb32(pb
, 20); /* size */
1902 ffio_wfourcc(pb
, "cbmp");
1903 avio_wb32(pb
, 0); /* version = 0 & flags = 0 */
1904 avio_wb32(pb
, 0); /* layout */
1905 avio_wb32(pb
, spherical_mapping
->padding
); /* padding */
1908 update_size(pb
, proj_pos
);
1910 return update_size(pb
, sv3d_pos
);
1913 static int mov_write_dvcc_dvvc_tag(AVFormatContext
*s
, AVIOContext
*pb
, AVDOVIDecoderConfigurationRecord
*dovi
)
1915 uint8_t buf
[ISOM_DVCC_DVVC_SIZE
];
1917 avio_wb32(pb
, 32); /* size = 8 + 24 */
1918 if (dovi
->dv_profile
> 10)
1919 ffio_wfourcc(pb
, "dvwC");
1920 else if (dovi
->dv_profile
> 7)
1921 ffio_wfourcc(pb
, "dvvC");
1923 ffio_wfourcc(pb
, "dvcC");
1925 ff_isom_put_dvcc_dvvc(s
, buf
, dovi
);
1926 avio_write(pb
, buf
, sizeof(buf
));
1928 return 32; /* 8 + 24 */
1931 static int mov_write_clap_tag(AVIOContext
*pb
, MOVTrack
*track
)
1934 ffio_wfourcc(pb
, "clap");
1935 avio_wb32(pb
, track
->par
->width
); /* apertureWidth_N */
1936 avio_wb32(pb
, 1); /* apertureWidth_D (= 1) */
1937 avio_wb32(pb
, track
->height
); /* apertureHeight_N */
1938 avio_wb32(pb
, 1); /* apertureHeight_D (= 1) */
1939 avio_wb32(pb
, 0); /* horizOff_N (= 0) */
1940 avio_wb32(pb
, 1); /* horizOff_D (= 1) */
1941 avio_wb32(pb
, 0); /* vertOff_N (= 0) */
1942 avio_wb32(pb
, 1); /* vertOff_D (= 1) */
1946 static int mov_write_pasp_tag(AVIOContext
*pb
, MOVTrack
*track
)
1949 av_reduce(&sar
.num
, &sar
.den
, track
->par
->sample_aspect_ratio
.num
,
1950 track
->par
->sample_aspect_ratio
.den
, INT_MAX
);
1953 ffio_wfourcc(pb
, "pasp");
1954 avio_wb32(pb
, sar
.num
);
1955 avio_wb32(pb
, sar
.den
);
1959 static int mov_write_gama_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
, double gamma
)
1963 gamma
= avpriv_get_gamma_from_trc(track
->par
->color_trc
);
1965 av_log(s
, AV_LOG_DEBUG
, "gamma value %g\n", gamma
);
1968 gama
= (uint32_t)lrint((double)(1<<16) * gamma
);
1969 av_log(s
, AV_LOG_DEBUG
, "writing gama value %"PRId32
"\n", gama
);
1971 av_assert0(track
->mode
== MODE_MOV
);
1973 ffio_wfourcc(pb
, "gama");
1974 avio_wb32(pb
, gama
);
1977 av_log(s
, AV_LOG_WARNING
, "gamma value unknown, unable to write gama atom\n");
1982 static int mov_write_colr_tag(AVIOContext
*pb
, MOVTrack
*track
, int prefer_icc
)
1984 int64_t pos
= avio_tell(pb
);
1986 // Ref (MOV): https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9
1987 // Ref (MP4): ISO/IEC 14496-12:2012
1989 const uint8_t *icc_profile
;
1990 size_t icc_profile_size
;
1993 icc_profile
= av_stream_get_side_data(track
->st
, AV_PKT_DATA_ICC_PROFILE
, &icc_profile_size
);
1996 avio_wb32(pb
, 12 + icc_profile_size
);
1997 ffio_wfourcc(pb
, "colr");
1998 ffio_wfourcc(pb
, "prof");
1999 avio_write(pb
, icc_profile
, icc_profile_size
);
2000 return 12 + icc_profile_size
;
2003 av_log(NULL
, AV_LOG_INFO
, "no ICC profile found, will write nclx/nclc colour info instead\n");
2007 /* We should only ever be called by MOV or MP4. */
2008 av_assert0(track
->mode
== MODE_MOV
|| track
->mode
== MODE_MP4
);
2010 avio_wb32(pb
, 0); /* size */
2011 ffio_wfourcc(pb
, "colr");
2012 if (track
->mode
== MODE_MP4
)
2013 ffio_wfourcc(pb
, "nclx");
2015 ffio_wfourcc(pb
, "nclc");
2016 // Do not try to guess the color info if it is AVCOL_PRI_UNSPECIFIED.
2017 // e.g., Dolby Vision for Apple devices should be set to AVCOL_PRI_UNSPECIFIED. See
2018 // https://developer.apple.com/av-foundation/High-Dynamic-Range-Metadata-for-Apple-Devices.pdf
2019 avio_wb16(pb
, track
->par
->color_primaries
);
2020 avio_wb16(pb
, track
->par
->color_trc
);
2021 avio_wb16(pb
, track
->par
->color_space
);
2022 if (track
->mode
== MODE_MP4
) {
2023 int full_range
= track
->par
->color_range
== AVCOL_RANGE_JPEG
;
2024 avio_w8(pb
, full_range
<< 7);
2027 return update_size(pb
, pos
);
2030 static int mov_write_clli_tag(AVIOContext
*pb
, MOVTrack
*track
)
2032 const uint8_t *side_data
;
2033 const AVContentLightMetadata
*content_light_metadata
;
2035 side_data
= av_stream_get_side_data(track
->st
, AV_PKT_DATA_CONTENT_LIGHT_LEVEL
, NULL
);
2039 content_light_metadata
= (const AVContentLightMetadata
*)side_data
;
2041 avio_wb32(pb
, 12); // size
2042 ffio_wfourcc(pb
, "clli");
2043 avio_wb16(pb
, content_light_metadata
->MaxCLL
);
2044 avio_wb16(pb
, content_light_metadata
->MaxFALL
);
2048 static inline int64_t rescale_mdcv(AVRational q
, int b
)
2050 return av_rescale(q
.num
, b
, q
.den
);
2053 static int mov_write_mdcv_tag(AVIOContext
*pb
, MOVTrack
*track
)
2055 const int chroma_den
= 50000;
2056 const int luma_den
= 10000;
2057 const uint8_t *side_data
;
2058 const AVMasteringDisplayMetadata
*metadata
;
2060 side_data
= av_stream_get_side_data(track
->st
, AV_PKT_DATA_MASTERING_DISPLAY_METADATA
, NULL
);
2061 metadata
= (const AVMasteringDisplayMetadata
*)side_data
;
2062 if (!metadata
|| !metadata
->has_primaries
|| !metadata
->has_luminance
) {
2066 avio_wb32(pb
, 32); // size
2067 ffio_wfourcc(pb
, "mdcv");
2068 avio_wb16(pb
, rescale_mdcv(metadata
->display_primaries
[1][0], chroma_den
));
2069 avio_wb16(pb
, rescale_mdcv(metadata
->display_primaries
[1][1], chroma_den
));
2070 avio_wb16(pb
, rescale_mdcv(metadata
->display_primaries
[2][0], chroma_den
));
2071 avio_wb16(pb
, rescale_mdcv(metadata
->display_primaries
[2][1], chroma_den
));
2072 avio_wb16(pb
, rescale_mdcv(metadata
->display_primaries
[0][0], chroma_den
));
2073 avio_wb16(pb
, rescale_mdcv(metadata
->display_primaries
[0][1], chroma_den
));
2074 avio_wb16(pb
, rescale_mdcv(metadata
->white_point
[0], chroma_den
));
2075 avio_wb16(pb
, rescale_mdcv(metadata
->white_point
[1], chroma_den
));
2076 avio_wb32(pb
, rescale_mdcv(metadata
->max_luminance
, luma_den
));
2077 avio_wb32(pb
, rescale_mdcv(metadata
->min_luminance
, luma_den
));
2081 static void find_compressor(char * compressor_name
, int len
, MOVTrack
*track
)
2083 AVDictionaryEntry
*encoder
;
2084 int xdcam_res
= (track
->par
->width
== 1280 && track
->par
->height
== 720)
2085 || (track
->par
->width
== 1440 && track
->par
->height
== 1080)
2086 || (track
->par
->width
== 1920 && track
->par
->height
== 1080);
2088 if (track
->mode
== MODE_MOV
&&
2089 (encoder
= av_dict_get(track
->st
->metadata
, "encoder", NULL
, 0))) {
2090 av_strlcpy(compressor_name
, encoder
->value
, 32);
2091 } else if (track
->par
->codec_id
== AV_CODEC_ID_MPEG2VIDEO
&& xdcam_res
) {
2092 int interlaced
= track
->par
->field_order
> AV_FIELD_PROGRESSIVE
;
2093 AVStream
*st
= track
->st
;
2094 int rate
= defined_frame_rate(NULL
, st
);
2095 av_strlcatf(compressor_name
, len
, "XDCAM");
2096 if (track
->par
->format
== AV_PIX_FMT_YUV422P
) {
2097 av_strlcatf(compressor_name
, len
, " HD422");
2098 } else if(track
->par
->width
== 1440) {
2099 av_strlcatf(compressor_name
, len
, " HD");
2101 av_strlcatf(compressor_name
, len
, " EX");
2103 av_strlcatf(compressor_name
, len
, " %d%c", track
->par
->height
, interlaced
? 'i' : 'p');
2105 av_strlcatf(compressor_name
, len
, "%d", rate
* (interlaced
+ 1));
2109 static int mov_write_video_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVMuxContext
*mov
, MOVTrack
*track
)
2111 int ret
= AVERROR_BUG
;
2112 int64_t pos
= avio_tell(pb
);
2113 char compressor_name
[32] = { 0 };
2116 int uncompressed_ycbcr
= ((track
->par
->codec_id
== AV_CODEC_ID_RAWVIDEO
&& track
->par
->format
== AV_PIX_FMT_UYVY422
)
2117 || (track
->par
->codec_id
== AV_CODEC_ID_RAWVIDEO
&& track
->par
->format
== AV_PIX_FMT_YUYV422
)
2118 || track
->par
->codec_id
== AV_CODEC_ID_V308
2119 || track
->par
->codec_id
== AV_CODEC_ID_V408
2120 || track
->par
->codec_id
== AV_CODEC_ID_V410
2121 || track
->par
->codec_id
== AV_CODEC_ID_V210
);
2123 avio_wb32(pb
, 0); /* size */
2124 if (mov
->encryption_scheme
!= MOV_ENC_NONE
) {
2125 ffio_wfourcc(pb
, "encv");
2127 avio_wl32(pb
, track
->tag
); // store it byteswapped
2129 avio_wb32(pb
, 0); /* Reserved */
2130 avio_wb16(pb
, 0); /* Reserved */
2131 avio_wb16(pb
, 1); /* Data-reference index */
2133 if (uncompressed_ycbcr
) {
2134 avio_wb16(pb
, 2); /* Codec stream version */
2136 avio_wb16(pb
, 0); /* Codec stream version */
2138 avio_wb16(pb
, 0); /* Codec stream revision (=0) */
2139 if (track
->mode
== MODE_MOV
) {
2140 ffio_wfourcc(pb
, "FFMP"); /* Vendor */
2141 if (track
->par
->codec_id
== AV_CODEC_ID_RAWVIDEO
|| uncompressed_ycbcr
) {
2142 avio_wb32(pb
, 0); /* Temporal Quality */
2143 avio_wb32(pb
, 0x400); /* Spatial Quality = lossless*/
2145 avio_wb32(pb
, 0x200); /* Temporal Quality = normal */
2146 avio_wb32(pb
, 0x200); /* Spatial Quality = normal */
2149 ffio_fill(pb
, 0, 3 * 4); /* Reserved */
2151 avio_wb16(pb
, track
->par
->width
); /* Video width */
2152 avio_wb16(pb
, track
->height
); /* Video height */
2153 avio_wb32(pb
, 0x00480000); /* Horizontal resolution 72dpi */
2154 avio_wb32(pb
, 0x00480000); /* Vertical resolution 72dpi */
2155 avio_wb32(pb
, 0); /* Data size (= 0) */
2156 avio_wb16(pb
, 1); /* Frame count (= 1) */
2158 /* FIXME not sure, ISO 14496-1 draft where it shall be set to 0 */
2159 find_compressor(compressor_name
, 32, track
);
2160 avio_w8(pb
, strlen(compressor_name
));
2161 avio_write(pb
, compressor_name
, 31);
2163 if (track
->mode
== MODE_MOV
&&
2164 (track
->par
->codec_id
== AV_CODEC_ID_V410
|| track
->par
->codec_id
== AV_CODEC_ID_V210
))
2165 avio_wb16(pb
, 0x18);
2166 else if (track
->mode
== MODE_MOV
&& track
->par
->bits_per_coded_sample
)
2167 avio_wb16(pb
, track
->par
->bits_per_coded_sample
|
2168 (track
->par
->format
== AV_PIX_FMT_GRAY8
? 0x20 : 0));
2170 avio_wb16(pb
, 0x18); /* Reserved */
2172 if (track
->mode
== MODE_MOV
&& track
->par
->format
== AV_PIX_FMT_PAL8
) {
2174 avio_wb16(pb
, 0); /* Color table ID */
2175 avio_wb32(pb
, 0); /* Color table seed */
2176 avio_wb16(pb
, 0x8000); /* Color table flags */
2177 if (track
->par
->bits_per_coded_sample
< 0 || track
->par
->bits_per_coded_sample
> 8)
2178 return AVERROR(EINVAL
);
2179 pal_size
= 1 << track
->par
->bits_per_coded_sample
;
2180 avio_wb16(pb
, pal_size
- 1); /* Color table size (zero-relative) */
2181 for (i
= 0; i
< pal_size
; i
++) {
2182 uint32_t rgb
= track
->palette
[i
];
2183 uint16_t r
= (rgb
>> 16) & 0xff;
2184 uint16_t g
= (rgb
>> 8) & 0xff;
2185 uint16_t b
= rgb
& 0xff;
2187 avio_wb16(pb
, (r
<< 8) | r
);
2188 avio_wb16(pb
, (g
<< 8) | g
);
2189 avio_wb16(pb
, (b
<< 8) | b
);
2192 avio_wb16(pb
, 0xffff); /* Reserved */
2194 if (track
->tag
== MKTAG('m','p','4','v'))
2195 mov_write_esds_tag(pb
, track
);
2196 else if (track
->par
->codec_id
== AV_CODEC_ID_H263
)
2197 mov_write_d263_tag(pb
);
2198 else if (track
->par
->codec_id
== AV_CODEC_ID_AVUI
||
2199 track
->par
->codec_id
== AV_CODEC_ID_SVQ3
) {
2200 mov_write_extradata_tag(pb
, track
);
2202 } else if (track
->par
->codec_id
== AV_CODEC_ID_DNXHD
) {
2203 mov_write_avid_tag(pb
, track
);
2205 } else if (track
->par
->codec_id
== AV_CODEC_ID_HEVC
)
2206 mov_write_hvcc_tag(pb
, track
);
2207 else if (track
->par
->codec_id
== AV_CODEC_ID_H264
&& !TAG_IS_AVCI(track
->tag
)) {
2208 mov_write_avcc_tag(pb
, track
);
2209 if (track
->mode
== MODE_IPOD
)
2210 mov_write_uuid_tag_ipod(pb
);
2211 } else if (track
->par
->codec_id
== AV_CODEC_ID_VP9
) {
2212 mov_write_vpcc_tag(mov
->fc
, pb
, track
);
2213 } else if (track
->par
->codec_id
== AV_CODEC_ID_AV1
) {
2214 mov_write_av1c_tag(pb
, track
);
2215 } else if (track
->par
->codec_id
== AV_CODEC_ID_VC1
&& track
->vos_len
> 0)
2216 mov_write_dvc1_tag(pb
, track
);
2217 else if (track
->par
->codec_id
== AV_CODEC_ID_VP6F
||
2218 track
->par
->codec_id
== AV_CODEC_ID_VP6A
) {
2219 /* Don't write any potential extradata here - the cropping
2220 * is signalled via the normal width/height fields. */
2221 } else if (track
->par
->codec_id
== AV_CODEC_ID_R10K
) {
2222 if (track
->par
->codec_tag
== MKTAG('R','1','0','k'))
2223 mov_write_dpxe_tag(pb
, track
);
2224 } else if (track
->vos_len
> 0)
2225 mov_write_glbl_tag(pb
, track
);
2227 if (track
->par
->codec_id
!= AV_CODEC_ID_H264
&&
2228 track
->par
->codec_id
!= AV_CODEC_ID_MPEG4
&&
2229 track
->par
->codec_id
!= AV_CODEC_ID_DNXHD
) {
2230 int field_order
= track
->par
->field_order
;
2232 if (field_order
!= AV_FIELD_UNKNOWN
)
2233 mov_write_fiel_tag(pb
, track
, field_order
);
2236 if (mov
->flags
& FF_MOV_FLAG_WRITE_GAMA
) {
2237 if (track
->mode
== MODE_MOV
)
2238 mov_write_gama_tag(s
, pb
, track
, mov
->gamma
);
2240 av_log(mov
->fc
, AV_LOG_WARNING
, "Not writing 'gama' atom. Format is not MOV.\n");
2242 if (track
->mode
== MODE_MOV
|| track
->mode
== MODE_MP4
) {
2243 int has_color_info
= track
->par
->color_primaries
!= AVCOL_PRI_UNSPECIFIED
&&
2244 track
->par
->color_trc
!= AVCOL_TRC_UNSPECIFIED
&&
2245 track
->par
->color_space
!= AVCOL_SPC_UNSPECIFIED
;
2246 if (has_color_info
|| mov
->flags
& FF_MOV_FLAG_WRITE_COLR
||
2247 av_stream_get_side_data(track
->st
, AV_PKT_DATA_ICC_PROFILE
, NULL
)) {
2248 int prefer_icc
= mov
->flags
& FF_MOV_FLAG_PREFER_ICC
|| !has_color_info
;
2249 mov_write_colr_tag(pb
, track
, prefer_icc
);
2250 } else if (mov
->flags
& FF_MOV_FLAG_WRITE_COLR
) {
2251 av_log(mov
->fc
, AV_LOG_WARNING
, "Not writing 'colr' atom. Format is not MOV or MP4.\n");
2254 if (track
->mode
== MODE_MOV
|| track
->mode
== MODE_MP4
) {
2255 mov_write_clli_tag(pb
, track
);
2256 mov_write_mdcv_tag(pb
, track
);
2259 if (track
->mode
== MODE_MP4
&& mov
->fc
->strict_std_compliance
<= FF_COMPLIANCE_UNOFFICIAL
) {
2260 AVStereo3D
* stereo_3d
= (AVStereo3D
*) av_stream_get_side_data(track
->st
, AV_PKT_DATA_STEREO3D
, NULL
);
2261 AVSphericalMapping
* spherical_mapping
= (AVSphericalMapping
*)av_stream_get_side_data(track
->st
, AV_PKT_DATA_SPHERICAL
, NULL
);
2262 AVDOVIDecoderConfigurationRecord
*dovi
= (AVDOVIDecoderConfigurationRecord
*)
2263 av_stream_get_side_data(track
->st
, AV_PKT_DATA_DOVI_CONF
, NULL
);
2266 mov_write_st3d_tag(s
, pb
, stereo_3d
);
2267 if (spherical_mapping
)
2268 mov_write_sv3d_tag(mov
->fc
, pb
, spherical_mapping
);
2270 mov_write_dvcc_dvvc_tag(s
, pb
, dovi
);
2273 if (track
->par
->sample_aspect_ratio
.den
&& track
->par
->sample_aspect_ratio
.num
) {
2274 mov_write_pasp_tag(pb
, track
);
2277 if (uncompressed_ycbcr
){
2278 mov_write_clap_tag(pb
, track
);
2281 if (mov
->encryption_scheme
!= MOV_ENC_NONE
) {
2282 ff_mov_cenc_write_sinf_tag(track
, pb
, mov
->encryption_kid
);
2285 if (track
->mode
== MODE_MP4
&&
2286 ((ret
= mov_write_btrt_tag(pb
, track
)) < 0))
2289 /* extra padding for avid stsd */
2290 /* https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-61112 */
2294 return update_size(pb
, pos
);
2297 static int mov_write_rtp_tag(AVIOContext
*pb
, MOVTrack
*track
)
2299 int64_t pos
= avio_tell(pb
);
2300 avio_wb32(pb
, 0); /* size */
2301 ffio_wfourcc(pb
, "rtp ");
2302 avio_wb32(pb
, 0); /* Reserved */
2303 avio_wb16(pb
, 0); /* Reserved */
2304 avio_wb16(pb
, 1); /* Data-reference index */
2306 avio_wb16(pb
, 1); /* Hint track version */
2307 avio_wb16(pb
, 1); /* Highest compatible version */
2308 avio_wb32(pb
, track
->max_packet_size
); /* Max packet size */
2310 avio_wb32(pb
, 12); /* size */
2311 ffio_wfourcc(pb
, "tims");
2312 avio_wb32(pb
, track
->timescale
);
2314 return update_size(pb
, pos
);
2317 static int mov_write_source_reference_tag(AVIOContext
*pb
, MOVTrack
*track
, const char *reel_name
)
2319 uint64_t str_size
=strlen(reel_name
);
2320 int64_t pos
= avio_tell(pb
);
2322 if (str_size
>= UINT16_MAX
){
2323 av_log(NULL
, AV_LOG_ERROR
, "reel_name length %"PRIu64
" is too large\n", str_size
);
2325 return AVERROR(EINVAL
);
2328 avio_wb32(pb
, 0); /* size */
2329 ffio_wfourcc(pb
, "name"); /* Data format */
2330 avio_wb16(pb
, str_size
); /* string size */
2331 avio_wb16(pb
, track
->language
); /* langcode */
2332 avio_write(pb
, reel_name
, str_size
); /* reel name */
2333 return update_size(pb
,pos
);
2336 static int mov_write_tmcd_tag(AVIOContext
*pb
, MOVTrack
*track
)
2338 int64_t pos
= avio_tell(pb
);
2342 AVDictionaryEntry
*t
= NULL
;
2344 if (!track
->st
->avg_frame_rate
.num
|| !track
->st
->avg_frame_rate
.den
) {
2345 av_log(NULL
, AV_LOG_ERROR
, "avg_frame_rate not set for tmcd track.\n");
2346 return AVERROR(EINVAL
);
2348 frame_duration
= av_rescale(track
->timescale
, track
->st
->avg_frame_rate
.den
, track
->st
->avg_frame_rate
.num
);
2349 nb_frames
= ROUNDED_DIV(track
->st
->avg_frame_rate
.num
, track
->st
->avg_frame_rate
.den
);
2352 if (nb_frames
> 255) {
2353 av_log(NULL
, AV_LOG_ERROR
, "fps %d is too large\n", nb_frames
);
2354 return AVERROR(EINVAL
);
2357 avio_wb32(pb
, 0); /* size */
2358 ffio_wfourcc(pb
, "tmcd"); /* Data format */
2359 avio_wb32(pb
, 0); /* Reserved */
2360 avio_wb32(pb
, 1); /* Data reference index */
2361 avio_wb32(pb
, 0); /* Flags */
2362 avio_wb32(pb
, track
->timecode_flags
); /* Flags (timecode) */
2363 avio_wb32(pb
, track
->timescale
); /* Timescale */
2364 avio_wb32(pb
, frame_duration
); /* Frame duration */
2365 avio_w8(pb
, nb_frames
); /* Number of frames */
2366 avio_w8(pb
, 0); /* Reserved */
2368 t
= av_dict_get(track
->st
->metadata
, "reel_name", NULL
, 0);
2369 if (t
&& utf8len(t
->value
) && track
->mode
!= MODE_MP4
)
2370 mov_write_source_reference_tag(pb
, track
, t
->value
);
2372 avio_wb16(pb
, 0); /* zero size */
2375 avio_wb32(pb
, 0); /* size */
2376 ffio_wfourcc(pb
, "tmcd"); /* Data format */
2377 avio_wb32(pb
, 0); /* Reserved */
2378 avio_wb32(pb
, 1); /* Data reference index */
2379 if (track
->par
->extradata_size
)
2380 avio_write(pb
, track
->par
->extradata
, track
->par
->extradata_size
);
2382 return update_size(pb
, pos
);
2385 static int mov_write_gpmd_tag(AVIOContext
*pb
, const MOVTrack
*track
)
2387 int64_t pos
= avio_tell(pb
);
2388 avio_wb32(pb
, 0); /* size */
2389 ffio_wfourcc(pb
, "gpmd");
2390 avio_wb32(pb
, 0); /* Reserved */
2391 avio_wb16(pb
, 0); /* Reserved */
2392 avio_wb16(pb
, 1); /* Data-reference index */
2393 avio_wb32(pb
, 0); /* Reserved */
2394 return update_size(pb
, pos
);
2397 static int mov_write_stsd_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVMuxContext
*mov
, MOVTrack
*track
)
2399 int64_t pos
= avio_tell(pb
);
2401 avio_wb32(pb
, 0); /* size */
2402 ffio_wfourcc(pb
, "stsd");
2403 avio_wb32(pb
, 0); /* version & flags */
2404 avio_wb32(pb
, 1); /* entry count */
2405 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
)
2406 ret
= mov_write_video_tag(s
, pb
, mov
, track
);
2407 else if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
)
2408 ret
= mov_write_audio_tag(s
, pb
, mov
, track
);
2409 else if (track
->par
->codec_type
== AVMEDIA_TYPE_SUBTITLE
)
2410 ret
= mov_write_subtitle_tag(pb
, track
);
2411 else if (track
->par
->codec_tag
== MKTAG('r','t','p',' '))
2412 ret
= mov_write_rtp_tag(pb
, track
);
2413 else if (track
->par
->codec_tag
== MKTAG('t','m','c','d'))
2414 ret
= mov_write_tmcd_tag(pb
, track
);
2415 else if (track
->par
->codec_tag
== MKTAG('g','p','m','d'))
2416 ret
= mov_write_gpmd_tag(pb
, track
);
2421 return update_size(pb
, pos
);
2424 static int mov_write_ctts_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
2426 MOVMuxContext
*mov
= s
->priv_data
;
2427 MOVCtts
*ctts_entries
;
2428 uint32_t entries
= 0;
2432 ctts_entries
= av_malloc_array((track
->entry
+ 1), sizeof(*ctts_entries
)); /* worst case */
2434 return AVERROR(ENOMEM
);
2435 ctts_entries
[0].count
= 1;
2436 ctts_entries
[0].duration
= track
->cluster
[0].cts
;
2437 for (i
= 1; i
< track
->entry
; i
++) {
2438 if (track
->cluster
[i
].cts
== ctts_entries
[entries
].duration
) {
2439 ctts_entries
[entries
].count
++; /* compress */
2442 ctts_entries
[entries
].duration
= track
->cluster
[i
].cts
;
2443 ctts_entries
[entries
].count
= 1;
2446 entries
++; /* last one */
2447 atom_size
= 16 + (entries
* 8);
2448 avio_wb32(pb
, atom_size
); /* size */
2449 ffio_wfourcc(pb
, "ctts");
2450 if (mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
)
2451 avio_w8(pb
, 1); /* version */
2453 avio_w8(pb
, 0); /* version */
2454 avio_wb24(pb
, 0); /* flags */
2455 avio_wb32(pb
, entries
); /* entry count */
2456 for (i
= 0; i
< entries
; i
++) {
2457 avio_wb32(pb
, ctts_entries
[i
].count
);
2458 avio_wb32(pb
, ctts_entries
[i
].duration
);
2460 av_free(ctts_entries
);
2464 /* Time to sample atom */
2465 static int mov_write_stts_tag(AVIOContext
*pb
, MOVTrack
*track
)
2467 MOVStts
*stts_entries
= NULL
;
2468 uint32_t entries
= -1;
2472 if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
&& !track
->audio_vbr
) {
2473 stts_entries
= av_malloc(sizeof(*stts_entries
)); /* one entry */
2475 return AVERROR(ENOMEM
);
2476 stts_entries
[0].count
= track
->sample_count
;
2477 stts_entries
[0].duration
= 1;
2481 stts_entries
= av_malloc_array(track
->entry
, sizeof(*stts_entries
)); /* worst case */
2483 return AVERROR(ENOMEM
);
2485 for (i
= 0; i
< track
->entry
; i
++) {
2486 int duration
= get_cluster_duration(track
, i
);
2487 if (i
&& duration
== stts_entries
[entries
].duration
) {
2488 stts_entries
[entries
].count
++; /* compress */
2491 stts_entries
[entries
].duration
= duration
;
2492 stts_entries
[entries
].count
= 1;
2495 entries
++; /* last one */
2497 atom_size
= 16 + (entries
* 8);
2498 avio_wb32(pb
, atom_size
); /* size */
2499 ffio_wfourcc(pb
, "stts");
2500 avio_wb32(pb
, 0); /* version & flags */
2501 avio_wb32(pb
, entries
); /* entry count */
2502 for (i
= 0; i
< entries
; i
++) {
2503 avio_wb32(pb
, stts_entries
[i
].count
);
2504 avio_wb32(pb
, stts_entries
[i
].duration
);
2506 av_free(stts_entries
);
2510 static int mov_write_dref_tag(AVIOContext
*pb
)
2512 avio_wb32(pb
, 28); /* size */
2513 ffio_wfourcc(pb
, "dref");
2514 avio_wb32(pb
, 0); /* version & flags */
2515 avio_wb32(pb
, 1); /* entry count */
2517 avio_wb32(pb
, 0xc); /* size */
2518 //FIXME add the alis and rsrc atom
2519 ffio_wfourcc(pb
, "url ");
2520 avio_wb32(pb
, 1); /* version & flags */
2525 static int mov_preroll_write_stbl_atoms(AVIOContext
*pb
, MOVTrack
*track
)
2529 int16_t roll_distance
;
2530 int group_description_index
;
2533 struct sgpd_entry
*sgpd_entries
= NULL
;
2538 const int OPUS_SEEK_PREROLL_MS
= 80;
2539 int roll_samples
= av_rescale_q(OPUS_SEEK_PREROLL_MS
,
2540 (AVRational
){1, 1000},
2541 (AVRational
){1, 48000});
2546 sgpd_entries
= av_malloc_array(track
->entry
, sizeof(*sgpd_entries
));
2548 return AVERROR(ENOMEM
);
2550 av_assert0(track
->par
->codec_id
== AV_CODEC_ID_OPUS
|| track
->par
->codec_id
== AV_CODEC_ID_AAC
);
2552 if (track
->par
->codec_id
== AV_CODEC_ID_OPUS
) {
2553 for (i
= 0; i
< track
->entry
; i
++) {
2554 int roll_samples_remaining
= roll_samples
;
2556 for (j
= i
- 1; j
>= 0; j
--) {
2557 roll_samples_remaining
-= get_cluster_duration(track
, j
);
2559 if (roll_samples_remaining
<= 0)
2562 /* We don't have enough preceeding samples to compute a valid
2563 roll_distance here, so this sample can't be independently
2565 if (roll_samples_remaining
> 0)
2567 /* Verify distance is a maximum of 32 (2.5ms) packets. */
2569 return AVERROR_INVALIDDATA
;
2570 if (i
&& distance
== sgpd_entries
[entries
].roll_distance
) {
2571 sgpd_entries
[entries
].count
++;
2574 sgpd_entries
[entries
].count
= 1;
2575 sgpd_entries
[entries
].roll_distance
= distance
;
2576 sgpd_entries
[entries
].group_description_index
= distance
? ++group
: 0;
2581 sgpd_entries
[entries
].count
= track
->sample_count
;
2582 sgpd_entries
[entries
].roll_distance
= 1;
2583 sgpd_entries
[entries
].group_description_index
= ++group
;
2588 av_free(sgpd_entries
);
2592 /* Write sgpd tag */
2593 avio_wb32(pb
, 24 + (group
* 2)); /* size */
2594 ffio_wfourcc(pb
, "sgpd");
2595 avio_wb32(pb
, 1 << 24); /* fullbox */
2596 ffio_wfourcc(pb
, "roll");
2597 avio_wb32(pb
, 2); /* default_length */
2598 avio_wb32(pb
, group
); /* entry_count */
2599 for (i
= 0; i
< entries
; i
++) {
2600 if (sgpd_entries
[i
].group_description_index
) {
2601 avio_wb16(pb
, -sgpd_entries
[i
].roll_distance
); /* roll_distance */
2605 /* Write sbgp tag */
2606 avio_wb32(pb
, 20 + (entries
* 8)); /* size */
2607 ffio_wfourcc(pb
, "sbgp");
2608 avio_wb32(pb
, 0); /* fullbox */
2609 ffio_wfourcc(pb
, "roll");
2610 avio_wb32(pb
, entries
); /* entry_count */
2611 for (i
= 0; i
< entries
; i
++) {
2612 avio_wb32(pb
, sgpd_entries
[i
].count
); /* sample_count */
2613 avio_wb32(pb
, sgpd_entries
[i
].group_description_index
); /* group_description_index */
2616 av_free(sgpd_entries
);
2620 static int mov_write_stbl_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVMuxContext
*mov
, MOVTrack
*track
)
2622 int64_t pos
= avio_tell(pb
);
2625 avio_wb32(pb
, 0); /* size */
2626 ffio_wfourcc(pb
, "stbl");
2627 if ((ret
= mov_write_stsd_tag(s
, pb
, mov
, track
)) < 0)
2629 mov_write_stts_tag(pb
, track
);
2630 if ((track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
||
2631 track
->par
->codec_id
== AV_CODEC_ID_TRUEHD
||
2632 track
->par
->codec_id
== AV_CODEC_ID_MPEGH_3D_AUDIO
||
2633 track
->par
->codec_tag
== MKTAG('r','t','p',' ')) &&
2634 track
->has_keyframes
&& track
->has_keyframes
< track
->entry
)
2635 mov_write_stss_tag(pb
, track
, MOV_SYNC_SAMPLE
);
2636 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
&& track
->has_disposable
)
2637 mov_write_sdtp_tag(pb
, track
);
2638 if (track
->mode
== MODE_MOV
&& track
->flags
& MOV_TRACK_STPS
)
2639 mov_write_stss_tag(pb
, track
, MOV_PARTIAL_SYNC_SAMPLE
);
2640 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
&&
2641 track
->flags
& MOV_TRACK_CTTS
&& track
->entry
) {
2643 if ((ret
= mov_write_ctts_tag(s
, pb
, track
)) < 0)
2646 mov_write_stsc_tag(pb
, track
);
2647 mov_write_stsz_tag(pb
, track
);
2648 mov_write_stco_tag(pb
, track
);
2649 if (track
->cenc
.aes_ctr
) {
2650 ff_mov_cenc_write_stbl_atoms(&track
->cenc
, pb
);
2652 if (track
->par
->codec_id
== AV_CODEC_ID_OPUS
|| track
->par
->codec_id
== AV_CODEC_ID_AAC
) {
2653 mov_preroll_write_stbl_atoms(pb
, track
);
2655 return update_size(pb
, pos
);
2658 static int mov_write_dinf_tag(AVIOContext
*pb
)
2660 int64_t pos
= avio_tell(pb
);
2661 avio_wb32(pb
, 0); /* size */
2662 ffio_wfourcc(pb
, "dinf");
2663 mov_write_dref_tag(pb
);
2664 return update_size(pb
, pos
);
2667 static int mov_write_nmhd_tag(AVIOContext
*pb
)
2670 ffio_wfourcc(pb
, "nmhd");
2675 static int mov_write_sthd_tag(AVIOContext
*pb
)
2678 ffio_wfourcc(pb
, "sthd");
2683 static int mov_write_tcmi_tag(AVIOContext
*pb
, MOVTrack
*track
)
2685 int64_t pos
= avio_tell(pb
);
2686 const char *font
= "Lucida Grande";
2687 avio_wb32(pb
, 0); /* size */
2688 ffio_wfourcc(pb
, "tcmi"); /* timecode media information atom */
2689 avio_wb32(pb
, 0); /* version & flags */
2690 avio_wb16(pb
, 0); /* text font */
2691 avio_wb16(pb
, 0); /* text face */
2692 avio_wb16(pb
, 12); /* text size */
2693 avio_wb16(pb
, 0); /* (unknown, not in the QT specs...) */
2694 avio_wb16(pb
, 0x0000); /* text color (red) */
2695 avio_wb16(pb
, 0x0000); /* text color (green) */
2696 avio_wb16(pb
, 0x0000); /* text color (blue) */
2697 avio_wb16(pb
, 0xffff); /* background color (red) */
2698 avio_wb16(pb
, 0xffff); /* background color (green) */
2699 avio_wb16(pb
, 0xffff); /* background color (blue) */
2700 avio_w8(pb
, strlen(font
)); /* font len (part of the pascal string) */
2701 avio_write(pb
, font
, strlen(font
)); /* font name */
2702 return update_size(pb
, pos
);
2705 static int mov_write_gmhd_tag(AVIOContext
*pb
, MOVTrack
*track
)
2707 int64_t pos
= avio_tell(pb
);
2708 avio_wb32(pb
, 0); /* size */
2709 ffio_wfourcc(pb
, "gmhd");
2710 avio_wb32(pb
, 0x18); /* gmin size */
2711 ffio_wfourcc(pb
, "gmin");/* generic media info */
2712 avio_wb32(pb
, 0); /* version & flags */
2713 avio_wb16(pb
, 0x40); /* graphics mode = */
2714 avio_wb16(pb
, 0x8000); /* opColor (r?) */
2715 avio_wb16(pb
, 0x8000); /* opColor (g?) */
2716 avio_wb16(pb
, 0x8000); /* opColor (b?) */
2717 avio_wb16(pb
, 0); /* balance */
2718 avio_wb16(pb
, 0); /* reserved */
2721 * This special text atom is required for
2722 * Apple Quicktime chapters. The contents
2723 * don't appear to be documented, so the
2724 * bytes are copied verbatim.
2726 if (track
->tag
!= MKTAG('c','6','0','8')) {
2727 avio_wb32(pb
, 0x2C); /* size */
2728 ffio_wfourcc(pb
, "text");
2729 avio_wb16(pb
, 0x01);
2730 avio_wb32(pb
, 0x00);
2731 avio_wb32(pb
, 0x00);
2732 avio_wb32(pb
, 0x00);
2733 avio_wb32(pb
, 0x01);
2734 avio_wb32(pb
, 0x00);
2735 avio_wb32(pb
, 0x00);
2736 avio_wb32(pb
, 0x00);
2737 avio_wb32(pb
, 0x00004000);
2738 avio_wb16(pb
, 0x0000);
2741 if (track
->par
->codec_tag
== MKTAG('t','m','c','d')) {
2742 int64_t tmcd_pos
= avio_tell(pb
);
2743 avio_wb32(pb
, 0); /* size */
2744 ffio_wfourcc(pb
, "tmcd");
2745 mov_write_tcmi_tag(pb
, track
);
2746 update_size(pb
, tmcd_pos
);
2747 } else if (track
->par
->codec_tag
== MKTAG('g','p','m','d')) {
2748 int64_t gpmd_pos
= avio_tell(pb
);
2749 avio_wb32(pb
, 0); /* size */
2750 ffio_wfourcc(pb
, "gpmd");
2751 avio_wb32(pb
, 0); /* version */
2752 update_size(pb
, gpmd_pos
);
2754 return update_size(pb
, pos
);
2757 static int mov_write_smhd_tag(AVIOContext
*pb
)
2759 avio_wb32(pb
, 16); /* size */
2760 ffio_wfourcc(pb
, "smhd");
2761 avio_wb32(pb
, 0); /* version & flags */
2762 avio_wb16(pb
, 0); /* reserved (balance, normally = 0) */
2763 avio_wb16(pb
, 0); /* reserved */
2767 static int mov_write_vmhd_tag(AVIOContext
*pb
)
2769 avio_wb32(pb
, 0x14); /* size (always 0x14) */
2770 ffio_wfourcc(pb
, "vmhd");
2771 avio_wb32(pb
, 0x01); /* version & flags */
2772 avio_wb64(pb
, 0); /* reserved (graphics mode = copy) */
2776 static int is_clcp_track(MOVTrack
*track
)
2778 return track
->tag
== MKTAG('c','7','0','8') ||
2779 track
->tag
== MKTAG('c','6','0','8');
2782 static int mov_write_hdlr_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVTrack
*track
)
2784 MOVMuxContext
*mov
= s
->priv_data
;
2785 const char *hdlr
, *descr
= NULL
, *hdlr_type
= NULL
;
2786 int64_t pos
= avio_tell(pb
);
2791 descr
= "DataHandler";
2794 hdlr
= (track
->mode
== MODE_MOV
) ? "mhlr" : "\0\0\0\0";
2795 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
2797 descr
= "VideoHandler";
2798 } else if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
2800 descr
= "SoundHandler";
2801 } else if (track
->par
->codec_type
== AVMEDIA_TYPE_SUBTITLE
) {
2802 if (is_clcp_track(track
)) {
2804 descr
= "ClosedCaptionHandler";
2806 if (track
->tag
== MKTAG('t','x','3','g')) {
2808 } else if (track
->tag
== MKTAG('m','p','4','s')) {
2810 } else if (track
->tag
== MOV_MP4_TTML_TAG
) {
2815 descr
= "SubtitleHandler";
2817 } else if (track
->par
->codec_tag
== MKTAG('r','t','p',' ')) {
2819 descr
= "HintHandler";
2820 } else if (track
->par
->codec_tag
== MKTAG('t','m','c','d')) {
2822 descr
= "TimeCodeHandler";
2823 } else if (track
->par
->codec_tag
== MKTAG('g','p','m','d')) {
2825 descr
= "GoPro MET"; // GoPro Metadata
2827 av_log(s
, AV_LOG_WARNING
,
2828 "Unknown hdlr_type for %s, writing dummy values\n",
2829 av_fourcc2str(track
->par
->codec_tag
));
2832 // hdlr.name is used by some players to identify the content title
2833 // of the track. So if an alternate handler description is
2834 // specified, use it.
2835 AVDictionaryEntry
*t
;
2836 t
= av_dict_get(track
->st
->metadata
, "handler_name", NULL
, 0);
2837 if (t
&& utf8len(t
->value
))
2842 if (mov
->empty_hdlr_name
) /* expressly allowed by QTFF and not prohibited in ISO 14496-12 8.4.3.3 */
2845 avio_wb32(pb
, 0); /* size */
2846 ffio_wfourcc(pb
, "hdlr");
2847 avio_wb32(pb
, 0); /* Version & flags */
2848 avio_write(pb
, hdlr
, 4); /* handler */
2849 ffio_wfourcc(pb
, hdlr_type
); /* handler type */
2850 avio_wb32(pb
, 0); /* reserved */
2851 avio_wb32(pb
, 0); /* reserved */
2852 avio_wb32(pb
, 0); /* reserved */
2853 descr_len
= strlen(descr
);
2854 if (!track
|| track
->mode
== MODE_MOV
)
2855 avio_w8(pb
, descr_len
); /* pascal string */
2856 avio_write(pb
, descr
, descr_len
); /* handler description */
2857 if (track
&& track
->mode
!= MODE_MOV
)
2858 avio_w8(pb
, 0); /* c string */
2859 return update_size(pb
, pos
);
2862 static int mov_write_hmhd_tag(AVIOContext
*pb
)
2864 /* This atom must be present, but leaving the values at zero
2865 * seems harmless. */
2866 avio_wb32(pb
, 28); /* size */
2867 ffio_wfourcc(pb
, "hmhd");
2868 avio_wb32(pb
, 0); /* version, flags */
2869 avio_wb16(pb
, 0); /* maxPDUsize */
2870 avio_wb16(pb
, 0); /* avgPDUsize */
2871 avio_wb32(pb
, 0); /* maxbitrate */
2872 avio_wb32(pb
, 0); /* avgbitrate */
2873 avio_wb32(pb
, 0); /* reserved */
2877 static int mov_write_minf_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVMuxContext
*mov
, MOVTrack
*track
)
2879 int64_t pos
= avio_tell(pb
);
2882 avio_wb32(pb
, 0); /* size */
2883 ffio_wfourcc(pb
, "minf");
2884 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
)
2885 mov_write_vmhd_tag(pb
);
2886 else if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
)
2887 mov_write_smhd_tag(pb
);
2888 else if (track
->par
->codec_type
== AVMEDIA_TYPE_SUBTITLE
) {
2889 if (track
->tag
== MKTAG('t','e','x','t') || is_clcp_track(track
)) {
2890 mov_write_gmhd_tag(pb
, track
);
2891 } else if (track
->tag
== MOV_MP4_TTML_TAG
) {
2892 mov_write_sthd_tag(pb
);
2894 mov_write_nmhd_tag(pb
);
2896 } else if (track
->tag
== MKTAG('r','t','p',' ')) {
2897 mov_write_hmhd_tag(pb
);
2898 } else if (track
->tag
== MKTAG('t','m','c','d')) {
2899 if (track
->mode
!= MODE_MOV
)
2900 mov_write_nmhd_tag(pb
);
2902 mov_write_gmhd_tag(pb
, track
);
2903 } else if (track
->tag
== MKTAG('g','p','m','d')) {
2904 mov_write_gmhd_tag(pb
, track
);
2906 if (track
->mode
== MODE_MOV
) /* ISO 14496-12 8.4.3.1 specifies hdlr only within mdia or meta boxes */
2907 mov_write_hdlr_tag(s
, pb
, NULL
);
2908 mov_write_dinf_tag(pb
);
2909 if ((ret
= mov_write_stbl_tag(s
, pb
, mov
, track
)) < 0)
2911 return update_size(pb
, pos
);
2914 static void get_pts_range(MOVMuxContext
*mov
, MOVTrack
*track
,
2915 int64_t *start
, int64_t *end
)
2917 if (track
->tag
== MKTAG('t','m','c','d') && mov
->nb_meta_tmcd
) {
2918 // tmcd tracks gets track_duration set in mov_write_moov_tag from
2919 // another track's duration, while the end_pts may be left at zero.
2920 // Calculate the pts duration for that track instead.
2921 get_pts_range(mov
, &mov
->tracks
[track
->src_track
], start
, end
);
2922 *start
= av_rescale(*start
, track
->timescale
,
2923 mov
->tracks
[track
->src_track
].timescale
);
2924 *end
= av_rescale(*end
, track
->timescale
,
2925 mov
->tracks
[track
->src_track
].timescale
);
2928 if (track
->end_pts
!= AV_NOPTS_VALUE
&&
2929 track
->start_dts
!= AV_NOPTS_VALUE
&&
2930 track
->start_cts
!= AV_NOPTS_VALUE
) {
2931 *start
= track
->start_dts
+ track
->start_cts
;
2932 *end
= track
->end_pts
;
2936 *end
= track
->track_duration
;
2939 static int64_t calc_samples_pts_duration(MOVMuxContext
*mov
, MOVTrack
*track
)
2942 get_pts_range(mov
, track
, &start
, &end
);
2946 // Calculate the actual duration of the track, after edits.
2947 // If it starts with a pts < 0, that is removed by the edit list.
2948 // If it starts with a pts > 0, the edit list adds a delay before that.
2949 // Thus, with edit lists enabled, the post-edit output of the file is
2950 // starting with pts=0.
2951 static int64_t calc_pts_duration(MOVMuxContext
*mov
, MOVTrack
*track
)
2954 get_pts_range(mov
, track
, &start
, &end
);
2955 if (mov
->use_editlist
!= 0)
2960 static int mov_write_mdhd_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
2963 int64_t duration
= calc_samples_pts_duration(mov
, track
);
2964 int version
= duration
< INT32_MAX
? 0 : 1;
2966 if (track
->mode
== MODE_ISM
)
2969 (version
== 1) ? avio_wb32(pb
, 44) : avio_wb32(pb
, 32); /* size */
2970 ffio_wfourcc(pb
, "mdhd");
2971 avio_w8(pb
, version
);
2972 avio_wb24(pb
, 0); /* flags */
2974 avio_wb64(pb
, track
->time
);
2975 avio_wb64(pb
, track
->time
);
2977 avio_wb32(pb
, track
->time
); /* creation time */
2978 avio_wb32(pb
, track
->time
); /* modification time */
2980 avio_wb32(pb
, track
->timescale
); /* time scale (sample rate for audio) */
2981 if (!track
->entry
&& mov
->mode
== MODE_ISM
)
2982 (version
== 1) ? avio_wb64(pb
, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb
, 0xffffffff);
2983 else if (!track
->entry
)
2984 (version
== 1) ? avio_wb64(pb
, 0) : avio_wb32(pb
, 0);
2986 (version
== 1) ? avio_wb64(pb
, duration
) : avio_wb32(pb
, duration
); /* duration */
2987 avio_wb16(pb
, track
->language
); /* language */
2988 avio_wb16(pb
, 0); /* reserved (quality) */
2990 if (version
!= 0 && track
->mode
== MODE_MOV
) {
2991 av_log(NULL
, AV_LOG_ERROR
,
2992 "FATAL error, file duration too long for timebase, this file will not be\n"
2993 "playable with QuickTime. Choose a different timebase with "
2994 "-video_track_timescale or a different container format\n");
3000 static int mov_write_mdia_tag(AVFormatContext
*s
, AVIOContext
*pb
,
3001 MOVMuxContext
*mov
, MOVTrack
*track
)
3003 int64_t pos
= avio_tell(pb
);
3006 avio_wb32(pb
, 0); /* size */
3007 ffio_wfourcc(pb
, "mdia");
3008 mov_write_mdhd_tag(pb
, mov
, track
);
3009 mov_write_hdlr_tag(s
, pb
, track
);
3010 if ((ret
= mov_write_minf_tag(s
, pb
, mov
, track
)) < 0)
3012 return update_size(pb
, pos
);
3015 /* transformation matrix
3019 static void write_matrix(AVIOContext
*pb
, int16_t a
, int16_t b
, int16_t c
,
3020 int16_t d
, int16_t tx
, int16_t ty
)
3022 avio_wb32(pb
, a
<< 16); /* 16.16 format */
3023 avio_wb32(pb
, b
<< 16); /* 16.16 format */
3024 avio_wb32(pb
, 0); /* u in 2.30 format */
3025 avio_wb32(pb
, c
<< 16); /* 16.16 format */
3026 avio_wb32(pb
, d
<< 16); /* 16.16 format */
3027 avio_wb32(pb
, 0); /* v in 2.30 format */
3028 avio_wb32(pb
, tx
<< 16); /* 16.16 format */
3029 avio_wb32(pb
, ty
<< 16); /* 16.16 format */
3030 avio_wb32(pb
, 1 << 30); /* w in 2.30 format */
3033 static int mov_write_tkhd_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3034 MOVTrack
*track
, AVStream
*st
)
3036 int64_t duration
= av_rescale_rnd(calc_pts_duration(mov
, track
),
3037 mov
->movie_timescale
, track
->timescale
,
3039 int version
= duration
< INT32_MAX
? 0 : 1;
3040 int flags
= MOV_TKHD_FLAG_IN_MOVIE
;
3043 uint32_t *display_matrix
= NULL
;
3044 size_t display_matrix_size
;
3048 if (mov
->per_stream_grouping
)
3051 group
= st
->codecpar
->codec_type
;
3053 display_matrix
= (uint32_t*)av_stream_get_side_data(st
, AV_PKT_DATA_DISPLAYMATRIX
,
3054 &display_matrix_size
);
3055 if (display_matrix
&& display_matrix_size
< 9 * sizeof(*display_matrix
))
3056 display_matrix
= NULL
;
3059 if (track
->flags
& MOV_TRACK_ENABLED
)
3060 flags
|= MOV_TKHD_FLAG_ENABLED
;
3062 if (track
->mode
== MODE_ISM
)
3065 (version
== 1) ? avio_wb32(pb
, 104) : avio_wb32(pb
, 92); /* size */
3066 ffio_wfourcc(pb
, "tkhd");
3067 avio_w8(pb
, version
);
3068 avio_wb24(pb
, flags
);
3070 avio_wb64(pb
, track
->time
);
3071 avio_wb64(pb
, track
->time
);
3073 avio_wb32(pb
, track
->time
); /* creation time */
3074 avio_wb32(pb
, track
->time
); /* modification time */
3076 avio_wb32(pb
, track
->track_id
); /* track-id */
3077 avio_wb32(pb
, 0); /* reserved */
3078 if (!track
->entry
&& mov
->mode
== MODE_ISM
)
3079 (version
== 1) ? avio_wb64(pb
, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb
, 0xffffffff);
3080 else if (!track
->entry
)
3081 (version
== 1) ? avio_wb64(pb
, 0) : avio_wb32(pb
, 0);
3083 (version
== 1) ? avio_wb64(pb
, duration
) : avio_wb32(pb
, duration
);
3085 avio_wb32(pb
, 0); /* reserved */
3086 avio_wb32(pb
, 0); /* reserved */
3087 avio_wb16(pb
, 0); /* layer */
3088 avio_wb16(pb
, group
); /* alternate group) */
3089 /* Volume, only for audio */
3090 if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
)
3091 avio_wb16(pb
, 0x0100);
3094 avio_wb16(pb
, 0); /* reserved */
3096 /* Matrix structure */
3097 if (display_matrix
) {
3098 for (i
= 0; i
< 9; i
++)
3099 avio_wb32(pb
, display_matrix
[i
]);
3101 write_matrix(pb
, 1, 0, 0, 1, 0, 0);
3103 /* Track width and height, for visual only */
3104 if (st
&& (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
||
3105 track
->par
->codec_type
== AVMEDIA_TYPE_SUBTITLE
)) {
3106 int64_t track_width_1616
;
3107 if (track
->mode
== MODE_MOV
) {
3108 track_width_1616
= track
->par
->width
* 0x10000ULL
;
3110 track_width_1616
= av_rescale(st
->sample_aspect_ratio
.num
,
3111 track
->par
->width
* 0x10000LL
,
3112 st
->sample_aspect_ratio
.den
);
3113 if (!track_width_1616
||
3114 track
->height
!= track
->par
->height
||
3115 track_width_1616
> UINT32_MAX
)
3116 track_width_1616
= track
->par
->width
* 0x10000ULL
;
3118 if (track_width_1616
> UINT32_MAX
) {
3119 av_log(mov
->fc
, AV_LOG_WARNING
, "track width is too large\n");
3120 track_width_1616
= 0;
3122 avio_wb32(pb
, track_width_1616
);
3123 if (track
->height
> 0xFFFF) {
3124 av_log(mov
->fc
, AV_LOG_WARNING
, "track height is too large\n");
3127 avio_wb32(pb
, track
->height
* 0x10000U
);
3135 static int mov_write_tapt_tag(AVIOContext
*pb
, MOVTrack
*track
)
3137 int32_t width
= av_rescale(track
->par
->sample_aspect_ratio
.num
, track
->par
->width
,
3138 track
->par
->sample_aspect_ratio
.den
);
3140 int64_t pos
= avio_tell(pb
);
3142 avio_wb32(pb
, 0); /* size */
3143 ffio_wfourcc(pb
, "tapt");
3146 ffio_wfourcc(pb
, "clef");
3148 avio_wb32(pb
, width
<< 16);
3149 avio_wb32(pb
, track
->par
->height
<< 16);
3152 ffio_wfourcc(pb
, "prof");
3154 avio_wb32(pb
, width
<< 16);
3155 avio_wb32(pb
, track
->par
->height
<< 16);
3158 ffio_wfourcc(pb
, "enof");
3160 avio_wb32(pb
, track
->par
->width
<< 16);
3161 avio_wb32(pb
, track
->par
->height
<< 16);
3163 return update_size(pb
, pos
);
3166 // This box seems important for the psp playback ... without it the movie seems to hang
3167 static int mov_write_edts_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3170 int64_t duration
= av_rescale_rnd(calc_samples_pts_duration(mov
, track
),
3171 mov
->movie_timescale
, track
->timescale
,
3173 int version
= duration
< INT32_MAX
? 0 : 1;
3174 int entry_size
, entry_count
, size
;
3175 int64_t delay
, start_ct
= track
->start_cts
;
3176 int64_t start_dts
= track
->start_dts
;
3179 if (start_dts
!= track
->cluster
[0].dts
|| start_ct
!= track
->cluster
[0].cts
) {
3181 av_log(mov
->fc
, AV_LOG_DEBUG
,
3182 "EDTS using dts:%"PRId64
" cts:%d instead of dts:%"PRId64
" cts:%"PRId64
" tid:%d\n",
3183 track
->cluster
[0].dts
, track
->cluster
[0].cts
,
3184 start_dts
, start_ct
, track
->track_id
);
3185 start_dts
= track
->cluster
[0].dts
;
3186 start_ct
= track
->cluster
[0].cts
;
3190 delay
= av_rescale_rnd(start_dts
+ start_ct
, mov
->movie_timescale
,
3191 track
->timescale
, AV_ROUND_DOWN
);
3192 version
|= delay
< INT32_MAX
? 0 : 1;
3194 entry_size
= (version
== 1) ? 20 : 12;
3195 entry_count
= 1 + (delay
> 0);
3196 size
= 24 + entry_count
* entry_size
;
3198 /* write the atom data */
3199 avio_wb32(pb
, size
);
3200 ffio_wfourcc(pb
, "edts");
3201 avio_wb32(pb
, size
- 8);
3202 ffio_wfourcc(pb
, "elst");
3203 avio_w8(pb
, version
);
3204 avio_wb24(pb
, 0); /* flags */
3206 avio_wb32(pb
, entry_count
);
3207 if (delay
> 0) { /* add an empty edit to delay presentation */
3208 /* In the positive delay case, the delay includes the cts
3209 * offset, and the second edit list entry below trims out
3210 * the same amount from the actual content. This makes sure
3211 * that the offset last sample is included in the edit
3212 * list duration as well. */
3214 avio_wb64(pb
, delay
);
3217 avio_wb32(pb
, delay
);
3220 avio_wb32(pb
, 0x00010000);
3222 /* Avoid accidentally ending up with start_ct = -1 which has got a
3223 * special meaning. Normally start_ct should end up positive or zero
3224 * here, but use FFMIN in case dts is a small positive integer
3225 * rounded to 0 when represented in movie timescale units. */
3226 av_assert0(av_rescale_rnd(start_dts
, mov
->movie_timescale
, track
->timescale
, AV_ROUND_DOWN
) <= 0);
3227 start_ct
= -FFMIN(start_dts
, 0);
3228 /* Note, this delay is calculated from the pts of the first sample,
3229 * ensuring that we don't reduce the duration for cases with
3234 /* For fragmented files, we don't know the full length yet. Setting
3235 * duration to 0 allows us to only specify the offset, including
3236 * the rest of the content (from all future fragments) without specifying
3237 * an explicit duration. */
3238 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
)
3243 avio_wb64(pb
, duration
);
3244 avio_wb64(pb
, start_ct
);
3246 avio_wb32(pb
, duration
);
3247 avio_wb32(pb
, start_ct
);
3249 avio_wb32(pb
, 0x00010000);
3253 static int mov_write_tref_tag(AVIOContext
*pb
, MOVTrack
*track
)
3255 avio_wb32(pb
, 20); // size
3256 ffio_wfourcc(pb
, "tref");
3257 avio_wb32(pb
, 12); // size (subatom)
3258 avio_wl32(pb
, track
->tref_tag
);
3259 avio_wb32(pb
, track
->tref_id
);
3263 // goes at the end of each track! ... Critical for PSP playback ("Incompatible data" without it)
3264 static int mov_write_uuid_tag_psp(AVIOContext
*pb
, MOVTrack
*mov
)
3266 avio_wb32(pb
, 0x34); /* size ... reports as 28 in mp4box! */
3267 ffio_wfourcc(pb
, "uuid");
3268 ffio_wfourcc(pb
, "USMT");
3269 avio_wb32(pb
, 0x21d24fce);
3270 avio_wb32(pb
, 0xbb88695c);
3271 avio_wb32(pb
, 0xfac9c740);
3272 avio_wb32(pb
, 0x1c); // another size here!
3273 ffio_wfourcc(pb
, "MTDT");
3274 avio_wb32(pb
, 0x00010012);
3275 avio_wb32(pb
, 0x0a);
3276 avio_wb32(pb
, 0x55c40000);
3282 static int mov_write_udta_sdp(AVIOContext
*pb
, MOVTrack
*track
)
3284 AVFormatContext
*ctx
= track
->rtp_ctx
;
3285 char buf
[1000] = "";
3288 ff_sdp_write_media(buf
, sizeof(buf
), ctx
->streams
[0], track
->src_track
,
3289 NULL
, NULL
, 0, 0, ctx
);
3290 av_strlcatf(buf
, sizeof(buf
), "a=control:streamid=%d\r\n", track
->track_id
);
3293 avio_wb32(pb
, len
+ 24);
3294 ffio_wfourcc(pb
, "udta");
3295 avio_wb32(pb
, len
+ 16);
3296 ffio_wfourcc(pb
, "hnti");
3297 avio_wb32(pb
, len
+ 8);
3298 ffio_wfourcc(pb
, "sdp ");
3299 avio_write(pb
, buf
, len
);
3303 static int mov_write_track_metadata(AVIOContext
*pb
, AVStream
*st
,
3304 const char *tag
, const char *str
)
3306 int64_t pos
= avio_tell(pb
);
3307 AVDictionaryEntry
*t
= av_dict_get(st
->metadata
, str
, NULL
, 0);
3308 if (!t
|| !utf8len(t
->value
))
3311 avio_wb32(pb
, 0); /* size */
3312 ffio_wfourcc(pb
, tag
); /* type */
3313 avio_write(pb
, t
->value
, strlen(t
->value
)); /* UTF8 string value */
3314 return update_size(pb
, pos
);
3317 static int mov_write_track_kind(AVIOContext
*pb
, const char *scheme_uri
,
3320 int64_t pos
= avio_tell(pb
);
3322 /* Box|FullBox basics */
3323 avio_wb32(pb
, 0); /* size placeholder */
3324 ffio_wfourcc(pb
, (const unsigned char *)"kind");
3325 avio_w8(pb
, 0); /* version = 0 */
3326 avio_wb24(pb
, 0); /* flags = 0 */
3328 /* Required null-terminated scheme URI */
3329 avio_write(pb
, (const unsigned char *)scheme_uri
,
3330 strlen(scheme_uri
));
3333 /* Optional value string */
3334 if (value
&& value
[0])
3335 avio_write(pb
, (const unsigned char *)value
,
3340 return update_size(pb
, pos
);
3343 static int mov_write_track_kinds(AVIOContext
*pb
, AVStream
*st
)
3345 int ret
= AVERROR_BUG
;
3347 for (int i
= 0; ff_mov_track_kind_table
[i
].scheme_uri
; i
++) {
3348 const struct MP4TrackKindMapping map
= ff_mov_track_kind_table
[i
];
3350 for (int j
= 0; map
.value_maps
[j
].disposition
; j
++) {
3351 const struct MP4TrackKindValueMapping value_map
= map
.value_maps
[j
];
3352 if (!(st
->disposition
& value_map
.disposition
))
3355 if ((ret
= mov_write_track_kind(pb
, map
.scheme_uri
, value_map
.value
)) < 0)
3363 static int mov_write_track_udta_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3366 AVIOContext
*pb_buf
;
3373 ret
= avio_open_dyn_buf(&pb_buf
);
3377 if (mov
->mode
& (MODE_MP4
|MODE_MOV
))
3378 mov_write_track_metadata(pb_buf
, st
, "name", "title");
3380 if (mov
->mode
& MODE_MP4
) {
3381 if ((ret
= mov_write_track_kinds(pb_buf
, st
)) < 0)
3385 if ((size
= avio_get_dyn_buf(pb_buf
, &buf
)) > 0) {
3386 avio_wb32(pb
, size
+ 8);
3387 ffio_wfourcc(pb
, "udta");
3388 avio_write(pb
, buf
, size
);
3390 ffio_free_dyn_buf(&pb_buf
);
3395 static int mov_write_trak_tag(AVFormatContext
*s
, AVIOContext
*pb
, MOVMuxContext
*mov
,
3396 MOVTrack
*track
, AVStream
*st
)
3398 int64_t pos
= avio_tell(pb
);
3399 int entry_backup
= track
->entry
;
3400 int chunk_backup
= track
->chunkCount
;
3403 /* If we want to have an empty moov, but some samples already have been
3404 * buffered (delay_moov), pretend that no samples have been written yet. */
3405 if (mov
->flags
& FF_MOV_FLAG_EMPTY_MOOV
)
3406 track
->chunkCount
= track
->entry
= 0;
3408 avio_wb32(pb
, 0); /* size */
3409 ffio_wfourcc(pb
, "trak");
3410 mov_write_tkhd_tag(pb
, mov
, track
, st
);
3412 av_assert2(mov
->use_editlist
>= 0);
3414 if (track
->start_dts
!= AV_NOPTS_VALUE
) {
3415 if (mov
->use_editlist
)
3416 mov_write_edts_tag(pb
, mov
, track
); // PSP Movies and several other cases require edts box
3417 else if ((track
->entry
&& track
->cluster
[0].dts
) || track
->mode
== MODE_PSP
|| is_clcp_track(track
))
3418 av_log(mov
->fc
, AV_LOG_WARNING
,
3419 "Not writing any edit list even though one would have been required\n");
3422 if (track
->tref_tag
)
3423 mov_write_tref_tag(pb
, track
);
3425 if ((ret
= mov_write_mdia_tag(s
, pb
, mov
, track
)) < 0)
3427 if (track
->mode
== MODE_PSP
)
3428 mov_write_uuid_tag_psp(pb
, track
); // PSP Movies require this uuid box
3429 if (track
->tag
== MKTAG('r','t','p',' '))
3430 mov_write_udta_sdp(pb
, track
);
3431 if (track
->mode
== MODE_MOV
) {
3432 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
3433 double sample_aspect_ratio
= av_q2d(st
->sample_aspect_ratio
);
3434 if (st
->sample_aspect_ratio
.num
&& 1.0 != sample_aspect_ratio
) {
3435 mov_write_tapt_tag(pb
, track
);
3438 if (is_clcp_track(track
) && st
->sample_aspect_ratio
.num
) {
3439 mov_write_tapt_tag(pb
, track
);
3442 mov_write_track_udta_tag(pb
, mov
, st
);
3443 track
->entry
= entry_backup
;
3444 track
->chunkCount
= chunk_backup
;
3445 return update_size(pb
, pos
);
3448 static int mov_write_iods_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
3450 int i
, has_audio
= 0, has_video
= 0;
3451 int64_t pos
= avio_tell(pb
);
3452 int audio_profile
= mov
->iods_audio_profile
;
3453 int video_profile
= mov
->iods_video_profile
;
3454 for (i
= 0; i
< mov
->nb_streams
; i
++) {
3455 if (mov
->tracks
[i
].entry
> 0 || mov
->flags
& FF_MOV_FLAG_EMPTY_MOOV
) {
3456 has_audio
|= mov
->tracks
[i
].par
->codec_type
== AVMEDIA_TYPE_AUDIO
;
3457 has_video
|= mov
->tracks
[i
].par
->codec_type
== AVMEDIA_TYPE_VIDEO
;
3460 if (audio_profile
< 0)
3461 audio_profile
= 0xFF - has_audio
;
3462 if (video_profile
< 0)
3463 video_profile
= 0xFF - has_video
;
3464 avio_wb32(pb
, 0x0); /* size */
3465 ffio_wfourcc(pb
, "iods");
3466 avio_wb32(pb
, 0); /* version & flags */
3467 put_descr(pb
, 0x10, 7);
3468 avio_wb16(pb
, 0x004f);
3471 avio_w8(pb
, audio_profile
);
3472 avio_w8(pb
, video_profile
);
3474 return update_size(pb
, pos
);
3477 static int mov_write_trex_tag(AVIOContext
*pb
, MOVTrack
*track
)
3479 avio_wb32(pb
, 0x20); /* size */
3480 ffio_wfourcc(pb
, "trex");
3481 avio_wb32(pb
, 0); /* version & flags */
3482 avio_wb32(pb
, track
->track_id
); /* track ID */
3483 avio_wb32(pb
, 1); /* default sample description index */
3484 avio_wb32(pb
, 0); /* default sample duration */
3485 avio_wb32(pb
, 0); /* default sample size */
3486 avio_wb32(pb
, 0); /* default sample flags */
3490 static int mov_write_mvex_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
3492 int64_t pos
= avio_tell(pb
);
3494 avio_wb32(pb
, 0x0); /* size */
3495 ffio_wfourcc(pb
, "mvex");
3496 for (i
= 0; i
< mov
->nb_streams
; i
++)
3497 mov_write_trex_tag(pb
, &mov
->tracks
[i
]);
3498 return update_size(pb
, pos
);
3501 static int mov_write_mvhd_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
3503 int max_track_id
= 1, i
;
3504 int64_t max_track_len
= 0;
3507 for (i
= 0; i
< mov
->nb_streams
; i
++) {
3508 if (mov
->tracks
[i
].entry
> 0 && mov
->tracks
[i
].timescale
) {
3509 int64_t max_track_len_temp
= av_rescale_rnd(
3510 calc_pts_duration(mov
, &mov
->tracks
[i
]),
3511 mov
->movie_timescale
,
3512 mov
->tracks
[i
].timescale
,
3514 if (max_track_len
< max_track_len_temp
)
3515 max_track_len
= max_track_len_temp
;
3516 if (max_track_id
< mov
->tracks
[i
].track_id
)
3517 max_track_id
= mov
->tracks
[i
].track_id
;
3520 /* If using delay_moov, make sure the output is the same as if no
3521 * samples had been written yet. */
3522 if (mov
->flags
& FF_MOV_FLAG_EMPTY_MOOV
) {
3527 version
= max_track_len
< UINT32_MAX
? 0 : 1;
3528 avio_wb32(pb
, version
== 1 ? 120 : 108); /* size */
3530 ffio_wfourcc(pb
, "mvhd");
3531 avio_w8(pb
, version
);
3532 avio_wb24(pb
, 0); /* flags */
3534 avio_wb64(pb
, mov
->time
);
3535 avio_wb64(pb
, mov
->time
);
3537 avio_wb32(pb
, mov
->time
); /* creation time */
3538 avio_wb32(pb
, mov
->time
); /* modification time */
3540 avio_wb32(pb
, mov
->movie_timescale
);
3541 (version
== 1) ? avio_wb64(pb
, max_track_len
) : avio_wb32(pb
, max_track_len
); /* duration of longest track */
3543 avio_wb32(pb
, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
3544 avio_wb16(pb
, 0x0100); /* reserved (preferred volume) 1.0 = normal */
3545 ffio_fill(pb
, 0, 2 + 2 * 4); /* reserved */
3547 /* Matrix structure */
3548 write_matrix(pb
, 1, 0, 0, 1, 0, 0);
3550 avio_wb32(pb
, 0); /* reserved (preview time) */
3551 avio_wb32(pb
, 0); /* reserved (preview duration) */
3552 avio_wb32(pb
, 0); /* reserved (poster time) */
3553 avio_wb32(pb
, 0); /* reserved (selection time) */
3554 avio_wb32(pb
, 0); /* reserved (selection duration) */
3555 avio_wb32(pb
, 0); /* reserved (current time) */
3556 avio_wb32(pb
, max_track_id
+ 1); /* Next track id */
3560 static int mov_write_itunes_hdlr_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3563 avio_wb32(pb
, 33); /* size */
3564 ffio_wfourcc(pb
, "hdlr");
3567 ffio_wfourcc(pb
, "mdir");
3568 ffio_wfourcc(pb
, "appl");
3575 /* helper function to write a data tag with the specified string as data */
3576 static int mov_write_string_data_tag(AVIOContext
*pb
, const char *data
, int lang
, int long_style
)
3578 size_t data_len
= strlen(data
);
3580 int size
= 16 + data_len
;
3581 avio_wb32(pb
, size
); /* size */
3582 ffio_wfourcc(pb
, "data");
3585 avio_write(pb
, data
, data_len
);
3588 avio_wb16(pb
, data_len
); /* string length */
3590 lang
= ff_mov_iso639_to_lang("und", 1);
3591 avio_wb16(pb
, lang
);
3592 avio_write(pb
, data
, data_len
);
3593 return data_len
+ 4;
3597 static int mov_write_string_tag(AVIOContext
*pb
, const char *name
,
3598 const char *value
, int lang
, int long_style
)
3601 if (value
&& value
[0]) {
3602 int64_t pos
= avio_tell(pb
);
3603 avio_wb32(pb
, 0); /* size */
3604 ffio_wfourcc(pb
, name
);
3605 mov_write_string_data_tag(pb
, value
, lang
, long_style
);
3606 size
= update_size(pb
, pos
);
3611 static AVDictionaryEntry
*get_metadata_lang(AVFormatContext
*s
,
3612 const char *tag
, int *lang
)
3615 AVDictionaryEntry
*t
, *t2
= NULL
;
3620 if (!(t
= av_dict_get(s
->metadata
, tag
, NULL
, 0)))
3623 len
= strlen(t
->key
);
3624 snprintf(tag2
, sizeof(tag2
), "%s-", tag
);
3625 while ((t2
= av_dict_get(s
->metadata
, tag2
, t2
, AV_DICT_IGNORE_SUFFIX
))) {
3626 len2
= strlen(t2
->key
);
3627 if (len2
== len
+ 4 && !strcmp(t
->value
, t2
->value
)
3628 && (l
= ff_mov_iso639_to_lang(&t2
->key
[len2
- 3], 1)) >= 0) {
3636 static int mov_write_string_metadata(AVFormatContext
*s
, AVIOContext
*pb
,
3637 const char *name
, const char *tag
,
3641 AVDictionaryEntry
*t
= get_metadata_lang(s
, tag
, &lang
);
3644 return mov_write_string_tag(pb
, name
, t
->value
, lang
, long_style
);
3647 /* iTunes bpm number */
3648 static int mov_write_tmpo_tag(AVIOContext
*pb
, AVFormatContext
*s
)
3650 AVDictionaryEntry
*t
= av_dict_get(s
->metadata
, "tmpo", NULL
, 0);
3651 int size
= 0, tmpo
= t
? atoi(t
->value
) : 0;
3654 avio_wb32(pb
, size
);
3655 ffio_wfourcc(pb
, "tmpo");
3656 avio_wb32(pb
, size
-8); /* size */
3657 ffio_wfourcc(pb
, "data");
3658 avio_wb32(pb
, 0x15); //type specifier
3660 avio_wb16(pb
, tmpo
); // data
3665 /* 3GPP TS 26.244 */
3666 static int mov_write_loci_tag(AVFormatContext
*s
, AVIOContext
*pb
)
3669 int64_t pos
= avio_tell(pb
);
3670 double latitude
, longitude
, altitude
;
3671 int32_t latitude_fix
, longitude_fix
, altitude_fix
;
3672 AVDictionaryEntry
*t
= get_metadata_lang(s
, "location", &lang
);
3673 const char *ptr
, *place
= "";
3675 static const char *astronomical_body
= "earth";
3680 longitude
= strtod(ptr
, &end
);
3682 av_log(s
, AV_LOG_WARNING
, "malformed location metadata\n");
3686 latitude
= strtod(ptr
, &end
);
3688 av_log(s
, AV_LOG_WARNING
, "malformed location metadata\n");
3692 altitude
= strtod(ptr
, &end
);
3693 /* If no altitude was present, the default 0 should be fine */
3697 latitude_fix
= (int32_t) ((1 << 16) * latitude
);
3698 longitude_fix
= (int32_t) ((1 << 16) * longitude
);
3699 altitude_fix
= (int32_t) ((1 << 16) * altitude
);
3701 avio_wb32(pb
, 0); /* size */
3702 ffio_wfourcc(pb
, "loci"); /* type */
3703 avio_wb32(pb
, 0); /* version + flags */
3704 avio_wb16(pb
, lang
);
3705 avio_write(pb
, place
, strlen(place
) + 1);
3706 avio_w8(pb
, 0); /* role of place (0 == shooting location, 1 == real location, 2 == fictional location) */
3707 avio_wb32(pb
, latitude_fix
);
3708 avio_wb32(pb
, longitude_fix
);
3709 avio_wb32(pb
, altitude_fix
);
3710 avio_write(pb
, astronomical_body
, strlen(astronomical_body
) + 1);
3711 avio_w8(pb
, 0); /* additional notes, null terminated string */
3713 return update_size(pb
, pos
);
3716 /* iTunes track or disc number */
3717 static int mov_write_trkn_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3718 AVFormatContext
*s
, int disc
)
3720 AVDictionaryEntry
*t
= av_dict_get(s
->metadata
,
3721 disc
? "disc" : "track",
3723 int size
= 0, track
= t
? atoi(t
->value
) : 0;
3726 char *slash
= strchr(t
->value
, '/');
3728 tracks
= atoi(slash
+ 1);
3729 avio_wb32(pb
, 32); /* size */
3730 ffio_wfourcc(pb
, disc
? "disk" : "trkn");
3731 avio_wb32(pb
, 24); /* size */
3732 ffio_wfourcc(pb
, "data");
3733 avio_wb32(pb
, 0); // 8 bytes empty
3735 avio_wb16(pb
, 0); // empty
3736 avio_wb16(pb
, track
); // track / disc number
3737 avio_wb16(pb
, tracks
); // total track / disc number
3738 avio_wb16(pb
, 0); // empty
3744 static int mov_write_int8_metadata(AVFormatContext
*s
, AVIOContext
*pb
,
3745 const char *name
, const char *tag
,
3748 AVDictionaryEntry
*t
= NULL
;
3750 int size
= 24 + len
;
3752 if (len
!= 1 && len
!= 4)
3755 if (!(t
= av_dict_get(s
->metadata
, tag
, NULL
, 0)))
3757 num
= atoi(t
->value
);
3759 avio_wb32(pb
, size
);
3760 ffio_wfourcc(pb
, name
);
3761 avio_wb32(pb
, size
- 8);
3762 ffio_wfourcc(pb
, "data");
3763 avio_wb32(pb
, 0x15);
3765 if (len
==4) avio_wb32(pb
, num
);
3766 else avio_w8 (pb
, num
);
3771 static int mov_write_covr(AVIOContext
*pb
, AVFormatContext
*s
)
3773 MOVMuxContext
*mov
= s
->priv_data
;
3777 for (i
= 0; i
< s
->nb_streams
; i
++) {
3778 MOVTrack
*trk
= &mov
->tracks
[i
];
3780 if (!is_cover_image(trk
->st
) || trk
->cover_image
->size
<= 0)
3784 pos
= avio_tell(pb
);
3786 ffio_wfourcc(pb
, "covr");
3788 avio_wb32(pb
, 16 + trk
->cover_image
->size
);
3789 ffio_wfourcc(pb
, "data");
3790 avio_wb32(pb
, trk
->tag
);
3792 avio_write(pb
, trk
->cover_image
->data
, trk
->cover_image
->size
);
3795 return pos
? update_size(pb
, pos
) : 0;
3798 /* iTunes meta data list */
3799 static int mov_write_ilst_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3802 int64_t pos
= avio_tell(pb
);
3803 avio_wb32(pb
, 0); /* size */
3804 ffio_wfourcc(pb
, "ilst");
3805 mov_write_string_metadata(s
, pb
, "\251nam", "title" , 1);
3806 mov_write_string_metadata(s
, pb
, "\251ART", "artist" , 1);
3807 mov_write_string_metadata(s
, pb
, "aART", "album_artist", 1);
3808 mov_write_string_metadata(s
, pb
, "\251wrt", "composer" , 1);
3809 mov_write_string_metadata(s
, pb
, "\251alb", "album" , 1);
3810 mov_write_string_metadata(s
, pb
, "\251day", "date" , 1);
3811 if (!mov_write_string_metadata(s
, pb
, "\251too", "encoding_tool", 1)) {
3812 if (!(s
->flags
& AVFMT_FLAG_BITEXACT
))
3813 mov_write_string_tag(pb
, "\251too", LIBAVFORMAT_IDENT
, 0, 1);
3815 mov_write_string_metadata(s
, pb
, "\251cmt", "comment" , 1);
3816 mov_write_string_metadata(s
, pb
, "\251gen", "genre" , 1);
3817 mov_write_string_metadata(s
, pb
, "cprt", "copyright", 1);
3818 mov_write_string_metadata(s
, pb
, "\251grp", "grouping" , 1);
3819 mov_write_string_metadata(s
, pb
, "\251lyr", "lyrics" , 1);
3820 mov_write_string_metadata(s
, pb
, "desc", "description",1);
3821 mov_write_string_metadata(s
, pb
, "ldes", "synopsis" , 1);
3822 mov_write_string_metadata(s
, pb
, "tvsh", "show" , 1);
3823 mov_write_string_metadata(s
, pb
, "tven", "episode_id",1);
3824 mov_write_string_metadata(s
, pb
, "tvnn", "network" , 1);
3825 mov_write_string_metadata(s
, pb
, "keyw", "keywords" , 1);
3826 mov_write_int8_metadata (s
, pb
, "tves", "episode_sort",4);
3827 mov_write_int8_metadata (s
, pb
, "tvsn", "season_number",4);
3828 mov_write_int8_metadata (s
, pb
, "stik", "media_type",1);
3829 mov_write_int8_metadata (s
, pb
, "hdvd", "hd_video", 1);
3830 mov_write_int8_metadata (s
, pb
, "pgap", "gapless_playback",1);
3831 mov_write_int8_metadata (s
, pb
, "cpil", "compilation", 1);
3832 mov_write_covr(pb
, s
);
3833 mov_write_trkn_tag(pb
, mov
, s
, 0); // track number
3834 mov_write_trkn_tag(pb
, mov
, s
, 1); // disc number
3835 mov_write_tmpo_tag(pb
, s
);
3836 return update_size(pb
, pos
);
3839 static int mov_write_mdta_hdlr_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3842 avio_wb32(pb
, 33); /* size */
3843 ffio_wfourcc(pb
, "hdlr");
3846 ffio_wfourcc(pb
, "mdta");
3854 static int mov_write_mdta_keys_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3857 AVDictionaryEntry
*t
= NULL
;
3858 int64_t pos
= avio_tell(pb
);
3859 int64_t curpos
, entry_pos
;
3862 avio_wb32(pb
, 0); /* size */
3863 ffio_wfourcc(pb
, "keys");
3865 entry_pos
= avio_tell(pb
);
3866 avio_wb32(pb
, 0); /* entry count */
3868 while (t
= av_dict_get(s
->metadata
, "", t
, AV_DICT_IGNORE_SUFFIX
)) {
3869 size_t key_len
= strlen(t
->key
);
3870 avio_wb32(pb
, key_len
+ 8);
3871 ffio_wfourcc(pb
, "mdta");
3872 avio_write(pb
, t
->key
, key_len
);
3875 curpos
= avio_tell(pb
);
3876 avio_seek(pb
, entry_pos
, SEEK_SET
);
3877 avio_wb32(pb
, count
); // rewrite entry count
3878 avio_seek(pb
, curpos
, SEEK_SET
);
3880 return update_size(pb
, pos
);
3883 static int mov_write_mdta_ilst_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3886 AVDictionaryEntry
*t
= NULL
;
3887 int64_t pos
= avio_tell(pb
);
3888 int count
= 1; /* keys are 1-index based */
3890 avio_wb32(pb
, 0); /* size */
3891 ffio_wfourcc(pb
, "ilst");
3893 while (t
= av_dict_get(s
->metadata
, "", t
, AV_DICT_IGNORE_SUFFIX
)) {
3894 int64_t entry_pos
= avio_tell(pb
);
3895 avio_wb32(pb
, 0); /* size */
3896 avio_wb32(pb
, count
); /* key */
3897 mov_write_string_data_tag(pb
, t
->value
, 0, 1);
3898 update_size(pb
, entry_pos
);
3901 return update_size(pb
, pos
);
3904 /* meta data tags */
3905 static int mov_write_meta_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
3909 int64_t pos
= avio_tell(pb
);
3910 avio_wb32(pb
, 0); /* size */
3911 ffio_wfourcc(pb
, "meta");
3913 if (mov
->flags
& FF_MOV_FLAG_USE_MDTA
) {
3914 mov_write_mdta_hdlr_tag(pb
, mov
, s
);
3915 mov_write_mdta_keys_tag(pb
, mov
, s
);
3916 mov_write_mdta_ilst_tag(pb
, mov
, s
);
3919 /* iTunes metadata tag */
3920 mov_write_itunes_hdlr_tag(pb
, mov
, s
);
3921 mov_write_ilst_tag(pb
, mov
, s
);
3923 size
= update_size(pb
, pos
);
3927 static int mov_write_raw_metadata_tag(AVFormatContext
*s
, AVIOContext
*pb
,
3928 const char *name
, const char *key
)
3931 AVDictionaryEntry
*t
;
3933 if (!(t
= av_dict_get(s
->metadata
, key
, NULL
, 0)))
3936 len
= strlen(t
->value
);
3939 avio_wb32(pb
, size
);
3940 ffio_wfourcc(pb
, name
);
3941 avio_write(pb
, t
->value
, len
);
3947 static int ascii_to_wc(AVIOContext
*pb
, const uint8_t *b
)
3951 GET_UTF8(val
, *b
++, return -1;)
3954 avio_wb16(pb
, 0x00);
3958 static uint16_t language_code(const char *str
)
3960 return (((str
[0] - 0x60) & 0x1F) << 10) +
3961 (((str
[1] - 0x60) & 0x1F) << 5) +
3962 (( str
[2] - 0x60) & 0x1F);
3965 static int mov_write_3gp_udta_tag(AVIOContext
*pb
, AVFormatContext
*s
,
3966 const char *tag
, const char *str
)
3968 int64_t pos
= avio_tell(pb
);
3969 AVDictionaryEntry
*t
= av_dict_get(s
->metadata
, str
, NULL
, 0);
3970 if (!t
|| !utf8len(t
->value
))
3972 avio_wb32(pb
, 0); /* size */
3973 ffio_wfourcc(pb
, tag
); /* type */
3974 avio_wb32(pb
, 0); /* version + flags */
3975 if (!strcmp(tag
, "yrrc"))
3976 avio_wb16(pb
, atoi(t
->value
));
3978 avio_wb16(pb
, language_code("eng")); /* language */
3979 avio_write(pb
, t
->value
, strlen(t
->value
) + 1); /* UTF8 string value */
3980 if (!strcmp(tag
, "albm") &&
3981 (t
= av_dict_get(s
->metadata
, "track", NULL
, 0)))
3982 avio_w8(pb
, atoi(t
->value
));
3984 return update_size(pb
, pos
);
3987 static int mov_write_chpl_tag(AVIOContext
*pb
, AVFormatContext
*s
)
3989 int64_t pos
= avio_tell(pb
);
3990 int i
, nb_chapters
= FFMIN(s
->nb_chapters
, 255);
3992 avio_wb32(pb
, 0); // size
3993 ffio_wfourcc(pb
, "chpl");
3994 avio_wb32(pb
, 0x01000000); // version + flags
3995 avio_wb32(pb
, 0); // unknown
3996 avio_w8(pb
, nb_chapters
);
3998 for (i
= 0; i
< nb_chapters
; i
++) {
3999 AVChapter
*c
= s
->chapters
[i
];
4000 AVDictionaryEntry
*t
;
4001 avio_wb64(pb
, av_rescale_q(c
->start
, c
->time_base
, (AVRational
){1,10000000}));
4003 if ((t
= av_dict_get(c
->metadata
, "title", NULL
, 0))) {
4004 int len
= FFMIN(strlen(t
->value
), 255);
4006 avio_write(pb
, t
->value
, len
);
4010 return update_size(pb
, pos
);
4013 static int mov_write_udta_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
4016 AVIOContext
*pb_buf
;
4020 ret
= avio_open_dyn_buf(&pb_buf
);
4024 if (mov
->mode
& MODE_3GP
) {
4025 mov_write_3gp_udta_tag(pb_buf
, s
, "perf", "artist");
4026 mov_write_3gp_udta_tag(pb_buf
, s
, "titl", "title");
4027 mov_write_3gp_udta_tag(pb_buf
, s
, "auth", "author");
4028 mov_write_3gp_udta_tag(pb_buf
, s
, "gnre", "genre");
4029 mov_write_3gp_udta_tag(pb_buf
, s
, "dscp", "comment");
4030 mov_write_3gp_udta_tag(pb_buf
, s
, "albm", "album");
4031 mov_write_3gp_udta_tag(pb_buf
, s
, "cprt", "copyright");
4032 mov_write_3gp_udta_tag(pb_buf
, s
, "yrrc", "date");
4033 mov_write_loci_tag(s
, pb_buf
);
4034 } 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
4035 mov_write_string_metadata(s
, pb_buf
, "\251ART", "artist", 0);
4036 mov_write_string_metadata(s
, pb_buf
, "\251nam", "title", 0);
4037 mov_write_string_metadata(s
, pb_buf
, "\251aut", "author", 0);
4038 mov_write_string_metadata(s
, pb_buf
, "\251alb", "album", 0);
4039 mov_write_string_metadata(s
, pb_buf
, "\251day", "date", 0);
4040 mov_write_string_metadata(s
, pb_buf
, "\251swr", "encoder", 0);
4041 // currently ignored by mov.c
4042 mov_write_string_metadata(s
, pb_buf
, "\251des", "comment", 0);
4043 // add support for libquicktime, this atom is also actually read by mov.c
4044 mov_write_string_metadata(s
, pb_buf
, "\251cmt", "comment", 0);
4045 mov_write_string_metadata(s
, pb_buf
, "\251gen", "genre", 0);
4046 mov_write_string_metadata(s
, pb_buf
, "\251cpy", "copyright", 0);
4047 mov_write_string_metadata(s
, pb_buf
, "\251mak", "make", 0);
4048 mov_write_string_metadata(s
, pb_buf
, "\251mod", "model", 0);
4049 mov_write_string_metadata(s
, pb_buf
, "\251xyz", "location", 0);
4050 mov_write_string_metadata(s
, pb_buf
, "\251key", "keywords", 0);
4051 mov_write_raw_metadata_tag(s
, pb_buf
, "XMP_", "xmp");
4053 /* iTunes meta data */
4054 mov_write_meta_tag(pb_buf
, mov
, s
);
4055 mov_write_loci_tag(s
, pb_buf
);
4058 if (s
->nb_chapters
&& !(mov
->flags
& FF_MOV_FLAG_DISABLE_CHPL
))
4059 mov_write_chpl_tag(pb_buf
, s
);
4061 if ((size
= avio_get_dyn_buf(pb_buf
, &buf
)) > 0) {
4062 avio_wb32(pb
, size
+ 8);
4063 ffio_wfourcc(pb
, "udta");
4064 avio_write(pb
, buf
, size
);
4066 ffio_free_dyn_buf(&pb_buf
);
4071 static void mov_write_psp_udta_tag(AVIOContext
*pb
,
4072 const char *str
, const char *lang
, int type
)
4074 int len
= utf8len(str
) + 1;
4077 avio_wb16(pb
, len
* 2 + 10); /* size */
4078 avio_wb32(pb
, type
); /* type */
4079 avio_wb16(pb
, language_code(lang
)); /* language */
4080 avio_wb16(pb
, 0x01); /* ? */
4081 ascii_to_wc(pb
, str
);
4084 static int mov_write_uuidusmt_tag(AVIOContext
*pb
, AVFormatContext
*s
)
4086 AVDictionaryEntry
*title
= av_dict_get(s
->metadata
, "title", NULL
, 0);
4090 pos
= avio_tell(pb
);
4091 avio_wb32(pb
, 0); /* size placeholder*/
4092 ffio_wfourcc(pb
, "uuid");
4093 ffio_wfourcc(pb
, "USMT");
4094 avio_wb32(pb
, 0x21d24fce); /* 96 bit UUID */
4095 avio_wb32(pb
, 0xbb88695c);
4096 avio_wb32(pb
, 0xfac9c740);
4098 pos2
= avio_tell(pb
);
4099 avio_wb32(pb
, 0); /* size placeholder*/
4100 ffio_wfourcc(pb
, "MTDT");
4104 avio_wb16(pb
, 0x0C); /* size */
4105 avio_wb32(pb
, 0x0B); /* type */
4106 avio_wb16(pb
, language_code("und")); /* language */
4107 avio_wb16(pb
, 0x0); /* ? */
4108 avio_wb16(pb
, 0x021C); /* data */
4110 if (!(s
->flags
& AVFMT_FLAG_BITEXACT
))
4111 mov_write_psp_udta_tag(pb
, LIBAVCODEC_IDENT
, "eng", 0x04);
4112 mov_write_psp_udta_tag(pb
, title
->value
, "eng", 0x01);
4113 mov_write_psp_udta_tag(pb
, "2006/04/01 11:11:11", "und", 0x03);
4115 update_size(pb
, pos2
);
4116 return update_size(pb
, pos
);
4122 static void build_chunks(MOVTrack
*trk
)
4125 MOVIentry
*chunk
= &trk
->cluster
[0];
4126 uint64_t chunkSize
= chunk
->size
;
4127 chunk
->chunkNum
= 1;
4128 if (trk
->chunkCount
)
4130 trk
->chunkCount
= 1;
4131 for (i
= 1; i
<trk
->entry
; i
++){
4132 if (chunk
->pos
+ chunkSize
== trk
->cluster
[i
].pos
&&
4133 chunkSize
+ trk
->cluster
[i
].size
< (1<<20)){
4134 chunkSize
+= trk
->cluster
[i
].size
;
4135 chunk
->samples_in_chunk
+= trk
->cluster
[i
].entries
;
4137 trk
->cluster
[i
].chunkNum
= chunk
->chunkNum
+1;
4138 chunk
=&trk
->cluster
[i
];
4139 chunkSize
= chunk
->size
;
4146 * Assign track ids. If option "use_stream_ids_as_track_ids" is set,
4147 * the stream ids are used as track ids.
4149 * This assumes mov->tracks and s->streams are in the same order and
4150 * there are no gaps in either of them (so mov->tracks[n] refers to
4153 * As an exception, there can be more entries in
4154 * s->streams than in mov->tracks, in which case new track ids are
4155 * generated (starting after the largest found stream id).
4157 static int mov_setup_track_ids(MOVMuxContext
*mov
, AVFormatContext
*s
)
4161 if (mov
->track_ids_ok
)
4164 if (mov
->use_stream_ids_as_track_ids
) {
4165 int next_generated_track_id
= 0;
4166 for (i
= 0; i
< s
->nb_streams
; i
++) {
4167 if (s
->streams
[i
]->id
> next_generated_track_id
)
4168 next_generated_track_id
= s
->streams
[i
]->id
;
4171 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4172 if (mov
->tracks
[i
].entry
<= 0 && !(mov
->flags
& FF_MOV_FLAG_FRAGMENT
))
4175 mov
->tracks
[i
].track_id
= i
>= s
->nb_streams
? ++next_generated_track_id
: s
->streams
[i
]->id
;
4178 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4179 if (mov
->tracks
[i
].entry
<= 0 && !(mov
->flags
& FF_MOV_FLAG_FRAGMENT
))
4182 mov
->tracks
[i
].track_id
= i
+ 1;
4186 mov
->track_ids_ok
= 1;
4191 static int mov_write_moov_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
4195 int64_t pos
= avio_tell(pb
);
4196 avio_wb32(pb
, 0); /* size placeholder*/
4197 ffio_wfourcc(pb
, "moov");
4199 mov_setup_track_ids(mov
, s
);
4201 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4202 if (mov
->tracks
[i
].entry
<= 0 && !(mov
->flags
& FF_MOV_FLAG_FRAGMENT
))
4205 mov
->tracks
[i
].time
= mov
->time
;
4207 if (mov
->tracks
[i
].entry
)
4208 build_chunks(&mov
->tracks
[i
]);
4211 if (mov
->chapter_track
)
4212 for (i
= 0; i
< s
->nb_streams
; i
++) {
4213 mov
->tracks
[i
].tref_tag
= MKTAG('c','h','a','p');
4214 mov
->tracks
[i
].tref_id
= mov
->tracks
[mov
->chapter_track
].track_id
;
4216 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4217 MOVTrack
*track
= &mov
->tracks
[i
];
4218 if (track
->tag
== MKTAG('r','t','p',' ')) {
4219 track
->tref_tag
= MKTAG('h','i','n','t');
4220 track
->tref_id
= mov
->tracks
[track
->src_track
].track_id
;
4221 } else if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
4224 fallback
= (int*)av_stream_get_side_data(track
->st
,
4225 AV_PKT_DATA_FALLBACK_TRACK
,
4227 if (fallback
!= NULL
&& size
== sizeof(int)) {
4228 if (*fallback
>= 0 && *fallback
< mov
->nb_streams
) {
4229 track
->tref_tag
= MKTAG('f','a','l','l');
4230 track
->tref_id
= mov
->tracks
[*fallback
].track_id
;
4235 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4236 if (mov
->tracks
[i
].tag
== MKTAG('t','m','c','d')) {
4237 int src_trk
= mov
->tracks
[i
].src_track
;
4238 mov
->tracks
[src_trk
].tref_tag
= mov
->tracks
[i
].tag
;
4239 mov
->tracks
[src_trk
].tref_id
= mov
->tracks
[i
].track_id
;
4240 //src_trk may have a different timescale than the tmcd track
4241 mov
->tracks
[i
].track_duration
= av_rescale(mov
->tracks
[src_trk
].track_duration
,
4242 mov
->tracks
[i
].timescale
,
4243 mov
->tracks
[src_trk
].timescale
);
4247 mov_write_mvhd_tag(pb
, mov
);
4248 if (mov
->mode
!= MODE_MOV
&& !mov
->iods_skip
)
4249 mov_write_iods_tag(pb
, mov
);
4250 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4251 if (mov
->tracks
[i
].entry
> 0 || mov
->flags
& FF_MOV_FLAG_FRAGMENT
) {
4252 int ret
= mov_write_trak_tag(s
, pb
, mov
, &(mov
->tracks
[i
]), i
< s
->nb_streams
? s
->streams
[i
] : NULL
);
4257 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
)
4258 mov_write_mvex_tag(pb
, mov
); /* QuickTime requires trak to precede this */
4260 if (mov
->mode
== MODE_PSP
)
4261 mov_write_uuidusmt_tag(pb
, s
);
4263 mov_write_udta_tag(pb
, mov
, s
);
4265 return update_size(pb
, pos
);
4268 static void param_write_int(AVIOContext
*pb
, const char *name
, int value
)
4270 avio_printf(pb
, "<param name=\"%s\" value=\"%d\" valuetype=\"data\"/>\n", name
, value
);
4273 static void param_write_string(AVIOContext
*pb
, const char *name
, const char *value
)
4275 avio_printf(pb
, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name
, value
);
4278 static void param_write_hex(AVIOContext
*pb
, const char *name
, const uint8_t *value
, int len
)
4281 len
= FFMIN(sizeof(buf
) / 2 - 1, len
);
4282 ff_data_to_hex(buf
, value
, len
, 0);
4283 avio_printf(pb
, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name
, buf
);
4286 static int mov_write_isml_manifest(AVIOContext
*pb
, MOVMuxContext
*mov
, AVFormatContext
*s
)
4288 int64_t pos
= avio_tell(pb
);
4291 static const uint8_t uuid
[] = {
4292 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
4293 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
4297 ffio_wfourcc(pb
, "uuid");
4298 avio_write(pb
, uuid
, sizeof(uuid
));
4301 avio_printf(pb
, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
4302 avio_printf(pb
, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
4303 avio_printf(pb
, "<head>\n");
4304 if (!(mov
->fc
->flags
& AVFMT_FLAG_BITEXACT
))
4305 avio_printf(pb
, "<meta name=\"creator\" content=\"%s\" />\n",
4307 avio_printf(pb
, "</head>\n");
4308 avio_printf(pb
, "<body>\n");
4309 avio_printf(pb
, "<switch>\n");
4311 mov_setup_track_ids(mov
, s
);
4313 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4314 MOVTrack
*track
= &mov
->tracks
[i
];
4315 struct mpeg4_bit_rate_values bit_rates
=
4316 calculate_mpeg4_bit_rates(track
);
4318 int track_id
= track
->track_id
;
4319 char track_name_buf
[32] = { 0 };
4321 AVStream
*st
= track
->st
;
4322 AVDictionaryEntry
*lang
= av_dict_get(st
->metadata
, "language", NULL
,0);
4324 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
&& !is_cover_image(st
)) {
4326 } else if (track
->par
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
4332 avio_printf(pb
, "<%s systemBitrate=\"%"PRIu32
"\">\n", type
,
4333 bit_rates
.avg_bit_rate
);
4334 param_write_int(pb
, "systemBitrate", bit_rates
.avg_bit_rate
);
4335 param_write_int(pb
, "trackID", track_id
);
4336 param_write_string(pb
, "systemLanguage", lang
? lang
->value
: "und");
4338 /* Build track name piece by piece: */
4340 av_strlcat(track_name_buf
, type
, sizeof(track_name_buf
));
4341 /* 2. track language, if available */
4343 av_strlcatf(track_name_buf
, sizeof(track_name_buf
),
4344 "_%s", lang
->value
);
4345 /* 3. special type suffix */
4346 /* "_cc" = closed captions, "_ad" = audio_description */
4347 if (st
->disposition
& AV_DISPOSITION_HEARING_IMPAIRED
)
4348 av_strlcat(track_name_buf
, "_cc", sizeof(track_name_buf
));
4349 else if (st
->disposition
& AV_DISPOSITION_VISUAL_IMPAIRED
)
4350 av_strlcat(track_name_buf
, "_ad", sizeof(track_name_buf
));
4352 param_write_string(pb
, "trackName", track_name_buf
);
4354 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
4355 if (track
->par
->codec_id
== AV_CODEC_ID_H264
) {
4357 int size
= track
->par
->extradata_size
;
4358 if (!ff_avc_write_annexb_extradata(track
->par
->extradata
, &ptr
,
4360 param_write_hex(pb
, "CodecPrivateData",
4361 ptr
? ptr
: track
->par
->extradata
,
4365 param_write_string(pb
, "FourCC", "H264");
4366 } else if (track
->par
->codec_id
== AV_CODEC_ID_VC1
) {
4367 param_write_string(pb
, "FourCC", "WVC1");
4368 param_write_hex(pb
, "CodecPrivateData", track
->par
->extradata
,
4369 track
->par
->extradata_size
);
4371 param_write_int(pb
, "MaxWidth", track
->par
->width
);
4372 param_write_int(pb
, "MaxHeight", track
->par
->height
);
4373 param_write_int(pb
, "DisplayWidth", track
->par
->width
);
4374 param_write_int(pb
, "DisplayHeight", track
->par
->height
);
4376 if (track
->par
->codec_id
== AV_CODEC_ID_AAC
) {
4377 switch (track
->par
->profile
)
4379 case FF_PROFILE_AAC_HE_V2
:
4380 param_write_string(pb
, "FourCC", "AACP");
4382 case FF_PROFILE_AAC_HE
:
4383 param_write_string(pb
, "FourCC", "AACH");
4386 param_write_string(pb
, "FourCC", "AACL");
4388 } else if (track
->par
->codec_id
== AV_CODEC_ID_WMAPRO
) {
4389 param_write_string(pb
, "FourCC", "WMAP");
4391 param_write_hex(pb
, "CodecPrivateData", track
->par
->extradata
,
4392 track
->par
->extradata_size
);
4393 param_write_int(pb
, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags
,
4394 track
->par
->codec_id
));
4395 param_write_int(pb
, "Channels", track
->par
->channels
);
4396 param_write_int(pb
, "SamplingRate", track
->par
->sample_rate
);
4397 param_write_int(pb
, "BitsPerSample", 16);
4398 param_write_int(pb
, "PacketSize", track
->par
->block_align
?
4399 track
->par
->block_align
: 4);
4401 avio_printf(pb
, "</%s>\n", type
);
4403 avio_printf(pb
, "</switch>\n");
4404 avio_printf(pb
, "</body>\n");
4405 avio_printf(pb
, "</smil>\n");
4407 return update_size(pb
, pos
);
4410 static int mov_write_mfhd_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
4413 ffio_wfourcc(pb
, "mfhd");
4415 avio_wb32(pb
, mov
->fragments
);
4419 static uint32_t get_sample_flags(MOVTrack
*track
, MOVIentry
*entry
)
4421 return entry
->flags
& MOV_SYNC_SAMPLE
? MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO
:
4422 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES
| MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC
);
4425 static int mov_write_tfhd_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
4426 MOVTrack
*track
, int64_t moof_offset
)
4428 int64_t pos
= avio_tell(pb
);
4429 uint32_t flags
= MOV_TFHD_DEFAULT_SIZE
| MOV_TFHD_DEFAULT_DURATION
|
4430 MOV_TFHD_BASE_DATA_OFFSET
;
4431 if (!track
->entry
) {
4432 flags
|= MOV_TFHD_DURATION_IS_EMPTY
;
4434 flags
|= MOV_TFHD_DEFAULT_FLAGS
;
4436 if (mov
->flags
& FF_MOV_FLAG_OMIT_TFHD_OFFSET
)
4437 flags
&= ~MOV_TFHD_BASE_DATA_OFFSET
;
4438 if (mov
->flags
& FF_MOV_FLAG_DEFAULT_BASE_MOOF
) {
4439 flags
&= ~MOV_TFHD_BASE_DATA_OFFSET
;
4440 flags
|= MOV_TFHD_DEFAULT_BASE_IS_MOOF
;
4442 /* CMAF requires all values to be explicit in tfhd atoms */
4443 if (mov
->flags
& FF_MOV_FLAG_CMAF
)
4444 flags
|= MOV_TFHD_STSD_ID
;
4446 /* Don't set a default sample size, the silverlight player refuses
4447 * to play files with that set. Don't set a default sample duration,
4448 * WMP freaks out if it is set. Don't set a base data offset, PIFF
4449 * file format says it MUST NOT be set. */
4450 if (track
->mode
== MODE_ISM
)
4451 flags
&= ~(MOV_TFHD_DEFAULT_SIZE
| MOV_TFHD_DEFAULT_DURATION
|
4452 MOV_TFHD_BASE_DATA_OFFSET
| MOV_TFHD_STSD_ID
);
4454 avio_wb32(pb
, 0); /* size placeholder */
4455 ffio_wfourcc(pb
, "tfhd");
4456 avio_w8(pb
, 0); /* version */
4457 avio_wb24(pb
, flags
);
4459 avio_wb32(pb
, track
->track_id
); /* track-id */
4460 if (flags
& MOV_TFHD_BASE_DATA_OFFSET
)
4461 avio_wb64(pb
, moof_offset
);
4462 if (flags
& MOV_TFHD_STSD_ID
) {
4465 if (flags
& MOV_TFHD_DEFAULT_DURATION
) {
4466 track
->default_duration
= get_cluster_duration(track
, 0);
4467 avio_wb32(pb
, track
->default_duration
);
4469 if (flags
& MOV_TFHD_DEFAULT_SIZE
) {
4470 track
->default_size
= track
->entry
? track
->cluster
[0].size
: 1;
4471 avio_wb32(pb
, track
->default_size
);
4473 track
->default_size
= -1;
4475 if (flags
& MOV_TFHD_DEFAULT_FLAGS
) {
4476 /* Set the default flags based on the second sample, if available.
4477 * If the first sample is different, that can be signaled via a separate field. */
4478 if (track
->entry
> 1)
4479 track
->default_sample_flags
= get_sample_flags(track
, &track
->cluster
[1]);
4481 track
->default_sample_flags
=
4482 track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
?
4483 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES
| MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC
) :
4484 MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO
;
4485 avio_wb32(pb
, track
->default_sample_flags
);
4488 return update_size(pb
, pos
);
4491 static int mov_write_trun_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
4492 MOVTrack
*track
, int moof_size
,
4495 int64_t pos
= avio_tell(pb
);
4496 uint32_t flags
= MOV_TRUN_DATA_OFFSET
;
4499 for (i
= first
; i
< end
; i
++) {
4500 if (get_cluster_duration(track
, i
) != track
->default_duration
)
4501 flags
|= MOV_TRUN_SAMPLE_DURATION
;
4502 if (track
->cluster
[i
].size
!= track
->default_size
)
4503 flags
|= MOV_TRUN_SAMPLE_SIZE
;
4504 if (i
> first
&& get_sample_flags(track
, &track
->cluster
[i
]) != track
->default_sample_flags
)
4505 flags
|= MOV_TRUN_SAMPLE_FLAGS
;
4507 if (!(flags
& MOV_TRUN_SAMPLE_FLAGS
) && track
->entry
> 0 &&
4508 get_sample_flags(track
, &track
->cluster
[0]) != track
->default_sample_flags
)
4509 flags
|= MOV_TRUN_FIRST_SAMPLE_FLAGS
;
4510 if (track
->flags
& MOV_TRACK_CTTS
)
4511 flags
|= MOV_TRUN_SAMPLE_CTS
;
4513 avio_wb32(pb
, 0); /* size placeholder */
4514 ffio_wfourcc(pb
, "trun");
4515 if (mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
)
4516 avio_w8(pb
, 1); /* version */
4518 avio_w8(pb
, 0); /* version */
4519 avio_wb24(pb
, flags
);
4521 avio_wb32(pb
, end
- first
); /* sample count */
4522 if (mov
->flags
& FF_MOV_FLAG_OMIT_TFHD_OFFSET
&&
4523 !(mov
->flags
& FF_MOV_FLAG_DEFAULT_BASE_MOOF
) &&
4525 avio_wb32(pb
, 0); /* Later tracks follow immediately after the previous one */
4527 avio_wb32(pb
, moof_size
+ 8 + track
->data_offset
+
4528 track
->cluster
[first
].pos
); /* data offset */
4529 if (flags
& MOV_TRUN_FIRST_SAMPLE_FLAGS
)
4530 avio_wb32(pb
, get_sample_flags(track
, &track
->cluster
[first
]));
4532 for (i
= first
; i
< end
; i
++) {
4533 if (flags
& MOV_TRUN_SAMPLE_DURATION
)
4534 avio_wb32(pb
, get_cluster_duration(track
, i
));
4535 if (flags
& MOV_TRUN_SAMPLE_SIZE
)
4536 avio_wb32(pb
, track
->cluster
[i
].size
);
4537 if (flags
& MOV_TRUN_SAMPLE_FLAGS
)
4538 avio_wb32(pb
, get_sample_flags(track
, &track
->cluster
[i
]));
4539 if (flags
& MOV_TRUN_SAMPLE_CTS
)
4540 avio_wb32(pb
, track
->cluster
[i
].cts
);
4543 mov
->first_trun
= 0;
4544 return update_size(pb
, pos
);
4547 static int mov_write_tfxd_tag(AVIOContext
*pb
, MOVTrack
*track
)
4549 int64_t pos
= avio_tell(pb
);
4550 static const uint8_t uuid
[] = {
4551 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
4552 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
4555 avio_wb32(pb
, 0); /* size placeholder */
4556 ffio_wfourcc(pb
, "uuid");
4557 avio_write(pb
, uuid
, sizeof(uuid
));
4560 avio_wb64(pb
, track
->cluster
[0].dts
+ track
->cluster
[0].cts
);
4561 avio_wb64(pb
, track
->end_pts
-
4562 (track
->cluster
[0].dts
+ track
->cluster
[0].cts
));
4564 return update_size(pb
, pos
);
4567 static int mov_write_tfrf_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
4568 MOVTrack
*track
, int entry
)
4570 int n
= track
->nb_frag_info
- 1 - entry
, i
;
4571 int size
= 8 + 16 + 4 + 1 + 16*n
;
4572 static const uint8_t uuid
[] = {
4573 0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95,
4574 0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f
4580 avio_seek(pb
, track
->frag_info
[entry
].tfrf_offset
, SEEK_SET
);
4581 avio_wb32(pb
, size
);
4582 ffio_wfourcc(pb
, "uuid");
4583 avio_write(pb
, uuid
, sizeof(uuid
));
4587 for (i
= 0; i
< n
; i
++) {
4588 int index
= entry
+ 1 + i
;
4589 avio_wb64(pb
, track
->frag_info
[index
].time
);
4590 avio_wb64(pb
, track
->frag_info
[index
].duration
);
4592 if (n
< mov
->ism_lookahead
) {
4593 int free_size
= 16 * (mov
->ism_lookahead
- n
);
4594 avio_wb32(pb
, free_size
);
4595 ffio_wfourcc(pb
, "free");
4596 ffio_fill(pb
, 0, free_size
- 8);
4602 static int mov_write_tfrf_tags(AVIOContext
*pb
, MOVMuxContext
*mov
,
4605 int64_t pos
= avio_tell(pb
);
4607 for (i
= 0; i
< mov
->ism_lookahead
; i
++) {
4608 /* Update the tfrf tag for the last ism_lookahead fragments,
4609 * nb_frag_info - 1 is the next fragment to be written. */
4610 mov_write_tfrf_tag(pb
, mov
, track
, track
->nb_frag_info
- 2 - i
);
4612 avio_seek(pb
, pos
, SEEK_SET
);
4616 static int mov_add_tfra_entries(AVIOContext
*pb
, MOVMuxContext
*mov
, int tracks
,
4620 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4621 MOVTrack
*track
= &mov
->tracks
[i
];
4622 MOVFragmentInfo
*info
;
4623 if ((tracks
>= 0 && i
!= tracks
) || !track
->entry
)
4625 track
->nb_frag_info
++;
4626 if (track
->nb_frag_info
>= track
->frag_info_capacity
) {
4627 unsigned new_capacity
= track
->nb_frag_info
+ MOV_FRAG_INFO_ALLOC_INCREMENT
;
4628 if (av_reallocp_array(&track
->frag_info
,
4630 sizeof(*track
->frag_info
)))
4631 return AVERROR(ENOMEM
);
4632 track
->frag_info_capacity
= new_capacity
;
4634 info
= &track
->frag_info
[track
->nb_frag_info
- 1];
4635 info
->offset
= avio_tell(pb
);
4637 // Try to recreate the original pts for the first packet
4638 // from the fields we have stored
4639 info
->time
= track
->cluster
[0].dts
+ track
->cluster
[0].cts
;
4640 info
->duration
= track
->end_pts
-
4641 (track
->cluster
[0].dts
+ track
->cluster
[0].cts
);
4642 // If the pts is less than zero, we will have trimmed
4643 // away parts of the media track using an edit list,
4644 // and the corresponding start presentation time is zero.
4645 if (info
->time
< 0) {
4646 info
->duration
+= info
->time
;
4649 info
->tfrf_offset
= 0;
4650 mov_write_tfrf_tags(pb
, mov
, track
);
4655 static void mov_prune_frag_info(MOVMuxContext
*mov
, int tracks
, int max
)
4658 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4659 MOVTrack
*track
= &mov
->tracks
[i
];
4660 if ((tracks
>= 0 && i
!= tracks
) || !track
->entry
)
4662 if (track
->nb_frag_info
> max
) {
4663 memmove(track
->frag_info
, track
->frag_info
+ (track
->nb_frag_info
- max
), max
* sizeof(*track
->frag_info
));
4664 track
->nb_frag_info
= max
;
4669 static int mov_write_tfdt_tag(AVIOContext
*pb
, MOVTrack
*track
)
4671 int64_t pos
= avio_tell(pb
);
4673 avio_wb32(pb
, 0); /* size */
4674 ffio_wfourcc(pb
, "tfdt");
4675 avio_w8(pb
, 1); /* version */
4677 avio_wb64(pb
, track
->cluster
[0].dts
- track
->start_dts
);
4678 return update_size(pb
, pos
);
4681 static int mov_write_traf_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
4682 MOVTrack
*track
, int64_t moof_offset
,
4685 int64_t pos
= avio_tell(pb
);
4687 avio_wb32(pb
, 0); /* size placeholder */
4688 ffio_wfourcc(pb
, "traf");
4690 mov_write_tfhd_tag(pb
, mov
, track
, moof_offset
);
4691 if (mov
->mode
!= MODE_ISM
)
4692 mov_write_tfdt_tag(pb
, track
);
4693 for (i
= 1; i
< track
->entry
; i
++) {
4694 if (track
->cluster
[i
].pos
!= track
->cluster
[i
- 1].pos
+ track
->cluster
[i
- 1].size
) {
4695 mov_write_trun_tag(pb
, mov
, track
, moof_size
, start
, i
);
4699 mov_write_trun_tag(pb
, mov
, track
, moof_size
, start
, track
->entry
);
4700 if (mov
->mode
== MODE_ISM
) {
4701 mov_write_tfxd_tag(pb
, track
);
4703 if (mov
->ism_lookahead
) {
4704 int size
= 16 + 4 + 1 + 16 * mov
->ism_lookahead
;
4706 if (track
->nb_frag_info
> 0) {
4707 MOVFragmentInfo
*info
= &track
->frag_info
[track
->nb_frag_info
- 1];
4708 if (!info
->tfrf_offset
)
4709 info
->tfrf_offset
= avio_tell(pb
);
4711 avio_wb32(pb
, 8 + size
);
4712 ffio_wfourcc(pb
, "free");
4713 ffio_fill(pb
, 0, size
);
4717 return update_size(pb
, pos
);
4720 static int mov_write_moof_tag_internal(AVIOContext
*pb
, MOVMuxContext
*mov
,
4721 int tracks
, int moof_size
)
4723 int64_t pos
= avio_tell(pb
);
4726 avio_wb32(pb
, 0); /* size placeholder */
4727 ffio_wfourcc(pb
, "moof");
4728 mov
->first_trun
= 1;
4730 mov_write_mfhd_tag(pb
, mov
);
4731 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4732 MOVTrack
*track
= &mov
->tracks
[i
];
4733 if (tracks
>= 0 && i
!= tracks
)
4737 mov_write_traf_tag(pb
, mov
, track
, pos
, moof_size
);
4740 return update_size(pb
, pos
);
4743 static int mov_write_sidx_tag(AVIOContext
*pb
,
4744 MOVTrack
*track
, int ref_size
, int total_sidx_size
)
4746 int64_t pos
= avio_tell(pb
), offset_pos
, end_pos
;
4747 int64_t presentation_time
, duration
, offset
;
4748 unsigned starts_with_SAP
;
4753 presentation_time
= track
->cluster
[0].dts
+ track
->cluster
[0].cts
;
4754 duration
= track
->end_pts
-
4755 (track
->cluster
[0].dts
+ track
->cluster
[0].cts
);
4756 starts_with_SAP
= track
->cluster
[0].flags
& MOV_SYNC_SAMPLE
;
4758 // pts<0 should be cut away using edts
4759 if (presentation_time
< 0) {
4760 duration
+= presentation_time
;
4761 presentation_time
= 0;
4764 entries
= track
->nb_frag_info
;
4767 presentation_time
= track
->frag_info
[0].time
;
4770 avio_wb32(pb
, 0); /* size */
4771 ffio_wfourcc(pb
, "sidx");
4772 avio_w8(pb
, 1); /* version */
4774 avio_wb32(pb
, track
->track_id
); /* reference_ID */
4775 avio_wb32(pb
, track
->timescale
); /* timescale */
4776 avio_wb64(pb
, presentation_time
); /* earliest_presentation_time */
4777 offset_pos
= avio_tell(pb
);
4778 avio_wb64(pb
, 0); /* first_offset (offset to referenced moof) */
4779 avio_wb16(pb
, 0); /* reserved */
4781 avio_wb16(pb
, entries
); /* reference_count */
4782 for (i
= 0; i
< entries
; i
++) {
4783 if (!track
->entry
) {
4784 if (i
> 1 && track
->frag_info
[i
].offset
!= track
->frag_info
[i
- 1].offset
+ track
->frag_info
[i
- 1].size
) {
4785 av_log(NULL
, AV_LOG_ERROR
, "Non-consecutive fragments, writing incorrect sidx\n");
4787 duration
= track
->frag_info
[i
].duration
;
4788 ref_size
= track
->frag_info
[i
].size
;
4789 starts_with_SAP
= 1;
4791 avio_wb32(pb
, (0 << 31) | (ref_size
& 0x7fffffff)); /* reference_type (0 = media) | referenced_size */
4792 avio_wb32(pb
, duration
); /* subsegment_duration */
4793 avio_wb32(pb
, (starts_with_SAP
<< 31) | (0 << 28) | 0); /* starts_with_SAP | SAP_type | SAP_delta_time */
4796 end_pos
= avio_tell(pb
);
4797 offset
= pos
+ total_sidx_size
- end_pos
;
4798 avio_seek(pb
, offset_pos
, SEEK_SET
);
4799 avio_wb64(pb
, offset
);
4800 avio_seek(pb
, end_pos
, SEEK_SET
);
4801 return update_size(pb
, pos
);
4804 static int mov_write_sidx_tags(AVIOContext
*pb
, MOVMuxContext
*mov
,
4805 int tracks
, int ref_size
)
4808 AVIOContext
*avio_buf
;
4810 for (round
= 0; round
< 2; round
++) {
4811 // First run one round to calculate the total size of all
4813 // This would be much simpler if we'd only write one sidx
4814 // atom, for the first track in the moof.
4816 if ((ret
= ffio_open_null_buf(&avio_buf
)) < 0)
4821 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4822 MOVTrack
*track
= &mov
->tracks
[i
];
4823 if (tracks
>= 0 && i
!= tracks
)
4825 // When writing a sidx for the full file, entry is 0, but
4826 // we want to include all tracks. ref_size is 0 in this case,
4827 // since we read it from frag_info instead.
4828 if (!track
->entry
&& ref_size
> 0)
4830 total_size
-= mov_write_sidx_tag(avio_buf
, track
, ref_size
,
4834 total_size
= ffio_close_null_buf(avio_buf
);
4839 static int mov_write_prft_tag(AVIOContext
*pb
, MOVMuxContext
*mov
, int tracks
)
4841 int64_t pos
= avio_tell(pb
), pts_us
, ntp_ts
;
4842 MOVTrack
*first_track
;
4845 /* PRFT should be associated with at most one track. So, choosing only the
4849 first_track
= &(mov
->tracks
[0]);
4851 if (!first_track
->entry
) {
4852 av_log(mov
->fc
, AV_LOG_WARNING
, "Unable to write PRFT, no entries in the track\n");
4856 if (first_track
->cluster
[0].pts
== AV_NOPTS_VALUE
) {
4857 av_log(mov
->fc
, AV_LOG_WARNING
, "Unable to write PRFT, first PTS is invalid\n");
4861 if (mov
->write_prft
== MOV_PRFT_SRC_WALLCLOCK
) {
4862 if (first_track
->cluster
[0].prft
.wallclock
) {
4863 /* Round the NTP time to whole milliseconds. */
4864 ntp_ts
= ff_get_formatted_ntp_time((first_track
->cluster
[0].prft
.wallclock
/ 1000) * 1000 +
4866 flags
= first_track
->cluster
[0].prft
.flags
;
4868 ntp_ts
= ff_get_formatted_ntp_time(ff_ntp_time());
4869 } else if (mov
->write_prft
== MOV_PRFT_SRC_PTS
) {
4870 pts_us
= av_rescale_q(first_track
->cluster
[0].pts
,
4871 first_track
->st
->time_base
, AV_TIME_BASE_Q
);
4872 ntp_ts
= ff_get_formatted_ntp_time(pts_us
+ NTP_OFFSET_US
);
4874 av_log(mov
->fc
, AV_LOG_WARNING
, "Unsupported PRFT box configuration: %d\n",
4879 avio_wb32(pb
, 0); // Size place holder
4880 ffio_wfourcc(pb
, "prft"); // Type
4881 avio_w8(pb
, 1); // Version
4882 avio_wb24(pb
, flags
); // Flags
4883 avio_wb32(pb
, first_track
->track_id
); // reference track ID
4884 avio_wb64(pb
, ntp_ts
); // NTP time stamp
4885 avio_wb64(pb
, first_track
->cluster
[0].pts
); //media time
4886 return update_size(pb
, pos
);
4889 static int mov_write_moof_tag(AVIOContext
*pb
, MOVMuxContext
*mov
, int tracks
,
4892 AVIOContext
*avio_buf
;
4895 if ((ret
= ffio_open_null_buf(&avio_buf
)) < 0)
4897 mov_write_moof_tag_internal(avio_buf
, mov
, tracks
, 0);
4898 moof_size
= ffio_close_null_buf(avio_buf
);
4900 if (mov
->flags
& FF_MOV_FLAG_DASH
&&
4901 !(mov
->flags
& (FF_MOV_FLAG_GLOBAL_SIDX
| FF_MOV_FLAG_SKIP_SIDX
)))
4902 mov_write_sidx_tags(pb
, mov
, tracks
, moof_size
+ 8 + mdat_size
);
4904 if (mov
->write_prft
> MOV_PRFT_NONE
&& mov
->write_prft
< MOV_PRFT_NB
)
4905 mov_write_prft_tag(pb
, mov
, tracks
);
4907 if (mov
->flags
& FF_MOV_FLAG_GLOBAL_SIDX
||
4908 !(mov
->flags
& FF_MOV_FLAG_SKIP_TRAILER
) ||
4909 mov
->ism_lookahead
) {
4910 if ((ret
= mov_add_tfra_entries(pb
, mov
, tracks
, moof_size
+ 8 + mdat_size
)) < 0)
4912 if (!(mov
->flags
& FF_MOV_FLAG_GLOBAL_SIDX
) &&
4913 mov
->flags
& FF_MOV_FLAG_SKIP_TRAILER
) {
4914 mov_prune_frag_info(mov
, tracks
, mov
->ism_lookahead
+ 1);
4918 return mov_write_moof_tag_internal(pb
, mov
, tracks
, moof_size
);
4921 static int mov_write_tfra_tag(AVIOContext
*pb
, MOVTrack
*track
)
4923 int64_t pos
= avio_tell(pb
);
4926 avio_wb32(pb
, 0); /* size placeholder */
4927 ffio_wfourcc(pb
, "tfra");
4928 avio_w8(pb
, 1); /* version */
4931 avio_wb32(pb
, track
->track_id
);
4932 avio_wb32(pb
, 0); /* length of traf/trun/sample num */
4933 avio_wb32(pb
, track
->nb_frag_info
);
4934 for (i
= 0; i
< track
->nb_frag_info
; i
++) {
4935 avio_wb64(pb
, track
->frag_info
[i
].time
);
4936 avio_wb64(pb
, track
->frag_info
[i
].offset
+ track
->data_offset
);
4937 avio_w8(pb
, 1); /* traf number */
4938 avio_w8(pb
, 1); /* trun number */
4939 avio_w8(pb
, 1); /* sample number */
4942 return update_size(pb
, pos
);
4945 static int mov_write_mfra_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
4947 AVIOContext
*mfra_pb
;
4951 ret
= avio_open_dyn_buf(&mfra_pb
);
4955 avio_wb32(mfra_pb
, 0); /* size placeholder */
4956 ffio_wfourcc(mfra_pb
, "mfra");
4957 /* An empty mfra atom is enough to indicate to the publishing point that
4958 * the stream has ended. */
4959 if (mov
->flags
& FF_MOV_FLAG_ISML
)
4962 for (i
= 0; i
< mov
->nb_streams
; i
++) {
4963 MOVTrack
*track
= &mov
->tracks
[i
];
4964 if (track
->nb_frag_info
)
4965 mov_write_tfra_tag(mfra_pb
, track
);
4968 avio_wb32(mfra_pb
, 16);
4969 ffio_wfourcc(mfra_pb
, "mfro");
4970 avio_wb32(mfra_pb
, 0); /* version + flags */
4971 avio_wb32(mfra_pb
, avio_tell(mfra_pb
) + 4);
4975 sz
= update_size(mfra_pb
, 0);
4976 ret
= avio_get_dyn_buf(mfra_pb
, &buf
);
4977 avio_write(pb
, buf
, ret
);
4978 ffio_free_dyn_buf(&mfra_pb
);
4983 static int mov_write_mdat_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
4985 avio_wb32(pb
, 8); // placeholder for extended size field (64 bit)
4986 ffio_wfourcc(pb
, mov
->mode
== MODE_MOV
? "wide" : "free");
4988 mov
->mdat_pos
= avio_tell(pb
);
4989 avio_wb32(pb
, 0); /* size placeholder*/
4990 ffio_wfourcc(pb
, "mdat");
4994 static void mov_write_ftyp_tag_internal(AVIOContext
*pb
, AVFormatContext
*s
,
4995 int has_h264
, int has_video
, int write_minor
)
4997 MOVMuxContext
*mov
= s
->priv_data
;
5000 if (mov
->major_brand
&& strlen(mov
->major_brand
) >= 4)
5001 ffio_wfourcc(pb
, mov
->major_brand
);
5002 else if (mov
->mode
== MODE_3GP
) {
5003 ffio_wfourcc(pb
, has_h264
? "3gp6" : "3gp4");
5004 minor
= has_h264
? 0x100 : 0x200;
5005 } else if (mov
->mode
& MODE_3G2
) {
5006 ffio_wfourcc(pb
, has_h264
? "3g2b" : "3g2a");
5007 minor
= has_h264
? 0x20000 : 0x10000;
5008 } else if (mov
->mode
== MODE_PSP
)
5009 ffio_wfourcc(pb
, "MSNV");
5010 else if (mov
->mode
== MODE_MP4
&& mov
->flags
& FF_MOV_FLAG_FRAGMENT
&&
5011 mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
)
5012 ffio_wfourcc(pb
, "iso6"); // Required when using signed CTS offsets in trun boxes
5013 else if (mov
->mode
== MODE_MP4
&& mov
->flags
& FF_MOV_FLAG_DEFAULT_BASE_MOOF
)
5014 ffio_wfourcc(pb
, "iso5"); // Required when using default-base-is-moof
5015 else if (mov
->mode
== MODE_MP4
&& mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
)
5016 ffio_wfourcc(pb
, "iso4");
5017 else if (mov
->mode
== MODE_MP4
)
5018 ffio_wfourcc(pb
, "isom");
5019 else if (mov
->mode
== MODE_IPOD
)
5020 ffio_wfourcc(pb
, has_video
? "M4V ":"M4A ");
5021 else if (mov
->mode
== MODE_ISM
)
5022 ffio_wfourcc(pb
, "isml");
5023 else if (mov
->mode
== MODE_F4V
)
5024 ffio_wfourcc(pb
, "f4v ");
5026 ffio_wfourcc(pb
, "qt ");
5029 avio_wb32(pb
, minor
);
5032 static int mov_write_ftyp_tag(AVIOContext
*pb
, AVFormatContext
*s
)
5034 MOVMuxContext
*mov
= s
->priv_data
;
5035 int64_t pos
= avio_tell(pb
);
5036 int has_h264
= 0, has_av1
= 0, has_video
= 0, has_dolby
= 0;
5039 for (i
= 0; i
< s
->nb_streams
; i
++) {
5040 AVStream
*st
= s
->streams
[i
];
5041 if (is_cover_image(st
))
5043 if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
)
5045 if (st
->codecpar
->codec_id
== AV_CODEC_ID_H264
)
5047 if (st
->codecpar
->codec_id
== AV_CODEC_ID_AV1
)
5049 if (st
->codecpar
->codec_id
== AV_CODEC_ID_AC3
||
5050 st
->codecpar
->codec_id
== AV_CODEC_ID_EAC3
||
5051 st
->codecpar
->codec_id
== AV_CODEC_ID_TRUEHD
||
5052 av_stream_get_side_data(st
, AV_PKT_DATA_DOVI_CONF
, NULL
))
5056 avio_wb32(pb
, 0); /* size */
5057 ffio_wfourcc(pb
, "ftyp");
5059 // Write major brand
5060 mov_write_ftyp_tag_internal(pb
, s
, has_h264
, has_video
, 1);
5061 // Write the major brand as the first compatible brand as well
5062 mov_write_ftyp_tag_internal(pb
, s
, has_h264
, has_video
, 0);
5064 // Write compatible brands, ensuring that we don't write the major brand as a
5065 // compatible brand a second time.
5066 if (mov
->mode
== MODE_ISM
) {
5067 ffio_wfourcc(pb
, "piff");
5068 } else if (mov
->mode
!= MODE_MOV
) {
5069 // We add tfdt atoms when fragmenting, signal this with the iso6 compatible
5070 // brand, if not already the major brand. This is compatible with users that
5071 // don't understand tfdt.
5072 if (mov
->mode
== MODE_MP4
) {
5073 if (mov
->flags
& FF_MOV_FLAG_CMAF
)
5074 ffio_wfourcc(pb
, "cmfc");
5075 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
&& !(mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
))
5076 ffio_wfourcc(pb
, "iso6");
5078 ffio_wfourcc(pb
, "av01");
5080 ffio_wfourcc(pb
, "dby1");
5082 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
)
5083 ffio_wfourcc(pb
, "iso6");
5084 if (mov
->flags
& FF_MOV_FLAG_DEFAULT_BASE_MOOF
)
5085 ffio_wfourcc(pb
, "iso5");
5086 else if (mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
)
5087 ffio_wfourcc(pb
, "iso4");
5089 // Brands prior to iso5 can't be signaled when using default-base-is-moof
5090 if (!(mov
->flags
& FF_MOV_FLAG_DEFAULT_BASE_MOOF
)) {
5091 // write isom for mp4 only if it it's not the major brand already.
5092 if (mov
->mode
!= MODE_MP4
|| mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
)
5093 ffio_wfourcc(pb
, "isom");
5094 ffio_wfourcc(pb
, "iso2");
5096 ffio_wfourcc(pb
, "avc1");
5100 if (mov
->mode
== MODE_MP4
)
5101 ffio_wfourcc(pb
, "mp41");
5103 if (mov
->flags
& FF_MOV_FLAG_DASH
&& mov
->flags
& FF_MOV_FLAG_GLOBAL_SIDX
)
5104 ffio_wfourcc(pb
, "dash");
5106 return update_size(pb
, pos
);
5109 static int mov_write_uuidprof_tag(AVIOContext
*pb
, AVFormatContext
*s
)
5111 AVStream
*video_st
= s
->streams
[0];
5112 AVCodecParameters
*video_par
= s
->streams
[0]->codecpar
;
5113 AVCodecParameters
*audio_par
= s
->streams
[1]->codecpar
;
5114 int audio_rate
= audio_par
->sample_rate
;
5115 int64_t frame_rate
= video_st
->avg_frame_rate
.den
?
5116 (video_st
->avg_frame_rate
.num
* 0x10000LL
) / video_st
->avg_frame_rate
.den
:
5118 int audio_kbitrate
= audio_par
->bit_rate
/ 1000;
5119 int video_kbitrate
= FFMIN(video_par
->bit_rate
/ 1000, 800 - audio_kbitrate
);
5121 if (frame_rate
< 0 || frame_rate
> INT32_MAX
) {
5122 av_log(s
, AV_LOG_ERROR
, "Frame rate %f outside supported range\n", frame_rate
/ (double)0x10000);
5123 return AVERROR(EINVAL
);
5126 avio_wb32(pb
, 0x94); /* size */
5127 ffio_wfourcc(pb
, "uuid");
5128 ffio_wfourcc(pb
, "PROF");
5130 avio_wb32(pb
, 0x21d24fce); /* 96 bit UUID */
5131 avio_wb32(pb
, 0xbb88695c);
5132 avio_wb32(pb
, 0xfac9c740);
5134 avio_wb32(pb
, 0x0); /* ? */
5135 avio_wb32(pb
, 0x3); /* 3 sections ? */
5137 avio_wb32(pb
, 0x14); /* size */
5138 ffio_wfourcc(pb
, "FPRF");
5139 avio_wb32(pb
, 0x0); /* ? */
5140 avio_wb32(pb
, 0x0); /* ? */
5141 avio_wb32(pb
, 0x0); /* ? */
5143 avio_wb32(pb
, 0x2c); /* size */
5144 ffio_wfourcc(pb
, "APRF"); /* audio */
5146 avio_wb32(pb
, 0x2); /* TrackID */
5147 ffio_wfourcc(pb
, "mp4a");
5148 avio_wb32(pb
, 0x20f);
5150 avio_wb32(pb
, audio_kbitrate
);
5151 avio_wb32(pb
, audio_kbitrate
);
5152 avio_wb32(pb
, audio_rate
);
5153 avio_wb32(pb
, audio_par
->channels
);
5155 avio_wb32(pb
, 0x34); /* size */
5156 ffio_wfourcc(pb
, "VPRF"); /* video */
5158 avio_wb32(pb
, 0x1); /* TrackID */
5159 if (video_par
->codec_id
== AV_CODEC_ID_H264
) {
5160 ffio_wfourcc(pb
, "avc1");
5161 avio_wb16(pb
, 0x014D);
5162 avio_wb16(pb
, 0x0015);
5164 ffio_wfourcc(pb
, "mp4v");
5165 avio_wb16(pb
, 0x0000);
5166 avio_wb16(pb
, 0x0103);
5169 avio_wb32(pb
, video_kbitrate
);
5170 avio_wb32(pb
, video_kbitrate
);
5171 avio_wb32(pb
, frame_rate
);
5172 avio_wb32(pb
, frame_rate
);
5173 avio_wb16(pb
, video_par
->width
);
5174 avio_wb16(pb
, video_par
->height
);
5175 avio_wb32(pb
, 0x010001); /* ? */
5180 static int mov_write_identification(AVIOContext
*pb
, AVFormatContext
*s
)
5182 MOVMuxContext
*mov
= s
->priv_data
;
5185 mov_write_ftyp_tag(pb
,s
);
5186 if (mov
->mode
== MODE_PSP
) {
5187 int video_streams_nb
= 0, audio_streams_nb
= 0, other_streams_nb
= 0;
5188 for (i
= 0; i
< s
->nb_streams
; i
++) {
5189 AVStream
*st
= s
->streams
[i
];
5190 if (is_cover_image(st
))
5192 if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
)
5194 else if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_AUDIO
)
5200 if (video_streams_nb
!= 1 || audio_streams_nb
!= 1 || other_streams_nb
) {
5201 av_log(s
, AV_LOG_ERROR
, "PSP mode need one video and one audio stream\n");
5202 return AVERROR(EINVAL
);
5204 return mov_write_uuidprof_tag(pb
, s
);
5209 static int mov_parse_mpeg2_frame(AVPacket
*pkt
, uint32_t *flags
)
5212 int i
, closed_gop
= 0;
5214 for (i
= 0; i
< pkt
->size
- 4; i
++) {
5215 c
= (c
<< 8) + pkt
->data
[i
];
5216 if (c
== 0x1b8) { // gop
5217 closed_gop
= pkt
->data
[i
+ 4] >> 6 & 0x01;
5218 } else if (c
== 0x100) { // pic
5219 int temp_ref
= (pkt
->data
[i
+ 1] << 2) | (pkt
->data
[i
+ 2] >> 6);
5220 if (!temp_ref
|| closed_gop
) // I picture is not reordered
5221 *flags
= MOV_SYNC_SAMPLE
;
5223 *flags
= MOV_PARTIAL_SYNC_SAMPLE
;
5230 static void mov_parse_vc1_frame(AVPacket
*pkt
, MOVTrack
*trk
)
5232 const uint8_t *start
, *next
, *end
= pkt
->data
+ pkt
->size
;
5233 int seq
= 0, entry
= 0;
5234 int key
= pkt
->flags
& AV_PKT_FLAG_KEY
;
5235 start
= find_next_marker(pkt
->data
, end
);
5236 for (next
= start
; next
< end
; start
= next
) {
5237 next
= find_next_marker(start
+ 4, end
);
5238 switch (AV_RB32(start
)) {
5239 case VC1_CODE_SEQHDR
:
5242 case VC1_CODE_ENTRYPOINT
:
5245 case VC1_CODE_SLICE
:
5246 trk
->vc1_info
.slices
= 1;
5250 if (!trk
->entry
&& trk
->vc1_info
.first_packet_seen
)
5251 trk
->vc1_info
.first_frag_written
= 1;
5252 if (!trk
->entry
&& !trk
->vc1_info
.first_frag_written
) {
5253 /* First packet in first fragment */
5254 trk
->vc1_info
.first_packet_seq
= seq
;
5255 trk
->vc1_info
.first_packet_entry
= entry
;
5256 trk
->vc1_info
.first_packet_seen
= 1;
5257 } else if ((seq
&& !trk
->vc1_info
.packet_seq
) ||
5258 (entry
&& !trk
->vc1_info
.packet_entry
)) {
5260 for (i
= 0; i
< trk
->entry
; i
++)
5261 trk
->cluster
[i
].flags
&= ~MOV_SYNC_SAMPLE
;
5262 trk
->has_keyframes
= 0;
5264 trk
->vc1_info
.packet_seq
= 1;
5266 trk
->vc1_info
.packet_entry
= 1;
5267 if (!trk
->vc1_info
.first_frag_written
) {
5268 /* First fragment */
5269 if ((!seq
|| trk
->vc1_info
.first_packet_seq
) &&
5270 (!entry
|| trk
->vc1_info
.first_packet_entry
)) {
5271 /* First packet had the same headers as this one, readd the
5272 * sync sample flag. */
5273 trk
->cluster
[0].flags
|= MOV_SYNC_SAMPLE
;
5274 trk
->has_keyframes
= 1;
5278 if (trk
->vc1_info
.packet_seq
&& trk
->vc1_info
.packet_entry
)
5280 else if (trk
->vc1_info
.packet_seq
)
5282 else if (trk
->vc1_info
.packet_entry
)
5285 trk
->cluster
[trk
->entry
].flags
|= MOV_SYNC_SAMPLE
;
5286 trk
->has_keyframes
++;
5290 static void mov_parse_truehd_frame(AVPacket
*pkt
, MOVTrack
*trk
)
5297 length
= (AV_RB16(pkt
->data
) & 0xFFF) * 2;
5298 if (length
< 8 || length
> pkt
->size
)
5301 if (AV_RB32(pkt
->data
+ 4) == 0xF8726FBA) {
5302 trk
->cluster
[trk
->entry
].flags
|= MOV_SYNC_SAMPLE
;
5303 trk
->has_keyframes
++;
5309 static int mov_flush_fragment_interleaving(AVFormatContext
*s
, MOVTrack
*track
)
5311 MOVMuxContext
*mov
= s
->priv_data
;
5316 if (!track
->mdat_buf
)
5318 if (!mov
->mdat_buf
) {
5319 if ((ret
= avio_open_dyn_buf(&mov
->mdat_buf
)) < 0)
5322 buf_size
= avio_get_dyn_buf(track
->mdat_buf
, &buf
);
5324 offset
= avio_tell(mov
->mdat_buf
);
5325 avio_write(mov
->mdat_buf
, buf
, buf_size
);
5326 ffio_free_dyn_buf(&track
->mdat_buf
);
5328 for (i
= track
->entries_flushed
; i
< track
->entry
; i
++)
5329 track
->cluster
[i
].pos
+= offset
;
5330 track
->entries_flushed
= track
->entry
;
5334 static int mov_write_squashed_packet(AVFormatContext
*s
, MOVTrack
*track
)
5336 MOVMuxContext
*mov
= s
->priv_data
;
5337 AVPacket
*squashed_packet
= mov
->pkt
;
5338 int ret
= AVERROR_BUG
;
5340 switch (track
->st
->codecpar
->codec_id
) {
5341 case AV_CODEC_ID_TTML
: {
5342 int had_packets
= !!track
->squashed_packet_queue
.head
;
5344 if ((ret
= ff_mov_generate_squashed_ttml_packet(s
, track
, squashed_packet
)) < 0) {
5348 // We have generated a padding packet (no actual input packets in
5349 // queue) and its duration is zero. Skipping writing it.
5350 if (!had_packets
&& squashed_packet
->duration
== 0) {
5354 track
->end_reliable
= 1;
5358 ret
= AVERROR(EINVAL
);
5362 squashed_packet
->stream_index
= track
->st
->index
;
5364 ret
= mov_write_single_packet(s
, squashed_packet
);
5367 av_packet_unref(squashed_packet
);
5372 static int mov_write_squashed_packets(AVFormatContext
*s
)
5374 MOVMuxContext
*mov
= s
->priv_data
;
5376 for (int i
= 0; i
< s
->nb_streams
; i
++) {
5377 MOVTrack
*track
= &mov
->tracks
[i
];
5378 int ret
= AVERROR_BUG
;
5380 if (track
->squash_fragment_samples_to_one
&& !track
->entry
) {
5381 if ((ret
= mov_write_squashed_packet(s
, track
)) < 0) {
5382 av_log(s
, AV_LOG_ERROR
,
5383 "Failed to write squashed packet for %s stream with "
5384 "index %d and track id %d. Error: %s\n",
5385 avcodec_get_name(track
->st
->codecpar
->codec_id
),
5386 track
->st
->index
, track
->track_id
,
5396 static int mov_flush_fragment(AVFormatContext
*s
, int force
)
5398 MOVMuxContext
*mov
= s
->priv_data
;
5399 int i
, first_track
= -1;
5400 int64_t mdat_size
= 0;
5402 int has_video
= 0, starts_with_key
= 0, first_video_track
= 1;
5404 if (!(mov
->flags
& FF_MOV_FLAG_FRAGMENT
))
5407 // Check if we have any tracks that require squashing.
5408 // In that case, we'll have to write the packet here.
5409 if ((ret
= mov_write_squashed_packets(s
)) < 0)
5412 // Try to fill in the duration of the last packet in each stream
5413 // from queued packets in the interleave queues. If the flushing
5414 // of fragments was triggered automatically by an AVPacket, we
5415 // already have reliable info for the end of that track, but other
5416 // tracks may need to be filled in.
5417 for (i
= 0; i
< s
->nb_streams
; i
++) {
5418 MOVTrack
*track
= &mov
->tracks
[i
];
5419 if (!track
->end_reliable
) {
5420 const AVPacket
*pkt
= ff_interleaved_peek(s
, i
);
5422 int64_t offset
, dts
, pts
;
5423 ff_get_muxer_ts_offset(s
, i
, &offset
);
5424 pts
= pkt
->pts
+ offset
;
5425 dts
= pkt
->dts
+ offset
;
5426 if (track
->dts_shift
!= AV_NOPTS_VALUE
)
5427 dts
+= track
->dts_shift
;
5428 track
->track_duration
= dts
- track
->start_dts
;
5429 if (pts
!= AV_NOPTS_VALUE
)
5430 track
->end_pts
= pts
;
5432 track
->end_pts
= dts
;
5437 for (i
= 0; i
< mov
->nb_streams
; i
++) {
5438 MOVTrack
*track
= &mov
->tracks
[i
];
5439 if (track
->entry
<= 1)
5441 // Sample durations are calculated as the diff of dts values,
5442 // but for the last sample in a fragment, we don't know the dts
5443 // of the first sample in the next fragment, so we have to rely
5444 // on what was set as duration in the AVPacket. Not all callers
5445 // set this though, so we might want to replace it with an
5446 // estimate if it currently is zero.
5447 if (get_cluster_duration(track
, track
->entry
- 1) != 0)
5449 // Use the duration (i.e. dts diff) of the second last sample for
5450 // the last one. This is a wild guess (and fatal if it turns out
5451 // to be too long), but probably the best we can do - having a zero
5452 // duration is bad as well.
5453 track
->track_duration
+= get_cluster_duration(track
, track
->entry
- 2);
5454 track
->end_pts
+= get_cluster_duration(track
, track
->entry
- 2);
5455 if (!mov
->missing_duration_warned
) {
5456 av_log(s
, AV_LOG_WARNING
,
5457 "Estimating the duration of the last packet in a "
5458 "fragment, consider setting the duration field in "
5459 "AVPacket instead.\n");
5460 mov
->missing_duration_warned
= 1;
5464 if (!mov
->moov_written
) {
5465 int64_t pos
= avio_tell(s
->pb
);
5467 int buf_size
, moov_size
;
5469 for (i
= 0; i
< mov
->nb_streams
; i
++)
5470 if (!mov
->tracks
[i
].entry
&& !is_cover_image(mov
->tracks
[i
].st
))
5472 /* Don't write the initial moov unless all tracks have data */
5473 if (i
< mov
->nb_streams
&& !force
)
5476 moov_size
= get_moov_size(s
);
5477 for (i
= 0; i
< mov
->nb_streams
; i
++)
5478 mov
->tracks
[i
].data_offset
= pos
+ moov_size
+ 8;
5480 avio_write_marker(s
->pb
, AV_NOPTS_VALUE
, AVIO_DATA_MARKER_HEADER
);
5481 if (mov
->flags
& FF_MOV_FLAG_DELAY_MOOV
)
5482 mov_write_identification(s
->pb
, s
);
5483 if ((ret
= mov_write_moov_tag(s
->pb
, mov
, s
)) < 0)
5486 if (mov
->flags
& FF_MOV_FLAG_DELAY_MOOV
) {
5487 if (mov
->flags
& FF_MOV_FLAG_GLOBAL_SIDX
)
5488 mov
->reserved_header_pos
= avio_tell(s
->pb
);
5489 avio_write_marker(s
->pb
, AV_NOPTS_VALUE
, AVIO_DATA_MARKER_FLUSH_POINT
);
5490 mov
->moov_written
= 1;
5494 buf_size
= avio_get_dyn_buf(mov
->mdat_buf
, &buf
);
5495 avio_wb32(s
->pb
, buf_size
+ 8);
5496 ffio_wfourcc(s
->pb
, "mdat");
5497 avio_write(s
->pb
, buf
, buf_size
);
5498 ffio_free_dyn_buf(&mov
->mdat_buf
);
5500 if (mov
->flags
& FF_MOV_FLAG_GLOBAL_SIDX
)
5501 mov
->reserved_header_pos
= avio_tell(s
->pb
);
5503 mov
->moov_written
= 1;
5505 for (i
= 0; i
< mov
->nb_streams
; i
++) {
5506 mov
->tracks
[i
].entry
= 0;
5507 mov
->tracks
[i
].end_reliable
= 0;
5509 avio_write_marker(s
->pb
, AV_NOPTS_VALUE
, AVIO_DATA_MARKER_FLUSH_POINT
);
5513 if (mov
->frag_interleave
) {
5514 for (i
= 0; i
< mov
->nb_streams
; i
++) {
5515 MOVTrack
*track
= &mov
->tracks
[i
];
5517 if ((ret
= mov_flush_fragment_interleaving(s
, track
)) < 0)
5523 mdat_size
= avio_tell(mov
->mdat_buf
);
5526 for (i
= 0; i
< mov
->nb_streams
; i
++) {
5527 MOVTrack
*track
= &mov
->tracks
[i
];
5528 if (mov
->flags
& FF_MOV_FLAG_SEPARATE_MOOF
|| mov
->frag_interleave
)
5529 track
->data_offset
= 0;
5531 track
->data_offset
= mdat_size
;
5532 if (track
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
5534 if (first_video_track
) {
5536 starts_with_key
= track
->cluster
[0].flags
& MOV_SYNC_SAMPLE
;
5537 first_video_track
= 0;
5542 if (track
->mdat_buf
)
5543 mdat_size
+= avio_tell(track
->mdat_buf
);
5544 if (first_track
< 0)
5551 avio_write_marker(s
->pb
,
5552 av_rescale(mov
->tracks
[first_track
].cluster
[0].dts
, AV_TIME_BASE
, mov
->tracks
[first_track
].timescale
),
5553 (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
);
5555 for (i
= 0; i
< mov
->nb_streams
; i
++) {
5556 MOVTrack
*track
= &mov
->tracks
[i
];
5557 int buf_size
, write_moof
= 1, moof_tracks
= -1;
5560 if (mov
->flags
& FF_MOV_FLAG_SEPARATE_MOOF
) {
5563 mdat_size
= avio_tell(track
->mdat_buf
);
5566 write_moof
= i
== first_track
;
5570 avio_write_marker(s
->pb
, AV_NOPTS_VALUE
, AVIO_DATA_MARKER_FLUSH_POINT
);
5572 mov_write_moof_tag(s
->pb
, mov
, moof_tracks
, mdat_size
);
5575 avio_wb32(s
->pb
, mdat_size
+ 8);
5576 ffio_wfourcc(s
->pb
, "mdat");
5580 track
->entries_flushed
= 0;
5581 track
->end_reliable
= 0;
5582 if (!mov
->frag_interleave
) {
5583 if (!track
->mdat_buf
)
5585 buf_size
= avio_close_dyn_buf(track
->mdat_buf
, &buf
);
5586 track
->mdat_buf
= NULL
;
5590 buf_size
= avio_close_dyn_buf(mov
->mdat_buf
, &buf
);
5591 mov
->mdat_buf
= NULL
;
5594 avio_write(s
->pb
, buf
, buf_size
);
5600 avio_write_marker(s
->pb
, AV_NOPTS_VALUE
, AVIO_DATA_MARKER_FLUSH_POINT
);
5604 static int mov_auto_flush_fragment(AVFormatContext
*s
, int force
)
5606 MOVMuxContext
*mov
= s
->priv_data
;
5607 int had_moov
= mov
->moov_written
;
5608 int ret
= mov_flush_fragment(s
, force
);
5611 // If using delay_moov, the first flush only wrote the moov,
5612 // not the actual moof+mdat pair, thus flush once again.
5613 if (!had_moov
&& mov
->flags
& FF_MOV_FLAG_DELAY_MOOV
)
5614 ret
= mov_flush_fragment(s
, force
);
5618 static int check_pkt(AVFormatContext
*s
, AVPacket
*pkt
)
5620 MOVMuxContext
*mov
= s
->priv_data
;
5621 MOVTrack
*trk
= &mov
->tracks
[pkt
->stream_index
];
5626 ref
= trk
->cluster
[trk
->entry
- 1].dts
;
5627 } else if ( trk
->start_dts
!= AV_NOPTS_VALUE
5628 && !trk
->frag_discont
) {
5629 ref
= trk
->start_dts
+ trk
->track_duration
;
5631 ref
= pkt
->dts
; // Skip tests for the first packet
5633 if (trk
->dts_shift
!= AV_NOPTS_VALUE
) {
5634 /* With negative CTS offsets we have set an offset to the DTS,
5635 * reverse this for the check. */
5636 ref
-= trk
->dts_shift
;
5639 duration
= pkt
->dts
- ref
;
5640 if (pkt
->dts
< ref
|| duration
>= INT_MAX
) {
5641 av_log(s
, AV_LOG_ERROR
, "Application provided duration: %"PRId64
" / timestamp: %"PRId64
" is out of range for mov/mp4 format\n",
5646 pkt
->pts
= AV_NOPTS_VALUE
;
5649 if (pkt
->duration
< 0 || pkt
->duration
> INT_MAX
) {
5650 av_log(s
, AV_LOG_ERROR
, "Application provided duration: %"PRId64
" is invalid\n", pkt
->duration
);
5651 return AVERROR(EINVAL
);
5656 int ff_mov_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
5658 MOVMuxContext
*mov
= s
->priv_data
;
5659 AVIOContext
*pb
= s
->pb
;
5660 MOVTrack
*trk
= &mov
->tracks
[pkt
->stream_index
];
5661 AVCodecParameters
*par
= trk
->par
;
5662 AVProducerReferenceTime
*prft
;
5663 unsigned int samples_in_chunk
= 0;
5664 int size
= pkt
->size
, ret
= 0, offset
= 0;
5666 uint8_t *reformatted_data
= NULL
;
5668 ret
= check_pkt(s
, pkt
);
5672 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
) {
5674 if (mov
->moov_written
|| mov
->flags
& FF_MOV_FLAG_EMPTY_MOOV
) {
5675 if (mov
->frag_interleave
&& mov
->fragments
> 0) {
5676 if (trk
->entry
- trk
->entries_flushed
>= mov
->frag_interleave
) {
5677 if ((ret
= mov_flush_fragment_interleaving(s
, trk
)) < 0)
5682 if (!trk
->mdat_buf
) {
5683 if ((ret
= avio_open_dyn_buf(&trk
->mdat_buf
)) < 0)
5688 if (!mov
->mdat_buf
) {
5689 if ((ret
= avio_open_dyn_buf(&mov
->mdat_buf
)) < 0)
5696 if (par
->codec_id
== AV_CODEC_ID_AMR_NB
) {
5697 /* We must find out how many AMR blocks there are in one packet */
5698 static const uint16_t packed_size
[16] =
5699 {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
5702 while (len
< size
&& samples_in_chunk
< 100) {
5703 len
+= packed_size
[(pkt
->data
[len
] >> 3) & 0x0F];
5706 if (samples_in_chunk
> 1) {
5707 av_log(s
, AV_LOG_ERROR
, "fatal error, input is not a single packet, implement a AVParser for it\n");
5710 } else if (par
->codec_id
== AV_CODEC_ID_ADPCM_MS
||
5711 par
->codec_id
== AV_CODEC_ID_ADPCM_IMA_WAV
) {
5712 samples_in_chunk
= trk
->par
->frame_size
;
5713 } else if (trk
->sample_size
)
5714 samples_in_chunk
= size
/ trk
->sample_size
;
5716 samples_in_chunk
= 1;
5718 if (samples_in_chunk
< 1) {
5719 av_log(s
, AV_LOG_ERROR
, "fatal error, input packet contains no samples\n");
5720 return AVERROR_PATCHWELCOME
;
5723 /* copy extradata if it exists */
5724 if (trk
->vos_len
== 0 && par
->extradata_size
> 0 &&
5725 !TAG_IS_AVCI(trk
->tag
) &&
5726 (par
->codec_id
!= AV_CODEC_ID_DNXHD
)) {
5727 trk
->vos_len
= par
->extradata_size
;
5728 trk
->vos_data
= av_malloc(trk
->vos_len
+ AV_INPUT_BUFFER_PADDING_SIZE
);
5729 if (!trk
->vos_data
) {
5730 ret
= AVERROR(ENOMEM
);
5733 memcpy(trk
->vos_data
, par
->extradata
, trk
->vos_len
);
5734 memset(trk
->vos_data
+ trk
->vos_len
, 0, AV_INPUT_BUFFER_PADDING_SIZE
);
5737 if ((par
->codec_id
== AV_CODEC_ID_DNXHD
||
5738 par
->codec_id
== AV_CODEC_ID_H264
||
5739 par
->codec_id
== AV_CODEC_ID_HEVC
||
5740 par
->codec_id
== AV_CODEC_ID_TRUEHD
||
5741 par
->codec_id
== AV_CODEC_ID_AC3
) && !trk
->vos_len
&&
5742 !TAG_IS_AVCI(trk
->tag
)) {
5743 /* copy frame to create needed atoms */
5744 trk
->vos_len
= size
;
5745 trk
->vos_data
= av_malloc(size
+ AV_INPUT_BUFFER_PADDING_SIZE
);
5746 if (!trk
->vos_data
) {
5747 ret
= AVERROR(ENOMEM
);
5750 memcpy(trk
->vos_data
, pkt
->data
, size
);
5751 memset(trk
->vos_data
+ size
, 0, AV_INPUT_BUFFER_PADDING_SIZE
);
5754 if (par
->codec_id
== AV_CODEC_ID_AAC
&& pkt
->size
> 2 &&
5755 (AV_RB16(pkt
->data
) & 0xfff0) == 0xfff0) {
5756 if (!s
->streams
[pkt
->stream_index
]->nb_frames
) {
5757 av_log(s
, AV_LOG_ERROR
, "Malformed AAC bitstream detected: "
5758 "use the audio bitstream filter 'aac_adtstoasc' to fix it "
5759 "('-bsf:a aac_adtstoasc' option with ffmpeg)\n");
5762 av_log(s
, AV_LOG_WARNING
, "aac bitstream error\n");
5764 if (par
->codec_id
== AV_CODEC_ID_H264
&& trk
->vos_len
> 0 && *(uint8_t *)trk
->vos_data
!= 1 && !TAG_IS_AVCI(trk
->tag
)) {
5765 /* from x264 or from bytestream H.264 */
5766 /* NAL reformatting needed */
5767 if (trk
->hint_track
>= 0 && trk
->hint_track
< mov
->nb_streams
) {
5768 ret
= ff_avc_parse_nal_units_buf(pkt
->data
, &reformatted_data
,
5772 avio_write(pb
, reformatted_data
, size
);
5774 if (trk
->cenc
.aes_ctr
) {
5775 size
= ff_mov_cenc_avc_parse_nal_units(&trk
->cenc
, pb
, pkt
->data
, size
);
5781 size
= ff_avc_parse_nal_units(pb
, pkt
->data
, pkt
->size
);
5784 } else if (par
->codec_id
== AV_CODEC_ID_HEVC
&& trk
->vos_len
> 6 &&
5785 (AV_RB24(trk
->vos_data
) == 1 || AV_RB32(trk
->vos_data
) == 1)) {
5786 /* extradata is Annex B, assume the bitstream is too and convert it */
5787 if (trk
->hint_track
>= 0 && trk
->hint_track
< mov
->nb_streams
) {
5788 ret
= ff_hevc_annexb2mp4_buf(pkt
->data
, &reformatted_data
,
5792 avio_write(pb
, reformatted_data
, size
);
5794 if (trk
->cenc
.aes_ctr
) {
5795 size
= ff_mov_cenc_avc_parse_nal_units(&trk
->cenc
, pb
, pkt
->data
, size
);
5801 size
= ff_hevc_annexb2mp4(pb
, pkt
->data
, pkt
->size
, 0, NULL
);
5804 } else if (par
->codec_id
== AV_CODEC_ID_AV1
) {
5805 if (trk
->hint_track
>= 0 && trk
->hint_track
< mov
->nb_streams
) {
5806 ret
= ff_av1_filter_obus_buf(pkt
->data
, &reformatted_data
,
5810 avio_write(pb
, reformatted_data
, size
);
5812 size
= ff_av1_filter_obus(pb
, pkt
->data
, pkt
->size
);
5814 #if CONFIG_AC3_PARSER
5815 } else if (par
->codec_id
== AV_CODEC_ID_EAC3
) {
5816 size
= handle_eac3(mov
, pkt
, trk
);
5821 avio_write(pb
, pkt
->data
, size
);
5823 } else if (par
->codec_id
== AV_CODEC_ID_EIA_608
) {
5826 for (int i
= 0; i
< pkt
->size
; i
+= 3) {
5827 if (pkt
->data
[i
] == 0xFC) {
5831 avio_wb32(pb
, size
);
5832 ffio_wfourcc(pb
, "cdat");
5833 for (int i
= 0; i
< pkt
->size
; i
+= 3) {
5834 if (pkt
->data
[i
] == 0xFC) {
5835 avio_w8(pb
, pkt
->data
[i
+ 1]);
5836 avio_w8(pb
, pkt
->data
[i
+ 2]);
5840 if (trk
->cenc
.aes_ctr
) {
5841 if (par
->codec_id
== AV_CODEC_ID_H264
&& par
->extradata_size
> 4) {
5842 int nal_size_length
= (par
->extradata
[4] & 0x3) + 1;
5843 ret
= ff_mov_cenc_avc_write_nal_units(s
, &trk
->cenc
, nal_size_length
, pb
, pkt
->data
, size
);
5844 } else if(par
->codec_id
== AV_CODEC_ID_HEVC
&& par
->extradata_size
> 21) {
5845 int nal_size_length
= (par
->extradata
[21] & 0x3) + 1;
5846 ret
= ff_mov_cenc_avc_write_nal_units(s
, &trk
->cenc
, nal_size_length
, pb
, pkt
->data
, size
);
5848 ret
= ff_mov_cenc_write_packet(&trk
->cenc
, pb
, pkt
->data
, size
);
5855 avio_write(pb
, pkt
->data
, size
);
5859 if (trk
->entry
>= trk
->cluster_capacity
) {
5860 unsigned new_capacity
= trk
->entry
+ MOV_INDEX_CLUSTER_SIZE
;
5861 void *cluster
= av_realloc_array(trk
->cluster
, new_capacity
, sizeof(*trk
->cluster
));
5863 ret
= AVERROR(ENOMEM
);
5866 trk
->cluster
= cluster
;
5867 trk
->cluster_capacity
= new_capacity
;
5870 trk
->cluster
[trk
->entry
].pos
= avio_tell(pb
) - size
;
5871 trk
->cluster
[trk
->entry
].samples_in_chunk
= samples_in_chunk
;
5872 trk
->cluster
[trk
->entry
].chunkNum
= 0;
5873 trk
->cluster
[trk
->entry
].size
= size
;
5874 trk
->cluster
[trk
->entry
].entries
= samples_in_chunk
;
5875 trk
->cluster
[trk
->entry
].dts
= pkt
->dts
;
5876 trk
->cluster
[trk
->entry
].pts
= pkt
->pts
;
5877 if (!trk
->squash_fragment_samples_to_one
&&
5878 !trk
->entry
&& trk
->start_dts
!= AV_NOPTS_VALUE
) {
5879 if (!trk
->frag_discont
) {
5880 /* First packet of a new fragment. We already wrote the duration
5881 * of the last packet of the previous fragment based on track_duration,
5882 * which might not exactly match our dts. Therefore adjust the dts
5883 * of this packet to be what the previous packets duration implies. */
5884 trk
->cluster
[trk
->entry
].dts
= trk
->start_dts
+ trk
->track_duration
;
5885 /* We also may have written the pts and the corresponding duration
5886 * in sidx/tfrf/tfxd tags; make sure the sidx pts and duration match up with
5887 * the next fragment. This means the cts of the first sample must
5888 * be the same in all fragments, unless end_pts was updated by
5889 * the packet causing the fragment to be written. */
5890 if ((mov
->flags
& FF_MOV_FLAG_DASH
&&
5891 !(mov
->flags
& (FF_MOV_FLAG_GLOBAL_SIDX
| FF_MOV_FLAG_SKIP_SIDX
))) ||
5892 mov
->mode
== MODE_ISM
)
5893 pkt
->pts
= pkt
->dts
+ trk
->end_pts
- trk
->cluster
[trk
->entry
].dts
;
5895 /* New fragment, but discontinuous from previous fragments.
5896 * Pretend the duration sum of the earlier fragments is
5897 * pkt->dts - trk->start_dts. */
5898 trk
->end_pts
= AV_NOPTS_VALUE
;
5899 trk
->frag_discont
= 0;
5903 if (!trk
->entry
&& trk
->start_dts
== AV_NOPTS_VALUE
&& !mov
->use_editlist
&&
5904 s
->avoid_negative_ts
== AVFMT_AVOID_NEG_TS_MAKE_ZERO
) {
5905 /* Not using edit lists and shifting the first track to start from zero.
5906 * If the other streams start from a later timestamp, we won't be able
5907 * to signal the difference in starting time without an edit list.
5908 * Thus move the timestamp for this first sample to 0, increasing
5909 * its duration instead. */
5910 trk
->cluster
[trk
->entry
].dts
= trk
->start_dts
= 0;
5912 if (trk
->start_dts
== AV_NOPTS_VALUE
) {
5913 trk
->start_dts
= pkt
->dts
;
5914 if (trk
->frag_discont
) {
5915 if (mov
->use_editlist
) {
5916 /* Pretend the whole stream started at pts=0, with earlier fragments
5917 * already written. If the stream started at pts=0, the duration sum
5918 * of earlier fragments would have been pkt->pts. */
5919 trk
->start_dts
= pkt
->dts
- pkt
->pts
;
5921 /* Pretend the whole stream started at dts=0, with earlier fragments
5922 * already written, with a duration summing up to pkt->dts. */
5925 trk
->frag_discont
= 0;
5926 } else if (pkt
->dts
&& mov
->moov_written
)
5927 av_log(s
, AV_LOG_WARNING
,
5928 "Track %d starts with a nonzero dts %"PRId64
", while the moov "
5929 "already has been written. Set the delay_moov flag to handle "
5931 pkt
->stream_index
, pkt
->dts
);
5933 trk
->track_duration
= pkt
->dts
- trk
->start_dts
+ pkt
->duration
;
5934 trk
->last_sample_is_subtitle_end
= 0;
5936 if (pkt
->pts
== AV_NOPTS_VALUE
) {
5937 av_log(s
, AV_LOG_WARNING
, "pts has no value\n");
5938 pkt
->pts
= pkt
->dts
;
5940 if (pkt
->dts
!= pkt
->pts
)
5941 trk
->flags
|= MOV_TRACK_CTTS
;
5942 trk
->cluster
[trk
->entry
].cts
= pkt
->pts
- pkt
->dts
;
5943 trk
->cluster
[trk
->entry
].flags
= 0;
5944 if (trk
->start_cts
== AV_NOPTS_VALUE
)
5945 trk
->start_cts
= pkt
->pts
- pkt
->dts
;
5946 if (trk
->end_pts
== AV_NOPTS_VALUE
)
5947 trk
->end_pts
= trk
->cluster
[trk
->entry
].dts
+
5948 trk
->cluster
[trk
->entry
].cts
+ pkt
->duration
;
5950 trk
->end_pts
= FFMAX(trk
->end_pts
, trk
->cluster
[trk
->entry
].dts
+
5951 trk
->cluster
[trk
->entry
].cts
+
5954 if (par
->codec_id
== AV_CODEC_ID_VC1
) {
5955 mov_parse_vc1_frame(pkt
, trk
);
5956 } else if (par
->codec_id
== AV_CODEC_ID_TRUEHD
) {
5957 mov_parse_truehd_frame(pkt
, trk
);
5958 } else if (pkt
->flags
& AV_PKT_FLAG_KEY
) {
5959 if (mov
->mode
== MODE_MOV
&& par
->codec_id
== AV_CODEC_ID_MPEG2VIDEO
&&
5960 trk
->entry
> 0) { // force sync sample for the first key frame
5961 mov_parse_mpeg2_frame(pkt
, &trk
->cluster
[trk
->entry
].flags
);
5962 if (trk
->cluster
[trk
->entry
].flags
& MOV_PARTIAL_SYNC_SAMPLE
)
5963 trk
->flags
|= MOV_TRACK_STPS
;
5965 trk
->cluster
[trk
->entry
].flags
= MOV_SYNC_SAMPLE
;
5967 if (trk
->cluster
[trk
->entry
].flags
& MOV_SYNC_SAMPLE
)
5968 trk
->has_keyframes
++;
5970 if (pkt
->flags
& AV_PKT_FLAG_DISPOSABLE
) {
5971 trk
->cluster
[trk
->entry
].flags
|= MOV_DISPOSABLE_SAMPLE
;
5972 trk
->has_disposable
++;
5975 prft
= (AVProducerReferenceTime
*)av_packet_get_side_data(pkt
, AV_PKT_DATA_PRFT
, &prft_size
);
5976 if (prft
&& prft_size
== sizeof(AVProducerReferenceTime
))
5977 memcpy(&trk
->cluster
[trk
->entry
].prft
, prft
, prft_size
);
5979 memset(&trk
->cluster
[trk
->entry
].prft
, 0, sizeof(AVProducerReferenceTime
));
5982 trk
->sample_count
+= samples_in_chunk
;
5983 mov
->mdat_size
+= size
;
5985 if (trk
->hint_track
>= 0 && trk
->hint_track
< mov
->nb_streams
)
5986 ff_mov_add_hinted_packet(s
, pkt
, trk
->hint_track
, trk
->entry
,
5987 reformatted_data
? reformatted_data
+ offset
5993 if (pkt
->data
!= reformatted_data
)
5994 av_free(reformatted_data
);
5998 static int mov_write_single_packet(AVFormatContext
*s
, AVPacket
*pkt
)
6000 MOVMuxContext
*mov
= s
->priv_data
;
6001 MOVTrack
*trk
= &mov
->tracks
[pkt
->stream_index
];
6002 AVCodecParameters
*par
= trk
->par
;
6003 int64_t frag_duration
= 0;
6004 int size
= pkt
->size
;
6006 int ret
= check_pkt(s
, pkt
);
6010 if (mov
->flags
& FF_MOV_FLAG_FRAG_DISCONT
) {
6012 for (i
= 0; i
< s
->nb_streams
; i
++)
6013 mov
->tracks
[i
].frag_discont
= 1;
6014 mov
->flags
&= ~FF_MOV_FLAG_FRAG_DISCONT
;
6017 if (mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
) {
6018 if (trk
->dts_shift
== AV_NOPTS_VALUE
)
6019 trk
->dts_shift
= pkt
->pts
- pkt
->dts
;
6020 pkt
->dts
+= trk
->dts_shift
;
6023 if (trk
->par
->codec_id
== AV_CODEC_ID_MP4ALS
||
6024 trk
->par
->codec_id
== AV_CODEC_ID_AAC
||
6025 trk
->par
->codec_id
== AV_CODEC_ID_AV1
||
6026 trk
->par
->codec_id
== AV_CODEC_ID_FLAC
) {
6028 uint8_t *side
= av_packet_get_side_data(pkt
, AV_PKT_DATA_NEW_EXTRADATA
, &side_size
);
6029 if (side
&& side_size
> 0 && (side_size
!= par
->extradata_size
|| memcmp(side
, par
->extradata
, side_size
))) {
6030 void *newextra
= av_mallocz(side_size
+ AV_INPUT_BUFFER_PADDING_SIZE
);
6032 return AVERROR(ENOMEM
);
6033 av_free(par
->extradata
);
6034 par
->extradata
= newextra
;
6035 memcpy(par
->extradata
, side
, side_size
);
6036 par
->extradata_size
= side_size
;
6037 if (!pkt
->size
) // Flush packet
6038 mov
->need_rewrite_extradata
= 1;
6043 if (trk
->start_dts
== AV_NOPTS_VALUE
&& trk
->frag_discont
) {
6044 trk
->start_dts
= pkt
->dts
;
6045 if (pkt
->pts
!= AV_NOPTS_VALUE
)
6046 trk
->start_cts
= pkt
->pts
- pkt
->dts
;
6051 return 0; /* Discard 0 sized packets */
6054 if (trk
->entry
&& pkt
->stream_index
< s
->nb_streams
)
6055 frag_duration
= av_rescale_q(pkt
->dts
- trk
->cluster
[0].dts
,
6056 s
->streams
[pkt
->stream_index
]->time_base
,
6058 if ((mov
->max_fragment_duration
&&
6059 frag_duration
>= mov
->max_fragment_duration
) ||
6060 (mov
->max_fragment_size
&& mov
->mdat_size
+ size
>= mov
->max_fragment_size
) ||
6061 (mov
->flags
& FF_MOV_FLAG_FRAG_KEYFRAME
&&
6062 par
->codec_type
== AVMEDIA_TYPE_VIDEO
&&
6063 trk
->entry
&& pkt
->flags
& AV_PKT_FLAG_KEY
) ||
6064 (mov
->flags
& FF_MOV_FLAG_FRAG_EVERY_FRAME
)) {
6065 if (frag_duration
>= mov
->min_fragment_duration
) {
6067 // Set the duration of this track to line up with the next
6068 // sample in this track. This avoids relying on AVPacket
6069 // duration, but only helps for this particular track, not
6070 // for the other ones that are flushed at the same time.
6072 // If we have trk->entry == 0, no fragment will be written
6073 // for this track, and we can't adjust the track end here.
6074 trk
->track_duration
= pkt
->dts
- trk
->start_dts
;
6075 if (pkt
->pts
!= AV_NOPTS_VALUE
)
6076 trk
->end_pts
= pkt
->pts
;
6078 trk
->end_pts
= pkt
->dts
;
6079 trk
->end_reliable
= 1;
6081 mov_auto_flush_fragment(s
, 0);
6085 return ff_mov_write_packet(s
, pkt
);
6088 static int mov_write_subtitle_end_packet(AVFormatContext
*s
,
6091 MOVMuxContext
*mov
= s
->priv_data
;
6092 AVPacket
*end
= mov
->pkt
;
6093 uint8_t data
[2] = {0};
6096 end
->size
= sizeof(data
);
6101 end
->stream_index
= stream_index
;
6103 ret
= mov_write_single_packet(s
, end
);
6104 av_packet_unref(end
);
6109 static int mov_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
6111 MOVMuxContext
*mov
= s
->priv_data
;
6115 mov_flush_fragment(s
, 1);
6119 trk
= &mov
->tracks
[pkt
->stream_index
];
6121 if (is_cover_image(trk
->st
)) {
6124 if (trk
->st
->nb_frames
>= 1) {
6125 if (trk
->st
->nb_frames
== 1)
6126 av_log(s
, AV_LOG_WARNING
, "Got more than one picture in stream %d,"
6127 " ignoring.\n", pkt
->stream_index
);
6131 if ((ret
= av_packet_ref(trk
->cover_image
, pkt
)) < 0)
6139 return mov_write_single_packet(s
, pkt
); /* Passthrough. */
6142 * Subtitles require special handling.
6144 * 1) For full complaince, every track must have a sample at
6145 * dts == 0, which is rarely true for subtitles. So, as soon
6146 * as we see any packet with dts > 0, write an empty subtitle
6147 * at dts == 0 for any subtitle track with no samples in it.
6149 * 2) For each subtitle track, check if the current packet's
6150 * dts is past the duration of the last subtitle sample. If
6151 * so, we now need to write an end sample for that subtitle.
6153 * This must be done conditionally to allow for subtitles that
6154 * immediately replace each other, in which case an end sample
6155 * is not needed, and is, in fact, actively harmful.
6157 * 3) See mov_write_trailer for how the final end sample is
6160 for (i
= 0; i
< mov
->nb_streams
; i
++) {
6161 MOVTrack
*trk
= &mov
->tracks
[i
];
6164 if (trk
->par
->codec_id
== AV_CODEC_ID_MOV_TEXT
&&
6165 trk
->track_duration
< pkt
->dts
&&
6166 (trk
->entry
== 0 || !trk
->last_sample_is_subtitle_end
)) {
6167 ret
= mov_write_subtitle_end_packet(s
, i
, trk
->track_duration
);
6168 if (ret
< 0) return ret
;
6169 trk
->last_sample_is_subtitle_end
= 1;
6173 if (trk
->squash_fragment_samples_to_one
) {
6175 * If the track has to have its samples squashed into one sample,
6176 * we just take it into the track's queue.
6177 * This will then be utilized as the samples get written in either
6178 * mov_flush_fragment or when the mux is finalized in
6179 * mov_write_trailer.
6181 int ret
= AVERROR_BUG
;
6183 if (pkt
->pts
== AV_NOPTS_VALUE
) {
6184 av_log(s
, AV_LOG_ERROR
,
6185 "Packets without a valid presentation timestamp are "
6186 "not supported with packet squashing!\n");
6187 return AVERROR(EINVAL
);
6190 /* The following will reset pkt and is only allowed to be used
6191 * because we return immediately. afterwards. */
6192 if ((ret
= avpriv_packet_list_put(&trk
->squashed_packet_queue
,
6193 pkt
, NULL
, 0)) < 0) {
6201 if (trk
->mode
== MODE_MOV
&& trk
->par
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
6202 AVPacket
*opkt
= pkt
;
6203 int reshuffle_ret
, ret
;
6204 if (trk
->is_unaligned_qt_rgb
) {
6205 int64_t bpc
= trk
->par
->bits_per_coded_sample
!= 15 ? trk
->par
->bits_per_coded_sample
: 16;
6206 int expected_stride
= ((trk
->par
->width
* bpc
+ 15) >> 4)*2;
6207 reshuffle_ret
= ff_reshuffle_raw_rgb(s
, &pkt
, trk
->par
, expected_stride
);
6208 if (reshuffle_ret
< 0)
6209 return reshuffle_ret
;
6212 if (trk
->par
->format
== AV_PIX_FMT_PAL8
&& !trk
->pal_done
) {
6213 ret
= ff_get_packet_palette(s
, opkt
, reshuffle_ret
, trk
->palette
);
6218 } else if (trk
->par
->codec_id
== AV_CODEC_ID_RAWVIDEO
&&
6219 (trk
->par
->format
== AV_PIX_FMT_GRAY8
||
6220 trk
->par
->format
== AV_PIX_FMT_MONOBLACK
)) {
6221 for (i
= 0; i
< pkt
->size
; i
++)
6222 pkt
->data
[i
] = ~pkt
->data
[i
];
6224 if (reshuffle_ret
) {
6225 ret
= mov_write_single_packet(s
, pkt
);
6228 av_packet_free(&pkt
);
6233 return mov_write_single_packet(s
, pkt
);
6237 // QuickTime chapters involve an additional text track with the chapter names
6238 // as samples, and a tref pointing from the other tracks to the chapter one.
6239 static int mov_create_chapter_track(AVFormatContext
*s
, int tracknum
)
6243 MOVMuxContext
*mov
= s
->priv_data
;
6244 MOVTrack
*track
= &mov
->tracks
[tracknum
];
6245 AVPacket
*pkt
= mov
->pkt
;
6248 track
->mode
= mov
->mode
;
6249 track
->tag
= MKTAG('t','e','x','t');
6250 track
->timescale
= mov
->movie_timescale
;
6251 track
->par
= avcodec_parameters_alloc();
6253 return AVERROR(ENOMEM
);
6254 track
->par
->codec_type
= AVMEDIA_TYPE_SUBTITLE
;
6256 // These properties are required to make QT recognize the chapter track
6257 uint8_t chapter_properties
[43] = { 0, 0, 0, 0, 0, 0, 0, 1, };
6258 if (ff_alloc_extradata(track
->par
, sizeof(chapter_properties
)))
6259 return AVERROR(ENOMEM
);
6260 memcpy(track
->par
->extradata
, chapter_properties
, sizeof(chapter_properties
));
6262 if (avio_open_dyn_buf(&pb
) >= 0) {
6266 /* Stub header (usually for Quicktime chapter track) */
6268 avio_wb32(pb
, 0x01); // displayFlags
6269 avio_w8(pb
, 0x00); // horizontal justification
6270 avio_w8(pb
, 0x00); // vertical justification
6271 avio_w8(pb
, 0x00); // bgColourRed
6272 avio_w8(pb
, 0x00); // bgColourGreen
6273 avio_w8(pb
, 0x00); // bgColourBlue
6274 avio_w8(pb
, 0x00); // bgColourAlpha
6276 avio_wb16(pb
, 0x00); // defTextBoxTop
6277 avio_wb16(pb
, 0x00); // defTextBoxLeft
6278 avio_wb16(pb
, 0x00); // defTextBoxBottom
6279 avio_wb16(pb
, 0x00); // defTextBoxRight
6281 avio_wb16(pb
, 0x00); // startChar
6282 avio_wb16(pb
, 0x00); // endChar
6283 avio_wb16(pb
, 0x01); // fontID
6284 avio_w8(pb
, 0x00); // fontStyleFlags
6285 avio_w8(pb
, 0x00); // fontSize
6286 avio_w8(pb
, 0x00); // fgColourRed
6287 avio_w8(pb
, 0x00); // fgColourGreen
6288 avio_w8(pb
, 0x00); // fgColourBlue
6289 avio_w8(pb
, 0x00); // fgColourAlpha
6291 avio_wb32(pb
, 0x0D); // box size
6292 ffio_wfourcc(pb
, "ftab"); // box atom name
6293 avio_wb16(pb
, 0x01); // entry count
6295 avio_wb16(pb
, 0x01); // font ID
6296 avio_w8(pb
, 0x00); // font name length
6298 if ((size
= avio_close_dyn_buf(pb
, &buf
)) > 0) {
6299 track
->par
->extradata
= buf
;
6300 track
->par
->extradata_size
= size
;
6307 pkt
->stream_index
= tracknum
;
6308 pkt
->flags
= AV_PKT_FLAG_KEY
;
6310 for (i
= 0; i
< s
->nb_chapters
; i
++) {
6311 AVChapter
*c
= s
->chapters
[i
];
6312 AVDictionaryEntry
*t
;
6314 int64_t end
= av_rescale_q(c
->end
, c
->time_base
, (AVRational
){1,mov
->movie_timescale
});
6315 pkt
->pts
= pkt
->dts
= av_rescale_q(c
->start
, c
->time_base
, (AVRational
){1,mov
->movie_timescale
});
6316 pkt
->duration
= end
- pkt
->dts
;
6318 if ((t
= av_dict_get(c
->metadata
, "title", NULL
, 0))) {
6319 static const char encd
[12] = {
6320 0x00, 0x00, 0x00, 0x0C,
6322 0x00, 0x00, 0x01, 0x00 };
6323 len
= strlen(t
->value
);
6324 pkt
->size
= len
+ 2 + 12;
6325 pkt
->data
= av_malloc(pkt
->size
);
6327 av_packet_unref(pkt
);
6328 return AVERROR(ENOMEM
);
6330 AV_WB16(pkt
->data
, len
);
6331 memcpy(pkt
->data
+ 2, t
->value
, len
);
6332 memcpy(pkt
->data
+ len
+ 2, encd
, sizeof(encd
));
6333 ff_mov_write_packet(s
, pkt
);
6334 av_freep(&pkt
->data
);
6338 av_packet_unref(mov
->pkt
);
6344 static int mov_check_timecode_track(AVFormatContext
*s
, AVTimecode
*tc
, int src_index
, const char *tcstr
)
6348 /* compute the frame number */
6349 ret
= av_timecode_init_from_string(tc
, s
->streams
[src_index
]->avg_frame_rate
, tcstr
, s
);
6353 static int mov_create_timecode_track(AVFormatContext
*s
, int index
, int src_index
, AVTimecode tc
)
6355 MOVMuxContext
*mov
= s
->priv_data
;
6356 MOVTrack
*track
= &mov
->tracks
[index
];
6357 AVStream
*src_st
= s
->streams
[src_index
];
6359 AVPacket
*pkt
= mov
->pkt
;
6360 AVRational rate
= src_st
->avg_frame_rate
;
6363 /* tmcd track based on video stream */
6364 track
->mode
= mov
->mode
;
6365 track
->tag
= MKTAG('t','m','c','d');
6366 track
->src_track
= src_index
;
6367 track
->timescale
= mov
->tracks
[src_index
].timescale
;
6368 if (tc
.flags
& AV_TIMECODE_FLAG_DROPFRAME
)
6369 track
->timecode_flags
|= MOV_TIMECODE_FLAG_DROPFRAME
;
6371 /* set st to src_st for metadata access*/
6374 /* encode context: tmcd data stream */
6375 track
->par
= avcodec_parameters_alloc();
6377 return AVERROR(ENOMEM
);
6378 track
->par
->codec_type
= AVMEDIA_TYPE_DATA
;
6379 track
->par
->codec_tag
= track
->tag
;
6380 track
->st
->avg_frame_rate
= rate
;
6382 /* the tmcd track just contains one packet with the frame number */
6384 pkt
->stream_index
= index
;
6385 pkt
->flags
= AV_PKT_FLAG_KEY
;
6387 AV_WB32(pkt
->data
, tc
.start
);
6388 ret
= ff_mov_write_packet(s
, pkt
);
6389 av_packet_unref(pkt
);
6394 * st->disposition controls the "enabled" flag in the tkhd tag.
6395 * QuickTime will not play a track if it is not enabled. So make sure
6396 * that one track of each type (audio, video, subtitle) is enabled.
6398 * Subtitles are special. For audio and video, setting "enabled" also
6399 * makes the track "default" (i.e. it is rendered when played). For
6400 * subtitles, an "enabled" subtitle is not rendered by default, but
6401 * if no subtitle is enabled, the subtitle menu in QuickTime will be
6404 static void enable_tracks(AVFormatContext
*s
)
6406 MOVMuxContext
*mov
= s
->priv_data
;
6408 int enabled
[AVMEDIA_TYPE_NB
];
6409 int first
[AVMEDIA_TYPE_NB
];
6411 for (i
= 0; i
< AVMEDIA_TYPE_NB
; i
++) {
6416 for (i
= 0; i
< s
->nb_streams
; i
++) {
6417 AVStream
*st
= s
->streams
[i
];
6419 if (st
->codecpar
->codec_type
<= AVMEDIA_TYPE_UNKNOWN
||
6420 st
->codecpar
->codec_type
>= AVMEDIA_TYPE_NB
||
6424 if (first
[st
->codecpar
->codec_type
] < 0)
6425 first
[st
->codecpar
->codec_type
] = i
;
6426 if (st
->disposition
& AV_DISPOSITION_DEFAULT
) {
6427 mov
->tracks
[i
].flags
|= MOV_TRACK_ENABLED
;
6428 enabled
[st
->codecpar
->codec_type
]++;
6432 for (i
= 0; i
< AVMEDIA_TYPE_NB
; i
++) {
6434 case AVMEDIA_TYPE_VIDEO
:
6435 case AVMEDIA_TYPE_AUDIO
:
6436 case AVMEDIA_TYPE_SUBTITLE
:
6438 mov
->per_stream_grouping
= 1;
6439 if (!enabled
[i
] && first
[i
] >= 0)
6440 mov
->tracks
[first
[i
]].flags
|= MOV_TRACK_ENABLED
;
6446 static void mov_free(AVFormatContext
*s
)
6448 MOVMuxContext
*mov
= s
->priv_data
;
6454 if (mov
->chapter_track
) {
6455 avcodec_parameters_free(&mov
->tracks
[mov
->chapter_track
].par
);
6458 for (i
= 0; i
< mov
->nb_streams
; i
++) {
6459 MOVTrack
*const track
= &mov
->tracks
[i
];
6461 if (track
->tag
== MKTAG('r','t','p',' '))
6462 ff_mov_close_hinting(track
);
6463 else if (track
->tag
== MKTAG('t','m','c','d') && mov
->nb_meta_tmcd
)
6464 av_freep(&track
->par
);
6465 av_freep(&track
->cluster
);
6466 av_freep(&track
->frag_info
);
6467 av_packet_free(&track
->cover_image
);
6469 if (track
->eac3_priv
) {
6470 struct eac3_info
*info
= track
->eac3_priv
;
6471 av_packet_free(&info
->pkt
);
6472 av_freep(&track
->eac3_priv
);
6475 av_freep(&track
->vos_data
);
6477 ff_mov_cenc_free(&track
->cenc
);
6478 ffio_free_dyn_buf(&track
->mdat_buf
);
6480 avpriv_packet_list_free(&track
->squashed_packet_queue
);
6483 av_freep(&mov
->tracks
);
6484 ffio_free_dyn_buf(&mov
->mdat_buf
);
6487 static uint32_t rgb_to_yuv(uint32_t rgb
)
6492 r
= (rgb
>> 16) & 0xFF;
6493 g
= (rgb
>> 8) & 0xFF;
6496 y
= av_clip_uint8(( 16000 + 257 * r
+ 504 * g
+ 98 * b
)/1000);
6497 cb
= av_clip_uint8((128000 - 148 * r
- 291 * g
+ 439 * b
)/1000);
6498 cr
= av_clip_uint8((128000 + 439 * r
- 368 * g
- 71 * b
)/1000);
6500 return (y
<< 16) | (cr
<< 8) | cb
;
6503 static int mov_create_dvd_sub_decoder_specific_info(MOVTrack
*track
,
6506 int i
, width
= 720, height
= 480;
6507 int have_palette
= 0, have_size
= 0;
6508 uint32_t palette
[16];
6509 char *cur
= st
->codecpar
->extradata
;
6511 while (cur
&& *cur
) {
6512 if (strncmp("palette:", cur
, 8) == 0) {
6514 count
= sscanf(cur
+ 8,
6515 "%06"PRIx32
", %06"PRIx32
", %06"PRIx32
", %06"PRIx32
", "
6516 "%06"PRIx32
", %06"PRIx32
", %06"PRIx32
", %06"PRIx32
", "
6517 "%06"PRIx32
", %06"PRIx32
", %06"PRIx32
", %06"PRIx32
", "
6518 "%06"PRIx32
", %06"PRIx32
", %06"PRIx32
", %06"PRIx32
"",
6519 &palette
[ 0], &palette
[ 1], &palette
[ 2], &palette
[ 3],
6520 &palette
[ 4], &palette
[ 5], &palette
[ 6], &palette
[ 7],
6521 &palette
[ 8], &palette
[ 9], &palette
[10], &palette
[11],
6522 &palette
[12], &palette
[13], &palette
[14], &palette
[15]);
6524 for (i
= 0; i
< count
; i
++) {
6525 palette
[i
] = rgb_to_yuv(palette
[i
]);
6528 } else if (!strncmp("size:", cur
, 5)) {
6529 sscanf(cur
+ 5, "%dx%d", &width
, &height
);
6532 if (have_palette
&& have_size
)
6534 cur
+= strcspn(cur
, "\n\r");
6535 cur
+= strspn(cur
, "\n\r");
6538 track
->vos_data
= av_malloc(16*4 + AV_INPUT_BUFFER_PADDING_SIZE
);
6539 if (!track
->vos_data
)
6540 return AVERROR(ENOMEM
);
6541 for (i
= 0; i
< 16; i
++) {
6542 AV_WB32(track
->vos_data
+ i
* 4, palette
[i
]);
6544 memset(track
->vos_data
+ 16*4, 0, AV_INPUT_BUFFER_PADDING_SIZE
);
6545 track
->vos_len
= 16 * 4;
6547 st
->codecpar
->width
= width
;
6548 st
->codecpar
->height
= track
->height
= height
;
6553 static int mov_init(AVFormatContext
*s
)
6555 MOVMuxContext
*mov
= s
->priv_data
;
6559 mov
->pkt
= ffformatcontext(s
)->pkt
;
6561 /* Default mode == MP4 */
6562 mov
->mode
= MODE_MP4
;
6564 #define IS_MODE(muxer, config) (CONFIG_ ## config ## _MUXER && !strcmp(#muxer, s->oformat->name))
6565 if (IS_MODE(3gp
, TGP
)) mov
->mode
= MODE_3GP
;
6566 else if (IS_MODE(3g2
, TG2
)) mov
->mode
= MODE_3GP
|MODE_3G2
;
6567 else if (IS_MODE(mov
, MOV
)) mov
->mode
= MODE_MOV
;
6568 else if (IS_MODE(psp
, PSP
)) mov
->mode
= MODE_PSP
;
6569 else if (IS_MODE(ipod
, IPOD
)) mov
->mode
= MODE_IPOD
;
6570 else if (IS_MODE(ismv
, ISMV
)) mov
->mode
= MODE_ISM
;
6571 else if (IS_MODE(f4v
, F4V
)) mov
->mode
= MODE_F4V
;
6574 if (mov
->flags
& FF_MOV_FLAG_DELAY_MOOV
)
6575 mov
->flags
|= FF_MOV_FLAG_EMPTY_MOOV
;
6577 /* Set the FRAGMENT flag if any of the fragmentation methods are
6579 if (mov
->max_fragment_duration
|| mov
->max_fragment_size
||
6580 mov
->flags
& (FF_MOV_FLAG_EMPTY_MOOV
|
6581 FF_MOV_FLAG_FRAG_KEYFRAME
|
6582 FF_MOV_FLAG_FRAG_CUSTOM
|
6583 FF_MOV_FLAG_FRAG_EVERY_FRAME
))
6584 mov
->flags
|= FF_MOV_FLAG_FRAGMENT
;
6586 /* Set other implicit flags immediately */
6587 if (mov
->mode
== MODE_ISM
)
6588 mov
->flags
|= FF_MOV_FLAG_EMPTY_MOOV
| FF_MOV_FLAG_SEPARATE_MOOF
|
6589 FF_MOV_FLAG_FRAGMENT
| FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
;
6590 if (mov
->flags
& FF_MOV_FLAG_DASH
)
6591 mov
->flags
|= FF_MOV_FLAG_FRAGMENT
| FF_MOV_FLAG_EMPTY_MOOV
|
6592 FF_MOV_FLAG_DEFAULT_BASE_MOOF
;
6593 if (mov
->flags
& FF_MOV_FLAG_CMAF
)
6594 mov
->flags
|= FF_MOV_FLAG_FRAGMENT
| FF_MOV_FLAG_EMPTY_MOOV
|
6595 FF_MOV_FLAG_DEFAULT_BASE_MOOF
| FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
;
6597 if (mov
->flags
& FF_MOV_FLAG_EMPTY_MOOV
&& s
->flags
& AVFMT_FLAG_AUTO_BSF
) {
6598 av_log(s
, AV_LOG_VERBOSE
, "Empty MOOV enabled; disabling automatic bitstream filtering\n");
6599 s
->flags
&= ~AVFMT_FLAG_AUTO_BSF
;
6602 if (mov
->flags
& FF_MOV_FLAG_GLOBAL_SIDX
&& mov
->flags
& FF_MOV_FLAG_SKIP_SIDX
) {
6603 av_log(s
, AV_LOG_WARNING
, "Global SIDX enabled; Ignoring skip_sidx option\n");
6604 mov
->flags
&= ~FF_MOV_FLAG_SKIP_SIDX
;
6607 if (mov
->flags
& FF_MOV_FLAG_FASTSTART
) {
6608 mov
->reserved_moov_size
= -1;
6611 if (mov
->use_editlist
< 0) {
6612 mov
->use_editlist
= 1;
6613 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
&&
6614 !(mov
->flags
& FF_MOV_FLAG_DELAY_MOOV
)) {
6615 // If we can avoid needing an edit list by shifting the
6616 // tracks, prefer that over (trying to) write edit lists
6617 // in fragmented output.
6618 if (s
->avoid_negative_ts
== AVFMT_AVOID_NEG_TS_AUTO
||
6619 s
->avoid_negative_ts
== AVFMT_AVOID_NEG_TS_MAKE_ZERO
)
6620 mov
->use_editlist
= 0;
6622 if (mov
->flags
& FF_MOV_FLAG_CMAF
) {
6623 // CMAF Track requires negative cts offsets without edit lists
6624 mov
->use_editlist
= 0;
6627 if (mov
->flags
& FF_MOV_FLAG_EMPTY_MOOV
&&
6628 !(mov
->flags
& FF_MOV_FLAG_DELAY_MOOV
) && mov
->use_editlist
)
6629 av_log(s
, AV_LOG_WARNING
, "No meaningful edit list will be written when using empty_moov without delay_moov\n");
6631 if (mov
->flags
& FF_MOV_FLAG_CMAF
&& mov
->use_editlist
) {
6632 av_log(s
, AV_LOG_WARNING
, "Edit list enabled; Assuming writing CMAF Track File\n");
6633 mov
->flags
&= ~FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
;
6635 if (!mov
->use_editlist
&& s
->avoid_negative_ts
== AVFMT_AVOID_NEG_TS_AUTO
&&
6636 !(mov
->flags
& FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS
))
6637 s
->avoid_negative_ts
= AVFMT_AVOID_NEG_TS_MAKE_ZERO
;
6639 /* Clear the omit_tfhd_offset flag if default_base_moof is set;
6640 * if the latter is set that's enough and omit_tfhd_offset doesn't
6641 * add anything extra on top of that. */
6642 if (mov
->flags
& FF_MOV_FLAG_OMIT_TFHD_OFFSET
&&
6643 mov
->flags
& FF_MOV_FLAG_DEFAULT_BASE_MOOF
)
6644 mov
->flags
&= ~FF_MOV_FLAG_OMIT_TFHD_OFFSET
;
6646 if (mov
->frag_interleave
&&
6647 mov
->flags
& (FF_MOV_FLAG_OMIT_TFHD_OFFSET
| FF_MOV_FLAG_SEPARATE_MOOF
)) {
6648 av_log(s
, AV_LOG_ERROR
,
6649 "Sample interleaving in fragments is mutually exclusive with "
6650 "omit_tfhd_offset and separate_moof\n");
6651 return AVERROR(EINVAL
);
6654 /* Non-seekable output is ok if using fragmentation. If ism_lookahead
6655 * is enabled, we don't support non-seekable output at all. */
6656 if (!(s
->pb
->seekable
& AVIO_SEEKABLE_NORMAL
) &&
6657 (!(mov
->flags
& FF_MOV_FLAG_FRAGMENT
) || mov
->ism_lookahead
)) {
6658 av_log(s
, AV_LOG_ERROR
, "muxer does not support non seekable output\n");
6659 return AVERROR(EINVAL
);
6662 mov
->nb_streams
= s
->nb_streams
;
6663 if (mov
->mode
& (MODE_MP4
|MODE_MOV
|MODE_IPOD
) && s
->nb_chapters
)
6664 mov
->chapter_track
= mov
->nb_streams
++;
6666 if (mov
->flags
& FF_MOV_FLAG_RTP_HINT
) {
6667 for (i
= 0; i
< s
->nb_streams
; i
++)
6668 if (rtp_hinting_needed(s
->streams
[i
]))
6672 if ( mov
->write_tmcd
== -1 && (mov
->mode
== MODE_MOV
|| mov
->mode
== MODE_MP4
)
6673 || mov
->write_tmcd
== 1) {
6674 AVDictionaryEntry
*global_tcr
= av_dict_get(s
->metadata
, "timecode",
6677 /* +1 tmcd track for each video stream with a timecode */
6678 for (i
= 0; i
< s
->nb_streams
; i
++) {
6679 AVStream
*st
= s
->streams
[i
];
6680 AVDictionaryEntry
*t
= global_tcr
;
6681 if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
&&
6682 (t
|| (t
=av_dict_get(st
->metadata
, "timecode", NULL
, 0)))) {
6684 ret
= mov_check_timecode_track(s
, &tc
, i
, t
->value
);
6686 mov
->nb_meta_tmcd
++;
6690 /* check if there is already a tmcd track to remux */
6691 if (mov
->nb_meta_tmcd
) {
6692 for (i
= 0; i
< s
->nb_streams
; i
++) {
6693 AVStream
*st
= s
->streams
[i
];
6694 if (st
->codecpar
->codec_tag
== MKTAG('t','m','c','d')) {
6695 av_log(s
, AV_LOG_WARNING
, "You requested a copy of the original timecode track "
6696 "so timecode metadata are now ignored\n");
6697 mov
->nb_meta_tmcd
= 0;
6702 mov
->nb_streams
+= mov
->nb_meta_tmcd
;
6705 // Reserve an extra stream for chapters for the case where chapters
6706 // are written in the trailer
6707 mov
->tracks
= av_calloc(mov
->nb_streams
+ 1, sizeof(*mov
->tracks
));
6709 return AVERROR(ENOMEM
);
6711 if (mov
->encryption_scheme_str
!= NULL
&& strcmp(mov
->encryption_scheme_str
, "none") != 0) {
6712 if (strcmp(mov
->encryption_scheme_str
, "cenc-aes-ctr") == 0) {
6713 mov
->encryption_scheme
= MOV_ENC_CENC_AES_CTR
;
6715 if (mov
->encryption_key_len
!= AES_CTR_KEY_SIZE
) {
6716 av_log(s
, AV_LOG_ERROR
, "Invalid encryption key len %d expected %d\n",
6717 mov
->encryption_key_len
, AES_CTR_KEY_SIZE
);
6718 return AVERROR(EINVAL
);
6721 if (mov
->encryption_kid_len
!= CENC_KID_SIZE
) {
6722 av_log(s
, AV_LOG_ERROR
, "Invalid encryption kid len %d expected %d\n",
6723 mov
->encryption_kid_len
, CENC_KID_SIZE
);
6724 return AVERROR(EINVAL
);
6727 av_log(s
, AV_LOG_ERROR
, "unsupported encryption scheme %s\n",
6728 mov
->encryption_scheme_str
);
6729 return AVERROR(EINVAL
);
6733 for (i
= 0; i
< s
->nb_streams
; i
++) {
6734 AVStream
*st
= s
->streams
[i
];
6735 MOVTrack
*track
= &mov
->tracks
[i
];
6736 AVDictionaryEntry
*lang
= av_dict_get(st
->metadata
, "language", NULL
,0);
6739 track
->par
= st
->codecpar
;
6740 track
->language
= ff_mov_iso639_to_lang(lang
?lang
->value
:"und", mov
->mode
!=MODE_MOV
);
6741 if (track
->language
< 0)
6742 track
->language
= 32767; // Unspecified Macintosh language code
6743 track
->mode
= mov
->mode
;
6744 track
->tag
= mov_find_codec_tag(s
, track
);
6746 av_log(s
, AV_LOG_ERROR
, "Could not find tag for codec %s in stream #%d, "
6747 "codec not currently supported in container\n",
6748 avcodec_get_name(st
->codecpar
->codec_id
), i
);
6749 return AVERROR(EINVAL
);
6751 /* If hinting of this track is enabled by a later hint track,
6752 * this is updated. */
6753 track
->hint_track
= -1;
6754 track
->start_dts
= AV_NOPTS_VALUE
;
6755 track
->start_cts
= AV_NOPTS_VALUE
;
6756 track
->end_pts
= AV_NOPTS_VALUE
;
6757 track
->dts_shift
= AV_NOPTS_VALUE
;
6758 if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
6759 if (track
->tag
== MKTAG('m','x','3','p') || track
->tag
== MKTAG('m','x','3','n') ||
6760 track
->tag
== MKTAG('m','x','4','p') || track
->tag
== MKTAG('m','x','4','n') ||
6761 track
->tag
== MKTAG('m','x','5','p') || track
->tag
== MKTAG('m','x','5','n')) {
6762 if (st
->codecpar
->width
!= 720 || (st
->codecpar
->height
!= 608 && st
->codecpar
->height
!= 512)) {
6763 av_log(s
, AV_LOG_ERROR
, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
6764 return AVERROR(EINVAL
);
6766 track
->height
= track
->tag
>> 24 == 'n' ? 486 : 576;
6768 if (mov
->video_track_timescale
) {
6769 track
->timescale
= mov
->video_track_timescale
;
6770 if (mov
->mode
== MODE_ISM
&& mov
->video_track_timescale
!= 10000000)
6771 av_log(s
, AV_LOG_WARNING
, "Warning: some tools, like mp4split, assume a timescale of 10000000 for ISMV.\n");
6773 track
->timescale
= st
->time_base
.den
;
6774 while(track
->timescale
< 10000)
6775 track
->timescale
*= 2;
6777 if (st
->codecpar
->width
> 65535 || st
->codecpar
->height
> 65535) {
6778 av_log(s
, AV_LOG_ERROR
, "Resolution %dx%d too large for mov/mp4\n", st
->codecpar
->width
, st
->codecpar
->height
);
6779 return AVERROR(EINVAL
);
6781 if (track
->mode
== MODE_MOV
&& track
->timescale
> 100000)
6782 av_log(s
, AV_LOG_WARNING
,
6783 "WARNING codec timebase is very high. If duration is too long,\n"
6784 "file may not be playable by quicktime. Specify a shorter timebase\n"
6785 "or choose different container.\n");
6786 if (track
->mode
== MODE_MOV
&&
6787 track
->par
->codec_id
== AV_CODEC_ID_RAWVIDEO
&&
6788 track
->tag
== MKTAG('r','a','w',' ')) {
6789 enum AVPixelFormat pix_fmt
= track
->par
->format
;
6790 if (pix_fmt
== AV_PIX_FMT_NONE
&& track
->par
->bits_per_coded_sample
== 1)
6791 pix_fmt
= AV_PIX_FMT_MONOWHITE
;
6792 track
->is_unaligned_qt_rgb
=
6793 pix_fmt
== AV_PIX_FMT_RGB24
||
6794 pix_fmt
== AV_PIX_FMT_BGR24
||
6795 pix_fmt
== AV_PIX_FMT_PAL8
||
6796 pix_fmt
== AV_PIX_FMT_GRAY8
||
6797 pix_fmt
== AV_PIX_FMT_MONOWHITE
||
6798 pix_fmt
== AV_PIX_FMT_MONOBLACK
;
6800 if (track
->par
->codec_id
== AV_CODEC_ID_VP9
||
6801 track
->par
->codec_id
== AV_CODEC_ID_AV1
) {
6802 if (track
->mode
!= MODE_MP4
) {
6803 av_log(s
, AV_LOG_ERROR
, "%s only supported in MP4.\n", avcodec_get_name(track
->par
->codec_id
));
6804 return AVERROR(EINVAL
);
6806 } else if (track
->par
->codec_id
== AV_CODEC_ID_VP8
) {
6807 /* altref frames handling is not defined in the spec as of version v1.0,
6808 * so just forbid muxing VP8 streams altogether until a new version does */
6809 av_log(s
, AV_LOG_ERROR
, "VP8 muxing is currently not supported.\n");
6810 return AVERROR_PATCHWELCOME
;
6812 if (is_cover_image(st
)) {
6813 track
->cover_image
= av_packet_alloc();
6814 if (!track
->cover_image
)
6815 return AVERROR(ENOMEM
);
6817 } else if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
6818 track
->timescale
= st
->codecpar
->sample_rate
;
6819 if (!st
->codecpar
->frame_size
&& !av_get_bits_per_sample(st
->codecpar
->codec_id
)) {
6820 av_log(s
, AV_LOG_WARNING
, "track %d: codec frame size is not set\n", i
);
6821 track
->audio_vbr
= 1;
6822 }else if (st
->codecpar
->codec_id
== AV_CODEC_ID_ADPCM_MS
||
6823 st
->codecpar
->codec_id
== AV_CODEC_ID_ADPCM_IMA_WAV
||
6824 st
->codecpar
->codec_id
== AV_CODEC_ID_ILBC
){
6825 if (!st
->codecpar
->block_align
) {
6826 av_log(s
, AV_LOG_ERROR
, "track %d: codec block align is not set for adpcm\n", i
);
6827 return AVERROR(EINVAL
);
6829 track
->sample_size
= st
->codecpar
->block_align
;
6830 }else if (st
->codecpar
->frame_size
> 1){ /* assume compressed audio */
6831 track
->audio_vbr
= 1;
6833 track
->sample_size
= (av_get_bits_per_sample(st
->codecpar
->codec_id
) >> 3) * st
->codecpar
->channels
;
6835 if (st
->codecpar
->codec_id
== AV_CODEC_ID_ILBC
||
6836 st
->codecpar
->codec_id
== AV_CODEC_ID_ADPCM_IMA_QT
) {
6837 track
->audio_vbr
= 1;
6839 if (track
->mode
!= MODE_MOV
&&
6840 track
->par
->codec_id
== AV_CODEC_ID_MP3
&& track
->timescale
< 16000) {
6841 if (s
->strict_std_compliance
>= FF_COMPLIANCE_NORMAL
) {
6842 av_log(s
, AV_LOG_ERROR
, "track %d: muxing mp3 at %dhz is not standard, to mux anyway set strict to -1\n",
6843 i
, track
->par
->sample_rate
);
6844 return AVERROR(EINVAL
);
6846 av_log(s
, AV_LOG_WARNING
, "track %d: muxing mp3 at %dhz is not standard in MP4\n",
6847 i
, track
->par
->sample_rate
);
6850 if (track
->par
->codec_id
== AV_CODEC_ID_FLAC
||
6851 track
->par
->codec_id
== AV_CODEC_ID_TRUEHD
||
6852 track
->par
->codec_id
== AV_CODEC_ID_OPUS
) {
6853 if (track
->mode
!= MODE_MP4
) {
6854 av_log(s
, AV_LOG_ERROR
, "%s only supported in MP4.\n", avcodec_get_name(track
->par
->codec_id
));
6855 return AVERROR(EINVAL
);
6857 if (track
->par
->codec_id
!= AV_CODEC_ID_OPUS
&&
6858 s
->strict_std_compliance
> FF_COMPLIANCE_EXPERIMENTAL
) {
6859 av_log(s
, AV_LOG_ERROR
,
6860 "%s in MP4 support is experimental, add "
6861 "'-strict %d' if you want to use it.\n",
6862 avcodec_get_name(track
->par
->codec_id
), FF_COMPLIANCE_EXPERIMENTAL
);
6863 return AVERROR_EXPERIMENTAL
;
6866 } else if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_SUBTITLE
) {
6867 track
->timescale
= st
->time_base
.den
;
6869 if (track
->par
->codec_id
== AV_CODEC_ID_TTML
) {
6870 /* 14496-30 requires us to use a single sample per fragment
6871 for TTML, for which we define a per-track flag.
6873 We set the flag in case we are receiving TTML paragraphs
6874 from the input, in other words in case we are not doing
6876 track
->squash_fragment_samples_to_one
=
6877 ff_is_ttml_stream_paragraph_based(track
->par
);
6879 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
&&
6880 track
->squash_fragment_samples_to_one
) {
6881 av_log(s
, AV_LOG_ERROR
,
6882 "Fragmentation is not currently supported for "
6883 "TTML in MP4/ISMV (track synchronization between "
6884 "subtitles and other media is not yet implemented)!\n");
6885 return AVERROR_PATCHWELCOME
;
6888 if (track
->mode
!= MODE_ISM
&&
6889 track
->par
->codec_tag
== MOV_ISMV_TTML_TAG
&&
6890 s
->strict_std_compliance
> FF_COMPLIANCE_UNOFFICIAL
) {
6891 av_log(s
, AV_LOG_ERROR
,
6892 "ISMV style TTML support with the 'dfxp' tag in "
6893 "non-ISMV formats is not officially supported. Add "
6894 "'-strict unofficial' if you want to use it.\n");
6895 return AVERROR_EXPERIMENTAL
;
6898 } else if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_DATA
) {
6899 track
->timescale
= st
->time_base
.den
;
6901 track
->timescale
= mov
->movie_timescale
;
6904 track
->height
= st
->codecpar
->height
;
6905 /* The Protected Interoperable File Format (PIFF) standard, used by ISMV recommends but
6906 doesn't mandate a track timescale of 10,000,000. The muxer allows a custom timescale
6907 for video tracks, so if user-set, it isn't overwritten */
6908 if (mov
->mode
== MODE_ISM
&&
6909 (st
->codecpar
->codec_type
!= AVMEDIA_TYPE_VIDEO
||
6910 (st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
&& !mov
->video_track_timescale
))) {
6911 track
->timescale
= 10000000;
6914 avpriv_set_pts_info(st
, 64, 1, track
->timescale
);
6916 if (mov
->encryption_scheme
== MOV_ENC_CENC_AES_CTR
) {
6917 ret
= ff_mov_cenc_init(&track
->cenc
, mov
->encryption_key
,
6918 (track
->par
->codec_id
== AV_CODEC_ID_H264
|| track
->par
->codec_id
== AV_CODEC_ID_HEVC
),
6919 s
->flags
& AVFMT_FLAG_BITEXACT
);
6929 static int mov_write_header(AVFormatContext
*s
)
6931 AVIOContext
*pb
= s
->pb
;
6932 MOVMuxContext
*mov
= s
->priv_data
;
6933 int i
, ret
, hint_track
= 0, tmcd_track
= 0, nb_tracks
= s
->nb_streams
;
6935 if (mov
->mode
& (MODE_MP4
|MODE_MOV
|MODE_IPOD
) && s
->nb_chapters
)
6938 if (mov
->flags
& FF_MOV_FLAG_RTP_HINT
) {
6939 hint_track
= nb_tracks
;
6940 for (i
= 0; i
< s
->nb_streams
; i
++)
6941 if (rtp_hinting_needed(s
->streams
[i
]))
6945 if (mov
->nb_meta_tmcd
)
6946 tmcd_track
= nb_tracks
;
6948 for (i
= 0; i
< s
->nb_streams
; i
++) {
6950 AVStream
*st
= s
->streams
[i
];
6951 MOVTrack
*track
= &mov
->tracks
[i
];
6953 /* copy extradata if it exists */
6954 if (st
->codecpar
->extradata_size
) {
6955 if (st
->codecpar
->codec_id
== AV_CODEC_ID_DVD_SUBTITLE
)
6956 mov_create_dvd_sub_decoder_specific_info(track
, st
);
6957 else if (!TAG_IS_AVCI(track
->tag
) && st
->codecpar
->codec_id
!= AV_CODEC_ID_DNXHD
) {
6958 track
->vos_len
= st
->codecpar
->extradata_size
;
6959 track
->vos_data
= av_malloc(track
->vos_len
+ AV_INPUT_BUFFER_PADDING_SIZE
);
6960 if (!track
->vos_data
) {
6961 return AVERROR(ENOMEM
);
6963 memcpy(track
->vos_data
, st
->codecpar
->extradata
, track
->vos_len
);
6964 memset(track
->vos_data
+ track
->vos_len
, 0, AV_INPUT_BUFFER_PADDING_SIZE
);
6968 if (st
->codecpar
->codec_type
!= AVMEDIA_TYPE_AUDIO
||
6969 track
->par
->channel_layout
!= AV_CH_LAYOUT_MONO
)
6972 for (j
= 0; j
< s
->nb_streams
; j
++) {
6973 AVStream
*stj
= s
->streams
[j
];
6974 MOVTrack
*trackj
= &mov
->tracks
[j
];
6978 if (stj
->codecpar
->codec_type
!= AVMEDIA_TYPE_AUDIO
||
6979 trackj
->par
->channel_layout
!= AV_CH_LAYOUT_MONO
||
6980 trackj
->language
!= track
->language
||
6981 trackj
->tag
!= track
->tag
6984 track
->multichannel_as_mono
++;
6988 if (!(mov
->flags
& FF_MOV_FLAG_DELAY_MOOV
)) {
6989 if ((ret
= mov_write_identification(pb
, s
)) < 0)
6993 if (mov
->reserved_moov_size
){
6994 mov
->reserved_header_pos
= avio_tell(pb
);
6995 if (mov
->reserved_moov_size
> 0)
6996 avio_skip(pb
, mov
->reserved_moov_size
);
6999 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
) {
7000 /* If no fragmentation options have been set, set a default. */
7001 if (!(mov
->flags
& (FF_MOV_FLAG_FRAG_KEYFRAME
|
7002 FF_MOV_FLAG_FRAG_CUSTOM
|
7003 FF_MOV_FLAG_FRAG_EVERY_FRAME
)) &&
7004 !mov
->max_fragment_duration
&& !mov
->max_fragment_size
)
7005 mov
->flags
|= FF_MOV_FLAG_FRAG_KEYFRAME
;
7007 if (mov
->flags
& FF_MOV_FLAG_FASTSTART
)
7008 mov
->reserved_header_pos
= avio_tell(pb
);
7009 mov_write_mdat_tag(pb
, mov
);
7012 ff_parse_creation_time_metadata(s
, &mov
->time
, 1);
7014 mov
->time
+= 0x7C25B080; // 1970 based -> 1904 based
7016 if (mov
->chapter_track
)
7017 if ((ret
= mov_create_chapter_track(s
, mov
->chapter_track
)) < 0)
7020 if (mov
->flags
& FF_MOV_FLAG_RTP_HINT
) {
7021 for (i
= 0; i
< s
->nb_streams
; i
++) {
7022 if (rtp_hinting_needed(s
->streams
[i
])) {
7023 if ((ret
= ff_mov_init_hinting(s
, hint_track
, i
)) < 0)
7030 if (mov
->nb_meta_tmcd
) {
7031 const AVDictionaryEntry
*t
, *global_tcr
= av_dict_get(s
->metadata
,
7032 "timecode", NULL
, 0);
7033 /* Initialize the tmcd tracks */
7034 for (i
= 0; i
< s
->nb_streams
; i
++) {
7035 AVStream
*st
= s
->streams
[i
];
7038 if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
7041 t
= av_dict_get(st
->metadata
, "timecode", NULL
, 0);
7044 if (mov_check_timecode_track(s
, &tc
, i
, t
->value
) < 0)
7046 if ((ret
= mov_create_timecode_track(s
, tmcd_track
, i
, tc
)) < 0)
7055 if (mov
->flags
& FF_MOV_FLAG_ISML
)
7056 mov_write_isml_manifest(pb
, mov
, s
);
7058 if (mov
->flags
& FF_MOV_FLAG_EMPTY_MOOV
&&
7059 !(mov
->flags
& FF_MOV_FLAG_DELAY_MOOV
)) {
7060 if ((ret
= mov_write_moov_tag(pb
, mov
, s
)) < 0)
7062 mov
->moov_written
= 1;
7063 if (mov
->flags
& FF_MOV_FLAG_GLOBAL_SIDX
)
7064 mov
->reserved_header_pos
= avio_tell(pb
);
7070 static int get_moov_size(AVFormatContext
*s
)
7073 AVIOContext
*moov_buf
;
7074 MOVMuxContext
*mov
= s
->priv_data
;
7076 if ((ret
= ffio_open_null_buf(&moov_buf
)) < 0)
7078 if ((ret
= mov_write_moov_tag(moov_buf
, mov
, s
)) < 0)
7080 return ffio_close_null_buf(moov_buf
);
7083 static int get_sidx_size(AVFormatContext
*s
)
7087 MOVMuxContext
*mov
= s
->priv_data
;
7089 if ((ret
= ffio_open_null_buf(&buf
)) < 0)
7091 mov_write_sidx_tags(buf
, mov
, -1, 0);
7092 return ffio_close_null_buf(buf
);
7096 * This function gets the moov size if moved to the top of the file: the chunk
7097 * offset table can switch between stco (32-bit entries) to co64 (64-bit
7098 * entries) when the moov is moved to the beginning, so the size of the moov
7099 * would change. It also updates the chunk offset tables.
7101 static int compute_moov_size(AVFormatContext
*s
)
7103 int i
, moov_size
, moov_size2
;
7104 MOVMuxContext
*mov
= s
->priv_data
;
7106 moov_size
= get_moov_size(s
);
7110 for (i
= 0; i
< mov
->nb_streams
; i
++)
7111 mov
->tracks
[i
].data_offset
+= moov_size
;
7113 moov_size2
= get_moov_size(s
);
7117 /* if the size changed, we just switched from stco to co64 and need to
7118 * update the offsets */
7119 if (moov_size2
!= moov_size
)
7120 for (i
= 0; i
< mov
->nb_streams
; i
++)
7121 mov
->tracks
[i
].data_offset
+= moov_size2
- moov_size
;
7126 static int compute_sidx_size(AVFormatContext
*s
)
7129 MOVMuxContext
*mov
= s
->priv_data
;
7131 sidx_size
= get_sidx_size(s
);
7135 for (i
= 0; i
< mov
->nb_streams
; i
++)
7136 mov
->tracks
[i
].data_offset
+= sidx_size
;
7141 static int shift_data(AVFormatContext
*s
)
7144 MOVMuxContext
*mov
= s
->priv_data
;
7146 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
)
7147 moov_size
= compute_sidx_size(s
);
7149 moov_size
= compute_moov_size(s
);
7153 return ff_format_shift_data(s
, mov
->reserved_header_pos
, moov_size
);
7156 static int mov_write_trailer(AVFormatContext
*s
)
7158 MOVMuxContext
*mov
= s
->priv_data
;
7159 AVIOContext
*pb
= s
->pb
;
7164 if (mov
->need_rewrite_extradata
) {
7165 for (i
= 0; i
< s
->nb_streams
; i
++) {
7166 MOVTrack
*track
= &mov
->tracks
[i
];
7167 AVCodecParameters
*par
= track
->par
;
7169 track
->vos_len
= par
->extradata_size
;
7170 av_freep(&track
->vos_data
);
7171 track
->vos_data
= av_malloc(track
->vos_len
+ AV_INPUT_BUFFER_PADDING_SIZE
);
7172 if (!track
->vos_data
)
7173 return AVERROR(ENOMEM
);
7174 memcpy(track
->vos_data
, par
->extradata
, track
->vos_len
);
7175 memset(track
->vos_data
+ track
->vos_len
, 0, AV_INPUT_BUFFER_PADDING_SIZE
);
7177 mov
->need_rewrite_extradata
= 0;
7181 * Before actually writing the trailer, make sure that there are no
7182 * dangling subtitles, that need a terminating sample.
7184 for (i
= 0; i
< mov
->nb_streams
; i
++) {
7185 MOVTrack
*trk
= &mov
->tracks
[i
];
7186 if (trk
->par
->codec_id
== AV_CODEC_ID_MOV_TEXT
&&
7187 !trk
->last_sample_is_subtitle_end
) {
7188 mov_write_subtitle_end_packet(s
, i
, trk
->track_duration
);
7189 trk
->last_sample_is_subtitle_end
= 1;
7193 // Check if we have any tracks that require squashing.
7194 // In that case, we'll have to write the packet here.
7195 if ((res
= mov_write_squashed_packets(s
)) < 0)
7198 // If there were no chapters when the header was written, but there
7199 // are chapters now, write them in the trailer. This only works
7200 // when we are not doing fragments.
7201 if (!mov
->chapter_track
&& !(mov
->flags
& FF_MOV_FLAG_FRAGMENT
)) {
7202 if (mov
->mode
& (MODE_MP4
|MODE_MOV
|MODE_IPOD
) && s
->nb_chapters
) {
7203 mov
->chapter_track
= mov
->nb_streams
++;
7204 if ((res
= mov_create_chapter_track(s
, mov
->chapter_track
)) < 0)
7209 if (!(mov
->flags
& FF_MOV_FLAG_FRAGMENT
)) {
7210 moov_pos
= avio_tell(pb
);
7212 /* Write size of mdat tag */
7213 if (mov
->mdat_size
+ 8 <= UINT32_MAX
) {
7214 avio_seek(pb
, mov
->mdat_pos
, SEEK_SET
);
7215 avio_wb32(pb
, mov
->mdat_size
+ 8);
7217 /* overwrite 'wide' placeholder atom */
7218 avio_seek(pb
, mov
->mdat_pos
- 8, SEEK_SET
);
7219 /* special value: real atom size will be 64 bit value after
7222 ffio_wfourcc(pb
, "mdat");
7223 avio_wb64(pb
, mov
->mdat_size
+ 16);
7225 avio_seek(pb
, mov
->reserved_moov_size
> 0 ? mov
->reserved_header_pos
: moov_pos
, SEEK_SET
);
7227 if (mov
->flags
& FF_MOV_FLAG_FASTSTART
) {
7228 av_log(s
, AV_LOG_INFO
, "Starting second pass: moving the moov atom to the beginning of the file\n");
7229 res
= shift_data(s
);
7232 avio_seek(pb
, mov
->reserved_header_pos
, SEEK_SET
);
7233 if ((res
= mov_write_moov_tag(pb
, mov
, s
)) < 0)
7235 } else if (mov
->reserved_moov_size
> 0) {
7237 if ((res
= mov_write_moov_tag(pb
, mov
, s
)) < 0)
7239 size
= mov
->reserved_moov_size
- (avio_tell(pb
) - mov
->reserved_header_pos
);
7241 av_log(s
, AV_LOG_ERROR
, "reserved_moov_size is too small, needed %"PRId64
" additional\n", 8-size
);
7242 return AVERROR(EINVAL
);
7244 avio_wb32(pb
, size
);
7245 ffio_wfourcc(pb
, "free");
7246 ffio_fill(pb
, 0, size
- 8);
7247 avio_seek(pb
, moov_pos
, SEEK_SET
);
7249 if ((res
= mov_write_moov_tag(pb
, mov
, s
)) < 0)
7254 mov_auto_flush_fragment(s
, 1);
7255 for (i
= 0; i
< mov
->nb_streams
; i
++)
7256 mov
->tracks
[i
].data_offset
= 0;
7257 if (mov
->flags
& FF_MOV_FLAG_GLOBAL_SIDX
) {
7259 av_log(s
, AV_LOG_INFO
, "Starting second pass: inserting sidx atoms\n");
7260 res
= shift_data(s
);
7263 end
= avio_tell(pb
);
7264 avio_seek(pb
, mov
->reserved_header_pos
, SEEK_SET
);
7265 mov_write_sidx_tags(pb
, mov
, -1, 0);
7266 avio_seek(pb
, end
, SEEK_SET
);
7268 if (!(mov
->flags
& FF_MOV_FLAG_SKIP_TRAILER
)) {
7269 avio_write_marker(s
->pb
, AV_NOPTS_VALUE
, AVIO_DATA_MARKER_TRAILER
);
7270 res
= mov_write_mfra_tag(pb
, mov
);
7279 static int mov_check_bitstream(AVFormatContext
*s
, AVStream
*st
,
7280 const AVPacket
*pkt
)
7284 if (st
->codecpar
->codec_id
== AV_CODEC_ID_AAC
) {
7285 if (pkt
->size
> 2 && (AV_RB16(pkt
->data
) & 0xfff0) == 0xfff0)
7286 ret
= ff_stream_add_bitstream_filter(st
, "aac_adtstoasc", NULL
);
7287 } else if (st
->codecpar
->codec_id
== AV_CODEC_ID_VP9
) {
7288 ret
= ff_stream_add_bitstream_filter(st
, "vp9_superframe", NULL
);
7294 #if CONFIG_TGP_MUXER || CONFIG_TG2_MUXER
7295 static const AVCodecTag codec_3gp_tags
[] = {
7296 { AV_CODEC_ID_H263
, MKTAG('s','2','6','3') },
7297 { AV_CODEC_ID_H264
, MKTAG('a','v','c','1') },
7298 { AV_CODEC_ID_MPEG4
, MKTAG('m','p','4','v') },
7299 { AV_CODEC_ID_AAC
, MKTAG('m','p','4','a') },
7300 { AV_CODEC_ID_AMR_NB
, MKTAG('s','a','m','r') },
7301 { AV_CODEC_ID_AMR_WB
, MKTAG('s','a','w','b') },
7302 { AV_CODEC_ID_MOV_TEXT
, MKTAG('t','x','3','g') },
7303 { AV_CODEC_ID_NONE
, 0 },
7305 static const AVCodecTag
*const codec_3gp_tags_list
[] = { codec_3gp_tags
, NULL
};
7308 static const AVCodecTag codec_mp4_tags
[] = {
7309 { AV_CODEC_ID_MPEG4
, MKTAG('m', 'p', '4', 'v') },
7310 { AV_CODEC_ID_H264
, MKTAG('a', 'v', 'c', '1') },
7311 { AV_CODEC_ID_H264
, MKTAG('a', 'v', 'c', '3') },
7312 { AV_CODEC_ID_HEVC
, MKTAG('h', 'e', 'v', '1') },
7313 { AV_CODEC_ID_HEVC
, MKTAG('h', 'v', 'c', '1') },
7314 { AV_CODEC_ID_MPEG2VIDEO
, MKTAG('m', 'p', '4', 'v') },
7315 { AV_CODEC_ID_MPEG1VIDEO
, MKTAG('m', 'p', '4', 'v') },
7316 { AV_CODEC_ID_MJPEG
, MKTAG('m', 'p', '4', 'v') },
7317 { AV_CODEC_ID_PNG
, MKTAG('m', 'p', '4', 'v') },
7318 { AV_CODEC_ID_JPEG2000
, MKTAG('m', 'p', '4', 'v') },
7319 { AV_CODEC_ID_VC1
, MKTAG('v', 'c', '-', '1') },
7320 { AV_CODEC_ID_DIRAC
, MKTAG('d', 'r', 'a', 'c') },
7321 { AV_CODEC_ID_TSCC2
, MKTAG('m', 'p', '4', 'v') },
7322 { AV_CODEC_ID_VP9
, MKTAG('v', 'p', '0', '9') },
7323 { AV_CODEC_ID_AV1
, MKTAG('a', 'v', '0', '1') },
7324 { AV_CODEC_ID_AAC
, MKTAG('m', 'p', '4', 'a') },
7325 { AV_CODEC_ID_ALAC
, MKTAG('a', 'l', 'a', 'c') },
7326 { AV_CODEC_ID_MP4ALS
, MKTAG('m', 'p', '4', 'a') },
7327 { AV_CODEC_ID_MP3
, MKTAG('m', 'p', '4', 'a') },
7328 { AV_CODEC_ID_MP2
, MKTAG('m', 'p', '4', 'a') },
7329 { AV_CODEC_ID_AC3
, MKTAG('a', 'c', '-', '3') },
7330 { AV_CODEC_ID_EAC3
, MKTAG('e', 'c', '-', '3') },
7331 { AV_CODEC_ID_DTS
, MKTAG('m', 'p', '4', 'a') },
7332 { AV_CODEC_ID_TRUEHD
, MKTAG('m', 'l', 'p', 'a') },
7333 { AV_CODEC_ID_FLAC
, MKTAG('f', 'L', 'a', 'C') },
7334 { AV_CODEC_ID_OPUS
, MKTAG('O', 'p', 'u', 's') },
7335 { AV_CODEC_ID_VORBIS
, MKTAG('m', 'p', '4', 'a') },
7336 { AV_CODEC_ID_QCELP
, MKTAG('m', 'p', '4', 'a') },
7337 { AV_CODEC_ID_EVRC
, MKTAG('m', 'p', '4', 'a') },
7338 { AV_CODEC_ID_DVD_SUBTITLE
, MKTAG('m', 'p', '4', 's') },
7339 { AV_CODEC_ID_MOV_TEXT
, MKTAG('t', 'x', '3', 'g') },
7340 { AV_CODEC_ID_BIN_DATA
, MKTAG('g', 'p', 'm', 'd') },
7341 { AV_CODEC_ID_MPEGH_3D_AUDIO
, MKTAG('m', 'h', 'm', '1') },
7342 { AV_CODEC_ID_TTML
, MOV_MP4_TTML_TAG
},
7343 { AV_CODEC_ID_TTML
, MOV_ISMV_TTML_TAG
},
7344 { AV_CODEC_ID_NONE
, 0 },
7346 #if CONFIG_MP4_MUXER || CONFIG_PSP_MUXER
7347 static const AVCodecTag
*const mp4_codec_tags_list
[] = { codec_mp4_tags
, NULL
};
7350 static const AVCodecTag codec_ism_tags
[] = {
7351 { AV_CODEC_ID_WMAPRO
, MKTAG('w', 'm', 'a', ' ') },
7352 { AV_CODEC_ID_TTML
, MOV_ISMV_TTML_TAG
},
7353 { AV_CODEC_ID_NONE
, 0 },
7356 static const AVCodecTag codec_ipod_tags
[] = {
7357 { AV_CODEC_ID_H264
, MKTAG('a','v','c','1') },
7358 { AV_CODEC_ID_MPEG4
, MKTAG('m','p','4','v') },
7359 { AV_CODEC_ID_AAC
, MKTAG('m','p','4','a') },
7360 { AV_CODEC_ID_ALAC
, MKTAG('a','l','a','c') },
7361 { AV_CODEC_ID_AC3
, MKTAG('a','c','-','3') },
7362 { AV_CODEC_ID_MOV_TEXT
, MKTAG('t','x','3','g') },
7363 { AV_CODEC_ID_MOV_TEXT
, MKTAG('t','e','x','t') },
7364 { AV_CODEC_ID_NONE
, 0 },
7367 static const AVCodecTag codec_f4v_tags
[] = {
7368 { AV_CODEC_ID_MP3
, MKTAG('.','m','p','3') },
7369 { AV_CODEC_ID_AAC
, MKTAG('m','p','4','a') },
7370 { AV_CODEC_ID_H264
, MKTAG('a','v','c','1') },
7371 { AV_CODEC_ID_VP6A
, MKTAG('V','P','6','A') },
7372 { AV_CODEC_ID_VP6F
, MKTAG('V','P','6','F') },
7373 { AV_CODEC_ID_NONE
, 0 },
7376 #if CONFIG_MOV_MUXER
7377 const AVOutputFormat ff_mov_muxer
= {
7379 .long_name
= NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
7380 .extensions
= "mov",
7381 .priv_data_size
= sizeof(MOVMuxContext
),
7382 .audio_codec
= AV_CODEC_ID_AAC
,
7383 .video_codec
= CONFIG_LIBX264_ENCODER
?
7384 AV_CODEC_ID_H264
: AV_CODEC_ID_MPEG4
,
7386 .write_header
= mov_write_header
,
7387 .write_packet
= mov_write_packet
,
7388 .write_trailer
= mov_write_trailer
,
7390 .flags
= AVFMT_GLOBALHEADER
| AVFMT_ALLOW_FLUSH
| AVFMT_TS_NEGATIVE
,
7391 .codec_tag
= (const AVCodecTag
* const []){
7392 ff_codec_movvideo_tags
, ff_codec_movaudio_tags
, ff_codec_movsubtitle_tags
, 0
7394 .check_bitstream
= mov_check_bitstream
,
7395 .priv_class
= &mov_isobmff_muxer_class
,
7398 #if CONFIG_TGP_MUXER
7399 const AVOutputFormat ff_tgp_muxer
= {
7401 .long_name
= NULL_IF_CONFIG_SMALL("3GP (3GPP file format)"),
7402 .extensions
= "3gp",
7403 .priv_data_size
= sizeof(MOVMuxContext
),
7404 .audio_codec
= AV_CODEC_ID_AMR_NB
,
7405 .video_codec
= AV_CODEC_ID_H263
,
7407 .write_header
= mov_write_header
,
7408 .write_packet
= mov_write_packet
,
7409 .write_trailer
= mov_write_trailer
,
7411 .flags
= AVFMT_GLOBALHEADER
| AVFMT_ALLOW_FLUSH
| AVFMT_TS_NEGATIVE
,
7412 .codec_tag
= codec_3gp_tags_list
,
7413 .check_bitstream
= mov_check_bitstream
,
7414 .priv_class
= &mov_isobmff_muxer_class
,
7417 #if CONFIG_MP4_MUXER
7418 const AVOutputFormat ff_mp4_muxer
= {
7420 .long_name
= NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"),
7421 .mime_type
= "video/mp4",
7422 .extensions
= "mp4",
7423 .priv_data_size
= sizeof(MOVMuxContext
),
7424 .audio_codec
= AV_CODEC_ID_AAC
,
7425 .video_codec
= CONFIG_LIBX264_ENCODER
?
7426 AV_CODEC_ID_H264
: AV_CODEC_ID_MPEG4
,
7428 .write_header
= mov_write_header
,
7429 .write_packet
= mov_write_packet
,
7430 .write_trailer
= mov_write_trailer
,
7432 .flags
= AVFMT_GLOBALHEADER
| AVFMT_ALLOW_FLUSH
| AVFMT_TS_NEGATIVE
,
7433 .codec_tag
= mp4_codec_tags_list
,
7434 .check_bitstream
= mov_check_bitstream
,
7435 .priv_class
= &mov_isobmff_muxer_class
,
7438 #if CONFIG_PSP_MUXER
7439 const AVOutputFormat ff_psp_muxer
= {
7441 .long_name
= NULL_IF_CONFIG_SMALL("PSP MP4 (MPEG-4 Part 14)"),
7442 .extensions
= "mp4,psp",
7443 .priv_data_size
= sizeof(MOVMuxContext
),
7444 .audio_codec
= AV_CODEC_ID_AAC
,
7445 .video_codec
= CONFIG_LIBX264_ENCODER
?
7446 AV_CODEC_ID_H264
: AV_CODEC_ID_MPEG4
,
7448 .write_header
= mov_write_header
,
7449 .write_packet
= mov_write_packet
,
7450 .write_trailer
= mov_write_trailer
,
7452 .flags
= AVFMT_GLOBALHEADER
| AVFMT_ALLOW_FLUSH
| AVFMT_TS_NEGATIVE
,
7453 .codec_tag
= mp4_codec_tags_list
,
7454 .check_bitstream
= mov_check_bitstream
,
7455 .priv_class
= &mov_isobmff_muxer_class
,
7458 #if CONFIG_TG2_MUXER
7459 const AVOutputFormat ff_tg2_muxer
= {
7461 .long_name
= NULL_IF_CONFIG_SMALL("3GP2 (3GPP2 file format)"),
7462 .extensions
= "3g2",
7463 .priv_data_size
= sizeof(MOVMuxContext
),
7464 .audio_codec
= AV_CODEC_ID_AMR_NB
,
7465 .video_codec
= AV_CODEC_ID_H263
,
7467 .write_header
= mov_write_header
,
7468 .write_packet
= mov_write_packet
,
7469 .write_trailer
= mov_write_trailer
,
7471 .flags
= AVFMT_GLOBALHEADER
| AVFMT_ALLOW_FLUSH
| AVFMT_TS_NEGATIVE
,
7472 .codec_tag
= codec_3gp_tags_list
,
7473 .check_bitstream
= mov_check_bitstream
,
7474 .priv_class
= &mov_isobmff_muxer_class
,
7477 #if CONFIG_IPOD_MUXER
7478 const AVOutputFormat ff_ipod_muxer
= {
7480 .long_name
= NULL_IF_CONFIG_SMALL("iPod H.264 MP4 (MPEG-4 Part 14)"),
7481 .mime_type
= "video/mp4",
7482 .extensions
= "m4v,m4a,m4b",
7483 .priv_data_size
= sizeof(MOVMuxContext
),
7484 .audio_codec
= AV_CODEC_ID_AAC
,
7485 .video_codec
= AV_CODEC_ID_H264
,
7487 .write_header
= mov_write_header
,
7488 .write_packet
= mov_write_packet
,
7489 .write_trailer
= mov_write_trailer
,
7491 .flags
= AVFMT_GLOBALHEADER
| AVFMT_ALLOW_FLUSH
| AVFMT_TS_NEGATIVE
,
7492 .codec_tag
= (const AVCodecTag
* const []){ codec_ipod_tags
, 0 },
7493 .check_bitstream
= mov_check_bitstream
,
7494 .priv_class
= &mov_isobmff_muxer_class
,
7497 #if CONFIG_ISMV_MUXER
7498 const AVOutputFormat ff_ismv_muxer
= {
7500 .long_name
= NULL_IF_CONFIG_SMALL("ISMV/ISMA (Smooth Streaming)"),
7501 .mime_type
= "video/mp4",
7502 .extensions
= "ismv,isma",
7503 .priv_data_size
= sizeof(MOVMuxContext
),
7504 .audio_codec
= AV_CODEC_ID_AAC
,
7505 .video_codec
= AV_CODEC_ID_H264
,
7507 .write_header
= mov_write_header
,
7508 .write_packet
= mov_write_packet
,
7509 .write_trailer
= mov_write_trailer
,
7511 .flags
= AVFMT_GLOBALHEADER
| AVFMT_ALLOW_FLUSH
| AVFMT_TS_NEGATIVE
,
7512 .codec_tag
= (const AVCodecTag
* const []){
7513 codec_mp4_tags
, codec_ism_tags
, 0 },
7514 .check_bitstream
= mov_check_bitstream
,
7515 .priv_class
= &mov_isobmff_muxer_class
,
7518 #if CONFIG_F4V_MUXER
7519 const AVOutputFormat ff_f4v_muxer
= {
7521 .long_name
= NULL_IF_CONFIG_SMALL("F4V Adobe Flash Video"),
7522 .mime_type
= "application/f4v",
7523 .extensions
= "f4v",
7524 .priv_data_size
= sizeof(MOVMuxContext
),
7525 .audio_codec
= AV_CODEC_ID_AAC
,
7526 .video_codec
= AV_CODEC_ID_H264
,
7528 .write_header
= mov_write_header
,
7529 .write_packet
= mov_write_packet
,
7530 .write_trailer
= mov_write_trailer
,
7532 .flags
= AVFMT_GLOBALHEADER
| AVFMT_ALLOW_FLUSH
,
7533 .codec_tag
= (const AVCodecTag
* const []){ codec_f4v_tags
, 0 },
7534 .check_bitstream
= mov_check_bitstream
,
7535 .priv_class
= &mov_isobmff_muxer_class
,