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