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