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 < (int)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 int data_len = (int)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 #ifdef OHOS_OPT_COMPAT
4975 av_log(NULL, AV_LOG_ERROR, "Failed to write track %d.\n", i);
4976 #endif
4977 return ret;
4978 }
4979 #ifdef OHOS_OPT_COMPAT
4980 av_log(NULL, AV_LOG_INFO, "Wrote track %d successfully.\n", i);
4981 #endif
4982 }
4983 }
4984 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
4985 mov_write_mvex_tag(pb, mov); /* QuickTime requires trak to precede this */
4986
4987 if (mov->mode == MODE_PSP)
4988 mov_write_uuidusmt_tag(pb, s);
4989 else if (mov->mode != MODE_AVIF)
4990 mov_write_udta_tag(pb, mov, s);
4991
4992 #ifdef OHOS_MOOV_LEVEL_META
4993 if (av_dict_get(s->metadata, "moov_level_meta_flag", NULL, 0)) {
4994 mov_write_gnre_tag(pb, mov, s);
4995 mov_write_moov_level_meta_tag(pb, mov, s);
4996 }
4997 #endif
4998
4999 return update_size(pb, pos);
5000 }
5001
5002 static void param_write_int(AVIOContext *pb, const char *name, int value)
5003 {
5004 avio_printf(pb, "<param name=\"%s\" value=\"%d\" valuetype=\"data\"/>\n", name, value);
5005 }
5006
5007 static void param_write_string(AVIOContext *pb, const char *name, const char *value)
5008 {
5009 avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, value);
5010 }
5011
5012 static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *value, int len)
5013 {
5014 char buf[150];
5015 len = FFMIN(sizeof(buf) / 2 - 1, len);
5016 ff_data_to_hex(buf, value, len, 0);
5017 avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, buf);
5018 }
5019
5020 static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
5021 {
5022 int64_t pos = avio_tell(pb);
5023 int i;
5024
5025 static const AVUUID uuid = {
5026 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
5027 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
5028 };
5029
5030 avio_wb32(pb, 0);
5031 ffio_wfourcc(pb, "uuid");
5032 avio_write(pb, uuid, AV_UUID_LEN);
5033 avio_wb32(pb, 0);
5034
5035 avio_printf(pb, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
5036 avio_printf(pb, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
5037 avio_printf(pb, "<head>\n");
5038 if (!(mov->fc->flags & AVFMT_FLAG_BITEXACT))
5039 avio_printf(pb, "<meta name=\"creator\" content=\"%s\" />\n",
5040 LIBAVFORMAT_IDENT);
5041 avio_printf(pb, "</head>\n");
5042 avio_printf(pb, "<body>\n");
5043 avio_printf(pb, "<switch>\n");
5044
5045 mov_setup_track_ids(mov, s);
5046
5047 for (i = 0; i < mov->nb_streams; i++) {
5048 MOVTrack *track = &mov->tracks[i];
5049 struct mpeg4_bit_rate_values bit_rates =
5050 calculate_mpeg4_bit_rates(track);
5051 const char *type;
5052 int track_id = track->track_id;
5053 char track_name_buf[32] = { 0 };
5054
5055 AVStream *st = track->st;
5056 AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
5057
5058 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && !is_cover_image(st)) {
5059 type = "video";
5060 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
5061 type = "audio";
5062 } else {
5063 continue;
5064 }
5065
5066 avio_printf(pb, "<%s systemBitrate=\"%"PRIu32"\">\n", type,
5067 bit_rates.avg_bit_rate);
5068 param_write_int(pb, "systemBitrate", bit_rates.avg_bit_rate);
5069 param_write_int(pb, "trackID", track_id);
5070 param_write_string(pb, "systemLanguage", lang ? lang->value : "und");
5071
5072 /* Build track name piece by piece: */
5073 /* 1. track type */
5074 av_strlcat(track_name_buf, type, sizeof(track_name_buf));
5075 /* 2. track language, if available */
5076 if (lang)
5077 av_strlcatf(track_name_buf, sizeof(track_name_buf),
5078 "_%s", lang->value);
5079 /* 3. special type suffix */
5080 /* "_cc" = closed captions, "_ad" = audio_description */
5081 if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
5082 av_strlcat(track_name_buf, "_cc", sizeof(track_name_buf));
5083 else if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
5084 av_strlcat(track_name_buf, "_ad", sizeof(track_name_buf));
5085
5086 param_write_string(pb, "trackName", track_name_buf);
5087
5088 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
5089 if (track->par->codec_id == AV_CODEC_ID_H264) {
5090 uint8_t *ptr;
5091 int size = track->par->extradata_size;
5092 if (!ff_avc_write_annexb_extradata(track->par->extradata, &ptr,
5093 &size)) {
5094 param_write_hex(pb, "CodecPrivateData",
5095 ptr ? ptr : track->par->extradata,
5096 size);
5097 av_free(ptr);
5098 }
5099 param_write_string(pb, "FourCC", "H264");
5100 } else if (track->par->codec_id == AV_CODEC_ID_VC1) {
5101 param_write_string(pb, "FourCC", "WVC1");
5102 param_write_hex(pb, "CodecPrivateData", track->par->extradata,
5103 track->par->extradata_size);
5104 }
5105 param_write_int(pb, "MaxWidth", track->par->width);
5106 param_write_int(pb, "MaxHeight", track->par->height);
5107 param_write_int(pb, "DisplayWidth", track->par->width);
5108 param_write_int(pb, "DisplayHeight", track->par->height);
5109 } else {
5110 if (track->par->codec_id == AV_CODEC_ID_AAC) {
5111 switch (track->par->profile)
5112 {
5113 case FF_PROFILE_AAC_HE_V2:
5114 param_write_string(pb, "FourCC", "AACP");
5115 break;
5116 case FF_PROFILE_AAC_HE:
5117 param_write_string(pb, "FourCC", "AACH");
5118 break;
5119 default:
5120 param_write_string(pb, "FourCC", "AACL");
5121 }
5122 } else if (track->par->codec_id == AV_CODEC_ID_WMAPRO) {
5123 param_write_string(pb, "FourCC", "WMAP");
5124 }
5125 param_write_hex(pb, "CodecPrivateData", track->par->extradata,
5126 track->par->extradata_size);
5127 param_write_int(pb, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags,
5128 track->par->codec_id));
5129 param_write_int(pb, "Channels", track->par->ch_layout.nb_channels);
5130 param_write_int(pb, "SamplingRate", track->par->sample_rate);
5131 param_write_int(pb, "BitsPerSample", 16);
5132 param_write_int(pb, "PacketSize", track->par->block_align ?
5133 track->par->block_align : 4);
5134 }
5135 avio_printf(pb, "</%s>\n", type);
5136 }
5137 avio_printf(pb, "</switch>\n");
5138 avio_printf(pb, "</body>\n");
5139 avio_printf(pb, "</smil>\n");
5140
5141 return update_size(pb, pos);
5142 }
5143
5144 static int mov_write_mfhd_tag(AVIOContext *pb, MOVMuxContext *mov)
5145 {
5146 avio_wb32(pb, 16);
5147 ffio_wfourcc(pb, "mfhd");
5148 avio_wb32(pb, 0);
5149 avio_wb32(pb, mov->fragments);
5150 return 0;
5151 }
5152
5153 static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry)
5154 {
5155 return entry->flags & MOV_SYNC_SAMPLE ? MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO :
5156 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC);
5157 }
5158
5159 static int mov_write_tfhd_tag(AVIOContext *pb, MOVMuxContext *mov,
5160 MOVTrack *track, int64_t moof_offset)
5161 {
5162 int64_t pos = avio_tell(pb);
5163 uint32_t flags = MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION |
5164 MOV_TFHD_BASE_DATA_OFFSET;
5165 if (!track->entry) {
5166 flags |= MOV_TFHD_DURATION_IS_EMPTY;
5167 } else {
5168 flags |= MOV_TFHD_DEFAULT_FLAGS;
5169 }
5170 if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET)
5171 flags &= ~MOV_TFHD_BASE_DATA_OFFSET;
5172 if (mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) {
5173 flags &= ~MOV_TFHD_BASE_DATA_OFFSET;
5174 flags |= MOV_TFHD_DEFAULT_BASE_IS_MOOF;
5175 }
5176 /* CMAF requires all values to be explicit in tfhd atoms */
5177 if (mov->flags & FF_MOV_FLAG_CMAF)
5178 flags |= MOV_TFHD_STSD_ID;
5179
5180 /* Don't set a default sample size, the silverlight player refuses
5181 * to play files with that set. Don't set a default sample duration,
5182 * WMP freaks out if it is set. Don't set a base data offset, PIFF
5183 * file format says it MUST NOT be set. */
5184 if (track->mode == MODE_ISM)
5185 flags &= ~(MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION |
5186 MOV_TFHD_BASE_DATA_OFFSET | MOV_TFHD_STSD_ID);
5187
5188 avio_wb32(pb, 0); /* size placeholder */
5189 ffio_wfourcc(pb, "tfhd");
5190 avio_w8(pb, 0); /* version */
5191 avio_wb24(pb, flags);
5192
5193 avio_wb32(pb, track->track_id); /* track-id */
5194 if (flags & MOV_TFHD_BASE_DATA_OFFSET)
5195 avio_wb64(pb, moof_offset);
5196 if (flags & MOV_TFHD_STSD_ID) {
5197 avio_wb32(pb, 1);
5198 }
5199 if (flags & MOV_TFHD_DEFAULT_DURATION) {
5200 track->default_duration = get_cluster_duration(track, 0);
5201 avio_wb32(pb, track->default_duration);
5202 }
5203 if (flags & MOV_TFHD_DEFAULT_SIZE) {
5204 track->default_size = track->entry ? track->cluster[0].size : 1;
5205 avio_wb32(pb, track->default_size);
5206 } else
5207 track->default_size = -1;
5208
5209 if (flags & MOV_TFHD_DEFAULT_FLAGS) {
5210 /* Set the default flags based on the second sample, if available.
5211 * If the first sample is different, that can be signaled via a separate field. */
5212 if (track->entry > 1)
5213 track->default_sample_flags = get_sample_flags(track, &track->cluster[1]);
5214 else
5215 track->default_sample_flags =
5216 track->par->codec_type == AVMEDIA_TYPE_VIDEO ?
5217 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC) :
5218 MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO;
5219 avio_wb32(pb, track->default_sample_flags);
5220 }
5221
5222 return update_size(pb, pos);
5223 }
5224
5225 static int mov_write_trun_tag(AVIOContext *pb, MOVMuxContext *mov,
5226 MOVTrack *track, int moof_size,
5227 int first, int end)
5228 {
5229 int64_t pos = avio_tell(pb);
5230 uint32_t flags = MOV_TRUN_DATA_OFFSET;
5231 int i;
5232
5233 for (i = first; i < end; i++) {
5234 if (get_cluster_duration(track, i) != track->default_duration)
5235 flags |= MOV_TRUN_SAMPLE_DURATION;
5236 if (track->cluster[i].size != track->default_size)
5237 flags |= MOV_TRUN_SAMPLE_SIZE;
5238 if (i > first && get_sample_flags(track, &track->cluster[i]) != track->default_sample_flags)
5239 flags |= MOV_TRUN_SAMPLE_FLAGS;
5240 }
5241 if (!(flags & MOV_TRUN_SAMPLE_FLAGS) && track->entry > 0 &&
5242 get_sample_flags(track, &track->cluster[0]) != track->default_sample_flags)
5243 flags |= MOV_TRUN_FIRST_SAMPLE_FLAGS;
5244 if (track->flags & MOV_TRACK_CTTS)
5245 flags |= MOV_TRUN_SAMPLE_CTS;
5246
5247 avio_wb32(pb, 0); /* size placeholder */
5248 ffio_wfourcc(pb, "trun");
5249 if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5250 avio_w8(pb, 1); /* version */
5251 else
5252 avio_w8(pb, 0); /* version */
5253 avio_wb24(pb, flags);
5254
5255 avio_wb32(pb, end - first); /* sample count */
5256 if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET &&
5257 !(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) &&
5258 !mov->first_trun)
5259 avio_wb32(pb, 0); /* Later tracks follow immediately after the previous one */
5260 else
5261 avio_wb32(pb, moof_size + 8 + track->data_offset +
5262 track->cluster[first].pos); /* data offset */
5263 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS)
5264 avio_wb32(pb, get_sample_flags(track, &track->cluster[first]));
5265
5266 for (i = first; i < end; i++) {
5267 if (flags & MOV_TRUN_SAMPLE_DURATION)
5268 avio_wb32(pb, get_cluster_duration(track, i));
5269 if (flags & MOV_TRUN_SAMPLE_SIZE)
5270 avio_wb32(pb, track->cluster[i].size);
5271 if (flags & MOV_TRUN_SAMPLE_FLAGS)
5272 avio_wb32(pb, get_sample_flags(track, &track->cluster[i]));
5273 if (flags & MOV_TRUN_SAMPLE_CTS)
5274 avio_wb32(pb, track->cluster[i].cts);
5275 }
5276
5277 mov->first_trun = 0;
5278 return update_size(pb, pos);
5279 }
5280
5281 static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track)
5282 {
5283 int64_t pos = avio_tell(pb);
5284 static const uint8_t uuid[] = {
5285 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
5286 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
5287 };
5288
5289 avio_wb32(pb, 0); /* size placeholder */
5290 ffio_wfourcc(pb, "uuid");
5291 avio_write(pb, uuid, AV_UUID_LEN);
5292 avio_w8(pb, 1);
5293 avio_wb24(pb, 0);
5294 avio_wb64(pb, track->cluster[0].dts + track->cluster[0].cts);
5295 avio_wb64(pb, track->end_pts -
5296 (track->cluster[0].dts + track->cluster[0].cts));
5297
5298 return update_size(pb, pos);
5299 }
5300
5301 static int mov_write_tfrf_tag(AVIOContext *pb, MOVMuxContext *mov,
5302 MOVTrack *track, int entry)
5303 {
5304 int n = track->nb_frag_info - 1 - entry, i;
5305 int size = 8 + 16 + 4 + 1 + 16*n;
5306 static const uint8_t uuid[] = {
5307 0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95,
5308 0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f
5309 };
5310
5311 if (entry < 0)
5312 return 0;
5313
5314 avio_seek(pb, track->frag_info[entry].tfrf_offset, SEEK_SET);
5315 avio_wb32(pb, size);
5316 ffio_wfourcc(pb, "uuid");
5317 avio_write(pb, uuid, AV_UUID_LEN);
5318 avio_w8(pb, 1);
5319 avio_wb24(pb, 0);
5320 avio_w8(pb, n);
5321 for (i = 0; i < n; i++) {
5322 int index = entry + 1 + i;
5323 avio_wb64(pb, track->frag_info[index].time);
5324 avio_wb64(pb, track->frag_info[index].duration);
5325 }
5326 if (n < mov->ism_lookahead) {
5327 int free_size = 16 * (mov->ism_lookahead - n);
5328 avio_wb32(pb, free_size);
5329 ffio_wfourcc(pb, "free");
5330 ffio_fill(pb, 0, free_size - 8);
5331 }
5332
5333 return 0;
5334 }
5335
5336 static int mov_write_tfrf_tags(AVIOContext *pb, MOVMuxContext *mov,
5337 MOVTrack *track)
5338 {
5339 int64_t pos = avio_tell(pb);
5340 int i;
5341 for (i = 0; i < mov->ism_lookahead; i++) {
5342 /* Update the tfrf tag for the last ism_lookahead fragments,
5343 * nb_frag_info - 1 is the next fragment to be written. */
5344 mov_write_tfrf_tag(pb, mov, track, track->nb_frag_info - 2 - i);
5345 }
5346 avio_seek(pb, pos, SEEK_SET);
5347 return 0;
5348 }
5349
5350 static int mov_add_tfra_entries(AVIOContext *pb, MOVMuxContext *mov, int tracks,
5351 int size)
5352 {
5353 int i;
5354 for (i = 0; i < mov->nb_streams; i++) {
5355 MOVTrack *track = &mov->tracks[i];
5356 MOVFragmentInfo *info;
5357 if ((tracks >= 0 && i != tracks) || !track->entry)
5358 continue;
5359 track->nb_frag_info++;
5360 if (track->nb_frag_info >= track->frag_info_capacity) {
5361 unsigned new_capacity = track->nb_frag_info + MOV_FRAG_INFO_ALLOC_INCREMENT;
5362 if (av_reallocp_array(&track->frag_info,
5363 new_capacity,
5364 sizeof(*track->frag_info)))
5365 return AVERROR(ENOMEM);
5366 track->frag_info_capacity = new_capacity;
5367 }
5368 info = &track->frag_info[track->nb_frag_info - 1];
5369 info->offset = avio_tell(pb);
5370 info->size = size;
5371 // Try to recreate the original pts for the first packet
5372 // from the fields we have stored
5373 info->time = track->cluster[0].dts + track->cluster[0].cts;
5374 info->duration = track->end_pts -
5375 (track->cluster[0].dts + track->cluster[0].cts);
5376 // If the pts is less than zero, we will have trimmed
5377 // away parts of the media track using an edit list,
5378 // and the corresponding start presentation time is zero.
5379 if (info->time < 0) {
5380 info->duration += info->time;
5381 info->time = 0;
5382 }
5383 info->tfrf_offset = 0;
5384 mov_write_tfrf_tags(pb, mov, track);
5385 }
5386 return 0;
5387 }
5388
5389 static void mov_prune_frag_info(MOVMuxContext *mov, int tracks, int max)
5390 {
5391 int i;
5392 for (i = 0; i < mov->nb_streams; i++) {
5393 MOVTrack *track = &mov->tracks[i];
5394 if ((tracks >= 0 && i != tracks) || !track->entry)
5395 continue;
5396 if (track->nb_frag_info > max) {
5397 memmove(track->frag_info, track->frag_info + (track->nb_frag_info - max), max * sizeof(*track->frag_info));
5398 track->nb_frag_info = max;
5399 }
5400 }
5401 }
5402
5403 static int mov_write_tfdt_tag(AVIOContext *pb, MOVTrack *track)
5404 {
5405 int64_t pos = avio_tell(pb);
5406
5407 avio_wb32(pb, 0); /* size */
5408 ffio_wfourcc(pb, "tfdt");
5409 avio_w8(pb, 1); /* version */
5410 avio_wb24(pb, 0);
5411 avio_wb64(pb, track->cluster[0].dts - track->start_dts);
5412 return update_size(pb, pos);
5413 }
5414
5415 static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov,
5416 MOVTrack *track, int64_t moof_offset,
5417 int moof_size)
5418 {
5419 int64_t pos = avio_tell(pb);
5420 int i, start = 0;
5421 avio_wb32(pb, 0); /* size placeholder */
5422 ffio_wfourcc(pb, "traf");
5423
5424 mov_write_tfhd_tag(pb, mov, track, moof_offset);
5425 if (mov->mode != MODE_ISM)
5426 mov_write_tfdt_tag(pb, track);
5427 for (i = 1; i < track->entry; i++) {
5428 if (track->cluster[i].pos != track->cluster[i - 1].pos + track->cluster[i - 1].size) {
5429 mov_write_trun_tag(pb, mov, track, moof_size, start, i);
5430 start = i;
5431 }
5432 }
5433 mov_write_trun_tag(pb, mov, track, moof_size, start, track->entry);
5434 if (mov->mode == MODE_ISM) {
5435 mov_write_tfxd_tag(pb, track);
5436
5437 if (mov->ism_lookahead) {
5438 int size = 16 + 4 + 1 + 16 * mov->ism_lookahead;
5439
5440 if (track->nb_frag_info > 0) {
5441 MOVFragmentInfo *info = &track->frag_info[track->nb_frag_info - 1];
5442 if (!info->tfrf_offset)
5443 info->tfrf_offset = avio_tell(pb);
5444 }
5445 avio_wb32(pb, 8 + size);
5446 ffio_wfourcc(pb, "free");
5447 ffio_fill(pb, 0, size);
5448 }
5449 }
5450
5451 return update_size(pb, pos);
5452 }
5453
5454 static int mov_write_moof_tag_internal(AVIOContext *pb, MOVMuxContext *mov,
5455 int tracks, int moof_size)
5456 {
5457 int64_t pos = avio_tell(pb);
5458 int i;
5459
5460 avio_wb32(pb, 0); /* size placeholder */
5461 ffio_wfourcc(pb, "moof");
5462 mov->first_trun = 1;
5463
5464 mov_write_mfhd_tag(pb, mov);
5465 for (i = 0; i < mov->nb_streams; i++) {
5466 MOVTrack *track = &mov->tracks[i];
5467 if (tracks >= 0 && i != tracks)
5468 continue;
5469 if (!track->entry)
5470 continue;
5471 mov_write_traf_tag(pb, mov, track, pos, moof_size);
5472 }
5473
5474 return update_size(pb, pos);
5475 }
5476
5477 static int mov_write_sidx_tag(AVIOContext *pb,
5478 MOVTrack *track, int ref_size, int total_sidx_size)
5479 {
5480 int64_t pos = avio_tell(pb), offset_pos, end_pos;
5481 int64_t presentation_time, duration, offset;
5482 unsigned starts_with_SAP;
5483 int i, entries;
5484
5485 if (track->entry) {
5486 entries = 1;
5487 presentation_time = track->cluster[0].dts + track->cluster[0].cts -
5488 track->start_dts - track->start_cts;
5489 duration = track->end_pts -
5490 (track->cluster[0].dts + track->cluster[0].cts);
5491 starts_with_SAP = track->cluster[0].flags & MOV_SYNC_SAMPLE;
5492
5493 // pts<0 should be cut away using edts
5494 if (presentation_time < 0) {
5495 duration += presentation_time;
5496 presentation_time = 0;
5497 }
5498 } else {
5499 entries = track->nb_frag_info;
5500 if (entries <= 0)
5501 return 0;
5502 presentation_time = track->frag_info[0].time;
5503 /* presentation_time <= 0 is handled by mov_add_tfra_entries() */
5504 if (presentation_time > 0)
5505 presentation_time -= track->start_dts + track->start_cts;
5506 }
5507
5508 avio_wb32(pb, 0); /* size */
5509 ffio_wfourcc(pb, "sidx");
5510 avio_w8(pb, 1); /* version */
5511 avio_wb24(pb, 0);
5512 avio_wb32(pb, track->track_id); /* reference_ID */
5513 avio_wb32(pb, track->timescale); /* timescale */
5514 avio_wb64(pb, presentation_time); /* earliest_presentation_time */
5515 offset_pos = avio_tell(pb);
5516 avio_wb64(pb, 0); /* first_offset (offset to referenced moof) */
5517 avio_wb16(pb, 0); /* reserved */
5518
5519 avio_wb16(pb, entries); /* reference_count */
5520 for (i = 0; i < entries; i++) {
5521 if (!track->entry) {
5522 if (i > 1 && track->frag_info[i].offset != track->frag_info[i - 1].offset + track->frag_info[i - 1].size) {
5523 av_log(NULL, AV_LOG_ERROR, "Non-consecutive fragments, writing incorrect sidx\n");
5524 }
5525 duration = track->frag_info[i].duration;
5526 ref_size = track->frag_info[i].size;
5527 starts_with_SAP = 1;
5528 }
5529 avio_wb32(pb, (0 << 31) | (ref_size & 0x7fffffff)); /* reference_type (0 = media) | referenced_size */
5530 avio_wb32(pb, duration); /* subsegment_duration */
5531 avio_wb32(pb, (starts_with_SAP << 31) | (0 << 28) | 0); /* starts_with_SAP | SAP_type | SAP_delta_time */
5532 }
5533
5534 end_pos = avio_tell(pb);
5535 offset = pos + total_sidx_size - end_pos;
5536 avio_seek(pb, offset_pos, SEEK_SET);
5537 avio_wb64(pb, offset);
5538 avio_seek(pb, end_pos, SEEK_SET);
5539 return update_size(pb, pos);
5540 }
5541
5542 static int mov_write_sidx_tags(AVIOContext *pb, MOVMuxContext *mov,
5543 int tracks, int ref_size)
5544 {
5545 int i, round, ret;
5546 AVIOContext *avio_buf;
5547 int total_size = 0;
5548 for (round = 0; round < 2; round++) {
5549 // First run one round to calculate the total size of all
5550 // sidx atoms.
5551 // This would be much simpler if we'd only write one sidx
5552 // atom, for the first track in the moof.
5553 if (round == 0) {
5554 if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
5555 return ret;
5556 } else {
5557 avio_buf = pb;
5558 }
5559 for (i = 0; i < mov->nb_streams; i++) {
5560 MOVTrack *track = &mov->tracks[i];
5561 if (tracks >= 0 && i != tracks)
5562 continue;
5563 // When writing a sidx for the full file, entry is 0, but
5564 // we want to include all tracks. ref_size is 0 in this case,
5565 // since we read it from frag_info instead.
5566 if (!track->entry && ref_size > 0)
5567 continue;
5568 total_size -= mov_write_sidx_tag(avio_buf, track, ref_size,
5569 total_size);
5570 }
5571 if (round == 0)
5572 total_size = ffio_close_null_buf(avio_buf);
5573 }
5574 return 0;
5575 }
5576
5577 static int mov_write_prft_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks)
5578 {
5579 int64_t pos = avio_tell(pb), pts_us, ntp_ts;
5580 MOVTrack *first_track;
5581 int flags = 24;
5582
5583 /* PRFT should be associated with at most one track. So, choosing only the
5584 * first track. */
5585 if (tracks > 0)
5586 return 0;
5587 first_track = &(mov->tracks[0]);
5588
5589 if (!first_track->entry) {
5590 av_log(mov->fc, AV_LOG_WARNING, "Unable to write PRFT, no entries in the track\n");
5591 return 0;
5592 }
5593
5594 if (first_track->cluster[0].pts == AV_NOPTS_VALUE) {
5595 av_log(mov->fc, AV_LOG_WARNING, "Unable to write PRFT, first PTS is invalid\n");
5596 return 0;
5597 }
5598
5599 if (mov->write_prft == MOV_PRFT_SRC_WALLCLOCK) {
5600 if (first_track->cluster[0].prft.wallclock) {
5601 /* Round the NTP time to whole milliseconds. */
5602 ntp_ts = ff_get_formatted_ntp_time((first_track->cluster[0].prft.wallclock / 1000) * 1000 +
5603 NTP_OFFSET_US);
5604 flags = first_track->cluster[0].prft.flags;
5605 } else
5606 ntp_ts = ff_get_formatted_ntp_time(ff_ntp_time());
5607 } else if (mov->write_prft == MOV_PRFT_SRC_PTS) {
5608 pts_us = av_rescale_q(first_track->cluster[0].pts,
5609 first_track->st->time_base, AV_TIME_BASE_Q);
5610 ntp_ts = ff_get_formatted_ntp_time(pts_us + NTP_OFFSET_US);
5611 } else {
5612 av_log(mov->fc, AV_LOG_WARNING, "Unsupported PRFT box configuration: %d\n",
5613 mov->write_prft);
5614 return 0;
5615 }
5616
5617 avio_wb32(pb, 0); // Size place holder
5618 ffio_wfourcc(pb, "prft"); // Type
5619 avio_w8(pb, 1); // Version
5620 avio_wb24(pb, flags); // Flags
5621 avio_wb32(pb, first_track->track_id); // reference track ID
5622 avio_wb64(pb, ntp_ts); // NTP time stamp
5623 avio_wb64(pb, first_track->cluster[0].pts); //media time
5624 return update_size(pb, pos);
5625 }
5626
5627 static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks,
5628 int64_t mdat_size)
5629 {
5630 AVIOContext *avio_buf;
5631 int ret, moof_size;
5632
5633 if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
5634 return ret;
5635 mov_write_moof_tag_internal(avio_buf, mov, tracks, 0);
5636 moof_size = ffio_close_null_buf(avio_buf);
5637
5638 if (mov->flags & FF_MOV_FLAG_DASH &&
5639 !(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | FF_MOV_FLAG_SKIP_SIDX)))
5640 mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size);
5641
5642 if (mov->write_prft > MOV_PRFT_NONE && mov->write_prft < MOV_PRFT_NB)
5643 mov_write_prft_tag(pb, mov, tracks);
5644
5645 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX ||
5646 !(mov->flags & FF_MOV_FLAG_SKIP_TRAILER) ||
5647 mov->ism_lookahead) {
5648 if ((ret = mov_add_tfra_entries(pb, mov, tracks, moof_size + 8 + mdat_size)) < 0)
5649 return ret;
5650 if (!(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) &&
5651 mov->flags & FF_MOV_FLAG_SKIP_TRAILER) {
5652 mov_prune_frag_info(mov, tracks, mov->ism_lookahead + 1);
5653 }
5654 }
5655
5656 return mov_write_moof_tag_internal(pb, mov, tracks, moof_size);
5657 }
5658
5659 static int mov_write_tfra_tag(AVIOContext *pb, MOVTrack *track)
5660 {
5661 int64_t pos = avio_tell(pb);
5662 int i;
5663
5664 avio_wb32(pb, 0); /* size placeholder */
5665 ffio_wfourcc(pb, "tfra");
5666 avio_w8(pb, 1); /* version */
5667 avio_wb24(pb, 0);
5668
5669 avio_wb32(pb, track->track_id);
5670 avio_wb32(pb, 0); /* length of traf/trun/sample num */
5671 avio_wb32(pb, track->nb_frag_info);
5672 for (i = 0; i < track->nb_frag_info; i++) {
5673 avio_wb64(pb, track->frag_info[i].time);
5674 avio_wb64(pb, track->frag_info[i].offset + track->data_offset);
5675 avio_w8(pb, 1); /* traf number */
5676 avio_w8(pb, 1); /* trun number */
5677 avio_w8(pb, 1); /* sample number */
5678 }
5679
5680 return update_size(pb, pos);
5681 }
5682
5683 static int mov_write_mfra_tag(AVIOContext *pb, MOVMuxContext *mov)
5684 {
5685 AVIOContext *mfra_pb;
5686 int i, ret, sz;
5687 uint8_t *buf;
5688
5689 ret = avio_open_dyn_buf(&mfra_pb);
5690 if (ret < 0)
5691 return ret;
5692
5693 avio_wb32(mfra_pb, 0); /* size placeholder */
5694 ffio_wfourcc(mfra_pb, "mfra");
5695 /* An empty mfra atom is enough to indicate to the publishing point that
5696 * the stream has ended. */
5697 if (mov->flags & FF_MOV_FLAG_ISML)
5698 goto done_mfra;
5699
5700 for (i = 0; i < mov->nb_streams; i++) {
5701 MOVTrack *track = &mov->tracks[i];
5702 if (track->nb_frag_info)
5703 mov_write_tfra_tag(mfra_pb, track);
5704 }
5705
5706 avio_wb32(mfra_pb, 16);
5707 ffio_wfourcc(mfra_pb, "mfro");
5708 avio_wb32(mfra_pb, 0); /* version + flags */
5709 avio_wb32(mfra_pb, avio_tell(mfra_pb) + 4);
5710
5711 done_mfra:
5712
5713 sz = update_size(mfra_pb, 0);
5714 ret = avio_get_dyn_buf(mfra_pb, &buf);
5715 avio_write(pb, buf, ret);
5716 ffio_free_dyn_buf(&mfra_pb);
5717
5718 return sz;
5719 }
5720
5721 static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov)
5722 {
5723 avio_wb32(pb, 8); // placeholder for extended size field (64 bit)
5724 ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free");
5725
5726 mov->mdat_pos = avio_tell(pb);
5727 avio_wb32(pb, 0); /* size placeholder*/
5728 ffio_wfourcc(pb, "mdat");
5729 return 0;
5730 }
5731
5732 static void mov_write_ftyp_tag_internal(AVIOContext *pb, AVFormatContext *s,
5733 int has_h264, int has_video, int write_minor)
5734 {
5735 MOVMuxContext *mov = s->priv_data;
5736 int minor = 0x200;
5737
5738 if (mov->major_brand && strlen(mov->major_brand) >= 4)
5739 ffio_wfourcc(pb, mov->major_brand);
5740 else if (mov->mode == MODE_3GP) {
5741 ffio_wfourcc(pb, has_h264 ? "3gp6" : "3gp4");
5742 minor = has_h264 ? 0x100 : 0x200;
5743 } else if (mov->mode == MODE_AVIF) {
5744 ffio_wfourcc(pb, mov->is_animated_avif ? "avis" : "avif");
5745 minor = 0;
5746 } else if (mov->mode & MODE_3G2) {
5747 ffio_wfourcc(pb, has_h264 ? "3g2b" : "3g2a");
5748 minor = has_h264 ? 0x20000 : 0x10000;
5749 } else if (mov->mode == MODE_PSP)
5750 ffio_wfourcc(pb, "MSNV");
5751 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_FRAGMENT &&
5752 mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5753 ffio_wfourcc(pb, "iso6"); // Required when using signed CTS offsets in trun boxes
5754 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
5755 ffio_wfourcc(pb, "iso5"); // Required when using default-base-is-moof
5756 else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5757 ffio_wfourcc(pb, "iso4");
5758 else if (mov->mode == MODE_MP4)
5759 ffio_wfourcc(pb, "isom");
5760 else if (mov->mode == MODE_IPOD)
5761 ffio_wfourcc(pb, has_video ? "M4V ":"M4A ");
5762 else if (mov->mode == MODE_ISM)
5763 ffio_wfourcc(pb, "isml");
5764 else if (mov->mode == MODE_F4V)
5765 ffio_wfourcc(pb, "f4v ");
5766 else
5767 ffio_wfourcc(pb, "qt ");
5768
5769 if (write_minor)
5770 avio_wb32(pb, minor);
5771 }
5772
5773 static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s)
5774 {
5775 MOVMuxContext *mov = s->priv_data;
5776 int64_t pos = avio_tell(pb);
5777 int has_h264 = 0, has_av1 = 0, has_video = 0, has_dolby = 0;
5778 int i;
5779
5780 for (i = 0; i < s->nb_streams; i++) {
5781 AVStream *st = s->streams[i];
5782 if (is_cover_image(st))
5783 continue;
5784 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
5785 has_video = 1;
5786 if (st->codecpar->codec_id == AV_CODEC_ID_H264)
5787 has_h264 = 1;
5788 if (st->codecpar->codec_id == AV_CODEC_ID_AV1)
5789 has_av1 = 1;
5790 if (st->codecpar->codec_id == AV_CODEC_ID_AC3 ||
5791 st->codecpar->codec_id == AV_CODEC_ID_EAC3 ||
5792 st->codecpar->codec_id == AV_CODEC_ID_TRUEHD ||
5793 av_stream_get_side_data(st, AV_PKT_DATA_DOVI_CONF, NULL))
5794 has_dolby = 1;
5795 }
5796
5797 avio_wb32(pb, 0); /* size */
5798 ffio_wfourcc(pb, "ftyp");
5799
5800 // Write major brand
5801 mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 1);
5802 // Write the major brand as the first compatible brand as well
5803 mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 0);
5804
5805 // Write compatible brands, ensuring that we don't write the major brand as a
5806 // compatible brand a second time.
5807 if (mov->mode == MODE_ISM) {
5808 ffio_wfourcc(pb, "piff");
5809 } else if (mov->mode == MODE_AVIF) {
5810 const AVPixFmtDescriptor *pix_fmt_desc =
5811 av_pix_fmt_desc_get(s->streams[0]->codecpar->format);
5812 const int depth = pix_fmt_desc->comp[0].depth;
5813 if (mov->is_animated_avif) {
5814 // For animated AVIF, major brand is "avis". Add "avif" as a
5815 // compatible brand.
5816 ffio_wfourcc(pb, "avif");
5817 ffio_wfourcc(pb, "msf1");
5818 ffio_wfourcc(pb, "iso8");
5819 }
5820 ffio_wfourcc(pb, "mif1");
5821 ffio_wfourcc(pb, "miaf");
5822 if (depth == 8 || depth == 10) {
5823 // MA1B and MA1A brands are based on AV1 profile. Short hand for
5824 // computing that is based on chroma subsampling type. 420 chroma
5825 // subsampling is MA1B. 444 chroma subsampling is MA1A.
5826 if (!pix_fmt_desc->log2_chroma_w && !pix_fmt_desc->log2_chroma_h) {
5827 // 444 chroma subsampling.
5828 ffio_wfourcc(pb, "MA1A");
5829 } else {
5830 // 420 chroma subsampling.
5831 ffio_wfourcc(pb, "MA1B");
5832 }
5833 }
5834 } else if (mov->mode != MODE_MOV) {
5835 // We add tfdt atoms when fragmenting, signal this with the iso6 compatible
5836 // brand, if not already the major brand. This is compatible with users that
5837 // don't understand tfdt.
5838 if (mov->mode == MODE_MP4) {
5839 if (mov->flags & FF_MOV_FLAG_CMAF)
5840 ffio_wfourcc(pb, "cmfc");
5841 if (mov->flags & FF_MOV_FLAG_FRAGMENT && !(mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS))
5842 ffio_wfourcc(pb, "iso6");
5843 if (has_av1)
5844 ffio_wfourcc(pb, "av01");
5845 if (has_dolby)
5846 ffio_wfourcc(pb, "dby1");
5847 } else {
5848 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
5849 ffio_wfourcc(pb, "iso6");
5850 if (mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
5851 ffio_wfourcc(pb, "iso5");
5852 else if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5853 ffio_wfourcc(pb, "iso4");
5854 }
5855 // Brands prior to iso5 can't be signaled when using default-base-is-moof
5856 if (!(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)) {
5857 // write isom for mp4 only if it it's not the major brand already.
5858 if (mov->mode != MODE_MP4 || mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
5859 ffio_wfourcc(pb, "isom");
5860 ffio_wfourcc(pb, "iso2");
5861 if (has_h264)
5862 ffio_wfourcc(pb, "avc1");
5863 }
5864 }
5865
5866 if (mov->mode == MODE_MP4)
5867 ffio_wfourcc(pb, "mp41");
5868
5869 if (mov->flags & FF_MOV_FLAG_DASH && mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
5870 ffio_wfourcc(pb, "dash");
5871
5872 return update_size(pb, pos);
5873 }
5874
5875 static int mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s)
5876 {
5877 AVStream *video_st = s->streams[0];
5878 AVCodecParameters *video_par = s->streams[0]->codecpar;
5879 AVCodecParameters *audio_par = s->streams[1]->codecpar;
5880 int audio_rate = audio_par->sample_rate;
5881 int64_t frame_rate = video_st->avg_frame_rate.den ?
5882 (video_st->avg_frame_rate.num * 0x10000LL) / video_st->avg_frame_rate.den :
5883 0;
5884 int audio_kbitrate = audio_par->bit_rate / 1000;
5885 int video_kbitrate = FFMIN(video_par->bit_rate / 1000, 800 - audio_kbitrate);
5886
5887 if (frame_rate < 0 || frame_rate > INT32_MAX) {
5888 av_log(s, AV_LOG_ERROR, "Frame rate %f outside supported range\n", frame_rate / (double)0x10000);
5889 return AVERROR(EINVAL);
5890 }
5891
5892 avio_wb32(pb, 0x94); /* size */
5893 ffio_wfourcc(pb, "uuid");
5894 ffio_wfourcc(pb, "PROF");
5895
5896 avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */
5897 avio_wb32(pb, 0xbb88695c);
5898 avio_wb32(pb, 0xfac9c740);
5899
5900 avio_wb32(pb, 0x0); /* ? */
5901 avio_wb32(pb, 0x3); /* 3 sections ? */
5902
5903 avio_wb32(pb, 0x14); /* size */
5904 ffio_wfourcc(pb, "FPRF");
5905 avio_wb32(pb, 0x0); /* ? */
5906 avio_wb32(pb, 0x0); /* ? */
5907 avio_wb32(pb, 0x0); /* ? */
5908
5909 avio_wb32(pb, 0x2c); /* size */
5910 ffio_wfourcc(pb, "APRF"); /* audio */
5911 avio_wb32(pb, 0x0);
5912 avio_wb32(pb, 0x2); /* TrackID */
5913 ffio_wfourcc(pb, "mp4a");
5914 avio_wb32(pb, 0x20f);
5915 avio_wb32(pb, 0x0);
5916 avio_wb32(pb, audio_kbitrate);
5917 avio_wb32(pb, audio_kbitrate);
5918 avio_wb32(pb, audio_rate);
5919 avio_wb32(pb, audio_par->ch_layout.nb_channels);
5920
5921 avio_wb32(pb, 0x34); /* size */
5922 ffio_wfourcc(pb, "VPRF"); /* video */
5923 avio_wb32(pb, 0x0);
5924 avio_wb32(pb, 0x1); /* TrackID */
5925 if (video_par->codec_id == AV_CODEC_ID_H264) {
5926 ffio_wfourcc(pb, "avc1");
5927 avio_wb16(pb, 0x014D);
5928 avio_wb16(pb, 0x0015);
5929 } else {
5930 ffio_wfourcc(pb, "mp4v");
5931 avio_wb16(pb, 0x0000);
5932 avio_wb16(pb, 0x0103);
5933 }
5934 avio_wb32(pb, 0x0);
5935 avio_wb32(pb, video_kbitrate);
5936 avio_wb32(pb, video_kbitrate);
5937 avio_wb32(pb, frame_rate);
5938 avio_wb32(pb, frame_rate);
5939 avio_wb16(pb, video_par->width);
5940 avio_wb16(pb, video_par->height);
5941 avio_wb32(pb, 0x010001); /* ? */
5942
5943 return 0;
5944 }
5945
5946 static int mov_write_identification(AVIOContext *pb, AVFormatContext *s)
5947 {
5948 MOVMuxContext *mov = s->priv_data;
5949 int i;
5950
5951 mov_write_ftyp_tag(pb,s);
5952 if (mov->mode == MODE_PSP) {
5953 int video_streams_nb = 0, audio_streams_nb = 0, other_streams_nb = 0;
5954 for (i = 0; i < s->nb_streams; i++) {
5955 AVStream *st = s->streams[i];
5956 if (is_cover_image(st))
5957 continue;
5958 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
5959 video_streams_nb++;
5960 else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
5961 audio_streams_nb++;
5962 else
5963 other_streams_nb++;
5964 }
5965
5966 if (video_streams_nb != 1 || audio_streams_nb != 1 || other_streams_nb) {
5967 av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
5968 return AVERROR(EINVAL);
5969 }
5970 return mov_write_uuidprof_tag(pb, s);
5971 }
5972 return 0;
5973 }
5974
5975 static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags)
5976 {
5977 uint32_t c = -1;
5978 int i, closed_gop = 0;
5979
5980 for (i = 0; i < pkt->size - 4; i++) {
5981 c = (c << 8) + pkt->data[i];
5982 if (c == 0x1b8) { // gop
5983 closed_gop = pkt->data[i + 4] >> 6 & 0x01;
5984 } else if (c == 0x100) { // pic
5985 int temp_ref = (pkt->data[i + 1] << 2) | (pkt->data[i + 2] >> 6);
5986 if (!temp_ref || closed_gop) // I picture is not reordered
5987 *flags = MOV_SYNC_SAMPLE;
5988 else
5989 *flags = MOV_PARTIAL_SYNC_SAMPLE;
5990 break;
5991 }
5992 }
5993 return 0;
5994 }
5995
5996 static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk)
5997 {
5998 const uint8_t *start, *next, *end = pkt->data + pkt->size;
5999 int seq = 0, entry = 0;
6000 int key = pkt->flags & AV_PKT_FLAG_KEY;
6001 start = find_next_marker(pkt->data, end);
6002 for (next = start; next < end; start = next) {
6003 next = find_next_marker(start + 4, end);
6004 switch (AV_RB32(start)) {
6005 case VC1_CODE_SEQHDR:
6006 seq = 1;
6007 break;
6008 case VC1_CODE_ENTRYPOINT:
6009 entry = 1;
6010 break;
6011 case VC1_CODE_SLICE:
6012 trk->vc1_info.slices = 1;
6013 break;
6014 }
6015 }
6016 if (!trk->entry && trk->vc1_info.first_packet_seen)
6017 trk->vc1_info.first_frag_written = 1;
6018 if (!trk->entry && !trk->vc1_info.first_frag_written) {
6019 /* First packet in first fragment */
6020 trk->vc1_info.first_packet_seq = seq;
6021 trk->vc1_info.first_packet_entry = entry;
6022 trk->vc1_info.first_packet_seen = 1;
6023 } else if ((seq && !trk->vc1_info.packet_seq) ||
6024 (entry && !trk->vc1_info.packet_entry)) {
6025 int i;
6026 for (i = 0; i < trk->entry; i++)
6027 trk->cluster[i].flags &= ~MOV_SYNC_SAMPLE;
6028 trk->has_keyframes = 0;
6029 if (seq)
6030 trk->vc1_info.packet_seq = 1;
6031 if (entry)
6032 trk->vc1_info.packet_entry = 1;
6033 if (!trk->vc1_info.first_frag_written) {
6034 /* First fragment */
6035 if ((!seq || trk->vc1_info.first_packet_seq) &&
6036 (!entry || trk->vc1_info.first_packet_entry)) {
6037 /* First packet had the same headers as this one, readd the
6038 * sync sample flag. */
6039 trk->cluster[0].flags |= MOV_SYNC_SAMPLE;
6040 trk->has_keyframes = 1;
6041 }
6042 }
6043 }
6044 if (trk->vc1_info.packet_seq && trk->vc1_info.packet_entry)
6045 key = seq && entry;
6046 else if (trk->vc1_info.packet_seq)
6047 key = seq;
6048 else if (trk->vc1_info.packet_entry)
6049 key = entry;
6050 if (key) {
6051 trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
6052 trk->has_keyframes++;
6053 }
6054 }
6055
6056 static void mov_parse_truehd_frame(AVPacket *pkt, MOVTrack *trk)
6057 {
6058 int length;
6059
6060 if (pkt->size < 8)
6061 return;
6062
6063 length = (AV_RB16(pkt->data) & 0xFFF) * 2;
6064 if (length < 8 || length > pkt->size)
6065 return;
6066
6067 if (AV_RB32(pkt->data + 4) == 0xF8726FBA) {
6068 trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE;
6069 trk->has_keyframes++;
6070 }
6071
6072 return;
6073 }
6074
6075 static int mov_flush_fragment_interleaving(AVFormatContext *s, MOVTrack *track)
6076 {
6077 MOVMuxContext *mov = s->priv_data;
6078 int ret, buf_size;
6079 uint8_t *buf;
6080 int i, offset;
6081
6082 if (!track->mdat_buf)
6083 return 0;
6084 if (!mov->mdat_buf) {
6085 if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
6086 return ret;
6087 }
6088 buf_size = avio_get_dyn_buf(track->mdat_buf, &buf);
6089
6090 offset = avio_tell(mov->mdat_buf);
6091 avio_write(mov->mdat_buf, buf, buf_size);
6092 ffio_free_dyn_buf(&track->mdat_buf);
6093
6094 for (i = track->entries_flushed; i < track->entry; i++)
6095 track->cluster[i].pos += offset;
6096 track->entries_flushed = track->entry;
6097 return 0;
6098 }
6099
6100 static int mov_write_squashed_packet(AVFormatContext *s, MOVTrack *track)
6101 {
6102 MOVMuxContext *mov = s->priv_data;
6103 AVPacket *squashed_packet = mov->pkt;
6104 int ret = AVERROR_BUG;
6105
6106 switch (track->st->codecpar->codec_id) {
6107 case AV_CODEC_ID_TTML: {
6108 int had_packets = !!track->squashed_packet_queue.head;
6109
6110 if ((ret = ff_mov_generate_squashed_ttml_packet(s, track, squashed_packet)) < 0) {
6111 goto finish_squash;
6112 }
6113
6114 // We have generated a padding packet (no actual input packets in
6115 // queue) and its duration is zero. Skipping writing it.
6116 if (!had_packets && squashed_packet->duration == 0) {
6117 goto finish_squash;
6118 }
6119
6120 track->end_reliable = 1;
6121 break;
6122 }
6123 default:
6124 ret = AVERROR(EINVAL);
6125 goto finish_squash;
6126 }
6127
6128 squashed_packet->stream_index = track->st->index;
6129
6130 ret = mov_write_single_packet(s, squashed_packet);
6131
6132 finish_squash:
6133 av_packet_unref(squashed_packet);
6134
6135 return ret;
6136 }
6137
6138 static int mov_write_squashed_packets(AVFormatContext *s)
6139 {
6140 MOVMuxContext *mov = s->priv_data;
6141
6142 for (int i = 0; i < s->nb_streams; i++) {
6143 MOVTrack *track = &mov->tracks[i];
6144 int ret = AVERROR_BUG;
6145
6146 if (track->squash_fragment_samples_to_one && !track->entry) {
6147 if ((ret = mov_write_squashed_packet(s, track)) < 0) {
6148 av_log(s, AV_LOG_ERROR,
6149 "Failed to write squashed packet for %s stream with "
6150 "index %d and track id %d. Error: %s\n",
6151 avcodec_get_name(track->st->codecpar->codec_id),
6152 track->st->index, track->track_id,
6153 av_err2str(ret));
6154 return ret;
6155 }
6156 }
6157 }
6158
6159 return 0;
6160 }
6161
6162 static int mov_flush_fragment(AVFormatContext *s, int force)
6163 {
6164 MOVMuxContext *mov = s->priv_data;
6165 int i, first_track = -1;
6166 int64_t mdat_size = 0;
6167 int ret;
6168 int has_video = 0, starts_with_key = 0, first_video_track = 1;
6169
6170 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
6171 return 0;
6172
6173 // Check if we have any tracks that require squashing.
6174 // In that case, we'll have to write the packet here.
6175 if ((ret = mov_write_squashed_packets(s)) < 0)
6176 return ret;
6177
6178 // Try to fill in the duration of the last packet in each stream
6179 // from queued packets in the interleave queues. If the flushing
6180 // of fragments was triggered automatically by an AVPacket, we
6181 // already have reliable info for the end of that track, but other
6182 // tracks may need to be filled in.
6183 for (i = 0; i < s->nb_streams; i++) {
6184 MOVTrack *track = &mov->tracks[i];
6185 if (!track->end_reliable) {
6186 const AVPacket *pkt = ff_interleaved_peek(s, i);
6187 if (pkt) {
6188 int64_t offset, dts, pts;
6189 ff_get_muxer_ts_offset(s, i, &offset);
6190 pts = pkt->pts + offset;
6191 dts = pkt->dts + offset;
6192 if (track->dts_shift != AV_NOPTS_VALUE)
6193 dts += track->dts_shift;
6194 track->track_duration = dts - track->start_dts;
6195 if (pts != AV_NOPTS_VALUE)
6196 track->end_pts = pts;
6197 else
6198 track->end_pts = dts;
6199 }
6200 }
6201 }
6202
6203 for (i = 0; i < mov->nb_streams; i++) {
6204 MOVTrack *track = &mov->tracks[i];
6205 if (track->entry <= 1)
6206 continue;
6207 // Sample durations are calculated as the diff of dts values,
6208 // but for the last sample in a fragment, we don't know the dts
6209 // of the first sample in the next fragment, so we have to rely
6210 // on what was set as duration in the AVPacket. Not all callers
6211 // set this though, so we might want to replace it with an
6212 // estimate if it currently is zero.
6213 if (get_cluster_duration(track, track->entry - 1) != 0)
6214 continue;
6215 // Use the duration (i.e. dts diff) of the second last sample for
6216 // the last one. This is a wild guess (and fatal if it turns out
6217 // to be too long), but probably the best we can do - having a zero
6218 // duration is bad as well.
6219 track->track_duration += get_cluster_duration(track, track->entry - 2);
6220 track->end_pts += get_cluster_duration(track, track->entry - 2);
6221 if (!mov->missing_duration_warned) {
6222 av_log(s, AV_LOG_WARNING,
6223 "Estimating the duration of the last packet in a "
6224 "fragment, consider setting the duration field in "
6225 "AVPacket instead.\n");
6226 mov->missing_duration_warned = 1;
6227 }
6228 }
6229
6230 if (!mov->moov_written) {
6231 int64_t pos = avio_tell(s->pb);
6232 uint8_t *buf;
6233 int buf_size, moov_size;
6234
6235 for (i = 0; i < mov->nb_streams; i++)
6236 if (!mov->tracks[i].entry && !is_cover_image(mov->tracks[i].st))
6237 break;
6238 /* Don't write the initial moov unless all tracks have data */
6239 if (i < mov->nb_streams && !force)
6240 return 0;
6241
6242 moov_size = get_moov_size(s);
6243 for (i = 0; i < mov->nb_streams; i++)
6244 mov->tracks[i].data_offset = pos + moov_size + 8;
6245
6246 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER);
6247 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV)
6248 mov_write_identification(s->pb, s);
6249 if ((ret = mov_write_moov_tag(s->pb, mov, s)) < 0)
6250 return ret;
6251
6252 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) {
6253 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
6254 mov->reserved_header_pos = avio_tell(s->pb);
6255 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6256 mov->moov_written = 1;
6257 return 0;
6258 }
6259
6260 buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
6261 avio_wb32(s->pb, buf_size + 8);
6262 ffio_wfourcc(s->pb, "mdat");
6263 avio_write(s->pb, buf, buf_size);
6264 ffio_free_dyn_buf(&mov->mdat_buf);
6265
6266 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
6267 mov->reserved_header_pos = avio_tell(s->pb);
6268
6269 mov->moov_written = 1;
6270 mov->mdat_size = 0;
6271 for (i = 0; i < mov->nb_streams; i++) {
6272 mov->tracks[i].entry = 0;
6273 mov->tracks[i].end_reliable = 0;
6274 }
6275 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6276 return 0;
6277 }
6278
6279 if (mov->frag_interleave) {
6280 for (i = 0; i < mov->nb_streams; i++) {
6281 MOVTrack *track = &mov->tracks[i];
6282 int ret;
6283 if ((ret = mov_flush_fragment_interleaving(s, track)) < 0)
6284 return ret;
6285 }
6286
6287 if (!mov->mdat_buf)
6288 return 0;
6289 mdat_size = avio_tell(mov->mdat_buf);
6290 }
6291
6292 for (i = 0; i < mov->nb_streams; i++) {
6293 MOVTrack *track = &mov->tracks[i];
6294 if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF || mov->frag_interleave)
6295 track->data_offset = 0;
6296 else
6297 track->data_offset = mdat_size;
6298 if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
6299 has_video = 1;
6300 if (first_video_track) {
6301 if (track->entry)
6302 starts_with_key = track->cluster[0].flags & MOV_SYNC_SAMPLE;
6303 first_video_track = 0;
6304 }
6305 }
6306 if (!track->entry)
6307 continue;
6308 if (track->mdat_buf)
6309 mdat_size += avio_tell(track->mdat_buf);
6310 if (first_track < 0)
6311 first_track = i;
6312 }
6313
6314 if (!mdat_size)
6315 return 0;
6316
6317 avio_write_marker(s->pb,
6318 av_rescale(mov->tracks[first_track].cluster[0].dts, AV_TIME_BASE, mov->tracks[first_track].timescale),
6319 (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);
6320
6321 for (i = 0; i < mov->nb_streams; i++) {
6322 MOVTrack *track = &mov->tracks[i];
6323 int buf_size, write_moof = 1, moof_tracks = -1;
6324 uint8_t *buf;
6325
6326 if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) {
6327 if (!track->entry)
6328 continue;
6329 mdat_size = avio_tell(track->mdat_buf);
6330 moof_tracks = i;
6331 } else {
6332 write_moof = i == first_track;
6333 }
6334
6335 if (write_moof) {
6336 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6337
6338 mov_write_moof_tag(s->pb, mov, moof_tracks, mdat_size);
6339 mov->fragments++;
6340
6341 avio_wb32(s->pb, mdat_size + 8);
6342 ffio_wfourcc(s->pb, "mdat");
6343 }
6344
6345 track->entry = 0;
6346 track->entries_flushed = 0;
6347 track->end_reliable = 0;
6348 if (!mov->frag_interleave) {
6349 if (!track->mdat_buf)
6350 continue;
6351 buf_size = avio_close_dyn_buf(track->mdat_buf, &buf);
6352 track->mdat_buf = NULL;
6353 } else {
6354 if (!mov->mdat_buf)
6355 continue;
6356 buf_size = avio_close_dyn_buf(mov->mdat_buf, &buf);
6357 mov->mdat_buf = NULL;
6358 }
6359
6360 avio_write(s->pb, buf, buf_size);
6361 av_free(buf);
6362 }
6363
6364 mov->mdat_size = 0;
6365
6366 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
6367 return 0;
6368 }
6369
6370 static int mov_auto_flush_fragment(AVFormatContext *s, int force)
6371 {
6372 MOVMuxContext *mov = s->priv_data;
6373 int had_moov = mov->moov_written;
6374 int ret = mov_flush_fragment(s, force);
6375 if (ret < 0)
6376 return ret;
6377 // If using delay_moov, the first flush only wrote the moov,
6378 // not the actual moof+mdat pair, thus flush once again.
6379 if (!had_moov && mov->flags & FF_MOV_FLAG_DELAY_MOOV)
6380 ret = mov_flush_fragment(s, force);
6381 return ret;
6382 }
6383
6384 static int check_pkt(AVFormatContext *s, AVPacket *pkt)
6385 {
6386 MOVMuxContext *mov = s->priv_data;
6387 MOVTrack *trk = &mov->tracks[pkt->stream_index];
6388 int64_t ref;
6389 uint64_t duration;
6390
6391 if (trk->entry) {
6392 ref = trk->cluster[trk->entry - 1].dts;
6393 } else if ( trk->start_dts != AV_NOPTS_VALUE
6394 && !trk->frag_discont) {
6395 ref = trk->start_dts + trk->track_duration;
6396 } else
6397 ref = pkt->dts; // Skip tests for the first packet
6398
6399 if (trk->dts_shift != AV_NOPTS_VALUE) {
6400 /* With negative CTS offsets we have set an offset to the DTS,
6401 * reverse this for the check. */
6402 ref -= trk->dts_shift;
6403 }
6404
6405 duration = pkt->dts - ref;
6406 if (pkt->dts < ref || duration >= INT_MAX) {
6407 av_log(s, AV_LOG_WARNING, "Packet duration: %"PRId64" / dts: %"PRId64" is out of range\n",
6408 duration, pkt->dts);
6409
6410 pkt->dts = ref + 1;
6411 pkt->pts = AV_NOPTS_VALUE;
6412 }
6413
6414 if (pkt->duration < 0 || pkt->duration > INT_MAX) {
6415 av_log(s, AV_LOG_ERROR, "Application provided duration: %"PRId64" is invalid\n", pkt->duration);
6416 return AVERROR(EINVAL);
6417 }
6418 return 0;
6419 }
6420
6421 int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
6422 {
6423 MOVMuxContext *mov = s->priv_data;
6424 AVIOContext *pb = s->pb;
6425 MOVTrack *trk = &mov->tracks[pkt->stream_index];
6426 AVCodecParameters *par = trk->par;
6427 AVProducerReferenceTime *prft;
6428 unsigned int samples_in_chunk = 0;
6429 int size = pkt->size, ret = 0, offset = 0;
6430 size_t prft_size;
6431 uint8_t *reformatted_data = NULL;
6432
6433 ret = check_pkt(s, pkt);
6434 if (ret < 0)
6435 return ret;
6436
6437 if (mov->flags & FF_MOV_FLAG_FRAGMENT || mov->mode == MODE_AVIF) {
6438 int ret;
6439 if (mov->moov_written || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
6440 if (mov->frag_interleave && mov->fragments > 0) {
6441 if (trk->entry - trk->entries_flushed >= mov->frag_interleave) {
6442 if ((ret = mov_flush_fragment_interleaving(s, trk)) < 0)
6443 return ret;
6444 }
6445 }
6446
6447 if (!trk->mdat_buf) {
6448 if ((ret = avio_open_dyn_buf(&trk->mdat_buf)) < 0)
6449 return ret;
6450 }
6451 pb = trk->mdat_buf;
6452 } else {
6453 if (!mov->mdat_buf) {
6454 if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
6455 return ret;
6456 }
6457 pb = mov->mdat_buf;
6458 }
6459 }
6460
6461 if (par->codec_id == AV_CODEC_ID_AMR_NB) {
6462 /* We must find out how many AMR blocks there are in one packet */
6463 static const uint16_t packed_size[16] =
6464 {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
6465 int len = 0;
6466
6467 while (len < size && samples_in_chunk < 100) {
6468 len += packed_size[(pkt->data[len] >> 3) & 0x0F];
6469 samples_in_chunk++;
6470 }
6471 if (samples_in_chunk > 1) {
6472 av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
6473 return -1;
6474 }
6475 } else if (par->codec_id == AV_CODEC_ID_ADPCM_MS ||
6476 par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
6477 samples_in_chunk = trk->par->frame_size;
6478 } else if (trk->sample_size)
6479 samples_in_chunk = size / trk->sample_size;
6480 else
6481 samples_in_chunk = 1;
6482
6483 if (samples_in_chunk < 1) {
6484 av_log(s, AV_LOG_ERROR, "fatal error, input packet contains no samples\n");
6485 return AVERROR_PATCHWELCOME;
6486 }
6487
6488 /* copy extradata if it exists */
6489 if (trk->vos_len == 0 && par->extradata_size > 0 &&
6490 !TAG_IS_AVCI(trk->tag) &&
6491 (par->codec_id != AV_CODEC_ID_DNXHD)) {
6492 trk->vos_len = par->extradata_size;
6493 trk->vos_data = av_malloc(trk->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
6494 if (!trk->vos_data) {
6495 ret = AVERROR(ENOMEM);
6496 goto err;
6497 }
6498 memcpy(trk->vos_data, par->extradata, trk->vos_len);
6499 memset(trk->vos_data + trk->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
6500 }
6501
6502 if ((par->codec_id == AV_CODEC_ID_DNXHD ||
6503 par->codec_id == AV_CODEC_ID_H264 ||
6504 par->codec_id == AV_CODEC_ID_HEVC ||
6505 par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->vos_len &&
6506 !TAG_IS_AVCI(trk->tag)) {
6507 /* copy frame to create needed atoms */
6508 trk->vos_len = size;
6509 trk->vos_data = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
6510 if (!trk->vos_data) {
6511 ret = AVERROR(ENOMEM);
6512 goto err;
6513 }
6514 memcpy(trk->vos_data, pkt->data, size);
6515 memset(trk->vos_data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
6516 }
6517
6518 if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
6519 (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
6520 if (!s->streams[pkt->stream_index]->nb_frames) {
6521 av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: "
6522 "use the audio bitstream filter 'aac_adtstoasc' to fix it "
6523 "('-bsf:a aac_adtstoasc' option with ffmpeg)\n");
6524 return -1;
6525 }
6526 av_log(s, AV_LOG_WARNING, "aac bitstream error\n");
6527 }
6528 if (par->codec_id == AV_CODEC_ID_H264 && trk->vos_len > 0 && *(uint8_t *)trk->vos_data != 1 && !TAG_IS_AVCI(trk->tag)) {
6529 /* from x264 or from bytestream H.264 */
6530 /* NAL reformatting needed */
6531 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
6532 ret = ff_avc_parse_nal_units_buf(pkt->data, &reformatted_data,
6533 &size);
6534 if (ret < 0)
6535 return ret;
6536 avio_write(pb, reformatted_data, size);
6537 } else {
6538 if (trk->cenc.aes_ctr) {
6539 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
6540 if (size < 0) {
6541 ret = size;
6542 goto err;
6543 }
6544 } else {
6545 size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size);
6546 }
6547 }
6548 } else if (par->codec_id == AV_CODEC_ID_HEVC && trk->vos_len > 6 &&
6549 (AV_RB24(trk->vos_data) == 1 || AV_RB32(trk->vos_data) == 1)) {
6550 /* extradata is Annex B, assume the bitstream is too and convert it */
6551 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
6552 ret = ff_hevc_annexb2mp4_buf(pkt->data, &reformatted_data,
6553 &size, 0, NULL);
6554 if (ret < 0)
6555 return ret;
6556 avio_write(pb, reformatted_data, size);
6557 } else {
6558 if (trk->cenc.aes_ctr) {
6559 size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
6560 if (size < 0) {
6561 ret = size;
6562 goto err;
6563 }
6564 } else {
6565 size = ff_hevc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
6566 }
6567 }
6568 } else if (par->codec_id == AV_CODEC_ID_AV1) {
6569 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
6570 ret = ff_av1_filter_obus_buf(pkt->data, &reformatted_data,
6571 &size, &offset);
6572 if (ret < 0)
6573 return ret;
6574 avio_write(pb, reformatted_data, size);
6575 } else {
6576 size = ff_av1_filter_obus(pb, pkt->data, pkt->size);
6577 if (trk->mode == MODE_AVIF && !mov->avif_extent_length[pkt->stream_index]) {
6578 mov->avif_extent_length[pkt->stream_index] = size;
6579 }
6580 }
6581
6582 } else if (par->codec_id == AV_CODEC_ID_AC3 ||
6583 par->codec_id == AV_CODEC_ID_EAC3) {
6584 size = handle_eac3(mov, pkt, trk);
6585 if (size < 0)
6586 return size;
6587 else if (!size)
6588 goto end;
6589 avio_write(pb, pkt->data, size);
6590 } else if (par->codec_id == AV_CODEC_ID_EIA_608) {
6591 size = 8;
6592
6593 for (int i = 0; i < pkt->size; i += 3) {
6594 if (pkt->data[i] == 0xFC) {
6595 size += 2;
6596 }
6597 }
6598 avio_wb32(pb, size);
6599 ffio_wfourcc(pb, "cdat");
6600 for (int i = 0; i < pkt->size; i += 3) {
6601 if (pkt->data[i] == 0xFC) {
6602 avio_w8(pb, pkt->data[i + 1]);
6603 avio_w8(pb, pkt->data[i + 2]);
6604 }
6605 }
6606 } else {
6607 if (trk->cenc.aes_ctr) {
6608 if (par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 4) {
6609 int nal_size_length = (par->extradata[4] & 0x3) + 1;
6610 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
6611 } else if(par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 21) {
6612 int nal_size_length = (par->extradata[21] & 0x3) + 1;
6613 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
6614 } else {
6615 ret = ff_mov_cenc_write_packet(&trk->cenc, pb, pkt->data, size);
6616 }
6617
6618 if (ret) {
6619 goto err;
6620 }
6621 } else {
6622 avio_write(pb, pkt->data, size);
6623 }
6624 }
6625
6626 if (trk->entry >= trk->cluster_capacity) {
6627 unsigned new_capacity = trk->entry + MOV_INDEX_CLUSTER_SIZE;
6628 void *cluster = av_realloc_array(trk->cluster, new_capacity, sizeof(*trk->cluster));
6629 if (!cluster) {
6630 ret = AVERROR(ENOMEM);
6631 goto err;
6632 }
6633 trk->cluster = cluster;
6634 trk->cluster_capacity = new_capacity;
6635 }
6636
6637 trk->cluster[trk->entry].pos = avio_tell(pb) - size;
6638 trk->cluster[trk->entry].samples_in_chunk = samples_in_chunk;
6639 trk->cluster[trk->entry].chunkNum = 0;
6640 trk->cluster[trk->entry].size = size;
6641 trk->cluster[trk->entry].entries = samples_in_chunk;
6642 trk->cluster[trk->entry].dts = pkt->dts;
6643 trk->cluster[trk->entry].pts = pkt->pts;
6644 if (!trk->squash_fragment_samples_to_one &&
6645 !trk->entry && trk->start_dts != AV_NOPTS_VALUE) {
6646 if (!trk->frag_discont) {
6647 /* First packet of a new fragment. We already wrote the duration
6648 * of the last packet of the previous fragment based on track_duration,
6649 * which might not exactly match our dts. Therefore adjust the dts
6650 * of this packet to be what the previous packets duration implies. */
6651 trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration;
6652 /* We also may have written the pts and the corresponding duration
6653 * in sidx/tfrf/tfxd tags; make sure the sidx pts and duration match up with
6654 * the next fragment. This means the cts of the first sample must
6655 * be the same in all fragments, unless end_pts was updated by
6656 * the packet causing the fragment to be written. */
6657 if ((mov->flags & FF_MOV_FLAG_DASH &&
6658 !(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | FF_MOV_FLAG_SKIP_SIDX))) ||
6659 mov->mode == MODE_ISM)
6660 pkt->pts = pkt->dts + trk->end_pts - trk->cluster[trk->entry].dts;
6661 } else {
6662 /* New fragment, but discontinuous from previous fragments.
6663 * Pretend the duration sum of the earlier fragments is
6664 * pkt->dts - trk->start_dts. */
6665 trk->end_pts = AV_NOPTS_VALUE;
6666 trk->frag_discont = 0;
6667 }
6668 }
6669
6670 if (!trk->entry && trk->start_dts == AV_NOPTS_VALUE && !mov->use_editlist &&
6671 s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) {
6672 /* Not using edit lists and shifting the first track to start from zero.
6673 * If the other streams start from a later timestamp, we won't be able
6674 * to signal the difference in starting time without an edit list.
6675 * Thus move the timestamp for this first sample to 0, increasing
6676 * its duration instead. */
6677 trk->cluster[trk->entry].dts = trk->start_dts = 0;
6678 }
6679 if (trk->start_dts == AV_NOPTS_VALUE) {
6680 trk->start_dts = pkt->dts;
6681 if (trk->frag_discont) {
6682 if (mov->use_editlist) {
6683 /* Pretend the whole stream started at pts=0, with earlier fragments
6684 * already written. If the stream started at pts=0, the duration sum
6685 * of earlier fragments would have been pkt->pts. */
6686 trk->start_dts = pkt->dts - pkt->pts;
6687 } else {
6688 /* Pretend the whole stream started at dts=0, with earlier fragments
6689 * already written, with a duration summing up to pkt->dts. */
6690 trk->start_dts = 0;
6691 }
6692 trk->frag_discont = 0;
6693 } else if (pkt->dts && mov->moov_written)
6694 av_log(s, AV_LOG_WARNING,
6695 "Track %d starts with a nonzero dts %"PRId64", while the moov "
6696 "already has been written. Set the delay_moov flag to handle "
6697 "this case.\n",
6698 pkt->stream_index, pkt->dts);
6699 }
6700 trk->track_duration = pkt->dts - trk->start_dts + pkt->duration;
6701 trk->last_sample_is_subtitle_end = 0;
6702
6703 if (pkt->pts == AV_NOPTS_VALUE) {
6704 av_log(s, AV_LOG_WARNING, "pts has no value\n");
6705 pkt->pts = pkt->dts;
6706 }
6707 if (pkt->dts != pkt->pts)
6708 trk->flags |= MOV_TRACK_CTTS;
6709 trk->cluster[trk->entry].cts = pkt->pts - pkt->dts;
6710 trk->cluster[trk->entry].flags = 0;
6711 if (trk->start_cts == AV_NOPTS_VALUE)
6712 trk->start_cts = pkt->pts - pkt->dts;
6713 if (trk->end_pts == AV_NOPTS_VALUE)
6714 trk->end_pts = trk->cluster[trk->entry].dts +
6715 trk->cluster[trk->entry].cts + pkt->duration;
6716 else
6717 trk->end_pts = FFMAX(trk->end_pts, trk->cluster[trk->entry].dts +
6718 trk->cluster[trk->entry].cts +
6719 pkt->duration);
6720
6721 if (par->codec_id == AV_CODEC_ID_VC1) {
6722 mov_parse_vc1_frame(pkt, trk);
6723 } else if (par->codec_id == AV_CODEC_ID_TRUEHD) {
6724 mov_parse_truehd_frame(pkt, trk);
6725 } else if (pkt->flags & AV_PKT_FLAG_KEY) {
6726 if (mov->mode == MODE_MOV && par->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
6727 trk->entry > 0) { // force sync sample for the first key frame
6728 mov_parse_mpeg2_frame(pkt, &trk->cluster[trk->entry].flags);
6729 if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE)
6730 trk->flags |= MOV_TRACK_STPS;
6731 } else {
6732 trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE;
6733 }
6734 if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE)
6735 trk->has_keyframes++;
6736 }
6737 if (pkt->flags & AV_PKT_FLAG_DISPOSABLE) {
6738 trk->cluster[trk->entry].flags |= MOV_DISPOSABLE_SAMPLE;
6739 trk->has_disposable++;
6740 }
6741
6742 #ifdef OHOS_SDTP_BOX_EXT
6743 if ((unsigned int)pkt->flags & AV_PKT_FLAG_DISPOSABLE_EXT) {
6744 trk->cluster[trk->entry].flags |= MOV_DISPOSABLE_EXT_SAMPLE;
6745 trk->has_disposable++;
6746 }
6747 #endif
6748
6749 prft = (AVProducerReferenceTime *)av_packet_get_side_data(pkt, AV_PKT_DATA_PRFT, &prft_size);
6750 if (prft && prft_size == sizeof(AVProducerReferenceTime))
6751 memcpy(&trk->cluster[trk->entry].prft, prft, prft_size);
6752 else
6753 memset(&trk->cluster[trk->entry].prft, 0, sizeof(AVProducerReferenceTime));
6754
6755 trk->entry++;
6756 trk->sample_count += samples_in_chunk;
6757 mov->mdat_size += size;
6758
6759 if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams)
6760 ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry,
6761 reformatted_data ? reformatted_data + offset
6762 : NULL, size);
6763
6764 end:
6765 err:
6766
6767 if (pkt->data != reformatted_data)
6768 av_free(reformatted_data);
6769 return ret;
6770 }
6771
6772 static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
6773 {
6774 MOVMuxContext *mov = s->priv_data;
6775 MOVTrack *trk = &mov->tracks[pkt->stream_index];
6776 AVCodecParameters *par = trk->par;
6777 int64_t frag_duration = 0;
6778 int size = pkt->size;
6779
6780 int ret = check_pkt(s, pkt);
6781 if (ret < 0)
6782 return ret;
6783
6784 if (mov->flags & FF_MOV_FLAG_FRAG_DISCONT) {
6785 int i;
6786 for (i = 0; i < s->nb_streams; i++)
6787 mov->tracks[i].frag_discont = 1;
6788 mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT;
6789 }
6790
6791 if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) {
6792 if (trk->dts_shift == AV_NOPTS_VALUE)
6793 trk->dts_shift = pkt->pts - pkt->dts;
6794 pkt->dts += trk->dts_shift;
6795 }
6796
6797 if (trk->par->codec_id == AV_CODEC_ID_MP4ALS ||
6798 trk->par->codec_id == AV_CODEC_ID_AAC ||
6799 trk->par->codec_id == AV_CODEC_ID_AV1 ||
6800 trk->par->codec_id == AV_CODEC_ID_FLAC) {
6801 size_t side_size;
6802 uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
6803 if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) {
6804 void *newextra = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE);
6805 if (!newextra)
6806 return AVERROR(ENOMEM);
6807 av_free(par->extradata);
6808 par->extradata = newextra;
6809 memcpy(par->extradata, side, side_size);
6810 par->extradata_size = side_size;
6811 if (!pkt->size) // Flush packet
6812 mov->need_rewrite_extradata = 1;
6813 }
6814 }
6815
6816 if (!pkt->size) {
6817 if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) {
6818 trk->start_dts = pkt->dts;
6819 if (pkt->pts != AV_NOPTS_VALUE)
6820 trk->start_cts = pkt->pts - pkt->dts;
6821 else
6822 trk->start_cts = 0;
6823 }
6824
6825 return 0; /* Discard 0 sized packets */
6826 }
6827
6828 if (trk->entry && pkt->stream_index < s->nb_streams)
6829 frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts,
6830 s->streams[pkt->stream_index]->time_base,
6831 AV_TIME_BASE_Q);
6832 if ((mov->max_fragment_duration &&
6833 frag_duration >= mov->max_fragment_duration) ||
6834 (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) ||
6835 (mov->flags & FF_MOV_FLAG_FRAG_KEYFRAME &&
6836 par->codec_type == AVMEDIA_TYPE_VIDEO &&
6837 trk->entry && pkt->flags & AV_PKT_FLAG_KEY) ||
6838 (mov->flags & FF_MOV_FLAG_FRAG_EVERY_FRAME)) {
6839 if (frag_duration >= mov->min_fragment_duration) {
6840 if (trk->entry) {
6841 // Set the duration of this track to line up with the next
6842 // sample in this track. This avoids relying on AVPacket
6843 // duration, but only helps for this particular track, not
6844 // for the other ones that are flushed at the same time.
6845 //
6846 // If we have trk->entry == 0, no fragment will be written
6847 // for this track, and we can't adjust the track end here.
6848 trk->track_duration = pkt->dts - trk->start_dts;
6849 if (pkt->pts != AV_NOPTS_VALUE)
6850 trk->end_pts = pkt->pts;
6851 else
6852 trk->end_pts = pkt->dts;
6853 trk->end_reliable = 1;
6854 }
6855 mov_auto_flush_fragment(s, 0);
6856 }
6857 }
6858
6859 return ff_mov_write_packet(s, pkt);
6860 }
6861
6862 static int mov_write_subtitle_end_packet(AVFormatContext *s,
6863 int stream_index,
6864 int64_t dts) {
6865 MOVMuxContext *mov = s->priv_data;
6866 AVPacket *end = mov->pkt;
6867 uint8_t data[2] = {0};
6868 int ret;
6869
6870 end->size = sizeof(data);
6871 end->data = data;
6872 end->pts = dts;
6873 end->dts = dts;
6874 end->duration = 0;
6875 end->stream_index = stream_index;
6876
6877 ret = mov_write_single_packet(s, end);
6878 av_packet_unref(end);
6879
6880 return ret;
6881 }
6882
6883 static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
6884 {
6885 MOVMuxContext *mov = s->priv_data;
6886 MOVTrack *trk;
6887
6888 if (!pkt) {
6889 mov_flush_fragment(s, 1);
6890 return 1;
6891 }
6892
6893 trk = &mov->tracks[pkt->stream_index];
6894
6895 if (is_cover_image(trk->st)) {
6896 int ret;
6897
6898 if (trk->st->nb_frames >= 1) {
6899 if (trk->st->nb_frames == 1)
6900 av_log(s, AV_LOG_WARNING, "Got more than one picture in stream %d,"
6901 " ignoring.\n", pkt->stream_index);
6902 return 0;
6903 }
6904
6905 if ((ret = av_packet_ref(trk->cover_image, pkt)) < 0)
6906 return ret;
6907
6908 return 0;
6909 } else {
6910 int i;
6911
6912 if (!pkt->size)
6913 return mov_write_single_packet(s, pkt); /* Passthrough. */
6914
6915 /*
6916 * Subtitles require special handling.
6917 *
6918 * 1) For full complaince, every track must have a sample at
6919 * dts == 0, which is rarely true for subtitles. So, as soon
6920 * as we see any packet with dts > 0, write an empty subtitle
6921 * at dts == 0 for any subtitle track with no samples in it.
6922 *
6923 * 2) For each subtitle track, check if the current packet's
6924 * dts is past the duration of the last subtitle sample. If
6925 * so, we now need to write an end sample for that subtitle.
6926 *
6927 * This must be done conditionally to allow for subtitles that
6928 * immediately replace each other, in which case an end sample
6929 * is not needed, and is, in fact, actively harmful.
6930 *
6931 * 3) See mov_write_trailer for how the final end sample is
6932 * handled.
6933 */
6934 for (i = 0; i < mov->nb_streams; i++) {
6935 MOVTrack *trk = &mov->tracks[i];
6936 int ret;
6937
6938 if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
6939 trk->track_duration < pkt->dts &&
6940 (trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
6941 ret = mov_write_subtitle_end_packet(s, i, trk->track_duration);
6942 if (ret < 0) return ret;
6943 trk->last_sample_is_subtitle_end = 1;
6944 }
6945 }
6946
6947 if (trk->squash_fragment_samples_to_one) {
6948 /*
6949 * If the track has to have its samples squashed into one sample,
6950 * we just take it into the track's queue.
6951 * This will then be utilized as the samples get written in either
6952 * mov_flush_fragment or when the mux is finalized in
6953 * mov_write_trailer.
6954 */
6955 int ret = AVERROR_BUG;
6956
6957 if (pkt->pts == AV_NOPTS_VALUE) {
6958 av_log(s, AV_LOG_ERROR,
6959 "Packets without a valid presentation timestamp are "
6960 "not supported with packet squashing!\n");
6961 return AVERROR(EINVAL);
6962 }
6963
6964 /* The following will reset pkt and is only allowed to be used
6965 * because we return immediately. afterwards. */
6966 if ((ret = avpriv_packet_list_put(&trk->squashed_packet_queue,
6967 pkt, NULL, 0)) < 0) {
6968 return ret;
6969 }
6970
6971 return 0;
6972 }
6973
6974
6975 if (trk->mode == MODE_MOV && trk->par->codec_type == AVMEDIA_TYPE_VIDEO) {
6976 AVPacket *opkt = pkt;
6977 int reshuffle_ret, ret;
6978 if (trk->is_unaligned_qt_rgb) {
6979 int64_t bpc = trk->par->bits_per_coded_sample != 15 ? trk->par->bits_per_coded_sample : 16;
6980 int expected_stride = ((trk->par->width * bpc + 15) >> 4)*2;
6981 reshuffle_ret = ff_reshuffle_raw_rgb(s, &pkt, trk->par, expected_stride);
6982 if (reshuffle_ret < 0)
6983 return reshuffle_ret;
6984 } else
6985 reshuffle_ret = 0;
6986 if (trk->par->format == AV_PIX_FMT_PAL8 && !trk->pal_done) {
6987 ret = ff_get_packet_palette(s, opkt, reshuffle_ret, trk->palette);
6988 if (ret < 0)
6989 goto fail;
6990 if (ret)
6991 trk->pal_done++;
6992 } else if (trk->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
6993 (trk->par->format == AV_PIX_FMT_GRAY8 ||
6994 trk->par->format == AV_PIX_FMT_MONOBLACK)) {
6995 ret = av_packet_make_writable(pkt);
6996 if (ret < 0)
6997 goto fail;
6998 for (i = 0; i < pkt->size; i++)
6999 pkt->data[i] = ~pkt->data[i];
7000 }
7001 if (reshuffle_ret) {
7002 ret = mov_write_single_packet(s, pkt);
7003 fail:
7004 if (reshuffle_ret)
7005 av_packet_free(&pkt);
7006 return ret;
7007 }
7008 }
7009
7010 return mov_write_single_packet(s, pkt);
7011 }
7012 }
7013
7014 // QuickTime chapters involve an additional text track with the chapter names
7015 // as samples, and a tref pointing from the other tracks to the chapter one.
7016 static int mov_create_chapter_track(AVFormatContext *s, int tracknum)
7017 {
7018 static const uint8_t stub_header[] = {
7019 // TextSampleEntry
7020 0x00, 0x00, 0x00, 0x01, // displayFlags
7021 0x00, 0x00, // horizontal + vertical justification
7022 0x00, 0x00, 0x00, 0x00, // bgColourRed/Green/Blue/Alpha
7023 // BoxRecord
7024 0x00, 0x00, 0x00, 0x00, // defTextBoxTop/Left
7025 0x00, 0x00, 0x00, 0x00, // defTextBoxBottom/Right
7026 // StyleRecord
7027 0x00, 0x00, 0x00, 0x00, // startChar + endChar
7028 0x00, 0x01, // fontID
7029 0x00, 0x00, // fontStyleFlags + fontSize
7030 0x00, 0x00, 0x00, 0x00, // fgColourRed/Green/Blue/Alpha
7031 // FontTableBox
7032 0x00, 0x00, 0x00, 0x0D, // box size
7033 'f', 't', 'a', 'b', // box atom name
7034 0x00, 0x01, // entry count
7035 // FontRecord
7036 0x00, 0x01, // font ID
7037 0x00, // font name length
7038 };
7039 MOVMuxContext *mov = s->priv_data;
7040 MOVTrack *track = &mov->tracks[tracknum];
7041 AVPacket *pkt = mov->pkt;
7042 int i, len;
7043 int ret;
7044
7045 track->mode = mov->mode;
7046 track->tag = MKTAG('t','e','x','t');
7047 track->timescale = mov->movie_timescale;
7048 track->par = avcodec_parameters_alloc();
7049 if (!track->par)
7050 return AVERROR(ENOMEM);
7051 track->par->codec_type = AVMEDIA_TYPE_SUBTITLE;
7052 ret = ff_alloc_extradata(track->par, sizeof(stub_header));
7053 if (ret < 0)
7054 return ret;
7055 memcpy(track->par->extradata, stub_header, sizeof(stub_header));
7056
7057 pkt->stream_index = tracknum;
7058 pkt->flags = AV_PKT_FLAG_KEY;
7059
7060 for (i = 0; i < s->nb_chapters; i++) {
7061 AVChapter *c = s->chapters[i];
7062 AVDictionaryEntry *t;
7063
7064 int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,mov->movie_timescale});
7065 pkt->pts = pkt->dts = av_rescale_q(c->start, c->time_base, (AVRational){1,mov->movie_timescale});
7066 pkt->duration = end - pkt->dts;
7067
7068 if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
7069 static const char encd[12] = {
7070 0x00, 0x00, 0x00, 0x0C,
7071 'e', 'n', 'c', 'd',
7072 0x00, 0x00, 0x01, 0x00 };
7073 len = strlen(t->value);
7074 pkt->size = len + 2 + 12;
7075 pkt->data = av_malloc(pkt->size);
7076 if (!pkt->data) {
7077 av_packet_unref(pkt);
7078 return AVERROR(ENOMEM);
7079 }
7080 AV_WB16(pkt->data, len);
7081 memcpy(pkt->data + 2, t->value, len);
7082 memcpy(pkt->data + len + 2, encd, sizeof(encd));
7083 ff_mov_write_packet(s, pkt);
7084 av_freep(&pkt->data);
7085 }
7086 }
7087
7088 av_packet_unref(mov->pkt);
7089
7090 return 0;
7091 }
7092
7093
7094 static int mov_check_timecode_track(AVFormatContext *s, AVTimecode *tc, int src_index, const char *tcstr)
7095 {
7096 int ret;
7097
7098 /* compute the frame number */
7099 ret = av_timecode_init_from_string(tc, s->streams[src_index]->avg_frame_rate, tcstr, s);
7100 return ret;
7101 }
7102
7103 static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, AVTimecode tc)
7104 {
7105 MOVMuxContext *mov = s->priv_data;
7106 MOVTrack *track = &mov->tracks[index];
7107 AVStream *src_st = s->streams[src_index];
7108 uint8_t data[4];
7109 AVPacket *pkt = mov->pkt;
7110 AVRational rate = src_st->avg_frame_rate;
7111 int ret;
7112
7113 /* tmcd track based on video stream */
7114 track->mode = mov->mode;
7115 track->tag = MKTAG('t','m','c','d');
7116 track->src_track = src_index;
7117 track->timescale = mov->tracks[src_index].timescale;
7118 if (tc.flags & AV_TIMECODE_FLAG_DROPFRAME)
7119 track->timecode_flags |= MOV_TIMECODE_FLAG_DROPFRAME;
7120
7121 /* set st to src_st for metadata access*/
7122 track->st = src_st;
7123
7124 /* encode context: tmcd data stream */
7125 track->par = avcodec_parameters_alloc();
7126 if (!track->par)
7127 return AVERROR(ENOMEM);
7128 track->par->codec_type = AVMEDIA_TYPE_DATA;
7129 track->par->codec_tag = track->tag;
7130 track->st->avg_frame_rate = rate;
7131
7132 /* the tmcd track just contains one packet with the frame number */
7133 pkt->data = data;
7134 pkt->stream_index = index;
7135 pkt->flags = AV_PKT_FLAG_KEY;
7136 pkt->pts = pkt->dts = av_rescale_q(tc.start, av_inv_q(rate), (AVRational){1,mov->movie_timescale});
7137 pkt->size = 4;
7138 AV_WB32(pkt->data, tc.start);
7139 ret = ff_mov_write_packet(s, pkt);
7140 av_packet_unref(pkt);
7141 return ret;
7142 }
7143
7144 #ifdef OHOS_TIMED_META_TRACK
7145 static int mov_create_timed_metadata_track(AVFormatContext *s, int index, int src_index)
7146 {
7147 MOVMuxContext *mov = s->priv_data;
7148 MOVTrack *track = &mov->tracks[index];
7149 AVStream *src_st = s->streams[src_index];
7150 AVRational rate = src_st->avg_frame_rate;
7151 int ret;
7152 int track_tag = MKTAG('c','d','s','c');
7153
7154 /* timed metadata track based on video stream */
7155 track->mode = mov->mode;
7156 /* if the timed metadata track describes characteristics of the whole movie,
7157 * there should be no track reference of type 'cdsc'.
7158 */
7159 if (src_index >= 0) {
7160 MOVTrack *src_track = &mov->tracks[src_index];
7161 track->tag = track_tag;
7162 track->tref_tag = (unsigned int)track_tag;
7163 track->src_track = src_index;
7164 track->timescale = mov->tracks[src_index].timescale;
7165 int new_track_count = track->ref_track_count + 1;
7166 ret = av_reallocp_array(&track->tref_ids, new_track_count, sizeof(int)); // track->tref_ids为int数组
7167 if (ret < 0)
7168 return ret;
7169 track->ref_track_count = new_track_count;
7170 track->tref_ids[track->ref_track_count - 1] = src_track->track_id;
7171 }
7172
7173 /* set st to src_st for metadata access*/
7174 track->st = s->streams[index];
7175
7176 track->par = avcodec_parameters_alloc();
7177 if (!track->par)
7178 return AVERROR(ENOMEM);
7179 track->par->codec_type = AVMEDIA_TYPE_TIMEDMETA;
7180 track->par->codec_id = AV_CODEC_ID_FFMETADATA;
7181 track->par->codec_tag = (unsigned int)track_tag;
7182 track->st->avg_frame_rate = av_inv_q(rate);
7183 return 0;
7184 }
7185 #endif
7186
7187 /*
7188 * st->disposition controls the "enabled" flag in the tkhd tag.
7189 * QuickTime will not play a track if it is not enabled. So make sure
7190 * that one track of each type (audio, video, subtitle) is enabled.
7191 *
7192 * Subtitles are special. For audio and video, setting "enabled" also
7193 * makes the track "default" (i.e. it is rendered when played). For
7194 * subtitles, an "enabled" subtitle is not rendered by default, but
7195 * if no subtitle is enabled, the subtitle menu in QuickTime will be
7196 * empty!
7197 */
7198 static void enable_tracks(AVFormatContext *s)
7199 {
7200 MOVMuxContext *mov = s->priv_data;
7201 int i;
7202 int enabled[AVMEDIA_TYPE_NB];
7203 int first[AVMEDIA_TYPE_NB];
7204
7205 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
7206 enabled[i] = 0;
7207 first[i] = -1;
7208 }
7209
7210 for (i = 0; i < s->nb_streams; i++) {
7211 AVStream *st = s->streams[i];
7212
7213 if (st->codecpar->codec_type <= AVMEDIA_TYPE_UNKNOWN ||
7214 st->codecpar->codec_type >= AVMEDIA_TYPE_NB ||
7215 is_cover_image(st))
7216 continue;
7217
7218 if (first[st->codecpar->codec_type] < 0)
7219 first[st->codecpar->codec_type] = i;
7220 if (st->disposition & AV_DISPOSITION_DEFAULT) {
7221 mov->tracks[i].flags |= MOV_TRACK_ENABLED;
7222 enabled[st->codecpar->codec_type]++;
7223 }
7224 }
7225
7226 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
7227 switch (i) {
7228 case AVMEDIA_TYPE_VIDEO:
7229 case AVMEDIA_TYPE_AUDIO:
7230 case AVMEDIA_TYPE_SUBTITLE:
7231 if (enabled[i] > 1)
7232 mov->per_stream_grouping = 1;
7233 if (!enabled[i] && first[i] >= 0)
7234 mov->tracks[first[i]].flags |= MOV_TRACK_ENABLED;
7235 break;
7236 }
7237 }
7238 }
7239
7240 static void mov_free(AVFormatContext *s)
7241 {
7242 MOVMuxContext *mov = s->priv_data;
7243 int i;
7244
7245 if (!mov->tracks)
7246 return;
7247
7248 if (mov->chapter_track) {
7249 avcodec_parameters_free(&mov->tracks[mov->chapter_track].par);
7250 }
7251
7252 for (i = 0; i < mov->nb_streams; i++) {
7253 MOVTrack *const track = &mov->tracks[i];
7254
7255 if (track->tag == MKTAG('r','t','p',' '))
7256 ff_mov_close_hinting(track);
7257 else if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd)
7258 av_freep(&track->par);
7259 av_freep(&track->cluster);
7260 av_freep(&track->frag_info);
7261 av_packet_free(&track->cover_image);
7262
7263 if (track->eac3_priv) {
7264 struct eac3_info *info = track->eac3_priv;
7265 av_packet_free(&info->pkt);
7266 av_freep(&track->eac3_priv);
7267 }
7268 if (track->vos_len)
7269 av_freep(&track->vos_data);
7270
7271 ff_mov_cenc_free(&track->cenc);
7272 ffio_free_dyn_buf(&track->mdat_buf);
7273
7274 avpriv_packet_list_free(&track->squashed_packet_queue);
7275 #ifdef OHOS_TIMED_META_TRACK
7276 av_freep(&track->tref_ids);
7277 #endif
7278 }
7279
7280 av_freep(&mov->tracks);
7281 ffio_free_dyn_buf(&mov->mdat_buf);
7282 }
7283
7284 static uint32_t rgb_to_yuv(uint32_t rgb)
7285 {
7286 uint8_t r, g, b;
7287 int y, cb, cr;
7288
7289 r = (rgb >> 16) & 0xFF;
7290 g = (rgb >> 8) & 0xFF;
7291 b = (rgb ) & 0xFF;
7292
7293 y = av_clip_uint8(( 16000 + 257 * r + 504 * g + 98 * b)/1000);
7294 cb = av_clip_uint8((128000 - 148 * r - 291 * g + 439 * b)/1000);
7295 cr = av_clip_uint8((128000 + 439 * r - 368 * g - 71 * b)/1000);
7296
7297 return (y << 16) | (cr << 8) | cb;
7298 }
7299
7300 static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track,
7301 AVStream *st)
7302 {
7303 int i, width = 720, height = 480;
7304 int have_palette = 0, have_size = 0;
7305 uint32_t palette[16];
7306 char *cur = st->codecpar->extradata;
7307
7308 while (cur && *cur) {
7309 if (strncmp("palette:", cur, 8) == 0) {
7310 int i, count;
7311 count = sscanf(cur + 8,
7312 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
7313 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
7314 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
7315 "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32"",
7316 &palette[ 0], &palette[ 1], &palette[ 2], &palette[ 3],
7317 &palette[ 4], &palette[ 5], &palette[ 6], &palette[ 7],
7318 &palette[ 8], &palette[ 9], &palette[10], &palette[11],
7319 &palette[12], &palette[13], &palette[14], &palette[15]);
7320
7321 for (i = 0; i < count; i++) {
7322 palette[i] = rgb_to_yuv(palette[i]);
7323 }
7324 have_palette = 1;
7325 } else if (!strncmp("size:", cur, 5)) {
7326 sscanf(cur + 5, "%dx%d", &width, &height);
7327 have_size = 1;
7328 }
7329 if (have_palette && have_size)
7330 break;
7331 cur += strcspn(cur, "\n\r");
7332 cur += strspn(cur, "\n\r");
7333 }
7334 if (have_palette) {
7335 track->vos_data = av_malloc(16*4 + AV_INPUT_BUFFER_PADDING_SIZE);
7336 if (!track->vos_data)
7337 return AVERROR(ENOMEM);
7338 for (i = 0; i < 16; i++) {
7339 AV_WB32(track->vos_data + i * 4, palette[i]);
7340 }
7341 memset(track->vos_data + 16*4, 0, AV_INPUT_BUFFER_PADDING_SIZE);
7342 track->vos_len = 16 * 4;
7343 }
7344 st->codecpar->width = width;
7345 st->codecpar->height = track->height = height;
7346
7347 return 0;
7348 }
7349
7350 static int mov_init(AVFormatContext *s)
7351 {
7352 MOVMuxContext *mov = s->priv_data;
7353 int i, ret;
7354
7355 mov->fc = s;
7356 mov->pkt = ffformatcontext(s)->pkt;
7357
7358 /* Default mode == MP4 */
7359 mov->mode = MODE_MP4;
7360
7361 #define IS_MODE(muxer, config) (CONFIG_ ## config ## _MUXER && !strcmp(#muxer, s->oformat->name))
7362 if (IS_MODE(3gp, TGP)) mov->mode = MODE_3GP;
7363 else if (IS_MODE(3g2, TG2)) mov->mode = MODE_3GP|MODE_3G2;
7364 else if (IS_MODE(mov, MOV)) mov->mode = MODE_MOV;
7365 else if (IS_MODE(psp, PSP)) mov->mode = MODE_PSP;
7366 else if (IS_MODE(ipod, IPOD)) mov->mode = MODE_IPOD;
7367 else if (IS_MODE(ismv, ISMV)) mov->mode = MODE_ISM;
7368 else if (IS_MODE(f4v, F4V)) mov->mode = MODE_F4V;
7369 else if (IS_MODE(avif, AVIF)) mov->mode = MODE_AVIF;
7370 #undef IS_MODE
7371
7372 if (mov->flags & FF_MOV_FLAG_DELAY_MOOV)
7373 mov->flags |= FF_MOV_FLAG_EMPTY_MOOV;
7374
7375 if (mov->mode == MODE_AVIF)
7376 mov->flags |= FF_MOV_FLAG_DELAY_MOOV;
7377
7378 /* Set the FRAGMENT flag if any of the fragmentation methods are
7379 * enabled. */
7380 if (mov->max_fragment_duration || mov->max_fragment_size ||
7381 mov->flags & (FF_MOV_FLAG_EMPTY_MOOV |
7382 FF_MOV_FLAG_FRAG_KEYFRAME |
7383 FF_MOV_FLAG_FRAG_CUSTOM |
7384 FF_MOV_FLAG_FRAG_EVERY_FRAME))
7385 mov->flags |= FF_MOV_FLAG_FRAGMENT;
7386
7387 /* Set other implicit flags immediately */
7388 if (mov->mode == MODE_ISM)
7389 mov->flags |= FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_SEPARATE_MOOF |
7390 FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS;
7391 if (mov->flags & FF_MOV_FLAG_DASH)
7392 mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV |
7393 FF_MOV_FLAG_DEFAULT_BASE_MOOF;
7394 if (mov->flags & FF_MOV_FLAG_CMAF)
7395 mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV |
7396 FF_MOV_FLAG_DEFAULT_BASE_MOOF | FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS;
7397
7398 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && s->flags & AVFMT_FLAG_AUTO_BSF) {
7399 av_log(s, AV_LOG_VERBOSE, "Empty MOOV enabled; disabling automatic bitstream filtering\n");
7400 s->flags &= ~AVFMT_FLAG_AUTO_BSF;
7401 }
7402
7403 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX && mov->flags & FF_MOV_FLAG_SKIP_SIDX) {
7404 av_log(s, AV_LOG_WARNING, "Global SIDX enabled; Ignoring skip_sidx option\n");
7405 mov->flags &= ~FF_MOV_FLAG_SKIP_SIDX;
7406 }
7407
7408 if (mov->flags & FF_MOV_FLAG_FASTSTART) {
7409 mov->reserved_moov_size = -1;
7410 }
7411
7412 if (mov->use_editlist < 0) {
7413 mov->use_editlist = 1;
7414 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
7415 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
7416 // If we can avoid needing an edit list by shifting the
7417 // tracks, prefer that over (trying to) write edit lists
7418 // in fragmented output.
7419 if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO ||
7420 s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO)
7421 mov->use_editlist = 0;
7422 }
7423 if (mov->flags & FF_MOV_FLAG_CMAF) {
7424 // CMAF Track requires negative cts offsets without edit lists
7425 mov->use_editlist = 0;
7426 }
7427 }
7428 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
7429 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV) && mov->use_editlist)
7430 av_log(s, AV_LOG_WARNING, "No meaningful edit list will be written when using empty_moov without delay_moov\n");
7431
7432 if (mov->flags & FF_MOV_FLAG_CMAF && mov->use_editlist) {
7433 av_log(s, AV_LOG_WARNING, "Edit list enabled; Assuming writing CMAF Track File\n");
7434 mov->flags &= ~FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS;
7435 }
7436 if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO &&
7437 !(mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS))
7438 s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO;
7439
7440 /* Clear the omit_tfhd_offset flag if default_base_moof is set;
7441 * if the latter is set that's enough and omit_tfhd_offset doesn't
7442 * add anything extra on top of that. */
7443 if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET &&
7444 mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
7445 mov->flags &= ~FF_MOV_FLAG_OMIT_TFHD_OFFSET;
7446
7447 if (mov->frag_interleave &&
7448 mov->flags & (FF_MOV_FLAG_OMIT_TFHD_OFFSET | FF_MOV_FLAG_SEPARATE_MOOF)) {
7449 av_log(s, AV_LOG_ERROR,
7450 "Sample interleaving in fragments is mutually exclusive with "
7451 "omit_tfhd_offset and separate_moof\n");
7452 return AVERROR(EINVAL);
7453 }
7454
7455 /* Non-seekable output is ok if using fragmentation. If ism_lookahead
7456 * is enabled, we don't support non-seekable output at all. */
7457 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
7458 (!(mov->flags & FF_MOV_FLAG_FRAGMENT) || mov->ism_lookahead ||
7459 mov->mode == MODE_AVIF)) {
7460 av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
7461 return AVERROR(EINVAL);
7462 }
7463
7464 /* AVIF output must have at most two video streams (one for YUV and one for
7465 * alpha). */
7466 if (mov->mode == MODE_AVIF) {
7467 if (s->nb_streams > 2) {
7468 av_log(s, AV_LOG_ERROR, "AVIF output requires exactly one or two streams\n");
7469 return AVERROR(EINVAL);
7470 }
7471 if (s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
7472 (s->nb_streams > 1 && s->streams[1]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)) {
7473 av_log(s, AV_LOG_ERROR, "AVIF output supports only video streams\n");
7474 return AVERROR(EINVAL);
7475 }
7476 if (s->nb_streams > 1) {
7477 const AVPixFmtDescriptor *pixdesc =
7478 av_pix_fmt_desc_get(s->streams[1]->codecpar->format);
7479 if (pixdesc->nb_components != 1) {
7480 av_log(s, AV_LOG_ERROR, "Second stream for AVIF (alpha) output must have exactly one plane\n");
7481 return AVERROR(EINVAL);
7482 }
7483 }
7484 s->streams[0]->disposition |= AV_DISPOSITION_DEFAULT;
7485 }
7486
7487 mov->nb_streams = s->nb_streams;
7488 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
7489 mov->chapter_track = mov->nb_streams++;
7490
7491 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
7492 for (i = 0; i < s->nb_streams; i++)
7493 if (rtp_hinting_needed(s->streams[i]))
7494 mov->nb_streams++;
7495 }
7496
7497 if (mov->write_btrt < 0) {
7498 mov->write_btrt = mov->mode == MODE_MP4;
7499 }
7500
7501 if ( mov->write_tmcd == -1 && (mov->mode == MODE_MOV || mov->mode == MODE_MP4)
7502 || mov->write_tmcd == 1) {
7503 AVDictionaryEntry *global_tcr = av_dict_get(s->metadata, "timecode",
7504 NULL, 0);
7505
7506 /* +1 tmcd track for each video stream with a timecode */
7507 for (i = 0; i < s->nb_streams; i++) {
7508 AVStream *st = s->streams[i];
7509 AVDictionaryEntry *t = global_tcr;
7510 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
7511 (t || (t=av_dict_get(st->metadata, "timecode", NULL, 0)))) {
7512 AVTimecode tc;
7513 ret = mov_check_timecode_track(s, &tc, i, t->value);
7514 if (ret >= 0)
7515 mov->nb_meta_tmcd++;
7516 }
7517 }
7518
7519 /* check if there is already a tmcd track to remux */
7520 if (mov->nb_meta_tmcd) {
7521 for (i = 0; i < s->nb_streams; i++) {
7522 AVStream *st = s->streams[i];
7523 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
7524 av_log(s, AV_LOG_WARNING, "You requested a copy of the original timecode track "
7525 "so timecode metadata are now ignored\n");
7526 mov->nb_meta_tmcd = 0;
7527 }
7528 }
7529 }
7530
7531 mov->nb_streams += mov->nb_meta_tmcd;
7532 }
7533
7534 #ifdef OHOS_TIMED_META_TRACK
7535 if ((unsigned int)mov->flags & FF_MOV_FLAG_TIMED_METADATA) {
7536 for (i = 0; i < (int)s->nb_streams; i++) {
7537 AVStream *st = s->streams[i];
7538 if (st->codecpar->codec_type == AVMEDIA_TYPE_TIMEDMETA)
7539 mov->nb_timed_metadata_track++;
7540 }
7541 }
7542 #endif
7543 // Reserve an extra stream for chapters for the case where chapters
7544 // are written in the trailer
7545 mov->tracks = av_calloc(mov->nb_streams + 1, sizeof(*mov->tracks));
7546 if (!mov->tracks)
7547 return AVERROR(ENOMEM);
7548
7549 if (mov->encryption_scheme_str != NULL && strcmp(mov->encryption_scheme_str, "none") != 0) {
7550 if (strcmp(mov->encryption_scheme_str, "cenc-aes-ctr") == 0) {
7551 mov->encryption_scheme = MOV_ENC_CENC_AES_CTR;
7552
7553 if (mov->encryption_key_len != AES_CTR_KEY_SIZE) {
7554 av_log(s, AV_LOG_ERROR, "Invalid encryption key len %d expected %d\n",
7555 mov->encryption_key_len, AES_CTR_KEY_SIZE);
7556 return AVERROR(EINVAL);
7557 }
7558
7559 if (mov->encryption_kid_len != CENC_KID_SIZE) {
7560 av_log(s, AV_LOG_ERROR, "Invalid encryption kid len %d expected %d\n",
7561 mov->encryption_kid_len, CENC_KID_SIZE);
7562 return AVERROR(EINVAL);
7563 }
7564 } else {
7565 av_log(s, AV_LOG_ERROR, "unsupported encryption scheme %s\n",
7566 mov->encryption_scheme_str);
7567 return AVERROR(EINVAL);
7568 }
7569 }
7570
7571 for (i = 0; i < s->nb_streams; i++) {
7572 AVStream *st= s->streams[i];
7573 MOVTrack *track= &mov->tracks[i];
7574 AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
7575
7576 track->st = st;
7577 track->par = st->codecpar;
7578 track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
7579 if (track->language < 0)
7580 track->language = 32767; // Unspecified Macintosh language code
7581 track->mode = mov->mode;
7582 track->tag = mov_find_codec_tag(s, track);
7583 if (!track->tag) {
7584 av_log(s, AV_LOG_ERROR, "Could not find tag for codec %s in stream #%d, "
7585 "codec not currently supported in container\n",
7586 avcodec_get_name(st->codecpar->codec_id), i);
7587 return AVERROR(EINVAL);
7588 }
7589 /* If hinting of this track is enabled by a later hint track,
7590 * this is updated. */
7591 track->hint_track = -1;
7592 track->start_dts = AV_NOPTS_VALUE;
7593 track->start_cts = AV_NOPTS_VALUE;
7594 track->end_pts = AV_NOPTS_VALUE;
7595 track->dts_shift = AV_NOPTS_VALUE;
7596 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
7597 if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
7598 track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
7599 track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
7600 if (st->codecpar->width != 720 || (st->codecpar->height != 608 && st->codecpar->height != 512)) {
7601 av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
7602 return AVERROR(EINVAL);
7603 }
7604 track->height = track->tag >> 24 == 'n' ? 486 : 576;
7605 }
7606 if (mov->video_track_timescale) {
7607 track->timescale = mov->video_track_timescale;
7608 if (mov->mode == MODE_ISM && mov->video_track_timescale != 10000000)
7609 av_log(s, AV_LOG_WARNING, "Warning: some tools, like mp4split, assume a timescale of 10000000 for ISMV.\n");
7610 } else {
7611 track->timescale = st->time_base.den;
7612 while(track->timescale < 10000)
7613 track->timescale *= 2;
7614 }
7615 if (st->codecpar->width > 65535 || st->codecpar->height > 65535) {
7616 av_log(s, AV_LOG_ERROR, "Resolution %dx%d too large for mov/mp4\n", st->codecpar->width, st->codecpar->height);
7617 return AVERROR(EINVAL);
7618 }
7619 if (track->mode == MODE_MOV && track->timescale > 100000)
7620 av_log(s, AV_LOG_WARNING,
7621 "WARNING codec timebase is very high. If duration is too long,\n"
7622 "file may not be playable by quicktime. Specify a shorter timebase\n"
7623 "or choose different container.\n");
7624 if (track->mode == MODE_MOV &&
7625 track->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
7626 track->tag == MKTAG('r','a','w',' ')) {
7627 enum AVPixelFormat pix_fmt = track->par->format;
7628 if (pix_fmt == AV_PIX_FMT_NONE && track->par->bits_per_coded_sample == 1)
7629 pix_fmt = AV_PIX_FMT_MONOWHITE;
7630 track->is_unaligned_qt_rgb =
7631 pix_fmt == AV_PIX_FMT_RGB24 ||
7632 pix_fmt == AV_PIX_FMT_BGR24 ||
7633 pix_fmt == AV_PIX_FMT_PAL8 ||
7634 pix_fmt == AV_PIX_FMT_GRAY8 ||
7635 pix_fmt == AV_PIX_FMT_MONOWHITE ||
7636 pix_fmt == AV_PIX_FMT_MONOBLACK;
7637 }
7638 if (track->par->codec_id == AV_CODEC_ID_VP9 && track->mode != MODE_MP4) {
7639 av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id));
7640 return AVERROR(EINVAL);
7641 } else if (track->par->codec_id == AV_CODEC_ID_AV1 &&
7642 track->mode != MODE_MP4 && track->mode != MODE_AVIF) {
7643 av_log(s, AV_LOG_ERROR, "%s only supported in MP4 and AVIF.\n", avcodec_get_name(track->par->codec_id));
7644 return AVERROR(EINVAL);
7645 } else if (track->par->codec_id == AV_CODEC_ID_VP8) {
7646 /* altref frames handling is not defined in the spec as of version v1.0,
7647 * so just forbid muxing VP8 streams altogether until a new version does */
7648 av_log(s, AV_LOG_ERROR, "VP8 muxing is currently not supported.\n");
7649 return AVERROR_PATCHWELCOME;
7650 }
7651 if (is_cover_image(st)) {
7652 track->cover_image = av_packet_alloc();
7653 if (!track->cover_image)
7654 return AVERROR(ENOMEM);
7655 }
7656 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
7657 track->timescale = st->codecpar->sample_rate;
7658 if (!st->codecpar->frame_size && !av_get_bits_per_sample(st->codecpar->codec_id)) {
7659 av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i);
7660 track->audio_vbr = 1;
7661 }else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_MS ||
7662 st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
7663 st->codecpar->codec_id == AV_CODEC_ID_ILBC){
7664 if (!st->codecpar->block_align) {
7665 av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
7666 return AVERROR(EINVAL);
7667 }
7668 track->sample_size = st->codecpar->block_align;
7669 }else if (st->codecpar->frame_size > 1){ /* assume compressed audio */
7670 track->audio_vbr = 1;
7671 }else{
7672 track->sample_size = (av_get_bits_per_sample(st->codecpar->codec_id) >> 3) *
7673 st->codecpar->ch_layout.nb_channels;
7674 }
7675 if (st->codecpar->codec_id == AV_CODEC_ID_ILBC ||
7676 st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_QT) {
7677 track->audio_vbr = 1;
7678 }
7679 if (track->mode != MODE_MOV &&
7680 track->par->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) {
7681 if (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
7682 av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not standard, to mux anyway set strict to -1\n",
7683 i, track->par->sample_rate);
7684 return AVERROR(EINVAL);
7685 } else {
7686 av_log(s, AV_LOG_WARNING, "track %d: muxing mp3 at %dhz is not standard in MP4\n",
7687 i, track->par->sample_rate);
7688 }
7689 }
7690 if (track->par->codec_id == AV_CODEC_ID_FLAC ||
7691 track->par->codec_id == AV_CODEC_ID_TRUEHD ||
7692 track->par->codec_id == AV_CODEC_ID_OPUS) {
7693 if (track->mode != MODE_MP4) {
7694 av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id));
7695 return AVERROR(EINVAL);
7696 }
7697 if (track->par->codec_id != AV_CODEC_ID_OPUS &&
7698 s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
7699 av_log(s, AV_LOG_ERROR,
7700 "%s in MP4 support is experimental, add "
7701 "'-strict %d' if you want to use it.\n",
7702 avcodec_get_name(track->par->codec_id), FF_COMPLIANCE_EXPERIMENTAL);
7703 return AVERROR_EXPERIMENTAL;
7704 }
7705 }
7706 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
7707 track->timescale = st->time_base.den;
7708
7709 if (track->par->codec_id == AV_CODEC_ID_TTML) {
7710 /* 14496-30 requires us to use a single sample per fragment
7711 for TTML, for which we define a per-track flag.
7712
7713 We set the flag in case we are receiving TTML paragraphs
7714 from the input, in other words in case we are not doing
7715 stream copy. */
7716 track->squash_fragment_samples_to_one =
7717 ff_is_ttml_stream_paragraph_based(track->par);
7718
7719 if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
7720 track->squash_fragment_samples_to_one) {
7721 av_log(s, AV_LOG_ERROR,
7722 "Fragmentation is not currently supported for "
7723 "TTML in MP4/ISMV (track synchronization between "
7724 "subtitles and other media is not yet implemented)!\n");
7725 return AVERROR_PATCHWELCOME;
7726 }
7727
7728 if (track->mode != MODE_ISM &&
7729 track->par->codec_tag == MOV_ISMV_TTML_TAG &&
7730 s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
7731 av_log(s, AV_LOG_ERROR,
7732 "ISMV style TTML support with the 'dfxp' tag in "
7733 "non-ISMV formats is not officially supported. Add "
7734 "'-strict unofficial' if you want to use it.\n");
7735 return AVERROR_EXPERIMENTAL;
7736 }
7737 }
7738 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
7739 track->timescale = st->time_base.den;
7740 #ifdef OHOS_TIMED_META_TRACK
7741 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_TIMEDMETA) {
7742 track->timescale = (unsigned int)st->time_base.den;
7743 #endif
7744 } else {
7745 track->timescale = mov->movie_timescale;
7746 }
7747 if (!track->height)
7748 track->height = st->codecpar->height;
7749 /* The Protected Interoperable File Format (PIFF) standard, used by ISMV recommends but
7750 doesn't mandate a track timescale of 10,000,000. The muxer allows a custom timescale
7751 for video tracks, so if user-set, it isn't overwritten */
7752 if (mov->mode == MODE_ISM &&
7753 (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
7754 (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !mov->video_track_timescale))) {
7755 track->timescale = 10000000;
7756 }
7757
7758 avpriv_set_pts_info(st, 64, 1, track->timescale);
7759
7760 if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) {
7761 ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key,
7762 (track->par->codec_id == AV_CODEC_ID_H264 || track->par->codec_id == AV_CODEC_ID_HEVC),
7763 s->flags & AVFMT_FLAG_BITEXACT);
7764 if (ret)
7765 return ret;
7766 }
7767 }
7768
7769 enable_tracks(s);
7770 return 0;
7771 }
7772
7773 static int mov_write_header(AVFormatContext *s)
7774 {
7775 AVIOContext *pb = s->pb;
7776 MOVMuxContext *mov = s->priv_data;
7777 int i, ret, hint_track = 0, tmcd_track = 0, nb_tracks = s->nb_streams;
7778
7779 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters)
7780 nb_tracks++;
7781
7782 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
7783 hint_track = nb_tracks;
7784 for (i = 0; i < s->nb_streams; i++)
7785 if (rtp_hinting_needed(s->streams[i]))
7786 nb_tracks++;
7787 }
7788
7789 if (mov->nb_meta_tmcd)
7790 tmcd_track = nb_tracks;
7791
7792 for (i = 0; i < s->nb_streams; i++) {
7793 int j;
7794 AVStream *st= s->streams[i];
7795 MOVTrack *track= &mov->tracks[i];
7796
7797 /* copy extradata if it exists */
7798 if (st->codecpar->extradata_size) {
7799 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
7800 mov_create_dvd_sub_decoder_specific_info(track, st);
7801 else if (!TAG_IS_AVCI(track->tag) && st->codecpar->codec_id != AV_CODEC_ID_DNXHD) {
7802 track->vos_len = st->codecpar->extradata_size;
7803 track->vos_data = av_malloc(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
7804 if (!track->vos_data) {
7805 return AVERROR(ENOMEM);
7806 }
7807 memcpy(track->vos_data, st->codecpar->extradata, track->vos_len);
7808 memset(track->vos_data + track->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
7809 }
7810 }
7811
7812 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
7813 av_channel_layout_compare(&track->par->ch_layout,
7814 &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO))
7815 continue;
7816
7817 for (j = 0; j < s->nb_streams; j++) {
7818 AVStream *stj= s->streams[j];
7819 MOVTrack *trackj= &mov->tracks[j];
7820 if (j == i)
7821 continue;
7822
7823 if (stj->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
7824 (trackj->par->ch_layout.nb_channels != 1 ||
7825 !av_channel_layout_compare(&trackj->par->ch_layout,
7826 &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO))
7827 )
7828 track->mono_as_fc = -1;
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->par->ch_layout.nb_channels == 1 && track->mono_as_fc >= 0
7834 )
7835 track->mono_as_fc++;
7836
7837 if (stj->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
7838 av_channel_layout_compare(&trackj->par->ch_layout,
7839 &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO) ||
7840 trackj->language != track->language ||
7841 trackj->tag != track->tag
7842 )
7843 continue;
7844 track->multichannel_as_mono++;
7845 }
7846 }
7847
7848 if (!(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
7849 if ((ret = mov_write_identification(pb, s)) < 0)
7850 return ret;
7851 }
7852
7853 if (mov->reserved_moov_size){
7854 mov->reserved_header_pos = avio_tell(pb);
7855 if (mov->reserved_moov_size > 0)
7856 avio_skip(pb, mov->reserved_moov_size);
7857 }
7858
7859 if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
7860 /* If no fragmentation options have been set, set a default. */
7861 if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME |
7862 FF_MOV_FLAG_FRAG_CUSTOM |
7863 FF_MOV_FLAG_FRAG_EVERY_FRAME)) &&
7864 !mov->max_fragment_duration && !mov->max_fragment_size)
7865 mov->flags |= FF_MOV_FLAG_FRAG_KEYFRAME;
7866 } else if (mov->mode != MODE_AVIF) {
7867 if (mov->flags & FF_MOV_FLAG_FASTSTART)
7868 mov->reserved_header_pos = avio_tell(pb);
7869 mov_write_mdat_tag(pb, mov);
7870 }
7871
7872 ff_parse_creation_time_metadata(s, &mov->time, 1);
7873 if (mov->time)
7874 mov->time += 0x7C25B080; // 1970 based -> 1904 based
7875
7876 if (mov->chapter_track)
7877 if ((ret = mov_create_chapter_track(s, mov->chapter_track)) < 0)
7878 return ret;
7879
7880 if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
7881 for (i = 0; i < s->nb_streams; i++) {
7882 if (rtp_hinting_needed(s->streams[i])) {
7883 if ((ret = ff_mov_init_hinting(s, hint_track, i)) < 0)
7884 return ret;
7885 hint_track++;
7886 }
7887 }
7888 }
7889
7890 if (mov->nb_meta_tmcd) {
7891 const AVDictionaryEntry *t, *global_tcr = av_dict_get(s->metadata,
7892 "timecode", NULL, 0);
7893 /* Initialize the tmcd tracks */
7894 for (i = 0; i < s->nb_streams; i++) {
7895 AVStream *st = s->streams[i];
7896 t = global_tcr;
7897
7898 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
7899 AVTimecode tc;
7900 if (!t)
7901 t = av_dict_get(st->metadata, "timecode", NULL, 0);
7902 if (!t)
7903 continue;
7904 if (mov_check_timecode_track(s, &tc, i, t->value) < 0)
7905 continue;
7906 if ((ret = mov_create_timecode_track(s, tmcd_track, i, tc)) < 0)
7907 return ret;
7908 tmcd_track++;
7909 }
7910 }
7911 }
7912 #ifdef OHOS_TIMED_META_TRACK
7913 if ((unsigned int)mov->flags & FF_MOV_FLAG_TIMED_METADATA) {
7914 for (i = 0; i < s->nb_streams; i++) {
7915 AVStream *st = s->streams[i];
7916 if (st->codecpar->codec_type == AVMEDIA_TYPE_TIMEDMETA) {
7917 const AVDictionaryEntry *t = av_dict_get(st->metadata, "src_track_id", NULL, 0);
7918 if (!t)
7919 continue;
7920 size_t id_len = strlen(t->value);
7921 int track_id = 0;
7922 const int base = 10;
7923 const char start = '0';
7924 for (int j = 0; j < (int)id_len; j++)
7925 track_id = track_id * base + t->value[j] - start;
7926 if ((ret = mov_create_timed_metadata_track(s, i, track_id)) < 0)
7927 return ret;
7928 }
7929 }
7930 }
7931 #endif
7932
7933 avio_flush(pb);
7934
7935 if (mov->flags & FF_MOV_FLAG_ISML)
7936 mov_write_isml_manifest(pb, mov, s);
7937
7938 if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
7939 !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
7940 if ((ret = mov_write_moov_tag(pb, mov, s)) < 0)
7941 return ret;
7942 mov->moov_written = 1;
7943 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)
7944 mov->reserved_header_pos = avio_tell(pb);
7945 }
7946
7947 return 0;
7948 }
7949
7950 static int get_moov_size(AVFormatContext *s)
7951 {
7952 int ret;
7953 AVIOContext *moov_buf;
7954 MOVMuxContext *mov = s->priv_data;
7955
7956 if ((ret = ffio_open_null_buf(&moov_buf)) < 0)
7957 return ret;
7958 if ((ret = mov_write_moov_tag(moov_buf, mov, s)) < 0)
7959 return ret;
7960 return ffio_close_null_buf(moov_buf);
7961 }
7962
7963 static int get_sidx_size(AVFormatContext *s)
7964 {
7965 int ret;
7966 AVIOContext *buf;
7967 MOVMuxContext *mov = s->priv_data;
7968
7969 if ((ret = ffio_open_null_buf(&buf)) < 0)
7970 return ret;
7971 mov_write_sidx_tags(buf, mov, -1, 0);
7972 return ffio_close_null_buf(buf);
7973 }
7974
7975 /*
7976 * This function gets the moov size if moved to the top of the file: the chunk
7977 * offset table can switch between stco (32-bit entries) to co64 (64-bit
7978 * entries) when the moov is moved to the beginning, so the size of the moov
7979 * would change. It also updates the chunk offset tables.
7980 */
7981 static int compute_moov_size(AVFormatContext *s)
7982 {
7983 int i, moov_size, moov_size2;
7984 MOVMuxContext *mov = s->priv_data;
7985
7986 moov_size = get_moov_size(s);
7987 if (moov_size < 0)
7988 return moov_size;
7989
7990 for (i = 0; i < mov->nb_streams; i++)
7991 mov->tracks[i].data_offset += moov_size;
7992
7993 moov_size2 = get_moov_size(s);
7994 if (moov_size2 < 0)
7995 return moov_size2;
7996
7997 /* if the size changed, we just switched from stco to co64 and need to
7998 * update the offsets */
7999 if (moov_size2 != moov_size)
8000 for (i = 0; i < mov->nb_streams; i++)
8001 mov->tracks[i].data_offset += moov_size2 - moov_size;
8002
8003 return moov_size2;
8004 }
8005
8006 static int compute_sidx_size(AVFormatContext *s)
8007 {
8008 int i, sidx_size;
8009 MOVMuxContext *mov = s->priv_data;
8010
8011 sidx_size = get_sidx_size(s);
8012 if (sidx_size < 0)
8013 return sidx_size;
8014
8015 for (i = 0; i < mov->nb_streams; i++)
8016 mov->tracks[i].data_offset += sidx_size;
8017
8018 return sidx_size;
8019 }
8020
8021 static int shift_data(AVFormatContext *s)
8022 {
8023 int moov_size;
8024 MOVMuxContext *mov = s->priv_data;
8025
8026 if (mov->flags & FF_MOV_FLAG_FRAGMENT)
8027 moov_size = compute_sidx_size(s);
8028 else
8029 moov_size = compute_moov_size(s);
8030 if (moov_size < 0)
8031 return moov_size;
8032
8033 return ff_format_shift_data(s, mov->reserved_header_pos, moov_size);
8034 }
8035
8036 static int mov_write_trailer(AVFormatContext *s)
8037 {
8038 MOVMuxContext *mov = s->priv_data;
8039 AVIOContext *pb = s->pb;
8040 int res = 0;
8041 int i;
8042 int64_t moov_pos;
8043
8044 if (mov->need_rewrite_extradata) {
8045 for (i = 0; i < s->nb_streams; i++) {
8046 MOVTrack *track = &mov->tracks[i];
8047 AVCodecParameters *par = track->par;
8048
8049 track->vos_len = par->extradata_size;
8050 av_freep(&track->vos_data);
8051 track->vos_data = av_malloc(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
8052 if (!track->vos_data)
8053 return AVERROR(ENOMEM);
8054 memcpy(track->vos_data, par->extradata, track->vos_len);
8055 memset(track->vos_data + track->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8056 }
8057 mov->need_rewrite_extradata = 0;
8058 }
8059
8060 /*
8061 * Before actually writing the trailer, make sure that there are no
8062 * dangling subtitles, that need a terminating sample.
8063 */
8064 for (i = 0; i < mov->nb_streams; i++) {
8065 MOVTrack *trk = &mov->tracks[i];
8066 if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
8067 !trk->last_sample_is_subtitle_end) {
8068 mov_write_subtitle_end_packet(s, i, trk->track_duration);
8069 trk->last_sample_is_subtitle_end = 1;
8070 }
8071 }
8072
8073 // Check if we have any tracks that require squashing.
8074 // In that case, we'll have to write the packet here.
8075 if ((res = mov_write_squashed_packets(s)) < 0)
8076 return res;
8077
8078 // If there were no chapters when the header was written, but there
8079 // are chapters now, write them in the trailer. This only works
8080 // when we are not doing fragments.
8081 if (!mov->chapter_track && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
8082 if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) {
8083 mov->chapter_track = mov->nb_streams++;
8084 if ((res = mov_create_chapter_track(s, mov->chapter_track)) < 0)
8085 return res;
8086 }
8087 }
8088
8089 if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
8090 moov_pos = avio_tell(pb);
8091
8092 /* Write size of mdat tag */
8093 if (mov->mdat_size + 8 <= UINT32_MAX) {
8094 avio_seek(pb, mov->mdat_pos, SEEK_SET);
8095 avio_wb32(pb, mov->mdat_size + 8);
8096 } else {
8097 /* overwrite 'wide' placeholder atom */
8098 avio_seek(pb, mov->mdat_pos - 8, SEEK_SET);
8099 /* special value: real atom size will be 64 bit value after
8100 * tag field */
8101 avio_wb32(pb, 1);
8102 ffio_wfourcc(pb, "mdat");
8103 avio_wb64(pb, mov->mdat_size + 16);
8104 }
8105 avio_seek(pb, mov->reserved_moov_size > 0 ? mov->reserved_header_pos : moov_pos, SEEK_SET);
8106
8107 if (mov->flags & FF_MOV_FLAG_FASTSTART) {
8108 av_log(s, AV_LOG_INFO, "Starting second pass: moving the moov atom to the beginning of the file\n");
8109 res = shift_data(s);
8110 if (res < 0)
8111 return res;
8112 avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
8113 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
8114 return res;
8115 } else if (mov->reserved_moov_size > 0) {
8116 int64_t size;
8117 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
8118 return res;
8119 size = mov->reserved_moov_size - (avio_tell(pb) - mov->reserved_header_pos);
8120 if (size < 8){
8121 av_log(s, AV_LOG_ERROR, "reserved_moov_size is too small, needed %"PRId64" additional\n", 8-size);
8122 return AVERROR(EINVAL);
8123 }
8124 avio_wb32(pb, size);
8125 ffio_wfourcc(pb, "free");
8126 ffio_fill(pb, 0, size - 8);
8127 avio_seek(pb, moov_pos, SEEK_SET);
8128 } else {
8129 if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
8130 return res;
8131 }
8132 res = 0;
8133 } else {
8134 mov_auto_flush_fragment(s, 1);
8135 for (i = 0; i < mov->nb_streams; i++)
8136 mov->tracks[i].data_offset = 0;
8137 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) {
8138 int64_t end;
8139 av_log(s, AV_LOG_INFO, "Starting second pass: inserting sidx atoms\n");
8140 res = shift_data(s);
8141 if (res < 0)
8142 return res;
8143 end = avio_tell(pb);
8144 avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
8145 mov_write_sidx_tags(pb, mov, -1, 0);
8146 avio_seek(pb, end, SEEK_SET);
8147 }
8148 if (!(mov->flags & FF_MOV_FLAG_SKIP_TRAILER)) {
8149 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
8150 res = mov_write_mfra_tag(pb, mov);
8151 if (res < 0)
8152 return res;
8153 }
8154 }
8155 #ifdef OHOS_OPT_COMPAT
8156 if (res == 0) {
8157 av_log(s, AV_LOG_INFO, "Trailer written successfully.\n");
8158 } else {
8159 av_log(s, AV_LOG_ERROR, "Error writing trailer: %d\n", res);
8160 }
8161 #endif
8162
8163 return res;
8164 }
8165
8166 static int mov_check_bitstream(AVFormatContext *s, AVStream *st,
8167 const AVPacket *pkt)
8168 {
8169 int ret = 1;
8170
8171 if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
8172 if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0)
8173 ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
8174 } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) {
8175 ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
8176 }
8177
8178 return ret;
8179 }
8180
8181 static int avif_write_trailer(AVFormatContext *s)
8182 {
8183 AVIOContext *pb = s->pb;
8184 MOVMuxContext *mov = s->priv_data;
8185 int64_t pos_backup, extent_offsets[2];
8186 uint8_t *buf;
8187 int buf_size, moov_size, i;
8188
8189 if (mov->moov_written) return 0;
8190
8191 mov->is_animated_avif = s->streams[0]->nb_frames > 1;
8192 if (mov->is_animated_avif && s->nb_streams > 1) {
8193 // For animated avif with alpha channel, we need to write a tref tag
8194 // with type "auxl".
8195 mov->tracks[1].tref_tag = MKTAG('a', 'u', 'x', 'l');
8196 #ifdef OHOS_TIMED_META_TRACK
8197 mov->tracks[1].tref_ids[0] = 1;
8198 #else
8199 mov->tracks[1].tref_id = 1;
8200 #endif
8201 }
8202 mov_write_identification(pb, s);
8203 mov_write_meta_tag(pb, mov, s);
8204
8205 moov_size = get_moov_size(s);
8206 for (i = 0; i < s->nb_streams; i++)
8207 mov->tracks[i].data_offset = avio_tell(pb) + moov_size + 8;
8208
8209 if (mov->is_animated_avif) {
8210 int ret;
8211 if ((ret = mov_write_moov_tag(pb, mov, s)) < 0)
8212 return ret;
8213 }
8214
8215 buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf);
8216 avio_wb32(pb, buf_size + 8);
8217 ffio_wfourcc(pb, "mdat");
8218
8219 // The offset for the YUV planes is the starting position of mdat.
8220 extent_offsets[0] = avio_tell(pb);
8221 // The offset for alpha plane is YUV offset + YUV size.
8222 extent_offsets[1] = extent_offsets[0] + mov->avif_extent_length[0];
8223
8224 avio_write(pb, buf, buf_size);
8225
8226 // write extent offsets.
8227 pos_backup = avio_tell(pb);
8228 for (i = 0; i < s->nb_streams; i++) {
8229 if (extent_offsets[i] != (uint32_t)extent_offsets[i]) {
8230 av_log(s, AV_LOG_ERROR, "extent offset does not fit in 32 bits\n");
8231 return AVERROR_INVALIDDATA;
8232 }
8233 avio_seek(pb, mov->avif_extent_pos[i], SEEK_SET);
8234 avio_wb32(pb, extent_offsets[i]); /* rewrite offset */
8235 }
8236 avio_seek(pb, pos_backup, SEEK_SET);
8237
8238 return 0;
8239 }
8240
8241 #if CONFIG_TGP_MUXER || CONFIG_TG2_MUXER
8242 static const AVCodecTag codec_3gp_tags[] = {
8243 { AV_CODEC_ID_H263, MKTAG('s','2','6','3') },
8244 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
8245 { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
8246 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
8247 { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') },
8248 { AV_CODEC_ID_AMR_WB, MKTAG('s','a','w','b') },
8249 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
8250 { AV_CODEC_ID_NONE, 0 },
8251 };
8252 static const AVCodecTag *const codec_3gp_tags_list[] = { codec_3gp_tags, NULL };
8253 #endif
8254
8255 static const AVCodecTag codec_mp4_tags[] = {
8256 { AV_CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
8257 { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') },
8258 { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '3') },
8259 { AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') },
8260 { AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') },
8261 { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', '4', 'v') },
8262 { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', '4', 'v') },
8263 { AV_CODEC_ID_MJPEG, MKTAG('m', 'p', '4', 'v') },
8264 { AV_CODEC_ID_PNG, MKTAG('m', 'p', '4', 'v') },
8265 { AV_CODEC_ID_JPEG2000, MKTAG('m', 'p', '4', 'v') },
8266 { AV_CODEC_ID_VC1, MKTAG('v', 'c', '-', '1') },
8267 { AV_CODEC_ID_DIRAC, MKTAG('d', 'r', 'a', 'c') },
8268 { AV_CODEC_ID_TSCC2, MKTAG('m', 'p', '4', 'v') },
8269 { AV_CODEC_ID_VP9, MKTAG('v', 'p', '0', '9') },
8270 { AV_CODEC_ID_AV1, MKTAG('a', 'v', '0', '1') },
8271 { AV_CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') },
8272 { AV_CODEC_ID_ALAC, MKTAG('a', 'l', 'a', 'c') },
8273 { AV_CODEC_ID_MP4ALS, MKTAG('m', 'p', '4', 'a') },
8274 { AV_CODEC_ID_MP3, MKTAG('m', 'p', '4', 'a') },
8275 { AV_CODEC_ID_MP2, MKTAG('m', 'p', '4', 'a') },
8276 { AV_CODEC_ID_AC3, MKTAG('a', 'c', '-', '3') },
8277 { AV_CODEC_ID_EAC3, MKTAG('e', 'c', '-', '3') },
8278 { AV_CODEC_ID_DTS, MKTAG('m', 'p', '4', 'a') },
8279 { AV_CODEC_ID_TRUEHD, MKTAG('m', 'l', 'p', 'a') },
8280 { AV_CODEC_ID_FLAC, MKTAG('f', 'L', 'a', 'C') },
8281 { AV_CODEC_ID_OPUS, MKTAG('O', 'p', 'u', 's') },
8282 { AV_CODEC_ID_VORBIS, MKTAG('m', 'p', '4', 'a') },
8283 { AV_CODEC_ID_QCELP, MKTAG('m', 'p', '4', 'a') },
8284 { AV_CODEC_ID_EVRC, MKTAG('m', 'p', '4', 'a') },
8285 { AV_CODEC_ID_DVD_SUBTITLE, MKTAG('m', 'p', '4', 's') },
8286 { AV_CODEC_ID_MOV_TEXT, MKTAG('t', 'x', '3', 'g') },
8287 { AV_CODEC_ID_BIN_DATA, MKTAG('g', 'p', 'm', 'd') },
8288 { AV_CODEC_ID_MPEGH_3D_AUDIO, MKTAG('m', 'h', 'm', '1') },
8289 { AV_CODEC_ID_TTML, MOV_MP4_TTML_TAG },
8290 { AV_CODEC_ID_TTML, MOV_ISMV_TTML_TAG },
8291 #ifdef OHOS_TIMED_META_TRACK
8292 { AV_CODEC_ID_FFMETADATA, MKTAG('c', 'd', 's', 'c') },
8293 #endif
8294 { AV_CODEC_ID_NONE, 0 },
8295 };
8296 #if CONFIG_MP4_MUXER || CONFIG_PSP_MUXER
8297 static const AVCodecTag *const mp4_codec_tags_list[] = { codec_mp4_tags, NULL };
8298 #endif
8299
8300 static const AVCodecTag codec_ism_tags[] = {
8301 { AV_CODEC_ID_WMAPRO , MKTAG('w', 'm', 'a', ' ') },
8302 { AV_CODEC_ID_TTML , MOV_ISMV_TTML_TAG },
8303 { AV_CODEC_ID_NONE , 0 },
8304 };
8305
8306 static const AVCodecTag codec_ipod_tags[] = {
8307 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
8308 { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
8309 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
8310 { AV_CODEC_ID_ALAC, MKTAG('a','l','a','c') },
8311 { AV_CODEC_ID_AC3, MKTAG('a','c','-','3') },
8312 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
8313 { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') },
8314 { AV_CODEC_ID_NONE, 0 },
8315 };
8316
8317 static const AVCodecTag codec_f4v_tags[] = {
8318 { AV_CODEC_ID_MP3, MKTAG('.','m','p','3') },
8319 { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') },
8320 { AV_CODEC_ID_H264, MKTAG('a','v','c','1') },
8321 { AV_CODEC_ID_VP6A, MKTAG('V','P','6','A') },
8322 { AV_CODEC_ID_VP6F, MKTAG('V','P','6','F') },
8323 { AV_CODEC_ID_NONE, 0 },
8324 };
8325
8326 #if CONFIG_AVIF_MUXER
8327 static const AVCodecTag codec_avif_tags[] = {
8328 { AV_CODEC_ID_AV1, MKTAG('a','v','0','1') },
8329 { AV_CODEC_ID_NONE, 0 },
8330 };
8331 static const AVCodecTag *const codec_avif_tags_list[] = { codec_avif_tags, NULL };
8332
8333 static const AVClass mov_avif_muxer_class = {
8334 .class_name = "avif muxer",
8335 .item_name = av_default_item_name,
8336 .version = LIBAVUTIL_VERSION_INT,
8337 };
8338 #endif
8339
8340 #if CONFIG_MOV_MUXER
8341 const AVOutputFormat ff_mov_muxer = {
8342 .name = "mov",
8343 .long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
8344 .extensions = "mov",
8345 .priv_data_size = sizeof(MOVMuxContext),
8346 .audio_codec = AV_CODEC_ID_AAC,
8347 .video_codec = CONFIG_LIBX264_ENCODER ?
8348 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
8349 .init = mov_init,
8350 .write_header = mov_write_header,
8351 .write_packet = mov_write_packet,
8352 .write_trailer = mov_write_trailer,
8353 .deinit = mov_free,
8354 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8355 .codec_tag = (const AVCodecTag* const []){
8356 ff_codec_movvideo_tags, ff_codec_movaudio_tags, ff_codec_movsubtitle_tags, 0
8357 },
8358 .check_bitstream = mov_check_bitstream,
8359 .priv_class = &mov_isobmff_muxer_class,
8360 };
8361 #endif
8362 #if CONFIG_TGP_MUXER
8363 const AVOutputFormat ff_tgp_muxer = {
8364 .name = "3gp",
8365 .long_name = NULL_IF_CONFIG_SMALL("3GP (3GPP file format)"),
8366 .extensions = "3gp",
8367 .priv_data_size = sizeof(MOVMuxContext),
8368 .audio_codec = AV_CODEC_ID_AMR_NB,
8369 .video_codec = AV_CODEC_ID_H263,
8370 .init = mov_init,
8371 .write_header = mov_write_header,
8372 .write_packet = mov_write_packet,
8373 .write_trailer = mov_write_trailer,
8374 .deinit = mov_free,
8375 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8376 .codec_tag = codec_3gp_tags_list,
8377 .check_bitstream = mov_check_bitstream,
8378 .priv_class = &mov_isobmff_muxer_class,
8379 };
8380 #endif
8381 #if CONFIG_MP4_MUXER
8382 const AVOutputFormat ff_mp4_muxer = {
8383 .name = "mp4",
8384 .long_name = NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"),
8385 .mime_type = "video/mp4",
8386 .extensions = "mp4",
8387 .priv_data_size = sizeof(MOVMuxContext),
8388 .audio_codec = AV_CODEC_ID_AAC,
8389 .video_codec = CONFIG_LIBX264_ENCODER ?
8390 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
8391 .init = mov_init,
8392 .write_header = mov_write_header,
8393 .write_packet = mov_write_packet,
8394 .write_trailer = mov_write_trailer,
8395 .deinit = mov_free,
8396 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8397 .codec_tag = mp4_codec_tags_list,
8398 .check_bitstream = mov_check_bitstream,
8399 .priv_class = &mov_isobmff_muxer_class,
8400 };
8401 #endif
8402 #if CONFIG_PSP_MUXER
8403 const AVOutputFormat ff_psp_muxer = {
8404 .name = "psp",
8405 .long_name = NULL_IF_CONFIG_SMALL("PSP MP4 (MPEG-4 Part 14)"),
8406 .extensions = "mp4,psp",
8407 .priv_data_size = sizeof(MOVMuxContext),
8408 .audio_codec = AV_CODEC_ID_AAC,
8409 .video_codec = CONFIG_LIBX264_ENCODER ?
8410 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
8411 .init = mov_init,
8412 .write_header = mov_write_header,
8413 .write_packet = mov_write_packet,
8414 .write_trailer = mov_write_trailer,
8415 .deinit = mov_free,
8416 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8417 .codec_tag = mp4_codec_tags_list,
8418 .check_bitstream = mov_check_bitstream,
8419 .priv_class = &mov_isobmff_muxer_class,
8420 };
8421 #endif
8422 #if CONFIG_TG2_MUXER
8423 const AVOutputFormat ff_tg2_muxer = {
8424 .name = "3g2",
8425 .long_name = NULL_IF_CONFIG_SMALL("3GP2 (3GPP2 file format)"),
8426 .extensions = "3g2",
8427 .priv_data_size = sizeof(MOVMuxContext),
8428 .audio_codec = AV_CODEC_ID_AMR_NB,
8429 .video_codec = AV_CODEC_ID_H263,
8430 .init = mov_init,
8431 .write_header = mov_write_header,
8432 .write_packet = mov_write_packet,
8433 .write_trailer = mov_write_trailer,
8434 .deinit = mov_free,
8435 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8436 .codec_tag = codec_3gp_tags_list,
8437 .check_bitstream = mov_check_bitstream,
8438 .priv_class = &mov_isobmff_muxer_class,
8439 };
8440 #endif
8441 #if CONFIG_IPOD_MUXER
8442 const AVOutputFormat ff_ipod_muxer = {
8443 .name = "ipod",
8444 .long_name = NULL_IF_CONFIG_SMALL("iPod H.264 MP4 (MPEG-4 Part 14)"),
8445 .mime_type = "video/mp4",
8446 .extensions = "m4v,m4a,m4b",
8447 .priv_data_size = sizeof(MOVMuxContext),
8448 .audio_codec = AV_CODEC_ID_AAC,
8449 .video_codec = AV_CODEC_ID_H264,
8450 .init = mov_init,
8451 .write_header = mov_write_header,
8452 .write_packet = mov_write_packet,
8453 .write_trailer = mov_write_trailer,
8454 .deinit = mov_free,
8455 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8456 .codec_tag = (const AVCodecTag* const []){ codec_ipod_tags, 0 },
8457 .check_bitstream = mov_check_bitstream,
8458 .priv_class = &mov_isobmff_muxer_class,
8459 };
8460 #endif
8461 #if CONFIG_ISMV_MUXER
8462 const AVOutputFormat ff_ismv_muxer = {
8463 .name = "ismv",
8464 .long_name = NULL_IF_CONFIG_SMALL("ISMV/ISMA (Smooth Streaming)"),
8465 .mime_type = "video/mp4",
8466 .extensions = "ismv,isma",
8467 .priv_data_size = sizeof(MOVMuxContext),
8468 .audio_codec = AV_CODEC_ID_AAC,
8469 .video_codec = AV_CODEC_ID_H264,
8470 .init = mov_init,
8471 .write_header = mov_write_header,
8472 .write_packet = mov_write_packet,
8473 .write_trailer = mov_write_trailer,
8474 .deinit = mov_free,
8475 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
8476 .codec_tag = (const AVCodecTag* const []){
8477 codec_mp4_tags, codec_ism_tags, 0 },
8478 .check_bitstream = mov_check_bitstream,
8479 .priv_class = &mov_isobmff_muxer_class,
8480 };
8481 #endif
8482 #if CONFIG_F4V_MUXER
8483 const AVOutputFormat ff_f4v_muxer = {
8484 .name = "f4v",
8485 .long_name = NULL_IF_CONFIG_SMALL("F4V Adobe Flash Video"),
8486 .mime_type = "application/f4v",
8487 .extensions = "f4v",
8488 .priv_data_size = sizeof(MOVMuxContext),
8489 .audio_codec = AV_CODEC_ID_AAC,
8490 .video_codec = AV_CODEC_ID_H264,
8491 .init = mov_init,
8492 .write_header = mov_write_header,
8493 .write_packet = mov_write_packet,
8494 .write_trailer = mov_write_trailer,
8495 .deinit = mov_free,
8496 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
8497 .codec_tag = (const AVCodecTag* const []){ codec_f4v_tags, 0 },
8498 .check_bitstream = mov_check_bitstream,
8499 .priv_class = &mov_isobmff_muxer_class,
8500 };
8501 #endif
8502 #if CONFIG_AVIF_MUXER
8503 const AVOutputFormat ff_avif_muxer = {
8504 .name = "avif",
8505 .long_name = NULL_IF_CONFIG_SMALL("AVIF"),
8506 .mime_type = "image/avif",
8507 .extensions = "avif",
8508 .priv_data_size = sizeof(MOVMuxContext),
8509 .video_codec = AV_CODEC_ID_AV1,
8510 .init = mov_init,
8511 .write_header = mov_write_header,
8512 .write_packet = mov_write_packet,
8513 .write_trailer = avif_write_trailer,
8514 .deinit = mov_free,
8515 .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
8516 .codec_tag = codec_avif_tags_list,
8517 .priv_class = &mov_avif_muxer_class,
8518 };
8519 #endif
8520