1 /*
2 * MOV, 3GP, MP4 muxer
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>
6 *
7 * This file is part of FFmpeg.
8 *
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.
13 *
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.
18 *
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
22 */
23
24 #include "config_components.h"
25
26 #include <stdint.h>
27 #include <inttypes.h>
28
29 #include "movenc.h"
30 #include "avformat.h"
31 #include "avio_internal.h"
32 #include "dovi_isom.h"
33 #include "riff.h"
34 #include "avio.h"
35 #include "isom.h"
36 #include "av1.h"
37 #include "avc.h"
38 #include "libavcodec/ac3_parser_internal.h"
39 #include "libavcodec/dnxhddata.h"
40 #include "libavcodec/flac.h"
41 #include "libavcodec/get_bits.h"
42
43 #include "libavcodec/internal.h"
44 #include "libavcodec/put_bits.h"
45 #include "libavcodec/vc1_common.h"
46 #include "libavcodec/raw.h"
47 #include "internal.h"
48 #include "libavutil/avstring.h"
49 #include "libavutil/channel_layout.h"
50 #include "libavutil/intfloat.h"
51 #include "libavutil/mathematics.h"
52 #include "libavutil/libm.h"
53 #include "libavutil/opt.h"
54 #include "libavutil/dict.h"
55 #include "libavutil/pixdesc.h"
56 #include "libavutil/stereo3d.h"
57 #include "libavutil/timecode.h"
58 #include "libavutil/dovi_meta.h"
59 #include "libavutil/color_utils.h"
60 #include "libavutil/uuid.h"
61 #include "hevc.h"
62 #include "rtpenc.h"
63 #include "mov_chan.h"
64 #include "movenc_ttml.h"
65 #include "mux.h"
66 #include "rawutils.h"
67 #include "ttmlenc.h"
68 #include "version.h"
69 #include "vpcc.h"
70
71 static const AVOption options[] = {
72 { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
73 { "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" },
74 { "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 },
75 { "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" },
76 { "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" },
77 { "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" },
78 { "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" },
79 { "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" },
80 { "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" },
81 { "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" },
82 { "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" },
83 { "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" },
84 { "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" },
85 { "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" },
86 { "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" },
87 { "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" },
88 { "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" },
89 { "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" },
90 { "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" },
91 { "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" },
92 { "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" },
93 { "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" },
94 { "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" },
95 { "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" },
96 { "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" },
97 #ifdef OHOS_TIMED_META_TRACK
98 { "use_timed_meta_track", "Use timed meta data track for linking metadata to another track", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_TIMED_METADATA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
99 #endif
100 FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
101 { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
102 { "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},
103 { "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},
104 { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext, max_fragment_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
105 { "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},
106 { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
107 { "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},
108 { "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},
109 { "brand", "Override major brand", offsetof(MOVMuxContext, major_brand), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM },
110 { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
111 { "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},
112 { "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},
113 { "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 },
114 { "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 },
115 { "encryption_key", "The media encryption key (hex)", offsetof(MOVMuxContext, encryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM },
116 { "encryption_kid", "The media encryption key identifier (hex)", offsetof(MOVMuxContext, encryption_kid), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM },
117 { "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},
118 { "write_btrt", "force or disable writing btrt", offsetof(MOVMuxContext, write_btrt), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
119 { "write_tmcd", "force or disable writing tmcd", offsetof(MOVMuxContext, write_tmcd), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
120 { "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"},
121 { "wallclock", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_WALLCLOCK}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "prft"},
122 { "pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_PTS}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "prft"},
123 { "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},
124 { "movie_timescale", "set movie timescale", offsetof(MOVMuxContext, movie_timescale), AV_OPT_TYPE_INT, {.i64 = MOV_TIMESCALE}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
125 { NULL },
126 };
127
128 static const AVClass mov_isobmff_muxer_class = {
129 .class_name = "mov/mp4/tgp/psp/tg2/ipod/ismv/f4v muxer",
130 .item_name = av_default_item_name,
131 .option = options,
132 .version = LIBAVUTIL_VERSION_INT,
133 };
134
135 #ifdef OHOS_HDR_VIVID
136 typedef struct CuvaConfig {
137 int cuva_version_map;
138 int terminal_provide_code;
139 int terminal_provide_oriented_code;
140 } CuvaConfig;
141 #endif
142
143 static int get_moov_size(AVFormatContext *s);
144 static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt);
145
utf8len(const uint8_t *b)146 static int utf8len(const uint8_t *b)
147 {
148 int len = 0;
149 int val;
150 while (*b) {
151 GET_UTF8(val, *b++, return -1;)
152 len++;
153 }
154 return len;
155 }
156
157 //FIXME support 64 bit variant with wide placeholders
update_size(AVIOContext *pb, int64_t pos)158 static int64_t update_size(AVIOContext *pb, int64_t pos)
159 {
160 int64_t curpos = avio_tell(pb);
161 avio_seek(pb, pos, SEEK_SET);
162 avio_wb32(pb, curpos - pos); /* rewrite size */
163 avio_seek(pb, curpos, SEEK_SET);
164
165 return curpos - pos;
166 }
167
co64_required(const MOVTrack *track)168 static int co64_required(const MOVTrack *track)
169 {
170 if (track->entry > 0 && track->cluster[track->entry - 1].pos + track->data_offset > UINT32_MAX)
171 return 1;
172 return 0;
173 }
174
is_cover_image(const AVStream *st)175 static int is_cover_image(const AVStream *st)
176 {
177 /* Eg. AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS
178 * is encoded as sparse video track */
179 return st && st->disposition == AV_DISPOSITION_ATTACHED_PIC;
180 }
181
rtp_hinting_needed(const AVStream *st)182 static int rtp_hinting_needed(const AVStream *st)
183 {
184 /* Add hint tracks for each real audio and video stream */
185 if (is_cover_image(st))
186 return 0;
187 return st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
188 st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO;
189 }
190
191 /* Chunk offset atom */
mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)192 static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)
193 {
194 int i;
195 int mode64 = co64_required(track); // use 32 bit size variant if possible
196 int64_t pos = avio_tell(pb);
197 avio_wb32(pb, 0); /* size */
198 if (mode64)
199 ffio_wfourcc(pb, "co64");
200 else
201 ffio_wfourcc(pb, "stco");
202 avio_wb32(pb, 0); /* version & flags */
203 avio_wb32(pb, track->chunkCount); /* entry count */
204 for (i = 0; i < track->entry; i++) {
205 if (!track->cluster[i].chunkNum)
206 continue;
207 if (mode64 == 1)
208 avio_wb64(pb, track->cluster[i].pos + track->data_offset);
209 else
210 avio_wb32(pb, track->cluster[i].pos + track->data_offset);
211 }
212 return update_size(pb, pos);
213 }
214
215 /* Sample size atom */
mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)216 static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)
217 {
218 int equalChunks = 1;
219 int i, j, entries = 0, tst = -1, oldtst = -1;
220
221 int64_t pos = avio_tell(pb);
222 avio_wb32(pb, 0); /* size */
223 ffio_wfourcc(pb, "stsz");
224 avio_wb32(pb, 0); /* version & flags */
225
226 for (i = 0; i < track->entry; i++) {
227 tst = track->cluster[i].size / track->cluster[i].entries;
228 if (oldtst != -1 && tst != oldtst)
229 equalChunks = 0;
230 oldtst = tst;
231 entries += track->cluster[i].entries;
232 }
233 if (equalChunks && track->entry) {
234 int sSize = track->entry ? track->cluster[0].size / track->cluster[0].entries : 0;
235 sSize = FFMAX(1, sSize); // adpcm mono case could make sSize == 0
236 avio_wb32(pb, sSize); // sample size
237 avio_wb32(pb, entries); // sample count
238 } else {
239 avio_wb32(pb, 0); // sample size
240 avio_wb32(pb, entries); // sample count
241 for (i = 0; i < track->entry; i++) {
242 for (j = 0; j < track->cluster[i].entries; j++) {
243 avio_wb32(pb, track->cluster[i].size /
244 track->cluster[i].entries);
245 }
246 }
247 }
248 return update_size(pb, pos);
249 }
250
251 /* Sample to chunk atom */
mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track)252 static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track)
253 {
254 int index = 0, oldval = -1, i;
255 int64_t entryPos, curpos;
256
257 int64_t pos = avio_tell(pb);
258 avio_wb32(pb, 0); /* size */
259 ffio_wfourcc(pb, "stsc");
260 avio_wb32(pb, 0); // version & flags
261 entryPos = avio_tell(pb);
262 avio_wb32(pb, track->chunkCount); // entry count
263 for (i = 0; i < track->entry; i++) {
264 if (oldval != track->cluster[i].samples_in_chunk && track->cluster[i].chunkNum) {
265 avio_wb32(pb, track->cluster[i].chunkNum); // first chunk
266 avio_wb32(pb, track->cluster[i].samples_in_chunk); // samples per chunk
267 avio_wb32(pb, 0x1); // sample description index
268 oldval = track->cluster[i].samples_in_chunk;
269 index++;
270 }
271 }
272 curpos = avio_tell(pb);
273 avio_seek(pb, entryPos, SEEK_SET);
274 avio_wb32(pb, index); // rewrite size
275 avio_seek(pb, curpos, SEEK_SET);
276
277 return update_size(pb, pos);
278 }
279
280 /* Sync sample atom */
mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)281 static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)
282 {
283 int64_t curpos, entryPos;
284 int i, index = 0;
285 int64_t pos = avio_tell(pb);
286 avio_wb32(pb, 0); // size
287 ffio_wfourcc(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps");
288 avio_wb32(pb, 0); // version & flags
289 entryPos = avio_tell(pb);
290 avio_wb32(pb, track->entry); // entry count
291 for (i = 0; i < track->entry; i++) {
292 if (track->cluster[i].flags & flag) {
293 avio_wb32(pb, i + 1);
294 index++;
295 }
296 }
297 curpos = avio_tell(pb);
298 avio_seek(pb, entryPos, SEEK_SET);
299 avio_wb32(pb, index); // rewrite size
300 avio_seek(pb, curpos, SEEK_SET);
301 return update_size(pb, pos);
302 }
303
304 /* Sample dependency atom */
mov_write_sdtp_tag(AVIOContext *pb, MOVTrack *track)305 static int mov_write_sdtp_tag(AVIOContext *pb, MOVTrack *track)
306 {
307 int i;
308 uint8_t leading, dependent, reference, redundancy;
309 int64_t pos = avio_tell(pb);
310 avio_wb32(pb, 0); // size
311 ffio_wfourcc(pb, "sdtp");
312 avio_wb32(pb, 0); // version & flags
313 for (i = 0; i < track->entry; i++) {
314 dependent = MOV_SAMPLE_DEPENDENCY_YES;
315 leading = reference = redundancy = MOV_SAMPLE_DEPENDENCY_UNKNOWN;
316 if (track->cluster[i].flags & MOV_DISPOSABLE_SAMPLE) {
317 reference = MOV_SAMPLE_DEPENDENCY_NO;
318 #ifdef OHOS_SDTP_BOX_EXT
319 } else if (track->cluster[i].flags & MOV_DISPOSABLE_EXT_SAMPLE) {
320 reference = MOV_SAMPLE_DEPENDENCY_EXT;
321 #endif
322 }
323 if (track->cluster[i].flags & MOV_SYNC_SAMPLE) {
324 dependent = MOV_SAMPLE_DEPENDENCY_NO;
325 }
326 avio_w8(pb, (leading << 6) | (dependent << 4) |
327 (reference << 2) | redundancy);
328 }
329 return update_size(pb, pos);
330 }
331
mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)332 static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
333 {
334 avio_wb32(pb, 0x11); /* size */
335 if (track->mode == MODE_MOV) ffio_wfourcc(pb, "samr");
336 else ffio_wfourcc(pb, "damr");
337 ffio_wfourcc(pb, "FFMP");
338 avio_w8(pb, 0); /* decoder version */
339
340 avio_wb16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */
341 avio_w8(pb, 0x00); /* Mode change period (no restriction) */
342 avio_w8(pb, 0x01); /* Frames per sample */
343 return 0x11;
344 }
345
346 struct eac3_info {
347 AVPacket *pkt;
348 uint8_t ec3_done;
349 uint8_t num_blocks;
350
351 /* Layout of the EC3SpecificBox */
352 /* maximum bitrate */
353 uint16_t data_rate;
354 int8_t ac3_bit_rate_code;
355 /* number of independent substreams */
356 uint8_t num_ind_sub;
357 struct {
358 /* sample rate code (see ff_ac3_sample_rate_tab) 2 bits */
359 uint8_t fscod;
360 /* bit stream identification 5 bits */
361 uint8_t bsid;
362 /* one bit reserved */
363 /* audio service mixing (not supported yet) 1 bit */
364 /* bit stream mode 3 bits */
365 uint8_t bsmod;
366 /* audio coding mode 3 bits */
367 uint8_t acmod;
368 /* sub woofer on 1 bit */
369 uint8_t lfeon;
370 /* 3 bits reserved */
371 /* number of dependent substreams associated with this substream 4 bits */
372 uint8_t num_dep_sub;
373 /* channel locations of the dependent substream(s), if any, 9 bits */
374 uint16_t chan_loc;
375 /* if there is no dependent substream, then one bit reserved instead */
376 } substream[1]; /* TODO: support 8 independent substreams */
377 };
378
mov_write_ac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)379 static int mov_write_ac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
380 {
381 struct eac3_info *info = track->eac3_priv;
382 PutBitContext pbc;
383 uint8_t buf[3];
384
385 if (!info || !info->ec3_done) {
386 av_log(s, AV_LOG_ERROR,
387 "Cannot write moov atom before AC3 packets."
388 " Set the delay_moov flag to fix this.\n");
389 return AVERROR(EINVAL);
390 }
391
392 if (info->substream[0].bsid > 8) {
393 av_log(s, AV_LOG_ERROR,
394 "RealAudio AC-3/DolbyNet with bsid %d is not defined by the "
395 "ISOBMFF specification in ETSI TS 102 366!\n",
396 info->substream[0].bsid);
397 return AVERROR(EINVAL);
398 }
399
400 if (info->ac3_bit_rate_code < 0) {
401 av_log(s, AV_LOG_ERROR,
402 "No valid AC3 bit rate code for data rate of %d!\n",
403 info->data_rate);
404 return AVERROR(EINVAL);
405 }
406
407 avio_wb32(pb, 11);
408 ffio_wfourcc(pb, "dac3");
409
410 init_put_bits(&pbc, buf, sizeof(buf));
411 put_bits(&pbc, 2, info->substream[0].fscod);
412 put_bits(&pbc, 5, info->substream[0].bsid);
413 put_bits(&pbc, 3, info->substream[0].bsmod);
414 put_bits(&pbc, 3, info->substream[0].acmod);
415 put_bits(&pbc, 1, info->substream[0].lfeon);
416 put_bits(&pbc, 5, info->ac3_bit_rate_code); // bit_rate_code
417 put_bits(&pbc, 5, 0); // reserved
418
419 flush_put_bits(&pbc);
420 avio_write(pb, buf, sizeof(buf));
421
422 return 11;
423 }
424
handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)425 static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
426 {
427 AC3HeaderInfo *hdr = NULL;
428 struct eac3_info *info;
429 int num_blocks, ret;
430
431 if (!track->eac3_priv) {
432 if (!(track->eac3_priv = av_mallocz(sizeof(*info))))
433 return AVERROR(ENOMEM);
434
435 ((struct eac3_info *)track->eac3_priv)->ac3_bit_rate_code = -1;
436 }
437 info = track->eac3_priv;
438
439 if (!info->pkt && !(info->pkt = av_packet_alloc()))
440 return AVERROR(ENOMEM);
441
442 if ((ret = avpriv_ac3_parse_header(&hdr, pkt->data, pkt->size)) < 0) {
443 if (ret == AVERROR(ENOMEM))
444 goto end;
445
446 /* drop the packets until we see a good one */
447 if (!track->entry) {
448 av_log(mov->fc, AV_LOG_WARNING, "Dropping invalid packet from start of the stream\n");
449 ret = 0;
450 } else
451 ret = AVERROR_INVALIDDATA;
452 goto end;
453 }
454
455 info->data_rate = FFMAX(info->data_rate, hdr->bit_rate / 1000);
456 info->ac3_bit_rate_code = FFMAX(info->ac3_bit_rate_code,
457 hdr->ac3_bit_rate_code);
458 num_blocks = hdr->num_blocks;
459
460 if (!info->ec3_done) {
461 /* AC-3 substream must be the first one */
462 if (hdr->bitstream_id <= 10 && hdr->substreamid != 0) {
463 ret = AVERROR(EINVAL);
464 goto end;
465 }
466
467 /* this should always be the case, given that our AC-3 parser
468 * concatenates dependent frames to their independent parent */
469 if (hdr->frame_type == EAC3_FRAME_TYPE_INDEPENDENT ||
470 hdr->frame_type == EAC3_FRAME_TYPE_AC3_CONVERT) {
471 /* substream ids must be incremental */
472 if (hdr->substreamid > info->num_ind_sub + 1) {
473 ret = AVERROR(EINVAL);
474 goto end;
475 }
476
477 if (hdr->substreamid == info->num_ind_sub + 1) {
478 //info->num_ind_sub++;
479 avpriv_request_sample(mov->fc, "Multiple independent substreams");
480 ret = AVERROR_PATCHWELCOME;
481 goto end;
482 } else if (hdr->substreamid < info->num_ind_sub ||
483 hdr->substreamid == 0 && info->substream[0].bsid) {
484 info->ec3_done = 1;
485 goto concatenate;
486 }
487 } else {
488 if (hdr->substreamid != 0) {
489 avpriv_request_sample(mov->fc, "Multiple non EAC3 independent substreams");
490 ret = AVERROR_PATCHWELCOME;
491 goto end;
492 }
493 }
494
495 /* fill the info needed for the "dec3" atom */
496 info->substream[hdr->substreamid].fscod = hdr->sr_code;
497 info->substream[hdr->substreamid].bsid = hdr->bitstream_id;
498 info->substream[hdr->substreamid].bsmod = hdr->bitstream_mode;
499 info->substream[hdr->substreamid].acmod = hdr->channel_mode;
500 info->substream[hdr->substreamid].lfeon = hdr->lfe_on;
501
502 if (track->par->codec_id == AV_CODEC_ID_AC3) {
503 // with AC-3 we only require the information of a single packet,
504 // so we can finish as soon as the basic values of the bit stream
505 // have been set to the track's informational structure.
506 info->ec3_done = 1;
507 goto concatenate;
508 }
509
510 /* Parse dependent substream(s), if any */
511 if (pkt->size != hdr->frame_size) {
512 int cumul_size = hdr->frame_size;
513 int parent = hdr->substreamid;
514
515 while (cumul_size != pkt->size) {
516 GetBitContext gbc;
517 int i;
518 ret = avpriv_ac3_parse_header(&hdr, pkt->data + cumul_size, pkt->size - cumul_size);
519 if (ret < 0)
520 goto end;
521 if (hdr->frame_type != EAC3_FRAME_TYPE_DEPENDENT) {
522 ret = AVERROR(EINVAL);
523 goto end;
524 }
525 info->substream[parent].num_dep_sub++;
526 ret /= 8;
527
528 /* header is parsed up to lfeon, but custom channel map may be needed */
529 init_get_bits8(&gbc, pkt->data + cumul_size + ret, pkt->size - cumul_size - ret);
530 /* skip bsid */
531 skip_bits(&gbc, 5);
532 /* skip volume control params */
533 for (i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
534 skip_bits(&gbc, 5); // skip dialog normalization
535 if (get_bits1(&gbc)) {
536 skip_bits(&gbc, 8); // skip compression gain word
537 }
538 }
539 /* get the dependent stream channel map, if exists */
540 if (get_bits1(&gbc))
541 info->substream[parent].chan_loc |= (get_bits(&gbc, 16) >> 5) & 0x1f;
542 else
543 info->substream[parent].chan_loc |= hdr->channel_mode;
544 cumul_size += hdr->frame_size;
545 }
546 }
547 }
548
549 concatenate:
550 if (!info->num_blocks && num_blocks == 6) {
551 ret = pkt->size;
552 goto end;
553 }
554 else if (info->num_blocks + num_blocks > 6) {
555 ret = AVERROR_INVALIDDATA;
556 goto end;
557 }
558
559 if (!info->num_blocks) {
560 ret = av_packet_ref(info->pkt, pkt);
561 if (!ret)
562 info->num_blocks = num_blocks;
563 goto end;
564 } else {
565 if ((ret = av_grow_packet(info->pkt, pkt->size)) < 0)
566 goto end;
567 memcpy(info->pkt->data + info->pkt->size - pkt->size, pkt->data, pkt->size);
568 info->num_blocks += num_blocks;
569 info->pkt->duration += pkt->duration;
570 if (info->num_blocks != 6)
571 goto end;
572 av_packet_unref(pkt);
573 av_packet_move_ref(pkt, info->pkt);
574 info->num_blocks = 0;
575 }
576 ret = pkt->size;
577
578 end:
579 av_free(hdr);
580
581 return ret;
582 }
583
mov_write_eac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)584 static int mov_write_eac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
585 {
586 PutBitContext pbc;
587 uint8_t *buf;
588 struct eac3_info *info;
589 int size, i;
590
591 if (!track->eac3_priv) {
592 av_log(s, AV_LOG_ERROR,
593 "Cannot write moov atom before EAC3 packets parsed.\n");
594 return AVERROR(EINVAL);
595 }
596
597 info = track->eac3_priv;
598 size = 2 + ((34 * (info->num_ind_sub + 1) + 7) >> 3);
599 buf = av_malloc(size);
600 if (!buf) {
601 return AVERROR(ENOMEM);
602 }
603
604 init_put_bits(&pbc, buf, size);
605 put_bits(&pbc, 13, info->data_rate);
606 put_bits(&pbc, 3, info->num_ind_sub);
607 for (i = 0; i <= info->num_ind_sub; i++) {
608 put_bits(&pbc, 2, info->substream[i].fscod);
609 put_bits(&pbc, 5, info->substream[i].bsid);
610 put_bits(&pbc, 1, 0); /* reserved */
611 put_bits(&pbc, 1, 0); /* asvc */
612 put_bits(&pbc, 3, info->substream[i].bsmod);
613 put_bits(&pbc, 3, info->substream[i].acmod);
614 put_bits(&pbc, 1, info->substream[i].lfeon);
615 put_bits(&pbc, 5, 0); /* reserved */
616 put_bits(&pbc, 4, info->substream[i].num_dep_sub);
617 if (!info->substream[i].num_dep_sub) {
618 put_bits(&pbc, 1, 0); /* reserved */
619 } else {
620 put_bits(&pbc, 9, info->substream[i].chan_loc);
621 }
622 }
623 flush_put_bits(&pbc);
624 size = put_bytes_output(&pbc);
625
626 avio_wb32(pb, size + 8);
627 ffio_wfourcc(pb, "dec3");
628 avio_write(pb, buf, size);
629
630 av_free(buf);
631
632 return size;
633 }
634
635 /**
636 * This function writes extradata "as is".
637 * Extradata must be formatted like a valid atom (with size and tag).
638 */
mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)639 static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)
640 {
641 avio_write(pb, track->par->extradata, track->par->extradata_size);
642 return track->par->extradata_size;
643 }
644
mov_write_enda_tag(AVIOContext *pb)645 static int mov_write_enda_tag(AVIOContext *pb)
646 {
647 avio_wb32(pb, 10);
648 ffio_wfourcc(pb, "enda");
649 avio_wb16(pb, 1); /* little endian */
650 return 10;
651 }
652
mov_write_enda_tag_be(AVIOContext *pb)653 static int mov_write_enda_tag_be(AVIOContext *pb)
654 {
655 avio_wb32(pb, 10);
656 ffio_wfourcc(pb, "enda");
657 avio_wb16(pb, 0); /* big endian */
658 return 10;
659 }
660
put_descr(AVIOContext *pb, int tag, unsigned int size)661 static void put_descr(AVIOContext *pb, int tag, unsigned int size)
662 {
663 int i = 3;
664 avio_w8(pb, tag);
665 for (; i > 0; i--)
666 avio_w8(pb, (size >> (7 * i)) | 0x80);
667 avio_w8(pb, size & 0x7F);
668 }
669
compute_avg_bitrate(MOVTrack *track)670 static unsigned compute_avg_bitrate(MOVTrack *track)
671 {
672 uint64_t size = 0;
673 int i;
674 if (!track->track_duration)
675 return 0;
676 for (i = 0; i < track->entry; i++)
677 size += track->cluster[i].size;
678 return size * 8 * track->timescale / track->track_duration;
679 }
680
681 struct mpeg4_bit_rate_values {
682 uint32_t buffer_size; ///< Size of the decoding buffer for the elementary stream in bytes.
683 uint32_t max_bit_rate; ///< Maximum rate in bits/second over any window of one second.
684 uint32_t avg_bit_rate; ///< Average rate in bits/second over the entire presentation.
685 };
686
calculate_mpeg4_bit_rates(MOVTrack *track)687 static struct mpeg4_bit_rate_values calculate_mpeg4_bit_rates(MOVTrack *track)
688 {
689 AVCPBProperties *props = track->st ?
690 (AVCPBProperties*)av_stream_get_side_data(track->st,
691 AV_PKT_DATA_CPB_PROPERTIES,
692 NULL) :
693 NULL;
694 struct mpeg4_bit_rate_values bit_rates = { 0 };
695
696 bit_rates.avg_bit_rate = compute_avg_bitrate(track);
697 if (!bit_rates.avg_bit_rate) {
698 // if the average bit rate cannot be calculated at this point, such as
699 // in the case of fragmented MP4, utilize the following values as
700 // fall-back in priority order:
701 //
702 // 1. average bit rate property
703 // 2. bit rate (usually average over the whole clip)
704 // 3. maximum bit rate property
705
706 if (props && props->avg_bitrate) {
707 bit_rates.avg_bit_rate = props->avg_bitrate;
708 } else if (track->par->bit_rate) {
709 bit_rates.avg_bit_rate = track->par->bit_rate;
710 } else if (props && props->max_bitrate) {
711 bit_rates.avg_bit_rate = props->max_bitrate;
712 }
713 }
714
715 // (FIXME should be max rate in any 1 sec window)
716 bit_rates.max_bit_rate = FFMAX(track->par->bit_rate,
717 bit_rates.avg_bit_rate);
718
719 // utilize values from properties if we have them available
720 if (props) {
721 bit_rates.max_bit_rate = FFMAX(bit_rates.max_bit_rate,
722 props->max_bitrate);
723 bit_rates.buffer_size = props->buffer_size / 8;
724 }
725
726 return bit_rates;
727 }
728
mov_write_esds_tag(AVIOContext *pb, MOVTrack *track)729 static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
730 {
731 struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track);
732 int64_t pos = avio_tell(pb);
733 int decoder_specific_info_len = track->vos_len ? 5 + track->vos_len : 0;
734
735 avio_wb32(pb, 0); // size
736 ffio_wfourcc(pb, "esds");
737 avio_wb32(pb, 0); // Version
738
739 // ES descriptor
740 put_descr(pb, 0x03, 3 + 5+13 + decoder_specific_info_len + 5+1);
741 avio_wb16(pb, track->track_id);
742 avio_w8(pb, 0x00); // flags (= no flags)
743
744 // DecoderConfig descriptor
745 put_descr(pb, 0x04, 13 + decoder_specific_info_len);
746
747 // Object type indication
748 if ((track->par->codec_id == AV_CODEC_ID_MP2 ||
749 track->par->codec_id == AV_CODEC_ID_MP3) &&
750 track->par->sample_rate > 24000)
751 avio_w8(pb, 0x6B); // 11172-3
752 else
753 avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->par->codec_id));
754
755 // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
756 // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
757 if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
758 avio_w8(pb, (0x38 << 2) | 1); // flags (= NeroSubpicStream)
759 else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
760 avio_w8(pb, 0x15); // flags (= Audiostream)
761 else
762 avio_w8(pb, 0x11); // flags (= Visualstream)
763
764 avio_wb24(pb, bit_rates.buffer_size); // Buffersize DB
765 avio_wb32(pb, bit_rates.max_bit_rate); // maxbitrate
766 avio_wb32(pb, bit_rates.avg_bit_rate);
767
768 if (track->vos_len) {
769 // DecoderSpecific info descriptor
770 put_descr(pb, 0x05, track->vos_len);
771 avio_write(pb, track->vos_data, track->vos_len);
772 }
773
774 // SL descriptor
775 put_descr(pb, 0x06, 1);
776 avio_w8(pb, 0x02);
777 return update_size(pb, pos);
778 }
779
mov_pcm_le_gt16(enum AVCodecID codec_id)780 static int mov_pcm_le_gt16(enum AVCodecID codec_id)
781 {
782 return codec_id == AV_CODEC_ID_PCM_S24LE ||
783 codec_id == AV_CODEC_ID_PCM_S32LE ||
784 codec_id == AV_CODEC_ID_PCM_F32LE ||
785 codec_id == AV_CODEC_ID_PCM_F64LE;
786 }
787
mov_pcm_be_gt16(enum AVCodecID codec_id)788 static int mov_pcm_be_gt16(enum AVCodecID codec_id)
789 {
790 return codec_id == AV_CODEC_ID_PCM_S24BE ||
791 codec_id == AV_CODEC_ID_PCM_S32BE ||
792 codec_id == AV_CODEC_ID_PCM_F32BE ||
793 codec_id == AV_CODEC_ID_PCM_F64BE;
794 }
795
mov_write_ms_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)796 static int mov_write_ms_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
797 {
798 int ret;
799 int64_t pos = avio_tell(pb);
800 avio_wb32(pb, 0);
801 avio_wl32(pb, track->tag); // store it byteswapped
802 track->par->codec_tag = av_bswap16(track->tag >> 16);
803 if ((ret = ff_put_wav_header(s, pb, track->par, 0)) < 0)
804 return ret;
805 return update_size(pb, pos);
806 }
807
mov_write_wfex_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)808 static int mov_write_wfex_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
809 {
810 int ret;
811 int64_t pos = avio_tell(pb);
812 avio_wb32(pb, 0);
813 ffio_wfourcc(pb, "wfex");
814 if ((ret = ff_put_wav_header(s, pb, track->st->codecpar, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX)) < 0)
815 return ret;
816 return update_size(pb, pos);
817 }
818
mov_write_dfla_tag(AVIOContext *pb, MOVTrack *track)819 static int mov_write_dfla_tag(AVIOContext *pb, MOVTrack *track)
820 {
821 int64_t pos = avio_tell(pb);
822 avio_wb32(pb, 0);
823 ffio_wfourcc(pb, "dfLa");
824 avio_w8(pb, 0); /* version */
825 avio_wb24(pb, 0); /* flags */
826
827 /* Expect the encoder to pass a METADATA_BLOCK_TYPE_STREAMINFO. */
828 if (track->par->extradata_size != FLAC_STREAMINFO_SIZE)
829 return AVERROR_INVALIDDATA;
830
831 /* TODO: Write other METADATA_BLOCK_TYPEs if the encoder makes them available. */
832 avio_w8(pb, 1 << 7 | FLAC_METADATA_TYPE_STREAMINFO); /* LastMetadataBlockFlag << 7 | BlockType */
833 avio_wb24(pb, track->par->extradata_size); /* Length */
834 avio_write(pb, track->par->extradata, track->par->extradata_size); /* BlockData[Length] */
835
836 return update_size(pb, pos);
837 }
838
mov_write_dops_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)839 static int mov_write_dops_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
840 {
841 int64_t pos = avio_tell(pb);
842 int channels, channel_map;
843 avio_wb32(pb, 0);
844 ffio_wfourcc(pb, "dOps");
845 avio_w8(pb, 0); /* Version */
846 if (track->par->extradata_size < 19) {
847 av_log(s, AV_LOG_ERROR, "invalid extradata size\n");
848 return AVERROR_INVALIDDATA;
849 }
850 /* extradata contains an Ogg OpusHead, other than byte-ordering and
851 OpusHead's preceeding magic/version, OpusSpecificBox is currently
852 identical. */
853 channels = AV_RB8(track->par->extradata + 9);
854 channel_map = AV_RB8(track->par->extradata + 18);
855
856 avio_w8(pb, channels); /* OuputChannelCount */
857 avio_wb16(pb, AV_RL16(track->par->extradata + 10)); /* PreSkip */
858 avio_wb32(pb, AV_RL32(track->par->extradata + 12)); /* InputSampleRate */
859 avio_wb16(pb, AV_RL16(track->par->extradata + 16)); /* OutputGain */
860 avio_w8(pb, channel_map); /* ChannelMappingFamily */
861 /* Write the rest of the header out without byte-swapping. */
862 if (channel_map) {
863 if (track->par->extradata_size < 21 + channels) {
864 av_log(s, AV_LOG_ERROR, "invalid extradata size\n");
865 return AVERROR_INVALIDDATA;
866 }
867 avio_write(pb, track->par->extradata + 19, 2 + channels); /* ChannelMappingTable */
868 }
869
870 return update_size(pb, pos);
871 }
872
mov_write_dmlp_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)873 static int mov_write_dmlp_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
874 {
875 int64_t pos = avio_tell(pb);
876 int length;
877 avio_wb32(pb, 0);
878 ffio_wfourcc(pb, "dmlp");
879
880 if (track->vos_len < 20) {
881 av_log(s, AV_LOG_ERROR,
882 "Cannot write moov atom before TrueHD packets."
883 " Set the delay_moov flag to fix this.\n");
884 return AVERROR(EINVAL);
885 }
886
887 length = (AV_RB16(track->vos_data) & 0xFFF) * 2;
888 if (length < 20 || length > track->vos_len)
889 return AVERROR_INVALIDDATA;
890
891 // Only TrueHD is supported
892 if (AV_RB32(track->vos_data + 4) != 0xF8726FBA)
893 return AVERROR_INVALIDDATA;
894
895 avio_wb32(pb, AV_RB32(track->vos_data + 8)); /* format_info */
896 avio_wb16(pb, AV_RB16(track->vos_data + 18) << 1); /* peak_data_rate */
897 avio_wb32(pb, 0); /* reserved */
898
899 return update_size(pb, pos);
900 }
901
mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)902 static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
903 {
904 uint32_t layout_tag, bitmap, *channel_desc;
905 int64_t pos = avio_tell(pb);
906 int num_desc, ret;
907
908 if (track->multichannel_as_mono)
909 return 0;
910
911 ret = ff_mov_get_channel_layout_tag(track->par, &layout_tag,
912 &bitmap, &channel_desc);
913
914 if (ret < 0) {
915 if (ret == AVERROR(ENOSYS)) {
916 av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to "
917 "lack of channel information\n");
918 ret = 0;
919 }
920
921 return ret;
922 }
923
924 if (layout_tag == MOV_CH_LAYOUT_MONO && track->mono_as_fc > 0) {
925 av_assert0(!channel_desc);
926 channel_desc = av_malloc(sizeof(*channel_desc));
927 if (!channel_desc)
928 return AVERROR(ENOMEM);
929
930 layout_tag = 0;
931 bitmap = 0;
932 *channel_desc = 3; // channel label "Center"
933 }
934
935 num_desc = layout_tag ? 0 : track->par->ch_layout.nb_channels;
936
937 avio_wb32(pb, 0); // Size
938 ffio_wfourcc(pb, "chan"); // Type
939 avio_w8(pb, 0); // Version
940 avio_wb24(pb, 0); // Flags
941 avio_wb32(pb, layout_tag); // mChannelLayoutTag
942 avio_wb32(pb, bitmap); // mChannelBitmap
943 avio_wb32(pb, num_desc); // mNumberChannelDescriptions
944
945 for (int i = 0; i < num_desc; i++) {
946 avio_wb32(pb, channel_desc[i]); // mChannelLabel
947 avio_wb32(pb, 0); // mChannelFlags
948 avio_wl32(pb, 0); // mCoordinates[0]
949 avio_wl32(pb, 0); // mCoordinates[1]
950 avio_wl32(pb, 0); // mCoordinates[2]
951 }
952
953 av_free(channel_desc);
954
955 return update_size(pb, pos);
956 }
957
mov_write_wave_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)958 static int mov_write_wave_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
959 {
960 int64_t pos = avio_tell(pb);
961
962 avio_wb32(pb, 0); /* size */
963 ffio_wfourcc(pb, "wave");
964
965 if (track->par->codec_id != AV_CODEC_ID_QDM2) {
966 avio_wb32(pb, 12); /* size */
967 ffio_wfourcc(pb, "frma");
968 avio_wl32(pb, track->tag);
969 }
970
971 if (track->par->codec_id == AV_CODEC_ID_AAC) {
972 /* useless atom needed by mplayer, ipod, not needed by quicktime */
973 avio_wb32(pb, 12); /* size */
974 ffio_wfourcc(pb, "mp4a");
975 avio_wb32(pb, 0);
976 mov_write_esds_tag(pb, track);
977 } else if (mov_pcm_le_gt16(track->par->codec_id)) {
978 mov_write_enda_tag(pb);
979 } else if (mov_pcm_be_gt16(track->par->codec_id)) {
980 mov_write_enda_tag_be(pb);
981 } else if (track->par->codec_id == AV_CODEC_ID_AMR_NB) {
982 mov_write_amr_tag(pb, track);
983 } else if (track->par->codec_id == AV_CODEC_ID_AC3) {
984 mov_write_ac3_tag(s, pb, track);
985 } else if (track->par->codec_id == AV_CODEC_ID_EAC3) {
986 mov_write_eac3_tag(s, pb, track);
987 } else if (track->par->codec_id == AV_CODEC_ID_ALAC ||
988 track->par->codec_id == AV_CODEC_ID_QDM2) {
989 mov_write_extradata_tag(pb, track);
990 } else if (track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
991 track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
992 mov_write_ms_tag(s, pb, track);
993 }
994
995 avio_wb32(pb, 8); /* size */
996 avio_wb32(pb, 0); /* null tag */
997
998 return update_size(pb, pos);
999 }
1000
mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf)1001 static int mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf)
1002 {
1003 uint8_t *unescaped;
1004 const uint8_t *start, *next, *end = track->vos_data + track->vos_len;
1005 int unescaped_size, seq_found = 0;
1006 int level = 0, interlace = 0;
1007 int packet_seq = track->vc1_info.packet_seq;
1008 int packet_entry = track->vc1_info.packet_entry;
1009 int slices = track->vc1_info.slices;
1010 PutBitContext pbc;
1011
1012 if (track->start_dts == AV_NOPTS_VALUE) {
1013 /* No packets written yet, vc1_info isn't authoritative yet. */
1014 /* Assume inline sequence and entry headers. */
1015 packet_seq = packet_entry = 1;
1016 av_log(NULL, AV_LOG_WARNING,
1017 "moov atom written before any packets, unable to write correct "
1018 "dvc1 atom. Set the delay_moov flag to fix this.\n");
1019 }
1020
1021 unescaped = av_mallocz(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
1022 if (!unescaped)
1023 return AVERROR(ENOMEM);
1024 start = find_next_marker(track->vos_data, end);
1025 for (next = start; next < end; start = next) {
1026 GetBitContext gb;
1027 int size;
1028 next = find_next_marker(start + 4, end);
1029 size = next - start - 4;
1030 if (size <= 0)
1031 continue;
1032 unescaped_size = vc1_unescape_buffer(start + 4, size, unescaped);
1033 init_get_bits(&gb, unescaped, 8 * unescaped_size);
1034 if (AV_RB32(start) == VC1_CODE_SEQHDR) {
1035 int profile = get_bits(&gb, 2);
1036 if (profile != PROFILE_ADVANCED) {
1037 av_free(unescaped);
1038 return AVERROR(ENOSYS);
1039 }
1040 seq_found = 1;
1041 level = get_bits(&gb, 3);
1042 /* chromaformat, frmrtq_postproc, bitrtq_postproc, postprocflag,
1043 * width, height */
1044 skip_bits_long(&gb, 2 + 3 + 5 + 1 + 2*12);
1045 skip_bits(&gb, 1); /* broadcast */
1046 interlace = get_bits1(&gb);
1047 skip_bits(&gb, 4); /* tfcntrflag, finterpflag, reserved, psf */
1048 }
1049 }
1050 if (!seq_found) {
1051 av_free(unescaped);
1052 return AVERROR(ENOSYS);
1053 }
1054
1055 init_put_bits(&pbc, buf, 7);
1056 /* VC1DecSpecStruc */
1057 put_bits(&pbc, 4, 12); /* profile - advanced */
1058 put_bits(&pbc, 3, level);
1059 put_bits(&pbc, 1, 0); /* reserved */
1060 /* VC1AdvDecSpecStruc */
1061 put_bits(&pbc, 3, level);
1062 put_bits(&pbc, 1, 0); /* cbr */
1063 put_bits(&pbc, 6, 0); /* reserved */
1064 put_bits(&pbc, 1, !interlace); /* no interlace */
1065 put_bits(&pbc, 1, !packet_seq); /* no multiple seq */
1066 put_bits(&pbc, 1, !packet_entry); /* no multiple entry */
1067 put_bits(&pbc, 1, !slices); /* no slice code */
1068 put_bits(&pbc, 1, 0); /* no bframe */
1069 put_bits(&pbc, 1, 0); /* reserved */
1070
1071 /* framerate */
1072 if (track->st->avg_frame_rate.num > 0 && track->st->avg_frame_rate.den > 0)
1073 put_bits32(&pbc, track->st->avg_frame_rate.num / track->st->avg_frame_rate.den);
1074 else
1075 put_bits32(&pbc, 0xffffffff);
1076
1077 flush_put_bits(&pbc);
1078
1079 av_free(unescaped);
1080
1081 return 0;
1082 }
1083
mov_write_dvc1_tag(AVIOContext *pb, MOVTrack *track)1084 static int mov_write_dvc1_tag(AVIOContext *pb, MOVTrack *track)
1085 {
1086 uint8_t buf[7] = { 0 };
1087 int ret;
1088
1089 if ((ret = mov_write_dvc1_structs(track, buf)) < 0)
1090 return ret;
1091
1092 avio_wb32(pb, track->vos_len + 8 + sizeof(buf));
1093 ffio_wfourcc(pb, "dvc1");
1094 avio_write(pb, buf, sizeof(buf));
1095 avio_write(pb, track->vos_data, track->vos_len);
1096
1097 return 0;
1098 }
1099
mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)1100 static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
1101 {
1102 avio_wb32(pb, track->vos_len + 8);
1103 ffio_wfourcc(pb, "glbl");
1104 avio_write(pb, track->vos_data, track->vos_len);
1105 return 8 + track->vos_len;
1106 }
1107
1108 /**
1109 * Compute flags for 'lpcm' tag.
1110 * See CoreAudioTypes and AudioStreamBasicDescription at Apple.
1111 */
mov_get_lpcm_flags(enum AVCodecID codec_id)1112 static int mov_get_lpcm_flags(enum AVCodecID codec_id)
1113 {
1114 switch (codec_id) {
1115 case AV_CODEC_ID_PCM_F32BE:
1116 case AV_CODEC_ID_PCM_F64BE:
1117 return 11;
1118 case AV_CODEC_ID_PCM_F32LE:
1119 case AV_CODEC_ID_PCM_F64LE:
1120 return 9;
1121 case AV_CODEC_ID_PCM_U8:
1122 return 10;
1123 case AV_CODEC_ID_PCM_S16BE:
1124 case AV_CODEC_ID_PCM_S24BE:
1125 case AV_CODEC_ID_PCM_S32BE:
1126 return 14;
1127 case AV_CODEC_ID_PCM_S8:
1128 case AV_CODEC_ID_PCM_S16LE:
1129 case AV_CODEC_ID_PCM_S24LE:
1130 case AV_CODEC_ID_PCM_S32LE:
1131 return 12;
1132 default:
1133 return 0;
1134 }
1135 }
1136
get_cluster_duration(MOVTrack *track, int cluster_idx)1137 static int get_cluster_duration(MOVTrack *track, int cluster_idx)
1138 {
1139 int64_t next_dts;
1140
1141 if (cluster_idx >= track->entry)
1142 return 0;
1143
1144 if (cluster_idx + 1 == track->entry)
1145 next_dts = track->track_duration + track->start_dts;
1146 else
1147 next_dts = track->cluster[cluster_idx + 1].dts;
1148
1149 next_dts -= track->cluster[cluster_idx].dts;
1150
1151 av_assert0(next_dts >= 0);
1152 av_assert0(next_dts <= INT_MAX);
1153
1154 return next_dts;
1155 }
1156
get_samples_per_packet(MOVTrack *track)1157 static int get_samples_per_packet(MOVTrack *track)
1158 {
1159 int i, first_duration;
1160
1161 // return track->par->frame_size;
1162
1163 /* use 1 for raw PCM */
1164 if (!track->audio_vbr)
1165 return 1;
1166
1167 /* check to see if duration is constant for all clusters */
1168 if (!track->entry)
1169 return 0;
1170 first_duration = get_cluster_duration(track, 0);
1171 for (i = 1; i < track->entry; i++) {
1172 if (get_cluster_duration(track, i) != first_duration)
1173 return 0;
1174 }
1175 return first_duration;
1176 }
1177
mov_write_btrt_tag(AVIOContext *pb, MOVTrack *track)1178 static int mov_write_btrt_tag(AVIOContext *pb, MOVTrack *track)
1179 {
1180 int64_t pos = avio_tell(pb);
1181 struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track);
1182 if (!bit_rates.max_bit_rate && !bit_rates.avg_bit_rate &&
1183 !bit_rates.buffer_size)
1184 // no useful data to be written, skip
1185 return 0;
1186
1187 avio_wb32(pb, 0); /* size */
1188 ffio_wfourcc(pb, "btrt");
1189
1190 avio_wb32(pb, bit_rates.buffer_size);
1191 avio_wb32(pb, bit_rates.max_bit_rate);
1192 avio_wb32(pb, bit_rates.avg_bit_rate);
1193
1194 return update_size(pb, pos);
1195 }
1196
mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)1197 static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
1198 {
1199 int64_t pos = avio_tell(pb);
1200 int version = 0;
1201 uint32_t tag = track->tag;
1202 int ret = 0;
1203
1204 if (track->mode == MODE_MOV) {
1205 if (track->timescale > UINT16_MAX || !track->par->ch_layout.nb_channels) {
1206 if (mov_get_lpcm_flags(track->par->codec_id))
1207 tag = AV_RL32("lpcm");
1208 version = 2;
1209 } else if (track->audio_vbr || mov_pcm_le_gt16(track->par->codec_id) ||
1210 mov_pcm_be_gt16(track->par->codec_id) ||
1211 track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1212 track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
1213 track->par->codec_id == AV_CODEC_ID_QDM2) {
1214 version = 1;
1215 }
1216 }
1217
1218 avio_wb32(pb, 0); /* size */
1219 if (mov->encryption_scheme != MOV_ENC_NONE) {
1220 ffio_wfourcc(pb, "enca");
1221 } else {
1222 avio_wl32(pb, tag); // store it byteswapped
1223 }
1224 avio_wb32(pb, 0); /* Reserved */
1225 avio_wb16(pb, 0); /* Reserved */
1226 avio_wb16(pb, 1); /* Data-reference index, XXX == 1 */
1227
1228 /* SoundDescription */
1229 avio_wb16(pb, version); /* Version */
1230 avio_wb16(pb, 0); /* Revision level */
1231 avio_wb32(pb, 0); /* Reserved */
1232
1233 if (version == 2) {
1234 avio_wb16(pb, 3);
1235 avio_wb16(pb, 16);
1236 avio_wb16(pb, 0xfffe);
1237 avio_wb16(pb, 0);
1238 avio_wb32(pb, 0x00010000);
1239 avio_wb32(pb, 72);
1240 avio_wb64(pb, av_double2int(track->par->sample_rate));
1241 avio_wb32(pb, track->par->ch_layout.nb_channels);
1242 avio_wb32(pb, 0x7F000000);
1243 avio_wb32(pb, av_get_bits_per_sample(track->par->codec_id));
1244 avio_wb32(pb, mov_get_lpcm_flags(track->par->codec_id));
1245 avio_wb32(pb, track->sample_size);
1246 avio_wb32(pb, get_samples_per_packet(track));
1247 } else {
1248 if (track->mode == MODE_MOV) {
1249 avio_wb16(pb, track->par->ch_layout.nb_channels);
1250 if (track->par->codec_id == AV_CODEC_ID_PCM_U8 ||
1251 track->par->codec_id == AV_CODEC_ID_PCM_S8)
1252 avio_wb16(pb, 8); /* bits per sample */
1253 else if (track->par->codec_id == AV_CODEC_ID_ADPCM_G726)
1254 avio_wb16(pb, track->par->bits_per_coded_sample);
1255 else
1256 avio_wb16(pb, 16);
1257 avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
1258 } else { /* reserved for mp4/3gp */
1259 if (track->par->codec_id == AV_CODEC_ID_FLAC ||
1260 track->par->codec_id == AV_CODEC_ID_ALAC ||
1261 track->par->codec_id == AV_CODEC_ID_OPUS) {
1262 avio_wb16(pb, track->par->ch_layout.nb_channels);
1263 } else {
1264 avio_wb16(pb, 2);
1265 }
1266 if (track->par->codec_id == AV_CODEC_ID_FLAC ||
1267 track->par->codec_id == AV_CODEC_ID_ALAC) {
1268 avio_wb16(pb, track->par->bits_per_raw_sample);
1269 } else {
1270 avio_wb16(pb, 16);
1271 }
1272 avio_wb16(pb, 0);
1273 }
1274
1275 avio_wb16(pb, 0); /* packet size (= 0) */
1276 if (track->par->codec_id == AV_CODEC_ID_OPUS)
1277 avio_wb16(pb, 48000);
1278 else if (track->par->codec_id == AV_CODEC_ID_TRUEHD)
1279 avio_wb32(pb, track->par->sample_rate);
1280 else
1281 avio_wb16(pb, track->par->sample_rate <= UINT16_MAX ?
1282 track->par->sample_rate : 0);
1283
1284 if (track->par->codec_id != AV_CODEC_ID_TRUEHD)
1285 avio_wb16(pb, 0); /* Reserved */
1286 }
1287
1288 if (version == 1) { /* SoundDescription V1 extended info */
1289 if (mov_pcm_le_gt16(track->par->codec_id) ||
1290 mov_pcm_be_gt16(track->par->codec_id))
1291 avio_wb32(pb, 1); /* must be 1 for uncompressed formats */
1292 else
1293 avio_wb32(pb, track->par->frame_size); /* Samples per packet */
1294 avio_wb32(pb, track->sample_size / track->par->ch_layout.nb_channels); /* Bytes per packet */
1295 avio_wb32(pb, track->sample_size); /* Bytes per frame */
1296 avio_wb32(pb, 2); /* Bytes per sample */
1297 }
1298
1299 if (track->mode == MODE_MOV &&
1300 (track->par->codec_id == AV_CODEC_ID_AAC ||
1301 track->par->codec_id == AV_CODEC_ID_AC3 ||
1302 track->par->codec_id == AV_CODEC_ID_EAC3 ||
1303 track->par->codec_id == AV_CODEC_ID_AMR_NB ||
1304 track->par->codec_id == AV_CODEC_ID_ALAC ||
1305 track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1306 track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
1307 track->par->codec_id == AV_CODEC_ID_QDM2 ||
1308 (mov_pcm_le_gt16(track->par->codec_id) && version==1) ||
1309 (mov_pcm_be_gt16(track->par->codec_id) && version==1)))
1310 ret = mov_write_wave_tag(s, pb, track);
1311 else if (track->tag == MKTAG('m','p','4','a'))
1312 ret = mov_write_esds_tag(pb, track);
1313 else if (track->par->codec_id == AV_CODEC_ID_AMR_NB)
1314 ret = mov_write_amr_tag(pb, track);
1315 else if (track->par->codec_id == AV_CODEC_ID_AC3)
1316 ret = mov_write_ac3_tag(s, pb, track);
1317 else if (track->par->codec_id == AV_CODEC_ID_EAC3)
1318 ret = mov_write_eac3_tag(s, pb, track);
1319 else if (track->par->codec_id == AV_CODEC_ID_ALAC)
1320 ret = mov_write_extradata_tag(pb, track);
1321 else if (track->par->codec_id == AV_CODEC_ID_WMAPRO)
1322 ret = mov_write_wfex_tag(s, pb, track);
1323 else if (track->par->codec_id == AV_CODEC_ID_FLAC)
1324 ret = mov_write_dfla_tag(pb, track);
1325 else if (track->par->codec_id == AV_CODEC_ID_OPUS)
1326 ret = mov_write_dops_tag(s, pb, track);
1327 else if (track->par->codec_id == AV_CODEC_ID_TRUEHD)
1328 ret = mov_write_dmlp_tag(s, pb, track);
1329 else if (track->vos_len > 0)
1330 ret = mov_write_glbl_tag(pb, track);
1331
1332 if (ret < 0)
1333 return ret;
1334
1335 if (track->mode == MODE_MOV && track->par->codec_type == AVMEDIA_TYPE_AUDIO
1336 && ((ret = mov_write_chan_tag(s, pb, track)) < 0)) {
1337 return ret;
1338 }
1339
1340 if (mov->encryption_scheme != MOV_ENC_NONE
1341 && ((ret = ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid)) < 0)) {
1342 return ret;
1343 }
1344
1345 if (mov->write_btrt &&
1346 ((ret = mov_write_btrt_tag(pb, track)) < 0))
1347 return ret;
1348
1349 ret = update_size(pb, pos);
1350 return ret;
1351 }
1352
mov_write_d263_tag(AVIOContext *pb)1353 static int mov_write_d263_tag(AVIOContext *pb)
1354 {
1355 avio_wb32(pb, 0xf); /* size */
1356 ffio_wfourcc(pb, "d263");
1357 ffio_wfourcc(pb, "FFMP");
1358 avio_w8(pb, 0); /* decoder version */
1359 /* FIXME use AVCodecContext level/profile, when encoder will set values */
1360 avio_w8(pb, 0xa); /* level */
1361 avio_w8(pb, 0); /* profile */
1362 return 0xf;
1363 }
1364
mov_write_av1c_tag(AVIOContext *pb, MOVTrack *track)1365 static int mov_write_av1c_tag(AVIOContext *pb, MOVTrack *track)
1366 {
1367 int64_t pos = avio_tell(pb);
1368
1369 avio_wb32(pb, 0);
1370 ffio_wfourcc(pb, "av1C");
1371 ff_isom_write_av1c(pb, track->vos_data, track->vos_len, track->mode != MODE_AVIF);
1372 return update_size(pb, pos);
1373 }
1374
mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)1375 static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
1376 {
1377 int64_t pos = avio_tell(pb);
1378
1379 avio_wb32(pb, 0);
1380 ffio_wfourcc(pb, "avcC");
1381 ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
1382 return update_size(pb, pos);
1383 }
1384
mov_write_vpcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)1385 static int mov_write_vpcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1386 {
1387 int64_t pos = avio_tell(pb);
1388
1389 avio_wb32(pb, 0);
1390 ffio_wfourcc(pb, "vpcC");
1391 avio_w8(pb, 1); /* version */
1392 avio_wb24(pb, 0); /* flags */
1393 ff_isom_write_vpcc(s, pb, track->par);
1394 return update_size(pb, pos);
1395 }
1396
mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track)1397 static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track)
1398 {
1399 int64_t pos = avio_tell(pb);
1400
1401 avio_wb32(pb, 0);
1402 ffio_wfourcc(pb, "hvcC");
1403 if (track->tag == MKTAG('h','v','c','1'))
1404 ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 1);
1405 else
1406 ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0);
1407 return update_size(pb, pos);
1408 }
1409
1410 /* also used by all avid codecs (dv, imx, meridien) and their variants */
mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)1411 static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
1412 {
1413 int interlaced;
1414 int cid;
1415 int display_width = track->par->width;
1416
1417 if (track->vos_data && track->vos_len > 0x29) {
1418 if (ff_dnxhd_parse_header_prefix(track->vos_data) != 0) {
1419 /* looks like a DNxHD bit stream */
1420 interlaced = (track->vos_data[5] & 2);
1421 cid = AV_RB32(track->vos_data + 0x28);
1422 } else {
1423 av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream in vos_data\n");
1424 return 0;
1425 }
1426 } else {
1427 av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream, vos_data too small\n");
1428 return 0;
1429 }
1430
1431 avio_wb32(pb, 24); /* size */
1432 ffio_wfourcc(pb, "ACLR");
1433 ffio_wfourcc(pb, "ACLR");
1434 ffio_wfourcc(pb, "0001");
1435 if (track->par->color_range == AVCOL_RANGE_MPEG || /* Legal range (16-235) */
1436 track->par->color_range == AVCOL_RANGE_UNSPECIFIED) {
1437 avio_wb32(pb, 1); /* Corresponds to 709 in official encoder */
1438 } else { /* Full range (0-255) */
1439 avio_wb32(pb, 2); /* Corresponds to RGB in official encoder */
1440 }
1441 avio_wb32(pb, 0); /* unknown */
1442
1443 if (track->tag == MKTAG('A','V','d','h')) {
1444 avio_wb32(pb, 32);
1445 ffio_wfourcc(pb, "ADHR");
1446 ffio_wfourcc(pb, "0001");
1447 avio_wb32(pb, cid);
1448 avio_wb32(pb, 0); /* unknown */
1449 avio_wb32(pb, 1); /* unknown */
1450 avio_wb32(pb, 0); /* unknown */
1451 avio_wb32(pb, 0); /* unknown */
1452 return 0;
1453 }
1454
1455 avio_wb32(pb, 24); /* size */
1456 ffio_wfourcc(pb, "APRG");
1457 ffio_wfourcc(pb, "APRG");
1458 ffio_wfourcc(pb, "0001");
1459 avio_wb32(pb, 1); /* unknown */
1460 avio_wb32(pb, 0); /* unknown */
1461
1462 avio_wb32(pb, 120); /* size */
1463 ffio_wfourcc(pb, "ARES");
1464 ffio_wfourcc(pb, "ARES");
1465 ffio_wfourcc(pb, "0001");
1466 avio_wb32(pb, cid); /* dnxhd cid, some id ? */
1467 if ( track->par->sample_aspect_ratio.num > 0
1468 && track->par->sample_aspect_ratio.den > 0)
1469 display_width = display_width * track->par->sample_aspect_ratio.num / track->par->sample_aspect_ratio.den;
1470 avio_wb32(pb, display_width);
1471 /* values below are based on samples created with quicktime and avid codecs */
1472 if (interlaced) {
1473 avio_wb32(pb, track->par->height / 2);
1474 avio_wb32(pb, 2); /* unknown */
1475 avio_wb32(pb, 0); /* unknown */
1476 avio_wb32(pb, 4); /* unknown */
1477 } else {
1478 avio_wb32(pb, track->par->height);
1479 avio_wb32(pb, 1); /* unknown */
1480 avio_wb32(pb, 0); /* unknown */
1481 if (track->par->height == 1080)
1482 avio_wb32(pb, 5); /* unknown */
1483 else
1484 avio_wb32(pb, 6); /* unknown */
1485 }
1486 /* padding */
1487 ffio_fill(pb, 0, 10 * 8);
1488
1489 return 0;
1490 }
1491
mov_write_dpxe_tag(AVIOContext *pb, MOVTrack *track)1492 static int mov_write_dpxe_tag(AVIOContext *pb, MOVTrack *track)
1493 {
1494 avio_wb32(pb, 12);
1495 ffio_wfourcc(pb, "DpxE");
1496 if (track->par->extradata_size >= 12 &&
1497 !memcmp(&track->par->extradata[4], "DpxE", 4)) {
1498 avio_wb32(pb, track->par->extradata[11]);
1499 } else {
1500 avio_wb32(pb, 1);
1501 }
1502 return 0;
1503 }
1504
mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)1505 static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)
1506 {
1507 int tag;
1508
1509 if (track->par->width == 720) { /* SD */
1510 if (track->par->height == 480) { /* NTSC */
1511 if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
1512 else tag = MKTAG('d','v','c',' ');
1513 }else if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
1514 else if (track->par->format == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
1515 else tag = MKTAG('d','v','p','p');
1516 } else if (track->par->height == 720) { /* HD 720 line */
1517 if (track->st->time_base.den == 50) tag = MKTAG('d','v','h','q');
1518 else tag = MKTAG('d','v','h','p');
1519 } else if (track->par->height == 1080) { /* HD 1080 line */
1520 if (track->st->time_base.den == 25) tag = MKTAG('d','v','h','5');
1521 else tag = MKTAG('d','v','h','6');
1522 } else {
1523 av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n");
1524 return 0;
1525 }
1526
1527 return tag;
1528 }
1529
defined_frame_rate(AVFormatContext *s, AVStream *st)1530 static int defined_frame_rate(AVFormatContext *s, AVStream *st)
1531 {
1532 AVRational rational_framerate = st->avg_frame_rate;
1533 int rate = 0;
1534 if (rational_framerate.den != 0)
1535 rate = av_q2d(rational_framerate);
1536 return rate;
1537 }
1538
mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track)1539 static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track)
1540 {
1541 int tag = track->par->codec_tag;
1542 int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
1543 AVStream *st = track->st;
1544 int rate = defined_frame_rate(s, st);
1545
1546 if (!tag)
1547 tag = MKTAG('m', '2', 'v', '1'); //fallback tag
1548
1549 if (track->par->format == AV_PIX_FMT_YUV420P) {
1550 if (track->par->width == 1280 && track->par->height == 720) {
1551 if (!interlaced) {
1552 if (rate == 24) tag = MKTAG('x','d','v','4');
1553 else if (rate == 25) tag = MKTAG('x','d','v','5');
1554 else if (rate == 30) tag = MKTAG('x','d','v','1');
1555 else if (rate == 50) tag = MKTAG('x','d','v','a');
1556 else if (rate == 60) tag = MKTAG('x','d','v','9');
1557 }
1558 } else if (track->par->width == 1440 && track->par->height == 1080) {
1559 if (!interlaced) {
1560 if (rate == 24) tag = MKTAG('x','d','v','6');
1561 else if (rate == 25) tag = MKTAG('x','d','v','7');
1562 else if (rate == 30) tag = MKTAG('x','d','v','8');
1563 } else {
1564 if (rate == 25) tag = MKTAG('x','d','v','3');
1565 else if (rate == 30) tag = MKTAG('x','d','v','2');
1566 }
1567 } else if (track->par->width == 1920 && track->par->height == 1080) {
1568 if (!interlaced) {
1569 if (rate == 24) tag = MKTAG('x','d','v','d');
1570 else if (rate == 25) tag = MKTAG('x','d','v','e');
1571 else if (rate == 30) tag = MKTAG('x','d','v','f');
1572 } else {
1573 if (rate == 25) tag = MKTAG('x','d','v','c');
1574 else if (rate == 30) tag = MKTAG('x','d','v','b');
1575 }
1576 }
1577 } else if (track->par->format == AV_PIX_FMT_YUV422P) {
1578 if (track->par->width == 1280 && track->par->height == 720) {
1579 if (!interlaced) {
1580 if (rate == 24) tag = MKTAG('x','d','5','4');
1581 else if (rate == 25) tag = MKTAG('x','d','5','5');
1582 else if (rate == 30) tag = MKTAG('x','d','5','1');
1583 else if (rate == 50) tag = MKTAG('x','d','5','a');
1584 else if (rate == 60) tag = MKTAG('x','d','5','9');
1585 }
1586 } else if (track->par->width == 1920 && track->par->height == 1080) {
1587 if (!interlaced) {
1588 if (rate == 24) tag = MKTAG('x','d','5','d');
1589 else if (rate == 25) tag = MKTAG('x','d','5','e');
1590 else if (rate == 30) tag = MKTAG('x','d','5','f');
1591 } else {
1592 if (rate == 25) tag = MKTAG('x','d','5','c');
1593 else if (rate == 30) tag = MKTAG('x','d','5','b');
1594 }
1595 }
1596 }
1597
1598 return tag;
1599 }
1600
mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track)1601 static int mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track)
1602 {
1603 int tag = track->par->codec_tag;
1604 int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
1605 AVStream *st = track->st;
1606 int rate = defined_frame_rate(s, st);
1607
1608 if (!tag)
1609 tag = MKTAG('a', 'v', 'c', 'i'); //fallback tag
1610
1611 if (track->par->format == AV_PIX_FMT_YUV420P10) {
1612 if (track->par->width == 960 && track->par->height == 720) {
1613 if (!interlaced) {
1614 if (rate == 24) tag = MKTAG('a','i','5','p');
1615 else if (rate == 25) tag = MKTAG('a','i','5','q');
1616 else if (rate == 30) tag = MKTAG('a','i','5','p');
1617 else if (rate == 50) tag = MKTAG('a','i','5','q');
1618 else if (rate == 60) tag = MKTAG('a','i','5','p');
1619 }
1620 } else if (track->par->width == 1440 && track->par->height == 1080) {
1621 if (!interlaced) {
1622 if (rate == 24) tag = MKTAG('a','i','5','3');
1623 else if (rate == 25) tag = MKTAG('a','i','5','2');
1624 else if (rate == 30) tag = MKTAG('a','i','5','3');
1625 } else {
1626 if (rate == 50) tag = MKTAG('a','i','5','5');
1627 else if (rate == 60) tag = MKTAG('a','i','5','6');
1628 }
1629 }
1630 } else if (track->par->format == AV_PIX_FMT_YUV422P10) {
1631 if (track->par->width == 1280 && track->par->height == 720) {
1632 if (!interlaced) {
1633 if (rate == 24) tag = MKTAG('a','i','1','p');
1634 else if (rate == 25) tag = MKTAG('a','i','1','q');
1635 else if (rate == 30) tag = MKTAG('a','i','1','p');
1636 else if (rate == 50) tag = MKTAG('a','i','1','q');
1637 else if (rate == 60) tag = MKTAG('a','i','1','p');
1638 }
1639 } else if (track->par->width == 1920 && track->par->height == 1080) {
1640 if (!interlaced) {
1641 if (rate == 24) tag = MKTAG('a','i','1','3');
1642 else if (rate == 25) tag = MKTAG('a','i','1','2');
1643 else if (rate == 30) tag = MKTAG('a','i','1','3');
1644 } else {
1645 if (rate == 25) tag = MKTAG('a','i','1','5');
1646 else if (rate == 50) tag = MKTAG('a','i','1','5');
1647 else if (rate == 60) tag = MKTAG('a','i','1','6');
1648 }
1649 } else if ( track->par->width == 4096 && track->par->height == 2160
1650 || track->par->width == 3840 && track->par->height == 2160
1651 || track->par->width == 2048 && track->par->height == 1080) {
1652 tag = MKTAG('a','i','v','x');
1653 }
1654 }
1655
1656 return tag;
1657 }
1658
1659 static const struct {
1660 enum AVPixelFormat pix_fmt;
1661 uint32_t tag;
1662 unsigned bps;
1663 } mov_pix_fmt_tags[] = {
1664 { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','2'), 0 },
1665 { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','s'), 0 },
1666 { AV_PIX_FMT_UYVY422, MKTAG('2','v','u','y'), 0 },
1667 { AV_PIX_FMT_RGB555BE,MKTAG('r','a','w',' '), 16 },
1668 { AV_PIX_FMT_RGB555LE,MKTAG('L','5','5','5'), 16 },
1669 { AV_PIX_FMT_RGB565LE,MKTAG('L','5','6','5'), 16 },
1670 { AV_PIX_FMT_RGB565BE,MKTAG('B','5','6','5'), 16 },
1671 { AV_PIX_FMT_GRAY16BE,MKTAG('b','1','6','g'), 16 },
1672 { AV_PIX_FMT_RGB24, MKTAG('r','a','w',' '), 24 },
1673 { AV_PIX_FMT_BGR24, MKTAG('2','4','B','G'), 24 },
1674 { AV_PIX_FMT_ARGB, MKTAG('r','a','w',' '), 32 },
1675 { AV_PIX_FMT_BGRA, MKTAG('B','G','R','A'), 32 },
1676 { AV_PIX_FMT_RGBA, MKTAG('R','G','B','A'), 32 },
1677 { AV_PIX_FMT_ABGR, MKTAG('A','B','G','R'), 32 },
1678 { AV_PIX_FMT_RGB48BE, MKTAG('b','4','8','r'), 48 },
1679 };
1680
mov_get_dnxhd_codec_tag(AVFormatContext *s, MOVTrack *track)1681 static int mov_get_dnxhd_codec_tag(AVFormatContext *s, MOVTrack *track)
1682 {
1683 int tag = MKTAG('A','V','d','n');
1684 if (track->par->profile != FF_PROFILE_UNKNOWN &&
1685 track->par->profile != FF_PROFILE_DNXHD)
1686 tag = MKTAG('A','V','d','h');
1687 return tag;
1688 }
1689
mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track)1690 static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track)
1691 {
1692 int tag = track->par->codec_tag;
1693 int i;
1694 enum AVPixelFormat pix_fmt;
1695
1696 for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) {
1697 if (track->par->format == mov_pix_fmt_tags[i].pix_fmt) {
1698 tag = mov_pix_fmt_tags[i].tag;
1699 track->par->bits_per_coded_sample = mov_pix_fmt_tags[i].bps;
1700 if (track->par->codec_tag == mov_pix_fmt_tags[i].tag)
1701 break;
1702 }
1703 }
1704
1705 pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_MOV,
1706 track->par->bits_per_coded_sample);
1707 if (tag == MKTAG('r','a','w',' ') &&
1708 track->par->format != pix_fmt &&
1709 track->par->format != AV_PIX_FMT_GRAY8 &&
1710 track->par->format != AV_PIX_FMT_NONE)
1711 av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to mov, output file will be unreadable\n",
1712 av_get_pix_fmt_name(track->par->format));
1713 return tag;
1714 }
1715
mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)1716 static unsigned int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
1717 {
1718 unsigned int tag = track->par->codec_tag;
1719
1720 // "rtp " is used to distinguish internally created RTP-hint tracks
1721 // (with rtp_ctx) from other tracks.
1722 if (tag == MKTAG('r','t','p',' '))
1723 tag = 0;
1724 if (!tag || (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
1725 (track->par->codec_id == AV_CODEC_ID_DVVIDEO ||
1726 track->par->codec_id == AV_CODEC_ID_RAWVIDEO ||
1727 track->par->codec_id == AV_CODEC_ID_H263 ||
1728 track->par->codec_id == AV_CODEC_ID_H264 ||
1729 track->par->codec_id == AV_CODEC_ID_DNXHD ||
1730 track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO ||
1731 av_get_bits_per_sample(track->par->codec_id)))) { // pcm audio
1732 if (track->par->codec_id == AV_CODEC_ID_DVVIDEO)
1733 tag = mov_get_dv_codec_tag(s, track);
1734 else if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO)
1735 tag = mov_get_rawvideo_codec_tag(s, track);
1736 else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1737 tag = mov_get_mpeg2_xdcam_codec_tag(s, track);
1738 else if (track->par->codec_id == AV_CODEC_ID_H264)
1739 tag = mov_get_h264_codec_tag(s, track);
1740 else if (track->par->codec_id == AV_CODEC_ID_DNXHD)
1741 tag = mov_get_dnxhd_codec_tag(s, track);
1742 else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
1743 tag = ff_codec_get_tag(ff_codec_movvideo_tags, track->par->codec_id);
1744 if (!tag) { // if no mac fcc found, try with Microsoft tags
1745 tag = ff_codec_get_tag(ff_codec_bmp_tags, track->par->codec_id);
1746 if (tag)
1747 av_log(s, AV_LOG_WARNING, "Using MS style video codec tag, "
1748 "the file may be unplayable!\n");
1749 }
1750 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
1751 tag = ff_codec_get_tag(ff_codec_movaudio_tags, track->par->codec_id);
1752 if (!tag) { // if no mac fcc found, try with Microsoft tags
1753 int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->par->codec_id);
1754 if (ms_tag) {
1755 tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
1756 av_log(s, AV_LOG_WARNING, "Using MS style audio codec tag, "
1757 "the file may be unplayable!\n");
1758 }
1759 }
1760 } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
1761 tag = ff_codec_get_tag(ff_codec_movsubtitle_tags, track->par->codec_id);
1762 }
1763
1764 return tag;
1765 }
1766
1767 static const AVCodecTag codec_cover_image_tags[] = {
1768 { AV_CODEC_ID_MJPEG, 0xD },
1769 { AV_CODEC_ID_PNG, 0xE },
1770 { AV_CODEC_ID_BMP, 0x1B },
1771 { AV_CODEC_ID_NONE, 0 },
1772 };
1773
validate_codec_tag(const AVCodecTag *const *tags, unsigned int tag, int codec_id)1774 static unsigned int validate_codec_tag(const AVCodecTag *const *tags,
1775 unsigned int tag, int codec_id)
1776 {
1777 int i;
1778
1779 /**
1780 * Check that tag + id is in the table
1781 */
1782 for (i = 0; tags && tags[i]; i++) {
1783 const AVCodecTag *codec_tags = tags[i];
1784 while (codec_tags->id != AV_CODEC_ID_NONE) {
1785 if (ff_toupper4(codec_tags->tag) == ff_toupper4(tag) &&
1786 codec_tags->id == codec_id)
1787 return codec_tags->tag;
1788 codec_tags++;
1789 }
1790 }
1791 return 0;
1792 }
1793
mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)1794 static unsigned int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
1795 {
1796 if (is_cover_image(track->st))
1797 return ff_codec_get_tag(codec_cover_image_tags, track->par->codec_id);
1798
1799 if (track->mode == MODE_IPOD)
1800 if (!av_match_ext(s->url, "m4a") &&
1801 !av_match_ext(s->url, "m4v") &&
1802 !av_match_ext(s->url, "m4b"))
1803 av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v "
1804 "Quicktime/Ipod might not play the file\n");
1805
1806 if (track->mode == MODE_MOV) {
1807 return mov_get_codec_tag(s, track);
1808 } else
1809 return validate_codec_tag(s->oformat->codec_tag, track->par->codec_tag,
1810 track->par->codec_id);
1811 }
1812
1813 /** Write uuid atom.
1814 * Needed to make file play in iPods running newest firmware
1815 * goes after avcC atom in moov.trak.mdia.minf.stbl.stsd.avc1
1816 */
mov_write_uuid_tag_ipod(AVIOContext *pb)1817 static int mov_write_uuid_tag_ipod(AVIOContext *pb)
1818 {
1819 avio_wb32(pb, 28);
1820 ffio_wfourcc(pb, "uuid");
1821 avio_wb32(pb, 0x6b6840f2);
1822 avio_wb32(pb, 0x5f244fc5);
1823 avio_wb32(pb, 0xba39a51b);
1824 avio_wb32(pb, 0xcf0323f3);
1825 avio_wb32(pb, 0x0);
1826 return 28;
1827 }
1828
1829 static const uint16_t fiel_data[] = {
1830 0x0000, 0x0100, 0x0201, 0x0206, 0x0209, 0x020e
1831 };
1832
mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track, int field_order)1833 static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track, int field_order)
1834 {
1835 unsigned mov_field_order = 0;
1836 if (field_order < FF_ARRAY_ELEMS(fiel_data))
1837 mov_field_order = fiel_data[field_order];
1838 else
1839 return 0;
1840 avio_wb32(pb, 10);
1841 ffio_wfourcc(pb, "fiel");
1842 avio_wb16(pb, mov_field_order);
1843 return 10;
1844 }
1845
mov_write_subtitle_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)1846 static int mov_write_subtitle_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1847 {
1848 MOVMuxContext *mov = s->priv_data;
1849 int ret = AVERROR_BUG;
1850 int64_t pos = avio_tell(pb);
1851 avio_wb32(pb, 0); /* size */
1852 avio_wl32(pb, track->tag); // store it byteswapped
1853 avio_wb32(pb, 0); /* Reserved */
1854 avio_wb16(pb, 0); /* Reserved */
1855 avio_wb16(pb, 1); /* Data-reference index */
1856
1857 if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
1858 mov_write_esds_tag(pb, track);
1859 else if (track->par->codec_id == AV_CODEC_ID_TTML) {
1860 switch (track->par->codec_tag) {
1861 case MOV_ISMV_TTML_TAG:
1862 // ISMV dfxp requires no extradata.
1863 break;
1864 case MOV_MP4_TTML_TAG:
1865 // As specified in 14496-30, XMLSubtitleSampleEntry
1866 // Namespace
1867 avio_put_str(pb, "http://www.w3.org/ns/ttml");
1868 // Empty schema_location
1869 avio_w8(pb, 0);
1870 // Empty auxiliary_mime_types
1871 avio_w8(pb, 0);
1872 break;
1873 default:
1874 av_log(NULL, AV_LOG_ERROR,
1875 "Unknown codec tag '%s' utilized for TTML stream with "
1876 "index %d (track id %d)!\n",
1877 av_fourcc2str(track->par->codec_tag), track->st->index,
1878 track->track_id);
1879 return AVERROR(EINVAL);
1880 }
1881 } else if (track->par->extradata_size)
1882 avio_write(pb, track->par->extradata, track->par->extradata_size);
1883
1884 if (mov->write_btrt &&
1885 ((ret = mov_write_btrt_tag(pb, track)) < 0))
1886 return ret;
1887
1888 return update_size(pb, pos);
1889 }
1890
mov_write_st3d_tag(AVFormatContext *s, AVIOContext *pb, AVStereo3D *stereo_3d)1891 static int mov_write_st3d_tag(AVFormatContext *s, AVIOContext *pb, AVStereo3D *stereo_3d)
1892 {
1893 int8_t stereo_mode;
1894
1895 if (stereo_3d->flags != 0) {
1896 av_log(s, AV_LOG_WARNING, "Unsupported stereo_3d flags %x. st3d not written.\n", stereo_3d->flags);
1897 return 0;
1898 }
1899
1900 switch (stereo_3d->type) {
1901 case AV_STEREO3D_2D:
1902 stereo_mode = 0;
1903 break;
1904 case AV_STEREO3D_TOPBOTTOM:
1905 stereo_mode = 1;
1906 break;
1907 case AV_STEREO3D_SIDEBYSIDE:
1908 stereo_mode = 2;
1909 break;
1910 default:
1911 av_log(s, AV_LOG_WARNING, "Unsupported stereo_3d type %s. st3d not written.\n", av_stereo3d_type_name(stereo_3d->type));
1912 return 0;
1913 }
1914 avio_wb32(pb, 13); /* size */
1915 ffio_wfourcc(pb, "st3d");
1916 avio_wb32(pb, 0); /* version = 0 & flags = 0 */
1917 avio_w8(pb, stereo_mode);
1918 return 13;
1919 }
1920
mov_write_sv3d_tag(AVFormatContext *s, AVIOContext *pb, AVSphericalMapping *spherical_mapping)1921 static int mov_write_sv3d_tag(AVFormatContext *s, AVIOContext *pb, AVSphericalMapping *spherical_mapping)
1922 {
1923 int64_t sv3d_pos, svhd_pos, proj_pos;
1924 const char* metadata_source = s->flags & AVFMT_FLAG_BITEXACT ? "Lavf" : LIBAVFORMAT_IDENT;
1925
1926 if (spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR &&
1927 spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR_TILE &&
1928 spherical_mapping->projection != AV_SPHERICAL_CUBEMAP) {
1929 av_log(s, AV_LOG_WARNING, "Unsupported projection %d. sv3d not written.\n", spherical_mapping->projection);
1930 return 0;
1931 }
1932
1933 sv3d_pos = avio_tell(pb);
1934 avio_wb32(pb, 0); /* size */
1935 ffio_wfourcc(pb, "sv3d");
1936
1937 svhd_pos = avio_tell(pb);
1938 avio_wb32(pb, 0); /* size */
1939 ffio_wfourcc(pb, "svhd");
1940 avio_wb32(pb, 0); /* version = 0 & flags = 0 */
1941 avio_put_str(pb, metadata_source);
1942 update_size(pb, svhd_pos);
1943
1944 proj_pos = avio_tell(pb);
1945 avio_wb32(pb, 0); /* size */
1946 ffio_wfourcc(pb, "proj");
1947
1948 avio_wb32(pb, 24); /* size */
1949 ffio_wfourcc(pb, "prhd");
1950 avio_wb32(pb, 0); /* version = 0 & flags = 0 */
1951 avio_wb32(pb, spherical_mapping->yaw);
1952 avio_wb32(pb, spherical_mapping->pitch);
1953 avio_wb32(pb, spherical_mapping->roll);
1954
1955 switch (spherical_mapping->projection) {
1956 case AV_SPHERICAL_EQUIRECTANGULAR:
1957 case AV_SPHERICAL_EQUIRECTANGULAR_TILE:
1958 avio_wb32(pb, 28); /* size */
1959 ffio_wfourcc(pb, "equi");
1960 avio_wb32(pb, 0); /* version = 0 & flags = 0 */
1961 avio_wb32(pb, spherical_mapping->bound_top);
1962 avio_wb32(pb, spherical_mapping->bound_bottom);
1963 avio_wb32(pb, spherical_mapping->bound_left);
1964 avio_wb32(pb, spherical_mapping->bound_right);
1965 break;
1966 case AV_SPHERICAL_CUBEMAP:
1967 avio_wb32(pb, 20); /* size */
1968 ffio_wfourcc(pb, "cbmp");
1969 avio_wb32(pb, 0); /* version = 0 & flags = 0 */
1970 avio_wb32(pb, 0); /* layout */
1971 avio_wb32(pb, spherical_mapping->padding); /* padding */
1972 break;
1973 }
1974 update_size(pb, proj_pos);
1975
1976 return update_size(pb, sv3d_pos);
1977 }
1978
mov_write_dvcc_dvvc_tag(AVFormatContext *s, AVIOContext *pb, AVDOVIDecoderConfigurationRecord *dovi)1979 static int mov_write_dvcc_dvvc_tag(AVFormatContext *s, AVIOContext *pb, AVDOVIDecoderConfigurationRecord *dovi)
1980 {
1981 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
1982
1983 avio_wb32(pb, 32); /* size = 8 + 24 */
1984 if (dovi->dv_profile > 10)
1985 ffio_wfourcc(pb, "dvwC");
1986 else if (dovi->dv_profile > 7)
1987 ffio_wfourcc(pb, "dvvC");
1988 else
1989 ffio_wfourcc(pb, "dvcC");
1990
1991 ff_isom_put_dvcc_dvvc(s, buf, dovi);
1992 avio_write(pb, buf, sizeof(buf));
1993
1994 return 32; /* 8 + 24 */
1995 }
1996
mov_write_clap_tag(AVIOContext *pb, MOVTrack *track)1997 static int mov_write_clap_tag(AVIOContext *pb, MOVTrack *track)
1998 {
1999 avio_wb32(pb, 40);
2000 ffio_wfourcc(pb, "clap");
2001 avio_wb32(pb, track->par->width); /* apertureWidth_N */
2002 avio_wb32(pb, 1); /* apertureWidth_D (= 1) */
2003 avio_wb32(pb, track->height); /* apertureHeight_N */
2004 avio_wb32(pb, 1); /* apertureHeight_D (= 1) */
2005 avio_wb32(pb, 0); /* horizOff_N (= 0) */
2006 avio_wb32(pb, 1); /* horizOff_D (= 1) */
2007 avio_wb32(pb, 0); /* vertOff_N (= 0) */
2008 avio_wb32(pb, 1); /* vertOff_D (= 1) */
2009 return 40;
2010 }
2011
mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track)2012 static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track)
2013 {
2014 AVRational sar;
2015 av_reduce(&sar.num, &sar.den, track->par->sample_aspect_ratio.num,
2016 track->par->sample_aspect_ratio.den, INT_MAX);
2017
2018 avio_wb32(pb, 16);
2019 ffio_wfourcc(pb, "pasp");
2020 avio_wb32(pb, sar.num);
2021 avio_wb32(pb, sar.den);
2022 return 16;
2023 }
2024
mov_write_gama_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track, double gamma)2025 static int mov_write_gama_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track, double gamma)
2026 {
2027 uint32_t gama = 0;
2028 if (gamma <= 0.0) {
2029 gamma = avpriv_get_gamma_from_trc(track->par->color_trc);
2030 }
2031 av_log(s, AV_LOG_DEBUG, "gamma value %g\n", gamma);
2032
2033 if (gamma > 1e-6) {
2034 gama = (uint32_t)lrint((double)(1<<16) * gamma);
2035 av_log(s, AV_LOG_DEBUG, "writing gama value %"PRId32"\n", gama);
2036
2037 av_assert0(track->mode == MODE_MOV);
2038 avio_wb32(pb, 12);
2039 ffio_wfourcc(pb, "gama");
2040 avio_wb32(pb, gama);
2041 return 12;
2042 } else {
2043 av_log(s, AV_LOG_WARNING, "gamma value unknown, unable to write gama atom\n");
2044 }
2045 return 0;
2046 }
2047
mov_write_colr_tag(AVIOContext *pb, MOVTrack *track, int prefer_icc)2048 static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track, int prefer_icc)
2049 {
2050 int64_t pos = avio_tell(pb);
2051
2052 // Ref (MOV): https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9
2053 // Ref (MP4): ISO/IEC 14496-12:2012
2054
2055 const uint8_t *icc_profile;
2056 size_t icc_profile_size;
2057
2058 if (prefer_icc) {
2059 icc_profile = av_stream_get_side_data(track->st, AV_PKT_DATA_ICC_PROFILE, &icc_profile_size);
2060
2061 if (icc_profile) {
2062 avio_wb32(pb, 12 + icc_profile_size);
2063 ffio_wfourcc(pb, "colr");
2064 ffio_wfourcc(pb, "prof");
2065 avio_write(pb, icc_profile, icc_profile_size);
2066 return 12 + icc_profile_size;
2067 }
2068 else {
2069 av_log(NULL, AV_LOG_INFO, "no ICC profile found, will write nclx/nclc colour info instead\n");
2070 }
2071 }
2072
2073 /* We should only ever be called for MOV, MP4 and AVIF. */
2074 av_assert0(track->mode == MODE_MOV || track->mode == MODE_MP4 ||
2075 track->mode == MODE_AVIF);
2076
2077 avio_wb32(pb, 0); /* size */
2078 ffio_wfourcc(pb, "colr");
2079 if (track->mode == MODE_MP4 || track->mode == MODE_AVIF)
2080 ffio_wfourcc(pb, "nclx");
2081 else
2082 ffio_wfourcc(pb, "nclc");
2083 // Do not try to guess the color info if it is AVCOL_PRI_UNSPECIFIED.
2084 // e.g., Dolby Vision for Apple devices should be set to AVCOL_PRI_UNSPECIFIED. See
2085 // https://developer.apple.com/av-foundation/High-Dynamic-Range-Metadata-for-Apple-Devices.pdf
2086 avio_wb16(pb, track->par->color_primaries);
2087 avio_wb16(pb, track->par->color_trc);
2088 avio_wb16(pb, track->par->color_space);
2089 if (track->mode == MODE_MP4 || track->mode == MODE_AVIF) {
2090 int full_range = track->par->color_range == AVCOL_RANGE_JPEG;
2091 avio_w8(pb, full_range << 7);
2092 }
2093
2094 return update_size(pb, pos);
2095 }
2096
2097 #ifdef OHOS_HDR_VIVID
mov_write_cuvv_tag(AVIOContext *pb, CuvaConfig *cuva)2098 static int mov_write_cuvv_tag(AVIOContext *pb, CuvaConfig *cuva)
2099 {
2100 int64_t pos = avio_tell(pb);
2101 avio_wb32(pb, 0); /* size */
2102 ffio_wfourcc(pb, "cuvv");
2103 avio_wb16(pb, cuva->cuva_version_map);
2104 avio_wb16(pb, cuva->terminal_provide_code);
2105 avio_wb16(pb, cuva->terminal_provide_oriented_code);
2106 avio_wb32(pb, 0); // reserved
2107 avio_wb32(pb, 0); // reserved
2108 avio_wb32(pb, 0); // reserved
2109 avio_wb32(pb, 0); // reserved
2110 return update_size(pb, pos);
2111 }
2112 #endif
2113
mov_write_clli_tag(AVIOContext *pb, MOVTrack *track)2114 static int mov_write_clli_tag(AVIOContext *pb, MOVTrack *track)
2115 {
2116 const uint8_t *side_data;
2117 const AVContentLightMetadata *content_light_metadata;
2118
2119 side_data = av_stream_get_side_data(track->st, AV_PKT_DATA_CONTENT_LIGHT_LEVEL, NULL);
2120 if (!side_data) {
2121 return 0;
2122 }
2123 content_light_metadata = (const AVContentLightMetadata*)side_data;
2124
2125 avio_wb32(pb, 12); // size
2126 ffio_wfourcc(pb, "clli");
2127 avio_wb16(pb, content_light_metadata->MaxCLL);
2128 avio_wb16(pb, content_light_metadata->MaxFALL);
2129 return 12;
2130 }
2131
rescale_mdcv(AVRational q, int b)2132 static inline int64_t rescale_mdcv(AVRational q, int b)
2133 {
2134 return av_rescale(q.num, b, q.den);
2135 }
2136
mov_write_mdcv_tag(AVIOContext *pb, MOVTrack *track)2137 static int mov_write_mdcv_tag(AVIOContext *pb, MOVTrack *track)
2138 {
2139 const int chroma_den = 50000;
2140 const int luma_den = 10000;
2141 const uint8_t *side_data;
2142 const AVMasteringDisplayMetadata *metadata;
2143
2144 side_data = av_stream_get_side_data(track->st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, NULL);
2145 metadata = (const AVMasteringDisplayMetadata*)side_data;
2146 if (!metadata || !metadata->has_primaries || !metadata->has_luminance) {
2147 return 0;
2148 }
2149
2150 avio_wb32(pb, 32); // size
2151 ffio_wfourcc(pb, "mdcv");
2152 avio_wb16(pb, rescale_mdcv(metadata->display_primaries[1][0], chroma_den));
2153 avio_wb16(pb, rescale_mdcv(metadata->display_primaries[1][1], chroma_den));
2154 avio_wb16(pb, rescale_mdcv(metadata->display_primaries[2][0], chroma_den));
2155 avio_wb16(pb, rescale_mdcv(metadata->display_primaries[2][1], chroma_den));
2156 avio_wb16(pb, rescale_mdcv(metadata->display_primaries[0][0], chroma_den));
2157 avio_wb16(pb, rescale_mdcv(metadata->display_primaries[0][1], chroma_den));
2158 avio_wb16(pb, rescale_mdcv(metadata->white_point[0], chroma_den));
2159 avio_wb16(pb, rescale_mdcv(metadata->white_point[1], chroma_den));
2160 avio_wb32(pb, rescale_mdcv(metadata->max_luminance, luma_den));
2161 avio_wb32(pb, rescale_mdcv(metadata->min_luminance, luma_den));
2162 return 32;
2163 }
2164
find_compressor(char * compressor_name, int len, MOVTrack *track)2165 static void find_compressor(char * compressor_name, int len, MOVTrack *track)
2166 {
2167 AVDictionaryEntry *encoder;
2168 int xdcam_res = (track->par->width == 1280 && track->par->height == 720)
2169 || (track->par->width == 1440 && track->par->height == 1080)
2170 || (track->par->width == 1920 && track->par->height == 1080);
2171
2172 if ((track->mode == MODE_AVIF ||
2173 track->mode == MODE_MOV ||
2174 track->mode == MODE_MP4) &&
2175 (encoder = av_dict_get(track->st->metadata, "encoder", NULL, 0))) {
2176 av_strlcpy(compressor_name, encoder->value, 32);
2177 } else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO && xdcam_res) {
2178 int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
2179 AVStream *st = track->st;
2180 int rate = defined_frame_rate(NULL, st);
2181 av_strlcatf(compressor_name, len, "XDCAM");
2182 if (track->par->format == AV_PIX_FMT_YUV422P) {
2183 av_strlcatf(compressor_name, len, " HD422");
2184 } else if(track->par->width == 1440) {
2185 av_strlcatf(compressor_name, len, " HD");
2186 } else
2187 av_strlcatf(compressor_name, len, " EX");
2188
2189 av_strlcatf(compressor_name, len, " %d%c", track->par->height, interlaced ? 'i' : 'p');
2190
2191 av_strlcatf(compressor_name, len, "%d", rate * (interlaced + 1));
2192 }
2193 }
2194
mov_write_ccst_tag(AVIOContext *pb)2195 static int mov_write_ccst_tag(AVIOContext *pb)
2196 {
2197 int64_t pos = avio_tell(pb);
2198 // Write sane defaults:
2199 // all_ref_pics_intra = 0 : all samples can use any type of reference.
2200 // intra_pred_used = 1 : intra prediction may or may not be used.
2201 // max_ref_per_pic = 15 : reserved value to indicate that any number of
2202 // reference images can be used.
2203 uint8_t ccstValue = (0 << 7) | /* all_ref_pics_intra */
2204 (1 << 6) | /* intra_pred_used */
2205 (15 << 2); /* max_ref_per_pic */
2206 avio_wb32(pb, 0); /* size */
2207 ffio_wfourcc(pb, "ccst");
2208 avio_wb32(pb, 0); /* Version & flags */
2209 avio_w8(pb, ccstValue);
2210 avio_wb24(pb, 0); /* reserved */
2211 return update_size(pb, pos);
2212 }
2213
2214 #ifdef OHOS_HDR_VIVID
mov_get_cuva_from_metadata(AVFormatContext *s, MOVMuxContext *mov, MOVTrack *track)2215 static CuvaConfig mov_get_cuva_from_metadata(AVFormatContext *s, MOVMuxContext *mov, MOVTrack *track)
2216 {
2217 CuvaConfig cuva;
2218 cuva.cuva_version_map = 0;
2219 cuva.terminal_provide_code = 0;
2220 cuva.terminal_provide_oriented_code = 0;
2221 if (s == NULL || mov == NULL || track == NULL) {
2222 av_log(mov->fc, AV_LOG_WARNING, "Not cuva info. Parameters is NULL!\n");
2223 return cuva;
2224 }
2225
2226 int i = 0;
2227 for (i = 0; i < mov->nb_streams; ++i) {
2228 if (track == &mov->tracks[i]) {
2229 break;
2230 }
2231 }
2232 if (i == mov->nb_streams) {
2233 av_log(mov->fc, AV_LOG_WARNING, "Not cuva info. The track is not in the mov!\n");
2234 return cuva;
2235 }
2236 AVStream *st = i < s->nb_streams ? s->streams[i] : NULL;
2237 if (st && st->metadata) {
2238 AVDictionaryEntry *rot = av_dict_get(st->metadata, "hdr_type", NULL, 0);
2239 if (rot && rot->value && strcmp(rot->value, "hdr_vivid") == 0) {
2240 cuva.cuva_version_map = 1;
2241 cuva.terminal_provide_code = 4;
2242 cuva.terminal_provide_oriented_code = 5;
2243 }
2244 }
2245 return cuva;
2246 }
2247 #endif
2248
2249 #ifdef OHOS_TIMED_META_TRACK
mov_write_metadata_setup_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)2250 static int mov_write_metadata_setup_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2251 {
2252 int64_t pos = avio_tell(pb);
2253 avio_wb32(pb, 0); /* size */
2254 ffio_wfourcc(pb, "setu");
2255 AVDictionaryEntry* key_val = av_dict_get(track->st->metadata, "setup_key", NULL, 0);
2256 if (key_val) {
2257 size_t key_len = strlen(key_val->value);
2258 avio_write(pb, key_val->value, key_len);
2259 }
2260 return update_size(pb, pos);
2261 }
2262
mov_write_metadata_locale_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)2263 static int mov_write_metadata_locale_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2264 {
2265 int64_t pos = avio_tell(pb);
2266 avio_wb32(pb, 0); /* size */
2267 ffio_wfourcc(pb, "loca");
2268 AVDictionaryEntry* key_val = av_dict_get(track->st->metadata, "locale_key", NULL, 0);
2269 if (key_val) {
2270 size_t key_len = strlen(key_val->value);
2271 avio_write(pb, key_val->value, key_len);
2272 }
2273 return update_size(pb, pos);
2274 }
2275
mov_write_metadata_keyd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, const char *metadata)2276 static int mov_write_metadata_keyd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, const char *metadata)
2277 {
2278 int64_t pos = avio_tell(pb);
2279 avio_wb32(pb, 0); /* size */
2280 ffio_wfourcc(pb, "keyd");
2281 size_t key_len = strlen(metadata);
2282 ffio_wfourcc(pb, "mdta");
2283 avio_write(pb, metadata, key_len);
2284 return update_size(pb, pos);
2285 }
2286
mov_write_metadata_keys_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)2287 static int mov_write_metadata_keys_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2288 {
2289 int ret = AVERROR_BUG;
2290 const AVDictionaryEntry *t = NULL;
2291 avio_wb32(pb, 0); /* Reserved */
2292 avio_wb16(pb, 0); /* Reserved */
2293 avio_wb16(pb, 1); /* Data-reference index */
2294 int64_t pos = avio_tell(pb);
2295 avio_wb32(pb, 0); /* size */
2296 ffio_wfourcc(pb, "keys");
2297 int count = 0;
2298
2299 const char *key_tag = "com.openharmony.timed_metadata";
2300 size_t key_tag_len = strlen(key_tag);
2301 // key atoms table
2302 while (t = av_dict_get(track->st->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) {
2303 size_t key_len = strlen(t->key);
2304 if (key_len > key_tag_len && strncmp(t->key, key_tag, key_tag_len) == 0) {
2305 int64_t entry_pos = avio_tell(pb);
2306 avio_wb32(pb, 0); /* size */
2307 avio_wb32(pb, count + 1); /* local key id, 0 and 0xFFFFFFFF reserved */
2308 ret = mov_write_metadata_keyd_tag(s, pb, mov, t->value);
2309 if (ret < 0)
2310 return ret;
2311 update_size(pb, entry_pos);
2312 count += 1;
2313 }
2314 }
2315
2316 return update_size(pb, pos);
2317 }
2318
mov_write_mebx_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)2319 static int mov_write_mebx_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2320 {
2321 int ret = AVERROR_BUG;
2322 int64_t pos = avio_tell(pb);
2323 avio_wb32(pb, 0); /* size */
2324 ffio_wfourcc(pb, "mebx");
2325 ret = mov_write_metadata_keys_tag(s, pb, mov, track);
2326 if (ret < 0)
2327 return ret;
2328
2329 return update_size(pb, pos);
2330 }
2331 #endif
2332
mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)2333 static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2334 {
2335 int ret = AVERROR_BUG;
2336 int64_t pos = avio_tell(pb);
2337 char compressor_name[32] = { 0 };
2338 int avid = 0;
2339
2340 int uncompressed_ycbcr = ((track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_UYVY422)
2341 || (track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_YUYV422)
2342 || track->par->codec_id == AV_CODEC_ID_V308
2343 || track->par->codec_id == AV_CODEC_ID_V408
2344 || track->par->codec_id == AV_CODEC_ID_V410
2345 || track->par->codec_id == AV_CODEC_ID_V210);
2346
2347 avio_wb32(pb, 0); /* size */
2348 if (mov->encryption_scheme != MOV_ENC_NONE) {
2349 ffio_wfourcc(pb, "encv");
2350 } else {
2351 avio_wl32(pb, track->tag); // store it byteswapped
2352 }
2353 avio_wb32(pb, 0); /* Reserved */
2354 avio_wb16(pb, 0); /* Reserved */
2355 avio_wb16(pb, 1); /* Data-reference index */
2356
2357 if (uncompressed_ycbcr) {
2358 avio_wb16(pb, 2); /* Codec stream version */
2359 } else {
2360 avio_wb16(pb, 0); /* Codec stream version */
2361 }
2362 avio_wb16(pb, 0); /* Codec stream revision (=0) */
2363 if (track->mode == MODE_MOV) {
2364 ffio_wfourcc(pb, "FFMP"); /* Vendor */
2365 if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO || uncompressed_ycbcr) {
2366 avio_wb32(pb, 0); /* Temporal Quality */
2367 avio_wb32(pb, 0x400); /* Spatial Quality = lossless*/
2368 } else {
2369 avio_wb32(pb, 0x200); /* Temporal Quality = normal */
2370 avio_wb32(pb, 0x200); /* Spatial Quality = normal */
2371 }
2372 } else {
2373 ffio_fill(pb, 0, 3 * 4); /* Reserved */
2374 }
2375 avio_wb16(pb, track->par->width); /* Video width */
2376 avio_wb16(pb, track->height); /* Video height */
2377 avio_wb32(pb, 0x00480000); /* Horizontal resolution 72dpi */
2378 avio_wb32(pb, 0x00480000); /* Vertical resolution 72dpi */
2379 avio_wb32(pb, 0); /* Data size (= 0) */
2380 avio_wb16(pb, 1); /* Frame count (= 1) */
2381
2382 find_compressor(compressor_name, 32, track);
2383 #ifdef OHOS_HDR_VIVID
2384 CuvaConfig cuva = mov_get_cuva_from_metadata(s, mov, track);
2385 if (cuva.cuva_version_map > 0 && track->par->codec_id == AV_CODEC_ID_HEVC) {
2386 memset(compressor_name, 0, 32);
2387 memcpy(compressor_name, "CUVA HDR Video", 14);
2388 }
2389 #endif
2390 avio_w8(pb, strlen(compressor_name));
2391 avio_write(pb, compressor_name, 31);
2392
2393 if (track->mode == MODE_MOV &&
2394 (track->par->codec_id == AV_CODEC_ID_V410 || track->par->codec_id == AV_CODEC_ID_V210))
2395 avio_wb16(pb, 0x18);
2396 else if (track->mode == MODE_MOV && track->par->bits_per_coded_sample)
2397 avio_wb16(pb, track->par->bits_per_coded_sample |
2398 (track->par->format == AV_PIX_FMT_GRAY8 ? 0x20 : 0));
2399 else
2400 avio_wb16(pb, 0x18); /* Reserved */
2401
2402 if (track->mode == MODE_MOV && track->par->format == AV_PIX_FMT_PAL8) {
2403 int pal_size, i;
2404 avio_wb16(pb, 0); /* Color table ID */
2405 avio_wb32(pb, 0); /* Color table seed */
2406 avio_wb16(pb, 0x8000); /* Color table flags */
2407 if (track->par->bits_per_coded_sample < 0 || track->par->bits_per_coded_sample > 8)
2408 return AVERROR(EINVAL);
2409 pal_size = 1 << track->par->bits_per_coded_sample;
2410 avio_wb16(pb, pal_size - 1); /* Color table size (zero-relative) */
2411 for (i = 0; i < pal_size; i++) {
2412 uint32_t rgb = track->palette[i];
2413 uint16_t r = (rgb >> 16) & 0xff;
2414 uint16_t g = (rgb >> 8) & 0xff;
2415 uint16_t b = rgb & 0xff;
2416 avio_wb16(pb, 0);
2417 avio_wb16(pb, (r << 8) | r);
2418 avio_wb16(pb, (g << 8) | g);
2419 avio_wb16(pb, (b << 8) | b);
2420 }
2421 } else
2422 avio_wb16(pb, 0xffff); /* Reserved */
2423
2424 if (track->tag == MKTAG('m','p','4','v'))
2425 mov_write_esds_tag(pb, track);
2426 else if (track->par->codec_id == AV_CODEC_ID_H263)
2427 mov_write_d263_tag(pb);
2428 else if (track->par->codec_id == AV_CODEC_ID_AVUI ||
2429 track->par->codec_id == AV_CODEC_ID_SVQ3) {
2430 mov_write_extradata_tag(pb, track);
2431 avio_wb32(pb, 0);
2432 } else if (track->par->codec_id == AV_CODEC_ID_DNXHD) {
2433 mov_write_avid_tag(pb, track);
2434 avid = 1;
2435 } else if (track->par->codec_id == AV_CODEC_ID_HEVC)
2436 mov_write_hvcc_tag(pb, track);
2437 else if (track->par->codec_id == AV_CODEC_ID_H264 && !TAG_IS_AVCI(track->tag)) {
2438 mov_write_avcc_tag(pb, track);
2439 if (track->mode == MODE_IPOD)
2440 mov_write_uuid_tag_ipod(pb);
2441 } else if (track->par->codec_id == AV_CODEC_ID_VP9) {
2442 mov_write_vpcc_tag(mov->fc, pb, track);
2443 } else if (track->par->codec_id == AV_CODEC_ID_AV1) {
2444 mov_write_av1c_tag(pb, track);
2445 } else if (track->par->codec_id == AV_CODEC_ID_VC1 && track->vos_len > 0)
2446 mov_write_dvc1_tag(pb, track);
2447 else if (track->par->codec_id == AV_CODEC_ID_VP6F ||
2448 track->par->codec_id == AV_CODEC_ID_VP6A) {
2449 /* Don't write any potential extradata here - the cropping
2450 * is signalled via the normal width/height fields. */
2451 } else if (track->par->codec_id == AV_CODEC_ID_R10K) {
2452 if (track->par->codec_tag == MKTAG('R','1','0','k'))
2453 mov_write_dpxe_tag(pb, track);
2454 } else if (track->vos_len > 0)
2455 mov_write_glbl_tag(pb, track);
2456
2457 if (track->par->codec_id != AV_CODEC_ID_H264 &&
2458 track->par->codec_id != AV_CODEC_ID_MPEG4 &&
2459 track->par->codec_id != AV_CODEC_ID_DNXHD) {
2460 int field_order = track->par->field_order;
2461
2462 if (field_order != AV_FIELD_UNKNOWN)
2463 mov_write_fiel_tag(pb, track, field_order);
2464 }
2465
2466 if (mov->flags & FF_MOV_FLAG_WRITE_GAMA) {
2467 if (track->mode == MODE_MOV)
2468 mov_write_gama_tag(s, pb, track, mov->gamma);
2469 else
2470 av_log(mov->fc, AV_LOG_WARNING, "Not writing 'gama' atom. Format is not MOV.\n");
2471 }
2472 if (track->mode == MODE_MOV || track->mode == MODE_MP4 || track->mode == MODE_AVIF) {
2473 int has_color_info = track->par->color_primaries != AVCOL_PRI_UNSPECIFIED &&
2474 track->par->color_trc != AVCOL_TRC_UNSPECIFIED &&
2475 track->par->color_space != AVCOL_SPC_UNSPECIFIED;
2476 if (has_color_info || mov->flags & FF_MOV_FLAG_WRITE_COLR ||
2477 av_stream_get_side_data(track->st, AV_PKT_DATA_ICC_PROFILE, NULL)) {
2478 int prefer_icc = mov->flags & FF_MOV_FLAG_PREFER_ICC || !has_color_info;
2479 mov_write_colr_tag(pb, track, prefer_icc);
2480 } else if (mov->flags & FF_MOV_FLAG_WRITE_COLR) {
2481 av_log(mov->fc, AV_LOG_WARNING, "Not writing 'colr' atom. Format is not MOV or MP4.\n");
2482 }
2483 }
2484 if (track->mode == MODE_MOV || track->mode == MODE_MP4) {
2485 mov_write_clli_tag(pb, track);
2486 mov_write_mdcv_tag(pb, track);
2487 }
2488
2489 if (track->mode == MODE_MP4 && mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
2490 AVStereo3D* stereo_3d = (AVStereo3D*) av_stream_get_side_data(track->st, AV_PKT_DATA_STEREO3D, NULL);
2491 AVSphericalMapping* spherical_mapping = (AVSphericalMapping*)av_stream_get_side_data(track->st, AV_PKT_DATA_SPHERICAL, NULL);
2492 AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *)
2493 av_stream_get_side_data(track->st, AV_PKT_DATA_DOVI_CONF, NULL);
2494
2495 if (stereo_3d)
2496 mov_write_st3d_tag(s, pb, stereo_3d);
2497 if (spherical_mapping)
2498 mov_write_sv3d_tag(mov->fc, pb, spherical_mapping);
2499 if (dovi)
2500 mov_write_dvcc_dvvc_tag(s, pb, dovi);
2501 }
2502
2503 if (track->par->sample_aspect_ratio.den && track->par->sample_aspect_ratio.num) {
2504 mov_write_pasp_tag(pb, track);
2505 }
2506
2507 if (uncompressed_ycbcr){
2508 mov_write_clap_tag(pb, track);
2509 }
2510
2511 if (mov->encryption_scheme != MOV_ENC_NONE) {
2512 ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid);
2513 }
2514
2515 #ifdef OHOS_HDR_VIVID
2516 if (cuva.cuva_version_map > 0 && track->par->codec_id == AV_CODEC_ID_HEVC) {
2517 mov_write_cuvv_tag(pb, &cuva);
2518 }
2519 #endif
2520
2521 if (mov->write_btrt &&
2522 ((ret = mov_write_btrt_tag(pb, track)) < 0))
2523 return ret;
2524
2525 /* extra padding for avid stsd */
2526 /* https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-61112 */
2527 if (avid)
2528 avio_wb32(pb, 0);
2529
2530 if (track->mode == MODE_AVIF)
2531 mov_write_ccst_tag(pb);
2532
2533 return update_size(pb, pos);
2534 }
2535
mov_write_rtp_tag(AVIOContext *pb, MOVTrack *track)2536 static int mov_write_rtp_tag(AVIOContext *pb, MOVTrack *track)
2537 {
2538 int64_t pos = avio_tell(pb);
2539 avio_wb32(pb, 0); /* size */
2540 ffio_wfourcc(pb, "rtp ");
2541 avio_wb32(pb, 0); /* Reserved */
2542 avio_wb16(pb, 0); /* Reserved */
2543 avio_wb16(pb, 1); /* Data-reference index */
2544
2545 avio_wb16(pb, 1); /* Hint track version */
2546 avio_wb16(pb, 1); /* Highest compatible version */
2547 avio_wb32(pb, track->max_packet_size); /* Max packet size */
2548
2549 avio_wb32(pb, 12); /* size */
2550 ffio_wfourcc(pb, "tims");
2551 avio_wb32(pb, track->timescale);
2552
2553 return update_size(pb, pos);
2554 }
2555
mov_write_source_reference_tag(AVIOContext *pb, MOVTrack *track, const char *reel_name)2556 static int mov_write_source_reference_tag(AVIOContext *pb, MOVTrack *track, const char *reel_name)
2557 {
2558 uint64_t str_size =strlen(reel_name);
2559 int64_t pos = avio_tell(pb);
2560
2561 if (str_size >= UINT16_MAX){
2562 av_log(NULL, AV_LOG_ERROR, "reel_name length %"PRIu64" is too large\n", str_size);
2563 avio_wb16(pb, 0);
2564 return AVERROR(EINVAL);
2565 }
2566
2567 avio_wb32(pb, 0); /* size */
2568 ffio_wfourcc(pb, "name"); /* Data format */
2569 avio_wb16(pb, str_size); /* string size */
2570 avio_wb16(pb, track->language); /* langcode */
2571 avio_write(pb, reel_name, str_size); /* reel name */
2572 return update_size(pb,pos);
2573 }
2574
mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track)2575 static int mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track)
2576 {
2577 int64_t pos = avio_tell(pb);
2578 #if 1
2579 int frame_duration;
2580 int nb_frames;
2581 AVDictionaryEntry *t = NULL;
2582
2583 if (!track->st->avg_frame_rate.num || !track->st->avg_frame_rate.den) {
2584 av_log(NULL, AV_LOG_ERROR, "avg_frame_rate not set for tmcd track.\n");
2585 return AVERROR(EINVAL);
2586 } else {
2587 frame_duration = av_rescale(track->timescale, track->st->avg_frame_rate.den, track->st->avg_frame_rate.num);
2588 nb_frames = ROUNDED_DIV(track->st->avg_frame_rate.num, track->st->avg_frame_rate.den);
2589 }
2590
2591 if (nb_frames > 255) {
2592 av_log(NULL, AV_LOG_ERROR, "fps %d is too large\n", nb_frames);
2593 return AVERROR(EINVAL);
2594 }
2595
2596 avio_wb32(pb, 0); /* size */
2597 ffio_wfourcc(pb, "tmcd"); /* Data format */
2598 avio_wb32(pb, 0); /* Reserved */
2599 avio_wb32(pb, 1); /* Data reference index */
2600 avio_wb32(pb, 0); /* Flags */
2601 avio_wb32(pb, track->timecode_flags); /* Flags (timecode) */
2602 avio_wb32(pb, track->timescale); /* Timescale */
2603 avio_wb32(pb, frame_duration); /* Frame duration */
2604 avio_w8(pb, nb_frames); /* Number of frames */
2605 avio_w8(pb, 0); /* Reserved */
2606
2607 t = av_dict_get(track->st->metadata, "reel_name", NULL, 0);
2608 if (t && utf8len(t->value) && track->mode != MODE_MP4)
2609 mov_write_source_reference_tag(pb, track, t->value);
2610 else
2611 avio_wb16(pb, 0); /* zero size */
2612 #else
2613
2614 avio_wb32(pb, 0); /* size */
2615 ffio_wfourcc(pb, "tmcd"); /* Data format */
2616 avio_wb32(pb, 0); /* Reserved */
2617 avio_wb32(pb, 1); /* Data reference index */
2618 if (track->par->extradata_size)
2619 avio_write(pb, track->par->extradata, track->par->extradata_size);
2620 #endif
2621 return update_size(pb, pos);
2622 }
2623
mov_write_gpmd_tag(AVIOContext *pb, const MOVTrack *track)2624 static int mov_write_gpmd_tag(AVIOContext *pb, const MOVTrack *track)
2625 {
2626 int64_t pos = avio_tell(pb);
2627 avio_wb32(pb, 0); /* size */
2628 ffio_wfourcc(pb, "gpmd");
2629 avio_wb32(pb, 0); /* Reserved */
2630 avio_wb16(pb, 0); /* Reserved */
2631 avio_wb16(pb, 1); /* Data-reference index */
2632 avio_wb32(pb, 0); /* Reserved */
2633 return update_size(pb, pos);
2634 }
2635
mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)2636 static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2637 {
2638 int64_t pos = avio_tell(pb);
2639 int ret = 0;
2640 avio_wb32(pb, 0); /* size */
2641 ffio_wfourcc(pb, "stsd");
2642 avio_wb32(pb, 0); /* version & flags */
2643 avio_wb32(pb, 1); /* entry count */
2644 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
2645 ret = mov_write_video_tag(s, pb, mov, track);
2646 else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
2647 ret = mov_write_audio_tag(s, pb, mov, track);
2648 else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
2649 ret = mov_write_subtitle_tag(s, pb, track);
2650 else if (track->par->codec_tag == MKTAG('r','t','p',' '))
2651 ret = mov_write_rtp_tag(pb, track);
2652 else if (track->par->codec_tag == MKTAG('t','m','c','d'))
2653 ret = mov_write_tmcd_tag(pb, track);
2654 else if (track->par->codec_tag == MKTAG('g','p','m','d'))
2655 ret = mov_write_gpmd_tag(pb, track);
2656 #ifdef OHOS_TIMED_META_TRACK
2657 else if (track->par->codec_type == AVMEDIA_TYPE_TIMEDMETA)
2658 ret = mov_write_mebx_tag(s, pb, mov, track);
2659 #endif
2660
2661 if (ret < 0)
2662 return ret;
2663
2664 return update_size(pb, pos);
2665 }
2666
mov_write_ctts_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)2667 static int mov_write_ctts_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
2668 {
2669 MOVMuxContext *mov = s->priv_data;
2670 MOVCtts *ctts_entries;
2671 uint32_t entries = 0;
2672 uint32_t atom_size;
2673 int i;
2674
2675 ctts_entries = av_malloc_array((track->entry + 1), sizeof(*ctts_entries)); /* worst case */
2676 if (!ctts_entries)
2677 return AVERROR(ENOMEM);
2678 ctts_entries[0].count = 1;
2679 ctts_entries[0].duration = track->cluster[0].cts;
2680 for (i = 1; i < track->entry; i++) {
2681 if (track->cluster[i].cts == ctts_entries[entries].duration) {
2682 ctts_entries[entries].count++; /* compress */
2683 } else {
2684 entries++;
2685 ctts_entries[entries].duration = track->cluster[i].cts;
2686 ctts_entries[entries].count = 1;
2687 }
2688 }
2689 entries++; /* last one */
2690 atom_size = 16 + (entries * 8);
2691 avio_wb32(pb, atom_size); /* size */
2692 ffio_wfourcc(pb, "ctts");
2693 if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
2694 avio_w8(pb, 1); /* version */
2695 else
2696 avio_w8(pb, 0); /* version */
2697 avio_wb24(pb, 0); /* flags */
2698 avio_wb32(pb, entries); /* entry count */
2699 for (i = 0; i < entries; i++) {
2700 avio_wb32(pb, ctts_entries[i].count);
2701 avio_wb32(pb, ctts_entries[i].duration);
2702 }
2703 av_free(ctts_entries);
2704 return atom_size;
2705 }
2706
2707 /* Time to sample atom */
mov_write_stts_tag(AVIOContext *pb, MOVTrack *track)2708 static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track)
2709 {
2710 MOVStts *stts_entries = NULL;
2711 uint32_t entries = -1;
2712 uint32_t atom_size;
2713 int i;
2714
2715 if (track->par->codec_type == AVMEDIA_TYPE_AUDIO && !track->audio_vbr) {
2716 stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */
2717 if (!stts_entries)
2718 return AVERROR(ENOMEM);
2719 stts_entries[0].count = track->sample_count;
2720 stts_entries[0].duration = 1;
2721 entries = 1;
2722 } else {
2723 if (track->entry) {
2724 stts_entries = av_malloc_array(track->entry, sizeof(*stts_entries)); /* worst case */
2725 if (!stts_entries)
2726 return AVERROR(ENOMEM);
2727 }
2728 for (i = 0; i < track->entry; i++) {
2729 int duration = get_cluster_duration(track, i);
2730 if (i && duration == stts_entries[entries].duration) {
2731 stts_entries[entries].count++; /* compress */
2732 } else {
2733 entries++;
2734 stts_entries[entries].duration = duration;
2735 stts_entries[entries].count = 1;
2736 }
2737 }
2738 entries++; /* last one */
2739 }
2740 atom_size = 16 + (entries * 8);
2741 avio_wb32(pb, atom_size); /* size */
2742 ffio_wfourcc(pb, "stts");
2743 avio_wb32(pb, 0); /* version & flags */
2744 avio_wb32(pb, entries); /* entry count */
2745 for (i = 0; i < entries; i++) {
2746 avio_wb32(pb, stts_entries[i].count);
2747 avio_wb32(pb, stts_entries[i].duration);
2748 }
2749 av_free(stts_entries);
2750 return atom_size;
2751 }
2752
mov_write_dref_tag(AVIOContext *pb)2753 static int mov_write_dref_tag(AVIOContext *pb)
2754 {
2755 avio_wb32(pb, 28); /* size */
2756 ffio_wfourcc(pb, "dref");
2757 avio_wb32(pb, 0); /* version & flags */
2758 avio_wb32(pb, 1); /* entry count */
2759
2760 avio_wb32(pb, 0xc); /* size */
2761 //FIXME add the alis and rsrc atom
2762 ffio_wfourcc(pb, "url ");
2763 avio_wb32(pb, 1); /* version & flags */
2764
2765 return 28;
2766 }
2767
mov_preroll_write_stbl_atoms(AVIOContext *pb, MOVTrack *track)2768 static int mov_preroll_write_stbl_atoms(AVIOContext *pb, MOVTrack *track)
2769 {
2770 struct sgpd_entry {
2771 int count;
2772 int16_t roll_distance;
2773 int group_description_index;
2774 };
2775
2776 struct sgpd_entry *sgpd_entries = NULL;
2777 int entries = -1;
2778 int group = 0;
2779 int i, j;
2780
2781 const int OPUS_SEEK_PREROLL_MS = 80;
2782 int roll_samples = av_rescale_q(OPUS_SEEK_PREROLL_MS,
2783 (AVRational){1, 1000},
2784 (AVRational){1, 48000});
2785
2786 if (!track->entry)
2787 return 0;
2788
2789 sgpd_entries = av_malloc_array(track->entry, sizeof(*sgpd_entries));
2790 if (!sgpd_entries)
2791 return AVERROR(ENOMEM);
2792
2793 av_assert0(track->par->codec_id == AV_CODEC_ID_OPUS || track->par->codec_id == AV_CODEC_ID_AAC);
2794
2795 if (track->par->codec_id == AV_CODEC_ID_OPUS) {
2796 for (i = 0; i < track->entry; i++) {
2797 int roll_samples_remaining = roll_samples;
2798 int distance = 0;
2799 for (j = i - 1; j >= 0; j--) {
2800 roll_samples_remaining -= get_cluster_duration(track, j);
2801 distance++;
2802 if (roll_samples_remaining <= 0)
2803 break;
2804 }
2805 /* We don't have enough preceeding samples to compute a valid
2806 roll_distance here, so this sample can't be independently
2807 decoded. */
2808 if (roll_samples_remaining > 0)
2809 distance = 0;
2810 /* Verify distance is a maximum of 32 (2.5ms) packets. */
2811 if (distance > 32)
2812 return AVERROR_INVALIDDATA;
2813 if (i && distance == sgpd_entries[entries].roll_distance) {
2814 sgpd_entries[entries].count++;
2815 } else {
2816 entries++;
2817 sgpd_entries[entries].count = 1;
2818 sgpd_entries[entries].roll_distance = distance;
2819 sgpd_entries[entries].group_description_index = distance ? ++group : 0;
2820 }
2821 }
2822 } else {
2823 entries++;
2824 sgpd_entries[entries].count = track->sample_count;
2825 sgpd_entries[entries].roll_distance = 1;
2826 sgpd_entries[entries].group_description_index = ++group;
2827 }
2828 entries++;
2829
2830 if (!group) {
2831 av_free(sgpd_entries);
2832 return 0;
2833 }
2834
2835 /* Write sgpd tag */
2836 avio_wb32(pb, 24 + (group * 2)); /* size */
2837 ffio_wfourcc(pb, "sgpd");
2838 avio_wb32(pb, 1 << 24); /* fullbox */
2839 ffio_wfourcc(pb, "roll");
2840 avio_wb32(pb, 2); /* default_length */
2841 avio_wb32(pb, group); /* entry_count */
2842 for (i = 0; i < entries; i++) {
2843 if (sgpd_entries[i].group_description_index) {
2844 avio_wb16(pb, -sgpd_entries[i].roll_distance); /* roll_distance */
2845 }
2846 }
2847
2848 /* Write sbgp tag */
2849 avio_wb32(pb, 20 + (entries * 8)); /* size */
2850 ffio_wfourcc(pb, "sbgp");
2851 avio_wb32(pb, 0); /* fullbox */
2852 ffio_wfourcc(pb, "roll");
2853 avio_wb32(pb, entries); /* entry_count */
2854 for (i = 0; i < entries; i++) {
2855 avio_wb32(pb, sgpd_entries[i].count); /* sample_count */
2856 avio_wb32(pb, sgpd_entries[i].group_description_index); /* group_description_index */
2857 }
2858
2859 av_free(sgpd_entries);
2860 return 0;
2861 }
2862
mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)2863 static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
2864 {
2865 int64_t pos = avio_tell(pb);
2866 int ret = 0;
2867
2868 avio_wb32(pb, 0); /* size */
2869 ffio_wfourcc(pb, "stbl");
2870 if ((ret = mov_write_stsd_tag(s, pb, mov, track)) < 0)
2871 return ret;
2872 mov_write_stts_tag(pb, track);
2873 if ((track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
2874 track->par->codec_id == AV_CODEC_ID_TRUEHD ||
2875 track->par->codec_id == AV_CODEC_ID_MPEGH_3D_AUDIO ||
2876 #ifdef OHOS_TIMED_META_TRACK
2877 track->par->codec_tag == MKTAG('r','t','p',' ') ||
2878 track->par->codec_type == AVMEDIA_TYPE_TIMEDMETA) &&
2879 #else
2880 track->par->codec_tag == MKTAG('r','t','p',' ')) &&
2881 #endif
2882 track->has_keyframes && track->has_keyframes < track->entry)
2883 mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE);
2884 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && track->has_disposable)
2885 mov_write_sdtp_tag(pb, track);
2886 if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS)
2887 mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE);
2888 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO &&
2889 track->flags & MOV_TRACK_CTTS && track->entry) {
2890
2891 if ((ret = mov_write_ctts_tag(s, pb, track)) < 0)
2892 return ret;
2893 }
2894 mov_write_stsc_tag(pb, track);
2895 mov_write_stsz_tag(pb, track);
2896 mov_write_stco_tag(pb, track);
2897 if (track->cenc.aes_ctr) {
2898 ff_mov_cenc_write_stbl_atoms(&track->cenc, pb);
2899 }
2900 if (track->par->codec_id == AV_CODEC_ID_OPUS || track->par->codec_id == AV_CODEC_ID_AAC) {
2901 mov_preroll_write_stbl_atoms(pb, track);
2902 }
2903 return update_size(pb, pos);
2904 }
2905
mov_write_dinf_tag(AVIOContext *pb)2906 static int mov_write_dinf_tag(AVIOContext *pb)
2907 {
2908 int64_t pos = avio_tell(pb);
2909 avio_wb32(pb, 0); /* size */
2910 ffio_wfourcc(pb, "dinf");
2911 mov_write_dref_tag(pb);
2912 return update_size(pb, pos);
2913 }
2914
mov_write_nmhd_tag(AVIOContext *pb)2915 static int mov_write_nmhd_tag(AVIOContext *pb)
2916 {
2917 avio_wb32(pb, 12);
2918 ffio_wfourcc(pb, "nmhd");
2919 avio_wb32(pb, 0);
2920 return 12;
2921 }
2922
mov_write_sthd_tag(AVIOContext *pb)2923 static int mov_write_sthd_tag(AVIOContext *pb)
2924 {
2925 avio_wb32(pb, 12);
2926 ffio_wfourcc(pb, "sthd");
2927 avio_wb32(pb, 0);
2928 return 12;
2929 }
2930
mov_write_tcmi_tag(AVIOContext *pb, MOVTrack *track)2931 static int mov_write_tcmi_tag(AVIOContext *pb, MOVTrack *track)
2932 {
2933 int64_t pos = avio_tell(pb);
2934 const char *font = "Lucida Grande";
2935 avio_wb32(pb, 0); /* size */
2936 ffio_wfourcc(pb, "tcmi"); /* timecode media information atom */
2937 avio_wb32(pb, 0); /* version & flags */
2938 avio_wb16(pb, 0); /* text font */
2939 avio_wb16(pb, 0); /* text face */
2940 avio_wb16(pb, 12); /* text size */
2941 avio_wb16(pb, 0); /* (unknown, not in the QT specs...) */
2942 avio_wb16(pb, 0x0000); /* text color (red) */
2943 avio_wb16(pb, 0x0000); /* text color (green) */
2944 avio_wb16(pb, 0x0000); /* text color (blue) */
2945 avio_wb16(pb, 0xffff); /* background color (red) */
2946 avio_wb16(pb, 0xffff); /* background color (green) */
2947 avio_wb16(pb, 0xffff); /* background color (blue) */
2948 avio_w8(pb, strlen(font)); /* font len (part of the pascal string) */
2949 avio_write(pb, font, strlen(font)); /* font name */
2950 return update_size(pb, pos);
2951 }
2952
mov_write_gmhd_tag(AVIOContext *pb, MOVTrack *track)2953 static int mov_write_gmhd_tag(AVIOContext *pb, MOVTrack *track)
2954 {
2955 int64_t pos = avio_tell(pb);
2956 avio_wb32(pb, 0); /* size */
2957 ffio_wfourcc(pb, "gmhd");
2958 avio_wb32(pb, 0x18); /* gmin size */
2959 ffio_wfourcc(pb, "gmin");/* generic media info */
2960 avio_wb32(pb, 0); /* version & flags */
2961 avio_wb16(pb, 0x40); /* graphics mode = */
2962 avio_wb16(pb, 0x8000); /* opColor (r?) */
2963 avio_wb16(pb, 0x8000); /* opColor (g?) */
2964 avio_wb16(pb, 0x8000); /* opColor (b?) */
2965 avio_wb16(pb, 0); /* balance */
2966 avio_wb16(pb, 0); /* reserved */
2967
2968 /*
2969 * This special text atom is required for
2970 * Apple Quicktime chapters. The contents
2971 * don't appear to be documented, so the
2972 * bytes are copied verbatim.
2973 */
2974 if (track->tag != MKTAG('c','6','0','8')) {
2975 avio_wb32(pb, 0x2C); /* size */
2976 ffio_wfourcc(pb, "text");
2977 avio_wb16(pb, 0x01);
2978 avio_wb32(pb, 0x00);
2979 avio_wb32(pb, 0x00);
2980 avio_wb32(pb, 0x00);
2981 avio_wb32(pb, 0x01);
2982 avio_wb32(pb, 0x00);
2983 avio_wb32(pb, 0x00);
2984 avio_wb32(pb, 0x00);
2985 avio_wb32(pb, 0x00004000);
2986 avio_wb16(pb, 0x0000);
2987 }
2988
2989 if (track->par->codec_tag == MKTAG('t','m','c','d')) {
2990 int64_t tmcd_pos = avio_tell(pb);
2991 avio_wb32(pb, 0); /* size */
2992 ffio_wfourcc(pb, "tmcd");
2993 mov_write_tcmi_tag(pb, track);
2994 update_size(pb, tmcd_pos);
2995 } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
2996 int64_t gpmd_pos = avio_tell(pb);
2997 avio_wb32(pb, 0); /* size */
2998 ffio_wfourcc(pb, "gpmd");
2999 avio_wb32(pb, 0); /* version */
3000 update_size(pb, gpmd_pos);
3001 }
3002 return update_size(pb, pos);
3003 }
3004
mov_write_smhd_tag(AVIOContext *pb)3005 static int mov_write_smhd_tag(AVIOContext *pb)
3006 {
3007 avio_wb32(pb, 16); /* size */
3008 ffio_wfourcc(pb, "smhd");
3009 avio_wb32(pb, 0); /* version & flags */
3010 avio_wb16(pb, 0); /* reserved (balance, normally = 0) */
3011 avio_wb16(pb, 0); /* reserved */
3012 return 16;
3013 }
3014
mov_write_vmhd_tag(AVIOContext *pb)3015 static int mov_write_vmhd_tag(AVIOContext *pb)
3016 {
3017 avio_wb32(pb, 0x14); /* size (always 0x14) */
3018 ffio_wfourcc(pb, "vmhd");
3019 avio_wb32(pb, 0x01); /* version & flags */
3020 avio_wb64(pb, 0); /* reserved (graphics mode = copy) */
3021 return 0x14;
3022 }
3023
is_clcp_track(MOVTrack *track)3024 static int is_clcp_track(MOVTrack *track)
3025 {
3026 return track->tag == MKTAG('c','7','0','8') ||
3027 track->tag == MKTAG('c','6','0','8');
3028 }
3029
mov_write_hdlr_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)3030 static int mov_write_hdlr_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
3031 {
3032 MOVMuxContext *mov = s->priv_data;
3033 const char *hdlr, *descr = NULL, *hdlr_type = NULL;
3034 int64_t pos = avio_tell(pb);
3035 size_t descr_len;
3036
3037 hdlr = "dhlr";
3038 hdlr_type = "url ";
3039 descr = "DataHandler";
3040
3041 if (track) {
3042 hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
3043 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
3044 if (track->mode == MODE_AVIF) {
3045 hdlr_type = (track == &mov->tracks[0]) ? "pict" : "auxv";
3046 descr = "PictureHandler";
3047 } else {
3048 hdlr_type = "vide";
3049 descr = "VideoHandler";
3050 }
3051 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
3052 hdlr_type = "soun";
3053 descr = "SoundHandler";
3054 } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
3055 if (is_clcp_track(track)) {
3056 hdlr_type = "clcp";
3057 descr = "ClosedCaptionHandler";
3058 } else {
3059 if (track->tag == MKTAG('t','x','3','g')) {
3060 hdlr_type = "sbtl";
3061 } else if (track->tag == MKTAG('m','p','4','s')) {
3062 hdlr_type = "subp";
3063 } else if (track->tag == MOV_MP4_TTML_TAG) {
3064 hdlr_type = "subt";
3065 } else {
3066 hdlr_type = "text";
3067 }
3068 descr = "SubtitleHandler";
3069 }
3070 } else if (track->par->codec_tag == MKTAG('r','t','p',' ')) {
3071 hdlr_type = "hint";
3072 descr = "HintHandler";
3073 } else if (track->par->codec_tag == MKTAG('t','m','c','d')) {
3074 hdlr_type = "tmcd";
3075 descr = "TimeCodeHandler";
3076 } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
3077 hdlr_type = "meta";
3078 descr = "GoPro MET"; // GoPro Metadata
3079 #ifdef OHOS_TIMED_META_TRACK
3080 } else if (track->par->codec_type == AVMEDIA_TYPE_TIMEDMETA) {
3081 hdlr_type = "meta";
3082 #endif
3083 } else {
3084 av_log(s, AV_LOG_WARNING,
3085 "Unknown hdlr_type for %s, writing dummy values\n",
3086 av_fourcc2str(track->par->codec_tag));
3087 }
3088 if (track->st) {
3089 // hdlr.name is used by some players to identify the content title
3090 // of the track. So if an alternate handler description is
3091 // specified, use it.
3092 AVDictionaryEntry *t;
3093 t = av_dict_get(track->st->metadata, "handler_name", NULL, 0);
3094 if (t && utf8len(t->value))
3095 descr = t->value;
3096 }
3097 }
3098
3099 if (mov->empty_hdlr_name) /* expressly allowed by QTFF and not prohibited in ISO 14496-12 8.4.3.3 */
3100 descr = "";
3101
3102 avio_wb32(pb, 0); /* size */
3103 ffio_wfourcc(pb, "hdlr");
3104 avio_wb32(pb, 0); /* Version & flags */
3105 avio_write(pb, hdlr, 4); /* handler */
3106 ffio_wfourcc(pb, hdlr_type); /* handler type */
3107 avio_wb32(pb, 0); /* reserved */
3108 avio_wb32(pb, 0); /* reserved */
3109 avio_wb32(pb, 0); /* reserved */
3110 descr_len = strlen(descr);
3111 if (!track || track->mode == MODE_MOV)
3112 avio_w8(pb, descr_len); /* pascal string */
3113 avio_write(pb, descr, descr_len); /* handler description */
3114 if (track && track->mode != MODE_MOV)
3115 avio_w8(pb, 0); /* c string */
3116 return update_size(pb, pos);
3117 }
3118
mov_write_pitm_tag(AVIOContext *pb, int item_id)3119 static int mov_write_pitm_tag(AVIOContext *pb, int item_id)
3120 {
3121 int64_t pos = avio_tell(pb);
3122 avio_wb32(pb, 0); /* size */
3123 ffio_wfourcc(pb, "pitm");
3124 avio_wb32(pb, 0); /* Version & flags */
3125 avio_wb16(pb, item_id); /* item_id */
3126 return update_size(pb, pos);
3127 }
3128
mov_write_iloc_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)3129 static int mov_write_iloc_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3130 {
3131 int64_t pos = avio_tell(pb);
3132 avio_wb32(pb, 0); /* size */
3133 ffio_wfourcc(pb, "iloc");
3134 avio_wb32(pb, 0); /* Version & flags */
3135 avio_w8(pb, (4 << 4) + 4); /* offset_size(4) and length_size(4) */
3136 avio_w8(pb, 0); /* base_offset_size(4) and reserved(4) */
3137 avio_wb16(pb, s->nb_streams); /* item_count */
3138
3139 for (int i = 0; i < s->nb_streams; i++) {
3140 avio_wb16(pb, i + 1); /* item_id */
3141 avio_wb16(pb, 0); /* data_reference_index */
3142 avio_wb16(pb, 1); /* extent_count */
3143 mov->avif_extent_pos[i] = avio_tell(pb);
3144 avio_wb32(pb, 0); /* extent_offset (written later) */
3145 // For animated AVIF, we simply write the first packet's size.
3146 avio_wb32(pb, mov->avif_extent_length[i]); /* extent_length */
3147 }
3148
3149 return update_size(pb, pos);
3150 }
3151
mov_write_iinf_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)3152 static int mov_write_iinf_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3153 {
3154 int64_t iinf_pos = avio_tell(pb);
3155 avio_wb32(pb, 0); /* size */
3156 ffio_wfourcc(pb, "iinf");
3157 avio_wb32(pb, 0); /* Version & flags */
3158 avio_wb16(pb, s->nb_streams); /* entry_count */
3159
3160 for (int i = 0; i < s->nb_streams; i++) {
3161 int64_t infe_pos = avio_tell(pb);
3162 avio_wb32(pb, 0); /* size */
3163 ffio_wfourcc(pb, "infe");
3164 avio_w8(pb, 0x2); /* Version */
3165 avio_wb24(pb, 0); /* flags */
3166 avio_wb16(pb, i + 1); /* item_id */
3167 avio_wb16(pb, 0); /* item_protection_index */
3168 avio_write(pb, "av01", 4); /* item_type */
3169 avio_write(pb, !i ? "Color\0" : "Alpha\0", 6); /* item_name */
3170 update_size(pb, infe_pos);
3171 }
3172
3173 return update_size(pb, iinf_pos);
3174 }
3175
3176
mov_write_iref_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)3177 static int mov_write_iref_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3178 {
3179 int64_t auxl_pos;
3180 int64_t iref_pos = avio_tell(pb);
3181 avio_wb32(pb, 0); /* size */
3182 ffio_wfourcc(pb, "iref");
3183 avio_wb32(pb, 0); /* Version & flags */
3184
3185 auxl_pos = avio_tell(pb);
3186 avio_wb32(pb, 0); /* size */
3187 ffio_wfourcc(pb, "auxl");
3188 avio_wb16(pb, 2); /* from_item_ID */
3189 avio_wb16(pb, 1); /* reference_count */
3190 avio_wb16(pb, 1); /* to_item_ID */
3191 update_size(pb, auxl_pos);
3192
3193 return update_size(pb, iref_pos);
3194 }
3195
mov_write_ispe_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s, int stream_index)3196 static int mov_write_ispe_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s,
3197 int stream_index)
3198 {
3199 int64_t pos = avio_tell(pb);
3200 avio_wb32(pb, 0); /* size */
3201 ffio_wfourcc(pb, "ispe");
3202 avio_wb32(pb, 0); /* Version & flags */
3203 avio_wb32(pb, s->streams[stream_index]->codecpar->width); /* image_width */
3204 avio_wb32(pb, s->streams[stream_index]->codecpar->height); /* image_height */
3205 return update_size(pb, pos);
3206 }
3207
mov_write_pixi_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s, int stream_index)3208 static int mov_write_pixi_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s,
3209 int stream_index)
3210 {
3211 int64_t pos = avio_tell(pb);
3212 const AVPixFmtDescriptor *pixdesc =
3213 av_pix_fmt_desc_get(s->streams[stream_index]->codecpar->format);
3214 avio_wb32(pb, 0); /* size */
3215 ffio_wfourcc(pb, "pixi");
3216 avio_wb32(pb, 0); /* Version & flags */
3217 avio_w8(pb, pixdesc->nb_components); /* num_channels */
3218 for (int i = 0; i < pixdesc->nb_components; ++i) {
3219 avio_w8(pb, pixdesc->comp[i].depth); /* bits_per_channel */
3220 }
3221 return update_size(pb, pos);
3222 }
3223
mov_write_auxC_tag(AVIOContext *pb)3224 static int mov_write_auxC_tag(AVIOContext *pb)
3225 {
3226 int64_t pos = avio_tell(pb);
3227 avio_wb32(pb, 0); /* size */
3228 ffio_wfourcc(pb, "auxC");
3229 avio_wb32(pb, 0); /* Version & flags */
3230 avio_write(pb, "urn:mpeg:mpegB:cicp:systems:auxiliary:alpha\0", 44);
3231 return update_size(pb, pos);
3232 }
3233
mov_write_ipco_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)3234 static int mov_write_ipco_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3235 {
3236 int64_t pos = avio_tell(pb);
3237 avio_wb32(pb, 0); /* size */
3238 ffio_wfourcc(pb, "ipco");
3239 for (int i = 0; i < s->nb_streams; i++) {
3240 mov_write_ispe_tag(pb, mov, s, i);
3241 mov_write_pixi_tag(pb, mov, s, i);
3242 mov_write_av1c_tag(pb, &mov->tracks[i]);
3243 if (!i)
3244 mov_write_colr_tag(pb, &mov->tracks[0], 0);
3245 else
3246 mov_write_auxC_tag(pb);
3247 }
3248 return update_size(pb, pos);
3249 }
3250
mov_write_ipma_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)3251 static int mov_write_ipma_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3252 {
3253 int64_t pos = avio_tell(pb);
3254 avio_wb32(pb, 0); /* size */
3255 ffio_wfourcc(pb, "ipma");
3256 avio_wb32(pb, 0); /* Version & flags */
3257 avio_wb32(pb, s->nb_streams); /* entry_count */
3258
3259 for (int i = 0, index = 1; i < s->nb_streams; i++) {
3260 avio_wb16(pb, i + 1); /* item_ID */
3261 avio_w8(pb, 4); /* association_count */
3262
3263 // ispe association.
3264 avio_w8(pb, index++); /* essential and property_index */
3265 // pixi association.
3266 avio_w8(pb, index++); /* essential and property_index */
3267 // av1C association.
3268 avio_w8(pb, 0x80 | index++); /* essential and property_index */
3269 // colr/auxC association.
3270 avio_w8(pb, index++); /* essential and property_index */
3271 }
3272 return update_size(pb, pos);
3273 }
3274
mov_write_iprp_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)3275 static int mov_write_iprp_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
3276 {
3277 int64_t pos = avio_tell(pb);
3278 avio_wb32(pb, 0); /* size */
3279 ffio_wfourcc(pb, "iprp");
3280 mov_write_ipco_tag(pb, mov, s);
3281 mov_write_ipma_tag(pb, mov, s);
3282 return update_size(pb, pos);
3283 }
3284
mov_write_hmhd_tag(AVIOContext *pb)3285 static int mov_write_hmhd_tag(AVIOContext *pb)
3286 {
3287 /* This atom must be present, but leaving the values at zero
3288 * seems harmless. */
3289 avio_wb32(pb, 28); /* size */
3290 ffio_wfourcc(pb, "hmhd");
3291 avio_wb32(pb, 0); /* version, flags */
3292 avio_wb16(pb, 0); /* maxPDUsize */
3293 avio_wb16(pb, 0); /* avgPDUsize */
3294 avio_wb32(pb, 0); /* maxbitrate */
3295 avio_wb32(pb, 0); /* avgbitrate */
3296 avio_wb32(pb, 0); /* reserved */
3297 return 28;
3298 }
3299
mov_write_minf_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)3300 static int mov_write_minf_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
3301 {
3302 int64_t pos = avio_tell(pb);
3303 int ret;
3304
3305 avio_wb32(pb, 0); /* size */
3306 ffio_wfourcc(pb, "minf");
3307 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
3308 mov_write_vmhd_tag(pb);
3309 else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
3310 mov_write_smhd_tag(pb);
3311 else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
3312 if (track->tag == MKTAG('t','e','x','t') || is_clcp_track(track)) {
3313 mov_write_gmhd_tag(pb, track);
3314 } else if (track->tag == MOV_MP4_TTML_TAG) {
3315 mov_write_sthd_tag(pb);
3316 } else {
3317 mov_write_nmhd_tag(pb);
3318 }
3319 } else if (track->tag == MKTAG('r','t','p',' ')) {
3320 mov_write_hmhd_tag(pb);
3321 } else if (track->tag == MKTAG('t','m','c','d')) {
3322 if (track->mode != MODE_MOV)
3323 mov_write_nmhd_tag(pb);
3324 else
3325 mov_write_gmhd_tag(pb, track);
3326 } else if (track->tag == MKTAG('g','p','m','d')) {
3327 mov_write_gmhd_tag(pb, track);
3328 }
3329 if (track->mode == MODE_MOV) /* ISO 14496-12 8.4.3.1 specifies hdlr only within mdia or meta boxes */
3330 mov_write_hdlr_tag(s, pb, NULL);
3331 mov_write_dinf_tag(pb);
3332 if ((ret = mov_write_stbl_tag(s, pb, mov, track)) < 0)
3333 return ret;
3334 return update_size(pb, pos);
3335 }
3336
get_pts_range(MOVMuxContext *mov, MOVTrack *track, int64_t *start, int64_t *end)3337 static void get_pts_range(MOVMuxContext *mov, MOVTrack *track,
3338 int64_t *start, int64_t *end)
3339 {
3340 #ifdef OHOS_TIMED_META_TRACK
3341 if ((track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) ||
3342 (track->tag == MKTAG('c','d','s','c'))) {
3343 #else
3344 if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) {
3345 #endif
3346 // tmcd tracks gets track_duration set in mov_write_moov_tag from
3347 // another track's duration, while the end_pts may be left at zero.
3348 // Calculate the pts duration for that track instead.
3349 get_pts_range(mov, &mov->tracks[track->src_track], start, end);
3350 *start = av_rescale(*start, track->timescale,
3351 mov->tracks[track->src_track].timescale);
3352 *end = av_rescale(*end, track->timescale,
3353 mov->tracks[track->src_track].timescale);
3354 return;
3355 }
3356 if (track->end_pts != AV_NOPTS_VALUE &&
3357 track->start_dts != AV_NOPTS_VALUE &&
3358 track->start_cts != AV_NOPTS_VALUE) {
3359 *start = track->start_dts + track->start_cts;
3360 *end = track->end_pts;
3361 return;
3362 }
3363 *start = 0;
3364 *end = track->track_duration;
3365 }
3366
3367 static int64_t calc_samples_pts_duration(MOVMuxContext *mov, MOVTrack *track)
3368 {
3369 int64_t start, end;
3370 get_pts_range(mov, track, &start, &end);
3371 return end - start;
3372 }
3373
3374 // Calculate the actual duration of the track, after edits.
3375 // If it starts with a pts < 0, that is removed by the edit list.
3376 // If it starts with a pts > 0, the edit list adds a delay before that.
3377 // Thus, with edit lists enabled, the post-edit output of the file is
3378 // starting with pts=0.
3379 static int64_t calc_pts_duration(MOVMuxContext *mov, MOVTrack *track)
3380 {
3381 int64_t start, end;
3382 get_pts_range(mov, track, &start, &end);
3383 if (mov->use_editlist != 0)
3384 start = 0;
3385 return end - start;
3386 }
3387
3388 static int mov_write_mdhd_tag(AVIOContext *pb, MOVMuxContext *mov,
3389 MOVTrack *track)
3390 {
3391 int64_t duration = calc_samples_pts_duration(mov, track);
3392 int version = duration < INT32_MAX ? 0 : 1;
3393
3394 if (track->mode == MODE_ISM)
3395 version = 1;
3396
3397 (version == 1) ? avio_wb32(pb, 44) : avio_wb32(pb, 32); /* size */
3398 ffio_wfourcc(pb, "mdhd");
3399 avio_w8(pb, version);
3400 avio_wb24(pb, 0); /* flags */
3401 if (version == 1) {
3402 avio_wb64(pb, track->time);
3403 avio_wb64(pb, track->time);
3404 } else {
3405 avio_wb32(pb, track->time); /* creation time */
3406 avio_wb32(pb, track->time); /* modification time */
3407 }
3408 avio_wb32(pb, track->timescale); /* time scale (sample rate for audio) */
3409 if (!track->entry && mov->mode == MODE_ISM)
3410 (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
3411 else if (!track->entry)
3412 (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
3413 else
3414 (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration); /* duration */
3415 avio_wb16(pb, track->language); /* language */
3416 avio_wb16(pb, 0); /* reserved (quality) */
3417
3418 if (version != 0 && track->mode == MODE_MOV) {
3419 av_log(NULL, AV_LOG_ERROR,
3420 "FATAL error, file duration too long for timebase, this file will not be\n"
3421 "playable with QuickTime. Choose a different timebase with "
3422 "-video_track_timescale or a different container format\n");
3423 }
3424
3425 return 32;
3426 }
3427
3428 static int mov_write_mdia_tag(AVFormatContext *s, AVIOContext *pb,
3429 MOVMuxContext *mov, MOVTrack *track)
3430 {
3431 int64_t pos = avio_tell(pb);
3432 int ret;
3433
3434 avio_wb32(pb, 0); /* size */
3435 ffio_wfourcc(pb, "mdia");
3436 mov_write_mdhd_tag(pb, mov, track);
3437 mov_write_hdlr_tag(s, pb, track);
3438 if ((ret = mov_write_minf_tag(s, pb, mov, track)) < 0)
3439 return ret;
3440 return update_size(pb, pos);
3441 }
3442
3443 /* transformation matrix
3444 |a b u|
3445 |c d v|
3446 |tx ty w| */
3447 static void write_matrix(AVIOContext *pb, int16_t a, int16_t b, int16_t c,
3448 int16_t d, int16_t tx, int16_t ty)
3449 {
3450 avio_wb32(pb, a << 16); /* 16.16 format */
3451 avio_wb32(pb, b << 16); /* 16.16 format */
3452 avio_wb32(pb, 0); /* u in 2.30 format */
3453 avio_wb32(pb, c << 16); /* 16.16 format */
3454 avio_wb32(pb, d << 16); /* 16.16 format */
3455 avio_wb32(pb, 0); /* v in 2.30 format */
3456 avio_wb32(pb, tx << 16); /* 16.16 format */
3457 avio_wb32(pb, ty << 16); /* 16.16 format */
3458 avio_wb32(pb, 1 << 30); /* w in 2.30 format */
3459 }
3460
3461 static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov,
3462 MOVTrack *track, AVStream *st)
3463 {
3464 int64_t duration = av_rescale_rnd(calc_pts_duration(mov, track),
3465 mov->movie_timescale, track->timescale,
3466 AV_ROUND_UP);
3467 int version = duration < INT32_MAX ? 0 : 1;
3468 int flags = MOV_TKHD_FLAG_IN_MOVIE;
3469 int group = 0;
3470
3471 uint32_t *display_matrix = NULL;
3472 size_t display_matrix_size;
3473 int i;
3474
3475 if (st) {
3476 if (mov->per_stream_grouping)
3477 group = st->index;
3478 else
3479 group = st->codecpar->codec_type;
3480
3481 display_matrix = (uint32_t*)av_stream_get_side_data(st, AV_PKT_DATA_DISPLAYMATRIX,
3482 &display_matrix_size);
3483 if (display_matrix && display_matrix_size < 9 * sizeof(*display_matrix))
3484 display_matrix = NULL;
3485 }
3486
3487 if (track->flags & MOV_TRACK_ENABLED)
3488 flags |= MOV_TKHD_FLAG_ENABLED;
3489
3490 if (track->mode == MODE_ISM)
3491 version = 1;
3492
3493 (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */
3494 ffio_wfourcc(pb, "tkhd");
3495 avio_w8(pb, version);
3496 avio_wb24(pb, flags);
3497 if (version == 1) {
3498 avio_wb64(pb, track->time);
3499 avio_wb64(pb, track->time);
3500 } else {
3501 avio_wb32(pb, track->time); /* creation time */
3502 avio_wb32(pb, track->time); /* modification time */
3503 }
3504 avio_wb32(pb, track->track_id); /* track-id */
3505 avio_wb32(pb, 0); /* reserved */
3506 if (!track->entry && mov->mode == MODE_ISM)
3507 (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
3508 else if (!track->entry)
3509 (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
3510 else
3511 (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration);
3512
3513 avio_wb32(pb, 0); /* reserved */
3514 avio_wb32(pb, 0); /* reserved */
3515 avio_wb16(pb, 0); /* layer */
3516 avio_wb16(pb, group); /* alternate group) */
3517 /* Volume, only for audio */
3518 if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
3519 avio_wb16(pb, 0x0100);
3520 else
3521 avio_wb16(pb, 0);
3522 avio_wb16(pb, 0); /* reserved */
3523
3524 /* Matrix structure */
3525 if (display_matrix) {
3526 for (i = 0; i < 9; i++)
3527 avio_wb32(pb, display_matrix[i]);
3528 } else {
3529 write_matrix(pb, 1, 0, 0, 1, 0, 0);
3530 }
3531 /* Track width and height, for visual only */
3532 if (st && (track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
3533 track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
3534 int64_t track_width_1616;
3535 if (track->mode == MODE_MOV || track->mode == MODE_AVIF) {
3536 track_width_1616 = track->par->width * 0x10000ULL;
3537 } else {
3538 track_width_1616 = av_rescale(st->sample_aspect_ratio.num,
3539 track->par->width * 0x10000LL,
3540 st->sample_aspect_ratio.den);
3541 if (!track_width_1616 ||
3542 track->height != track->par->height ||
3543 track_width_1616 > UINT32_MAX)
3544 track_width_1616 = track->par->width * 0x10000ULL;
3545 }
3546 if (track_width_1616 > UINT32_MAX) {
3547 av_log(mov->fc, AV_LOG_WARNING, "track width is too large\n");
3548 track_width_1616 = 0;
3549 }
3550 avio_wb32(pb, track_width_1616);
3551 if (track->height > 0xFFFF) {
3552 av_log(mov->fc, AV_LOG_WARNING, "track height is too large\n");
3553 avio_wb32(pb, 0);
3554 } else
3555 avio_wb32(pb, track->height * 0x10000U);
3556 } else {
3557 avio_wb32(pb, 0);
3558 avio_wb32(pb, 0);
3559 }
3560 return 0x5c;
3561 }
3562
3563 static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
3564 {
3565 int32_t width = av_rescale(track->par->sample_aspect_ratio.num, track->par->width,
3566 track->par->sample_aspect_ratio.den);
3567
3568 int64_t pos = avio_tell(pb);
3569
3570 avio_wb32(pb, 0); /* size */
3571 ffio_wfourcc(pb, "tapt");
3572
3573 avio_wb32(pb, 20);
3574 ffio_wfourcc(pb, "clef");
3575 avio_wb32(pb, 0);
3576 avio_wb32(pb, width << 16);
3577 avio_wb32(pb, track->par->height << 16);
3578
3579 avio_wb32(pb, 20);
3580 ffio_wfourcc(pb, "prof");
3581 avio_wb32(pb, 0);
3582 avio_wb32(pb, width << 16);
3583 avio_wb32(pb, track->par->height << 16);
3584
3585 avio_wb32(pb, 20);
3586 ffio_wfourcc(pb, "enof");
3587 avio_wb32(pb, 0);
3588 avio_wb32(pb, track->par->width << 16);
3589 avio_wb32(pb, track->par->height << 16);
3590
3591 return update_size(pb, pos);
3592 }
3593
3594 // This box seems important for the psp playback ... without it the movie seems to hang
3595 static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov,
3596 MOVTrack *track)
3597 {
3598 int64_t duration = av_rescale_rnd(calc_samples_pts_duration(mov, track),
3599 mov->movie_timescale, track->timescale,
3600 AV_ROUND_UP);
3601 int version = duration < INT32_MAX ? 0 : 1;
3602 int entry_size, entry_count, size;
3603 int64_t delay, start_ct = track->start_cts;
3604 int64_t start_dts = track->start_dts;
3605
3606 if (track->entry) {
3607 if (start_dts != track->cluster[0].dts || start_ct != track->cluster[0].cts) {
3608
3609 av_log(mov->fc, AV_LOG_DEBUG,
3610 "EDTS using dts:%"PRId64" cts:%d instead of dts:%"PRId64" cts:%"PRId64" tid:%d\n",
3611 track->cluster[0].dts, track->cluster[0].cts,
3612 start_dts, start_ct, track->track_id);
3613 start_dts = track->cluster[0].dts;
3614 start_ct = track->cluster[0].cts;
3615 }
3616 }
3617
3618 delay = av_rescale_rnd(start_dts + start_ct, mov->movie_timescale,
3619 track->timescale, AV_ROUND_DOWN);
3620 version |= delay < INT32_MAX ? 0 : 1;
3621
3622 entry_size = (version == 1) ? 20 : 12;
3623 entry_count = 1 + (delay > 0);
3624 size = 24 + entry_count * entry_size;
3625
3626 /* write the atom data */
3627 avio_wb32(pb, size);
3628 ffio_wfourcc(pb, "edts");
3629 avio_wb32(pb, size - 8);
3630 ffio_wfourcc(pb, "elst");
3631 avio_w8(pb, version);
3632 avio_wb24(pb, 0); /* flags */
3633
3634 avio_wb32(pb, entry_count);
3635 if (delay > 0) { /* add an empty edit to delay presentation */
3636 /* In the positive delay case, the delay includes the cts
3637 * offset, and the second edit list entry below trims out
3638 * the same amount from the actual content. This makes sure
3639 * that the offset last sample is included in the edit
3640 * list duration as well. */
3641 if (version == 1) {
3642 avio_wb64(pb, delay);
3643 avio_wb64(pb, -1);
3644 } else {
3645 avio_wb32(pb, delay);
3646 avio_wb32(pb, -1);
3647 }
3648 avio_wb32(pb, 0x00010000);
3649 } else {
3650 /* Avoid accidentally ending up with start_ct = -1 which has got a
3651 * special meaning. Normally start_ct should end up positive or zero
3652 * here, but use FFMIN in case dts is a small positive integer
3653 * rounded to 0 when represented in movie timescale units. */
3654 av_assert0(av_rescale_rnd(start_dts, mov->movie_timescale, track->timescale, AV_ROUND_DOWN) <= 0);
3655 start_ct = -FFMIN(start_dts, 0);
3656 /* Note, this delay is calculated from the pts of the first sample,
3657 * ensuring that we don't reduce the duration for cases with
3658 * dts<0 pts=0. */
3659 duration += delay;
3660 }
3661
3662 /* For fragmented files, we don't know the full length yet. Setting
3663 * duration to 0 allows us to only specify the offset, including
3664 * the rest of the content (from all future fragments) without specifying
3665 * an explicit duration. */
3666 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
3667 duration = 0;
3668
3669 /* duration */
3670 if (version == 1) {
3671 avio_wb64(pb, duration);
3672 avio_wb64(pb, start_ct);
3673 } else {
3674 avio_wb32(pb, duration);
3675 avio_wb32(pb, start_ct);
3676 }
3677 avio_wb32(pb, 0x00010000);
3678 return size;
3679 }
3680
3681 static int mov_write_tref_tag(AVIOContext *pb, MOVTrack *track)
3682 {
3683 #ifdef OHOS_TIMED_META_TRACK
3684 int64_t pos = avio_tell(pb);
3685 int tref_index;
3686 avio_wb32(pb, 0);
3687 ffio_wfourcc(pb, "tref");
3688 int64_t pos_cdsc = avio_tell(pb);
3689 avio_wb32(pb, 0);
3690 avio_wl32(pb, track->tref_tag);
3691 for (tref_index = 0; tref_index < track->ref_track_count; tref_index++) {
3692 avio_wb32(pb, track->tref_ids[tref_index]);
3693 }
3694 update_size(pb, pos_cdsc);
3695 return update_size(pb, pos);
3696 #else
3697 avio_wb32(pb, 20); // size
3698 ffio_wfourcc(pb, "tref");
3699 avio_wb32(pb, 12); // size (subatom)
3700 avio_wl32(pb, track->tref_tag);
3701 avio_wb32(pb, track->tref_id);
3702 return 20;
3703 #endif
3704 }
3705
3706 // goes at the end of each track! ... Critical for PSP playback ("Incompatible data" without it)
3707 static int mov_write_uuid_tag_psp(AVIOContext *pb, MOVTrack *mov)
3708 {
3709 avio_wb32(pb, 0x34); /* size ... reports as 28 in mp4box! */
3710 ffio_wfourcc(pb, "uuid");
3711 ffio_wfourcc(pb, "USMT");
3712 avio_wb32(pb, 0x21d24fce);
3713 avio_wb32(pb, 0xbb88695c);
3714 avio_wb32(pb, 0xfac9c740);
3715 avio_wb32(pb, 0x1c); // another size here!
3716 ffio_wfourcc(pb, "MTDT");
3717 avio_wb32(pb, 0x00010012);
3718 avio_wb32(pb, 0x0a);
3719 avio_wb32(pb, 0x55c40000);
3720 avio_wb32(pb, 0x1);
3721 avio_wb32(pb, 0x0);
3722 return 0x34;
3723 }
3724
3725 static int mov_write_udta_sdp(AVIOContext *pb, MOVTrack *track)
3726 {
3727 AVFormatContext *ctx = track->rtp_ctx;
3728 char buf[1000] = "";
3729 int len;
3730
3731 ff_sdp_write_media(buf, sizeof(buf), ctx->streams[0], track->src_track,
3732 NULL, NULL, 0, 0, ctx);
3733 av_strlcatf(buf, sizeof(buf), "a=control:streamid=%d\r\n", track->track_id);
3734 len = strlen(buf);
3735
3736 avio_wb32(pb, len + 24);
3737 ffio_wfourcc(pb, "udta");
3738 avio_wb32(pb, len + 16);
3739 ffio_wfourcc(pb, "hnti");
3740 avio_wb32(pb, len + 8);
3741 ffio_wfourcc(pb, "sdp ");
3742 avio_write(pb, buf, len);
3743 return len + 24;
3744 }
3745
3746 static int mov_write_track_metadata(AVIOContext *pb, AVStream *st,
3747 const char *tag, const char *str)
3748 {
3749 int64_t pos = avio_tell(pb);
3750 AVDictionaryEntry *t = av_dict_get(st->metadata, str, NULL, 0);
3751 if (!t || !utf8len(t->value))
3752 return 0;
3753
3754 avio_wb32(pb, 0); /* size */
3755 ffio_wfourcc(pb, tag); /* type */
3756 avio_write(pb, t->value, strlen(t->value)); /* UTF8 string value */
3757 return update_size(pb, pos);
3758 }
3759
3760 static int mov_write_track_kind(AVIOContext *pb, const char *scheme_uri,
3761 const char *value)
3762 {
3763 int64_t pos = avio_tell(pb);
3764
3765 /* Box|FullBox basics */
3766 avio_wb32(pb, 0); /* size placeholder */
3767 ffio_wfourcc(pb, (const unsigned char *)"kind");
3768 avio_w8(pb, 0); /* version = 0 */
3769 avio_wb24(pb, 0); /* flags = 0 */
3770
3771 /* Required null-terminated scheme URI */
3772 avio_write(pb, (const unsigned char *)scheme_uri,
3773 strlen(scheme_uri));
3774 avio_w8(pb, 0);
3775
3776 /* Optional value string */
3777 if (value && value[0])
3778 avio_write(pb, (const unsigned char *)value,
3779 strlen(value));
3780
3781 avio_w8(pb, 0);
3782
3783 return update_size(pb, pos);
3784 }
3785
3786 static int mov_write_track_kinds(AVIOContext *pb, AVStream *st)
3787 {
3788 int ret = AVERROR_BUG;
3789
3790 for (int i = 0; ff_mov_track_kind_table[i].scheme_uri; i++) {
3791 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
3792
3793 for (int j = 0; map.value_maps[j].disposition; j++) {
3794 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
3795 if (!(st->disposition & value_map.disposition))
3796 continue;
3797
3798 if ((ret = mov_write_track_kind(pb, map.scheme_uri, value_map.value)) < 0)
3799 return ret;
3800 }
3801 }
3802
3803 return 0;
3804 }
3805
3806 static int mov_write_track_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
3807 AVStream *st)
3808 {
3809 AVIOContext *pb_buf;
3810 int ret, size;
3811 uint8_t *buf;
3812
3813 if (!st)
3814 return 0;
3815
3816 ret = avio_open_dyn_buf(&pb_buf);
3817 if (ret < 0)
3818 return ret;
3819
3820 if (mov->mode & (MODE_MP4|MODE_MOV))
3821 mov_write_track_metadata(pb_buf, st, "name", "title");
3822
3823 if (mov->mode & MODE_MP4) {
3824 if ((ret = mov_write_track_kinds(pb_buf, st)) < 0)
3825 return ret;
3826 }
3827
3828 if ((size = avio_get_dyn_buf(pb_buf, &buf)) > 0) {
3829 avio_wb32(pb, size + 8);
3830 ffio_wfourcc(pb, "udta");
3831 avio_write(pb, buf, size);
3832 }
3833 ffio_free_dyn_buf(&pb_buf);
3834
3835 return 0;
3836 }
3837
3838 static int mov_write_trak_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov,
3839 MOVTrack *track, AVStream *st)
3840 {
3841 int64_t pos = avio_tell(pb);
3842 int entry_backup = track->entry;
3843 int chunk_backup = track->chunkCount;
3844 int ret;
3845
3846 /* If we want to have an empty moov, but some samples already have been
3847 * buffered (delay_moov), pretend that no samples have been written yet. */
3848 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV)
3849 track->chunkCount = track->entry = 0;
3850
3851 avio_wb32(pb, 0); /* size */
3852 ffio_wfourcc(pb, "trak");
3853 mov_write_tkhd_tag(pb, mov, track, st);
3854
3855 av_assert2(mov->use_editlist >= 0);
3856
3857 if (track->start_dts != AV_NOPTS_VALUE) {
3858 if (mov->use_editlist)
3859 mov_write_edts_tag(pb, mov, track); // PSP Movies and several other cases require edts box
3860 else if ((track->entry && track->cluster[0].dts) || track->mode == MODE_PSP || is_clcp_track(track))
3861 av_log(mov->fc, AV_LOG_WARNING,
3862 "Not writing any edit list even though one would have been required\n");
3863 }
3864
3865 if (track->tref_tag)
3866 mov_write_tref_tag(pb, track);
3867
3868 if ((ret = mov_write_mdia_tag(s, pb, mov, track)) < 0)
3869 return ret;
3870 if (track->mode == MODE_PSP)
3871 mov_write_uuid_tag_psp(pb, track); // PSP Movies require this uuid box
3872 if (track->tag == MKTAG('r','t','p',' '))
3873 mov_write_udta_sdp(pb, track);
3874 if (track->mode == MODE_MOV) {
3875 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
3876 double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
3877 if (st->sample_aspect_ratio.num && 1.0 != sample_aspect_ratio) {
3878 mov_write_tapt_tag(pb, track);
3879 }
3880 }
3881 if (is_clcp_track(track) && st->sample_aspect_ratio.num) {
3882 mov_write_tapt_tag(pb, track);
3883 }
3884 }
3885 mov_write_track_udta_tag(pb, mov, st);
3886 track->entry = entry_backup;
3887 track->chunkCount = chunk_backup;
3888 return update_size(pb, pos);
3889 }
3890
3891 static int mov_write_iods_tag(AVIOContext *pb, MOVMuxContext *mov)
3892 {
3893 int i, has_audio = 0, has_video = 0;
3894 int64_t pos = avio_tell(pb);
3895 int audio_profile = mov->iods_audio_profile;
3896 int video_profile = mov->iods_video_profile;
3897 for (i = 0; i < mov->nb_streams; i++) {
3898 if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
3899 has_audio |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_AUDIO;
3900 has_video |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_VIDEO;
3901 }
3902 }
3903 if (audio_profile < 0)
3904 audio_profile = 0xFF - has_audio;
3905 if (video_profile < 0)
3906 video_profile = 0xFF - has_video;
3907 avio_wb32(pb, 0x0); /* size */
3908 ffio_wfourcc(pb, "iods");
3909 avio_wb32(pb, 0); /* version & flags */
3910 put_descr(pb, 0x10, 7);
3911 avio_wb16(pb, 0x004f);
3912 avio_w8(pb, 0xff);
3913 avio_w8(pb, 0xff);
3914 avio_w8(pb, audio_profile);
3915 avio_w8(pb, video_profile);
3916 avio_w8(pb, 0xff);
3917 return update_size(pb, pos);
3918 }
3919
3920 static int mov_write_trex_tag(AVIOContext *pb, MOVTrack *track)
3921 {
3922 avio_wb32(pb, 0x20); /* size */
3923 ffio_wfourcc(pb, "trex");
3924 avio_wb32(pb, 0); /* version & flags */
3925 avio_wb32(pb, track->track_id); /* track ID */
3926 avio_wb32(pb, 1); /* default sample description index */
3927 avio_wb32(pb, 0); /* default sample duration */
3928 avio_wb32(pb, 0); /* default sample size */
3929 avio_wb32(pb, 0); /* default sample flags */
3930 return 0;
3931 }
3932
3933 static int mov_write_mvex_tag(AVIOContext *pb, MOVMuxContext *mov)
3934 {
3935 int64_t pos = avio_tell(pb);
3936 int i;
3937 avio_wb32(pb, 0x0); /* size */
3938 ffio_wfourcc(pb, "mvex");
3939 for (i = 0; i < mov->nb_streams; i++)
3940 mov_write_trex_tag(pb, &mov->tracks[i]);
3941 return update_size(pb, pos);
3942 }
3943
3944 static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov)
3945 {
3946 int max_track_id = 1, i;
3947 int64_t max_track_len = 0;
3948 int version;
3949 int timescale;
3950
3951 for (i = 0; i < mov->nb_streams; i++) {
3952 if (mov->tracks[i].entry > 0 && mov->tracks[i].timescale) {
3953 int64_t max_track_len_temp = av_rescale_rnd(
3954 calc_pts_duration(mov, &mov->tracks[i]),
3955 mov->movie_timescale,
3956 mov->tracks[i].timescale,
3957 AV_ROUND_UP);
3958 if (max_track_len < max_track_len_temp)
3959 max_track_len = max_track_len_temp;
3960 if (max_track_id < mov->tracks[i].track_id)
3961 max_track_id = mov->tracks[i].track_id;
3962 }
3963 }
3964 /* If using delay_moov, make sure the output is the same as if no
3965 * samples had been written yet. */
3966 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
3967 max_track_len = 0;
3968 max_track_id = 1;
3969 }
3970
3971 version = max_track_len < UINT32_MAX ? 0 : 1;
3972 avio_wb32(pb, version == 1 ? 120 : 108); /* size */
3973
3974 ffio_wfourcc(pb, "mvhd");
3975 avio_w8(pb, version);
3976 avio_wb24(pb, 0); /* flags */
3977 if (version == 1) {
3978 avio_wb64(pb, mov->time);
3979 avio_wb64(pb, mov->time);
3980 } else {
3981 avio_wb32(pb, mov->time); /* creation time */
3982 avio_wb32(pb, mov->time); /* modification time */
3983 }
3984
3985 timescale = mov->movie_timescale;
3986 if (mov->mode == MODE_AVIF && !timescale)
3987 timescale = mov->tracks[0].timescale;
3988
3989 avio_wb32(pb, timescale);
3990 (version == 1) ? avio_wb64(pb, max_track_len) : avio_wb32(pb, max_track_len); /* duration of longest track */
3991
3992 avio_wb32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
3993 avio_wb16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
3994 ffio_fill(pb, 0, 2 + 2 * 4); /* reserved */
3995
3996 /* Matrix structure */
3997 write_matrix(pb, 1, 0, 0, 1, 0, 0);
3998
3999 avio_wb32(pb, 0); /* reserved (preview time) */
4000 avio_wb32(pb, 0); /* reserved (preview duration) */
4001 avio_wb32(pb, 0); /* reserved (poster time) */
4002 avio_wb32(pb, 0); /* reserved (selection time) */
4003 avio_wb32(pb, 0); /* reserved (selection duration) */
4004 avio_wb32(pb, 0); /* reserved (current time) */
4005 avio_wb32(pb, max_track_id + 1); /* Next track id */
4006 return 0x6c;
4007 }
4008
4009 static int mov_write_itunes_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov,
4010 AVFormatContext *s)
4011 {
4012 avio_wb32(pb, 33); /* size */
4013 ffio_wfourcc(pb, "hdlr");
4014 avio_wb32(pb, 0);
4015 avio_wb32(pb, 0);
4016 ffio_wfourcc(pb, "mdir");
4017 ffio_wfourcc(pb, "appl");
4018 avio_wb32(pb, 0);
4019 avio_wb32(pb, 0);
4020 avio_w8(pb, 0);
4021 return 33;
4022 }
4023
4024 /* helper function to write a data tag with the specified string as data */
4025 static int mov_write_string_data_tag(AVIOContext *pb, const char *data, int lang, int long_style)
4026 {
4027 size_t data_len = strlen(data);
4028 if (long_style) {
4029 int size = 16 + data_len;
4030 avio_wb32(pb, size); /* size */
4031 ffio_wfourcc(pb, "data");
4032 avio_wb32(pb, 1);
4033 avio_wb32(pb, 0);
4034 avio_write(pb, data, data_len);
4035 return size;
4036 } else {
4037 avio_wb16(pb, data_len); /* string length */
4038 if (!lang)
4039 lang = ff_mov_iso639_to_lang("und", 1);
4040 avio_wb16(pb, lang);
4041 avio_write(pb, data, data_len);
4042 return data_len + 4;
4043 }
4044 }
4045
4046 #ifdef OHOS_MOOV_LEVEL_META
4047 static int mov_write_moov_level_meta_data_tag(AVIOContext *pb, const char *data)
4048 {
4049 size_t data_len = strlen(data);
4050 int size = 0;
4051 if (data_len >= 8) {
4052 if (strncmp(data, "00000001", 8) == 0) {
4053 size = 16 + data_len - 8;
4054 avio_wb32(pb, size); /* size */
4055 ffio_wfourcc(pb, "data");
4056 avio_wb32(pb, 1); // string
4057 avio_wb32(pb, 0);
4058 avio_write(pb, data + 8, data_len - 8);
4059 } else if (strncmp(data, "00000017", 8) == 0) {
4060 size = 16 + 4;
4061 avio_wb32(pb, size); /* size */
4062 ffio_wfourcc(pb, "data");
4063 avio_wb32(pb, 23); // float
4064 avio_wb32(pb, 0);
4065 avio_wb32(pb, av_float2int(atof(data + 8)));
4066 } else if (strncmp(data, "00000043", 8) == 0) {
4067 size = 16 + 4;
4068 avio_wb32(pb, size); /* size */
4069 ffio_wfourcc(pb, "data");
4070 avio_wb32(pb, 67); // int
4071 avio_wb32(pb, 0);
4072 avio_wb32(pb, atoi(data + 8));
4073 } else {
4074 size = 16 + 4;
4075 avio_wb32(pb, size); /* size */
4076 ffio_wfourcc(pb, "data");
4077 avio_wb32(pb, 77); // unkown
4078 avio_wb32(pb, 0);
4079 avio_wb32(pb, 0);
4080 }
4081 } else {
4082 size = 16 + data_len;
4083 avio_wb32(pb, size); /* size */
4084 ffio_wfourcc(pb, "data");
4085 avio_wb32(pb, 1); // default string
4086 avio_wb32(pb, 0);
4087 avio_write(pb, data, data_len);
4088 }
4089 return size;
4090 }
4091 #endif
4092
4093 static int mov_write_string_tag(AVIOContext *pb, const char *name,
4094 const char *value, int lang, int long_style)
4095 {
4096 int size = 0;
4097 if (value && value[0]) {
4098 int64_t pos = avio_tell(pb);
4099 avio_wb32(pb, 0); /* size */
4100 ffio_wfourcc(pb, name);
4101 mov_write_string_data_tag(pb, value, lang, long_style);
4102 size = update_size(pb, pos);
4103 }
4104 return size;
4105 }
4106
4107 static AVDictionaryEntry *get_metadata_lang(AVFormatContext *s,
4108 const char *tag, int *lang)
4109 {
4110 int l, len, len2;
4111 AVDictionaryEntry *t, *t2 = NULL;
4112 char tag2[16];
4113
4114 *lang = 0;
4115
4116 if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
4117 return NULL;
4118
4119 len = strlen(t->key);
4120 snprintf(tag2, sizeof(tag2), "%s-", tag);
4121 while ((t2 = av_dict_get(s->metadata, tag2, t2, AV_DICT_IGNORE_SUFFIX))) {
4122 len2 = strlen(t2->key);
4123 if (len2 == len + 4 && !strcmp(t->value, t2->value)
4124 && (l = ff_mov_iso639_to_lang(&t2->key[len2 - 3], 1)) >= 0) {
4125 *lang = l;
4126 return t;
4127 }
4128 }
4129 return t;
4130 }
4131
4132 static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb,
4133 const char *name, const char *tag,
4134 int long_style)
4135 {
4136 int lang;
4137 AVDictionaryEntry *t = get_metadata_lang(s, tag, &lang);
4138 if (!t)
4139 return 0;
4140 return mov_write_string_tag(pb, name, t->value, lang, long_style);
4141 }
4142
4143 /* iTunes bpm number */
4144 static int mov_write_tmpo_tag(AVIOContext *pb, AVFormatContext *s)
4145 {
4146 AVDictionaryEntry *t = av_dict_get(s->metadata, "tmpo", NULL, 0);
4147 int size = 0, tmpo = t ? atoi(t->value) : 0;
4148 if (tmpo) {
4149 size = 26;
4150 avio_wb32(pb, size);
4151 ffio_wfourcc(pb, "tmpo");
4152 avio_wb32(pb, size-8); /* size */
4153 ffio_wfourcc(pb, "data");
4154 avio_wb32(pb, 0x15); //type specifier
4155 avio_wb32(pb, 0);
4156 avio_wb16(pb, tmpo); // data
4157 }
4158 return size;
4159 }
4160
4161 /* 3GPP TS 26.244 */
4162 static int mov_write_loci_tag(AVFormatContext *s, AVIOContext *pb)
4163 {
4164 int lang;
4165 int64_t pos = avio_tell(pb);
4166 double latitude, longitude, altitude;
4167 int32_t latitude_fix, longitude_fix, altitude_fix;
4168 AVDictionaryEntry *t = get_metadata_lang(s, "location", &lang);
4169 const char *ptr, *place = "";
4170 char *end;
4171 static const char *astronomical_body = "earth";
4172 if (!t)
4173 return 0;
4174
4175 ptr = t->value;
4176 longitude = strtod(ptr, &end);
4177 if (end == ptr) {
4178 av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
4179 return 0;
4180 }
4181 ptr = end;
4182 latitude = strtod(ptr, &end);
4183 if (end == ptr) {
4184 av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
4185 return 0;
4186 }
4187 ptr = end;
4188 altitude = strtod(ptr, &end);
4189 /* If no altitude was present, the default 0 should be fine */
4190 if (*end == '/')
4191 place = end + 1;
4192
4193 latitude_fix = (int32_t) ((1 << 16) * latitude);
4194 longitude_fix = (int32_t) ((1 << 16) * longitude);
4195 altitude_fix = (int32_t) ((1 << 16) * altitude);
4196
4197 avio_wb32(pb, 0); /* size */
4198 ffio_wfourcc(pb, "loci"); /* type */
4199 avio_wb32(pb, 0); /* version + flags */
4200 avio_wb16(pb, lang);
4201 avio_write(pb, place, strlen(place) + 1);
4202 avio_w8(pb, 0); /* role of place (0 == shooting location, 1 == real location, 2 == fictional location) */
4203 #ifdef OHOS_MOOV_LEVEL_META
4204 /* fix save order, refer to 3GPP TS 26.244, ffmpeg7.0 */
4205 avio_wb32(pb, longitude_fix);
4206 avio_wb32(pb, latitude_fix);
4207 #else
4208 avio_wb32(pb, latitude_fix);
4209 avio_wb32(pb, longitude_fix);
4210 #endif
4211 avio_wb32(pb, altitude_fix);
4212 avio_write(pb, astronomical_body, strlen(astronomical_body) + 1);
4213 avio_w8(pb, 0); /* additional notes, null terminated string */
4214
4215 return update_size(pb, pos);
4216 }
4217
4218 #ifdef OHOS_MOOV_LEVEL_META
4219 static int mov_write_geo_tag(AVFormatContext *s, AVIOContext *pb)
4220 {
4221 int lang;
4222 int64_t pos = avio_tell(pb);
4223 float latitude, longitude, altitude;
4224 int32_t latitudex10000, longitudex10000, altitudex10000;
4225 AVDictionaryEntry *t = get_metadata_lang(s, "location", &lang);
4226 const char *ptr;
4227 char *end;
4228 if (!t)
4229 return 0;
4230
4231 ptr = t->value;
4232 longitude = strtof(ptr, &end);
4233 if (end == ptr) {
4234 av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
4235 return 0;
4236 }
4237 ptr = end;
4238 latitude = strtof(ptr, &end);
4239 if (end == ptr) {
4240 av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
4241 return 0;
4242 }
4243 ptr = end;
4244 altitude = strtof(ptr, &end);
4245
4246 latitudex10000 = (int32_t) (10000 * latitude);
4247 longitudex10000 = (int32_t) (10000 * longitude);
4248 altitudex10000 = (int32_t) (10000 * altitude);
4249 if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
4250 longitudex10000 < -1800000 || longitudex10000 > 1800000) {
4251 av_log(s, AV_LOG_WARNING, "longitude or latitude is not in range\n");
4252 return 0;
4253 }
4254
4255 // calc latitude
4256 int is_negative = latitudex10000 < 0;
4257 char sign = is_negative? '-' : '+';
4258 char latitude_str[9];
4259 memset(latitude_str, 0, sizeof(latitude_str));
4260 int32_t whole_part = latitudex10000 / 10000;
4261 if (whole_part == 0) {
4262 snprintf(latitude_str, 5, "%c%.2d.", sign, whole_part);
4263 } else {
4264 snprintf(latitude_str, 5, "%+.2d.", whole_part);
4265 }
4266 int32_t fraction_part = latitudex10000 - (whole_part * 10000);
4267 if (fraction_part < 0) {
4268 fraction_part = -fraction_part;
4269 }
4270 snprintf(&latitude_str[4], 5, "%.4d.", fraction_part);
4271
4272 // calc longitude
4273 is_negative = longitudex10000 < 0;
4274 sign = is_negative? '-' : '+';
4275 char longitude_str[10];
4276 memset(longitude_str, 0, sizeof(longitude_str));
4277 whole_part = longitudex10000 / 10000;
4278 if (whole_part == 0) {
4279 snprintf(longitude_str, 6, "%c%.3d.", sign, whole_part);
4280 } else {
4281 snprintf(longitude_str, 6, "%+.3d.", whole_part);
4282 }
4283 fraction_part = longitudex10000 - (whole_part * 10000);
4284 if (fraction_part < 0) {
4285 fraction_part = -fraction_part;
4286 }
4287 snprintf(&longitude_str[5], 5, "%.4d.", fraction_part);
4288
4289 avio_wb32(pb, 0); /* size */
4290 ffio_wfourcc(pb, "\xA9xyz"); /* type */
4291 avio_wb32(pb, 0x001215c7);
4292 avio_write(pb, latitude_str, 8);
4293 avio_write(pb, longitude_str, 9);
4294 avio_w8(pb, 0x2F);
4295 return update_size(pb, pos);
4296 }
4297
4298 static int mov_write_gnre_tag(AVIOContext* pb, MOVMuxContext* mov, AVFormatContext* s)
4299 {
4300 int64_t pos = avio_tell(pb);
4301 AVDictionaryEntry *t;
4302 if ((t = av_dict_get(s->metadata, "genre", NULL, 0))) {
4303 avio_wb32(pb, 0); /* size */
4304 ffio_wfourcc(pb, "gnre");
4305 avio_wb32(pb, 0);
4306 avio_wb16(pb, 0);
4307 avio_write(pb, t->value, strlen(t->value) + 1);
4308 avio_wb32(pb, 0);
4309 avio_wb32(pb, 0);
4310 }
4311 return update_size(pb, pos);
4312 }
4313 #endif
4314
4315 /* iTunes track or disc number */
4316 static int mov_write_trkn_tag(AVIOContext *pb, MOVMuxContext *mov,
4317 AVFormatContext *s, int disc)
4318 {
4319 AVDictionaryEntry *t = av_dict_get(s->metadata,
4320 disc ? "disc" : "track",
4321 NULL, 0);
4322 int size = 0, track = t ? atoi(t->value) : 0;
4323 if (track) {
4324 int tracks = 0;
4325 char *slash = strchr(t->value, '/');
4326 if (slash)
4327 tracks = atoi(slash + 1);
4328 avio_wb32(pb, 32); /* size */
4329 ffio_wfourcc(pb, disc ? "disk" : "trkn");
4330 avio_wb32(pb, 24); /* size */
4331 ffio_wfourcc(pb, "data");
4332 avio_wb32(pb, 0); // 8 bytes empty
4333 avio_wb32(pb, 0);
4334 avio_wb16(pb, 0); // empty
4335 avio_wb16(pb, track); // track / disc number
4336 avio_wb16(pb, tracks); // total track / disc number
4337 avio_wb16(pb, 0); // empty
4338 size = 32;
4339 }
4340 return size;
4341 }
4342
4343 static int mov_write_int8_metadata(AVFormatContext *s, AVIOContext *pb,
4344 const char *name, const char *tag,
4345 int len)
4346 {
4347 AVDictionaryEntry *t = NULL;
4348 uint8_t num;
4349 int size = 24 + len;
4350
4351 if (len != 1 && len != 4)
4352 return -1;
4353
4354 if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
4355 return 0;
4356 num = atoi(t->value);
4357
4358 avio_wb32(pb, size);
4359 ffio_wfourcc(pb, name);
4360 avio_wb32(pb, size - 8);
4361 ffio_wfourcc(pb, "data");
4362 avio_wb32(pb, 0x15);
4363 avio_wb32(pb, 0);
4364 if (len==4) avio_wb32(pb, num);
4365 else avio_w8 (pb, num);
4366
4367 return size;
4368 }
4369
4370 static int mov_write_covr(AVIOContext *pb, AVFormatContext *s)
4371 {
4372 MOVMuxContext *mov = s->priv_data;
4373 int64_t pos = 0;
4374 int i;
4375
4376 for (i = 0; i < s->nb_streams; i++) {
4377 MOVTrack *trk = &mov->tracks[i];
4378
4379 if (!is_cover_image(trk->st) || trk->cover_image->size <= 0)
4380 continue;
4381
4382 if (!pos) {
4383 pos = avio_tell(pb);
4384 avio_wb32(pb, 0);
4385 ffio_wfourcc(pb, "covr");
4386 }
4387 avio_wb32(pb, 16 + trk->cover_image->size);
4388 ffio_wfourcc(pb, "data");
4389 avio_wb32(pb, trk->tag);
4390 avio_wb32(pb , 0);
4391 avio_write(pb, trk->cover_image->data, trk->cover_image->size);
4392 }
4393
4394 return pos ? update_size(pb, pos) : 0;
4395 }
4396
4397 /* iTunes meta data list */
4398 static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
4399 AVFormatContext *s)
4400 {
4401 int64_t pos = avio_tell(pb);
4402 avio_wb32(pb, 0); /* size */
4403 ffio_wfourcc(pb, "ilst");
4404 mov_write_string_metadata(s, pb, "\251nam", "title" , 1);
4405 mov_write_string_metadata(s, pb, "\251ART", "artist" , 1);
4406 mov_write_string_metadata(s, pb, "aART", "album_artist", 1);
4407 mov_write_string_metadata(s, pb, "\251wrt", "composer" , 1);
4408 mov_write_string_metadata(s, pb, "\251alb", "album" , 1);
4409 mov_write_string_metadata(s, pb, "\251day", "date" , 1);
4410 if (!mov_write_string_metadata(s, pb, "\251too", "encoding_tool", 1)) {
4411 if (!(s->flags & AVFMT_FLAG_BITEXACT))
4412 mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1);
4413 }
4414 mov_write_string_metadata(s, pb, "\251cmt", "comment" , 1);
4415 mov_write_string_metadata(s, pb, "\251gen", "genre" , 1);
4416 mov_write_string_metadata(s, pb, "cprt", "copyright", 1);
4417 mov_write_string_metadata(s, pb, "\251grp", "grouping" , 1);
4418 mov_write_string_metadata(s, pb, "\251lyr", "lyrics" , 1);
4419 mov_write_string_metadata(s, pb, "desc", "description",1);
4420 mov_write_string_metadata(s, pb, "ldes", "synopsis" , 1);
4421 mov_write_string_metadata(s, pb, "tvsh", "show" , 1);
4422 mov_write_string_metadata(s, pb, "tven", "episode_id",1);
4423 mov_write_string_metadata(s, pb, "tvnn", "network" , 1);
4424 mov_write_string_metadata(s, pb, "keyw", "keywords" , 1);
4425 mov_write_int8_metadata (s, pb, "tves", "episode_sort",4);
4426 mov_write_int8_metadata (s, pb, "tvsn", "season_number",4);
4427 mov_write_int8_metadata (s, pb, "stik", "media_type",1);
4428 mov_write_int8_metadata (s, pb, "hdvd", "hd_video", 1);
4429 mov_write_int8_metadata (s, pb, "pgap", "gapless_playback",1);
4430 mov_write_int8_metadata (s, pb, "cpil", "compilation", 1);
4431 mov_write_covr(pb, s);
4432 mov_write_trkn_tag(pb, mov, s, 0); // track number
4433 mov_write_trkn_tag(pb, mov, s, 1); // disc number
4434 mov_write_tmpo_tag(pb, s);
4435 return update_size(pb, pos);
4436 }
4437
4438 static int mov_write_mdta_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov,
4439 AVFormatContext *s)
4440 {
4441 avio_wb32(pb, 33); /* size */
4442 ffio_wfourcc(pb, "hdlr");
4443 avio_wb32(pb, 0);
4444 avio_wb32(pb, 0);
4445 ffio_wfourcc(pb, "mdta");
4446 avio_wb32(pb, 0);
4447 avio_wb32(pb, 0);
4448 avio_wb32(pb, 0);
4449 avio_w8(pb, 0);
4450 return 33;
4451 }
4452
4453 static int mov_write_mdta_keys_tag(AVIOContext *pb, MOVMuxContext *mov,
4454 AVFormatContext *s)
4455 {
4456 AVDictionaryEntry *t = NULL;
4457 int64_t pos = avio_tell(pb);
4458 int64_t curpos, entry_pos;
4459 int count = 0;
4460
4461 avio_wb32(pb, 0); /* size */
4462 ffio_wfourcc(pb, "keys");
4463 avio_wb32(pb, 0);
4464 entry_pos = avio_tell(pb);
4465 avio_wb32(pb, 0); /* entry count */
4466
4467 while (t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) {
4468 size_t key_len = strlen(t->key);
4469 avio_wb32(pb, key_len + 8);
4470 ffio_wfourcc(pb, "mdta");
4471 avio_write(pb, t->key, key_len);
4472 count += 1;
4473 }
4474 curpos = avio_tell(pb);
4475 avio_seek(pb, entry_pos, SEEK_SET);
4476 avio_wb32(pb, count); // rewrite entry count
4477 avio_seek(pb, curpos, SEEK_SET);
4478
4479 return update_size(pb, pos);
4480 }
4481
4482 static int mov_write_mdta_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
4483 AVFormatContext *s)
4484 {
4485 AVDictionaryEntry *t = NULL;
4486 int64_t pos = avio_tell(pb);
4487 int count = 1; /* keys are 1-index based */
4488
4489 avio_wb32(pb, 0); /* size */
4490 ffio_wfourcc(pb, "ilst");
4491
4492 while (t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) {
4493 int64_t entry_pos = avio_tell(pb);
4494 avio_wb32(pb, 0); /* size */
4495 avio_wb32(pb, count); /* key */
4496 mov_write_string_data_tag(pb, t->value, 0, 1);
4497 update_size(pb, entry_pos);
4498 count += 1;
4499 }
4500 return update_size(pb, pos);
4501 }
4502
4503 /* meta data tags */
4504 static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov,
4505 AVFormatContext *s)
4506 {
4507 int size = 0;
4508 int64_t pos = avio_tell(pb);
4509 avio_wb32(pb, 0); /* size */
4510 ffio_wfourcc(pb, "meta");
4511 avio_wb32(pb, 0);
4512 if (mov->flags & FF_MOV_FLAG_USE_MDTA) {
4513 mov_write_mdta_hdlr_tag(pb, mov, s);
4514 mov_write_mdta_keys_tag(pb, mov, s);
4515 mov_write_mdta_ilst_tag(pb, mov, s);
4516 } else if (mov->mode == MODE_AVIF) {
4517 mov_write_hdlr_tag(s, pb, &mov->tracks[0]);
4518 // We always write the primary item id as 1 since only one track is
4519 // supported for AVIF.
4520 mov_write_pitm_tag(pb, 1);
4521 mov_write_iloc_tag(pb, mov, s);
4522 mov_write_iinf_tag(pb, mov, s);
4523 if (s->nb_streams > 1)
4524 mov_write_iref_tag(pb, mov, s);
4525 mov_write_iprp_tag(pb, mov, s);
4526 } else {
4527 /* iTunes metadata tag */
4528 mov_write_itunes_hdlr_tag(pb, mov, s);
4529 mov_write_ilst_tag(pb, mov, s);
4530 }
4531 size = update_size(pb, pos);
4532 return size;
4533 }
4534
4535 #ifdef OHOS_MOOV_LEVEL_META
4536 static int mov_write_moov_level_meta_mdta_keys_tag(AVIOContext *pb, MOVMuxContext *mov,
4537 AVFormatContext *s)
4538 {
4539 const AVDictionaryEntry *t = NULL;
4540 int64_t pos = avio_tell(pb);
4541 int64_t curpos, entry_pos;
4542 int count = 0;
4543
4544 avio_wb32(pb, 0); /* size */
4545 ffio_wfourcc(pb, "keys");
4546 avio_wb32(pb, 0);
4547 entry_pos = avio_tell(pb);
4548 avio_wb32(pb, 0); /* entry count */
4549
4550 const char *key_tag = "moov_level_meta_key_";
4551 size_t key_tag_len = strlen(key_tag);
4552 while (t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) {
4553 size_t key_len = strlen(t->key);
4554 if (key_len > key_tag_len && strncmp(t->key, key_tag, key_tag_len) == 0) {
4555 avio_wb32(pb, key_len + 8 - key_tag_len);
4556 ffio_wfourcc(pb, "mdta");
4557 avio_write(pb, t->key + key_tag_len, key_len - key_tag_len);
4558 count += 1;
4559 }
4560 }
4561 curpos = avio_tell(pb);
4562 avio_seek(pb, entry_pos, SEEK_SET);
4563 avio_wb32(pb, count); // rewrite entry count
4564 avio_seek(pb, curpos, SEEK_SET);
4565
4566 return update_size(pb, pos);
4567 }
4568
4569 static int mov_write_moov_level_meta_mdta_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
4570 AVFormatContext *s)
4571 {
4572 const AVDictionaryEntry *t = NULL;
4573 int64_t pos = avio_tell(pb);
4574 int count = 1; /* keys are 1-index based */
4575
4576 avio_wb32(pb, 0); /* size */
4577 ffio_wfourcc(pb, "ilst");
4578
4579 const char *key_tag = "moov_level_meta_key_";
4580 size_t key_tag_len = strlen(key_tag);
4581 while (t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) {
4582 size_t key_len = strlen(t->key);
4583 if (key_len > key_tag_len && strncmp(t->key, key_tag, key_tag_len) == 0) {
4584 int64_t entry_pos = avio_tell(pb);
4585 avio_wb32(pb, 0); /* size */
4586 avio_wb32(pb, count); /* key */
4587 mov_write_moov_level_meta_data_tag(pb, t->value);
4588 update_size(pb, entry_pos);
4589 count += 1;
4590 }
4591 }
4592 return update_size(pb, pos);
4593 }
4594
4595 static int mov_write_moov_level_meta_tag(AVIOContext *pb, MOVMuxContext *mov,
4596 AVFormatContext *s)
4597 {
4598 int size = 0;
4599 int64_t pos = avio_tell(pb);
4600 avio_wb32(pb, 0); /* size */
4601 ffio_wfourcc(pb, "meta");
4602 avio_wb32(pb, 0);
4603 mov_write_mdta_hdlr_tag(pb, mov, s);
4604 mov_write_moov_level_meta_mdta_keys_tag(pb, mov, s);
4605 mov_write_moov_level_meta_mdta_ilst_tag(pb, mov, s);
4606 size = update_size(pb, pos);
4607 return size;
4608 }
4609 #endif
4610
4611 static int mov_write_raw_metadata_tag(AVFormatContext *s, AVIOContext *pb,
4612 const char *name, const char *key)
4613 {
4614 int len;
4615 AVDictionaryEntry *t;
4616
4617 if (!(t = av_dict_get(s->metadata, key, NULL, 0)))
4618 return 0;
4619
4620 len = strlen(t->value);
4621 if (len > 0) {
4622 int size = len + 8;
4623 avio_wb32(pb, size);
4624 ffio_wfourcc(pb, name);
4625 avio_write(pb, t->value, len);
4626 return size;
4627 }
4628 return 0;
4629 }
4630
4631 static int ascii_to_wc(AVIOContext *pb, const uint8_t *b)
4632 {
4633 int val;
4634 while (*b) {
4635 GET_UTF8(val, *b++, return -1;)
4636 avio_wb16(pb, val);
4637 }
4638 avio_wb16(pb, 0x00);
4639 return 0;
4640 }
4641
4642 static uint16_t language_code(const char *str)
4643 {
4644 return (((str[0] - 0x60) & 0x1F) << 10) +
4645 (((str[1] - 0x60) & 0x1F) << 5) +
4646 (( str[2] - 0x60) & 0x1F);
4647 }
4648
4649 static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s,
4650 const char *tag, const char *str)
4651 {
4652 int64_t pos = avio_tell(pb);
4653 AVDictionaryEntry *t = av_dict_get(s->metadata, str, NULL, 0);
4654 if (!t || !utf8len(t->value))
4655 return 0;
4656 avio_wb32(pb, 0); /* size */
4657 ffio_wfourcc(pb, tag); /* type */
4658 avio_wb32(pb, 0); /* version + flags */
4659 if (!strcmp(tag, "yrrc"))
4660 avio_wb16(pb, atoi(t->value));
4661 else {
4662 avio_wb16(pb, language_code("eng")); /* language */
4663 avio_write(pb, t->value, strlen(t->value) + 1); /* UTF8 string value */
4664 if (!strcmp(tag, "albm") &&
4665 (t = av_dict_get(s->metadata, "track", NULL, 0)))
4666 avio_w8(pb, atoi(t->value));
4667 }
4668 return update_size(pb, pos);
4669 }
4670
4671 static int mov_write_chpl_tag(AVIOContext *pb, AVFormatContext *s)
4672 {
4673 int64_t pos = avio_tell(pb);
4674 int i, nb_chapters = FFMIN(s->nb_chapters, 255);
4675
4676 avio_wb32(pb, 0); // size
4677 ffio_wfourcc(pb, "chpl");
4678 avio_wb32(pb, 0x01000000); // version + flags
4679 avio_wb32(pb, 0); // unknown
4680 avio_w8(pb, nb_chapters);
4681
4682 for (i = 0; i < nb_chapters; i++) {
4683 AVChapter *c = s->chapters[i];
4684 AVDictionaryEntry *t;
4685 avio_wb64(pb, av_rescale_q(c->start, c->time_base, (AVRational){1,10000000}));
4686
4687 if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
4688 int len = FFMIN(strlen(t->value), 255);
4689 avio_w8(pb, len);
4690 avio_write(pb, t->value, len);
4691 } else
4692 avio_w8(pb, 0);
4693 }
4694 return update_size(pb, pos);
4695 }
4696
4697 static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
4698 AVFormatContext *s)
4699 {
4700 AVIOContext *pb_buf;
4701 int ret, size;
4702 uint8_t *buf;
4703
4704 ret = avio_open_dyn_buf(&pb_buf);
4705 if (ret < 0)
4706 return ret;
4707
4708 if (mov->mode & MODE_3GP) {
4709 mov_write_3gp_udta_tag(pb_buf, s, "perf", "artist");
4710 mov_write_3gp_udta_tag(pb_buf, s, "titl", "title");
4711 mov_write_3gp_udta_tag(pb_buf, s, "auth", "author");
4712 mov_write_3gp_udta_tag(pb_buf, s, "gnre", "genre");
4713 mov_write_3gp_udta_tag(pb_buf, s, "dscp", "comment");
4714 mov_write_3gp_udta_tag(pb_buf, s, "albm", "album");
4715 mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
4716 mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date");
4717 mov_write_loci_tag(s, pb_buf);
4718 } 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
4719 mov_write_string_metadata(s, pb_buf, "\251ART", "artist", 0);
4720 mov_write_string_metadata(s, pb_buf, "\251nam", "title", 0);
4721 mov_write_string_metadata(s, pb_buf, "\251aut", "author", 0);
4722 mov_write_string_metadata(s, pb_buf, "\251alb", "album", 0);
4723 mov_write_string_metadata(s, pb_buf, "\251day", "date", 0);
4724 mov_write_string_metadata(s, pb_buf, "\251swr", "encoder", 0);
4725 // currently ignored by mov.c
4726 mov_write_string_metadata(s, pb_buf, "\251des", "comment", 0);
4727 // add support for libquicktime, this atom is also actually read by mov.c
4728 mov_write_string_metadata(s, pb_buf, "\251cmt", "comment", 0);
4729 mov_write_string_metadata(s, pb_buf, "\251gen", "genre", 0);
4730 mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright", 0);
4731 mov_write_string_metadata(s, pb_buf, "\251mak", "make", 0);
4732 mov_write_string_metadata(s, pb_buf, "\251mod", "model", 0);
4733 mov_write_string_metadata(s, pb_buf, "\251xyz", "location", 0);
4734 mov_write_string_metadata(s, pb_buf, "\251key", "keywords", 0);
4735 mov_write_raw_metadata_tag(s, pb_buf, "XMP_", "xmp");
4736 } else {
4737 #ifdef OHOS_MOOV_LEVEL_META
4738 if (av_dict_get(s->metadata, "moov_level_meta_flag", NULL, 0)) {
4739 mov_write_geo_tag(s, pb_buf);
4740 }
4741 #endif
4742 /* iTunes meta data */
4743 mov_write_meta_tag(pb_buf, mov, s);
4744 mov_write_loci_tag(s, pb_buf);
4745 }
4746
4747 if (s->nb_chapters && !(mov->flags & FF_MOV_FLAG_DISABLE_CHPL))
4748 mov_write_chpl_tag(pb_buf, s);
4749
4750 if ((size = avio_get_dyn_buf(pb_buf, &buf)) > 0) {
4751 avio_wb32(pb, size + 8);
4752 ffio_wfourcc(pb, "udta");
4753 avio_write(pb, buf, size);
4754 }
4755 ffio_free_dyn_buf(&pb_buf);
4756
4757 return 0;
4758 }
4759
4760 static void mov_write_psp_udta_tag(AVIOContext *pb,
4761 const char *str, const char *lang, int type)
4762 {
4763 int len = utf8len(str) + 1;
4764 if (len <= 0)
4765 return;
4766 avio_wb16(pb, len * 2 + 10); /* size */
4767 avio_wb32(pb, type); /* type */
4768 avio_wb16(pb, language_code(lang)); /* language */
4769 avio_wb16(pb, 0x01); /* ? */
4770 ascii_to_wc(pb, str);
4771 }
4772
4773 static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s)
4774 {
4775 AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
4776 int64_t pos, pos2;
4777
4778 if (title) {
4779 pos = avio_tell(pb);
4780 avio_wb32(pb, 0); /* size placeholder*/
4781 ffio_wfourcc(pb, "uuid");
4782 ffio_wfourcc(pb, "USMT");
4783 avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
4784 avio_wb32(pb, 0xbb88695c);
4785 avio_wb32(pb, 0xfac9c740);
4786
4787 pos2 = avio_tell(pb);
4788 avio_wb32(pb, 0); /* size placeholder*/
4789 ffio_wfourcc(pb, "MTDT");
4790 avio_wb16(pb, 4);
4791
4792 // ?
4793 avio_wb16(pb, 0x0C); /* size */
4794 avio_wb32(pb, 0x0B); /* type */
4795 avio_wb16(pb, language_code("und")); /* language */
4796 avio_wb16(pb, 0x0); /* ? */
4797 avio_wb16(pb, 0x021C); /* data */
4798
4799 if (!(s->flags & AVFMT_FLAG_BITEXACT))
4800 mov_write_psp_udta_tag(pb, LIBAVFORMAT_IDENT, "eng", 0x04);
4801 mov_write_psp_udta_tag(pb, title->value, "eng", 0x01);
4802 mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03);
4803
4804 update_size(pb, pos2);
4805 return update_size(pb, pos);
4806 }
4807
4808 return 0;
4809 }
4810
4811 static void build_chunks(MOVTrack *trk)
4812 {
4813 int i;
4814 MOVIentry *chunk = &trk->cluster[0];
4815 uint64_t chunkSize = chunk->size;
4816 chunk->chunkNum = 1;
4817 if (trk->chunkCount)
4818 return;
4819 trk->chunkCount = 1;
4820 for (i = 1; i<trk->entry; i++){
4821 if (chunk->pos + chunkSize == trk->cluster[i].pos &&
4822 chunkSize + trk->cluster[i].size < (1<<20)){
4823 chunkSize += trk->cluster[i].size;
4824 chunk->samples_in_chunk += trk->cluster[i].entries;
4825 } else {
4826 trk->cluster[i].chunkNum = chunk->chunkNum+1;
4827 chunk=&trk->cluster[i];
4828 chunkSize = chunk->size;
4829 trk->chunkCount++;
4830 }
4831 }
4832 }
4833
4834 /**
4835 * Assign track ids. If option "use_stream_ids_as_track_ids" is set,
4836 * the stream ids are used as track ids.
4837 *
4838 * This assumes mov->tracks and s->streams are in the same order and
4839 * there are no gaps in either of them (so mov->tracks[n] refers to
4840 * s->streams[n]).
4841 *
4842 * As an exception, there can be more entries in
4843 * s->streams than in mov->tracks, in which case new track ids are
4844 * generated (starting after the largest found stream id).
4845 */
4846 static int mov_setup_track_ids(MOVMuxContext *mov, AVFormatContext *s)
4847 {
4848 int i;
4849
4850 if (mov->track_ids_ok)
4851 return 0;
4852
4853 if (mov->use_stream_ids_as_track_ids) {
4854 int next_generated_track_id = 0;
4855 for (i = 0; i < s->nb_streams; i++) {
4856 if (s->streams[i]->id > next_generated_track_id)
4857 next_generated_track_id = s->streams[i]->id;
4858 }
4859
4860 for (i = 0; i < mov->nb_streams; i++) {
4861 if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
4862 continue;
4863
4864 mov->tracks[i].track_id = i >= s->nb_streams ? ++next_generated_track_id : s->streams[i]->id;
4865 }
4866 } else {
4867 for (i = 0; i < mov->nb_streams; i++) {
4868 if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
4869 continue;
4870
4871 mov->tracks[i].track_id = i + 1;
4872 }
4873 }
4874
4875 mov->track_ids_ok = 1;
4876
4877 return 0;
4878 }
4879
4880 static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
4881 AVFormatContext *s)
4882 {
4883 int i;
4884 int64_t pos = avio_tell(pb);
4885 avio_wb32(pb, 0); /* size placeholder*/
4886 ffio_wfourcc(pb, "moov");
4887
4888 mov_setup_track_ids(mov, s);
4889
4890 for (i = 0; i < mov->nb_streams; i++) {
4891 if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT))
4892 continue;
4893
4894 mov->tracks[i].time = mov->time;
4895
4896 if (mov->tracks[i].entry)
4897 build_chunks(&mov->tracks[i]);
4898 }
4899
4900 if (mov->chapter_track)
4901 for (i = 0; i < s->nb_streams; i++) {
4902 mov->tracks[i].tref_tag = MKTAG('c','h','a','p');
4903 #ifdef OHOS_TIMED_META_TRACK
4904 mov->tracks[i].ref_track_count++;
4905 mov->tracks[i].tref_ids[0] = mov->tracks[mov->chapter_track].track_id;
4906 #else
4907 mov->tracks[i].tref_id = mov->tracks[mov->chapter_track].track_id;
4908 #endif
4909 }
4910 for (i = 0; i < mov->nb_streams; i++) {
4911 MOVTrack *track = &mov->tracks[i];
4912 if (track->tag == MKTAG('r','t','p',' ')) {
4913 track->tref_tag = MKTAG('h','i','n','t');
4914 #ifdef OHOS_TIMED_META_TRACK
4915 track->ref_track_count++;
4916 track->tref_ids[0] = mov->tracks[track->src_track].track_id;
4917 #else
4918 track->tref_id = mov->tracks[track->src_track].track_id;
4919 #endif
4920 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
4921 size_t size;
4922 int *fallback;
4923 fallback = (int*)av_stream_get_side_data(track->st,
4924 AV_PKT_DATA_FALLBACK_TRACK,
4925 &size);
4926 if (fallback != NULL && size == sizeof(int)) {
4927 if (*fallback >= 0 && *fallback < mov->nb_streams) {
4928 track->tref_tag = MKTAG('f','a','l','l');
4929 #ifdef OHOS_TIMED_META_TRACK
4930 track->ref_track_count++;
4931 track->tref_ids[0] = mov->tracks[*fallback].track_id;
4932 #else
4933 track->tref_id = mov->tracks[*fallback].track_id;
4934 #endif
4935 }
4936 }
4937 }
4938 }
4939 for (i = 0; i < mov->nb_streams; i++) {
4940 if (mov->tracks[i].tag == MKTAG('t','m','c','d')) {
4941 int src_trk = mov->tracks[i].src_track;
4942 mov->tracks[src_trk].tref_tag = mov->tracks[i].tag;
4943 #ifdef OHOS_TIMED_META_TRACK
4944 mov->tracks[src_trk].ref_track_count++;
4945 mov->tracks[src_trk].tref_ids[0] = mov->tracks[i].track_id;
4946 #else
4947 mov->tracks[src_trk].tref_id = mov->tracks[i].track_id;
4948 #endif
4949 //src_trk may have a different timescale than the tmcd track
4950 mov->tracks[i].track_duration = av_rescale(mov->tracks[src_trk].track_duration,
4951 mov->tracks[i].timescale,
4952 mov->tracks[src_trk].timescale);
4953 }
4954 }
4955 #ifdef OHOS_TIMED_META_TRACK
4956 for (i = 0; i < mov->nb_streams; i++) {
4957 if (mov->tracks[i].tag == MKTAG('c','d','s','c')) {
4958 int src_trk = mov->tracks[i].src_track;
4959 for (int j = 0; j < mov->tracks[i].ref_track_count; j++) {
4960 mov->tracks[i].tref_ids[j] = mov->tracks[src_trk].track_id;
4961 }
4962 }
4963 }
4964 #endif
4965
4966 mov_write_mvhd_tag(pb, mov);
4967 if (mov->mode != MODE_MOV && mov->mode != MODE_AVIF && !mov->iods_skip)
4968 mov_write_iods_tag(pb, mov);
4969 for (i = 0; i < mov->nb_streams; i++) {
4970 if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_FRAGMENT ||
4971 mov->mode == MODE_AVIF) {
4972 int ret = mov_write_trak_tag(s, pb, mov, &(mov->tracks[i]), i < s->nb_streams ? s->streams[i] : NULL);
4973 if (ret < 0)
4974 return ret;
4975 }
4976 }
4977 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
4978 mov_write_mvex_tag(pb, mov); /* QuickTime requires trak to precede this */
4979
4980 if (mov->mode == MODE_PSP)
4981 mov_write_uuidusmt_tag(pb, s);
4982 else if (mov->mode != MODE_AVIF)
4983 mov_write_udta_tag(pb, mov, s);
4984
4985 #ifdef OHOS_MOOV_LEVEL_META
4986 if (av_dict_get(s->metadata, "moov_level_meta_flag", NULL, 0)) {
4987 mov_write_gnre_tag(pb, mov, s);
4988 mov_write_moov_level_meta_tag(pb, mov, s);
4989 }
4990 #endif
4991
4992 return update_size(pb, pos);
4993 }
4994
4995 static void param_write_int(AVIOContext *pb, const char *name, int value)
4996 {
4997 avio_printf(pb, "<param name=\"%s\" value=\"%d\" valuetype=\"data\"/>\n", name, value);
4998 }
4999
5000 static void param_write_string(AVIOContext *pb, const char *name, const char *value)
5001 {
5002 avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, value);
5003 }
5004
5005 static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *value, int len)
5006 {
5007 char buf[150];
5008 len = FFMIN(sizeof(buf) / 2 - 1, len);
5009 ff_data_to_hex(buf, value, len, 0);
5010 avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, buf);
5011 }
5012
5013 static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
5014 {
5015 int64_t pos = avio_tell(pb);
5016 int i;
5017
5018 static const AVUUID uuid = {
5019 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
5020 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
5021 };
5022
5023 avio_wb32(pb, 0);
5024 ffio_wfourcc(pb, "uuid");
5025 avio_write(pb, uuid, AV_UUID_LEN);
5026 avio_wb32(pb, 0);
5027
5028 avio_printf(pb, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
5029 avio_printf(pb, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
5030 avio_printf(pb, "<head>\n");
5031 if (!(mov->fc->flags & AVFMT_FLAG_BITEXACT))
5032 avio_printf(pb, "<meta name=\"creator\" content=\"%s\" />\n",
5033 LIBAVFORMAT_IDENT);
5034 avio_printf(pb, "</head>\n");
5035 avio_printf(pb, "<body>\n");
5036 avio_printf(pb, "<switch>\n");
5037
5038 mov_setup_track_ids(mov, s);
5039
5040 for (i = 0; i < mov->nb_streams; i++) {
5041 MOVTrack *track = &mov->tracks[i];
5042 struct mpeg4_bit_rate_values bit_rates =
5043 calculate_mpeg4_bit_rates(track);
5044 const char *type;
5045 int track_id = track->track_id;
5046 char track_name_buf[32] = { 0 };
5047
5048 AVStream *st = track->st;
5049 AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
5050
5051 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && !is_cover_image(st)) {
5052 type = "video";
5053 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
5054 type = "audio";
5055 } else {
5056 continue;
5057 }
5058
5059 avio_printf(pb, "<%s systemBitrate=\"%"PRIu32"\">\n", type,
5060 bit_rates.avg_bit_rate);
5061 param_write_int(pb, "systemBitrate", bit_rates.avg_bit_rate);
5062 param_write_int(pb, "trackID", track_id);
5063 param_write_string(pb, "systemLanguage", lang ? lang->value : "und");
5064
5065 /* Build track name piece by piece: */
5066 /* 1. track type */
5067 av_strlcat(track_name_buf, type, sizeof(track_name_buf));
5068 /* 2. track language, if available */
5069 if (lang)
5070 av_strlcatf(track_name_buf, sizeof(track_name_buf),
5071 "_%s", lang->value);
5072 /* 3. special type suffix */
5073 /* "_cc" = closed captions, "_ad" = audio_description */
5074 if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
5075 av_strlcat(track_name_buf, "_cc", sizeof(track_name_buf));
5076 else if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
5077 av_strlcat(track_name_buf, "_ad", sizeof(track_name_buf));
5078
5079 param_write_string(pb, "trackName", track_name_buf);
5080
5081 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
5082 if (track->par->codec_id == AV_CODEC_ID_H264) {
5083 uint8_t *ptr;
5084 int size = track->par->extradata_size;
5085 if (!ff_avc_write_annexb_extradata(track->par->extradata, &ptr,
5086 &size)) {
5087 param_write_hex(pb, "CodecPrivateData",
5088 ptr ? ptr : track->par->extradata,
5089 size);
5090 av_free(ptr);
5091 }
5092 param_write_string(pb, "FourCC", "H264");
5093 } else if (track->par->codec_id == AV_CODEC_ID_VC1) {
5094 param_write_string(pb, "FourCC", "WVC1");
5095 param_write_hex(pb, "CodecPrivateData", track->par->extradata,
5096 track->par->extradata_size);
5097 }
5098 param_write_int(pb, "MaxWidth", track->par->width);
5099 param_write_int(pb, "MaxHeight", track->par->height);
5100 param_write_int(pb, "DisplayWidth", track->par->width);
5101 param_write_int(pb, "DisplayHeight", track->par->height);
5102 } else {
5103 if (track->par->codec_id == AV_CODEC_ID_AAC) {
5104 switch (track->par->profile)
5105 {
5106 case FF_PROFILE_AAC_HE_V2:
5107 param_write_string(pb, "FourCC", "AACP");
5108 break;
5109 case FF_PROFILE_AAC_HE:
5110 param_write_string(pb, "FourCC", "AACH");
5111 break;
5112 default:
5113 param_write_string(pb, "FourCC", "AACL");
5114 }
5115 } else if (track->par->codec_id == AV_CODEC_ID_WMAPRO) {
5116 param_write_string(pb, "FourCC", "WMAP");
5117 }
5118 param_write_hex(pb, "CodecPrivateData", track->par->extradata,
5119 track->par->extradata_size);
5120 param_write_int(pb, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags,
5121 track->par->codec_id));
5122 param_write_int(pb, "Channels", track->par->ch_layout.nb_channels);
5123 param_write_int(pb, "SamplingRate", track->par->sample_rate);
5124 param_write_int(pb, "BitsPerSample", 16);
5125 param_write_int(pb, "PacketSize", track->par->block_align ?
5126 track->par->block_align : 4);
5127 }
5128 avio_printf(pb, "</%s>\n", type);
5129 }
5130 avio_printf(pb, "</switch>\n");
5131 avio_printf(pb, "</body>\n");
5132 avio_printf(pb, "</smil>\n");
5133
5134 return update_size(pb, pos);
5135 }
5136
5137 static int mov_write_mfhd_tag(AVIOContext *pb, MOVMuxContext *mov)
5138 {
5139 avio_wb32(pb, 16);
5140 ffio_wfourcc(pb, "mfhd");
5141 avio_wb32(pb, 0);
5142 avio_wb32(pb, mov->fragments);
5143 return 0;
5144 }
5145
5146 static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry)
5147 {
5148 return entry->flags & MOV_SYNC_SAMPLE ? MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO :
5149 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC);
5150 }
5151
5152 static int mov_write_tfhd_tag(AVIOContext *pb, MOVMuxContext *mov,
5153 MOVTrack *track, int64_t moof_offset)
5154 {
5155 int64_t pos = avio_tell(pb);
5156 uint32_t flags = MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION |
5157 MOV_TFHD_BASE_DATA_OFFSET;
5158 if (!track->entry) {
5159 flags |= MOV_TFHD_DURATION_IS_EMPTY;
5160 } else {
5161 flags |= MOV_TFHD_DEFAULT_FLAGS;
5162 }
5163 if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET)
5164 flags &= ~MOV_TFHD_BASE_DATA_OFFSET;
5165 if (mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) {
5166 flags &= ~MOV_TFHD_BASE_DATA_OFFSET;
5167 flags |= MOV_TFHD_DEFAULT_BASE_IS_MOOF;
5168 }
5169 /* CMAF requires all values to be explicit in tfhd atoms */
5170 if (mov->flags & FF_MOV_FLAG_CMAF)
5171 flags |= MOV_TFHD_STSD_ID;
5172
5173 /* Don't set a default sample size, the silverlight player refuses
5174 * to play files with that set. Don't set a default sample duration,
5175 * WMP freaks out if it is set. Don't set a base data offset, PIFF
5176 * file format says it MUST NOT be set. */
5177 if (track->mode == MODE_ISM)
5178 flags &= ~(MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION |
5179 MOV_TFHD_BASE_DATA_OFFSET | MOV_TFHD_STSD_ID);
5180
5181 avio_wb32(pb, 0); /* size placeholder */
5182 ffio_wfourcc(pb, "tfhd");
5183 avio_w8(pb, 0); /* version */
5184 avio_wb24(pb, flags);
5185
5186 avio_wb32(pb, track->track_id); /* track-id */
5187 if (flags & MOV_TFHD_BASE_DATA_OFFSET)
5188 avio_wb64(pb, moof_offset);
5189 if (flags & MOV_TFHD_STSD_ID) {
5190 avio_wb32(pb, 1);
5191 }
5192 if (flags & MOV_TFHD_DEFAULT_DURATION) {
5193 track->default_duration = get_cluster_duration(track, 0);
5194 avio_wb32(pb, track->default_duration);
5195 }
5196 if (flags & MOV_TFHD_DEFAULT_SIZE) {
5197 track->default_size = track->entry ? track->cluster[0].size : 1;
5198 avio_wb32(pb, track->default_size);
5199 } else
5200 track->default_size = -1;
5201
5202 if (flags & MOV_TFHD_DEFAULT_FLAGS) {
5203 /* Set the default flags based on the second sample, if available.
5204 * If the first sample is different, that can be signaled via a separate field. */
5205 if (track->entry > 1)
5206 track->default_sample_flags = get_sample_flags(track, &track->cluster[1]);
5207 else
5208 track->default_sample_flags =
5209 track->par->codec_type == AVMEDIA_TYPE_VIDEO ?
5210 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC) :
5211 MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO;
5212 avio_wb32(pb, track->default_sample_flags);
5213 }
5214
5215 return update_size(pb, pos);
5216 }
5217
5218 static int mov_write_trun_tag(AVIOContext *pb, MOVMuxContext *mov,
5219 MOVTrack *track, int moof_size,
5220 int first, int end)
5221 {
5222 int64_t pos = avio_tell(pb);
5223 uint32_t flags = MOV_TRUN_DATA_OFFSET;
5224 int i;
5225
5226 for (i = first; i < end; i++) {
5227 if (get_cluster_duration(track, i) != track->default_duration)
5228 flags |= MOV_TRUN_SAMPLE_DURATION;
5229 if (track->cluster[i].size != track->default_size)
5230 flags |= MOV_TRUN_SAMPLE_SIZE;
5231 if (i > first && get_sample_flags(track, &track->cluster[i]) != track->default_sample_flags)
5232 flags |= MOV_TRUN_SAMPLE_FLAGS;
5233 }
5234 if (!(flags & MOV_TRUN_SAMPLE_FLAGS) && track->entry > 0 &&
5235 get_sample_flags(track, &track->cluster[0]) != track->default_sample_flags)
5236 flags |= MOV_TRUN_FIRST_SAMPLE_FLAGS;
5237 if (track->flags & MOV_TRACK_CTTS)
5238 flags |= MOV_TRUN_SAMPLE_CTS;
5239
5240 avio_wb32(pb, 0); /* size placeholder */
5241 ffio_wfourcc(pb, "trun");
5242 if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5243 avio_w8(pb, 1); /* version */
5244 else
5245 avio_w8(pb, 0); /* version */
5246 avio_wb24(pb, flags);
5247
5248 avio_wb32(pb, end - first); /* sample count */
5249 if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET &&
5250 !(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) &&
5251 !mov->first_trun)
5252 avio_wb32(pb, 0); /* Later tracks follow immediately after the previous one */
5253 else
5254 avio_wb32(pb, moof_size + 8 + track->data_offset +
5255 track->cluster[first].pos); /* data offset */
5256 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS)
5257 avio_wb32(pb, get_sample_flags(track, &track->cluster[first]));
5258
5259 for (i = first; i < end; i++) {
5260 if (flags & MOV_TRUN_SAMPLE_DURATION)
5261 avio_wb32(pb, get_cluster_duration(track, i));
5262 if (flags & MOV_TRUN_SAMPLE_SIZE)
5263 avio_wb32(pb, track->cluster[i].size);
5264 if (flags & MOV_TRUN_SAMPLE_FLAGS)
5265 avio_wb32(pb, get_sample_flags(track, &track->cluster[i]));
5266 if (flags & MOV_TRUN_SAMPLE_CTS)
5267 avio_wb32(pb, track->cluster[i].cts);
5268 }
5269
5270 mov->first_trun = 0;
5271 return update_size(pb, pos);
5272 }
5273
5274 static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track)
5275 {
5276 int64_t pos = avio_tell(pb);
5277 static const uint8_t uuid[] = {
5278 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
5279 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
5280 };
5281
5282 avio_wb32(pb, 0); /* size placeholder */
5283 ffio_wfourcc(pb, "uuid");
5284 avio_write(pb, uuid, AV_UUID_LEN);
5285 avio_w8(pb, 1);
5286 avio_wb24(pb, 0);
5287 avio_wb64(pb, track->cluster[0].dts + track->cluster[0].cts);
5288 avio_wb64(pb, track->end_pts -
5289 (track->cluster[0].dts + track->cluster[0].cts));
5290
5291 return update_size(pb, pos);
5292 }
5293
5294 static int mov_write_tfrf_tag(AVIOContext *pb, MOVMuxContext *mov,
5295 MOVTrack *track, int entry)
5296 {
5297 int n = track->nb_frag_info - 1 - entry, i;
5298 int size = 8 + 16 + 4 + 1 + 16*n;
5299 static const uint8_t uuid[] = {
5300 0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95,
5301 0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f
5302 };
5303
5304 if (entry < 0)
5305 return 0;
5306
5307 avio_seek(pb, track->frag_info[entry].tfrf_offset, SEEK_SET);
5308 avio_wb32(pb, size);
5309 ffio_wfourcc(pb, "uuid");
5310 avio_write(pb, uuid, AV_UUID_LEN);
5311 avio_w8(pb, 1);
5312 avio_wb24(pb, 0);
5313 avio_w8(pb, n);
5314 for (i = 0; i < n; i++) {
5315 int index = entry + 1 + i;
5316 avio_wb64(pb, track->frag_info[index].time);
5317 avio_wb64(pb, track->frag_info[index].duration);
5318 }
5319 if (n < mov->ism_lookahead) {
5320 int free_size = 16 * (mov->ism_lookahead - n);
5321 avio_wb32(pb, free_size);
5322 ffio_wfourcc(pb, "free");
5323 ffio_fill(pb, 0, free_size - 8);
5324 }
5325
5326 return 0;
5327 }
5328
5329 static int mov_write_tfrf_tags(AVIOContext *pb, MOVMuxContext *mov,
5330 MOVTrack *track)
5331 {
5332 int64_t pos = avio_tell(pb);
5333 int i;
5334 for (i = 0; i < mov->ism_lookahead; i++) {
5335 /* Update the tfrf tag for the last ism_lookahead fragments,
5336 * nb_frag_info - 1 is the next fragment to be written. */
5337 mov_write_tfrf_tag(pb, mov, track, track->nb_frag_info - 2 - i);
5338 }
5339 avio_seek(pb, pos, SEEK_SET);
5340 return 0;
5341 }
5342
5343 static int mov_add_tfra_entries(AVIOContext *pb, MOVMuxContext *mov, int tracks,
5344 int size)
5345 {
5346 int i;
5347 for (i = 0; i < mov->nb_streams; i++) {
5348 MOVTrack *track = &mov->tracks[i];
5349 MOVFragmentInfo *info;
5350 if ((tracks >= 0 && i != tracks) || !track->entry)
5351 continue;
5352 track->nb_frag_info++;
5353 if (track->nb_frag_info >= track->frag_info_capacity) {
5354 unsigned new_capacity = track->nb_frag_info + MOV_FRAG_INFO_ALLOC_INCREMENT;
5355 if (av_reallocp_array(&track->frag_info,
5356 new_capacity,
5357 sizeof(*track->frag_info)))
5358 return AVERROR(ENOMEM);
5359 track->frag_info_capacity = new_capacity;
5360 }
5361 info = &track->frag_info[track->nb_frag_info - 1];
5362 info->offset = avio_tell(pb);
5363 info->size = size;
5364 // Try to recreate the original pts for the first packet
5365 // from the fields we have stored
5366 info->time = track->cluster[0].dts + track->cluster[0].cts;
5367 info->duration = track->end_pts -
5368 (track->cluster[0].dts + track->cluster[0].cts);
5369 // If the pts is less than zero, we will have trimmed
5370 // away parts of the media track using an edit list,
5371 // and the corresponding start presentation time is zero.
5372 if (info->time < 0) {
5373 info->duration += info->time;
5374 info->time = 0;
5375 }
5376 info->tfrf_offset = 0;
5377 mov_write_tfrf_tags(pb, mov, track);
5378 }
5379 return 0;
5380 }
5381
5382 static void mov_prune_frag_info(MOVMuxContext *mov, int tracks, int max)
5383 {
5384 int i;
5385 for (i = 0; i < mov->nb_streams; i++) {
5386 MOVTrack *track = &mov->tracks[i];
5387 if ((tracks >= 0 && i != tracks) || !track->entry)
5388 continue;
5389 if (track->nb_frag_info > max) {
5390 memmove(track->frag_info, track->frag_info + (track->nb_frag_info - max), max * sizeof(*track->frag_info));
5391 track->nb_frag_info = max;
5392 }
5393 }
5394 }
5395
5396 static int mov_write_tfdt_tag(AVIOContext *pb, MOVTrack *track)
5397 {
5398 int64_t pos = avio_tell(pb);
5399
5400 avio_wb32(pb, 0); /* size */
5401 ffio_wfourcc(pb, "tfdt");
5402 avio_w8(pb, 1); /* version */
5403 avio_wb24(pb, 0);
5404 avio_wb64(pb, track->cluster[0].dts - track->start_dts);
5405 return update_size(pb, pos);
5406 }
5407
5408 static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov,
5409 MOVTrack *track, int64_t moof_offset,
5410 int moof_size)
5411 {
5412 int64_t pos = avio_tell(pb);
5413 int i, start = 0;
5414 avio_wb32(pb, 0); /* size placeholder */
5415 ffio_wfourcc(pb, "traf");
5416
5417 mov_write_tfhd_tag(pb, mov, track, moof_offset);
5418 if (mov->mode != MODE_ISM)
5419 mov_write_tfdt_tag(pb, track);
5420 for (i = 1; i < track->entry; i++) {
5421 if (track->cluster[i].pos != track->cluster[i - 1].pos + track->cluster[i - 1].size) {
5422 mov_write_trun_tag(pb, mov, track, moof_size, start, i);
5423 start = i;
5424 }
5425 }
5426 mov_write_trun_tag(pb, mov, track, moof_size, start, track->entry);
5427 if (mov->mode == MODE_ISM) {
5428 mov_write_tfxd_tag(pb, track);
5429
5430 if (mov->ism_lookahead) {
5431 int size = 16 + 4 + 1 + 16 * mov->ism_lookahead;
5432
5433 if (track->nb_frag_info > 0) {
5434 MOVFragmentInfo *info = &track->frag_info[track->nb_frag_info - 1];
5435 if (!info->tfrf_offset)
5436 info->tfrf_offset = avio_tell(pb);
5437 }
5438 avio_wb32(pb, 8 + size);
5439 ffio_wfourcc(pb, "free");
5440 ffio_fill(pb, 0, size);
5441 }
5442 }
5443
5444 return update_size(pb, pos);
5445 }
5446
5447 static int mov_write_moof_tag_internal(AVIOContext *pb, MOVMuxContext *mov,
5448 int tracks, int moof_size)
5449 {
5450 int64_t pos = avio_tell(pb);
5451 int i;
5452
5453 avio_wb32(pb, 0); /* size placeholder */
5454 ffio_wfourcc(pb, "moof");
5455 mov->first_trun = 1;
5456
5457 mov_write_mfhd_tag(pb, mov);
5458 for (i = 0; i < mov->nb_streams; i++) {
5459 MOVTrack *track = &mov->tracks[i];
5460 if (tracks >= 0 && i != tracks)
5461 continue;
5462 if (!track->entry)
5463 continue;
5464 mov_write_traf_tag(pb, mov, track, pos, moof_size);
5465 }
5466
5467 return update_size(pb, pos);
5468 }
5469
5470 static int mov_write_sidx_tag(AVIOContext *pb,
5471 MOVTrack *track, int ref_size, int total_sidx_size)
5472 {
5473 int64_t pos = avio_tell(pb), offset_pos, end_pos;
5474 int64_t presentation_time, duration, offset;
5475 unsigned starts_with_SAP;
5476 int i, entries;
5477
5478 if (track->entry) {
5479 entries = 1;
5480 presentation_time = track->cluster[0].dts + track->cluster[0].cts -
5481 track->start_dts - track->start_cts;
5482 duration = track->end_pts -
5483 (track->cluster[0].dts + track->cluster[0].cts);
5484 starts_with_SAP = track->cluster[0].flags & MOV_SYNC_SAMPLE;
5485
5486 // pts<0 should be cut away using edts
5487 if (presentation_time < 0) {
5488 duration += presentation_time;
5489 presentation_time = 0;
5490 }
5491 } else {
5492 entries = track->nb_frag_info;
5493 if (entries <= 0)
5494 return 0;
5495 presentation_time = track->frag_info[0].time;
5496 /* presentation_time <= 0 is handled by mov_add_tfra_entries() */
5497 if (presentation_time > 0)
5498 presentation_time -= track->start_dts + track->start_cts;
5499 }
5500
5501 avio_wb32(pb, 0); /* size */
5502 ffio_wfourcc(pb, "sidx");
5503 avio_w8(pb, 1); /* version */
5504 avio_wb24(pb, 0);
5505 avio_wb32(pb, track->track_id); /* reference_ID */
5506 avio_wb32(pb, track->timescale); /* timescale */
5507 avio_wb64(pb, presentation_time); /* earliest_presentation_time */
5508 offset_pos = avio_tell(pb);
5509 avio_wb64(pb, 0); /* first_offset (offset to referenced moof) */
5510 avio_wb16(pb, 0); /* reserved */
5511
5512 avio_wb16(pb, entries); /* reference_count */
5513 for (i = 0; i < entries; i++) {
5514 if (!track->entry) {
5515 if (i > 1 && track->frag_info[i].offset != track->frag_info[i - 1].offset + track->frag_info[i - 1].size) {
5516 av_log(NULL, AV_LOG_ERROR, "Non-consecutive fragments, writing incorrect sidx\n");
5517 }
5518 duration = track->frag_info[i].duration;
5519 ref_size = track->frag_info[i].size;
5520 starts_with_SAP = 1;
5521 }
5522 avio_wb32(pb, (0 << 31) | (ref_size & 0x7fffffff)); /* reference_type (0 = media) | referenced_size */
5523 avio_wb32(pb, duration); /* subsegment_duration */
5524 avio_wb32(pb, (starts_with_SAP << 31) | (0 << 28) | 0); /* starts_with_SAP | SAP_type | SAP_delta_time */
5525 }
5526
5527 end_pos = avio_tell(pb);
5528 offset = pos + total_sidx_size - end_pos;
5529 avio_seek(pb, offset_pos, SEEK_SET);
5530 avio_wb64(pb, offset);
5531 avio_seek(pb, end_pos, SEEK_SET);
5532 return update_size(pb, pos);
5533 }
5534
5535 static int mov_write_sidx_tags(AVIOContext *pb, MOVMuxContext *mov,
5536 int tracks, int ref_size)
5537 {
5538 int i, round, ret;
5539 AVIOContext *avio_buf;
5540 int total_size = 0;
5541 for (round = 0; round < 2; round++) {
5542 // First run one round to calculate the total size of all
5543 // sidx atoms.
5544 // This would be much simpler if we'd only write one sidx
5545 // atom, for the first track in the moof.
5546 if (round == 0) {
5547 if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
5548 return ret;
5549 } else {
5550 avio_buf = pb;
5551 }
5552 for (i = 0; i < mov->nb_streams; i++) {
5553 MOVTrack *track = &mov->tracks[i];
5554 if (tracks >= 0 && i != tracks)
5555 continue;
5556 // When writing a sidx for the full file, entry is 0, but
5557 // we want to include all tracks. ref_size is 0 in this case,
5558 // since we read it from frag_info instead.
5559 if (!track->entry && ref_size > 0)
5560 continue;
5561 total_size -= mov_write_sidx_tag(avio_buf, track, ref_size,
5562 total_size);
5563 }
5564 if (round == 0)
5565 total_size = ffio_close_null_buf(avio_buf);
5566 }
5567 return 0;
5568 }
5569
5570 static int mov_write_prft_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks)
5571 {
5572 int64_t pos = avio_tell(pb), pts_us, ntp_ts;
5573 MOVTrack *first_track;
5574 int flags = 24;
5575
5576 /* PRFT should be associated with at most one track. So, choosing only the
5577 * first track. */
5578 if (tracks > 0)
5579 return 0;
5580 first_track = &(mov->tracks[0]);
5581
5582 if (!first_track->entry) {
5583 av_log(mov->fc, AV_LOG_WARNING, "Unable to write PRFT, no entries in the track\n");
5584 return 0;
5585 }
5586
5587 if (first_track->cluster[0].pts == AV_NOPTS_VALUE) {
5588 av_log(mov->fc, AV_LOG_WARNING, "Unable to write PRFT, first PTS is invalid\n");
5589 return 0;
5590 }
5591
5592 if (mov->write_prft == MOV_PRFT_SRC_WALLCLOCK) {
5593 if (first_track->cluster[0].prft.wallclock) {
5594 /* Round the NTP time to whole milliseconds. */
5595 ntp_ts = ff_get_formatted_ntp_time((first_track->cluster[0].prft.wallclock / 1000) * 1000 +
5596 NTP_OFFSET_US);
5597 flags = first_track->cluster[0].prft.flags;
5598 } else
5599 ntp_ts = ff_get_formatted_ntp_time(ff_ntp_time());
5600 } else if (mov->write_prft == MOV_PRFT_SRC_PTS) {
5601 pts_us = av_rescale_q(first_track->cluster[0].pts,
5602 first_track->st->time_base, AV_TIME_BASE_Q);
5603 ntp_ts = ff_get_formatted_ntp_time(pts_us + NTP_OFFSET_US);
5604 } else {
5605 av_log(mov->fc, AV_LOG_WARNING, "Unsupported PRFT box configuration: %d\n",
5606 mov->write_prft);
5607 return 0;
5608 }
5609
5610 avio_wb32(pb, 0); // Size place holder
5611 ffio_wfourcc(pb, "prft"); // Type
5612 avio_w8(pb, 1); // Version
5613 avio_wb24(pb, flags); // Flags
5614 avio_wb32(pb, first_track->track_id); // reference track ID
5615 avio_wb64(pb, ntp_ts); // NTP time stamp
5616 avio_wb64(pb, first_track->cluster[0].pts); //media time
5617 return update_size(pb, pos);
5618 }
5619
5620 static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks,
5621 int64_t mdat_size)
5622 {
5623 AVIOContext *avio_buf;
5624 int ret, moof_size;
5625
5626 if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
5627 return ret;
5628 mov_write_moof_tag_internal(avio_buf, mov, tracks, 0);
5629 moof_size = ffio_close_null_buf(avio_buf);
5630
5631 if (mov->flags & FF_MOV_FLAG_DASH &&
5632 !(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | FF_MOV_FLAG_SKIP_SIDX)))
5633 mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size);
5634
5635 if (mov->write_prft > MOV_PRFT_NONE && mov->write_prft < MOV_PRFT_NB)
5636 mov_write_prft_tag(pb, mov, tracks);
5637
5638 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX ||
5639 !(mov->flags & FF_MOV_FLAG_SKIP_TRAILER) ||
5640 mov->ism_lookahead) {
5641 if ((ret = mov_add_tfra_entries(pb, mov, tracks, moof_size + 8 + mdat_size)) < 0)
5642 return ret;
5643 if (!(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) &&
5644 mov->flags & FF_MOV_FLAG_SKIP_TRAILER) {
5645 mov_prune_frag_info(mov, tracks, mov->ism_lookahead + 1);
5646 }
5647 }
5648
5649 return mov_write_moof_tag_internal(pb, mov, tracks, moof_size);
5650 }
5651
5652 static int mov_write_tfra_tag(AVIOContext *pb, MOVTrack *track)
5653 {
5654 int64_t pos = avio_tell(pb);
5655 int i;
5656
5657 avio_wb32(pb, 0); /* size placeholder */
5658 ffio_wfourcc(pb, "tfra");
5659 avio_w8(pb, 1); /* version */
5660 avio_wb24(pb, 0);
5661
5662 avio_wb32(pb, track->track_id);
5663 avio_wb32(pb, 0); /* length of traf/trun/sample num */
5664 avio_wb32(pb, track->nb_frag_info);
5665 for (i = 0; i < track->nb_frag_info; i++) {
5666 avio_wb64(pb, track->frag_info[i].time);
5667 avio_wb64(pb, track->frag_info[i].offset + track->data_offset);
5668 avio_w8(pb, 1); /* traf number */
5669 avio_w8(pb, 1); /* trun number */
5670 avio_w8(pb, 1); /* sample number */
5671 }
5672
5673 return update_size(pb, pos);
5674 }
5675
5676 static int mov_write_mfra_tag(AVIOContext *pb, MOVMuxContext *mov)
5677 {
5678 AVIOContext *mfra_pb;
5679 int i, ret, sz;
5680 uint8_t *buf;
5681
5682 ret = avio_open_dyn_buf(&mfra_pb);
5683 if (ret < 0)
5684 return ret;
5685
5686 avio_wb32(mfra_pb, 0); /* size placeholder */
5687 ffio_wfourcc(mfra_pb, "mfra");
5688 /* An empty mfra atom is enough to indicate to the publishing point that
5689 * the stream has ended. */
5690 if (mov->flags & FF_MOV_FLAG_ISML)
5691 goto done_mfra;
5692
5693 for (i = 0; i < mov->nb_streams; i++) {
5694 MOVTrack *track = &mov->tracks[i];
5695 if (track->nb_frag_info)
5696 mov_write_tfra_tag(mfra_pb, track);
5697 }
5698
5699 avio_wb32(mfra_pb, 16);
5700 ffio_wfourcc(mfra_pb, "mfro");
5701 avio_wb32(mfra_pb, 0); /* version + flags */
5702 avio_wb32(mfra_pb, avio_tell(mfra_pb) + 4);
5703
5704 done_mfra:
5705
5706 sz = update_size(mfra_pb, 0);
5707 ret = avio_get_dyn_buf(mfra_pb, &buf);
5708 avio_write(pb, buf, ret);
5709 ffio_free_dyn_buf(&mfra_pb);
5710
5711 return sz;
5712 }
5713
5714 static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov)
5715 {
5716 avio_wb32(pb, 8); // placeholder for extended size field (64 bit)
5717 ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
5718
5719 mov->mdat_pos = avio_tell(pb);
5720 avio_wb32(pb, 0); /* size placeholder*/
5721 ffio_wfourcc(pb, "mdat");
5722 return 0;
5723 }
5724
5725 static void mov_write_ftyp_tag_internal(AVIOContext *pb, AVFormatContext *s,
5726 int has_h264, int has_video, int write_minor)
5727 {
5728 MOVMuxContext *mov = s->priv_data;
5729 int minor = 0x200;
5730
5731 if (mov->major_brand && strlen(mov->major_brand) >= 4)
5732 ffio_wfourcc(pb, mov->major_brand);
5733 else if (mov->mode == MODE_3GP) {
5734 ffio_wfourcc(pb, has_h264 ? "3gp6" : "3gp4");
5735 minor = has_h264 ? 0x100 : 0x200;
5736 } else if (mov->mode == MODE_AVIF) {
5737 ffio_wfourcc(pb, mov->is_animated_avif ? "avis" : "avif");
5738 minor = 0;
5739 } else if (mov->mode & MODE_3G2) {
5740 ffio_wfourcc(pb, has_h264 ? "3g2b" : "3g2a");
5741 minor = has_h264 ? 0x20000 : 0x10000;
5742 } else if (mov->mode == MODE_PSP)
5743 ffio_wfourcc(pb, "MSNV");
5744 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_FRAGMENT &&
5745 mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5746 ffio_wfourcc(pb, "iso6"); // Required when using signed CTS offsets in trun boxes
5747 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
5748 ffio_wfourcc(pb, "iso5"); // Required when using default-base-is-moof
5749 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5750 ffio_wfourcc(pb, "iso4");
5751 else if (mov->mode == MODE_MP4)
5752 ffio_wfourcc(pb, "isom");
5753 else if (mov->mode == MODE_IPOD)
5754 ffio_wfourcc(pb, has_video ? "M4V ":"M4A ");
5755 else if (mov->mode == MODE_ISM)
5756 ffio_wfourcc(pb, "isml");
5757 else if (mov->mode == MODE_F4V)
5758 ffio_wfourcc(pb, "f4v ");
5759 else
5760 ffio_wfourcc(pb, "qt ");
5761
5762 if (write_minor)
5763 avio_wb32(pb, minor);
5764 }
5765
5766 static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s)
5767 {
5768 MOVMuxContext *mov = s->priv_data;
5769 int64_t pos = avio_tell(pb);
5770 int has_h264 = 0, has_av1 = 0, has_video = 0, has_dolby = 0;
5771 int i;
5772
5773 for (i = 0; i < s->nb_streams; i++) {
5774 AVStream *st = s->streams[i];
5775 if (is_cover_image(st))
5776 continue;
5777 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
5778 has_video = 1;
5779 if (st->codecpar->codec_id == AV_CODEC_ID_H264)
5780 has_h264 = 1;
5781 if (st->codecpar->codec_id == AV_CODEC_ID_AV1)
5782 has_av1 = 1;
5783 if (st->codecpar->codec_id == AV_CODEC_ID_AC3 ||
5784 st->codecpar->codec_id == AV_CODEC_ID_EAC3 ||
5785 st->codecpar->codec_id == AV_CODEC_ID_TRUEHD ||
5786 av_stream_get_side_data(st, AV_PKT_DATA_DOVI_CONF, NULL))
5787 has_dolby = 1;
5788 }
5789
5790 avio_wb32(pb, 0); /* size */
5791 ffio_wfourcc(pb, "ftyp");
5792
5793 // Write major brand
5794 mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 1);
5795 // Write the major brand as the first compatible brand as well
5796 mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 0);
5797
5798 // Write compatible brands, ensuring that we don't write the major brand as a
5799 // compatible brand a second time.
5800 if (mov->mode == MODE_ISM) {
5801 ffio_wfourcc(pb, "piff");
5802 } else if (mov->mode == MODE_AVIF) {
5803 const AVPixFmtDescriptor *pix_fmt_desc =
5804 av_pix_fmt_desc_get(s->streams[0]->codecpar->format);
5805 const int depth = pix_fmt_desc->comp[0].depth;
5806 if (mov->is_animated_avif) {
5807 // For animated AVIF, major brand is "avis". Add "avif" as a
5808 // compatible brand.
5809 ffio_wfourcc(pb, "avif");
5810 ffio_wfourcc(pb, "msf1");
5811 ffio_wfourcc(pb, "iso8");
5812 }
5813 ffio_wfourcc(pb, "mif1");
5814 ffio_wfourcc(pb, "miaf");
5815 if (depth == 8 || depth == 10) {
5816 // MA1B and MA1A brands are based on AV1 profile. Short hand for
5817 // computing that is based on chroma subsampling type. 420 chroma
5818 // subsampling is MA1B. 444 chroma subsampling is MA1A.
5819 if (!pix_fmt_desc->log2_chroma_w && !pix_fmt_desc->log2_chroma_h) {
5820 // 444 chroma subsampling.
5821 ffio_wfourcc(pb, "MA1A");
5822 } else {
5823 // 420 chroma subsampling.
5824 ffio_wfourcc(pb, "MA1B");
5825 }
5826 }
5827 } else if (mov->mode != MODE_MOV) {
5828 // We add tfdt atoms when fragmenting, signal this with the iso6 compatible
5829 // brand, if not already the major brand. This is compatible with users that
5830 // don't understand tfdt.
5831 if (mov->mode == MODE_MP4) {
5832 if (mov->flags & FF_MOV_FLAG_CMAF)
5833 ffio_wfourcc(pb, "cmfc");
5834 if (mov->flags & FF_MOV_FLAG_FRAGMENT && !(mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS))
5835 ffio_wfourcc(pb, "iso6");
5836 if (has_av1)
5837 ffio_wfourcc(pb, "av01");
5838 if (has_dolby)
5839 ffio_wfourcc(pb, "dby1");
5840 } else {
5841 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
5842 ffio_wfourcc(pb, "iso6");
5843 if (mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
5844 ffio_wfourcc(pb, "iso5");
5845 else if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5846 ffio_wfourcc(pb, "iso4");
5847 }
5848 // Brands prior to iso5 can't be signaled when using default-base-is-moof
5849 if (!(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)) {
5850 // write isom for mp4 only if it it's not the major brand already.
5851 if (mov->mode != MODE_MP4 || mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5852 ffio_wfourcc(pb, "isom");
5853 ffio_wfourcc(pb, "iso2");
5854 if (has_h264)
5855 ffio_wfourcc(pb, "avc1");
5856 }
5857 }
5858
5859 if (mov->mode == MODE_MP4)
5860 ffio_wfourcc(pb, "mp41");
5861
5862 if (mov->flags & FF_MOV_FLAG_DASH && mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
5863 ffio_wfourcc(pb, "dash");
5864
5865 return update_size(pb, pos);
5866 }
5867
5868 static int mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s)
5869 {
5870 AVStream *video_st = s->streams[0];
5871 AVCodecParameters *video_par = s->streams[0]->codecpar;
5872 AVCodecParameters *audio_par = s->streams[1]->codecpar;
5873 int audio_rate = audio_par->sample_rate;
5874 int64_t frame_rate = video_st->avg_frame_rate.den ?
5875 (video_st->avg_frame_rate.num * 0x10000LL) / video_st->avg_frame_rate.den :
5876 0;
5877 int audio_kbitrate = audio_par->bit_rate / 1000;
5878 int video_kbitrate = FFMIN(video_par->bit_rate / 1000, 800 - audio_kbitrate);
5879
5880 if (frame_rate < 0 || frame_rate > INT32_MAX) {
5881 av_log(s, AV_LOG_ERROR, "Frame rate %f outside supported range\n", frame_rate / (double)0x10000);
5882 return AVERROR(EINVAL);
5883 }
5884
5885 avio_wb32(pb, 0x94); /* size */
5886 ffio_wfourcc(pb, "uuid");
5887 ffio_wfourcc(pb, "PROF");
5888
5889 avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
5890 avio_wb32(pb, 0xbb88695c);
5891 avio_wb32(pb, 0xfac9c740);
5892
5893 avio_wb32(pb, 0x0); /* ? */
5894 avio_wb32(pb, 0x3); /* 3 sections ? */
5895
5896 avio_wb32(pb, 0x14); /* size */
5897 ffio_wfourcc(pb, "FPRF");
5898 avio_wb32(pb, 0x0); /* ? */
5899 avio_wb32(pb, 0x0); /* ? */
5900 avio_wb32(pb, 0x0); /* ? */
5901
5902 avio_wb32(pb, 0x2c); /* size */
5903 ffio_wfourcc(pb, "APRF"); /* audio */
5904 avio_wb32(pb, 0x0);
5905 avio_wb32(pb, 0x2); /* TrackID */
5906 ffio_wfourcc(pb, "mp4a");
5907 avio_wb32(pb, 0x20f);
5908 avio_wb32(pb, 0x0);
5909 avio_wb32(pb, audio_kbitrate);
5910 avio_wb32(pb, audio_kbitrate);
5911 avio_wb32(pb, audio_rate);
5912 avio_wb32(pb, audio_par->ch_layout.nb_channels);
5913
5914 avio_wb32(pb, 0x34); /* size */
5915 ffio_wfourcc(pb, "VPRF"); /* video */
5916 avio_wb32(pb, 0x0);
5917 avio_wb32(pb, 0x1); /* TrackID */
5918 if (video_par->codec_id == AV_CODEC_ID_H264) {
5919 ffio_wfourcc(pb, "avc1");
5920 avio_wb16(pb, 0x014D);
5921 avio_wb16(pb, 0x0015);
5922 } else {
5923 ffio_wfourcc(pb, "mp4v");
5924 avio_wb16(pb, 0x0000);
5925 avio_wb16(pb, 0x0103);
5926 }
5927 avio_wb32(pb, 0x0);
5928 avio_wb32(pb, video_kbitrate);
5929 avio_wb32(pb, video_kbitrate);
5930 avio_wb32(pb, frame_rate);
5931 avio_wb32(pb, frame_rate);
5932 avio_wb16(pb, video_par->width);
5933 avio_wb16(pb, video_par->height);
5934 avio_wb32(pb, 0x010001); /* ? */
5935
5936 return 0;
5937 }
5938
5939 static int mov_write_identification(AVIOContext *pb, AVFormatContext *s)
5940 {
5941 MOVMuxContext *mov = s->priv_data;
5942 int i;
5943
5944 mov_write_ftyp_tag(pb,s);
5945 if (mov->mode == MODE_PSP) {
5946 int video_streams_nb = 0, audio_streams_nb = 0, other_streams_nb = 0;
5947 for (i = 0; i < s->nb_streams; i++) {
5948 AVStream *st = s->streams[i];
5949 if (is_cover_image(st))
5950 continue;
5951 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
5952 video_streams_nb++;
5953 else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
5954 audio_streams_nb++;
5955 else
5956 other_streams_nb++;
5957 }
5958
5959 if (video_streams_nb != 1 || audio_streams_nb != 1 || other_streams_nb) {
5960 av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
5961 return AVERROR(EINVAL);
5962 }
5963 return mov_write_uuidprof_tag(pb, s);
5964 }
5965 return 0;
5966 }
5967
5968 static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags)
5969 {
5970 uint32_t c = -1;
5971 int i, closed_gop = 0;
5972
5973 for (i = 0; i < pkt->size - 4; i++) {
5974 c = (c << 8) + pkt->data[i];
5975 if (c == 0x1b8) { // gop
5976 closed_gop = pkt->data[i + 4] >> 6 & 0x01;
5977 } else if (c == 0x100) { // pic
5978 int temp_ref = (pkt->data[i + 1] << 2) | (pkt->data[i + 2] >> 6);
5979 if (!temp_ref || closed_gop) // I picture is not reordered
5980 *flags = MOV_SYNC_SAMPLE;
5981 else
5982 *flags = MOV_PARTIAL_SYNC_SAMPLE;
5983 break;
5984 }
5985 }
5986 return 0;
5987 }
5988
5989 static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk)
5990 {
5991 const uint8_t *start, *next, *end = pkt->data + pkt->size;
5992 int seq = 0, entry = 0;
5993 int key = pkt->flags & AV_PKT_FLAG_KEY;
5994 start = find_next_marker(pkt->data, end);
5995 for (next = start; next < end; start = next) {
5996 next = find_next_marker(start + 4, end);
5997 switch (AV_RB32(start)) {
5998 case VC1_CODE_SEQHDR:
5999 seq = 1;
6000 break;
6001 case VC1_CODE_ENTRYPOINT:
6002 entry = 1;
6003 break;
6004 case VC1_CODE_SLICE:
6005 trk->vc1_info.slices = 1;
6006 break;
6007 }
6008 }
6009 if (!trk->entry && trk->vc1_info.first_packet_seen)
6010 trk->vc1_info.first_frag_written = 1;
6011 if (!trk->entry && !trk->vc1_info.first_frag_written) {
6012 /* First packet in first fragment */
6013 trk->vc1_info.first_packet_seq = seq;
6014 trk->vc1_info.first_packet_entry = entry;
6015 trk->vc1_info.first_packet_seen = 1;
6016 } else if ((seq && !trk->vc1_info.packet_seq) ||
6017 (entry && !trk->vc1_info.packet_entry)) {
6018 int i;
6019 for (i = 0; i < trk->entry; i++)
6020 trk->cluster[i].flags &= ~MOV_SYNC_SAMPLE;
6021 trk->has_keyframes = 0;
6022 if (seq)
6023 trk->vc1_info.packet_seq = 1;
6024 if (entry)
6025 trk->vc1_info.packet_entry = 1;
6026 if (!trk->vc1_info.first_frag_written) {
6027 /* First fragment */
6028 if ((!seq || trk->vc1_info.first_packet_seq) &&
6029 (!entry || trk->vc1_info.first_packet_entry)) {
6030 /* First packet had the same headers as this one, readd the
6031 * sync sample flag. */
6032 trk->cluster[0].flags |= MOV_SYNC_SAMPLE;
6033 trk->has_keyframes = 1;
6034 }
6035 }
6036 }
6037 if (trk->vc1_info.packet_seq && trk->vc1_info.packet_entry)
6038 key = seq && entry;
6039 else if (trk->vc1_info.packet_seq)
6040 key = seq;
6041 else if (trk->vc1_info.packet_entry)
6042 key = entry;
6043 if (key) {
6044 trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
6045 trk->has_keyframes++;
6046 }
6047 }
6048
6049 static void mov_parse_truehd_frame(AVPacket *pkt, MOVTrack *trk)
6050 {
6051 int length;
6052
6053 if (pkt->size < 8)
6054 return;
6055
6056 length = (AV_RB16(pkt->data) & 0xFFF) * 2;
6057 if (length < 8 || length > pkt->size)
6058 return;
6059
6060 if (AV_RB32(pkt->data + 4) == 0xF8726FBA) {
6061 trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
6062 trk->has_keyframes++;
6063 }
6064
6065 return;
6066 }
6067
6068 static int mov_flush_fragment_interleaving(AVFormatContext *s, MOVTrack *track)
6069 {
6070 MOVMuxContext *mov = s->priv_data;
6071 int ret, buf_size;
6072 uint8_t *buf;
6073 int i, offset;
6074
6075 if (!track->mdat_buf)
6076 return 0;
6077 if (!mov->mdat_buf) {
6078 if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
6079 return ret;
6080 }
6081 buf_size = avio_get_dyn_buf(track->mdat_buf, &buf);
6082
6083 offset = avio_tell(mov->mdat_buf);
6084 avio_write(mov->mdat_buf, buf, buf_size);
6085 ffio_free_dyn_buf(&track->mdat_buf);
6086
6087 for (i = track->entries_flushed; i < track->entry; i++)
6088 track->cluster[i].pos += offset;
6089 track->entries_flushed = track->entry;
6090 return 0;
6091 }
6092
6093 static int mov_write_squashed_packet(AVFormatContext *s, MOVTrack *track)
6094 {
6095 MOVMuxContext *mov = s->priv_data;
6096 AVPacket *squashed_packet = mov->pkt;
6097 int ret = AVERROR_BUG;
6098
6099 switch (track->st->codecpar->codec_id) {
6100 case AV_CODEC_ID_TTML: {
6101 int had_packets = !!track->squashed_packet_queue.head;
6102
6103 if ((ret = ff_mov_generate_squashed_ttml_packet(s, track, squashed_packet)) < 0) {
6104 goto finish_squash;
6105 }
6106
6107 // We have generated a padding packet (no actual input packets in
6108 // queue) and its duration is zero. Skipping writing it.
6109 if (!had_packets && squashed_packet->duration == 0) {
6110 goto finish_squash;
6111 }
6112
6113 track->end_reliable = 1;
6114 break;
6115 }
6116 default:
6117 ret = AVERROR(EINVAL);
6118 goto finish_squash;
6119 }
6120
6121 squashed_packet->stream_index = track->st->index;
6122
6123 ret = mov_write_single_packet(s, squashed_packet);
6124
6125 finish_squash:
6126 av_packet_unref(squashed_packet);
6127
6128 return ret;
6129 }
6130
6131 static int mov_write_squashed_packets(AVFormatContext *s)
6132 {
6133 MOVMuxContext *mov = s->priv_data;
6134
6135 for (int i = 0; i < s->nb_streams; i++) {
6136 MOVTrack *track = &mov->tracks[i];
6137 int ret = AVERROR_BUG;
6138
6139 if (track->squash_fragment_samples_to_one && !track->entry) {
6140 if ((ret = mov_write_squashed_packet(s, track)) < 0) {
6141 av_log(s, AV_LOG_ERROR,
6142 "Failed to write squashed packet for %s stream with "
6143 "index %d and track id %d. Error: %s\n",
6144 avcodec_get_name(track->st->codecpar->codec_id),
6145 track->st->index, track->track_id,
6146 av_err2str(ret));
6147 return ret;
6148 }
6149 }
6150 }
6151
6152 return 0;
6153 }
6154
6155 static int mov_flush_fragment(AVFormatContext *s, int force)
6156 {
6157 MOVMuxContext *mov = s->priv_data;
6158 int i, first_track = -1;
6159 int64_t mdat_size = 0;
6160 int ret;
6161 int has_video = 0, starts_with_key = 0, first_video_track = 1;
6162
6163 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
6164 return 0;
6165
6166 // Check if we have any tracks that require squashing.
6167 // In that case, we'll have to write the packet here.
6168 if ((ret = mov_write_squashed_packets(s)) < 0)
6169 return ret;
6170
6171 // Try to fill in the duration of the last packet in each stream
6172 // from queued packets in the interleave queues. If the flushing
6173 // of fragments was triggered automatically by an AVPacket, we
6174 // already have reliable info for the end of that track, but other
6175 // tracks may need to be filled in.
6176 for (i = 0; i < s->nb_streams; i++) {
6177 MOVTrack *track = &mov->tracks[i];
6178 if (!track->end_reliable) {
6179 const AVPacket *pkt = ff_interleaved_peek(s, i);
6180 if (pkt) {
6181 int64_t offset, dts, pts;
6182 ff_get_muxer_ts_offset(s, i, &offset);
6183 pts = pkt->pts + offset;
6184 dts = pkt->dts + offset;
6185 if (track->dts_shift != AV_NOPTS_VALUE)
6186 dts += track->dts_shift;
6187 track->track_duration = dts - track->start_dts;
6188 if (pts != AV_NOPTS_VALUE)
6189 track->end_pts = pts;
6190 else
6191 track->end_pts = dts;
6192 }
6193 }
6194 }
6195
6196 for (i = 0; i < mov->nb_streams; i++) {
6197 MOVTrack *track = &mov->tracks[i];
6198 if (track->entry <= 1)
6199 continue;
6200 // Sample durations are calculated as the diff of dts values,
6201 // but for the last sample in a fragment, we don't know the dts
6202 // of the first sample in the next fragment, so we have to rely
6203 // on what was set as duration in the AVPacket. Not all callers
6204 // set this though, so we might want to replace it with an
6205 // estimate if it currently is zero.
6206 if (get_cluster_duration(track, track->entry - 1) != 0)
6207 continue;
6208 // Use the duration (i.e. dts diff) of the second last sample for
6209 // the last one. This is a wild guess (and fatal if it turns out
6210 // to be too long), but probably the best we can do - having a zero
6211 // duration is bad as well.
6212 track->track_duration += get_cluster_duration(track, track->entry - 2);
6213 track->end_pts += get_cluster_duration(track, track->entry - 2);
6214 if (!mov->missing_duration_warned) {
6215 av_log(s, AV_LOG_WARNING,
6216 "Estimating the duration of the last packet in a "
6217 "fragment, consider setting the duration field in "
6218 "AVPacket instead.\n");
6219 mov->missing_duration_warned = 1;
6220 }
6221 }
6222
6223 if (!mov->moov_written) {
6224 int64_t pos = avio_tell(s->pb);
6225 uint8_t *buf;
6226 int buf_size, moov_size;
6227
6228 for (i = 0; i < mov->nb_streams; i++)
6229 if (!mov->tracks[i].entry && !is_cover_image(mov->tracks[i].st))
6230 break;
6231 /* Don't write the initial moov unless all tracks have data */
6232 if (i < mov->nb_streams && !force)
6233 return 0;
6234
6235 moov_size = get_moov_size(s);
6236 for (i = 0; i < mov->nb_streams; i++)
6237 mov->tracks[i].data_offset = pos + moov_size + 8;
6238
6239 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER);
6240 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV)
6241 mov_write_identification(s->pb, s);
6242 if ((ret = mov_write_moov_tag(s->pb, mov, s)) < 0)
6243 return ret;
6244
6245 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) {
6246 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
6247 mov->reserved_header_pos = avio_tell(s->pb);
6248 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6249 mov->moov_written = 1;
6250 return 0;
6251 }
6252
6253 buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
6254 avio_wb32(s->pb, buf_size + 8);
6255 ffio_wfourcc(s->pb, "mdat");
6256 avio_write(s->pb, buf, buf_size);
6257 ffio_free_dyn_buf(&mov->mdat_buf);
6258
6259 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
6260 mov->reserved_header_pos = avio_tell(s->pb);
6261
6262 mov->moov_written = 1;
6263 mov->mdat_size = 0;
6264 for (i = 0; i < mov->nb_streams; i++) {
6265 mov->tracks[i].entry = 0;
6266 mov->tracks[i].end_reliable = 0;
6267 }
6268 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6269 return 0;
6270 }
6271
6272 if (mov->frag_interleave) {
6273 for (i = 0; i < mov->nb_streams; i++) {
6274 MOVTrack *track = &mov->tracks[i];
6275 int ret;
6276 if ((ret = mov_flush_fragment_interleaving(s, track)) < 0)
6277 return ret;
6278 }
6279
6280 if (!mov->mdat_buf)
6281 return 0;
6282 mdat_size = avio_tell(mov->mdat_buf);
6283 }
6284
6285 for (i = 0; i < mov->nb_streams; i++) {
6286 MOVTrack *track = &mov->tracks[i];
6287 if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF || mov->frag_interleave)
6288 track->data_offset = 0;
6289 else
6290 track->data_offset = mdat_size;
6291 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
6292 has_video = 1;
6293 if (first_video_track) {
6294 if (track->entry)
6295 starts_with_key = track->cluster[0].flags & MOV_SYNC_SAMPLE;
6296 first_video_track = 0;
6297 }
6298 }
6299 if (!track->entry)
6300 continue;
6301 if (track->mdat_buf)
6302 mdat_size += avio_tell(track->mdat_buf);
6303 if (first_track < 0)
6304 first_track = i;
6305 }
6306
6307 if (!mdat_size)
6308 return 0;
6309
6310 avio_write_marker(s->pb,
6311 av_rescale(mov->tracks[first_track].cluster[0].dts, AV_TIME_BASE, mov->tracks[first_track].timescale),
6312 (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);
6313
6314 for (i = 0; i < mov->nb_streams; i++) {
6315 MOVTrack *track = &mov->tracks[i];
6316 int buf_size, write_moof = 1, moof_tracks = -1;
6317 uint8_t *buf;
6318
6319 if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) {
6320 if (!track->entry)
6321 continue;
6322 mdat_size = avio_tell(track->mdat_buf);
6323 moof_tracks = i;
6324 } else {
6325 write_moof = i == first_track;
6326 }
6327
6328 if (write_moof) {
6329 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6330
6331 mov_write_moof_tag(s->pb, mov, moof_tracks, mdat_size);
6332 mov->fragments++;
6333
6334 avio_wb32(s->pb, mdat_size + 8);
6335 ffio_wfourcc(s->pb, "mdat");
6336 }
6337
6338 track->entry = 0;
6339 track->entries_flushed = 0;
6340 track->end_reliable = 0;
6341 if (!mov->frag_interleave) {
6342 if (!track->mdat_buf)
6343 continue;
6344 buf_size = avio_close_dyn_buf(track->mdat_buf, &buf);
6345 track->mdat_buf = NULL;
6346 } else {
6347 if (!mov->mdat_buf)
6348 continue;
6349 buf_size = avio_close_dyn_buf(mov->mdat_buf, &buf);
6350 mov->mdat_buf = NULL;
6351 }
6352
6353 avio_write(s->pb, buf, buf_size);
6354 av_free(buf);
6355 }
6356
6357 mov->mdat_size = 0;
6358
6359 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6360 return 0;
6361 }
6362
6363 static int mov_auto_flush_fragment(AVFormatContext *s, int force)
6364 {
6365 MOVMuxContext *mov = s->priv_data;
6366 int had_moov = mov->moov_written;
6367 int ret = mov_flush_fragment(s, force);
6368 if (ret < 0)
6369 return ret;
6370 // If using delay_moov, the first flush only wrote the moov,
6371 // not the actual moof+mdat pair, thus flush once again.
6372 if (!had_moov && mov->flags & FF_MOV_FLAG_DELAY_MOOV)
6373 ret = mov_flush_fragment(s, force);
6374 return ret;
6375 }
6376
6377 static int check_pkt(AVFormatContext *s, AVPacket *pkt)
6378 {
6379 MOVMuxContext *mov = s->priv_data;
6380 MOVTrack *trk = &mov->tracks[pkt->stream_index];
6381 int64_t ref;
6382 uint64_t duration;
6383
6384 if (trk->entry) {
6385 ref = trk->cluster[trk->entry - 1].dts;
6386 } else if ( trk->start_dts != AV_NOPTS_VALUE
6387 && !trk->frag_discont) {
6388 ref = trk->start_dts + trk->track_duration;
6389 } else
6390 ref = pkt->dts; // Skip tests for the first packet
6391
6392 if (trk->dts_shift != AV_NOPTS_VALUE) {
6393 /* With negative CTS offsets we have set an offset to the DTS,
6394 * reverse this for the check. */
6395 ref -= trk->dts_shift;
6396 }
6397
6398 duration = pkt->dts - ref;
6399 if (pkt->dts < ref || duration >= INT_MAX) {
6400 av_log(s, AV_LOG_WARNING, "Packet duration: %"PRId64" / dts: %"PRId64" is out of range\n",
6401 duration, pkt->dts);
6402
6403 pkt->dts = ref + 1;
6404 pkt->pts = AV_NOPTS_VALUE;
6405 }
6406
6407 if (pkt->duration < 0 || pkt->duration > INT_MAX) {
6408 av_log(s, AV_LOG_ERROR, "Application provided duration: %"PRId64" is invalid\n", pkt->duration);
6409 return AVERROR(EINVAL);
6410 }
6411 return 0;
6412 }
6413
6414 int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
6415 {
6416 MOVMuxContext *mov = s->priv_data;
6417 AVIOContext *pb = s->pb;
6418 MOVTrack *trk = &mov->tracks[pkt->stream_index];
6419 AVCodecParameters *par = trk->par;
6420 AVProducerReferenceTime *prft;
6421 unsigned int samples_in_chunk = 0;
6422 int size = pkt->size, ret = 0, offset = 0;
6423 size_t prft_size;
6424 uint8_t *reformatted_data = NULL;
6425
6426 ret = check_pkt(s, pkt);
6427 if (ret < 0)
6428 return ret;
6429
6430 if (mov->flags & FF_MOV_FLAG_FRAGMENT || mov->mode == MODE_AVIF) {
6431 int ret;
6432 if (mov->moov_written || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
6433 if (mov->frag_interleave && mov->fragments > 0) {
6434 if (trk->entry - trk->entries_flushed >= mov->frag_interleave) {
6435 if ((ret = mov_flush_fragment_interleaving(s, trk)) < 0)
6436 return ret;
6437 }
6438 }
6439
6440 if (!trk->mdat_buf) {
6441 if ((ret = avio_open_dyn_buf(&trk->mdat_buf)) < 0)
6442 return ret;
6443 }
6444 pb = trk->mdat_buf;
6445 } else {
6446 if (!mov->mdat_buf) {
6447 if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
6448 return ret;
6449 }
6450 pb = mov->mdat_buf;
6451 }
6452 }
6453
6454 if (par->codec_id == AV_CODEC_ID_AMR_NB) {
6455 /* We must find out how many AMR blocks there are in one packet */
6456 static const uint16_t packed_size[16] =
6457 {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
6458 int len = 0;
6459
6460 while (len < size && samples_in_chunk < 100) {
6461 len += packed_size[(pkt->data[len] >> 3) & 0x0F];
6462 samples_in_chunk++;
6463 }
6464 if (samples_in_chunk > 1) {
6465 av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
6466 return -1;
6467 }
6468 } else if (par->codec_id == AV_CODEC_ID_ADPCM_MS ||
6469 par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
6470 samples_in_chunk = trk->par->frame_size;
6471 } else if (trk->sample_size)
6472 samples_in_chunk = size / trk->sample_size;
6473 else
6474 samples_in_chunk = 1;
6475
6476 if (samples_in_chunk < 1) {
6477 av_log(s, AV_LOG_ERROR, "fatal error, input packet contains no samples\n");
6478 return AVERROR_PATCHWELCOME;
6479 }
6480
6481 /* copy extradata if it exists */
6482 if (trk->vos_len == 0 && par->extradata_size > 0 &&
6483 !TAG_IS_AVCI(trk->tag) &&
6484 (par->codec_id != AV_CODEC_ID_DNXHD)) {
6485 trk->vos_len = par->extradata_size;
6486 trk->vos_data = av_malloc(trk->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
6487 if (!trk->vos_data) {
6488 ret = AVERROR(ENOMEM);
6489 goto err;
6490 }
6491 memcpy(trk->vos_data, par->extradata, trk->vos_len);
6492 memset(trk->vos_data + trk->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
6493 }
6494
6495 if ((par->codec_id == AV_CODEC_ID_DNXHD ||
6496 par->codec_id == AV_CODEC_ID_H264 ||
6497 par->codec_id == AV_CODEC_ID_HEVC ||
6498 par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->vos_len &&
6499 !TAG_IS_AVCI(trk->tag)) {
6500 /* copy frame to create needed atoms */
6501 trk->vos_len = size;
6502 trk->vos_data = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
6503 if (!trk->vos_data) {
6504 ret = AVERROR(ENOMEM);
6505 goto err;
6506 }
6507 memcpy(trk->vos_data, pkt->data, size);
6508 memset(trk->vos_data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
6509 }
6510
6511 if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
6512 (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
6513 if (!s->streams[pkt->stream_index]->nb_frames) {
6514 av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: "
6515 "use the audio bitstream filter 'aac_adtstoasc' to fix it "
6516 "('-bsf:a aac_adtstoasc' option with ffmpeg)\n");
6517 return -1;
6518 }
6519 av_log(s, AV_LOG_WARNING, "aac bitstream error\n");
6520 }
6521 if (par->codec_id == AV_CODEC_ID_H264 && trk->vos_len > 0 && *(uint8_t *)trk->vos_data != 1 && !TAG_IS_AVCI(trk->tag)) {
6522 /* from x264 or from bytestream H.264 */
6523 /* NAL reformatting needed */
6524 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
6525 ret = ff_avc_parse_nal_units_buf(pkt->data, &reformatted_data,
6526 &size);
6527 if (ret < 0)
6528 return ret;
6529 avio_write(pb, reformatted_data, size);
6530 } else {
6531 if (trk->cenc.aes_ctr) {
6532 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
6533 if (size < 0) {
6534 ret = size;
6535 goto err;
6536 }
6537 } else {
6538 size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size);
6539 }
6540 }
6541 } else if (par->codec_id == AV_CODEC_ID_HEVC && trk->vos_len > 6 &&
6542 (AV_RB24(trk->vos_data) == 1 || AV_RB32(trk->vos_data) == 1)) {
6543 /* extradata is Annex B, assume the bitstream is too and convert it */
6544 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
6545 ret = ff_hevc_annexb2mp4_buf(pkt->data, &reformatted_data,
6546 &size, 0, NULL);
6547 if (ret < 0)
6548 return ret;
6549 avio_write(pb, reformatted_data, size);
6550 } else {
6551 if (trk->cenc.aes_ctr) {
6552 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
6553 if (size < 0) {
6554 ret = size;
6555 goto err;
6556 }
6557 } else {
6558 size = ff_hevc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
6559 }
6560 }
6561 } else if (par->codec_id == AV_CODEC_ID_AV1) {
6562 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
6563 ret = ff_av1_filter_obus_buf(pkt->data, &reformatted_data,
6564 &size, &offset);
6565 if (ret < 0)
6566 return ret;
6567 avio_write(pb, reformatted_data, size);
6568 } else {
6569 size = ff_av1_filter_obus(pb, pkt->data, pkt->size);
6570 if (trk->mode == MODE_AVIF && !mov->avif_extent_length[pkt->stream_index]) {
6571 mov->avif_extent_length[pkt->stream_index] = size;
6572 }
6573 }
6574
6575 } else if (par->codec_id == AV_CODEC_ID_AC3 ||
6576 par->codec_id == AV_CODEC_ID_EAC3) {
6577 size = handle_eac3(mov, pkt, trk);
6578 if (size < 0)
6579 return size;
6580 else if (!size)
6581 goto end;
6582 avio_write(pb, pkt->data, size);
6583 } else if (par->codec_id == AV_CODEC_ID_EIA_608) {
6584 size = 8;
6585
6586 for (int i = 0; i < pkt->size; i += 3) {
6587 if (pkt->data[i] == 0xFC) {
6588 size += 2;
6589 }
6590 }
6591 avio_wb32(pb, size);
6592 ffio_wfourcc(pb, "cdat");
6593 for (int i = 0; i < pkt->size; i += 3) {
6594 if (pkt->data[i] == 0xFC) {
6595 avio_w8(pb, pkt->data[i + 1]);
6596 avio_w8(pb, pkt->data[i + 2]);
6597 }
6598 }
6599 } else {
6600 if (trk->cenc.aes_ctr) {
6601 if (par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 4) {
6602 int nal_size_length = (par->extradata[4] & 0x3) + 1;
6603 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
6604 } else if(par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 21) {
6605 int nal_size_length = (par->extradata[21] & 0x3) + 1;
6606 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
6607 } else {
6608 ret = ff_mov_cenc_write_packet(&trk->cenc, pb, pkt->data, size);
6609 }
6610
6611 if (ret) {
6612 goto err;
6613 }
6614 } else {
6615 avio_write(pb, pkt->data, size);
6616 }
6617 }
6618
6619 if (trk->entry >= trk->cluster_capacity) {
6620 unsigned new_capacity = trk->entry + MOV_INDEX_CLUSTER_SIZE;
6621 void *cluster = av_realloc_array(trk->cluster, new_capacity, sizeof(*trk->cluster));
6622 if (!cluster) {
6623 ret = AVERROR(ENOMEM);
6624 goto err;
6625 }
6626 trk->cluster = cluster;
6627 trk->cluster_capacity = new_capacity;
6628 }
6629
6630 trk->cluster[trk->entry].pos = avio_tell(pb) - size;
6631 trk->cluster[trk->entry].samples_in_chunk = samples_in_chunk;
6632 trk->cluster[trk->entry].chunkNum = 0;
6633 trk->cluster[trk->entry].size = size;
6634 trk->cluster[trk->entry].entries = samples_in_chunk;
6635 trk->cluster[trk->entry].dts = pkt->dts;
6636 trk->cluster[trk->entry].pts = pkt->pts;
6637 if (!trk->squash_fragment_samples_to_one &&
6638 !trk->entry && trk->start_dts != AV_NOPTS_VALUE) {
6639 if (!trk->frag_discont) {
6640 /* First packet of a new fragment. We already wrote the duration
6641 * of the last packet of the previous fragment based on track_duration,
6642 * which might not exactly match our dts. Therefore adjust the dts
6643 * of this packet to be what the previous packets duration implies. */
6644 trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration;
6645 /* We also may have written the pts and the corresponding duration
6646 * in sidx/tfrf/tfxd tags; make sure the sidx pts and duration match up with
6647 * the next fragment. This means the cts of the first sample must
6648 * be the same in all fragments, unless end_pts was updated by
6649 * the packet causing the fragment to be written. */
6650 if ((mov->flags & FF_MOV_FLAG_DASH &&
6651 !(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | FF_MOV_FLAG_SKIP_SIDX))) ||
6652 mov->mode == MODE_ISM)
6653 pkt->pts = pkt->dts + trk->end_pts - trk->cluster[trk->entry].dts;
6654 } else {
6655 /* New fragment, but discontinuous from previous fragments.
6656 * Pretend the duration sum of the earlier fragments is
6657 * pkt->dts - trk->start_dts. */
6658 trk->end_pts = AV_NOPTS_VALUE;
6659 trk->frag_discont = 0;
6660 }
6661 }
6662
6663 if (!trk->entry && trk->start_dts == AV_NOPTS_VALUE && !mov->use_editlist &&
6664 s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) {
6665 /* Not using edit lists and shifting the first track to start from zero.
6666 * If the other streams start from a later timestamp, we won't be able
6667 * to signal the difference in starting time without an edit list.
6668 * Thus move the timestamp for this first sample to 0, increasing
6669 * its duration instead. */
6670 trk->cluster[trk->entry].dts = trk->start_dts = 0;
6671 }
6672 if (trk->start_dts == AV_NOPTS_VALUE) {
6673 trk->start_dts = pkt->dts;
6674 if (trk->frag_discont) {
6675 if (mov->use_editlist) {
6676 /* Pretend the whole stream started at pts=0, with earlier fragments
6677 * already written. If the stream started at pts=0, the duration sum
6678 * of earlier fragments would have been pkt->pts. */
6679 trk->start_dts = pkt->dts - pkt->pts;
6680 } else {
6681 /* Pretend the whole stream started at dts=0, with earlier fragments
6682 * already written, with a duration summing up to pkt->dts. */
6683 trk->start_dts = 0;
6684 }
6685 trk->frag_discont = 0;
6686 } else if (pkt->dts && mov->moov_written)
6687 av_log(s, AV_LOG_WARNING,
6688 "Track %d starts with a nonzero dts %"PRId64", while the moov "
6689 "already has been written. Set the delay_moov flag to handle "
6690 "this case.\n",
6691 pkt->stream_index, pkt->dts);
6692 }
6693 trk->track_duration = pkt->dts - trk->start_dts + pkt->duration;
6694 trk->last_sample_is_subtitle_end = 0;
6695
6696 if (pkt->pts == AV_NOPTS_VALUE) {
6697 av_log(s, AV_LOG_WARNING, "pts has no value\n");
6698 pkt->pts = pkt->dts;
6699 }
6700 if (pkt->dts != pkt->pts)
6701 trk->flags |= MOV_TRACK_CTTS;
6702 trk->cluster[trk->entry].cts = pkt->pts - pkt->dts;
6703 trk->cluster[trk->entry].flags = 0;
6704 if (trk->start_cts == AV_NOPTS_VALUE)
6705 trk->start_cts = pkt->pts - pkt->dts;
6706 if (trk->end_pts == AV_NOPTS_VALUE)
6707 trk->end_pts = trk->cluster[trk->entry].dts +
6708 trk->cluster[trk->entry].cts + pkt->duration;
6709 else
6710 trk->end_pts = FFMAX(trk->end_pts, trk->cluster[trk->entry].dts +
6711 trk->cluster[trk->entry].cts +
6712 pkt->duration);
6713
6714 if (par->codec_id == AV_CODEC_ID_VC1) {
6715 mov_parse_vc1_frame(pkt, trk);
6716 } else if (par->codec_id == AV_CODEC_ID_TRUEHD) {
6717 mov_parse_truehd_frame(pkt, trk);
6718 } else if (pkt->flags & AV_PKT_FLAG_KEY) {
6719 if (mov->mode == MODE_MOV && par->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
6720 trk->entry > 0) { // force sync sample for the first key frame
6721 mov_parse_mpeg2_frame(pkt, &trk->cluster[trk->entry].flags);
6722 if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE)
6723 trk->flags |= MOV_TRACK_STPS;
6724 } else {
6725 trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE;
6726 }
6727 if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE)
6728 trk->has_keyframes++;
6729 }
6730 if (pkt->flags & AV_PKT_FLAG_DISPOSABLE) {
6731 trk->cluster[trk->entry].flags |= MOV_DISPOSABLE_SAMPLE;
6732 trk->has_disposable++;
6733 }
6734
6735 #ifdef OHOS_SDTP_BOX_EXT
6736 if (pkt->flags & AV_PKT_FLAG_DISPOSABLE_EXT) {
6737 trk->cluster[trk->entry].flags |= MOV_DISPOSABLE_EXT_SAMPLE;
6738 trk->has_disposable++;
6739 }
6740 #endif
6741
6742 prft = (AVProducerReferenceTime *)av_packet_get_side_data(pkt, AV_PKT_DATA_PRFT, &prft_size);
6743 if (prft && prft_size == sizeof(AVProducerReferenceTime))
6744 memcpy(&trk->cluster[trk->entry].prft, prft, prft_size);
6745 else
6746 memset(&trk->cluster[trk->entry].prft, 0, sizeof(AVProducerReferenceTime));
6747
6748 trk->entry++;
6749 trk->sample_count += samples_in_chunk;
6750 mov->mdat_size += size;
6751
6752 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams)
6753 ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry,
6754 reformatted_data ? reformatted_data + offset
6755 : NULL, size);
6756
6757 end:
6758 err:
6759
6760 if (pkt->data != reformatted_data)
6761 av_free(reformatted_data);
6762 return ret;
6763 }
6764
6765 static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
6766 {
6767 MOVMuxContext *mov = s->priv_data;
6768 MOVTrack *trk = &mov->tracks[pkt->stream_index];
6769 AVCodecParameters *par = trk->par;
6770 int64_t frag_duration = 0;
6771 int size = pkt->size;
6772
6773 int ret = check_pkt(s, pkt);
6774 if (ret < 0)
6775 return ret;
6776
6777 if (mov->flags & FF_MOV_FLAG_FRAG_DISCONT) {
6778 int i;
6779 for (i = 0; i < s->nb_streams; i++)
6780 mov->tracks[i].frag_discont = 1;
6781 mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT;
6782 }
6783
6784 if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) {
6785 if (trk->dts_shift == AV_NOPTS_VALUE)
6786 trk->dts_shift = pkt->pts - pkt->dts;
6787 pkt->dts += trk->dts_shift;
6788 }
6789
6790 if (trk->par->codec_id == AV_CODEC_ID_MP4ALS ||
6791 trk->par->codec_id == AV_CODEC_ID_AAC ||
6792 trk->par->codec_id == AV_CODEC_ID_AV1 ||
6793 trk->par->codec_id == AV_CODEC_ID_FLAC) {
6794 size_t side_size;
6795 uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
6796 if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) {
6797 void *newextra = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE);
6798 if (!newextra)
6799 return AVERROR(ENOMEM);
6800 av_free(par->extradata);
6801 par->extradata = newextra;
6802 memcpy(par->extradata, side, side_size);
6803 par->extradata_size = side_size;
6804 if (!pkt->size) // Flush packet
6805 mov->need_rewrite_extradata = 1;
6806 }
6807 }
6808
6809 if (!pkt->size) {
6810 if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) {
6811 trk->start_dts = pkt->dts;
6812 if (pkt->pts != AV_NOPTS_VALUE)
6813 trk->start_cts = pkt->pts - pkt->dts;
6814 else
6815 trk->start_cts = 0;
6816 }
6817
6818 return 0; /* Discard 0 sized packets */
6819 }
6820
6821 if (trk->entry && pkt->stream_index < s->nb_streams)
6822 frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts,
6823 s->streams[pkt->stream_index]->time_base,
6824 AV_TIME_BASE_Q);
6825 if ((mov->max_fragment_duration &&
6826 frag_duration >= mov->max_fragment_duration) ||
6827 (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) ||
6828 (mov->flags & FF_MOV_FLAG_FRAG_KEYFRAME &&
6829 par->codec_type == AVMEDIA_TYPE_VIDEO &&
6830 trk->entry && pkt->flags & AV_PKT_FLAG_KEY) ||
6831 (mov->flags & FF_MOV_FLAG_FRAG_EVERY_FRAME)) {
6832 if (frag_duration >= mov->min_fragment_duration) {
6833 if (trk->entry) {
6834 // Set the duration of this track to line up with the next
6835 // sample in this track. This avoids relying on AVPacket
6836 // duration, but only helps for this particular track, not
6837 // for the other ones that are flushed at the same time.
6838 //
6839 // If we have trk->entry == 0, no fragment will be written
6840 // for this track, and we can't adjust the track end here.
6841 trk->track_duration = pkt->dts - trk->start_dts;
6842 if (pkt->pts != AV_NOPTS_VALUE)
6843 trk->end_pts = pkt->pts;
6844 else
6845 trk->end_pts = pkt->dts;
6846 trk->end_reliable = 1;
6847 }
6848 mov_auto_flush_fragment(s, 0);
6849 }
6850 }
6851
6852 return ff_mov_write_packet(s, pkt);
6853 }
6854
6855 static int mov_write_subtitle_end_packet(AVFormatContext *s,
6856 int stream_index,
6857 int64_t dts) {
6858 MOVMuxContext *mov = s->priv_data;
6859 AVPacket *end = mov->pkt;
6860 uint8_t data[2] = {0};
6861 int ret;
6862
6863 end->size = sizeof(data);
6864 end->data = data;
6865 end->pts = dts;
6866 end->dts = dts;
6867 end->duration = 0;
6868 end->stream_index = stream_index;
6869
6870 ret = mov_write_single_packet(s, end);
6871 av_packet_unref(end);
6872
6873 return ret;
6874 }
6875
6876 static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
6877 {
6878 MOVMuxContext *mov = s->priv_data;
6879 MOVTrack *trk;
6880
6881 if (!pkt) {
6882 mov_flush_fragment(s, 1);
6883 return 1;
6884 }
6885
6886 trk = &mov->tracks[pkt->stream_index];
6887
6888 if (is_cover_image(trk->st)) {
6889 int ret;
6890
6891 if (trk->st->nb_frames >= 1) {
6892 if (trk->st->nb_frames == 1)
6893 av_log(s, AV_LOG_WARNING, "Got more than one picture in stream %d,"
6894 " ignoring.\n", pkt->stream_index);
6895 return 0;
6896 }
6897
6898 if ((ret = av_packet_ref(trk->cover_image, pkt)) < 0)
6899 return ret;
6900
6901 return 0;
6902 } else {
6903 int i;
6904
6905 if (!pkt->size)
6906 return mov_write_single_packet(s, pkt); /* Passthrough. */
6907
6908 /*
6909 * Subtitles require special handling.
6910 *
6911 * 1) For full complaince, every track must have a sample at
6912 * dts == 0, which is rarely true for subtitles. So, as soon
6913 * as we see any packet with dts > 0, write an empty subtitle
6914 * at dts == 0 for any subtitle track with no samples in it.
6915 *
6916 * 2) For each subtitle track, check if the current packet's
6917 * dts is past the duration of the last subtitle sample. If
6918 * so, we now need to write an end sample for that subtitle.
6919 *
6920 * This must be done conditionally to allow for subtitles that
6921 * immediately replace each other, in which case an end sample
6922 * is not needed, and is, in fact, actively harmful.
6923 *
6924 * 3) See mov_write_trailer for how the final end sample is
6925 * handled.
6926 */
6927 for (i = 0; i < mov->nb_streams; i++) {
6928 MOVTrack *trk = &mov->tracks[i];
6929 int ret;
6930
6931 if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
6932 trk->track_duration < pkt->dts &&
6933 (trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
6934 ret = mov_write_subtitle_end_packet(s, i, trk->track_duration);
6935 if (ret < 0) return ret;
6936 trk->last_sample_is_subtitle_end = 1;
6937 }
6938 }
6939
6940 if (trk->squash_fragment_samples_to_one) {
6941 /*
6942 * If the track has to have its samples squashed into one sample,
6943 * we just take it into the track's queue.
6944 * This will then be utilized as the samples get written in either
6945 * mov_flush_fragment or when the mux is finalized in
6946 * mov_write_trailer.
6947 */
6948 int ret = AVERROR_BUG;
6949
6950 if (pkt->pts == AV_NOPTS_VALUE) {
6951 av_log(s, AV_LOG_ERROR,
6952 "Packets without a valid presentation timestamp are "
6953 "not supported with packet squashing!\n");
6954 return AVERROR(EINVAL);
6955 }
6956
6957 /* The following will reset pkt and is only allowed to be used
6958 * because we return immediately. afterwards. */
6959 if ((ret = avpriv_packet_list_put(&trk->squashed_packet_queue,
6960 pkt, NULL, 0)) < 0) {
6961 return ret;
6962 }
6963
6964 return 0;
6965 }
6966
6967
6968 if (trk->mode == MODE_MOV && trk->par->codec_type == AVMEDIA_TYPE_VIDEO) {
6969 AVPacket *opkt = pkt;
6970 int reshuffle_ret, ret;
6971 if (trk->is_unaligned_qt_rgb) {
6972 int64_t bpc = trk->par->bits_per_coded_sample != 15 ? trk->par->bits_per_coded_sample : 16;
6973 int expected_stride = ((trk->par->width * bpc + 15) >> 4)*2;
6974 reshuffle_ret = ff_reshuffle_raw_rgb(s, &pkt, trk->par, expected_stride);
6975 if (reshuffle_ret < 0)
6976 return reshuffle_ret;
6977 } else
6978 reshuffle_ret = 0;
6979 if (trk->par->format == AV_PIX_FMT_PAL8 && !trk->pal_done) {
6980 ret = ff_get_packet_palette(s, opkt, reshuffle_ret, trk->palette);
6981 if (ret < 0)
6982 goto fail;
6983 if (ret)
6984 trk->pal_done++;
6985 } else if (trk->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
6986 (trk->par->format == AV_PIX_FMT_GRAY8 ||
6987 trk->par->format == AV_PIX_FMT_MONOBLACK)) {
6988 ret = av_packet_make_writable(pkt);
6989 if (ret < 0)
6990 goto fail;
6991 for (i = 0; i < pkt->size; i++)
6992 pkt->data[i] = ~pkt->data[i];
6993 }
6994 if (reshuffle_ret) {
6995 ret = mov_write_single_packet(s, pkt);
6996 fail:
6997 if (reshuffle_ret)
6998 av_packet_free(&pkt);
6999 return ret;
7000 }
7001 }
7002
7003 return mov_write_single_packet(s, pkt);
7004 }
7005 }
7006
7007 // QuickTime chapters involve an additional text track with the chapter names
7008 // as samples, and a tref pointing from the other tracks to the chapter one.
7009 static int mov_create_chapter_track(AVFormatContext *s, int tracknum)
7010 {
7011 static const uint8_t stub_header[] = {
7012 // TextSampleEntry
7013 0x00, 0x00, 0x00, 0x01, // displayFlags
7014 0x00, 0x00, // horizontal + vertical justification
7015 0x00, 0x00, 0x00, 0x00, // bgColourRed/Green/Blue/Alpha
7016 // BoxRecord
7017 0x00, 0x00, 0x00, 0x00, // defTextBoxTop/Left
7018 0x00, 0x00, 0x00, 0x00, // defTextBoxBottom/Right
7019 // StyleRecord
7020 0x00, 0x00, 0x00, 0x00, // startChar + endChar
7021 0x00, 0x01, // fontID
7022 0x00, 0x00, // fontStyleFlags + fontSize
7023 0x00, 0x00, 0x00, 0x00, // fgColourRed/Green/Blue/Alpha
7024 // FontTableBox
7025 0x00, 0x00, 0x00, 0x0D, // box size
7026 'f', 't', 'a', 'b', // box atom name
7027 0x00, 0x01, // entry count
7028 // FontRecord
7029 0x00, 0x01, // font ID
7030 0x00, // font name length
7031 };
7032 MOVMuxContext *mov = s->priv_data;
7033 MOVTrack *track = &mov->tracks[tracknum];
7034 AVPacket *pkt = mov->pkt;
7035 int i, len;
7036 int ret;
7037
7038 track->mode = mov->mode;
7039 track->tag = MKTAG('t','e','x','t');
7040 track->timescale = mov->movie_timescale;
7041 track->par = avcodec_parameters_alloc();
7042 if (!track->par)
7043 return AVERROR(ENOMEM);
7044 track->par->codec_type = AVMEDIA_TYPE_SUBTITLE;
7045 ret = ff_alloc_extradata(track->par, sizeof(stub_header));
7046 if (ret < 0)
7047 return ret;
7048 memcpy(track->par->extradata, stub_header, sizeof(stub_header));
7049
7050 pkt->stream_index = tracknum;
7051 pkt->flags = AV_PKT_FLAG_KEY;
7052
7053 for (i = 0; i < s->nb_chapters; i++) {
7054 AVChapter *c = s->chapters[i];
7055 AVDictionaryEntry *t;
7056
7057 int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,mov->movie_timescale});
7058 pkt->pts = pkt->dts = av_rescale_q(c->start, c->time_base, (AVRational){1,mov->movie_timescale});
7059 pkt->duration = end - pkt->dts;
7060
7061 if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
7062 static const char encd[12] = {
7063 0x00, 0x00, 0x00, 0x0C,
7064 'e', 'n', 'c', 'd',
7065 0x00, 0x00, 0x01, 0x00 };
7066 len = strlen(t->value);
7067 pkt->size = len + 2 + 12;
7068 pkt->data = av_malloc(pkt->size);
7069 if (!pkt->data) {
7070 av_packet_unref(pkt);
7071 return AVERROR(ENOMEM);
7072 }
7073 AV_WB16(pkt->data, len);
7074 memcpy(pkt->data + 2, t->value, len);
7075 memcpy(pkt->data + len + 2, encd, sizeof(encd));
7076 ff_mov_write_packet(s, pkt);
7077 av_freep(&pkt->data);
7078 }
7079 }
7080
7081 av_packet_unref(mov->pkt);
7082
7083 return 0;
7084 }
7085
7086
7087 static int mov_check_timecode_track(AVFormatContext *s, AVTimecode *tc, int src_index, const char *tcstr)
7088 {
7089 int ret;
7090
7091 /* compute the frame number */
7092 ret = av_timecode_init_from_string(tc, s->streams[src_index]->avg_frame_rate, tcstr, s);
7093 return ret;
7094 }
7095
7096 static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, AVTimecode tc)
7097 {
7098 MOVMuxContext *mov = s->priv_data;
7099 MOVTrack *track = &mov->tracks[index];
7100 AVStream *src_st = s->streams[src_index];
7101 uint8_t data[4];
7102 AVPacket *pkt = mov->pkt;
7103 AVRational rate = src_st->avg_frame_rate;
7104 int ret;
7105
7106 /* tmcd track based on video stream */
7107 track->mode = mov->mode;
7108 track->tag = MKTAG('t','m','c','d');
7109 track->src_track = src_index;
7110 track->timescale = mov->tracks[src_index].timescale;
7111 if (tc.flags & AV_TIMECODE_FLAG_DROPFRAME)
7112 track->timecode_flags |= MOV_TIMECODE_FLAG_DROPFRAME;
7113
7114 /* set st to src_st for metadata access*/
7115 track->st = src_st;
7116
7117 /* encode context: tmcd data stream */
7118 track->par = avcodec_parameters_alloc();
7119 if (!track->par)
7120 return AVERROR(ENOMEM);
7121 track->par->codec_type = AVMEDIA_TYPE_DATA;
7122 track->par->codec_tag = track->tag;
7123 track->st->avg_frame_rate = rate;
7124
7125 /* the tmcd track just contains one packet with the frame number */
7126 pkt->data = data;
7127 pkt->stream_index = index;
7128 pkt->flags = AV_PKT_FLAG_KEY;
7129 pkt->pts = pkt->dts = av_rescale_q(tc.start, av_inv_q(rate), (AVRational){1,mov->movie_timescale});
7130 pkt->size = 4;
7131 AV_WB32(pkt->data, tc.start);
7132 ret = ff_mov_write_packet(s, pkt);
7133 av_packet_unref(pkt);
7134 return ret;
7135 }
7136
7137 #ifdef OHOS_TIMED_META_TRACK
7138 static int mov_create_timed_metadata_track(AVFormatContext *s, int index, int src_index)
7139 {
7140 MOVMuxContext *mov = s->priv_data;
7141 MOVTrack *track = &mov->tracks[index];
7142 AVStream *src_st = s->streams[src_index];
7143 AVRational rate = src_st->avg_frame_rate;
7144 int ret;
7145 int track_tag = MKTAG('c','d','s','c');
7146
7147 /* timed metadata track based on video stream */
7148 track->mode = mov->mode;
7149 /* if the timed metadata track describes characteristics of the whole movie,
7150 * there should be no track reference of type 'cdsc'.
7151 */
7152 if (src_index >= 0) {
7153 MOVTrack *src_track = &mov->tracks[src_index];
7154 track->tag = track_tag;
7155 track->tref_tag = track_tag;
7156 track->src_track = src_index;
7157 track->timescale = mov->tracks[src_index].timescale;
7158 int new_track_count = track->ref_track_count + 1;
7159 ret = av_reallocp_array(&track->tref_ids, new_track_count, sizeof(track->tref_ids));
7160 if (ret < 0)
7161 return ret;
7162 track->ref_track_count = new_track_count;
7163 track->tref_ids[track->ref_track_count - 1] = src_track->track_id;
7164 }
7165
7166 /* set st to src_st for metadata access*/
7167 track->st = s->streams[index];
7168
7169 track->par = avcodec_parameters_alloc();
7170 if (!track->par)
7171 return AVERROR(ENOMEM);
7172 track->par->codec_type = AVMEDIA_TYPE_TIMEDMETA;
7173 track->par->codec_id = AV_CODEC_ID_FFMETADATA;
7174 track->par->codec_tag = track_tag;
7175 track->st->avg_frame_rate = av_inv_q(rate);
7176 return 0;
7177 }
7178 #endif
7179
7180 /*
7181 * st->disposition controls the "enabled" flag in the tkhd tag.
7182 * QuickTime will not play a track if it is not enabled. So make sure
7183 * that one track of each type (audio, video, subtitle) is enabled.
7184 *
7185 * Subtitles are special. For audio and video, setting "enabled" also
7186 * makes the track "default" (i.e. it is rendered when played). For
7187 * subtitles, an "enabled" subtitle is not rendered by default, but
7188 * if no subtitle is enabled, the subtitle menu in QuickTime will be
7189 * empty!
7190 */
7191 static void enable_tracks(AVFormatContext *s)
7192 {
7193 MOVMuxContext *mov = s->priv_data;
7194 int i;
7195 int enabled[AVMEDIA_TYPE_NB];
7196 int first[AVMEDIA_TYPE_NB];
7197
7198 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
7199 enabled[i] = 0;
7200 first[i] = -1;
7201 }
7202
7203 for (i = 0; i < s->nb_streams; i++) {
7204 AVStream *st = s->streams[i];
7205
7206 if (st->codecpar->codec_type <= AVMEDIA_TYPE_UNKNOWN ||
7207 st->codecpar->codec_type >= AVMEDIA_TYPE_NB ||
7208 is_cover_image(st))
7209 continue;
7210
7211 if (first[st->codecpar->codec_type] < 0)
7212 first[st->codecpar->codec_type] = i;
7213 if (st->disposition & AV_DISPOSITION_DEFAULT) {
7214 mov->tracks[i].flags |= MOV_TRACK_ENABLED;
7215 enabled[st->codecpar->codec_type]++;
7216 }
7217 }
7218
7219 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
7220 switch (i) {
7221 case AVMEDIA_TYPE_VIDEO:
7222 case AVMEDIA_TYPE_AUDIO:
7223 case AVMEDIA_TYPE_SUBTITLE:
7224 if (enabled[i] > 1)
7225 mov->per_stream_grouping = 1;
7226 if (!enabled[i] && first[i] >= 0)
7227 mov->tracks[first[i]].flags |= MOV_TRACK_ENABLED;
7228 break;
7229 }
7230 }
7231 }
7232
7233 static void mov_free(AVFormatContext *s)
7234 {
7235 MOVMuxContext *mov = s->priv_data;
7236 int i;
7237
7238 if (!mov->tracks)
7239 return;
7240
7241 if (mov->chapter_track) {
7242 avcodec_parameters_free(&mov->tracks[mov->chapter_track].par);
7243 }
7244
7245 for (i = 0; i < mov->nb_streams; i++) {
7246 MOVTrack *const track = &mov->tracks[i];
7247
7248 if (track->tag == MKTAG('r','t','p',' '))
7249 ff_mov_close_hinting(track);
7250 else if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd)
7251 av_freep(&track->par);
7252 av_freep(&track->cluster);
7253 av_freep(&track->frag_info);
7254 av_packet_free(&track->cover_image);
7255
7256 if (track->eac3_priv) {
7257 struct eac3_info *info = track->eac3_priv;
7258 av_packet_free(&info->pkt);
7259 av_freep(&track->eac3_priv);
7260 }
7261 if (track->vos_len)
7262 av_freep(&track->vos_data);
7263
7264 ff_mov_cenc_free(&track->cenc);
7265 ffio_free_dyn_buf(&track->mdat_buf);
7266
7267 avpriv_packet_list_free(&track->squashed_packet_queue);
7268 #ifdef OHOS_TIMED_META_TRACK
7269 av_freep(&track->tref_ids);
7270 #endif
7271 }
7272
7273 av_freep(&mov->tracks);
7274 ffio_free_dyn_buf(&mov->mdat_buf);
7275 }
7276
7277 static uint32_t rgb_to_yuv(uint32_t rgb)
7278 {
7279 uint8_t r, g, b;
7280 int y, cb, cr;
7281
7282 r = (rgb >> 16) & 0xFF;
7283 g = (rgb >> 8) & 0xFF;
7284 b = (rgb ) & 0xFF;
7285
7286 y = av_clip_uint8(( 16000 + 257 * r + 504 * g + 98 * b)/1000);
7287 cb = av_clip_uint8((128000 - 148 * r - 291 * g + 439 * b)/1000);
7288 cr = av_clip_uint8((128000 + 439 * r - 368 * g - 71 * b)/1000);
7289
7290 return (y << 16) | (cr << 8) | cb;
7291 }
7292
7293 static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track,
7294 AVStream *st)
7295 {
7296 int i, width = 720, height = 480;
7297 int have_palette = 0, have_size = 0;
7298 uint32_t palette[16];
7299 char *cur = st->codecpar->extradata;
7300
7301 while (cur && *cur) {
7302 if (strncmp("palette:", cur, 8) == 0) {
7303 int i, count;
7304 count = sscanf(cur + 8,
7305 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
7306 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
7307 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
7308 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32"",
7309 &palette[ 0], &palette[ 1], &palette[ 2], &palette[ 3],
7310 &palette[ 4], &palette[ 5], &palette[ 6], &palette[ 7],
7311 &palette[ 8], &palette[ 9], &palette[10], &palette[11],
7312 &palette[12], &palette[13], &palette[14], &palette[15]);
7313
7314 for (i = 0; i < count; i++) {
7315 palette[i] = rgb_to_yuv(palette[i]);
7316 }
7317 have_palette = 1;
7318 } else if (!strncmp("size:", cur, 5)) {
7319 sscanf(cur + 5, "%dx%d", &width, &height);
7320 have_size = 1;
7321 }
7322 if (have_palette && have_size)
7323 break;
7324 cur += strcspn(cur, "\n\r");
7325 cur += strspn(cur, "\n\r");
7326 }
7327 if (have_palette) {
7328 track->vos_data = av_malloc(16*4 + AV_INPUT_BUFFER_PADDING_SIZE);
7329 if (!track->vos_data)
7330 return AVERROR(ENOMEM);
7331 for (i = 0; i < 16; i++) {
7332 AV_WB32(track->vos_data + i * 4, palette[i]);
7333 }
7334 memset(track->vos_data + 16*4, 0, AV_INPUT_BUFFER_PADDING_SIZE);
7335 track->vos_len = 16 * 4;
7336 }
7337 st->codecpar->width = width;
7338 st->codecpar->height = track->height = height;
7339
7340 return 0;
7341 }
7342
7343 static int mov_init(AVFormatContext *s)
7344 {
7345 MOVMuxContext *mov = s->priv_data;
7346 int i, ret;
7347
7348 mov->fc = s;
7349 mov->pkt = ffformatcontext(s)->pkt;
7350
7351 /* Default mode == MP4 */
7352 mov->mode = MODE_MP4;
7353
7354 #define IS_MODE(muxer, config) (CONFIG_ ## config ## _MUXER && !strcmp(#muxer, s->oformat->name))
7355 if (IS_MODE(3gp, TGP)) mov->mode = MODE_3GP;
7356 else if (IS_MODE(3g2, TG2)) mov->mode = MODE_3GP|MODE_3G2;
7357 else if (IS_MODE(mov, MOV)) mov->mode = MODE_MOV;
7358 else if (IS_MODE(psp, PSP)) mov->mode = MODE_PSP;
7359 else if (IS_MODE(ipod, IPOD)) mov->mode = MODE_IPOD;
7360 else if (IS_MODE(ismv, ISMV)) mov->mode = MODE_ISM;
7361 else if (IS_MODE(f4v, F4V)) mov->mode = MODE_F4V;
7362 else if (IS_MODE(avif, AVIF)) mov->mode = MODE_AVIF;
7363 #undef IS_MODE
7364
7365 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV)
7366 mov->flags |= FF_MOV_FLAG_EMPTY_MOOV;
7367
7368 if (mov->mode == MODE_AVIF)
7369 mov->flags |= FF_MOV_FLAG_DELAY_MOOV;
7370
7371 /* Set the FRAGMENT flag if any of the fragmentation methods are
7372 * enabled. */
7373 if (mov->max_fragment_duration || mov->max_fragment_size ||
7374 mov->flags & (FF_MOV_FLAG_EMPTY_MOOV |
7375 FF_MOV_FLAG_FRAG_KEYFRAME |
7376 FF_MOV_FLAG_FRAG_CUSTOM |
7377 FF_MOV_FLAG_FRAG_EVERY_FRAME))
7378 mov->flags |= FF_MOV_FLAG_FRAGMENT;
7379
7380 /* Set other implicit flags immediately */
7381 if (mov->mode == MODE_ISM)
7382 mov->flags |= FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_SEPARATE_MOOF |
7383 FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS;
7384 if (mov->flags & FF_MOV_FLAG_DASH)
7385 mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV |
7386 FF_MOV_FLAG_DEFAULT_BASE_MOOF;
7387 if (mov->flags & FF_MOV_FLAG_CMAF)
7388 mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV |
7389 FF_MOV_FLAG_DEFAULT_BASE_MOOF | FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS;
7390
7391 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && s->flags & AVFMT_FLAG_AUTO_BSF) {
7392 av_log(s, AV_LOG_VERBOSE, "Empty MOOV enabled; disabling automatic bitstream filtering\n");
7393 s->flags &= ~AVFMT_FLAG_AUTO_BSF;
7394 }
7395
7396 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX && mov->flags & FF_MOV_FLAG_SKIP_SIDX) {
7397 av_log(s, AV_LOG_WARNING, "Global SIDX enabled; Ignoring skip_sidx option\n");
7398 mov->flags &= ~FF_MOV_FLAG_SKIP_SIDX;
7399 }
7400
7401 if (mov->flags & FF_MOV_FLAG_FASTSTART) {
7402 mov->reserved_moov_size = -1;
7403 }
7404
7405 if (mov->use_editlist < 0) {
7406 mov->use_editlist = 1;
7407 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
7408 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
7409 // If we can avoid needing an edit list by shifting the
7410 // tracks, prefer that over (trying to) write edit lists
7411 // in fragmented output.
7412 if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO ||
7413 s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO)
7414 mov->use_editlist = 0;
7415 }
7416 if (mov->flags & FF_MOV_FLAG_CMAF) {
7417 // CMAF Track requires negative cts offsets without edit lists
7418 mov->use_editlist = 0;
7419 }
7420 }
7421 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
7422 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV) && mov->use_editlist)
7423 av_log(s, AV_LOG_WARNING, "No meaningful edit list will be written when using empty_moov without delay_moov\n");
7424
7425 if (mov->flags & FF_MOV_FLAG_CMAF && mov->use_editlist) {
7426 av_log(s, AV_LOG_WARNING, "Edit list enabled; Assuming writing CMAF Track File\n");
7427 mov->flags &= ~FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS;
7428 }
7429 if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO &&
7430 !(mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS))
7431 s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO;
7432
7433 /* Clear the omit_tfhd_offset flag if default_base_moof is set;
7434 * if the latter is set that's enough and omit_tfhd_offset doesn't
7435 * add anything extra on top of that. */
7436 if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET &&
7437 mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
7438 mov->flags &= ~FF_MOV_FLAG_OMIT_TFHD_OFFSET;
7439
7440 if (mov->frag_interleave &&
7441 mov->flags & (FF_MOV_FLAG_OMIT_TFHD_OFFSET | FF_MOV_FLAG_SEPARATE_MOOF)) {
7442 av_log(s, AV_LOG_ERROR,
7443 "Sample interleaving in fragments is mutually exclusive with "
7444 "omit_tfhd_offset and separate_moof\n");
7445 return AVERROR(EINVAL);
7446 }
7447
7448 /* Non-seekable output is ok if using fragmentation. If ism_lookahead
7449 * is enabled, we don't support non-seekable output at all. */
7450 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
7451 (!(mov->flags & FF_MOV_FLAG_FRAGMENT) || mov->ism_lookahead ||
7452 mov->mode == MODE_AVIF)) {
7453 av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
7454 return AVERROR(EINVAL);
7455 }
7456
7457 /* AVIF output must have at most two video streams (one for YUV and one for
7458 * alpha). */
7459 if (mov->mode == MODE_AVIF) {
7460 if (s->nb_streams > 2) {
7461 av_log(s, AV_LOG_ERROR, "AVIF output requires exactly one or two streams\n");
7462 return AVERROR(EINVAL);
7463 }
7464 if (s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
7465 (s->nb_streams > 1 && s->streams[1]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)) {
7466 av_log(s, AV_LOG_ERROR, "AVIF output supports only video streams\n");
7467 return AVERROR(EINVAL);
7468 }
7469 if (s->nb_streams > 1) {
7470 const AVPixFmtDescriptor *pixdesc =
7471 av_pix_fmt_desc_get(s->streams[1]->codecpar->format);
7472 if (pixdesc->nb_components != 1) {
7473 av_log(s, AV_LOG_ERROR, "Second stream for AVIF (alpha) output must have exactly one plane\n");
7474 return AVERROR(EINVAL);
7475 }
7476 }
7477 s->streams[0]->disposition |= AV_DISPOSITION_DEFAULT;
7478 }
7479
7480 mov->nb_streams = s->nb_streams;
7481 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
7482 mov->chapter_track = mov->nb_streams++;
7483
7484 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
7485 for (i = 0; i < s->nb_streams; i++)
7486 if (rtp_hinting_needed(s->streams[i]))
7487 mov->nb_streams++;
7488 }
7489
7490 if (mov->write_btrt < 0) {
7491 mov->write_btrt = mov->mode == MODE_MP4;
7492 }
7493
7494 if ( mov->write_tmcd == -1 && (mov->mode == MODE_MOV || mov->mode == MODE_MP4)
7495 || mov->write_tmcd == 1) {
7496 AVDictionaryEntry *global_tcr = av_dict_get(s->metadata, "timecode",
7497 NULL, 0);
7498
7499 /* +1 tmcd track for each video stream with a timecode */
7500 for (i = 0; i < s->nb_streams; i++) {
7501 AVStream *st = s->streams[i];
7502 AVDictionaryEntry *t = global_tcr;
7503 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
7504 (t || (t=av_dict_get(st->metadata, "timecode", NULL, 0)))) {
7505 AVTimecode tc;
7506 ret = mov_check_timecode_track(s, &tc, i, t->value);
7507 if (ret >= 0)
7508 mov->nb_meta_tmcd++;
7509 }
7510 }
7511
7512 /* check if there is already a tmcd track to remux */
7513 if (mov->nb_meta_tmcd) {
7514 for (i = 0; i < s->nb_streams; i++) {
7515 AVStream *st = s->streams[i];
7516 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
7517 av_log(s, AV_LOG_WARNING, "You requested a copy of the original timecode track "
7518 "so timecode metadata are now ignored\n");
7519 mov->nb_meta_tmcd = 0;
7520 }
7521 }
7522 }
7523
7524 mov->nb_streams += mov->nb_meta_tmcd;
7525 }
7526
7527 #ifdef OHOS_TIMED_META_TRACK
7528 if (mov->flags & FF_MOV_FLAG_TIMED_METADATA) {
7529 for (i = 0; i < s->nb_streams; i++) {
7530 AVStream *st = s->streams[i];
7531 if (st->codecpar->codec_type == AVMEDIA_TYPE_TIMEDMETA)
7532 mov->nb_timed_metadata_track++;
7533 }
7534 }
7535 #endif
7536 // Reserve an extra stream for chapters for the case where chapters
7537 // are written in the trailer
7538 mov->tracks = av_calloc(mov->nb_streams + 1, sizeof(*mov->tracks));
7539 if (!mov->tracks)
7540 return AVERROR(ENOMEM);
7541
7542 if (mov->encryption_scheme_str != NULL && strcmp(mov->encryption_scheme_str, "none") != 0) {
7543 if (strcmp(mov->encryption_scheme_str, "cenc-aes-ctr") == 0) {
7544 mov->encryption_scheme = MOV_ENC_CENC_AES_CTR;
7545
7546 if (mov->encryption_key_len != AES_CTR_KEY_SIZE) {
7547 av_log(s, AV_LOG_ERROR, "Invalid encryption key len %d expected %d\n",
7548 mov->encryption_key_len, AES_CTR_KEY_SIZE);
7549 return AVERROR(EINVAL);
7550 }
7551
7552 if (mov->encryption_kid_len != CENC_KID_SIZE) {
7553 av_log(s, AV_LOG_ERROR, "Invalid encryption kid len %d expected %d\n",
7554 mov->encryption_kid_len, CENC_KID_SIZE);
7555 return AVERROR(EINVAL);
7556 }
7557 } else {
7558 av_log(s, AV_LOG_ERROR, "unsupported encryption scheme %s\n",
7559 mov->encryption_scheme_str);
7560 return AVERROR(EINVAL);
7561 }
7562 }
7563
7564 for (i = 0; i < s->nb_streams; i++) {
7565 AVStream *st= s->streams[i];
7566 MOVTrack *track= &mov->tracks[i];
7567 AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
7568
7569 track->st = st;
7570 track->par = st->codecpar;
7571 track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
7572 if (track->language < 0)
7573 track->language = 32767; // Unspecified Macintosh language code
7574 track->mode = mov->mode;
7575 track->tag = mov_find_codec_tag(s, track);
7576 if (!track->tag) {
7577 av_log(s, AV_LOG_ERROR, "Could not find tag for codec %s in stream #%d, "
7578 "codec not currently supported in container\n",
7579 avcodec_get_name(st->codecpar->codec_id), i);
7580 return AVERROR(EINVAL);
7581 }
7582 /* If hinting of this track is enabled by a later hint track,
7583 * this is updated. */
7584 track->hint_track = -1;
7585 track->start_dts = AV_NOPTS_VALUE;
7586 track->start_cts = AV_NOPTS_VALUE;
7587 track->end_pts = AV_NOPTS_VALUE;
7588 track->dts_shift = AV_NOPTS_VALUE;
7589 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
7590 if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
7591 track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
7592 track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
7593 if (st->codecpar->width != 720 || (st->codecpar->height != 608 && st->codecpar->height != 512)) {
7594 av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
7595 return AVERROR(EINVAL);
7596 }
7597 track->height = track->tag >> 24 == 'n' ? 486 : 576;
7598 }
7599 if (mov->video_track_timescale) {
7600 track->timescale = mov->video_track_timescale;
7601 if (mov->mode == MODE_ISM && mov->video_track_timescale != 10000000)
7602 av_log(s, AV_LOG_WARNING, "Warning: some tools, like mp4split, assume a timescale of 10000000 for ISMV.\n");
7603 } else {
7604 track->timescale = st->time_base.den;
7605 while(track->timescale < 10000)
7606 track->timescale *= 2;
7607 }
7608 if (st->codecpar->width > 65535 || st->codecpar->height > 65535) {
7609 av_log(s, AV_LOG_ERROR, "Resolution %dx%d too large for mov/mp4\n", st->codecpar->width, st->codecpar->height);
7610 return AVERROR(EINVAL);
7611 }
7612 if (track->mode == MODE_MOV && track->timescale > 100000)
7613 av_log(s, AV_LOG_WARNING,
7614 "WARNING codec timebase is very high. If duration is too long,\n"
7615 "file may not be playable by quicktime. Specify a shorter timebase\n"
7616 "or choose different container.\n");
7617 if (track->mode == MODE_MOV &&
7618 track->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
7619 track->tag == MKTAG('r','a','w',' ')) {
7620 enum AVPixelFormat pix_fmt = track->par->format;
7621 if (pix_fmt == AV_PIX_FMT_NONE && track->par->bits_per_coded_sample == 1)
7622 pix_fmt = AV_PIX_FMT_MONOWHITE;
7623 track->is_unaligned_qt_rgb =
7624 pix_fmt == AV_PIX_FMT_RGB24 ||
7625 pix_fmt == AV_PIX_FMT_BGR24 ||
7626 pix_fmt == AV_PIX_FMT_PAL8 ||
7627 pix_fmt == AV_PIX_FMT_GRAY8 ||
7628 pix_fmt == AV_PIX_FMT_MONOWHITE ||
7629 pix_fmt == AV_PIX_FMT_MONOBLACK;
7630 }
7631 if (track->par->codec_id == AV_CODEC_ID_VP9 && track->mode != MODE_MP4) {
7632 av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id));
7633 return AVERROR(EINVAL);
7634 } else if (track->par->codec_id == AV_CODEC_ID_AV1 &&
7635 track->mode != MODE_MP4 && track->mode != MODE_AVIF) {
7636 av_log(s, AV_LOG_ERROR, "%s only supported in MP4 and AVIF.\n", avcodec_get_name(track->par->codec_id));
7637 return AVERROR(EINVAL);
7638 } else if (track->par->codec_id == AV_CODEC_ID_VP8) {
7639 /* altref frames handling is not defined in the spec as of version v1.0,
7640 * so just forbid muxing VP8 streams altogether until a new version does */
7641 av_log(s, AV_LOG_ERROR, "VP8 muxing is currently not supported.\n");
7642 return AVERROR_PATCHWELCOME;
7643 }
7644 if (is_cover_image(st)) {
7645 track->cover_image = av_packet_alloc();
7646 if (!track->cover_image)
7647 return AVERROR(ENOMEM);
7648 }
7649 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
7650 track->timescale = st->codecpar->sample_rate;
7651 if (!st->codecpar->frame_size && !av_get_bits_per_sample(st->codecpar->codec_id)) {
7652 av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i);
7653 track->audio_vbr = 1;
7654 }else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_MS ||
7655 st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
7656 st->codecpar->codec_id == AV_CODEC_ID_ILBC){
7657 if (!st->codecpar->block_align) {
7658 av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
7659 return AVERROR(EINVAL);
7660 }
7661 track->sample_size = st->codecpar->block_align;
7662 }else if (st->codecpar->frame_size > 1){ /* assume compressed audio */
7663 track->audio_vbr = 1;
7664 }else{
7665 track->sample_size = (av_get_bits_per_sample(st->codecpar->codec_id) >> 3) *
7666 st->codecpar->ch_layout.nb_channels;
7667 }
7668 if (st->codecpar->codec_id == AV_CODEC_ID_ILBC ||
7669 st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_QT) {
7670 track->audio_vbr = 1;
7671 }
7672 if (track->mode != MODE_MOV &&
7673 track->par->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) {
7674 if (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
7675 av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not standard, to mux anyway set strict to -1\n",
7676 i, track->par->sample_rate);
7677 return AVERROR(EINVAL);
7678 } else {
7679 av_log(s, AV_LOG_WARNING, "track %d: muxing mp3 at %dhz is not standard in MP4\n",
7680 i, track->par->sample_rate);
7681 }
7682 }
7683 if (track->par->codec_id == AV_CODEC_ID_FLAC ||
7684 track->par->codec_id == AV_CODEC_ID_TRUEHD ||
7685 track->par->codec_id == AV_CODEC_ID_OPUS) {
7686 if (track->mode != MODE_MP4) {
7687 av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id));
7688 return AVERROR(EINVAL);
7689 }
7690 if (track->par->codec_id != AV_CODEC_ID_OPUS &&
7691 s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
7692 av_log(s, AV_LOG_ERROR,
7693 "%s in MP4 support is experimental, add "
7694 "'-strict %d' if you want to use it.\n",
7695 avcodec_get_name(track->par->codec_id), FF_COMPLIANCE_EXPERIMENTAL);
7696 return AVERROR_EXPERIMENTAL;
7697 }
7698 }
7699 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
7700 track->timescale = st->time_base.den;
7701
7702 if (track->par->codec_id == AV_CODEC_ID_TTML) {
7703 /* 14496-30 requires us to use a single sample per fragment
7704 for TTML, for which we define a per-track flag.
7705
7706 We set the flag in case we are receiving TTML paragraphs
7707 from the input, in other words in case we are not doing
7708 stream copy. */
7709 track->squash_fragment_samples_to_one =
7710 ff_is_ttml_stream_paragraph_based(track->par);
7711
7712 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
7713 track->squash_fragment_samples_to_one) {
7714 av_log(s, AV_LOG_ERROR,
7715 "Fragmentation is not currently supported for "
7716 "TTML in MP4/ISMV (track synchronization between "
7717 "subtitles and other media is not yet implemented)!\n");
7718 return AVERROR_PATCHWELCOME;
7719 }
7720
7721 if (track->mode != MODE_ISM &&
7722 track->par->codec_tag == MOV_ISMV_TTML_TAG &&
7723 s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
7724 av_log(s, AV_LOG_ERROR,
7725 "ISMV style TTML support with the 'dfxp' tag in "
7726 "non-ISMV formats is not officially supported. Add "
7727 "'-strict unofficial' if you want to use it.\n");
7728 return AVERROR_EXPERIMENTAL;
7729 }
7730 }
7731 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
7732 track->timescale = st->time_base.den;
7733 #ifdef OHOS_TIMED_META_TRACK
7734 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_TIMEDMETA) {
7735 track->timescale = st->time_base.den;
7736 #endif
7737 } else {
7738 track->timescale = mov->movie_timescale;
7739 }
7740 if (!track->height)
7741 track->height = st->codecpar->height;
7742 /* The Protected Interoperable File Format (PIFF) standard, used by ISMV recommends but
7743 doesn't mandate a track timescale of 10,000,000. The muxer allows a custom timescale
7744 for video tracks, so if user-set, it isn't overwritten */
7745 if (mov->mode == MODE_ISM &&
7746 (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
7747 (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !mov->video_track_timescale))) {
7748 track->timescale = 10000000;
7749 }
7750
7751 avpriv_set_pts_info(st, 64, 1, track->timescale);
7752
7753 if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) {
7754 ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key,
7755 (track->par->codec_id == AV_CODEC_ID_H264 || track->par->codec_id == AV_CODEC_ID_HEVC),
7756 s->flags & AVFMT_FLAG_BITEXACT);
7757 if (ret)
7758 return ret;
7759 }
7760 }
7761
7762 enable_tracks(s);
7763 return 0;
7764 }
7765
7766 static int mov_write_header(AVFormatContext *s)
7767 {
7768 AVIOContext *pb = s->pb;
7769 MOVMuxContext *mov = s->priv_data;
7770 int i, ret, hint_track = 0, tmcd_track = 0, nb_tracks = s->nb_streams;
7771
7772 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
7773 nb_tracks++;
7774
7775 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
7776 hint_track = nb_tracks;
7777 for (i = 0; i < s->nb_streams; i++)
7778 if (rtp_hinting_needed(s->streams[i]))
7779 nb_tracks++;
7780 }
7781
7782 if (mov->nb_meta_tmcd)
7783 tmcd_track = nb_tracks;
7784
7785 for (i = 0; i < s->nb_streams; i++) {
7786 int j;
7787 AVStream *st= s->streams[i];
7788 MOVTrack *track= &mov->tracks[i];
7789
7790 /* copy extradata if it exists */
7791 if (st->codecpar->extradata_size) {
7792 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
7793 mov_create_dvd_sub_decoder_specific_info(track, st);
7794 else if (!TAG_IS_AVCI(track->tag) && st->codecpar->codec_id != AV_CODEC_ID_DNXHD) {
7795 track->vos_len = st->codecpar->extradata_size;
7796 track->vos_data = av_malloc(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
7797 if (!track->vos_data) {
7798 return AVERROR(ENOMEM);
7799 }
7800 memcpy(track->vos_data, st->codecpar->extradata, track->vos_len);
7801 memset(track->vos_data + track->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
7802 }
7803 }
7804
7805 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
7806 av_channel_layout_compare(&track->par->ch_layout,
7807 &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO))
7808 continue;
7809
7810 for (j = 0; j < s->nb_streams; j++) {
7811 AVStream *stj= s->streams[j];
7812 MOVTrack *trackj= &mov->tracks[j];
7813 if (j == i)
7814 continue;
7815
7816 if (stj->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
7817 (trackj->par->ch_layout.nb_channels != 1 ||
7818 !av_channel_layout_compare(&trackj->par->ch_layout,
7819 &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO))
7820 )
7821 track->mono_as_fc = -1;
7822
7823 if (stj->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
7824 av_channel_layout_compare(&trackj->par->ch_layout,
7825 &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO) &&
7826 trackj->par->ch_layout.nb_channels == 1 && track->mono_as_fc >= 0
7827 )
7828 track->mono_as_fc++;
7829
7830 if (stj->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
7831 av_channel_layout_compare(&trackj->par->ch_layout,
7832 &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO) ||
7833 trackj->language != track->language ||
7834 trackj->tag != track->tag
7835 )
7836 continue;
7837 track->multichannel_as_mono++;
7838 }
7839 }
7840
7841 if (!(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
7842 if ((ret = mov_write_identification(pb, s)) < 0)
7843 return ret;
7844 }
7845
7846 if (mov->reserved_moov_size){
7847 mov->reserved_header_pos = avio_tell(pb);
7848 if (mov->reserved_moov_size > 0)
7849 avio_skip(pb, mov->reserved_moov_size);
7850 }
7851
7852 if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
7853 /* If no fragmentation options have been set, set a default. */
7854 if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME |
7855 FF_MOV_FLAG_FRAG_CUSTOM |
7856 FF_MOV_FLAG_FRAG_EVERY_FRAME)) &&
7857 !mov->max_fragment_duration && !mov->max_fragment_size)
7858 mov->flags |= FF_MOV_FLAG_FRAG_KEYFRAME;
7859 } else if (mov->mode != MODE_AVIF) {
7860 if (mov->flags & FF_MOV_FLAG_FASTSTART)
7861 mov->reserved_header_pos = avio_tell(pb);
7862 mov_write_mdat_tag(pb, mov);
7863 }
7864
7865 ff_parse_creation_time_metadata(s, &mov->time, 1);
7866 if (mov->time)
7867 mov->time += 0x7C25B080; // 1970 based -> 1904 based
7868
7869 if (mov->chapter_track)
7870 if ((ret = mov_create_chapter_track(s, mov->chapter_track)) < 0)
7871 return ret;
7872
7873 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
7874 for (i = 0; i < s->nb_streams; i++) {
7875 if (rtp_hinting_needed(s->streams[i])) {
7876 if ((ret = ff_mov_init_hinting(s, hint_track, i)) < 0)
7877 return ret;
7878 hint_track++;
7879 }
7880 }
7881 }
7882
7883 if (mov->nb_meta_tmcd) {
7884 const AVDictionaryEntry *t, *global_tcr = av_dict_get(s->metadata,
7885 "timecode", NULL, 0);
7886 /* Initialize the tmcd tracks */
7887 for (i = 0; i < s->nb_streams; i++) {
7888 AVStream *st = s->streams[i];
7889 t = global_tcr;
7890
7891 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
7892 AVTimecode tc;
7893 if (!t)
7894 t = av_dict_get(st->metadata, "timecode", NULL, 0);
7895 if (!t)
7896 continue;
7897 if (mov_check_timecode_track(s, &tc, i, t->value) < 0)
7898 continue;
7899 if ((ret = mov_create_timecode_track(s, tmcd_track, i, tc)) < 0)
7900 return ret;
7901 tmcd_track++;
7902 }
7903 }
7904 }
7905 #ifdef OHOS_TIMED_META_TRACK
7906 if (mov->flags & FF_MOV_FLAG_TIMED_METADATA) {
7907 for (i = 0; i < s->nb_streams; i++) {
7908 AVStream *st = s->streams[i];
7909 if (st->codecpar->codec_type == AVMEDIA_TYPE_TIMEDMETA) {
7910 const AVDictionaryEntry *t = av_dict_get(st->metadata, "src_track_id", NULL, 0);
7911 if (!t)
7912 continue;
7913 size_t id_len = strlen(t->value);
7914 int track_id = 0;
7915 const int base = 10;
7916 const char start = '0';
7917 for (int j = 0; j < id_len; j++)
7918 track_id = track_id * base + t->value[j] - start;
7919 if ((ret = mov_create_timed_metadata_track(s, i, track_id)) < 0)
7920 return ret;
7921 }
7922 }
7923 }
7924 #endif
7925
7926 avio_flush(pb);
7927
7928 if (mov->flags & FF_MOV_FLAG_ISML)
7929 mov_write_isml_manifest(pb, mov, s);
7930
7931 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
7932 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
7933 if ((ret = mov_write_moov_tag(pb, mov, s)) < 0)
7934 return ret;
7935 mov->moov_written = 1;
7936 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
7937 mov->reserved_header_pos = avio_tell(pb);
7938 }
7939
7940 return 0;
7941 }
7942
7943 static int get_moov_size(AVFormatContext *s)
7944 {
7945 int ret;
7946 AVIOContext *moov_buf;
7947 MOVMuxContext *mov = s->priv_data;
7948
7949 if ((ret = ffio_open_null_buf(&moov_buf)) < 0)
7950 return ret;
7951 if ((ret = mov_write_moov_tag(moov_buf, mov, s)) < 0)
7952 return ret;
7953 return ffio_close_null_buf(moov_buf);
7954 }
7955
7956 static int get_sidx_size(AVFormatContext *s)
7957 {
7958 int ret;
7959 AVIOContext *buf;
7960 MOVMuxContext *mov = s->priv_data;
7961
7962 if ((ret = ffio_open_null_buf(&buf)) < 0)
7963 return ret;
7964 mov_write_sidx_tags(buf, mov, -1, 0);
7965 return ffio_close_null_buf(buf);
7966 }
7967
7968 /*
7969 * This function gets the moov size if moved to the top of the file: the chunk
7970 * offset table can switch between stco (32-bit entries) to co64 (64-bit
7971 * entries) when the moov is moved to the beginning, so the size of the moov
7972 * would change. It also updates the chunk offset tables.
7973 */
7974 static int compute_moov_size(AVFormatContext *s)
7975 {
7976 int i, moov_size, moov_size2;
7977 MOVMuxContext *mov = s->priv_data;
7978
7979 moov_size = get_moov_size(s);
7980 if (moov_size < 0)
7981 return moov_size;
7982
7983 for (i = 0; i < mov->nb_streams; i++)
7984 mov->tracks[i].data_offset += moov_size;
7985
7986 moov_size2 = get_moov_size(s);
7987 if (moov_size2 < 0)
7988 return moov_size2;
7989
7990 /* if the size changed, we just switched from stco to co64 and need to
7991 * update the offsets */
7992 if (moov_size2 != moov_size)
7993 for (i = 0; i < mov->nb_streams; i++)
7994 mov->tracks[i].data_offset += moov_size2 - moov_size;
7995
7996 return moov_size2;
7997 }
7998
7999 static int compute_sidx_size(AVFormatContext *s)
8000 {
8001 int i, sidx_size;
8002 MOVMuxContext *mov = s->priv_data;
8003
8004 sidx_size = get_sidx_size(s);
8005 if (sidx_size < 0)
8006 return sidx_size;
8007
8008 for (i = 0; i < mov->nb_streams; i++)
8009 mov->tracks[i].data_offset += sidx_size;
8010
8011 return sidx_size;
8012 }
8013
8014 static int shift_data(AVFormatContext *s)
8015 {
8016 int moov_size;
8017 MOVMuxContext *mov = s->priv_data;
8018
8019 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
8020 moov_size = compute_sidx_size(s);
8021 else
8022 moov_size = compute_moov_size(s);
8023 if (moov_size < 0)
8024 return moov_size;
8025
8026 return ff_format_shift_data(s, mov->reserved_header_pos, moov_size);
8027 }
8028
8029 static int mov_write_trailer(AVFormatContext *s)
8030 {
8031 MOVMuxContext *mov = s->priv_data;
8032 AVIOContext *pb = s->pb;
8033 int res = 0;
8034 int i;
8035 int64_t moov_pos;
8036
8037 if (mov->need_rewrite_extradata) {
8038 for (i = 0; i < s->nb_streams; i++) {
8039 MOVTrack *track = &mov->tracks[i];
8040 AVCodecParameters *par = track->par;
8041
8042 track->vos_len = par->extradata_size;
8043 av_freep(&track->vos_data);
8044 track->vos_data = av_malloc(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
8045 if (!track->vos_data)
8046 return AVERROR(ENOMEM);
8047 memcpy(track->vos_data, par->extradata, track->vos_len);
8048 memset(track->vos_data + track->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8049 }
8050 mov->need_rewrite_extradata = 0;
8051 }
8052
8053 /*
8054 * Before actually writing the trailer, make sure that there are no
8055 * dangling subtitles, that need a terminating sample.
8056 */
8057 for (i = 0; i < mov->nb_streams; i++) {
8058 MOVTrack *trk = &mov->tracks[i];
8059 if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
8060 !trk->last_sample_is_subtitle_end) {
8061 mov_write_subtitle_end_packet(s, i, trk->track_duration);
8062 trk->last_sample_is_subtitle_end = 1;
8063 }
8064 }
8065
8066 // Check if we have any tracks that require squashing.
8067 // In that case, we'll have to write the packet here.
8068 if ((res = mov_write_squashed_packets(s)) < 0)
8069 return res;
8070
8071 // If there were no chapters when the header was written, but there
8072 // are chapters now, write them in the trailer. This only works
8073 // when we are not doing fragments.
8074 if (!mov->chapter_track && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
8075 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) {
8076 mov->chapter_track = mov->nb_streams++;
8077 if ((res = mov_create_chapter_track(s, mov->chapter_track)) < 0)
8078 return res;
8079 }
8080 }
8081
8082 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
8083 moov_pos = avio_tell(pb);
8084
8085 /* Write size of mdat tag */
8086 if (mov->mdat_size + 8 <= UINT32_MAX) {
8087 avio_seek(pb, mov->mdat_pos, SEEK_SET);
8088 avio_wb32(pb, mov->mdat_size + 8);
8089 } else {
8090 /* overwrite 'wide' placeholder atom */
8091 avio_seek(pb, mov->mdat_pos - 8, SEEK_SET);
8092 /* special value: real atom size will be 64 bit value after
8093 * tag field */
8094 avio_wb32(pb, 1);
8095 ffio_wfourcc(pb, "mdat");
8096 avio_wb64(pb, mov->mdat_size + 16);
8097 }
8098 avio_seek(pb, mov->reserved_moov_size > 0 ? mov->reserved_header_pos : moov_pos, SEEK_SET);
8099
8100 if (mov->flags & FF_MOV_FLAG_FASTSTART) {
8101 av_log(s, AV_LOG_INFO, "Starting second pass: moving the moov atom to the beginning of the file\n");
8102 res = shift_data(s);
8103 if (res < 0)
8104 return res;
8105 avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
8106 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
8107 return res;
8108 } else if (mov->reserved_moov_size > 0) {
8109 int64_t size;
8110 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
8111 return res;
8112 size = mov->reserved_moov_size - (avio_tell(pb) - mov->reserved_header_pos);
8113 if (size < 8){
8114 av_log(s, AV_LOG_ERROR, "reserved_moov_size is too small, needed %"PRId64" additional\n", 8-size);
8115 return AVERROR(EINVAL);
8116 }
8117 avio_wb32(pb, size);
8118 ffio_wfourcc(pb, "free");
8119 ffio_fill(pb, 0, size - 8);
8120 avio_seek(pb, moov_pos, SEEK_SET);
8121 } else {
8122 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
8123 return res;
8124 }
8125 res = 0;
8126 } else {
8127 mov_auto_flush_fragment(s, 1);
8128 for (i = 0; i < mov->nb_streams; i++)
8129 mov->tracks[i].data_offset = 0;
8130 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) {
8131 int64_t end;
8132 av_log(s, AV_LOG_INFO, "Starting second pass: inserting sidx atoms\n");
8133 res = shift_data(s);
8134 if (res < 0)
8135 return res;
8136 end = avio_tell(pb);
8137 avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
8138 mov_write_sidx_tags(pb, mov, -1, 0);
8139 avio_seek(pb, end, SEEK_SET);
8140 }
8141 if (!(mov->flags & FF_MOV_FLAG_SKIP_TRAILER)) {
8142 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
8143 res = mov_write_mfra_tag(pb, mov);
8144 if (res < 0)
8145 return res;
8146 }
8147 }
8148
8149 return res;
8150 }
8151
8152 static int mov_check_bitstream(AVFormatContext *s, AVStream *st,
8153 const AVPacket *pkt)
8154 {
8155 int ret = 1;
8156
8157 if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
8158 if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0)
8159 ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
8160 } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) {
8161 ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
8162 }
8163
8164 return ret;
8165 }
8166
8167 static int avif_write_trailer(AVFormatContext *s)
8168 {
8169 AVIOContext *pb = s->pb;
8170 MOVMuxContext *mov = s->priv_data;
8171 int64_t pos_backup, extent_offsets[2];
8172 uint8_t *buf;
8173 int buf_size, moov_size, i;
8174
8175 if (mov->moov_written) return 0;
8176
8177 mov->is_animated_avif = s->streams[0]->nb_frames > 1;
8178 if (mov->is_animated_avif && s->nb_streams > 1) {
8179 // For animated avif with alpha channel, we need to write a tref tag
8180 // with type "auxl".
8181 mov->tracks[1].tref_tag = MKTAG('a', 'u', 'x', 'l');
8182 #ifdef OHOS_TIMED_META_TRACK
8183 mov->tracks[1].tref_ids[0] = 1;
8184 #else
8185 mov->tracks[1].tref_id = 1;
8186 #endif
8187 }
8188 mov_write_identification(pb, s);
8189 mov_write_meta_tag(pb, mov, s);
8190
8191 moov_size = get_moov_size(s);
8192 for (i = 0; i < s->nb_streams; i++)
8193 mov->tracks[i].data_offset = avio_tell(pb) + moov_size + 8;
8194
8195 if (mov->is_animated_avif) {
8196 int ret;
8197 if ((ret = mov_write_moov_tag(pb, mov, s)) < 0)
8198 return ret;
8199 }
8200
8201 buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
8202 avio_wb32(pb, buf_size + 8);
8203 ffio_wfourcc(pb, "mdat");
8204
8205 // The offset for the YUV planes is the starting position of mdat.
8206 extent_offsets[0] = avio_tell(pb);
8207 // The offset for alpha plane is YUV offset + YUV size.
8208 extent_offsets[1] = extent_offsets[0] + mov->avif_extent_length[0];
8209
8210 avio_write(pb, buf, buf_size);
8211
8212 // write extent offsets.
8213 pos_backup = avio_tell(pb);
8214 for (i = 0; i < s->nb_streams; i++) {
8215 if (extent_offsets[i] != (uint32_t)extent_offsets[i]) {
8216 av_log(s, AV_LOG_ERROR, "extent offset does not fit in 32 bits\n");
8217 return AVERROR_INVALIDDATA;
8218 }
8219 avio_seek(pb, mov->avif_extent_pos[i], SEEK_SET);
8220 avio_wb32(pb, extent_offsets[i]); /* rewrite offset */
8221 }
8222 avio_seek(pb, pos_backup, SEEK_SET);
8223
8224 return 0;
8225 }
8226
8227 #if CONFIG_TGP_MUXER || CONFIG_TG2_MUXER
8228 static const AVCodecTag codec_3gp_tags[] = {
8229 { AV_CODEC_ID_H263, MKTAG('s','2','6','3') },
8230 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
8231 { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
8232 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
8233 { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') },
8234 { AV_CODEC_ID_AMR_WB, MKTAG('s','a','w','b') },
8235 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
8236 { AV_CODEC_ID_NONE, 0 },
8237 };
8238 static const AVCodecTag *const codec_3gp_tags_list[] = { codec_3gp_tags, NULL };
8239 #endif
8240
8241 static const AVCodecTag codec_mp4_tags[] = {
8242 { AV_CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
8243 { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') },
8244 { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '3') },
8245 { AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') },
8246 { AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') },
8247 { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', '4', 'v') },
8248 { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', '4', 'v') },
8249 { AV_CODEC_ID_MJPEG, MKTAG('m', 'p', '4', 'v') },
8250 { AV_CODEC_ID_PNG, MKTAG('m', 'p', '4', 'v') },
8251 { AV_CODEC_ID_JPEG2000, MKTAG('m', 'p', '4', 'v') },
8252 { AV_CODEC_ID_VC1, MKTAG('v', 'c', '-', '1') },
8253 { AV_CODEC_ID_DIRAC, MKTAG('d', 'r', 'a', 'c') },
8254 { AV_CODEC_ID_TSCC2, MKTAG('m', 'p', '4', 'v') },
8255 { AV_CODEC_ID_VP9, MKTAG('v', 'p', '0', '9') },
8256 { AV_CODEC_ID_AV1, MKTAG('a', 'v', '0', '1') },
8257 { AV_CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') },
8258 { AV_CODEC_ID_ALAC, MKTAG('a', 'l', 'a', 'c') },
8259 { AV_CODEC_ID_MP4ALS, MKTAG('m', 'p', '4', 'a') },
8260 { AV_CODEC_ID_MP3, MKTAG('m', 'p', '4', 'a') },
8261 { AV_CODEC_ID_MP2, MKTAG('m', 'p', '4', 'a') },
8262 { AV_CODEC_ID_AC3, MKTAG('a', 'c', '-', '3') },
8263 { AV_CODEC_ID_EAC3, MKTAG('e', 'c', '-', '3') },
8264 { AV_CODEC_ID_DTS, MKTAG('m', 'p', '4', 'a') },
8265 { AV_CODEC_ID_TRUEHD, MKTAG('m', 'l', 'p', 'a') },
8266 { AV_CODEC_ID_FLAC, MKTAG('f', 'L', 'a', 'C') },
8267 { AV_CODEC_ID_OPUS, MKTAG('O', 'p', 'u', 's') },
8268 { AV_CODEC_ID_VORBIS, MKTAG('m', 'p', '4', 'a') },
8269 { AV_CODEC_ID_QCELP, MKTAG('m', 'p', '4', 'a') },
8270 { AV_CODEC_ID_EVRC, MKTAG('m', 'p', '4', 'a') },
8271 { AV_CODEC_ID_DVD_SUBTITLE, MKTAG('m', 'p', '4', 's') },
8272 { AV_CODEC_ID_MOV_TEXT, MKTAG('t', 'x', '3', 'g') },
8273 { AV_CODEC_ID_BIN_DATA, MKTAG('g', 'p', 'm', 'd') },
8274 { AV_CODEC_ID_MPEGH_3D_AUDIO, MKTAG('m', 'h', 'm', '1') },
8275 { AV_CODEC_ID_TTML, MOV_MP4_TTML_TAG },
8276 { AV_CODEC_ID_TTML, MOV_ISMV_TTML_TAG },
8277 #ifdef OHOS_TIMED_META_TRACK
8278 { AV_CODEC_ID_FFMETADATA, MKTAG('c', 'd', 's', 'c') },
8279 #endif
8280 { AV_CODEC_ID_NONE, 0 },
8281 };
8282 #if CONFIG_MP4_MUXER || CONFIG_PSP_MUXER
8283 static const AVCodecTag *const mp4_codec_tags_list[] = { codec_mp4_tags, NULL };
8284 #endif
8285
8286 static const AVCodecTag codec_ism_tags[] = {
8287 { AV_CODEC_ID_WMAPRO , MKTAG('w', 'm', 'a', ' ') },
8288 { AV_CODEC_ID_TTML , MOV_ISMV_TTML_TAG },
8289 { AV_CODEC_ID_NONE , 0 },
8290 };
8291
8292 static const AVCodecTag codec_ipod_tags[] = {
8293 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
8294 { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
8295 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
8296 { AV_CODEC_ID_ALAC, MKTAG('a','l','a','c') },
8297 { AV_CODEC_ID_AC3, MKTAG('a','c','-','3') },
8298 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
8299 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') },
8300 { AV_CODEC_ID_NONE, 0 },
8301 };
8302
8303 static const AVCodecTag codec_f4v_tags[] = {
8304 { AV_CODEC_ID_MP3, MKTAG('.','m','p','3') },
8305 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
8306 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
8307 { AV_CODEC_ID_VP6A, MKTAG('V','P','6','A') },
8308 { AV_CODEC_ID_VP6F, MKTAG('V','P','6','F') },
8309 { AV_CODEC_ID_NONE, 0 },
8310 };
8311
8312 #if CONFIG_AVIF_MUXER
8313 static const AVCodecTag codec_avif_tags[] = {
8314 { AV_CODEC_ID_AV1, MKTAG('a','v','0','1') },
8315 { AV_CODEC_ID_NONE, 0 },
8316 };
8317 static const AVCodecTag *const codec_avif_tags_list[] = { codec_avif_tags, NULL };
8318
8319 static const AVClass mov_avif_muxer_class = {
8320 .class_name = "avif muxer",
8321 .item_name = av_default_item_name,
8322 .version = LIBAVUTIL_VERSION_INT,
8323 };
8324 #endif
8325
8326 #if CONFIG_MOV_MUXER
8327 const AVOutputFormat ff_mov_muxer = {
8328 .name = "mov",
8329 .long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
8330 .extensions = "mov",
8331 .priv_data_size = sizeof(MOVMuxContext),
8332 .audio_codec = AV_CODEC_ID_AAC,
8333 .video_codec = CONFIG_LIBX264_ENCODER ?
8334 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
8335 .init = mov_init,
8336 .write_header = mov_write_header,
8337 .write_packet = mov_write_packet,
8338 .write_trailer = mov_write_trailer,
8339 .deinit = mov_free,
8340 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8341 .codec_tag = (const AVCodecTag* const []){
8342 ff_codec_movvideo_tags, ff_codec_movaudio_tags, ff_codec_movsubtitle_tags, 0
8343 },
8344 .check_bitstream = mov_check_bitstream,
8345 .priv_class = &mov_isobmff_muxer_class,
8346 };
8347 #endif
8348 #if CONFIG_TGP_MUXER
8349 const AVOutputFormat ff_tgp_muxer = {
8350 .name = "3gp",
8351 .long_name = NULL_IF_CONFIG_SMALL("3GP (3GPP file format)"),
8352 .extensions = "3gp",
8353 .priv_data_size = sizeof(MOVMuxContext),
8354 .audio_codec = AV_CODEC_ID_AMR_NB,
8355 .video_codec = AV_CODEC_ID_H263,
8356 .init = mov_init,
8357 .write_header = mov_write_header,
8358 .write_packet = mov_write_packet,
8359 .write_trailer = mov_write_trailer,
8360 .deinit = mov_free,
8361 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8362 .codec_tag = codec_3gp_tags_list,
8363 .check_bitstream = mov_check_bitstream,
8364 .priv_class = &mov_isobmff_muxer_class,
8365 };
8366 #endif
8367 #if CONFIG_MP4_MUXER
8368 const AVOutputFormat ff_mp4_muxer = {
8369 .name = "mp4",
8370 .long_name = NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"),
8371 .mime_type = "video/mp4",
8372 .extensions = "mp4",
8373 .priv_data_size = sizeof(MOVMuxContext),
8374 .audio_codec = AV_CODEC_ID_AAC,
8375 .video_codec = CONFIG_LIBX264_ENCODER ?
8376 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
8377 .init = mov_init,
8378 .write_header = mov_write_header,
8379 .write_packet = mov_write_packet,
8380 .write_trailer = mov_write_trailer,
8381 .deinit = mov_free,
8382 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8383 .codec_tag = mp4_codec_tags_list,
8384 .check_bitstream = mov_check_bitstream,
8385 .priv_class = &mov_isobmff_muxer_class,
8386 };
8387 #endif
8388 #if CONFIG_PSP_MUXER
8389 const AVOutputFormat ff_psp_muxer = {
8390 .name = "psp",
8391 .long_name = NULL_IF_CONFIG_SMALL("PSP MP4 (MPEG-4 Part 14)"),
8392 .extensions = "mp4,psp",
8393 .priv_data_size = sizeof(MOVMuxContext),
8394 .audio_codec = AV_CODEC_ID_AAC,
8395 .video_codec = CONFIG_LIBX264_ENCODER ?
8396 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
8397 .init = mov_init,
8398 .write_header = mov_write_header,
8399 .write_packet = mov_write_packet,
8400 .write_trailer = mov_write_trailer,
8401 .deinit = mov_free,
8402 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8403 .codec_tag = mp4_codec_tags_list,
8404 .check_bitstream = mov_check_bitstream,
8405 .priv_class = &mov_isobmff_muxer_class,
8406 };
8407 #endif
8408 #if CONFIG_TG2_MUXER
8409 const AVOutputFormat ff_tg2_muxer = {
8410 .name = "3g2",
8411 .long_name = NULL_IF_CONFIG_SMALL("3GP2 (3GPP2 file format)"),
8412 .extensions = "3g2",
8413 .priv_data_size = sizeof(MOVMuxContext),
8414 .audio_codec = AV_CODEC_ID_AMR_NB,
8415 .video_codec = AV_CODEC_ID_H263,
8416 .init = mov_init,
8417 .write_header = mov_write_header,
8418 .write_packet = mov_write_packet,
8419 .write_trailer = mov_write_trailer,
8420 .deinit = mov_free,
8421 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8422 .codec_tag = codec_3gp_tags_list,
8423 .check_bitstream = mov_check_bitstream,
8424 .priv_class = &mov_isobmff_muxer_class,
8425 };
8426 #endif
8427 #if CONFIG_IPOD_MUXER
8428 const AVOutputFormat ff_ipod_muxer = {
8429 .name = "ipod",
8430 .long_name = NULL_IF_CONFIG_SMALL("iPod H.264 MP4 (MPEG-4 Part 14)"),
8431 .mime_type = "video/mp4",
8432 .extensions = "m4v,m4a,m4b",
8433 .priv_data_size = sizeof(MOVMuxContext),
8434 .audio_codec = AV_CODEC_ID_AAC,
8435 .video_codec = AV_CODEC_ID_H264,
8436 .init = mov_init,
8437 .write_header = mov_write_header,
8438 .write_packet = mov_write_packet,
8439 .write_trailer = mov_write_trailer,
8440 .deinit = mov_free,
8441 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8442 .codec_tag = (const AVCodecTag* const []){ codec_ipod_tags, 0 },
8443 .check_bitstream = mov_check_bitstream,
8444 .priv_class = &mov_isobmff_muxer_class,
8445 };
8446 #endif
8447 #if CONFIG_ISMV_MUXER
8448 const AVOutputFormat ff_ismv_muxer = {
8449 .name = "ismv",
8450 .long_name = NULL_IF_CONFIG_SMALL("ISMV/ISMA (Smooth Streaming)"),
8451 .mime_type = "video/mp4",
8452 .extensions = "ismv,isma",
8453 .priv_data_size = sizeof(MOVMuxContext),
8454 .audio_codec = AV_CODEC_ID_AAC,
8455 .video_codec = AV_CODEC_ID_H264,
8456 .init = mov_init,
8457 .write_header = mov_write_header,
8458 .write_packet = mov_write_packet,
8459 .write_trailer = mov_write_trailer,
8460 .deinit = mov_free,
8461 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8462 .codec_tag = (const AVCodecTag* const []){
8463 codec_mp4_tags, codec_ism_tags, 0 },
8464 .check_bitstream = mov_check_bitstream,
8465 .priv_class = &mov_isobmff_muxer_class,
8466 };
8467 #endif
8468 #if CONFIG_F4V_MUXER
8469 const AVOutputFormat ff_f4v_muxer = {
8470 .name = "f4v",
8471 .long_name = NULL_IF_CONFIG_SMALL("F4V Adobe Flash Video"),
8472 .mime_type = "application/f4v",
8473 .extensions = "f4v",
8474 .priv_data_size = sizeof(MOVMuxContext),
8475 .audio_codec = AV_CODEC_ID_AAC,
8476 .video_codec = AV_CODEC_ID_H264,
8477 .init = mov_init,
8478 .write_header = mov_write_header,
8479 .write_packet = mov_write_packet,
8480 .write_trailer = mov_write_trailer,
8481 .deinit = mov_free,
8482 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
8483 .codec_tag = (const AVCodecTag* const []){ codec_f4v_tags, 0 },
8484 .check_bitstream = mov_check_bitstream,
8485 .priv_class = &mov_isobmff_muxer_class,
8486 };
8487 #endif
8488 #if CONFIG_AVIF_MUXER
8489 const AVOutputFormat ff_avif_muxer = {
8490 .name = "avif",
8491 .long_name = NULL_IF_CONFIG_SMALL("AVIF"),
8492 .mime_type = "image/avif",
8493 .extensions = "avif",
8494 .priv_data_size = sizeof(MOVMuxContext),
8495 .video_codec = AV_CODEC_ID_AV1,
8496 .init = mov_init,
8497 .write_header = mov_write_header,
8498 .write_packet = mov_write_packet,
8499 .write_trailer = avif_write_trailer,
8500 .deinit = mov_free,
8501 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
8502 .codec_tag = codec_avif_tags_list,
8503 .priv_class = &mov_avif_muxer_class,
8504 };
8505 #endif
8506