FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/movenc.c
Date: 2024-02-16 17:37:06
Exec Total Coverage
Lines: 3192 4907 65.0%
Functions: 158 212 74.5%
Branches: 1865 3367 55.4%

Line Branch Exec Source
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 "evc.h"
39 #include "libavcodec/ac3_parser_internal.h"
40 #include "libavcodec/dnxhddata.h"
41 #include "libavcodec/flac.h"
42 #include "libavcodec/get_bits.h"
43
44 #include "libavcodec/internal.h"
45 #include "libavcodec/put_bits.h"
46 #include "libavcodec/vc1_common.h"
47 #include "libavcodec/raw.h"
48 #include "internal.h"
49 #include "libavutil/avstring.h"
50 #include "libavutil/channel_layout.h"
51 #include "libavutil/csp.h"
52 #include "libavutil/intfloat.h"
53 #include "libavutil/mathematics.h"
54 #include "libavutil/libm.h"
55 #include "libavutil/opt.h"
56 #include "libavutil/dict.h"
57 #include "libavutil/pixdesc.h"
58 #include "libavutil/stereo3d.h"
59 #include "libavutil/timecode.h"
60 #include "libavutil/dovi_meta.h"
61 #include "libavutil/uuid.h"
62 #include "hevc.h"
63 #include "rtpenc.h"
64 #include "mov_chan.h"
65 #include "movenc_ttml.h"
66 #include "mux.h"
67 #include "rawutils.h"
68 #include "ttmlenc.h"
69 #include "version.h"
70 #include "vpcc.h"
71 #include "vvc.h"
72
73 static const AVOption options[] = {
74 { "brand", "Override major brand", offsetof(MOVMuxContext, major_brand), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM },
75 { "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},
76 { "encryption_key", "The media encryption key (hex)", offsetof(MOVMuxContext, encryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM },
77 { "encryption_kid", "The media encryption key identifier (hex)", offsetof(MOVMuxContext, encryption_kid), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM },
78 { "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 },
79 { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext, max_fragment_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
80 { "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 },
81 { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
82 { "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},
83 { "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},
84 { "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},
85 { "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},
86 { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, .unit = "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, .unit = "movflags" },
88 { "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, .unit = "movflags" },
89 { "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, .unit = "movflags" },
90 { "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, .unit = "movflags" },
91 { "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, .unit = "movflags" },
92 { "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, .unit = "movflags" },
93 { "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, .unit = "movflags" },
94 { "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, .unit = "movflags" },
95 { "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, .unit = "movflags" },
96 { "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, .unit = "movflags" },
97 { "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, .unit = "movflags" },
98 { "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, .unit = "movflags" },
99 { "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, .unit = "movflags" },
100 { "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, .unit = 0 },
101 { "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, .unit = "movflags" },
102 { "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, .unit = "movflags" },
103 { "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, .unit = "movflags" },
104 { "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, .unit = "movflags" },
105 { "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, .unit = "movflags" },
106 { "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, .unit = "movflags" },
107 { "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, .unit = "movflags" },
108 { "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, .unit = "movflags" },
109 { "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, .unit = "movflags" },
110 { "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, .unit = "movflags" },
111 { "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},
112 { "mov_gamma", "gamma value for gama atom", offsetof(MOVMuxContext, gamma), AV_OPT_TYPE_FLOAT, {.dbl = 0.0 }, 0.0, 10, AV_OPT_FLAG_ENCODING_PARAM},
113 { "movie_timescale", "set movie timescale", offsetof(MOVMuxContext, movie_timescale), AV_OPT_TYPE_INT, {.i64 = MOV_TIMESCALE}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
114 FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
115 { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
116 { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
117 { "use_stream_ids_as_track_ids", "use stream ids as track ids", offsetof(MOVMuxContext, use_stream_ids_as_track_ids), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
118 { "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},
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_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, .unit = "prft"},
121 { "pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_PTS}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, .unit = "prft"},
122 { "wallclock", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_WALLCLOCK}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, .unit = "prft"},
123 { "write_tmcd", "force or disable writing tmcd", offsetof(MOVMuxContext, write_tmcd), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
124 { NULL },
125 };
126
127 static const AVClass mov_isobmff_muxer_class = {
128 .class_name = "mov/mp4/tgp/psp/tg2/ipod/ismv/f4v muxer",
129 .item_name = av_default_item_name,
130 .option = options,
131 .version = LIBAVUTIL_VERSION_INT,
132 };
133
134 static int get_moov_size(AVFormatContext *s);
135 static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt);
136
137 23 static int utf8len(const uint8_t *b)
138 {
139 23 int len = 0;
140 int val;
141
2/2
✓ Branch 0 taken 457 times.
✓ Branch 1 taken 23 times.
480 while (*b) {
142
3/8
✓ Branch 0 taken 457 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 457 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 457 times.
457 GET_UTF8(val, *b++, return -1;)
143 457 len++;
144 }
145 23 return len;
146 }
147
148 //FIXME support 64 bit variant with wide placeholders
149 5737 static int64_t update_size(AVIOContext *pb, int64_t pos)
150 {
151 5737 int64_t curpos = avio_tell(pb);
152 5737 avio_seek(pb, pos, SEEK_SET);
153 5737 avio_wb32(pb, curpos - pos); /* rewrite size */
154 5737 avio_seek(pb, curpos, SEEK_SET);
155
156 5737 return curpos - pos;
157 }
158
159 309 static int co64_required(const MOVTrack *track)
160 {
161
3/4
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 221 times.
309 if (track->entry > 0 && track->cluster[track->entry - 1].pos + track->data_offset > UINT32_MAX)
162 return 1;
163 309 return 0;
164 }
165
166 20241 static int is_cover_image(const AVStream *st)
167 {
168 /* Eg. AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS
169 * is encoded as sparse video track */
170
3/4
✓ Branch 0 taken 20241 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 20229 times.
20241 return st && st->disposition == AV_DISPOSITION_ATTACHED_PIC;
171 }
172
173 6 static int rtp_hinting_needed(const AVStream *st)
174 {
175 /* Add hint tracks for each real audio and video stream */
176
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (is_cover_image(st))
177 return 0;
178
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
9 return st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
179
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO;
180 }
181
182 /* Chunk offset atom */
183 309 static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)
184 {
185 int i;
186 309 int mode64 = co64_required(track); // use 32 bit size variant if possible
187 309 int64_t pos = avio_tell(pb);
188 309 avio_wb32(pb, 0); /* size */
189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
309 if (mode64)
190 ffio_wfourcc(pb, "co64");
191 else
192 309 ffio_wfourcc(pb, "stco");
193 309 avio_wb32(pb, 0); /* version & flags */
194 309 avio_wb32(pb, track->chunkCount); /* entry count */
195
2/2
✓ Branch 0 taken 15131 times.
✓ Branch 1 taken 309 times.
15440 for (i = 0; i < track->entry; i++) {
196
2/2
✓ Branch 0 taken 11013 times.
✓ Branch 1 taken 4118 times.
15131 if (!track->cluster[i].chunkNum)
197 11013 continue;
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4118 times.
4118 if (mode64 == 1)
199 avio_wb64(pb, track->cluster[i].pos + track->data_offset);
200 else
201 4118 avio_wb32(pb, track->cluster[i].pos + track->data_offset);
202 }
203 309 return update_size(pb, pos);
204 }
205
206 /* Sample size atom */
207 309 static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)
208 {
209 309 int equalChunks = 1;
210 309 int i, j, entries = 0, tst = -1, oldtst = -1;
211
212 309 int64_t pos = avio_tell(pb);
213 309 avio_wb32(pb, 0); /* size */
214 309 ffio_wfourcc(pb, "stsz");
215 309 avio_wb32(pb, 0); /* version & flags */
216
217
2/2
✓ Branch 0 taken 15131 times.
✓ Branch 1 taken 309 times.
15440 for (i = 0; i < track->entry; i++) {
218 15131 tst = track->cluster[i].size / track->cluster[i].entries;
219
4/4
✓ Branch 0 taken 14910 times.
✓ Branch 1 taken 221 times.
✓ Branch 2 taken 8428 times.
✓ Branch 3 taken 6482 times.
15131 if (oldtst != -1 && tst != oldtst)
220 8428 equalChunks = 0;
221 15131 oldtst = tst;
222 15131 entries += track->cluster[i].entries;
223 }
224
4/4
✓ Branch 0 taken 189 times.
✓ Branch 1 taken 120 times.
✓ Branch 2 taken 101 times.
✓ Branch 3 taken 88 times.
410 if (equalChunks && track->entry) {
225
1/2
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
101 int sSize = track->entry ? track->cluster[0].size / track->cluster[0].entries : 0;
226 101 sSize = FFMAX(1, sSize); // adpcm mono case could make sSize == 0
227 101 avio_wb32(pb, sSize); // sample size
228 101 avio_wb32(pb, entries); // sample count
229 } else {
230 208 avio_wb32(pb, 0); // sample size
231 208 avio_wb32(pb, entries); // sample count
232
2/2
✓ Branch 0 taken 9576 times.
✓ Branch 1 taken 208 times.
9784 for (i = 0; i < track->entry; i++) {
233
2/2
✓ Branch 0 taken 9576 times.
✓ Branch 1 taken 9576 times.
19152 for (j = 0; j < track->cluster[i].entries; j++) {
234 9576 avio_wb32(pb, track->cluster[i].size /
235 9576 track->cluster[i].entries);
236 }
237 }
238 }
239 309 return update_size(pb, pos);
240 }
241
242 /* Sample to chunk atom */
243 309 static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track)
244 {
245 309 int index = 0, oldval = -1, i;
246 int64_t entryPos, curpos;
247
248 309 int64_t pos = avio_tell(pb);
249 309 avio_wb32(pb, 0); /* size */
250 309 ffio_wfourcc(pb, "stsc");
251 309 avio_wb32(pb, 0); // version & flags
252 309 entryPos = avio_tell(pb);
253 309 avio_wb32(pb, track->chunkCount); // entry count
254
2/2
✓ Branch 0 taken 15131 times.
✓ Branch 1 taken 309 times.
15440 for (i = 0; i < track->entry; i++) {
255
4/4
✓ Branch 0 taken 11869 times.
✓ Branch 1 taken 3262 times.
✓ Branch 2 taken 856 times.
✓ Branch 3 taken 11013 times.
15131 if (oldval != track->cluster[i].samples_in_chunk && track->cluster[i].chunkNum) {
256 856 avio_wb32(pb, track->cluster[i].chunkNum); // first chunk
257 856 avio_wb32(pb, track->cluster[i].samples_in_chunk); // samples per chunk
258 856 avio_wb32(pb, 0x1); // sample description index
259 856 oldval = track->cluster[i].samples_in_chunk;
260 856 index++;
261 }
262 }
263 309 curpos = avio_tell(pb);
264 309 avio_seek(pb, entryPos, SEEK_SET);
265 309 avio_wb32(pb, index); // rewrite size
266 309 avio_seek(pb, curpos, SEEK_SET);
267
268 309 return update_size(pb, pos);
269 }
270
271 /* Sync sample atom */
272 49 static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag)
273 {
274 int64_t curpos, entryPos;
275 49 int i, index = 0;
276 49 int64_t pos = avio_tell(pb);
277 49 avio_wb32(pb, 0); // size
278
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 ffio_wfourcc(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps");
279 49 avio_wb32(pb, 0); // version & flags
280 49 entryPos = avio_tell(pb);
281 49 avio_wb32(pb, track->entry); // entry count
282
2/2
✓ Branch 0 taken 2943 times.
✓ Branch 1 taken 49 times.
2992 for (i = 0; i < track->entry; i++) {
283
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 2751 times.
2943 if (track->cluster[i].flags & flag) {
284 192 avio_wb32(pb, i + 1);
285 192 index++;
286 }
287 }
288 49 curpos = avio_tell(pb);
289 49 avio_seek(pb, entryPos, SEEK_SET);
290 49 avio_wb32(pb, index); // rewrite size
291 49 avio_seek(pb, curpos, SEEK_SET);
292 49 return update_size(pb, pos);
293 }
294
295 /* Sample dependency atom */
296 2 static int mov_write_sdtp_tag(AVIOContext *pb, MOVTrack *track)
297 {
298 int i;
299 uint8_t leading, dependent, reference, redundancy;
300 2 int64_t pos = avio_tell(pb);
301 2 avio_wb32(pb, 0); // size
302 2 ffio_wfourcc(pb, "sdtp");
303 2 avio_wb32(pb, 0); // version & flags
304
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (i = 0; i < track->entry; i++) {
305 2 dependent = MOV_SAMPLE_DEPENDENCY_YES;
306 2 leading = reference = redundancy = MOV_SAMPLE_DEPENDENCY_UNKNOWN;
307
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (track->cluster[i].flags & MOV_DISPOSABLE_SAMPLE) {
308 2 reference = MOV_SAMPLE_DEPENDENCY_NO;
309 }
310
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (track->cluster[i].flags & MOV_SYNC_SAMPLE) {
311 2 dependent = MOV_SAMPLE_DEPENDENCY_NO;
312 }
313 2 avio_w8(pb, (leading << 6) | (dependent << 4) |
314 2 (reference << 2) | redundancy);
315 }
316 2 return update_size(pb, pos);
317 }
318
319 static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
320 {
321 avio_wb32(pb, 0x11); /* size */
322 if (track->mode == MODE_MOV) ffio_wfourcc(pb, "samr");
323 else ffio_wfourcc(pb, "damr");
324 ffio_wfourcc(pb, "FFMP");
325 avio_w8(pb, 0); /* decoder version */
326
327 avio_wb16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */
328 avio_w8(pb, 0x00); /* Mode change period (no restriction) */
329 avio_w8(pb, 0x01); /* Frames per sample */
330 return 0x11;
331 }
332
333 struct eac3_info {
334 AVPacket *pkt;
335 uint8_t ec3_done;
336 uint8_t num_blocks;
337
338 /* Layout of the EC3SpecificBox */
339 /* maximum bitrate */
340 uint16_t data_rate;
341 int8_t ac3_bit_rate_code;
342 /* number of independent substreams */
343 uint8_t num_ind_sub;
344 struct {
345 /* sample rate code (see ff_ac3_sample_rate_tab) 2 bits */
346 uint8_t fscod;
347 /* bit stream identification 5 bits */
348 uint8_t bsid;
349 /* one bit reserved */
350 /* audio service mixing (not supported yet) 1 bit */
351 /* bit stream mode 3 bits */
352 uint8_t bsmod;
353 /* audio coding mode 3 bits */
354 uint8_t acmod;
355 /* sub woofer on 1 bit */
356 uint8_t lfeon;
357 /* 3 bits reserved */
358 /* number of dependent substreams associated with this substream 4 bits */
359 uint8_t num_dep_sub;
360 /* channel locations of the dependent substream(s), if any, 9 bits */
361 uint16_t chan_loc;
362 /* if there is no dependent substream, then one bit reserved instead */
363 } substream[1]; /* TODO: support 8 independent substreams */
364 };
365
366 5 static int mov_write_ac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
367 {
368 5 struct eac3_info *info = track->eac3_priv;
369 PutBitContext pbc;
370 uint8_t buf[3];
371
372
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (!info || !info->ec3_done) {
373 av_log(s, AV_LOG_ERROR,
374 "Cannot write moov atom before AC3 packets."
375 " Set the delay_moov flag to fix this.\n");
376 return AVERROR(EINVAL);
377 }
378
379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (info->substream[0].bsid > 8) {
380 av_log(s, AV_LOG_ERROR,
381 "RealAudio AC-3/DolbyNet with bsid %d is not defined by the "
382 "ISOBMFF specification in ETSI TS 102 366!\n",
383 info->substream[0].bsid);
384 return AVERROR(EINVAL);
385 }
386
387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (info->ac3_bit_rate_code < 0) {
388 av_log(s, AV_LOG_ERROR,
389 "No valid AC3 bit rate code for data rate of %d!\n",
390 info->data_rate);
391 return AVERROR(EINVAL);
392 }
393
394 5 avio_wb32(pb, 11);
395 5 ffio_wfourcc(pb, "dac3");
396
397 5 init_put_bits(&pbc, buf, sizeof(buf));
398 5 put_bits(&pbc, 2, info->substream[0].fscod);
399 5 put_bits(&pbc, 5, info->substream[0].bsid);
400 5 put_bits(&pbc, 3, info->substream[0].bsmod);
401 5 put_bits(&pbc, 3, info->substream[0].acmod);
402 5 put_bits(&pbc, 1, info->substream[0].lfeon);
403 5 put_bits(&pbc, 5, info->ac3_bit_rate_code); // bit_rate_code
404 5 put_bits(&pbc, 5, 0); // reserved
405
406 5 flush_put_bits(&pbc);
407 5 avio_write(pb, buf, sizeof(buf));
408
409 5 return 11;
410 }
411
412 1039 static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
413 {
414 1039 AC3HeaderInfo *hdr = NULL;
415 struct eac3_info *info;
416 int num_blocks, ret;
417
418
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1034 times.
1039 if (!track->eac3_priv) {
419
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (!(track->eac3_priv = av_mallocz(sizeof(*info))))
420 return AVERROR(ENOMEM);
421
422 5 ((struct eac3_info *)track->eac3_priv)->ac3_bit_rate_code = -1;
423 }
424 1039 info = track->eac3_priv;
425
426
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1034 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
1039 if (!info->pkt && !(info->pkt = av_packet_alloc()))
427 return AVERROR(ENOMEM);
428
429
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1038 times.
1039 if ((ret = avpriv_ac3_parse_header(&hdr, pkt->data, pkt->size)) < 0) {
430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret == AVERROR(ENOMEM))
431 goto end;
432
433 /* drop the packets until we see a good one */
434
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!track->entry) {
435 1 av_log(mov->fc, AV_LOG_WARNING, "Dropping invalid packet from start of the stream\n");
436 1 ret = 0;
437 } else
438 ret = AVERROR_INVALIDDATA;
439 1 goto end;
440 }
441
442 1038 info->data_rate = FFMAX(info->data_rate, hdr->bit_rate / 1000);
443 1038 info->ac3_bit_rate_code = FFMAX(info->ac3_bit_rate_code,
444 hdr->ac3_bit_rate_code);
445 1038 num_blocks = hdr->num_blocks;
446
447
2/2
✓ Branch 0 taken 1032 times.
✓ Branch 1 taken 6 times.
1038 if (!info->ec3_done) {
448 /* AC-3 substream must be the first one */
449
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
6 if (hdr->bitstream_id <= 10 && hdr->substreamid != 0) {
450 ret = AVERROR(EINVAL);
451 goto end;
452 }
453
454 /* this should always be the case, given that our AC-3 parser
455 * concatenates dependent frames to their independent parent */
456
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (hdr->frame_type == EAC3_FRAME_TYPE_INDEPENDENT ||
457
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 hdr->frame_type == EAC3_FRAME_TYPE_AC3_CONVERT) {
458 /* substream ids must be incremental */
459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (hdr->substreamid > info->num_ind_sub + 1) {
460 ret = AVERROR(EINVAL);
461 goto end;
462 }
463
464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (hdr->substreamid == info->num_ind_sub + 1) {
465 //info->num_ind_sub++;
466 avpriv_request_sample(mov->fc, "Multiple independent substreams");
467 ret = AVERROR_PATCHWELCOME;
468 goto end;
469
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 } else if (hdr->substreamid < info->num_ind_sub ||
470
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5 times.
6 hdr->substreamid == 0 && info->substream[0].bsid) {
471 1 info->ec3_done = 1;
472 1 goto concatenate;
473 }
474 } else {
475 if (hdr->substreamid != 0) {
476 avpriv_request_sample(mov->fc, "Multiple non EAC3 independent substreams");
477 ret = AVERROR_PATCHWELCOME;
478 goto end;
479 }
480 }
481
482 /* fill the info needed for the "dec3" atom */
483 5 info->substream[hdr->substreamid].fscod = hdr->sr_code;
484 5 info->substream[hdr->substreamid].bsid = hdr->bitstream_id;
485 5 info->substream[hdr->substreamid].bsmod = hdr->bitstream_mode;
486 5 info->substream[hdr->substreamid].acmod = hdr->channel_mode;
487 5 info->substream[hdr->substreamid].lfeon = hdr->lfe_on;
488
489
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 if (track->par->codec_id == AV_CODEC_ID_AC3) {
490 // with AC-3 we only require the information of a single packet,
491 // so we can finish as soon as the basic values of the bit stream
492 // have been set to the track's informational structure.
493 4 info->ec3_done = 1;
494 4 goto concatenate;
495 }
496
497 /* Parse dependent substream(s), if any */
498
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (pkt->size != hdr->frame_size) {
499 int cumul_size = hdr->frame_size;
500 int parent = hdr->substreamid;
501
502 while (cumul_size != pkt->size) {
503 GetBitContext gbc;
504 int i;
505 ret = avpriv_ac3_parse_header(&hdr, pkt->data + cumul_size, pkt->size - cumul_size);
506 if (ret < 0)
507 goto end;
508 if (hdr->frame_type != EAC3_FRAME_TYPE_DEPENDENT) {
509 ret = AVERROR(EINVAL);
510 goto end;
511 }
512 info->substream[parent].num_dep_sub++;
513 ret /= 8;
514
515 /* header is parsed up to lfeon, but custom channel map may be needed */
516 init_get_bits8(&gbc, pkt->data + cumul_size + ret, pkt->size - cumul_size - ret);
517 /* skip bsid */
518 skip_bits(&gbc, 5);
519 /* skip volume control params */
520 for (i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
521 skip_bits(&gbc, 5); // skip dialog normalization
522 if (get_bits1(&gbc)) {
523 skip_bits(&gbc, 8); // skip compression gain word
524 }
525 }
526 /* get the dependent stream channel map, if exists */
527 if (get_bits1(&gbc))
528 info->substream[parent].chan_loc |= (get_bits(&gbc, 16) >> 5) & 0x1f;
529 else
530 info->substream[parent].chan_loc |= hdr->channel_mode;
531 cumul_size += hdr->frame_size;
532 }
533 }
534 }
535
536 1033 concatenate:
537
2/4
✓ Branch 0 taken 1038 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1038 times.
✗ Branch 3 not taken.
1038 if (!info->num_blocks && num_blocks == 6) {
538 1038 ret = pkt->size;
539 1038 goto end;
540 }
541 else if (info->num_blocks + num_blocks > 6) {
542 ret = AVERROR_INVALIDDATA;
543 goto end;
544 }
545
546 if (!info->num_blocks) {
547 ret = av_packet_ref(info->pkt, pkt);
548 if (!ret)
549 info->num_blocks = num_blocks;
550 goto end;
551 } else {
552 if ((ret = av_grow_packet(info->pkt, pkt->size)) < 0)
553 goto end;
554 memcpy(info->pkt->data + info->pkt->size - pkt->size, pkt->data, pkt->size);
555 info->num_blocks += num_blocks;
556 info->pkt->duration += pkt->duration;
557 if (info->num_blocks != 6)
558 goto end;
559 av_packet_unref(pkt);
560 av_packet_move_ref(pkt, info->pkt);
561 info->num_blocks = 0;
562 }
563 ret = pkt->size;
564
565 1039 end:
566 1039 av_free(hdr);
567
568 1039 return ret;
569 }
570
571 1 static int mov_write_eac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
572 {
573 PutBitContext pbc;
574 uint8_t *buf;
575 struct eac3_info *info;
576 int size, i;
577
578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!track->eac3_priv) {
579 av_log(s, AV_LOG_ERROR,
580 "Cannot write moov atom before EAC3 packets parsed.\n");
581 return AVERROR(EINVAL);
582 }
583
584 1 info = track->eac3_priv;
585 1 size = 2 + ((34 * (info->num_ind_sub + 1) + 7) >> 3);
586 1 buf = av_malloc(size);
587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!buf) {
588 return AVERROR(ENOMEM);
589 }
590
591 1 init_put_bits(&pbc, buf, size);
592 1 put_bits(&pbc, 13, info->data_rate);
593 1 put_bits(&pbc, 3, info->num_ind_sub);
594
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (i = 0; i <= info->num_ind_sub; i++) {
595 1 put_bits(&pbc, 2, info->substream[i].fscod);
596 1 put_bits(&pbc, 5, info->substream[i].bsid);
597 1 put_bits(&pbc, 1, 0); /* reserved */
598 1 put_bits(&pbc, 1, 0); /* asvc */
599 1 put_bits(&pbc, 3, info->substream[i].bsmod);
600 1 put_bits(&pbc, 3, info->substream[i].acmod);
601 1 put_bits(&pbc, 1, info->substream[i].lfeon);
602 1 put_bits(&pbc, 5, 0); /* reserved */
603 1 put_bits(&pbc, 4, info->substream[i].num_dep_sub);
604
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!info->substream[i].num_dep_sub) {
605 1 put_bits(&pbc, 1, 0); /* reserved */
606 } else {
607 put_bits(&pbc, 9, info->substream[i].chan_loc);
608 }
609 }
610 1 flush_put_bits(&pbc);
611 1 size = put_bytes_output(&pbc);
612
613 1 avio_wb32(pb, size + 8);
614 1 ffio_wfourcc(pb, "dec3");
615 1 avio_write(pb, buf, size);
616
617 1 av_free(buf);
618
619 1 return size;
620 }
621
622 /**
623 * This function writes extradata "as is".
624 * Extradata must be formatted like a valid atom (with size and tag).
625 */
626 12 static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)
627 {
628 12 avio_write(pb, track->par->extradata, track->par->extradata_size);
629 12 return track->par->extradata_size;
630 }
631
632 static int mov_write_enda_tag(AVIOContext *pb)
633 {
634 avio_wb32(pb, 10);
635 ffio_wfourcc(pb, "enda");
636 avio_wb16(pb, 1); /* little endian */
637 return 10;
638 }
639
640 2 static int mov_write_enda_tag_be(AVIOContext *pb)
641 {
642 2 avio_wb32(pb, 10);
643 2 ffio_wfourcc(pb, "enda");
644 2 avio_wb16(pb, 0); /* big endian */
645 2 return 10;
646 }
647
648 292 static void put_descr(AVIOContext *pb, int tag, unsigned int size)
649 {
650 292 int i = 3;
651 292 avio_w8(pb, tag);
652
2/2
✓ Branch 0 taken 876 times.
✓ Branch 1 taken 292 times.
1168 for (; i > 0; i--)
653 876 avio_w8(pb, (size >> (7 * i)) | 0x80);
654 292 avio_w8(pb, size & 0x7F);
655 292 }
656
657 193 static unsigned compute_avg_bitrate(MOVTrack *track)
658 {
659 193 uint64_t size = 0;
660 int i;
661
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 159 times.
193 if (!track->track_duration)
662 34 return 0;
663
2/2
✓ Branch 0 taken 9124 times.
✓ Branch 1 taken 159 times.
9283 for (i = 0; i < track->entry; i++)
664 9124 size += track->cluster[i].size;
665 159 return size * 8 * track->timescale / track->track_duration;
666 }
667
668 struct mpeg4_bit_rate_values {
669 uint32_t buffer_size; ///< Size of the decoding buffer for the elementary stream in bytes.
670 uint32_t max_bit_rate; ///< Maximum rate in bits/second over any window of one second.
671 uint32_t avg_bit_rate; ///< Average rate in bits/second over the entire presentation.
672 };
673
674 193 static struct mpeg4_bit_rate_values calculate_mpeg4_bit_rates(MOVTrack *track)
675 {
676 386 const AVPacketSideData *sd = track->st ?
677 192 av_packet_side_data_get(track->st->codecpar->coded_side_data,
678 192 track->st->codecpar->nb_coded_side_data,
679
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 1 times.
193 AV_PKT_DATA_CPB_PROPERTIES) : NULL;
680
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 166 times.
193 AVCPBProperties *props = sd ? (AVCPBProperties *)sd->data : NULL;
681 193 struct mpeg4_bit_rate_values bit_rates = { 0 };
682
683 193 bit_rates.avg_bit_rate = compute_avg_bitrate(track);
684
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 69 times.
193 if (!bit_rates.avg_bit_rate) {
685 // if the average bit rate cannot be calculated at this point, such as
686 // in the case of fragmented MP4, utilize the following values as
687 // fall-back in priority order:
688 //
689 // 1. average bit rate property
690 // 2. bit rate (usually average over the whole clip)
691 // 3. maximum bit rate property
692
693
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 121 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
124 if (props && props->avg_bitrate) {
694 3 bit_rates.avg_bit_rate = props->avg_bitrate;
695
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 119 times.
121 } else if (track->par->bit_rate) {
696 2 bit_rates.avg_bit_rate = track->par->bit_rate;
697
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 119 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
119 } else if (props && props->max_bitrate) {
698 bit_rates.avg_bit_rate = props->max_bitrate;
699 }
700 }
701
702 // (FIXME should be max rate in any 1 sec window)
703 193 bit_rates.max_bit_rate = FFMAX(track->par->bit_rate,
704 bit_rates.avg_bit_rate);
705
706 // utilize values from properties if we have them available
707
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 166 times.
193 if (props) {
708 27 bit_rates.max_bit_rate = FFMAX(bit_rates.max_bit_rate,
709 props->max_bitrate);
710 27 bit_rates.buffer_size = props->buffer_size / 8;
711 }
712
713 193 return bit_rates;
714 }
715
716 73 static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
717 {
718 73 struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track);
719 73 int64_t pos = avio_tell(pb);
720
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 int decoder_specific_info_len = track->vos_len ? 5 + track->vos_len : 0;
721
722 73 avio_wb32(pb, 0); // size
723 73 ffio_wfourcc(pb, "esds");
724 73 avio_wb32(pb, 0); // Version
725
726 // ES descriptor
727 73 put_descr(pb, 0x03, 3 + 5+13 + decoder_specific_info_len + 5+1);
728 73 avio_wb16(pb, track->track_id);
729 73 avio_w8(pb, 0x00); // flags (= no flags)
730
731 // DecoderConfig descriptor
732 73 put_descr(pb, 0x04, 13 + decoder_specific_info_len);
733
734 // Object type indication
735
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 if ((track->par->codec_id == AV_CODEC_ID_MP2 ||
736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 track->par->codec_id == AV_CODEC_ID_MP3) &&
737 track->par->sample_rate > 24000)
738 avio_w8(pb, 0x6B); // 11172-3
739 else
740 73 avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->par->codec_id));
741
742 // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
743 // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
744
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
745 avio_w8(pb, (0x38 << 2) | 1); // flags (= NeroSubpicStream)
746
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 20 times.
73 else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
747 53 avio_w8(pb, 0x15); // flags (= Audiostream)
748 else
749 20 avio_w8(pb, 0x11); // flags (= Visualstream)
750
751 73 avio_wb24(pb, bit_rates.buffer_size); // Buffersize DB
752 73 avio_wb32(pb, bit_rates.max_bit_rate); // maxbitrate
753 73 avio_wb32(pb, bit_rates.avg_bit_rate);
754
755
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 if (track->vos_len) {
756 // DecoderSpecific info descriptor
757 73 put_descr(pb, 0x05, track->vos_len);
758 73 avio_write(pb, track->vos_data, track->vos_len);
759 }
760
761 // SL descriptor
762 73 put_descr(pb, 0x06, 1);
763 73 avio_w8(pb, 0x02);
764 73 return update_size(pb, pos);
765 }
766
767 71 static int mov_pcm_le_gt16(enum AVCodecID codec_id)
768 {
769
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 return codec_id == AV_CODEC_ID_PCM_S24LE ||
770
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 codec_id == AV_CODEC_ID_PCM_S32LE ||
771
2/4
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 71 times.
142 codec_id == AV_CODEC_ID_PCM_F32LE ||
772 codec_id == AV_CODEC_ID_PCM_F64LE;
773 }
774
775 71 static int mov_pcm_be_gt16(enum AVCodecID codec_id)
776 {
777
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 4 times.
67 return codec_id == AV_CODEC_ID_PCM_S24BE ||
778
1/2
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
63 codec_id == AV_CODEC_ID_PCM_S32BE ||
779
3/4
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 63 times.
138 codec_id == AV_CODEC_ID_PCM_F32BE ||
780 codec_id == AV_CODEC_ID_PCM_F64BE;
781 }
782
783 static int mov_write_ms_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
784 {
785 int ret;
786 int64_t pos = avio_tell(pb);
787 avio_wb32(pb, 0);
788 avio_wl32(pb, track->tag); // store it byteswapped
789 track->par->codec_tag = av_bswap16(track->tag >> 16);
790 if ((ret = ff_put_wav_header(s, pb, track->par, 0)) < 0)
791 return ret;
792 return update_size(pb, pos);
793 }
794
795 static int mov_write_wfex_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
796 {
797 int ret;
798 int64_t pos = avio_tell(pb);
799 avio_wb32(pb, 0);
800 ffio_wfourcc(pb, "wfex");
801 if ((ret = ff_put_wav_header(s, pb, track->st->codecpar, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX)) < 0)
802 return ret;
803 return update_size(pb, pos);
804 }
805
806 static int mov_write_dfla_tag(AVIOContext *pb, MOVTrack *track)
807 {
808 int64_t pos = avio_tell(pb);
809 avio_wb32(pb, 0);
810 ffio_wfourcc(pb, "dfLa");
811 avio_w8(pb, 0); /* version */
812 avio_wb24(pb, 0); /* flags */
813
814 /* Expect the encoder to pass a METADATA_BLOCK_TYPE_STREAMINFO. */
815 if (track->par->extradata_size != FLAC_STREAMINFO_SIZE)
816 return AVERROR_INVALIDDATA;
817
818 /* TODO: Write other METADATA_BLOCK_TYPEs if the encoder makes them available. */
819 avio_w8(pb, 1 << 7 | FLAC_METADATA_TYPE_STREAMINFO); /* LastMetadataBlockFlag << 7 | BlockType */
820 avio_wb24(pb, track->par->extradata_size); /* Length */
821 avio_write(pb, track->par->extradata, track->par->extradata_size); /* BlockData[Length] */
822
823 return update_size(pb, pos);
824 }
825
826 static int mov_write_dops_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
827 {
828 int64_t pos = avio_tell(pb);
829 int channels, channel_map;
830 avio_wb32(pb, 0);
831 ffio_wfourcc(pb, "dOps");
832 avio_w8(pb, 0); /* Version */
833 if (track->par->extradata_size < 19) {
834 av_log(s, AV_LOG_ERROR, "invalid extradata size\n");
835 return AVERROR_INVALIDDATA;
836 }
837 /* extradata contains an Ogg OpusHead, other than byte-ordering and
838 OpusHead's preceeding magic/version, OpusSpecificBox is currently
839 identical. */
840 channels = AV_RB8(track->par->extradata + 9);
841 channel_map = AV_RB8(track->par->extradata + 18);
842
843 avio_w8(pb, channels); /* OuputChannelCount */
844 avio_wb16(pb, AV_RL16(track->par->extradata + 10)); /* PreSkip */
845 avio_wb32(pb, AV_RL32(track->par->extradata + 12)); /* InputSampleRate */
846 avio_wb16(pb, AV_RL16(track->par->extradata + 16)); /* OutputGain */
847 avio_w8(pb, channel_map); /* ChannelMappingFamily */
848 /* Write the rest of the header out without byte-swapping. */
849 if (channel_map) {
850 if (track->par->extradata_size < 21 + channels) {
851 av_log(s, AV_LOG_ERROR, "invalid extradata size\n");
852 return AVERROR_INVALIDDATA;
853 }
854 avio_write(pb, track->par->extradata + 19, 2 + channels); /* ChannelMappingTable */
855 }
856
857 return update_size(pb, pos);
858 }
859
860 static int mov_write_dmlp_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
861 {
862 int64_t pos = avio_tell(pb);
863 int length;
864 avio_wb32(pb, 0);
865 ffio_wfourcc(pb, "dmlp");
866
867 if (track->vos_len < 20) {
868 av_log(s, AV_LOG_ERROR,
869 "Cannot write moov atom before TrueHD packets."
870 " Set the delay_moov flag to fix this.\n");
871 return AVERROR(EINVAL);
872 }
873
874 length = (AV_RB16(track->vos_data) & 0xFFF) * 2;
875 if (length < 20 || length > track->vos_len)
876 return AVERROR_INVALIDDATA;
877
878 // Only TrueHD is supported
879 if (AV_RB32(track->vos_data + 4) != 0xF8726FBA)
880 return AVERROR_INVALIDDATA;
881
882 avio_wb32(pb, AV_RB32(track->vos_data + 8)); /* format_info */
883 avio_wb16(pb, AV_RB16(track->vos_data + 18) << 1); /* peak_data_rate */
884 avio_wb32(pb, 0); /* reserved */
885
886 return update_size(pb, pos);
887 }
888
889 37 static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
890 {
891 uint32_t layout_tag, bitmap, *channel_desc;
892 37 int64_t pos = avio_tell(pb);
893 int num_desc, ret;
894
895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (track->multichannel_as_mono)
896 return 0;
897
898 37 ret = ff_mov_get_channel_layout_tag(track->par, &layout_tag,
899 &bitmap, &channel_desc);
900
901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (ret < 0) {
902 if (ret == AVERROR(ENOSYS)) {
903 av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to "
904 "lack of channel information\n");
905 ret = 0;
906 }
907
908 return ret;
909 }
910
911
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
37 if (layout_tag == MOV_CH_LAYOUT_MONO && track->mono_as_fc > 0) {
912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 av_assert0(!channel_desc);
913 1 channel_desc = av_malloc(sizeof(*channel_desc));
914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!channel_desc)
915 return AVERROR(ENOMEM);
916
917 1 layout_tag = 0;
918 1 bitmap = 0;
919 1 *channel_desc = 3; // channel label "Center"
920 }
921
922
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 34 times.
37 num_desc = layout_tag ? 0 : track->par->ch_layout.nb_channels;
923
924 37 avio_wb32(pb, 0); // Size
925 37 ffio_wfourcc(pb, "chan"); // Type
926 37 avio_w8(pb, 0); // Version
927 37 avio_wb24(pb, 0); // Flags
928 37 avio_wb32(pb, layout_tag); // mChannelLayoutTag
929 37 avio_wb32(pb, bitmap); // mChannelBitmap
930 37 avio_wb32(pb, num_desc); // mNumberChannelDescriptions
931
932
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 37 times.
40 for (int i = 0; i < num_desc; i++) {
933 3 avio_wb32(pb, channel_desc[i]); // mChannelLabel
934 3 avio_wb32(pb, 0); // mChannelFlags
935 3 avio_wl32(pb, 0); // mCoordinates[0]
936 3 avio_wl32(pb, 0); // mCoordinates[1]
937 3 avio_wl32(pb, 0); // mCoordinates[2]
938 }
939
940 37 av_free(channel_desc);
941
942 37 return update_size(pb, pos);
943 }
944
945 15 static int mov_write_wave_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
946 {
947 15 int64_t pos = avio_tell(pb);
948
949 15 avio_wb32(pb, 0); /* size */
950 15 ffio_wfourcc(pb, "wave");
951
952
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (track->par->codec_id != AV_CODEC_ID_QDM2) {
953 15 avio_wb32(pb, 12); /* size */
954 15 ffio_wfourcc(pb, "frma");
955 15 avio_wl32(pb, track->tag);
956 }
957
958
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 12 times.
15 if (track->par->codec_id == AV_CODEC_ID_AAC) {
959 /* useless atom needed by mplayer, ipod, not needed by quicktime */
960 3 avio_wb32(pb, 12); /* size */
961 3 ffio_wfourcc(pb, "mp4a");
962 3 avio_wb32(pb, 0);
963 3 mov_write_esds_tag(pb, track);
964
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 } else if (mov_pcm_le_gt16(track->par->codec_id)) {
965 mov_write_enda_tag(pb);
966
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 10 times.
12 } else if (mov_pcm_be_gt16(track->par->codec_id)) {
967 2 mov_write_enda_tag_be(pb);
968
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 } else if (track->par->codec_id == AV_CODEC_ID_AMR_NB) {
969 mov_write_amr_tag(pb, track);
970
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
10 } else if (track->par->codec_id == AV_CODEC_ID_AC3) {
971 1 mov_write_ac3_tag(s, pb, track);
972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 } else if (track->par->codec_id == AV_CODEC_ID_EAC3) {
973 mov_write_eac3_tag(s, pb, track);
974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 } else if (track->par->codec_id == AV_CODEC_ID_ALAC ||
975 track->par->codec_id == AV_CODEC_ID_QDM2) {
976 9 mov_write_extradata_tag(pb, track);
977 } else if (track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
978 track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
979 mov_write_ms_tag(s, pb, track);
980 }
981
982 15 avio_wb32(pb, 8); /* size */
983 15 avio_wb32(pb, 0); /* null tag */
984
985 15 return update_size(pb, pos);
986 }
987
988 static int mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf)
989 {
990 uint8_t *unescaped;
991 const uint8_t *start, *next, *end = track->vos_data + track->vos_len;
992 int unescaped_size, seq_found = 0;
993 int level = 0, interlace = 0;
994 int packet_seq = track->vc1_info.packet_seq;
995 int packet_entry = track->vc1_info.packet_entry;
996 int slices = track->vc1_info.slices;
997 PutBitContext pbc;
998
999 if (track->start_dts == AV_NOPTS_VALUE) {
1000 /* No packets written yet, vc1_info isn't authoritative yet. */
1001 /* Assume inline sequence and entry headers. */
1002 packet_seq = packet_entry = 1;
1003 av_log(NULL, AV_LOG_WARNING,
1004 "moov atom written before any packets, unable to write correct "
1005 "dvc1 atom. Set the delay_moov flag to fix this.\n");
1006 }
1007
1008 unescaped = av_mallocz(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE);
1009 if (!unescaped)
1010 return AVERROR(ENOMEM);
1011 start = find_next_marker(track->vos_data, end);
1012 for (next = start; next < end; start = next) {
1013 GetBitContext gb;
1014 int size;
1015 next = find_next_marker(start + 4, end);
1016 size = next - start - 4;
1017 if (size <= 0)
1018 continue;
1019 unescaped_size = vc1_unescape_buffer(start + 4, size, unescaped);
1020 init_get_bits(&gb, unescaped, 8 * unescaped_size);
1021 if (AV_RB32(start) == VC1_CODE_SEQHDR) {
1022 int profile = get_bits(&gb, 2);
1023 if (profile != PROFILE_ADVANCED) {
1024 av_free(unescaped);
1025 return AVERROR(ENOSYS);
1026 }
1027 seq_found = 1;
1028 level = get_bits(&gb, 3);
1029 /* chromaformat, frmrtq_postproc, bitrtq_postproc, postprocflag,
1030 * width, height */
1031 skip_bits_long(&gb, 2 + 3 + 5 + 1 + 2*12);
1032 skip_bits(&gb, 1); /* broadcast */
1033 interlace = get_bits1(&gb);
1034 skip_bits(&gb, 4); /* tfcntrflag, finterpflag, reserved, psf */
1035 }
1036 }
1037 if (!seq_found) {
1038 av_free(unescaped);
1039 return AVERROR(ENOSYS);
1040 }
1041
1042 init_put_bits(&pbc, buf, 7);
1043 /* VC1DecSpecStruc */
1044 put_bits(&pbc, 4, 12); /* profile - advanced */
1045 put_bits(&pbc, 3, level);
1046 put_bits(&pbc, 1, 0); /* reserved */
1047 /* VC1AdvDecSpecStruc */
1048 put_bits(&pbc, 3, level);
1049 put_bits(&pbc, 1, 0); /* cbr */
1050 put_bits(&pbc, 6, 0); /* reserved */
1051 put_bits(&pbc, 1, !interlace); /* no interlace */
1052 put_bits(&pbc, 1, !packet_seq); /* no multiple seq */
1053 put_bits(&pbc, 1, !packet_entry); /* no multiple entry */
1054 put_bits(&pbc, 1, !slices); /* no slice code */
1055 put_bits(&pbc, 1, 0); /* no bframe */
1056 put_bits(&pbc, 1, 0); /* reserved */
1057
1058 /* framerate */
1059 if (track->st->avg_frame_rate.num > 0 && track->st->avg_frame_rate.den > 0)
1060 put_bits32(&pbc, track->st->avg_frame_rate.num / track->st->avg_frame_rate.den);
1061 else
1062 put_bits32(&pbc, 0xffffffff);
1063
1064 flush_put_bits(&pbc);
1065
1066 av_free(unescaped);
1067
1068 return 0;
1069 }
1070
1071 static int mov_write_dvc1_tag(AVIOContext *pb, MOVTrack *track)
1072 {
1073 uint8_t buf[7] = { 0 };
1074 int ret;
1075
1076 if ((ret = mov_write_dvc1_structs(track, buf)) < 0)
1077 return ret;
1078
1079 avio_wb32(pb, track->vos_len + 8 + sizeof(buf));
1080 ffio_wfourcc(pb, "dvc1");
1081 avio_write(pb, buf, sizeof(buf));
1082 avio_write(pb, track->vos_data, track->vos_len);
1083
1084 return 0;
1085 }
1086
1087 4 static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track)
1088 {
1089 4 avio_wb32(pb, track->vos_len + 8);
1090 4 ffio_wfourcc(pb, "glbl");
1091 4 avio_write(pb, track->vos_data, track->vos_len);
1092 4 return 8 + track->vos_len;
1093 }
1094
1095 /**
1096 * Compute flags for 'lpcm' tag.
1097 * See CoreAudioTypes and AudioStreamBasicDescription at Apple.
1098 */
1099 8 static int mov_get_lpcm_flags(enum AVCodecID codec_id)
1100 {
1101
1/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
8 switch (codec_id) {
1102 case AV_CODEC_ID_PCM_F32BE:
1103 case AV_CODEC_ID_PCM_F64BE:
1104 return 11;
1105 case AV_CODEC_ID_PCM_F32LE:
1106 case AV_CODEC_ID_PCM_F64LE:
1107 return 9;
1108 case AV_CODEC_ID_PCM_U8:
1109 return 10;
1110 case AV_CODEC_ID_PCM_S16BE:
1111 case AV_CODEC_ID_PCM_S24BE:
1112 case AV_CODEC_ID_PCM_S32BE:
1113 return 14;
1114 case AV_CODEC_ID_PCM_S8:
1115 case AV_CODEC_ID_PCM_S16LE:
1116 case AV_CODEC_ID_PCM_S24LE:
1117 case AV_CODEC_ID_PCM_S32LE:
1118 return 12;
1119 8 default:
1120 8 return 0;
1121 }
1122 }
1123
1124 24055 static int get_cluster_duration(MOVTrack *track, int cluster_idx)
1125 {
1126 int64_t next_dts;
1127
1128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24055 times.
24055 if (cluster_idx >= track->entry)
1129 return 0;
1130
1131
2/2
✓ Branch 0 taken 598 times.
✓ Branch 1 taken 23457 times.
24055 if (cluster_idx + 1 == track->entry)
1132 598 next_dts = track->track_duration + track->start_dts;
1133 else
1134 23457 next_dts = track->cluster[cluster_idx + 1].dts;
1135
1136 24055 next_dts -= track->cluster[cluster_idx].dts;
1137
1138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24055 times.
24055 av_assert0(next_dts >= 0);
1139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24055 times.
24055 av_assert0(next_dts <= INT_MAX);
1140
1141 24055 return next_dts;
1142 }
1143
1144 4 static int get_samples_per_packet(MOVTrack *track)
1145 {
1146 int i, first_duration;
1147
1148 // return track->par->frame_size;
1149
1150 /* use 1 for raw PCM */
1151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!track->audio_vbr)
1152 return 1;
1153
1154 /* check to see if duration is constant for all clusters */
1155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!track->entry)
1156 return 0;
1157 4 first_duration = get_cluster_duration(track, 0);
1158
1/2
✓ Branch 0 taken 1872 times.
✗ Branch 1 not taken.
1872 for (i = 1; i < track->entry; i++) {
1159
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1868 times.
1872 if (get_cluster_duration(track, i) != first_duration)
1160 4 return 0;
1161 }
1162 return first_duration;
1163 }
1164
1165 120 static int mov_write_btrt_tag(AVIOContext *pb, MOVTrack *track)
1166 {
1167 120 int64_t pos = avio_tell(pb);
1168 120 struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track);
1169
3/4
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 79 times.
✗ Branch 3 not taken.
120 if (!bit_rates.max_bit_rate && !bit_rates.avg_bit_rate &&
1170
1/2
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
79 !bit_rates.buffer_size)
1171 // no useful data to be written, skip
1172 79 return 0;
1173
1174 41 avio_wb32(pb, 0); /* size */
1175 41 ffio_wfourcc(pb, "btrt");
1176
1177 41 avio_wb32(pb, bit_rates.buffer_size);
1178 41 avio_wb32(pb, bit_rates.max_bit_rate);
1179 41 avio_wb32(pb, bit_rates.avg_bit_rate);
1180
1181 41 return update_size(pb, pos);
1182 }
1183
1184 5 static int mov_write_chnl_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1185 {
1186 5 int64_t pos = avio_tell(pb);
1187 5 int config = 0;
1188 int ret;
1189 5 uint8_t *speaker_pos = NULL;
1190 5 const AVChannelLayout *layout = &track->par->ch_layout;
1191
1192 5 ret = ff_mov_get_channel_config_from_layout(layout, &config);
1193
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2 times.
5 if (ret || !config) {
1194 3 config = 0;
1195 3 speaker_pos = av_malloc(layout->nb_channels);
1196 3 ret = ff_mov_get_channel_positions_from_layout(layout,
1197 3 speaker_pos, layout->nb_channels);
1198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret) {
1199 char buf[128] = {0};
1200
1201 av_freep(&speaker_pos);
1202 av_channel_layout_describe(layout, buf, sizeof(buf));
1203 av_log(s, AV_LOG_ERROR, "unsupported channel layout %s\n", buf);
1204 return ret;
1205 }
1206 }
1207
1208 5 avio_wb32(pb, 0); /* size */
1209 5 ffio_wfourcc(pb, "chnl");
1210 5 avio_wb32(pb, 0); /* version & flags */
1211
1212 5 avio_w8(pb, 1); /* stream_structure */
1213 5 avio_w8(pb, config);
1214
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if (config) {
1215 2 avio_wb64(pb, 0);
1216 } else {
1217
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 3 times.
15 for (int i = 0; i < layout->nb_channels; i++)
1218 12 avio_w8(pb, speaker_pos[i]);
1219 3 av_freep(&speaker_pos);
1220 }
1221
1222 5 return update_size(pb, pos);
1223 }
1224
1225 7 static int mov_write_pcmc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1226 {
1227 7 int64_t pos = avio_tell(pb);
1228 int format_flags;
1229 int sample_size;
1230
1231 7 avio_wb32(pb, 0); /* size */
1232 7 ffio_wfourcc(pb, "pcmC");
1233 7 avio_wb32(pb, 0); /* version & flags */
1234
1235 /* 0x01: indicates little-endian format */
1236 20 format_flags = (track->par->codec_id == AV_CODEC_ID_PCM_F32LE ||
1237
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 track->par->codec_id == AV_CODEC_ID_PCM_F64LE ||
1238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 track->par->codec_id == AV_CODEC_ID_PCM_S16LE ||
1239
2/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
13 track->par->codec_id == AV_CODEC_ID_PCM_S24LE ||
1240 track->par->codec_id == AV_CODEC_ID_PCM_S32LE);
1241 7 avio_w8(pb, format_flags);
1242 7 sample_size = track->par->bits_per_raw_sample;
1243
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (!sample_size)
1244 1 sample_size = av_get_exact_bits_per_sample(track->par->codec_id);
1245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 av_assert0(sample_size);
1246 7 avio_w8(pb, sample_size);
1247
1248 7 return update_size(pb, pos);
1249 }
1250
1251 99 static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
1252 {
1253 99 int64_t pos = avio_tell(pb);
1254 99 int version = 0;
1255 99 uint32_t tag = track->tag;
1256 99 int ret = 0;
1257
1258
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 62 times.
99 if (track->mode == MODE_MOV) {
1259
3/4
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 33 times.
37 if (track->timescale > UINT16_MAX || !track->par->ch_layout.nb_channels) {
1260
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (mov_get_lpcm_flags(track->par->codec_id))
1261 tag = AV_RL32("lpcm");
1262 4 version = 2;
1263
5/6
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 10 times.
✓ Branch 3 taken 23 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
✓ Branch 6 taken 2 times.
56 } else if (track->audio_vbr || mov_pcm_le_gt16(track->par->codec_id) ||
1264 23 mov_pcm_be_gt16(track->par->codec_id) ||
1265
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1266
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
1267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 track->par->codec_id == AV_CODEC_ID_QDM2) {
1268 12 version = 1;
1269 }
1270 }
1271
1272 99 avio_wb32(pb, 0); /* size */
1273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (mov->encryption_scheme != MOV_ENC_NONE) {
1274 ffio_wfourcc(pb, "enca");
1275 } else {
1276 99 avio_wl32(pb, tag); // store it byteswapped
1277 }
1278 99 avio_wb32(pb, 0); /* Reserved */
1279 99 avio_wb16(pb, 0); /* Reserved */
1280 99 avio_wb16(pb, 1); /* Data-reference index, XXX == 1 */
1281
1282 /* SoundDescription */
1283 99 avio_wb16(pb, version); /* Version */
1284 99 avio_wb16(pb, 0); /* Revision level */
1285 99 avio_wb32(pb, 0); /* Reserved */
1286
1287
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 95 times.
99 if (version == 2) {
1288 4 avio_wb16(pb, 3);
1289 4 avio_wb16(pb, 16);
1290 4 avio_wb16(pb, 0xfffe);
1291 4 avio_wb16(pb, 0);
1292 4 avio_wb32(pb, 0x00010000);
1293 4 avio_wb32(pb, 72);
1294 4 avio_wb64(pb, av_double2int(track->par->sample_rate));
1295 4 avio_wb32(pb, track->par->ch_layout.nb_channels);
1296 4 avio_wb32(pb, 0x7F000000);
1297 4 avio_wb32(pb, av_get_bits_per_sample(track->par->codec_id));
1298 4 avio_wb32(pb, mov_get_lpcm_flags(track->par->codec_id));
1299 4 avio_wb32(pb, track->sample_size);
1300 4 avio_wb32(pb, get_samples_per_packet(track));
1301 } else {
1302
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 62 times.
95 if (track->mode == MODE_MOV) {
1303 33 avio_wb16(pb, track->par->ch_layout.nb_channels);
1304
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if (track->par->codec_id == AV_CODEC_ID_PCM_U8 ||
1305
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 32 times.
33 track->par->codec_id == AV_CODEC_ID_PCM_S8)
1306 1 avio_wb16(pb, 8); /* bits per sample */
1307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 else if (track->par->codec_id == AV_CODEC_ID_ADPCM_G726)
1308 avio_wb16(pb, track->par->bits_per_coded_sample);
1309 else
1310 32 avio_wb16(pb, 16);
1311
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 23 times.
33 avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
1312 } else { /* reserved for mp4/3gp */
1313 62 avio_wb16(pb, track->par->ch_layout.nb_channels);
1314
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 if (track->par->codec_id == AV_CODEC_ID_FLAC ||
1315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 track->par->codec_id == AV_CODEC_ID_ALAC) {
1316 avio_wb16(pb, track->par->bits_per_raw_sample);
1317 } else {
1318 62 avio_wb16(pb, 16);
1319 }
1320 62 avio_wb16(pb, 0);
1321 }
1322
1323 95 avio_wb16(pb, 0); /* packet size (= 0) */
1324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
95 if (track->par->codec_id == AV_CODEC_ID_OPUS)
1325 avio_wb16(pb, 48000);
1326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
95 else if (track->par->codec_id == AV_CODEC_ID_TRUEHD)
1327 avio_wb32(pb, track->par->sample_rate);
1328 else
1329
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
190 avio_wb16(pb, track->par->sample_rate <= UINT16_MAX ?
1330 95 track->par->sample_rate : 0);
1331
1332
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 if (track->par->codec_id != AV_CODEC_ID_TRUEHD)
1333 95 avio_wb16(pb, 0); /* Reserved */
1334 }
1335
1336
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 87 times.
99 if (version == 1) { /* SoundDescription V1 extended info */
1337
3/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 10 times.
24 if (mov_pcm_le_gt16(track->par->codec_id) ||
1338 12 mov_pcm_be_gt16(track->par->codec_id))
1339 2 avio_wb32(pb, 1); /* must be 1 for uncompressed formats */
1340 else
1341 10 avio_wb32(pb, track->par->frame_size); /* Samples per packet */
1342 12 avio_wb32(pb, track->sample_size / track->par->ch_layout.nb_channels); /* Bytes per packet */
1343 12 avio_wb32(pb, track->sample_size); /* Bytes per frame */
1344 12 avio_wb32(pb, 2); /* Bytes per sample */
1345 }
1346
1347
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 62 times.
99 if (track->mode == MODE_MOV &&
1348
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 3 times.
37 (track->par->codec_id == AV_CODEC_ID_AAC ||
1349
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 1 times.
34 track->par->codec_id == AV_CODEC_ID_AC3 ||
1350
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 track->par->codec_id == AV_CODEC_ID_EAC3 ||
1351
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 track->par->codec_id == AV_CODEC_ID_AMR_NB ||
1352
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 9 times.
33 track->par->codec_id == AV_CODEC_ID_ALAC ||
1353
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
1354
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
1355
2/4
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
48 track->par->codec_id == AV_CODEC_ID_QDM2 ||
1356
2/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 22 times.
48 (mov_pcm_le_gt16(track->par->codec_id) && version==1) ||
1357
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
26 (mov_pcm_be_gt16(track->par->codec_id) && version==1)))
1358 15 ret = mov_write_wave_tag(s, pb, track);
1359
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 34 times.
84 else if (track->tag == MKTAG('m','p','4','a'))
1360 50 ret = mov_write_esds_tag(pb, track);
1361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 else if (track->par->codec_id == AV_CODEC_ID_AMR_NB)
1362 ret = mov_write_amr_tag(pb, track);
1363
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 30 times.
34 else if (track->par->codec_id == AV_CODEC_ID_AC3)
1364 4 ret = mov_write_ac3_tag(s, pb, track);
1365
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 29 times.
30 else if (track->par->codec_id == AV_CODEC_ID_EAC3)
1366 1 ret = mov_write_eac3_tag(s, pb, track);
1367
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 else if (track->par->codec_id == AV_CODEC_ID_ALAC)
1368 ret = mov_write_extradata_tag(pb, track);
1369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 else if (track->par->codec_id == AV_CODEC_ID_WMAPRO)
1370 ret = mov_write_wfex_tag(s, pb, track);
1371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 else if (track->par->codec_id == AV_CODEC_ID_FLAC)
1372 ret = mov_write_dfla_tag(pb, track);
1373
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 else if (track->par->codec_id == AV_CODEC_ID_OPUS)
1374 ret = mov_write_dops_tag(s, pb, track);
1375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 else if (track->par->codec_id == AV_CODEC_ID_TRUEHD)
1376 ret = mov_write_dmlp_tag(s, pb, track);
1377
4/4
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 22 times.
29 else if (tag == MOV_MP4_IPCM_TAG || tag == MOV_MP4_FPCM_TAG) {
1378
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
7 if (track->par->ch_layout.nb_channels > 1)
1379 5 ret = mov_write_chnl_tag(s, pb, track);
1380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
1381 return ret;
1382 7 ret = mov_write_pcmc_tag(s, pb, track);
1383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 } else if (track->vos_len > 0)
1384 ret = mov_write_glbl_tag(pb, track);
1385
1386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (ret < 0)
1387 return ret;
1388
1389
3/4
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 62 times.
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
99 if (track->mode == MODE_MOV && track->par->codec_type == AVMEDIA_TYPE_AUDIO
1390
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
37 && ((ret = mov_write_chan_tag(s, pb, track)) < 0)) {
1391 return ret;
1392 }
1393
1394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (mov->encryption_scheme != MOV_ENC_NONE
1395 && ((ret = ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid)) < 0)) {
1396 return ret;
1397 }
1398
1399
3/4
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 59 times.
158 if (mov->write_btrt &&
1400 59 ((ret = mov_write_btrt_tag(pb, track)) < 0))
1401 return ret;
1402
1403 99 ret = update_size(pb, pos);
1404 99 return ret;
1405 }
1406
1407 static int mov_write_d263_tag(AVIOContext *pb)
1408 {
1409 avio_wb32(pb, 0xf); /* size */
1410 ffio_wfourcc(pb, "d263");
1411 ffio_wfourcc(pb, "FFMP");
1412 avio_w8(pb, 0); /* decoder version */
1413 /* FIXME use AVCodecContext level/profile, when encoder will set values */
1414 avio_w8(pb, 0xa); /* level */
1415 avio_w8(pb, 0); /* profile */
1416 return 0xf;
1417 }
1418
1419 1 static int mov_write_av1c_tag(AVIOContext *pb, MOVTrack *track)
1420 {
1421 1 int64_t pos = avio_tell(pb);
1422
1423 1 avio_wb32(pb, 0);
1424 1 ffio_wfourcc(pb, "av1C");
1425 1 ff_isom_write_av1c(pb, track->vos_data, track->vos_len, track->mode != MODE_AVIF);
1426 1 return update_size(pb, pos);
1427 }
1428
1429 51 static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
1430 {
1431 51 int64_t pos = avio_tell(pb);
1432
1433 51 avio_wb32(pb, 0);
1434 51 ffio_wfourcc(pb, "avcC");
1435 51 ff_isom_write_avcc(pb, track->vos_data, track->vos_len);
1436 51 return update_size(pb, pos);
1437 }
1438
1439 static int mov_write_vpcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
1440 {
1441 int64_t pos = avio_tell(pb);
1442
1443 avio_wb32(pb, 0);
1444 ffio_wfourcc(pb, "vpcC");
1445 ff_isom_write_vpcc(s, pb, track->vos_data, track->vos_len, track->par);
1446 return update_size(pb, pos);
1447 }
1448
1449 1 static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track)
1450 {
1451 1 int64_t pos = avio_tell(pb);
1452
1453 1 avio_wb32(pb, 0);
1454 1 ffio_wfourcc(pb, "hvcC");
1455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (track->tag == MKTAG('h','v','c','1'))
1456 ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 1);
1457 else
1458 1 ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0);
1459 1 return update_size(pb, pos);
1460 }
1461
1462 1 static int mov_write_evcc_tag(AVIOContext *pb, MOVTrack *track)
1463 {
1464 1 int64_t pos = avio_tell(pb);
1465
1466 1 avio_wb32(pb, 0);
1467 1 ffio_wfourcc(pb, "evcC");
1468
1469
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (track->tag == MKTAG('e','v','c','1'))
1470 1 ff_isom_write_evcc(pb, track->vos_data, track->vos_len, 1);
1471 else
1472 ff_isom_write_evcc(pb, track->vos_data, track->vos_len, 0);
1473
1474 1 return update_size(pb, pos);
1475 }
1476
1477 static int mov_write_vvcc_tag(AVIOContext *pb, MOVTrack *track)
1478 {
1479 int64_t pos = avio_tell(pb);
1480
1481 avio_wb32(pb, 0);
1482 ffio_wfourcc(pb, "vvcC");
1483
1484 avio_w8 (pb, 0); /* version */
1485 avio_wb24(pb, 0); /* flags */
1486
1487 if (track->tag == MKTAG('v','v','c','1'))
1488 ff_isom_write_vvcc(pb, track->vos_data, track->vos_len, 1);
1489 else
1490 ff_isom_write_vvcc(pb, track->vos_data, track->vos_len, 0);
1491 return update_size(pb, pos);
1492 }
1493
1494 /* also used by all avid codecs (dv, imx, meridien) and their variants */
1495 23 static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
1496 {
1497 int interlaced;
1498 int cid;
1499 23 int display_width = track->par->width;
1500
1501
2/4
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
23 if (track->vos_data && track->vos_len > 0x29) {
1502
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
46 if (ff_dnxhd_parse_header_prefix(track->vos_data) != 0) {
1503 /* looks like a DNxHD bit stream */
1504 23 interlaced = (track->vos_data[5] & 2);
1505 23 cid = AV_RB32(track->vos_data + 0x28);
1506 } else {
1507 av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream in vos_data\n");
1508 return 0;
1509 }
1510 } else {
1511 av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream, vos_data too small\n");
1512 return 0;
1513 }
1514
1515 23 avio_wb32(pb, 24); /* size */
1516 23 ffio_wfourcc(pb, "ACLR");
1517 23 ffio_wfourcc(pb, "ACLR");
1518 23 ffio_wfourcc(pb, "0001");
1519
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 if (track->par->color_range == AVCOL_RANGE_MPEG || /* Legal range (16-235) */
1520
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 track->par->color_range == AVCOL_RANGE_UNSPECIFIED) {
1521 23 avio_wb32(pb, 1); /* Corresponds to 709 in official encoder */
1522 } else { /* Full range (0-255) */
1523 avio_wb32(pb, 2); /* Corresponds to RGB in official encoder */
1524 }
1525 23 avio_wb32(pb, 0); /* unknown */
1526
1527
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 11 times.
23 if (track->tag == MKTAG('A','V','d','h')) {
1528 12 avio_wb32(pb, 32);
1529 12 ffio_wfourcc(pb, "ADHR");
1530 12 ffio_wfourcc(pb, "0001");
1531 12 avio_wb32(pb, cid);
1532 12 avio_wb32(pb, 0); /* unknown */
1533 12 avio_wb32(pb, 1); /* unknown */
1534 12 avio_wb32(pb, 0); /* unknown */
1535 12 avio_wb32(pb, 0); /* unknown */
1536 12 return 0;
1537 }
1538
1539 11 avio_wb32(pb, 24); /* size */
1540 11 ffio_wfourcc(pb, "APRG");
1541 11 ffio_wfourcc(pb, "APRG");
1542 11 ffio_wfourcc(pb, "0001");
1543 11 avio_wb32(pb, 1); /* unknown */
1544 11 avio_wb32(pb, 0); /* unknown */
1545
1546 11 avio_wb32(pb, 120); /* size */
1547 11 ffio_wfourcc(pb, "ARES");
1548 11 ffio_wfourcc(pb, "ARES");
1549 11 ffio_wfourcc(pb, "0001");
1550 11 avio_wb32(pb, cid); /* dnxhd cid, some id ? */
1551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if ( track->par->sample_aspect_ratio.num > 0
1552 && track->par->sample_aspect_ratio.den > 0)
1553 display_width = display_width * track->par->sample_aspect_ratio.num / track->par->sample_aspect_ratio.den;
1554 11 avio_wb32(pb, display_width);
1555 /* values below are based on samples created with quicktime and avid codecs */
1556
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (interlaced) {
1557 11 avio_wb32(pb, track->par->height / 2);
1558 11 avio_wb32(pb, 2); /* unknown */
1559 11 avio_wb32(pb, 0); /* unknown */
1560 11 avio_wb32(pb, 4); /* unknown */
1561 } else {
1562 avio_wb32(pb, track->par->height);
1563 avio_wb32(pb, 1); /* unknown */
1564 avio_wb32(pb, 0); /* unknown */
1565 if (track->par->height == 1080)
1566 avio_wb32(pb, 5); /* unknown */
1567 else
1568 avio_wb32(pb, 6); /* unknown */
1569 }
1570 /* padding */
1571 11 ffio_fill(pb, 0, 10 * 8);
1572
1573 11 return 0;
1574 }
1575
1576 static int mov_write_dpxe_tag(AVIOContext *pb, MOVTrack *track)
1577 {
1578 avio_wb32(pb, 12);
1579 ffio_wfourcc(pb, "DpxE");
1580 if (track->par->extradata_size >= 12 &&
1581 !memcmp(&track->par->extradata[4], "DpxE", 4)) {
1582 avio_wb32(pb, track->par->extradata[11]);
1583 } else {
1584 avio_wb32(pb, 1);
1585 }
1586 return 0;
1587 }
1588
1589 1 static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)
1590 {
1591 int tag;
1592
1593
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (track->par->width == 720) { /* SD */
1594
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (track->par->height == 480) { /* NTSC */
1595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
1596 1 else tag = MKTAG('d','v','c',' ');
1597 }else if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
1598 else if (track->par->format == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
1599 else tag = MKTAG('d','v','p','p');
1600 } else if (track->par->height == 720) { /* HD 720 line */
1601 if (track->st->time_base.den == 50) tag = MKTAG('d','v','h','q');
1602 else tag = MKTAG('d','v','h','p');
1603 } else if (track->par->height == 1080) { /* HD 1080 line */
1604 if (track->st->time_base.den == 25) tag = MKTAG('d','v','h','5');
1605 else tag = MKTAG('d','v','h','6');
1606 } else {
1607 av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n");
1608 return 0;
1609 }
1610
1611 1 return tag;
1612 }
1613
1614 2 static int defined_frame_rate(AVFormatContext *s, AVStream *st)
1615 {
1616 2 AVRational rational_framerate = st->avg_frame_rate;
1617 2 int rate = 0;
1618
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (rational_framerate.den != 0)
1619 2 rate = av_q2d(rational_framerate);
1620 2 return rate;
1621 }
1622
1623 1 static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track)
1624 {
1625 1 int tag = track->par->codec_tag;
1626 1 int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
1627 1 AVStream *st = track->st;
1628 1 int rate = defined_frame_rate(s, st);
1629
1630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!tag)
1631 tag = MKTAG('m', '2', 'v', '1'); //fallback tag
1632
1633
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (track->par->format == AV_PIX_FMT_YUV420P) {
1634
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (track->par->width == 1280 && track->par->height == 720) {
1635 if (!interlaced) {
1636 if (rate == 24) tag = MKTAG('x','d','v','4');
1637 else if (rate == 25) tag = MKTAG('x','d','v','5');
1638 else if (rate == 30) tag = MKTAG('x','d','v','1');
1639 else if (rate == 50) tag = MKTAG('x','d','v','a');
1640 else if (rate == 60) tag = MKTAG('x','d','v','9');
1641 }
1642
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 } else if (track->par->width == 1440 && track->par->height == 1080) {
1643 if (!interlaced) {
1644 if (rate == 24) tag = MKTAG('x','d','v','6');
1645 else if (rate == 25) tag = MKTAG('x','d','v','7');
1646 else if (rate == 30) tag = MKTAG('x','d','v','8');
1647 } else {
1648 if (rate == 25) tag = MKTAG('x','d','v','3');
1649 else if (rate == 30) tag = MKTAG('x','d','v','2');
1650 }
1651
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 } else if (track->par->width == 1920 && track->par->height == 1080) {
1652 if (!interlaced) {
1653 if (rate == 24) tag = MKTAG('x','d','v','d');
1654 else if (rate == 25) tag = MKTAG('x','d','v','e');
1655 else if (rate == 30) tag = MKTAG('x','d','v','f');
1656 } else {
1657 if (rate == 25) tag = MKTAG('x','d','v','c');
1658 else if (rate == 30) tag = MKTAG('x','d','v','b');
1659 }
1660 }
1661 } else if (track->par->format == AV_PIX_FMT_YUV422P) {
1662 if (track->par->width == 1280 && track->par->height == 720) {
1663 if (!interlaced) {
1664 if (rate == 24) tag = MKTAG('x','d','5','4');
1665 else if (rate == 25) tag = MKTAG('x','d','5','5');
1666 else if (rate == 30) tag = MKTAG('x','d','5','1');
1667 else if (rate == 50) tag = MKTAG('x','d','5','a');
1668 else if (rate == 60) tag = MKTAG('x','d','5','9');
1669 }
1670 } else if (track->par->width == 1920 && track->par->height == 1080) {
1671 if (!interlaced) {
1672 if (rate == 24) tag = MKTAG('x','d','5','d');
1673 else if (rate == 25) tag = MKTAG('x','d','5','e');
1674 else if (rate == 30) tag = MKTAG('x','d','5','f');
1675 } else {
1676 if (rate == 25) tag = MKTAG('x','d','5','c');
1677 else if (rate == 30) tag = MKTAG('x','d','5','b');
1678 }
1679 }
1680 }
1681
1682 1 return tag;
1683 }
1684
1685 1 static int mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track)
1686 {
1687 1 int tag = track->par->codec_tag;
1688 1 int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
1689 1 AVStream *st = track->st;
1690 1 int rate = defined_frame_rate(s, st);
1691
1692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!tag)
1693 tag = MKTAG('a', 'v', 'c', 'i'); //fallback tag
1694
1695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (track->par->format == AV_PIX_FMT_YUV420P10) {
1696 if (track->par->width == 960 && track->par->height == 720) {
1697 if (!interlaced) {
1698 if (rate == 24) tag = MKTAG('a','i','5','p');
1699 else if (rate == 25) tag = MKTAG('a','i','5','q');
1700 else if (rate == 30) tag = MKTAG('a','i','5','p');
1701 else if (rate == 50) tag = MKTAG('a','i','5','q');
1702 else if (rate == 60) tag = MKTAG('a','i','5','p');
1703 }
1704 } else if (track->par->width == 1440 && track->par->height == 1080) {
1705 if (!interlaced) {
1706 if (rate == 24) tag = MKTAG('a','i','5','3');
1707 else if (rate == 25) tag = MKTAG('a','i','5','2');
1708 else if (rate == 30) tag = MKTAG('a','i','5','3');
1709 } else {
1710 if (rate == 50) tag = MKTAG('a','i','5','5');
1711 else if (rate == 60) tag = MKTAG('a','i','5','6');
1712 }
1713 }
1714
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (track->par->format == AV_PIX_FMT_YUV422P10) {
1715 if (track->par->width == 1280 && track->par->height == 720) {
1716 if (!interlaced) {
1717 if (rate == 24) tag = MKTAG('a','i','1','p');
1718 else if (rate == 25) tag = MKTAG('a','i','1','q');
1719 else if (rate == 30) tag = MKTAG('a','i','1','p');
1720 else if (rate == 50) tag = MKTAG('a','i','1','q');
1721 else if (rate == 60) tag = MKTAG('a','i','1','p');
1722 }
1723 } else if (track->par->width == 1920 && track->par->height == 1080) {
1724 if (!interlaced) {
1725 if (rate == 24) tag = MKTAG('a','i','1','3');
1726 else if (rate == 25) tag = MKTAG('a','i','1','2');
1727 else if (rate == 30) tag = MKTAG('a','i','1','3');
1728 } else {
1729 if (rate == 25) tag = MKTAG('a','i','1','5');
1730 else if (rate == 50) tag = MKTAG('a','i','1','5');
1731 else if (rate == 60) tag = MKTAG('a','i','1','6');
1732 }
1733 } else if ( track->par->width == 4096 && track->par->height == 2160
1734 || track->par->width == 3840 && track->par->height == 2160
1735 || track->par->width == 2048 && track->par->height == 1080) {
1736 tag = MKTAG('a','i','v','x');
1737 }
1738 }
1739
1740 1 return tag;
1741 }
1742
1743 static int mov_get_evc_codec_tag(AVFormatContext *s, MOVTrack *track)
1744 {
1745 int tag = track->par->codec_tag;
1746
1747 if (!tag)
1748 tag = MKTAG('e', 'v', 'c', '1');
1749
1750 return tag;
1751 }
1752
1753 static const struct {
1754 enum AVPixelFormat pix_fmt;
1755 uint32_t tag;
1756 unsigned bps;
1757 } mov_pix_fmt_tags[] = {
1758 { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','2'), 0 },
1759 { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','s'), 0 },
1760 { AV_PIX_FMT_UYVY422, MKTAG('2','v','u','y'), 0 },
1761 { AV_PIX_FMT_RGB555BE,MKTAG('r','a','w',' '), 16 },
1762 { AV_PIX_FMT_RGB555LE,MKTAG('L','5','5','5'), 16 },
1763 { AV_PIX_FMT_RGB565LE,MKTAG('L','5','6','5'), 16 },
1764 { AV_PIX_FMT_RGB565BE,MKTAG('B','5','6','5'), 16 },
1765 { AV_PIX_FMT_GRAY16BE,MKTAG('b','1','6','g'), 16 },
1766 { AV_PIX_FMT_RGB24, MKTAG('r','a','w',' '), 24 },
1767 { AV_PIX_FMT_BGR24, MKTAG('2','4','B','G'), 24 },
1768 { AV_PIX_FMT_ARGB, MKTAG('r','a','w',' '), 32 },
1769 { AV_PIX_FMT_BGRA, MKTAG('B','G','R','A'), 32 },
1770 { AV_PIX_FMT_RGBA, MKTAG('R','G','B','A'), 32 },
1771 { AV_PIX_FMT_ABGR, MKTAG('A','B','G','R'), 32 },
1772 { AV_PIX_FMT_RGB48BE, MKTAG('b','4','8','r'), 48 },
1773 };
1774
1775 23 static int mov_get_dnxhd_codec_tag(AVFormatContext *s, MOVTrack *track)
1776 {
1777 23 int tag = MKTAG('A','V','d','n');
1778
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 if (track->par->profile != AV_PROFILE_UNKNOWN &&
1779
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 11 times.
23 track->par->profile != AV_PROFILE_DNXHD)
1780 12 tag = MKTAG('A','V','d','h');
1781 23 return tag;
1782 }
1783
1784 12 static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track)
1785 {
1786 12 int tag = track->par->codec_tag;
1787 int i;
1788 enum AVPixelFormat pix_fmt;
1789
1790
2/2
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 12 times.
192 for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) {
1791
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 168 times.
180 if (track->par->format == mov_pix_fmt_tags[i].pix_fmt) {
1792 12 tag = mov_pix_fmt_tags[i].tag;
1793 12 track->par->bits_per_coded_sample = mov_pix_fmt_tags[i].bps;
1794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (track->par->codec_tag == mov_pix_fmt_tags[i].tag)
1795 break;
1796 }
1797 }
1798
1799 12 pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_MOV,
1800 12 track->par->bits_per_coded_sample);
1801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (tag == MKTAG('r','a','w',' ') &&
1802 track->par->format != pix_fmt &&
1803 track->par->format != AV_PIX_FMT_GRAY8 &&
1804 track->par->format != AV_PIX_FMT_NONE)
1805 av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to mov, output file will be unreadable\n",
1806 av_get_pix_fmt_name(track->par->format));
1807 12 return tag;
1808 }
1809
1810 156 static unsigned int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
1811 {
1812 156 unsigned int tag = track->par->codec_tag;
1813
1814 // "rtp " is used to distinguish internally created RTP-hint tracks
1815 // (with rtp_ctx) from other tracks.
1816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 156 times.
156 if (tag == MKTAG('r','t','p',' '))
1817 tag = 0;
1818
3/4
✓ Branch 0 taken 156 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 120 times.
✓ Branch 3 taken 36 times.
156 if (!tag || (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
1819
2/2
✓ Branch 0 taken 119 times.
✓ Branch 1 taken 1 times.
120 (track->par->codec_id == AV_CODEC_ID_DVVIDEO ||
1820
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 12 times.
119 track->par->codec_id == AV_CODEC_ID_RAWVIDEO ||
1821
1/2
✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
107 track->par->codec_id == AV_CODEC_ID_H263 ||
1822
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 1 times.
107 track->par->codec_id == AV_CODEC_ID_H264 ||
1823
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 23 times.
106 track->par->codec_id == AV_CODEC_ID_DNXHD ||
1824
4/4
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 65 times.
165 track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO ||
1825 82 av_get_bits_per_sample(track->par->codec_id)))) { // pcm audio
1826
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 54 times.
55 if (track->par->codec_id == AV_CODEC_ID_DVVIDEO)
1827 1 tag = mov_get_dv_codec_tag(s, track);
1828
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 42 times.
54 else if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO)
1829 12 tag = mov_get_rawvideo_codec_tag(s, track);
1830
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 41 times.
42 else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1831 1 tag = mov_get_mpeg2_xdcam_codec_tag(s, track);
1832
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 40 times.
41 else if (track->par->codec_id == AV_CODEC_ID_H264)
1833 1 tag = mov_get_h264_codec_tag(s, track);
1834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 else if (track->par->codec_id == AV_CODEC_ID_EVC)
1835 tag = mov_get_evc_codec_tag(s, track);
1836
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 17 times.
40 else if (track->par->codec_id == AV_CODEC_ID_DNXHD)
1837 23 tag = mov_get_dnxhd_codec_tag(s, track);
1838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
1839 tag = ff_codec_get_tag(ff_codec_movvideo_tags, track->par->codec_id);
1840 if (!tag) { // if no mac fcc found, try with Microsoft tags
1841 tag = ff_codec_get_tag(ff_codec_bmp_tags, track->par->codec_id);
1842 if (tag)
1843 av_log(s, AV_LOG_WARNING, "Using MS style video codec tag, "
1844 "the file may be unplayable!\n");
1845 }
1846
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
1847 17 tag = ff_codec_get_tag(ff_codec_movaudio_tags, track->par->codec_id);
1848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (!tag) { // if no mac fcc found, try with Microsoft tags
1849 int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->par->codec_id);
1850 if (ms_tag) {
1851 tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
1852 av_log(s, AV_LOG_WARNING, "Using MS style audio codec tag, "
1853 "the file may be unplayable!\n");
1854 }
1855 }
1856 } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
1857 tag = ff_codec_get_tag(ff_codec_movsubtitle_tags, track->par->codec_id);
1858 }
1859
1860 156 return tag;
1861 }
1862
1863 static const AVCodecTag codec_cover_image_tags[] = {
1864 { AV_CODEC_ID_MJPEG, 0xD },
1865 { AV_CODEC_ID_PNG, 0xE },
1866 { AV_CODEC_ID_BMP, 0x1B },
1867 { AV_CODEC_ID_NONE, 0 },
1868 };
1869
1870 89 static unsigned int validate_codec_tag(const AVCodecTag *const *tags,
1871 unsigned int tag, int codec_id)
1872 {
1873 int i;
1874
1875 /**
1876 * Check that tag + id is in the table
1877 */
1878
2/4
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 89 times.
✗ Branch 3 not taken.
89 for (i = 0; tags && tags[i]; i++) {
1879 89 const AVCodecTag *codec_tags = tags[i];
1880
1/2
✓ Branch 0 taken 1256 times.
✗ Branch 1 not taken.
1256 while (codec_tags->id != AV_CODEC_ID_NONE) {
1881
2/2
✓ Branch 2 taken 101 times.
✓ Branch 3 taken 1155 times.
1256 if (ff_toupper4(codec_tags->tag) == ff_toupper4(tag) &&
1882
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 12 times.
101 codec_tags->id == codec_id)
1883 89 return codec_tags->tag;
1884 1167 codec_tags++;
1885 }
1886 }
1887 return 0;
1888 }
1889
1890 247 static unsigned int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
1891 {
1892
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 245 times.
247 if (is_cover_image(track->st))
1893 2 return ff_codec_get_tag(codec_cover_image_tags, track->par->codec_id);
1894
1895
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 244 times.
245 if (track->mode == MODE_IPOD)
1896
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
2 if (!av_match_ext(s->url, "m4a") &&
1897
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 !av_match_ext(s->url, "m4v") &&
1898 1 !av_match_ext(s->url, "m4b"))
1899 1 av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v "
1900 "Quicktime/Ipod might not play the file\n");
1901