FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2026-10-13 05:06:32
Exec Total Coverage
Lines: 5046 7858 64.2%
Functions: 205 243 84.4%
Branches: 2886 5295 54.5%

Line Branch Exec Source
1 /*
2 * MOV demuxer
3 * Copyright (c) 2001 Fabrice Bellard
4 * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
5 *
6 * first version by Francois Revol <revol@free.fr>
7 * seek function by Gael Chardon <gael.dev@4now.net>
8 *
9 * This file is part of FFmpeg.
10 *
11 * FFmpeg is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * FFmpeg is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with FFmpeg; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #include "config_components.h"
27
28 #include <inttypes.h>
29 #include <limits.h>
30 #include <stdint.h>
31 #include <stdlib.h>
32
33 #include "libavutil/attributes.h"
34 #include "libavutil/bprint.h"
35 #include "libavutil/channel_layout.h"
36 #include "libavutil/dovi_meta.h"
37 #include "libavutil/internal.h"
38 #include "libavutil/intreadwrite.h"
39 #include "libavutil/intfloat.h"
40 #include "libavutil/mathematics.h"
41 #include "libavutil/avassert.h"
42 #include "libavutil/avstring.h"
43 #include "libavutil/dict.h"
44 #include "libavutil/display.h"
45 #include "libavutil/mem.h"
46 #include "libavutil/opt.h"
47 #include "libavutil/aes.h"
48 #include "libavutil/aes_ctr.h"
49 #include "libavutil/gain_map.h"
50 #include "libavutil/pixdesc.h"
51 #include "libavutil/sha.h"
52 #include "libavutil/spherical.h"
53 #include "libavutil/stereo3d.h"
54 #include "libavutil/timecode.h"
55 #include "libavutil/uuid.h"
56 #include "libavcodec/ac3tab.h"
57 #include "libavcodec/exif.h"
58 #include "libavcodec/flac.h"
59 #include "libavcodec/hevc/hevc.h"
60 #include "libavcodec/mpegaudiodata.h"
61 #include "libavcodec/mpegaudiodecheader.h"
62 #include "libavcodec/mlp_parse.h"
63 #include "avformat.h"
64 #include "internal.h"
65 #include "avio_internal.h"
66 #include "demux.h"
67 #include "dvdclut.h"
68 #include "iamf_parse.h"
69 #include "iamf_reader.h"
70 #include "dovi_isom.h"
71 #include "riff.h"
72 #include "isom.h"
73 #include "libavcodec/get_bits.h"
74 #include "id3v1.h"
75 #include "mov_chan.h"
76 #include "replaygain.h"
77
78 #if CONFIG_ZLIB
79 #include <zlib.h>
80 #endif
81
82 #include "qtpalette.h"
83
84 /* those functions parse an atom */
85 /* links atom IDs to parse functions */
86 typedef struct MOVParseTableEntry {
87 uint32_t type;
88 int (*parse)(MOVContext *ctx, AVIOContext *pb, MOVAtom atom);
89 } MOVParseTableEntry;
90
91 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom);
92 static int mov_read_mfra(MOVContext *c, AVIOContext *f);
93 static void mov_free_stream_context(AVFormatContext *s, AVStream *st);
94
95 32 static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
96 unsigned len, const char *key)
97 {
98 char buf[16];
99
100 32 short current, total = 0;
101 32 avio_rb16(pb); // unknown
102 32 current = avio_rb16(pb);
103
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (len >= 6)
104 32 total = avio_rb16(pb);
105
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 25 times.
32 if (!total)
106 7 snprintf(buf, sizeof(buf), "%d", current);
107 else
108 25 snprintf(buf, sizeof(buf), "%d/%d", current, total);
109 32 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
110 32 av_dict_set(&c->fc->metadata, key, buf, 0);
111
112 32 return 0;
113 }
114
115 ✗ static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
116 unsigned len, const char *key)
117 {
118 /* bypass padding bytes */
119 ✗ avio_r8(pb);
120 ✗ avio_r8(pb);
121 ✗ avio_r8(pb);
122
123 ✗ c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
124 ✗ av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
125
126 ✗ return 0;
127 }
128
129 30 static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
130 unsigned len, const char *key)
131 {
132 30 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
133 30 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
134
135 30 return 0;
136 }
137
138 12 static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
139 unsigned len, const char *key)
140 {
141 short genre;
142
143 12 avio_r8(pb); // unknown
144
145 12 genre = avio_r8(pb);
146
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (genre < 1 || genre > ID3v1_GENRE_MAX)
147 ✗ return 0;
148 12 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
149 12 av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
150
151 12 return 0;
152 }
153
154 static const uint32_t mac_to_unicode[128] = {
155 0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
156 0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
157 0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,
158 0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,
159 0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,
160 0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,
161 0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,
162 0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,
163 0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,
164 0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,
165 0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,
166 0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,
167 0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,
168 0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,
169 0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,
170 0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7,
171 };
172
173 407 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
174 char *dst, int dstlen)
175 {
176 407 char *p = dst;
177 407 char *end = dst+dstlen-1;
178 int i;
179
180
2/2
✓ Branch 0 taken 3423 times.
✓ Branch 1 taken 407 times.
3830 for (i = 0; i < len; i++) {
181 3423 uint8_t t, c = avio_r8(pb);
182
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3423 times.
3423 if (p >= end)
184 ✗ continue;
185
186
2/2
✓ Branch 0 taken 3415 times.
✓ Branch 1 taken 8 times.
3423 if (c < 0x80)
187 3415 *p++ = c;
188
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 else if (p < end)
189
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✓ Branch 9 taken 8 times.
16 PUT_UTF8(mac_to_unicode[c-0x80], t, if (p < end) *p++ = t;);
190 }
191 407 *p = 0;
192 407 return p - dst;
193 }
194
195 /**
196 * Get the requested item.
197 */
198 272 static HEIFItem *get_heif_item(MOVContext *c, unsigned id)
199 {
200 272 HEIFItem *item = NULL;
201
202
2/2
✓ Branch 0 taken 816 times.
✓ Branch 1 taken 15 times.
831 for (int i = 0; i < c->nb_heif_item; i++) {
203
3/4
✓ Branch 0 taken 816 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 559 times.
✓ Branch 3 taken 257 times.
816 if (!c->heif_item[i] || c->heif_item[i]->item_id != id)
204 559 continue;
205
206 257 item = c->heif_item[i];
207 257 break;
208 }
209
210 272 return item;
211 }
212
213 /**
214 * Get the current stream in the parsing process. This can either be the
215 * latest stream added to the context, or the stream referenced by an item.
216 */
217 315 static AVStream *get_curr_st(MOVContext *c)
218 {
219 315 AVStream *st = NULL;
220 HEIFItem *item;
221
222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 315 times.
315 if (c->fc->nb_streams < 1)
223 ✗ return NULL;
224
225
2/2
✓ Branch 0 taken 242 times.
✓ Branch 1 taken 73 times.
315 if (c->cur_item_id == -1)
226 242 return c->fc->streams[c->fc->nb_streams-1];
227
228 73 item = get_heif_item(c, c->cur_item_id);
229
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 if (item)
230 73 st = item->st;
231
232 73 return st;
233 }
234
235 16 static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
236 {
237 AVStream *st;
238 MOVStreamContext *sc;
239 enum AVCodecID id;
240 int ret;
241
242
2/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
16 switch (type) {
243 9 case 0xd: id = AV_CODEC_ID_MJPEG; break;
244 7 case 0xe: id = AV_CODEC_ID_PNG; break;
245 ✗ case 0x1b: id = AV_CODEC_ID_BMP; break;
246 ✗ default:
247 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown cover type: 0x%x.\n", type);
248 ✗ avio_skip(pb, len);
249 ✗ return 0;
250 }
251
252 16 sc = av_mallocz(sizeof(*sc));
253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!sc)
254 ✗ return AVERROR(ENOMEM);
255 16 ret = ff_add_attached_pic(c->fc, NULL, pb, NULL, len);
256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0) {
257 ✗ av_free(sc);
258 ✗ return ret;
259 }
260 16 st = c->fc->streams[c->fc->nb_streams - 1];
261 16 st->priv_data = sc;
262 16 sc->id = st->id;
263 16 sc->refcount = 1;
264
265
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 if (st->attached_pic.size >= 8 && id != AV_CODEC_ID_BMP) {
266
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 9 times.
16 if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
267 7 id = AV_CODEC_ID_PNG;
268 } else {
269 9 id = AV_CODEC_ID_MJPEG;
270 }
271 }
272 16 st->codecpar->codec_id = id;
273
274 16 return 0;
275 }
276
277 // 3GPP TS 26.244
278 ✗ static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
279 {
280 ✗ char language[4] = { 0 };
281 char buf[200], place[100];
282 ✗ uint16_t langcode = 0;
283 double longitude, latitude, altitude;
284 ✗ const char *key = "location";
285
286 ✗ if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) {
287 ✗ av_log(c->fc, AV_LOG_ERROR, "loci too short\n");
288 ✗ return AVERROR_INVALIDDATA;
289 }
290
291 ✗ avio_skip(pb, 4); // version+flags
292 ✗ langcode = avio_rb16(pb);
293 ✗ ff_mov_lang_to_iso639(langcode, language);
294 ✗ len -= 6;
295
296 ✗ len -= avio_get_str(pb, len, place, sizeof(place));
297 ✗ if (len < 1) {
298 ✗ av_log(c->fc, AV_LOG_ERROR, "place name too long\n");
299 ✗ return AVERROR_INVALIDDATA;
300 }
301 ✗ avio_skip(pb, 1); // role
302 ✗ len -= 1;
303
304 ✗ if (len < 12) {
305 ✗ av_log(c->fc, AV_LOG_ERROR,
306 "loci too short (%u bytes left, need at least %d)\n", len, 12);
307 ✗ return AVERROR_INVALIDDATA;
308 }
309 ✗ longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
310 ✗ latitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
311 ✗ altitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
312
313 // Try to output in the same format as the ?xyz field
314 ✗ snprintf(buf, sizeof(buf), "%+08.4f%+09.4f", latitude, longitude);
315 ✗ if (altitude)
316 ✗ av_strlcatf(buf, sizeof(buf), "%+f", altitude);
317 ✗ av_strlcatf(buf, sizeof(buf), "/%s", place);
318
319 ✗ if (*language && strcmp(language, "und")) {
320 char key2[16];
321 ✗ snprintf(key2, sizeof(key2), "%s-%s", key, language);
322 ✗ av_dict_set(&c->fc->metadata, key2, buf, 0);
323 }
324 ✗ c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
325 ✗ return av_dict_set(&c->fc->metadata, key, buf, 0);
326 }
327
328 ✗ static int mov_metadata_hmmt(MOVContext *c, AVIOContext *pb, unsigned len)
329 {
330 int i, n_hmmt;
331
332 ✗ if (len < 2)
333 ✗ return 0;
334 ✗ if (c->ignore_chapters)
335 ✗ return 0;
336
337 ✗ n_hmmt = avio_rb32(pb);
338 ✗ if (n_hmmt > len / 4)
339 ✗ return AVERROR_INVALIDDATA;
340 ✗ for (i = 0; i < n_hmmt && !pb->eof_reached; i++) {
341 ✗ int moment_time = avio_rb32(pb);
342 ✗ avpriv_new_chapter(c->fc, i, av_make_q(1, 1000), moment_time, AV_NOPTS_VALUE, NULL);
343 }
344 ✗ if (avio_feof(pb))
345 ✗ return AVERROR_INVALIDDATA;
346 ✗ return 0;
347 }
348
349 634 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
350 {
351 634 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
352 634 char key2[32], language[4] = {0};
353 634 char *str = NULL;
354 634 const char *key = NULL;
355 634 uint16_t langcode = 0;
356 634 uint32_t data_type = 0, str_size_alloc;
357 uint64_t str_size;
358 634 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
359 634 int raw = 0;
360 634 int num = 0;
361 AVDictionary **metadata;
362
363
3/4
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 581 times.
✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
634 if (c->trak_index >= 0 && c->trak_index < c->fc->nb_streams)
364 53 metadata = &c->fc->streams[c->trak_index]->metadata;
365 else
366 581 metadata = &c->fc->metadata;
367
368
27/75
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 238 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 15 times.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 16 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 12 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 5 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 15 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✓ Branch 34 taken 16 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 40 taken 21 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 20 times.
✓ Branch 43 taken 3 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 12 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 4 times.
✓ Branch 48 taken 20 times.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✓ Branch 52 taken 2 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 5 times.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✓ Branch 59 taken 5 times.
✓ Branch 60 taken 5 times.
✓ Branch 61 taken 47 times.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✓ Branch 68 taken 63 times.
✓ Branch 69 taken 76 times.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✓ Branch 73 taken 3 times.
✓ Branch 74 taken 5 times.
634 switch (atom.type) {
369 3 case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break;
370 3 case MKTAG( '@','P','R','Q'): key = "quicktime_version"; raw = 1; break;
371 2 case MKTAG( 'X','M','P','_'):
372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->export_xmp) { key = "xmp"; raw = 1; } break;
373 16 case MKTAG( 'a','A','R','T'): key = "album_artist"; break;
374 ✗ case MKTAG( 'a','k','I','D'): key = "account_type";
375 ✗ parse = mov_metadata_int8_no_padding; break;
376 ✗ case MKTAG( 'a','p','I','D'): key = "account_id"; break;
377 ✗ case MKTAG( 'c','a','t','g'): key = "category"; break;
378 15 case MKTAG( 'c','p','i','l'): key = "compilation";
379 15 parse = mov_metadata_int8_no_padding; break;
380 2 case MKTAG( 'c','p','r','t'): key = "copyright"; break;
381 ✗ case MKTAG( 'd','e','s','c'): key = "description"; break;
382 16 case MKTAG( 'd','i','s','k'): key = "disc";
383 16 parse = mov_metadata_track_or_disc_number; break;
384 ✗ case MKTAG( 'e','g','i','d'): key = "episode_uid";
385 ✗ parse = mov_metadata_int8_no_padding; break;
386 ✗ case MKTAG( 'F','I','R','M'): key = "firmware"; raw = 1; break;
387 12 case MKTAG( 'g','n','r','e'): key = "genre";
388 12 parse = mov_metadata_gnre; break;
389 ✗ case MKTAG( 'h','d','v','d'): key = "hd_video";
390 ✗ parse = mov_metadata_int8_no_padding; break;
391 ✗ case MKTAG( 'H','M','M','T'):
392 ✗ return mov_metadata_hmmt(c, pb, atom.size);
393 ✗ case MKTAG( 'k','e','y','w'): key = "keywords"; break;
394 ✗ case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
395 ✗ case MKTAG( 'l','o','c','i'):
396 ✗ return mov_metadata_loci(c, pb, atom.size);
397 ✗ case MKTAG( 'm','a','n','u'): key = "make"; break;
398 ✗ case MKTAG( 'm','o','d','l'): key = "model"; break;
399 5 case MKTAG( 'n','a','m','e'): key = "name"; break;
400 ✗ case MKTAG( 'p','c','s','t'): key = "podcast";
401 ✗ parse = mov_metadata_int8_no_padding; break;
402 15 case MKTAG( 'p','g','a','p'): key = "gapless_playback";
403 15 parse = mov_metadata_int8_no_padding; break;
404 ✗ case MKTAG( 'p','u','r','d'): key = "purchase_date"; break;
405 ✗ case MKTAG( 'r','t','n','g'): key = "rating";
406 ✗ parse = mov_metadata_int8_no_padding; break;
407 ✗ case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break;
408 ✗ case MKTAG( 's','o','a','l'): key = "sort_album"; break;
409 ✗ case MKTAG( 's','o','a','r'): key = "sort_artist"; break;
410 ✗ case MKTAG( 's','o','c','o'): key = "sort_composer"; break;
411 ✗ case MKTAG( 's','o','n','m'): key = "sort_name"; break;
412 ✗ case MKTAG( 's','o','s','n'): key = "sort_show"; break;
413 ✗ case MKTAG( 's','t','i','k'): key = "media_type";
414 ✗ parse = mov_metadata_int8_no_padding; break;
415 16 case MKTAG( 't','r','k','n'): key = "track";
416 16 parse = mov_metadata_track_or_disc_number; break;
417 ✗ case MKTAG( 't','v','e','n'): key = "episode_id"; break;
418 ✗ case MKTAG( 't','v','e','s'): key = "episode_sort";
419 ✗ parse = mov_metadata_int8_bypass_padding; break;
420 ✗ case MKTAG( 't','v','n','n'): key = "network"; break;
421 ✗ case MKTAG( 't','v','s','h'): key = "show"; break;
422 ✗ case MKTAG( 't','v','s','n'): key = "season_number";
423 ✗ parse = mov_metadata_int8_bypass_padding; break;
424 21 case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
425 ✗ case MKTAG(0xa9,'P','R','D'): key = "producer"; break;
426 20 case MKTAG(0xa9,'a','l','b'): key = "album"; break;
427 3 case MKTAG(0xa9,'a','u','t'): key = "artist"; break;
428 ✗ case MKTAG(0xa9,'c','h','p'): key = "chapter"; break;
429 12 case MKTAG(0xa9,'c','m','t'): key = "comment"; break;
430 ✗ case MKTAG(0xa9,'c','o','m'): key = "composer"; break;
431 4 case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
432 20 case MKTAG(0xa9,'d','a','y'): key = "date"; break;
433 ✗ case MKTAG(0xa9,'d','i','r'): key = "director"; break;
434 ✗ case MKTAG(0xa9,'d','i','s'): key = "disclaimer"; break;
435 ✗ case MKTAG(0xa9,'e','d','1'): key = "edit_date"; break;
436 2 case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
437 ✗ case MKTAG(0xa9,'f','m','t'): key = "original_format"; break;
438 5 case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
439 ✗ case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
440 ✗ case MKTAG(0xa9,'h','s','t'): key = "host_computer"; break;
441 ✗ case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
442 ✗ case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
443 5 case MKTAG(0xa9,'m','a','k'): key = "make"; break;
444 5 case MKTAG(0xa9,'m','o','d'): key = "model"; break;
445 47 case MKTAG(0xa9,'n','a','m'): key = "title"; break;
446 ✗ case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break;
447 ✗ case MKTAG(0xa9,'p','r','d'): key = "producer"; break;
448 ✗ case MKTAG(0xa9,'p','r','f'): key = "performers"; break;
449 ✗ case MKTAG(0xa9,'r','e','q'): key = "playback_requirements"; break;
450 ✗ case MKTAG(0xa9,'s','r','c'): key = "original_source"; break;
451 ✗ case MKTAG(0xa9,'s','t','3'): key = "subtitle"; break;
452 63 case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
453 76 case MKTAG(0xa9,'t','o','o'): key = "encoder"; break;
454 ✗ case MKTAG(0xa9,'t','r','k'): key = "track"; break;
455 ✗ case MKTAG(0xa9,'u','r','l'): key = "URL"; break;
456 ✗ case MKTAG(0xa9,'w','r','n'): key = "warning"; break;
457 3 case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
458 5 case MKTAG(0xa9,'x','y','z'): key = "location"; break;
459 }
460 7 retry:
461
3/4
✓ Branch 0 taken 436 times.
✓ Branch 1 taken 205 times.
✓ Branch 2 taken 436 times.
✗ Branch 3 not taken.
1061 if (c->itunes_metadata && atom.size > 8) {
462 436 int data_size = avio_rb32(pb);
463 436 int tag = avio_rl32(pb);
464
3/6
✓ Branch 0 taken 436 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 436 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 436 times.
✗ Branch 5 not taken.
436 if (tag == MKTAG('d','a','t','a') && data_size <= atom.size && data_size >= 16) {
465 436 data_type = avio_rb32(pb); // type
466 436 avio_rb32(pb); // unknown
467 436 str_size = data_size - 16;
468 436 atom.size -= 16;
469
470
5/6
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 279 times.
✓ Branch 2 taken 104 times.
✓ Branch 3 taken 53 times.
✓ Branch 4 taken 104 times.
✗ Branch 5 not taken.
436 if (!key && c->found_hdlr_mdta && c->meta_keys) {
471 104 uint32_t index = av_bswap32(atom.type); // BE number has been read as LE
472
2/4
✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104 times.
✗ Branch 3 not taken.
104 if (index < c->meta_keys_count && index > 0) {
473 104 key = c->meta_keys[index];
474 ✗ } else if (atom.type != MKTAG('c', 'o', 'v', 'r')) {
475 ✗ av_log(c->fc, AV_LOG_WARNING,
476 "The index of 'data' is out of range: %"PRId32" < 1 or >= %d.\n",
477 index, c->meta_keys_count);
478 }
479 }
480
4/4
✓ Branch 0 taken 420 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 383 times.
✓ Branch 3 taken 37 times.
436 if (atom.type == MKTAG('c', 'o', 'v', 'r') ||
481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 383 times.
383 (key && !strcmp(key, "com.apple.quicktime.artwork"))) {
482 16 int ret = mov_read_covr(c, pb, data_type, str_size);
483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0) {
484 ✗ av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
485 ✗ return ret;
486 }
487 16 atom.size -= str_size;
488
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (atom.size > 8)
489 2 goto retry;
490 14 return ret;
491 }
492 ✗ } else return 0;
493
8/10
✓ Branch 0 taken 175 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 55 times.
✓ Branch 3 taken 120 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 55 times.
✓ Branch 6 taken 120 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 109 times.
✓ Branch 9 taken 11 times.
205 } else if (atom.size > 4 && (key || c->export_all) && !c->itunes_metadata && !raw) {
494 109 str_size = avio_rb16(pb); // string length
495
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 104 times.
109 if (str_size > atom.size) {
496 5 raw = 1;
497 5 avio_seek(pb, -2, SEEK_CUR);
498 5 av_log(c->fc, AV_LOG_WARNING, "UDTA parsing failed retrying raw\n");
499 5 goto retry;
500 }
501 104 langcode = avio_rb16(pb);
502 104 ff_mov_lang_to_iso639(langcode, language);
503 104 atom.size -= 4;
504 } else
505 96 str_size = atom.size;
506
507
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 620 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
620 if (c->export_all && !key) {
508 ✗ key = av_fourcc_make_string(tmp_key, atom.type);
509 }
510
511
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 498 times.
620 if (!key)
512 122 return 0;
513
2/4
✓ Branch 0 taken 498 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 498 times.
498 if (atom.size < 0 || str_size >= INT_MAX/2)
514 ✗ return AVERROR_INVALIDDATA;
515
516 // Allocates enough space if data_type is a int32 or float32 number, otherwise
517 // worst-case requirement for output string in case of utf8 coded input
518
3/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 426 times.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
498 num = (data_type >= 21 && data_type <= 23);
519
4/4
✓ Branch 0 taken 426 times.
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 415 times.
✓ Branch 3 taken 11 times.
498 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
520 498 str = av_mallocz(str_size_alloc);
521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 498 times.
498 if (!str)
522 ✗ return AVERROR(ENOMEM);
523
524
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 424 times.
498 if (parse)
525 74 parse(c, pb, str_size, key);
526 else {
527
8/10
✓ Branch 0 taken 413 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 413 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 108 times.
✓ Branch 5 taken 305 times.
✓ Branch 6 taken 91 times.
✓ Branch 7 taken 17 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 91 times.
424 if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
528 17 mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
529
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 405 times.
407 } else if (data_type == 21) { // BE signed integer, variable size
530 2 int val = 0;
531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (str_size == 1)
532 ✗ val = (int8_t)avio_r8(pb);
533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 2)
534 ✗ val = (int16_t)avio_rb16(pb);
535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 3)
536 ✗ val = ((int32_t)(avio_rb24(pb)<<8))>>8;
537
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (str_size == 4)
538 2 val = (int32_t)avio_rb32(pb);
539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
540 ✗ av_log(c->fc, AV_LOG_ERROR,
541 "Failed to store the number (%d) in string.\n", val);
542 ✗ av_free(str);
543 ✗ return AVERROR_INVALIDDATA;
544 }
545
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 405 times.
405 } else if (data_type == 22) { // BE unsigned integer, variable size
546 ✗ unsigned int val = 0;
547 ✗ if (str_size == 1)
548 ✗ val = avio_r8(pb);
549 ✗ else if (str_size == 2)
550 ✗ val = avio_rb16(pb);
551 ✗ else if (str_size == 3)
552 ✗ val = avio_rb24(pb);
553 ✗ else if (str_size == 4)
554 ✗ val = avio_rb32(pb);
555 ✗ if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
556 ✗ av_log(c->fc, AV_LOG_ERROR,
557 "Failed to store the number (%u) in string.\n", val);
558 ✗ av_free(str);
559 ✗ return AVERROR_INVALIDDATA;
560 }
561
3/4
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 365 times.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
445 } else if (data_type == 23 && str_size >= 4) { // BE float32
562 40 float val = av_int2float(avio_rb32(pb));
563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
564 ✗ av_log(c->fc, AV_LOG_ERROR,
565 "Failed to store the float32 number (%f) in string.\n", val);
566 ✗ av_free(str);
567 ✗ return AVERROR_INVALIDDATA;
568 }
569
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 365 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
365 } else if (data_type > 1 && data_type != 4) {
570 // data_type can be 0 if not set at all above. data_type 1 means
571 // UTF8 and 4 means "UTF8 sort". For any other type (UTF16 or e.g.
572 // a picture), don't return it blindly in a string that is supposed
573 // to be UTF8 text.
574 ✗ av_log(c->fc, AV_LOG_WARNING, "Skipping unhandled metadata %s of type %"PRIu32"\n", key, data_type);
575 ✗ av_free(str);
576 ✗ return 0;
577 } else {
578 365 int ret = ffio_read_size(pb, str, str_size);
579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 365 times.
365 if (ret < 0) {
580 ✗ av_free(str);
581 ✗ return ret;
582 }
583 365 str[str_size] = 0;
584 }
585 424 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
586
4/4
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 115 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 305 times.
424 if (c->itunes_metadata && av_dict_get(*metadata, key, NULL, 0))
587 4 av_dict_set(metadata, key, ";", AV_DICT_APPEND);
588
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 115 times.
424 av_dict_set(metadata, key, str, c->itunes_metadata ? AV_DICT_APPEND : 0);
589
4/4
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 320 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 67 times.
424 if (*language && strcmp(language, "und")) {
590 37 snprintf(key2, sizeof(key2), "%s-%s", key, language);
591 37 av_dict_set(metadata, key2, str, 0);
592 }
593
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 283 times.
424 if (!strcmp(key, "encoder")) {
594 int major, minor, micro;
595
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 140 times.
141 if (sscanf(str, "HandBrake %d.%d.%d", &major, &minor, &micro) == 3) {
596 1 c->handbrake_version = 1000000*major + 1000*minor + micro;
597 }
598 }
599
600 424 atom.size -= str_size;
601 424 av_freep(&str);
602
603 // Read remaining data atoms for multi-valued iTunes tags (e.g. multiple
604 // artists stored as multiple data atoms within one tag atom), consistent
605 // with the existing covr path.
606 // Note: multiple sibling tag atoms with the same key (e.g. three separate
607 // ©ART atoms under ilst) are handled by the AV_DICT_APPEND logic above,
608 // since mov_read_udta_string() is called once per tag atom.
609
3/4
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 115 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 309 times.
424 if (c->itunes_metadata && atom.size > 8)
610 ✗ goto retry;
611 }
612
613 498 av_freep(&str);
614 498 return 0;
615 }
616
617 12 static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
618 {
619 int64_t start;
620 int i, nb_chapters, str_len, version;
621 char str[256+1];
622 int ret;
623
624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->ignore_chapters)
625 ✗ return 0;
626
627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if ((atom.size -= 5) < 0)
628 ✗ return 0;
629
630 12 version = avio_r8(pb);
631 12 avio_rb24(pb);
632
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (version)
633 12 avio_rb32(pb); // ???
634 12 nb_chapters = avio_r8(pb);
635
636
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
30 for (i = 0; i < nb_chapters; i++) {
637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size < 9)
638 ✗ return 0;
639
640 18 start = avio_rb64(pb);
641 18 str_len = avio_r8(pb);
642
643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if ((atom.size -= 9+str_len) < 0)
644 ✗ return 0;
645
646 18 ret = ffio_read_size(pb, str, str_len);
647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (ret < 0)
648 ✗ return ret;
649 18 str[str_len] = 0;
650 18 avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
651 }
652 12 return 0;
653 }
654
655 #define MIN_DATA_ENTRY_BOX_SIZE 12
656 838 static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
657 {
658 AVStream *st;
659 MOVStreamContext *sc;
660 int entries, i, j;
661
662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->fc->nb_streams < 1)
663 ✗ return 0;
664 838 st = c->fc->streams[c->fc->nb_streams-1];
665 838 sc = st->priv_data;
666
667 838 avio_rb32(pb); // version + flags
668 838 entries = avio_rb32(pb);
669
1/2
✓ Branch 0 taken 838 times.
✗ Branch 1 not taken.
838 if (!entries ||
670
1/2
✓ Branch 0 taken 838 times.
✗ Branch 1 not taken.
838 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 entries >= UINT_MAX / sizeof(*sc->drefs))
672 ✗ return AVERROR_INVALIDDATA;
673
674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 for (i = 0; i < sc->drefs_count; i++) {
675 ✗ MOVDref *dref = &sc->drefs[i];
676 ✗ av_freep(&dref->path);
677 ✗ av_freep(&dref->dir);
678 }
679 838 av_free(sc->drefs);
680 838 sc->drefs_count = 0;
681 838 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (!sc->drefs)
683 ✗ return AVERROR(ENOMEM);
684 838 sc->drefs_count = entries;
685
686
2/2
✓ Branch 0 taken 838 times.
✓ Branch 1 taken 838 times.
1676 for (i = 0; i < entries; i++) {
687 838 MOVDref *dref = &sc->drefs[i];
688 838 uint32_t size = avio_rb32(pb);
689 838 int64_t next = avio_tell(pb);
690
691
3/6
✓ Branch 0 taken 838 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 838 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 838 times.
838 if (size < 12 || next < 0 || next > INT64_MAX - size)
692 ✗ return AVERROR_INVALIDDATA;
693
694 838 next += size - 4;
695
696 838 dref->type = avio_rl32(pb);
697 838 avio_rb32(pb); // version + flags
698
699
3/4
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 686 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 152 times.
838 if (dref->type == MKTAG('a','l','i','s') && size > 150) {
700 /* macintosh alias record */
701 uint16_t volume_len, len;
702 int16_t type;
703 int ret;
704
705 ✗ avio_skip(pb, 10);
706
707 ✗ volume_len = avio_r8(pb);
708 ✗ volume_len = FFMIN(volume_len, 27);
709 ✗ ret = ffio_read_size(pb, dref->volume, 27);
710 ✗ if (ret < 0)
711 ✗ return ret;
712 ✗ dref->volume[volume_len] = 0;
713 ✗ av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
714
715 ✗ avio_skip(pb, 12);
716
717 ✗ len = avio_r8(pb);
718 ✗ len = FFMIN(len, 63);
719 ✗ ret = ffio_read_size(pb, dref->filename, 63);
720 ✗ if (ret < 0)
721 ✗ return ret;
722 ✗ dref->filename[len] = 0;
723 ✗ av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
724
725 ✗ avio_skip(pb, 16);
726
727 /* read next level up_from_alias/down_to_target */
728 ✗ dref->nlvl_from = avio_rb16(pb);
729 ✗ dref->nlvl_to = avio_rb16(pb);
730 ✗ av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
731 ✗ dref->nlvl_from, dref->nlvl_to);
732
733 ✗ avio_skip(pb, 16);
734
735 ✗ for (type = 0; type != -1 && avio_tell(pb) < next; ) {
736 ✗ if (avio_feof(pb))
737 ✗ return AVERROR_EOF;
738 ✗ type = avio_rb16(pb);
739 ✗ len = avio_rb16(pb);
740 ✗ av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
741 ✗ if (len&1)
742 ✗ len += 1;
743 ✗ if (type == 2) { // absolute path
744 ✗ av_free(dref->path);
745 ✗ dref->path = av_mallocz(len+1);
746 ✗ if (!dref->path)
747 ✗ return AVERROR(ENOMEM);
748
749 ✗ ret = ffio_read_size(pb, dref->path, len);
750 ✗ if (ret < 0) {
751 ✗ av_freep(&dref->path);
752 ✗ return ret;
753 }
754 ✗ if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
755 ✗ len -= volume_len;
756 ✗ memmove(dref->path, dref->path+volume_len, len);
757 ✗ dref->path[len] = 0;
758 }
759 // trim string of any ending zeros
760 ✗ for (j = len - 1; j >= 0; j--) {
761 ✗ if (dref->path[j] == 0)
762 ✗ len--;
763 else
764 ✗ break;
765 }
766 ✗ for (j = 0; j < len; j++)
767 ✗ if (dref->path[j] == ':' || dref->path[j] == 0)
768 ✗ dref->path[j] = '/';
769 ✗ av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
770 ✗ } else if (type == 0) { // directory name
771 ✗ av_free(dref->dir);
772 ✗ dref->dir = av_malloc(len+1);
773 ✗ if (!dref->dir)
774 ✗ return AVERROR(ENOMEM);
775
776 ✗ ret = ffio_read_size(pb, dref->dir, len);
777 ✗ if (ret < 0) {
778 ✗ av_freep(&dref->dir);
779 ✗ return ret;
780 }
781 ✗ dref->dir[len] = 0;
782 ✗ for (j = 0; j < len; j++)
783 ✗ if (dref->dir[j] == ':')
784 ✗ dref->dir[j] = '/';
785 ✗ av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
786 } else
787 ✗ avio_skip(pb, len);
788 }
789 } else {
790 838 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
791 dref->type, size);
792 838 entries--;
793 838 i--;
794 }
795 838 avio_seek(pb, next, SEEK_SET);
796 }
797 838 return 0;
798 }
799
800 1464 static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
801 {
802 AVStream *st;
803 uint32_t type;
804 uint32_t ctype;
805 int64_t title_size;
806 char *title_str;
807 int ret;
808
809 1464 avio_r8(pb); /* version */
810 1464 avio_rb24(pb); /* flags */
811
812 /* component type */
813 1464 ctype = avio_rl32(pb);
814 1464 type = avio_rl32(pb); /* component subtype */
815
816 1464 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
817 1464 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
818
819
2/2
✓ Branch 0 taken 222 times.
✓ Branch 1 taken 1242 times.
1464 if (c->trak_index < 0) { // meta not inside a trak
820
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 208 times.
222 if (type == MKTAG('m','d','t','a')) {
821 14 c->found_hdlr_mdta = 1;
822 }
823 222 return 0;
824 }
825
826 1242 st = c->fc->streams[c->fc->nb_streams-1];
827
828
2/2
✓ Branch 0 taken 375 times.
✓ Branch 1 taken 867 times.
1242 if (type == MKTAG('v','i','d','e'))
829 375 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
830
2/2
✓ Branch 0 taken 397 times.
✓ Branch 1 taken 470 times.
867 else if (type == MKTAG('s','o','u','n'))
831 397 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 else if (type == MKTAG('m','1','a',' '))
833 ✗ st->codecpar->codec_id = AV_CODEC_ID_MP2;
834
2/4
✓ Branch 0 taken 470 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 470 times.
470 else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
835 ✗ st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
836
837 1242 avio_rb32(pb); /* component manufacture */
838 1242 avio_rb32(pb); /* component flags */
839 1242 avio_rb32(pb); /* component flags mask */
840
841 1242 title_size = atom.size - 24;
842
2/2
✓ Branch 0 taken 1236 times.
✓ Branch 1 taken 6 times.
1242 if (title_size > 0) {
843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1236 times.
1236 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
844 ✗ return AVERROR_INVALIDDATA;
845 1236 title_str = av_malloc(title_size + 1); /* Add null terminator */
846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1236 times.
1236 if (!title_str)
847 ✗ return AVERROR(ENOMEM);
848
849 1236 ret = ffio_read_size(pb, title_str, title_size);
850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1236 times.
1236 if (ret < 0) {
851 ✗ av_freep(&title_str);
852 ✗ return ret;
853 }
854 1236 title_str[title_size] = 0;
855
2/2
✓ Branch 0 taken 1172 times.
✓ Branch 1 taken 64 times.
1236 if (title_str[0]) {
856
4/4
✓ Branch 0 taken 778 times.
✓ Branch 1 taken 394 times.
✓ Branch 2 taken 776 times.
✓ Branch 3 taken 2 times.
1172 int off = (!c->isom && title_str[0] == title_size - 1);
857 // flag added so as to not set stream handler name if already set from mdia->hdlr
858 1172 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
859 }
860 1236 av_freep(&title_str);
861 }
862
863 1242 return 0;
864 }
865
866 301 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
867 {
868 301 return ff_mov_read_esds(c->fc, pb);
869 }
870
871 8 static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
872 {
873 AVStream *st;
874 AVPacketSideData *sd;
875 enum AVAudioServiceType *ast;
876 int ac3info, acmod, lfeon, bsmod;
877 uint64_t mask;
878
879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (c->fc->nb_streams < 1)
880 ✗ return 0;
881 8 st = c->fc->streams[c->fc->nb_streams-1];
882
883 8 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
884 8 &st->codecpar->nb_coded_side_data,
885 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
886 sizeof(*ast), 0);
887
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!sd)
888 ✗ return AVERROR(ENOMEM);
889
890 8 ast = (enum AVAudioServiceType*)sd->data;
891 8 ac3info = avio_rb24(pb);
892 8 bsmod = (ac3info >> 14) & 0x7;
893 8 acmod = (ac3info >> 11) & 0x7;
894 8 lfeon = (ac3info >> 10) & 0x1;
895
896 8 mask = ff_ac3_channel_layout_tab[acmod];
897
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (lfeon)
898 1 mask |= AV_CH_LOW_FREQUENCY;
899 8 av_channel_layout_uninit(&st->codecpar->ch_layout);
900 8 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
901
902 8 *ast = bsmod;
903
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7)
904 ✗ *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
905
906 8 return 0;
907 }
908
909 #if CONFIG_IAMFDEC
910 12 static int mov_read_iacb(MOVContext *c, AVIOContext *pb, MOVAtom atom)
911 {
912 AVStream *st;
913 MOVStreamContext *sc;
914 FFIOContext b;
915 AVIOContext *descriptor_pb;
916 AVDictionary *metadata;
917 IAMFContext *iamf;
918 int64_t start_time, duration;
919 unsigned descriptors_size;
920 int nb_frames, disposition;
921 int version, ret;
922
923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (atom.size < 5)
924 ✗ return AVERROR_INVALIDDATA;
925
926
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->fc->nb_streams < 1)
927 ✗ return 0;
928
929 12 version = avio_r8(pb);
930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (version != 1) {
931 ✗ av_log(c->fc, AV_LOG_ERROR, "%s configurationVersion %d",
932 version < 1 ? "invalid" : "unsupported", version);
933 ✗ return AVERROR_INVALIDDATA;
934 }
935
936 12 descriptors_size = ffio_read_leb(pb);
937
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (!descriptors_size || descriptors_size > INT_MAX)
938 ✗ return AVERROR_INVALIDDATA;
939
940 12 st = c->fc->streams[c->fc->nb_streams - 1];
941 12 sc = st->priv_data;
942
943
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->extradata) {
944 ✗ av_log(c->fc, AV_LOG_WARNING, "ignoring iacb\n");
945 ✗ return 0;
946 }
947
948 12 sc->iamf = av_mallocz(sizeof(*sc->iamf));
949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!sc->iamf)
950 ✗ return AVERROR(ENOMEM);
951 12 iamf = &sc->iamf->iamf;
952
953 12 ret = ff_alloc_extradata(st->codecpar, descriptors_size);
954
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
955 ✗ return ret;
956
957 12 ret = avio_read(pb, st->codecpar->extradata, descriptors_size);
958
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret != descriptors_size)
959 ✗ return ret < 0 ? ret : AVERROR_INVALIDDATA;
960
961 12 ffio_init_read_context(&b, st->codecpar->extradata, descriptors_size);
962 12 descriptor_pb = &b.pub;
963
964 12 ret = ff_iamfdec_read_descriptors(iamf, descriptor_pb, descriptors_size, c->fc);
965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
966 ✗ return ret;
967
968 12 metadata = st->metadata;
969 12 st->metadata = NULL;
970 12 start_time = st->start_time;
971 12 nb_frames = st->nb_frames;
972 12 duration = st->duration;
973 12 disposition = st->disposition;
974
975
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_audio_elements; i++) {
976 12 IAMFAudioElement *audio_element = iamf->audio_elements[i];
977 const AVIAMFAudioElement *element;
978 AVStreamGroup *stg =
979 12 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, NULL);
980
981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!stg) {
982 ✗ ret = AVERROR(ENOMEM);
983 ✗ goto fail;
984 }
985
986 12 av_iamf_audio_element_free(&stg->params.iamf_audio_element);
987 12 stg->id = audio_element->audio_element_id;
988 /* Transfer ownership */
989 12 element = stg->params.iamf_audio_element = audio_element->element;
990 12 audio_element->element = NULL;
991
992
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < audio_element->nb_substreams; j++) {
993 64 IAMFSubStream *substream = &audio_element->substreams[j];
994 AVStream *stream;
995
996
3/4
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 52 times.
64 if (!i && !j) {
997
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
12 if (audio_element->layers[0].substream_count != 1)
998 2 disposition &= ~AV_DISPOSITION_DEFAULT;
999 12 stream = st;
1000 } else
1001 52 stream = avformat_new_stream(c->fc, NULL);
1002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (!stream) {
1003 ✗ ret = AVERROR(ENOMEM);
1004 ✗ goto fail;
1005 }
1006
1007 64 stream->start_time = start_time;
1008 64 stream->nb_frames = nb_frames;
1009 64 stream->duration = duration;
1010 64 stream->disposition = disposition;
1011
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 12 times.
64 if (stream != st) {
1012 52 stream->priv_data = sc;
1013 52 sc->refcount++;
1014 }
1015
1016
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 56 times.
64 if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
1017 8 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1018
3/4
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 12 times.
64 if (i || j) {
1019 52 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1020
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 6 times.
52 if (audio_element->layers[0].substream_count == 1)
1021 46 stream->disposition &= ~AV_DISPOSITION_DEFAULT;
1022 }
1023
1024 64 ret = avcodec_parameters_copy(stream->codecpar, substream->codecpar);
1025
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
1026 ✗ goto fail;
1027
1028 64 stream->id = substream->audio_substream_id;
1029
1030 64 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
1031
1032 64 ret = avformat_stream_group_add_stream(stg, stream);
1033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
1034 ✗ goto fail;
1035 }
1036
1037 12 ret = av_dict_copy(&stg->metadata, metadata, 0);
1038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1039 ✗ goto fail;
1040 }
1041
1042
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1043 12 IAMFMixPresentation *mix_presentation = iamf->mix_presentations[i];
1044 12 const AVIAMFMixPresentation *mix = mix_presentation->cmix;
1045 AVStreamGroup *stg =
1046 12 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, NULL);
1047
1048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!stg) {
1049 ✗ ret = AVERROR(ENOMEM);
1050 ✗ goto fail;
1051 }
1052
1053 12 av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
1054 12 stg->id = mix_presentation->mix_presentation_id;
1055 /* Transfer ownership */
1056 12 stg->params.iamf_mix_presentation = mix_presentation->mix;
1057 12 mix_presentation->mix = NULL;
1058
1059
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 12 times.
26 for (int j = 0; j < mix->nb_submixes; j++) {
1060 14 const AVIAMFSubmix *submix = mix->submixes[j];
1061
1062
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
28 for (int k = 0; k < submix->nb_elements; k++) {
1063 14 const AVIAMFSubmixElement *submix_element = submix->elements[k];
1064 14 const AVStreamGroup *audio_element = NULL;
1065
1066
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 for (int l = 0; l < c->fc->nb_stream_groups; l++)
1067
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (c->fc->stream_groups[l]->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT &&
1068
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 c->fc->stream_groups[l]->id == submix_element->audio_element_id) {
1069 14 audio_element = c->fc->stream_groups[l];
1070 14 break;
1071 }
1072
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 av_assert0(audio_element);
1073
1074
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 14 times.
80 for (int l = 0; l < audio_element->nb_entries; l++) {
1075 66 ret = avformat_stream_group_add_stream(stg, audio_element->entries[l]->stream);
1076
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
66 if (ret < 0 && ret != AVERROR(EEXIST))
1077 ✗ goto fail;
1078 }
1079 }
1080 }
1081
1082 12 ret = av_dict_copy(&stg->metadata, metadata, 0);
1083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1084 ✗ goto fail;
1085 }
1086
1087 12 ret = 0;
1088 12 fail:
1089 12 av_dict_free(&metadata);
1090
1091 12 return ret;
1092 }
1093 #endif
1094
1095 5 static int mov_read_srat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1096 {
1097 AVStream *st;
1098 int32_t sample_rate;
1099
1100
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (atom.size < 8 || c->fc->nb_streams < 1)
1101 ✗ return 0;
1102
1103 5 st = c->fc->streams[c->fc->nb_streams-1];
1104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
1105 ✗ av_log(c->fc, AV_LOG_WARNING, "'srat' within non-audio sample entry, skip\n");
1106 ✗ return 0;
1107 }
1108
1109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!c->isom) {
1110 ✗ av_log(c->fc, AV_LOG_WARNING, "'srat' within non-isom, skip\n");
1111 ✗ return 0;
1112 }
1113
1114 5 avio_skip(pb, 4); // version+flags
1115 5 sample_rate = avio_rb32(pb);
1116
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (sample_rate > 0) {
1117 5 av_log(c->fc, AV_LOG_DEBUG,
1118 "overwrite sample rate from %d to %d by 'srat'\n",
1119 5 st->codecpar->sample_rate, sample_rate);
1120 5 st->codecpar->sample_rate = sample_rate;
1121 } else {
1122 ✗ av_log(c->fc, AV_LOG_WARNING,
1123 "ignore invalid sample rate %d in 'srat'\n", sample_rate);
1124 }
1125
1126 5 return 0;
1127 }
1128
1129 4 static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1130 {
1131 AVStream *st;
1132 AVPacketSideData *sd;
1133 enum AVAudioServiceType *ast;
1134 int eac3info, acmod, lfeon, bsmod;
1135 uint64_t mask;
1136 int ret;
1137
1138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
1139 ✗ return 0;
1140 4 st = c->fc->streams[c->fc->nb_streams-1];
1141
1142 /* Preserve the complete EC3SpecificBox payload, including optional
1143 * extensions such as E-AC-3 JOC signaling. */
1144
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (atom.size < 5 || (uint64_t)atom.size > (1 << 30))
1145 ✗ return AVERROR_INVALIDDATA;
1146 4 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
1147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
1148 ✗ return ret;
1149
1150 4 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1151 4 &st->codecpar->nb_coded_side_data,
1152 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
1153 sizeof(*ast), 0);
1154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sd)
1155 ✗ return AVERROR(ENOMEM);
1156
1157 4 ast = (enum AVAudioServiceType*)sd->data;
1158
1159 4 eac3info = AV_RB24(st->codecpar->extradata + 2);
1160 4 bsmod = (eac3info >> 12) & 0x1f;
1161 4 acmod = (eac3info >> 9) & 0x7;
1162 4 lfeon = (eac3info >> 8) & 0x1;
1163
1164 4 mask = ff_ac3_channel_layout_tab[acmod];
1165
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (lfeon)
1166 1 mask |= AV_CH_LOW_FREQUENCY;
1167 4 av_channel_layout_uninit(&st->codecpar->ch_layout);
1168 4 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
1169
1170 4 *ast = bsmod;
1171
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7)
1172 ✗ *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
1173
1174 4 return 0;
1175 }
1176
1177 /* Maps the DTS `StreamConstruction` field (ETSI TS 102 114 Table E-2) to the
1178 * coarse FFmpeg DTS profile enum. Extension-substream XLL maps to HD_MA;
1179 * extension-substream XXCH, X96, or XBR maps to HD_HRA; core-substream XCH or
1180 * XXCH maps to ES; core-substream X96 maps to 96/24; a core component alone
1181 * maps to DTS; and extension-substream LBR maps to Express. Value 0 (undefined)
1182 * and values outside 1..21 map to AV_PROFILE_UNKNOWN. */
1183 ✗ static int mov_dts_stream_construction_to_profile(unsigned int sc)
1184 {
1185 static const int profile[22] = {
1186 [ 1] = AV_PROFILE_DTS, /* core Core */
1187 [ 2] = AV_PROFILE_DTS_ES, /* core Core + core XCH */
1188 [ 3] = AV_PROFILE_DTS_ES, /* core Core + core XXCH */
1189 [ 4] = AV_PROFILE_DTS_96_24, /* core Core + core X96 */
1190 [ 5] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XXCH */
1191 [ 6] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XBR */
1192 [ 7] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XCH + ext XBR */
1193 [ 8] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XXCH + ext XBR */
1194 [ 9] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XXCH + ext XBR */
1195 [10] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext X96 */
1196 [11] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XCH + ext X96 */
1197 [12] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XXCH + ext X96 */
1198 [13] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XXCH + ext X96 */
1199 [14] = AV_PROFILE_DTS_HD_MA, /* core Core + ext XLL */
1200 [15] = AV_PROFILE_DTS_HD_MA, /* core Core + core XCH + ext XLL */
1201 [16] = AV_PROFILE_DTS_HD_MA, /* core Core + core X96 + ext XLL */
1202 [17] = AV_PROFILE_DTS_HD_MA, /* ext XLL */
1203 [18] = AV_PROFILE_DTS_EXPRESS, /* ext LBR */
1204 [19] = AV_PROFILE_DTS, /* ext Core */
1205 [20] = AV_PROFILE_DTS_HD_HRA, /* ext Core + ext XXCH */
1206 [21] = AV_PROFILE_DTS_HD_MA, /* ext Core + ext XLL */
1207 };
1208 ✗ if (!sc || sc > 21)
1209 ✗ return AV_PROFILE_UNKNOWN;
1210 ✗ return profile[sc];
1211 }
1212
1213 /* Maps the 16-bit DTS `ChannelLayout` bitmask (ETSI TS 102 114 Table E-5) to an
1214 * ffmpeg channel mask. Pair bits follow Table 7-10 / DCA_SPEAKER_PAIR_*;
1215 * LwRw (0x0400) and LssRss (0x0800) must not collapse onto SIDE like LsRs. */
1216 ✗ static uint64_t mov_dts_channel_layout_to_mask(unsigned int code)
1217 {
1218 static const struct { unsigned int dts; uint64_t av; } map[] = {
1219 { 0x0001, AV_CH_FRONT_CENTER },
1220 { 0x0002, AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT },
1221 { 0x0004, AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT },
1222 { 0x0008, AV_CH_LOW_FREQUENCY },
1223 { 0x0010, AV_CH_BACK_CENTER },
1224 { 0x0020, AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT },
1225 { 0x0040, AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT },
1226 { 0x0080, AV_CH_TOP_FRONT_CENTER },
1227 { 0x0100, AV_CH_TOP_CENTER },
1228 { 0x0200, AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER },
1229 { 0x0400, AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT },
1230 { 0x0800, AV_CH_SIDE_SURROUND_LEFT | AV_CH_SIDE_SURROUND_RIGHT },
1231 { 0x1000, AV_CH_LOW_FREQUENCY_2 },
1232 { 0x2000, AV_CH_TOP_SIDE_LEFT | AV_CH_TOP_SIDE_RIGHT },
1233 { 0x4000, AV_CH_TOP_BACK_CENTER },
1234 { 0x8000, AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT },
1235 };
1236 ✗ uint64_t mask = 0;
1237 int i;
1238 ✗ for (i = 0; i < FF_ARRAY_ELEMS(map); i++)
1239 ✗ if (code & map[i].dts)
1240 ✗ mask |= map[i].av;
1241 ✗ return mask;
1242 }
1243
1244 ✗ static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1245 {
1246 #define DDTS_SIZE 20
1247 uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
1248 ✗ AVStream *st = NULL;
1249 ✗ uint32_t frame_duration_code = 0;
1250 ✗ uint32_t channel_layout_code = 0;
1251 uint64_t channel_layout_mask;
1252 unsigned int stream_construction;
1253 unsigned int representation_type;
1254 GetBitContext gb;
1255 int ret;
1256
1257 ✗ if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
1258 ✗ return ret;
1259
1260 ✗ init_get_bits(&gb, buf, 8 * DDTS_SIZE);
1261
1262 ✗ if (c->fc->nb_streams < 1) {
1263 ✗ return 0;
1264 }
1265 ✗ st = c->fc->streams[c->fc->nb_streams-1];
1266
1267 ✗ st->codecpar->sample_rate = get_bits_long(&gb, 32);
1268 ✗ if (st->codecpar->sample_rate <= 0) {
1269 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
1270 ✗ return AVERROR_INVALIDDATA;
1271 }
1272 ✗ skip_bits_long(&gb, 32); /* max bitrate */
1273 ✗ st->codecpar->bit_rate = get_bits_long(&gb, 32);
1274 ✗ st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
1275 ✗ frame_duration_code = get_bits(&gb, 2);
1276 ✗ stream_construction = get_bits(&gb, 5); /* Table E-2 - profile source */
1277 ✗ skip_bits(&gb, 1); /* CoreLFEPresent */
1278 ✗ skip_bits(&gb, 6); /* CoreLayout */
1279 ✗ skip_bits(&gb, 14); /* CoreSize */
1280 ✗ skip_bits(&gb, 1); /* StereoDownmix */
1281 ✗ representation_type = get_bits(&gb, 3);
1282 ✗ channel_layout_code = get_bits(&gb, 16);
1283
1284 ✗ st->codecpar->frame_size =
1285 ✗ (frame_duration_code == 0) ? 512 :
1286 ✗ (frame_duration_code == 1) ? 1024 :
1287 ✗ (frame_duration_code == 2) ? 2048 :
1288 ✗ (frame_duration_code == 3) ? 4096 : 0;
1289
1290 /* Publish StreamConstruction as codecpar->profile, including for encrypted
1291 * tracks where frame headers cannot be inspected. */
1292 ✗ st->codecpar->profile = mov_dts_stream_construction_to_profile(stream_construction);
1293
1294 ✗ channel_layout_mask = mov_dts_channel_layout_to_mask(channel_layout_code);
1295 ✗ if (channel_layout_mask) {
1296 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
1297 ✗ av_channel_layout_from_mask(&st->codecpar->ch_layout, channel_layout_mask);
1298 ✗ } else if (representation_type == 2 || representation_type == 3) {
1299 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
1300 ✗ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
1301 }
1302
1303 ✗ return 0;
1304 }
1305
1306 50 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1307 {
1308 AVStream *st;
1309
1310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (c->fc->nb_streams < 1)
1311 ✗ return 0;
1312 50 st = c->fc->streams[c->fc->nb_streams-1];
1313
1314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (atom.size < 16)
1315 ✗ return 0;
1316
1317 /* skip version and flags */
1318 50 avio_skip(pb, 4);
1319
1320 50 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
1321
1322 50 return 0;
1323 }
1324
1325 5 static int mov_read_chnl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1326 {
1327 5 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
1328 int version, flags;
1329 int ret;
1330 AVStream *st;
1331
1332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
1333 ✗ return 0;
1334 5 st = c->fc->streams[c->fc->nb_streams-1];
1335
1336 5 version = avio_r8(pb);
1337 5 flags = avio_rb24(pb);
1338
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (version > 1 || flags != 0) {
1339 ✗ av_log(c->fc, AV_LOG_WARNING,
1340 "Unsupported 'chnl' box with version %d, flags: %#x\n",
1341 version, flags);
1342 ✗ return 0;
1343 }
1344
1345 5 ret = ff_mov_read_chnl(c->fc, pb, st, version);
1346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0) {
1347 ✗ avio_seek(pb, end, SEEK_SET);
1348 ✗ return 0;
1349 }
1350
1351
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_tell(pb) != end) {
1352 ✗ av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data inside chnl\n",
1353 ✗ end - avio_tell(pb));
1354 ✗ avio_seek(pb, end, SEEK_SET);
1355 }
1356 5 return ret;
1357 }
1358
1359 2 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1360 {
1361 AVStream *st;
1362 int ret;
1363
1364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
1365 ✗ return 0;
1366 2 st = c->fc->streams[c->fc->nb_streams-1];
1367
1368
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ff_get_wav_header(c->fc, pb, st->codecpar, atom.size, 0)) < 0)
1369 ✗ av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
1370
1371 2 return ret;
1372 }
1373
1374 21 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1375 {
1376 AVStream *st;
1377 HEIFItem *item;
1378 AVPacketSideData *sd;
1379 21 int width, height, err = 0;
1380 AVRational aperture_width, aperture_height, horiz_off, vert_off;
1381 AVRational pc_x, pc_y;
1382 uint64_t top, bottom, left, right;
1383
1384 21 item = get_heif_item(c, c->cur_item_id);
1385 21 st = get_curr_st(c);
1386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!st)
1387 ✗ return 0;
1388
1389 21 width = st->codecpar->width;
1390 21 height = st->codecpar->height;
1391
4/6
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
21 if ((!width || !height) && item) {
1392 6 width = item->width;
1393 6 height = item->height;
1394 }
1395
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
21 if (!width || !height) {
1396 ✗ err = AVERROR_INVALIDDATA;
1397 ✗ goto fail;
1398 }
1399
1400 21 aperture_width.num = avio_rb32(pb);
1401 21 aperture_width.den = avio_rb32(pb);
1402 21 aperture_height.num = avio_rb32(pb);
1403 21 aperture_height.den = avio_rb32(pb);
1404
1405 21 horiz_off.num = avio_rb32(pb);
1406 21 horiz_off.den = avio_rb32(pb);
1407 21 vert_off.num = avio_rb32(pb);
1408 21 vert_off.den = avio_rb32(pb);
1409
1410
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
21 if (aperture_width.num < 0 || aperture_width.den < 0 ||
1411
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
21 aperture_height.num < 0 || aperture_height.den < 0 ||
1412
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
21 horiz_off.den < 0 || vert_off.den < 0) {
1413 ✗ err = AVERROR_INVALIDDATA;
1414 ✗ goto fail;
1415 }
1416
3/4
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
39 if ((av_cmp_q((AVRational) { width, 1 }, aperture_width) < 0) ||
1417 18 (av_cmp_q((AVRational) { height, 1 }, aperture_height) < 0)) {
1418 3 err = AVERROR_INVALIDDATA;
1419 3 goto fail;
1420 }
1421 18 av_log(c->fc, AV_LOG_TRACE, "clap: apertureWidth %d/%d, apertureHeight %d/%d "
1422 "horizOff %d/%d vertOff %d/%d\n",
1423 aperture_width.num, aperture_width.den, aperture_height.num, aperture_height.den,
1424 horiz_off.num, horiz_off.den, vert_off.num, vert_off.den);
1425
1426 18 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1427 18 pc_x = av_add_q(pc_x, horiz_off);
1428 18 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1429 18 pc_y = av_add_q(pc_y, vert_off);
1430
1431 18 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1432 18 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1433 18 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1434 18 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1435
1436 18 left = av_q2d(av_sub_q(pc_x, aperture_width));
1437 18 right = av_q2d(av_add_q(pc_x, aperture_width));
1438 18 top = av_q2d(av_sub_q(pc_y, aperture_height));
1439 18 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1440
1441
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (bottom > (height - 1) ||
1442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 right > (width - 1)) {
1443 ✗ err = AVERROR_INVALIDDATA;
1444 ✗ goto fail;
1445 }
1446
1447 18 bottom = height - 1 - bottom;
1448 18 right = width - 1 - right;
1449
1450
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
18 if (!(left | right | top | bottom))
1451 6 return 0;
1452
1453
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if ((left + right) >= width ||
1454
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 (top + bottom) >= height) {
1455 ✗ err = AVERROR_INVALIDDATA;
1456 ✗ goto fail;
1457 }
1458
1459 12 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1460 12 &st->codecpar->nb_coded_side_data,
1461 AV_PKT_DATA_FRAME_CROPPING,
1462 sizeof(uint32_t) * 4, 0);
1463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!sd)
1464 ✗ return AVERROR(ENOMEM);
1465
1466 12 AV_WL32A(sd->data, top);
1467 12 AV_WL32A(sd->data + 4, bottom);
1468 12 AV_WL32A(sd->data + 8, left);
1469 12 AV_WL32A(sd->data + 12, right);
1470
1471 15 fail:
1472
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 12 times.
15 if (err < 0) {
1473 3 int explode = !!(c->fc->error_recognition & AV_EF_EXPLODE);
1474
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 av_log(c->fc, explode ? AV_LOG_ERROR : AV_LOG_WARNING, "Invalid clap box\n");
1475
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!explode)
1476 3 err = 0;
1477 }
1478
1479 15 return err;
1480 }
1481
1482 /* This atom overrides any previously set aspect ratio */
1483 108 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1484 {
1485 108 const int num = avio_rb32(pb);
1486 108 const int den = avio_rb32(pb);
1487 AVStream *st;
1488 MOVStreamContext *sc;
1489
1490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (c->fc->nb_streams < 1)
1491 ✗ return 0;
1492 108 st = c->fc->streams[c->fc->nb_streams-1];
1493 108 sc = st->priv_data;
1494
1495 108 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1496
1497
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 2 times.
108 if (den != 0) {
1498 106 sc->h_spacing = num;
1499 106 sc->v_spacing = den;
1500 }
1501 108 return 0;
1502 }
1503
1504 /* this atom contains actual media data */
1505 1085 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1506 {
1507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1085 times.
1085 if (atom.size == 0) /* wrong one (MP4) */
1508 ✗ return 0;
1509 1085 c->found_mdat=1;
1510 1085 return 0; /* now go for moov */
1511 }
1512
1513 #define DRM_BLOB_SIZE 56
1514
1515 ✗ static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1516 {
1517 uint8_t intermediate_key[20];
1518 uint8_t intermediate_iv[20];
1519 uint8_t input[64];
1520 uint8_t output[64];
1521 uint8_t file_checksum[20];
1522 uint8_t calculated_checksum[20];
1523 char checksum_string[2 * sizeof(file_checksum) + 1];
1524 struct AVSHA *sha;
1525 int i;
1526 ✗ int ret = 0;
1527 ✗ uint8_t *activation_bytes = c->activation_bytes;
1528 ✗ uint8_t *fixed_key = c->audible_fixed_key;
1529
1530 ✗ c->aax_mode = 1;
1531
1532 ✗ sha = av_sha_alloc();
1533 ✗ if (!sha)
1534 ✗ return AVERROR(ENOMEM);
1535 ✗ av_free(c->aes_decrypt);
1536 ✗ c->aes_decrypt = av_aes_alloc();
1537 ✗ if (!c->aes_decrypt) {
1538 ✗ ret = AVERROR(ENOMEM);
1539 ✗ goto fail;
1540 }
1541
1542 /* drm blob processing */
1543 ✗ avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1544 ✗ avio_read(pb, input, DRM_BLOB_SIZE);
1545 ✗ avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1546 ✗ ret = ffio_read_size(pb, file_checksum, 20);
1547 ✗ if (ret < 0)
1548 ✗ goto fail;
1549
1550 // required by external tools
1551 ✗ ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1);
1552 ✗ av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string);
1553
1554 /* verify activation data */
1555 ✗ if (!activation_bytes) {
1556 ✗ av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1557 ✗ ret = 0; /* allow ffprobe to continue working on .aax files */
1558 ✗ goto fail;
1559 }
1560 ✗ if (c->activation_bytes_size != 4) {
1561 ✗ av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1562 ✗ ret = AVERROR(EINVAL);
1563 ✗ goto fail;
1564 }
1565
1566 /* verify fixed key */
1567 ✗ if (c->audible_fixed_key_size != 16) {
1568 ✗ av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1569 ✗ ret = AVERROR(EINVAL);
1570 ✗ goto fail;
1571 }
1572
1573 /* AAX (and AAX+) key derivation */
1574 ✗ av_sha_init(sha, 160);
1575 ✗ av_sha_update(sha, fixed_key, 16);
1576 ✗ av_sha_update(sha, activation_bytes, 4);
1577 ✗ av_sha_final(sha, intermediate_key);
1578 ✗ av_sha_init(sha, 160);
1579 ✗ av_sha_update(sha, fixed_key, 16);
1580 ✗ av_sha_update(sha, intermediate_key, 20);
1581 ✗ av_sha_update(sha, activation_bytes, 4);
1582 ✗ av_sha_final(sha, intermediate_iv);
1583 ✗ av_sha_init(sha, 160);
1584 ✗ av_sha_update(sha, intermediate_key, 16);
1585 ✗ av_sha_update(sha, intermediate_iv, 16);
1586 ✗ av_sha_final(sha, calculated_checksum);
1587 ✗ if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1588 ✗ av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1589 ✗ ret = AVERROR_INVALIDDATA;
1590 ✗ goto fail;
1591 }
1592 ✗ av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1593 ✗ av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1594 ✗ for (i = 0; i < 4; i++) {
1595 // file data (in output) is stored in big-endian mode
1596 ✗ if (activation_bytes[i] != output[3 - i]) { // critical error
1597 ✗ av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1598 ✗ ret = AVERROR_INVALIDDATA;
1599 ✗ goto fail;
1600 }
1601 }
1602 ✗ memcpy(c->file_key, output + 8, 16);
1603 ✗ memcpy(input, output + 26, 16);
1604 ✗ av_sha_init(sha, 160);
1605 ✗ av_sha_update(sha, input, 16);
1606 ✗ av_sha_update(sha, c->file_key, 16);
1607 ✗ av_sha_update(sha, fixed_key, 16);
1608 ✗ av_sha_final(sha, c->file_iv);
1609
1610 ✗ fail:
1611 ✗ av_free(sha);
1612
1613 ✗ return ret;
1614 }
1615
1616 ✗ static int mov_aaxc_crypto(MOVContext *c)
1617 {
1618 ✗ if (c->audible_key_size != 16) {
1619 ✗ av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n");
1620 ✗ return AVERROR(EINVAL);
1621 }
1622
1623 ✗ if (c->audible_iv_size != 16) {
1624 ✗ av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n");
1625 ✗ return AVERROR(EINVAL);
1626 }
1627
1628 ✗ c->aes_decrypt = av_aes_alloc();
1629 ✗ if (!c->aes_decrypt) {
1630 ✗ return AVERROR(ENOMEM);
1631 }
1632
1633 ✗ memcpy(c->file_key, c->audible_key, 16);
1634 ✗ memcpy(c->file_iv, c->audible_iv, 16);
1635 ✗ c->aax_mode = 1;
1636
1637 ✗ return 0;
1638 }
1639
1640 // Audible AAX (and AAX+) bytestream decryption
1641 ✗ static int aax_filter(uint8_t *input, int size, MOVContext *c)
1642 {
1643 ✗ int blocks = 0;
1644 unsigned char iv[16];
1645
1646 ✗ memcpy(iv, c->file_iv, 16); // iv is overwritten
1647 ✗ blocks = size >> 4; // trailing bytes are not encrypted!
1648 ✗ av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1649 ✗ av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1650
1651 ✗ return 0;
1652 }
1653
1654 /* read major brand, minor version and compatible brands and store them as metadata */
1655 565 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1656 {
1657 uint32_t minor_ver;
1658 int comp_brand_size;
1659 char* comp_brands_str;
1660 565 uint8_t type[5] = {0};
1661 565 int ret = ffio_read_size(pb, type, 4);
1662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 565 times.
565 if (ret < 0)
1663 ✗ return ret;
1664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 565 times.
565 if (c->fc->nb_streams) {
1665 ✗ if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1666 ✗ return AVERROR_INVALIDDATA;
1667 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate FTYP\n");
1668 ✗ return 0;
1669 }
1670
1671
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 245 times.
565 if (strcmp(type, "qt "))
1672 320 c->isom = 1;
1673 565 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1674 565 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1675 565 minor_ver = avio_rb32(pb); /* minor version */
1676 565 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1677
1678 565 comp_brand_size = atom.size - 8;
1679
2/4
✓ Branch 0 taken 565 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 565 times.
565 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1680 ✗ return AVERROR_INVALIDDATA;
1681 565 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 565 times.
565 if (!comp_brands_str)
1683 ✗ return AVERROR(ENOMEM);
1684
1685 565 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 565 times.
565 if (ret < 0) {
1687 ✗ av_freep(&comp_brands_str);
1688 ✗ return ret;
1689 }
1690 565 comp_brands_str[comp_brand_size] = 0;
1691 565 av_dict_set(&c->fc->metadata, "compatible_brands",
1692 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1693
1694 // Logic for handling Audible's .aaxc files
1695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 565 times.
565 if (!strcmp(type, "aaxc")) {
1696 ✗ mov_aaxc_crypto(c);
1697 }
1698
1699 565 return 0;
1700 }
1701
1702 /* this atom should contain all header atoms */
1703 608 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1704 {
1705 int ret;
1706
1707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if (c->found_moov) {
1708 ✗ av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1709 ✗ avio_skip(pb, atom.size);
1710 ✗ return 0;
1711 }
1712
1713
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 608 times.
608 if ((ret = mov_read_default(c, pb, atom)) < 0)
1714 ✗ return ret;
1715 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1716 /* so we don't parse the whole file if over a network */
1717 608 c->found_moov=1;
1718 608 return 0; /* now go for mdat */
1719 }
1720
1721 6232 static MOVFragmentStreamInfo * get_frag_stream_info(
1722 MOVFragmentIndex *frag_index,
1723 int index,
1724 int id)
1725 {
1726 int i;
1727 MOVFragmentIndexItem * item;
1728
1729
2/4
✓ Branch 0 taken 6232 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6232 times.
6232 if (index < 0 || index >= frag_index->nb_items)
1730 ✗ return NULL;
1731 6232 item = &frag_index->item[index];
1732
1/2
✓ Branch 0 taken 154916 times.
✗ Branch 1 not taken.
154916 for (i = 0; i < item->nb_stream_info; i++)
1733
2/2
✓ Branch 0 taken 6232 times.
✓ Branch 1 taken 148684 times.
154916 if (item->stream_info[i].id == id)
1734 6232 return &item->stream_info[i];
1735
1736 // This shouldn't happen
1737 ✗ return NULL;
1738 }
1739
1740 706 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1741 {
1742 int i;
1743 MOVFragmentIndexItem * item;
1744
1745
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (frag_index->current < 0 ||
1746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 frag_index->current >= frag_index->nb_items)
1747 ✗ return;
1748
1749 706 item = &frag_index->item[frag_index->current];
1750
1/2
✓ Branch 0 taken 10665 times.
✗ Branch 1 not taken.
10665 for (i = 0; i < item->nb_stream_info; i++)
1751
2/2
✓ Branch 0 taken 706 times.
✓ Branch 1 taken 9959 times.
10665 if (item->stream_info[i].id == id) {
1752 706 item->current = i;
1753 706 return;
1754 }
1755
1756 // id not found. This shouldn't happen.
1757 ✗ item->current = -1;
1758 }
1759
1760 2072 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1761 MOVFragmentIndex *frag_index)
1762 {
1763 MOVFragmentIndexItem *item;
1764
1/2
✓ Branch 0 taken 2072 times.
✗ Branch 1 not taken.
2072 if (frag_index->current < 0 ||
1765
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 2051 times.
2072 frag_index->current >= frag_index->nb_items)
1766 21 return NULL;
1767
1768 2051 item = &frag_index->item[frag_index->current];
1769
2/4
✓ Branch 0 taken 2051 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2051 times.
✗ Branch 3 not taken.
2051 if (item->current >= 0 && item->current < item->nb_stream_info)
1770 2051 return &item->stream_info[item->current];
1771
1772 // This shouldn't happen
1773 ✗ return NULL;
1774 }
1775
1776 1113 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1777 {
1778 int a, b, m;
1779 int64_t moof_offset;
1780
1781 // Optimize for appending new entries
1782
2/2
✓ Branch 0 taken 1089 times.
✓ Branch 1 taken 24 times.
1113 if (!frag_index->nb_items ||
1783
2/2
✓ Branch 0 taken 469 times.
✓ Branch 1 taken 620 times.
1089 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1784 493 return frag_index->nb_items;
1785
1786 620 a = -1;
1787 620 b = frag_index->nb_items;
1788
1789
2/2
✓ Branch 0 taken 2980 times.
✓ Branch 1 taken 620 times.
3600 while (b - a > 1) {
1790 2980 m = (a + b) >> 1;
1791 2980 moof_offset = frag_index->item[m].moof_offset;
1792
2/2
✓ Branch 0 taken 950 times.
✓ Branch 1 taken 2030 times.
2980 if (moof_offset >= offset)
1793 950 b = m;
1794
2/2
✓ Branch 0 taken 2648 times.
✓ Branch 1 taken 332 times.
2980 if (moof_offset <= offset)
1795 2648 a = m;
1796 }
1797 620 return b;
1798 }
1799
1800 7 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1801 {
1802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 av_assert0(frag_stream_info);
1803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1804 ✗ return frag_stream_info->sidx_pts;
1805
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1806 4 return frag_stream_info->first_tfra_pts;
1807 3 return frag_stream_info->tfdt_dts;
1808 }
1809
1810 226 static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1811 MOVFragmentIndex *frag_index, int index)
1812 {
1813 MOVFragmentStreamInfo * frag_stream_info;
1814 226 MOVStreamContext *sc = dst_st->priv_data;
1815 int64_t timestamp;
1816 int i, j;
1817
1818 // If the stream is referenced by any sidx, limit the search
1819 // to fragments that referenced this stream in the sidx
1820
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 7 times.
226 if (sc->has_sidx) {
1821 219 frag_stream_info = get_frag_stream_info(frag_index, index, sc->id);
1822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!frag_stream_info)
1823 ✗ return AV_NOPTS_VALUE;
1824
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1825 219 return frag_stream_info->sidx_pts;
1826 ✗ if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1827 ✗ return frag_stream_info->first_tfra_pts;
1828 ✗ return frag_stream_info->sidx_pts;
1829 }
1830
1831
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 3 times.
15 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
1832
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7 times.
12 if (dst_st->id != frag_index->item[index].stream_info[i].id)
1833 5 continue;
1834 7 AVStream *frag_stream = NULL;
1835 7 frag_stream_info = &frag_index->item[index].stream_info[i];
1836
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
21 for (j = 0; j < s->nb_streams; j++) {
1837 14 MOVStreamContext *sc2 = s->streams[j]->priv_data;
1838
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (sc2->id == frag_stream_info->id)
1839 7 frag_stream = s->streams[j];
1840 }
1841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!frag_stream) {
1842 ✗ av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1843 ✗ continue;
1844 }
1845 7 timestamp = get_stream_info_time(frag_stream_info);
1846
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (timestamp != AV_NOPTS_VALUE)
1847 4 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1848 }
1849 3 return AV_NOPTS_VALUE;
1850 }
1851
1852 28 static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1853 AVStream *st, int64_t timestamp)
1854 {
1855 int a, b, m, m0;
1856 int64_t frag_time;
1857
1858 28 a = -1;
1859 28 b = frag_index->nb_items;
1860
1861
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 28 times.
252 while (b - a > 1) {
1862 224 m0 = m = (a + b) >> 1;
1863
1864
4/4
✓ Branch 0 taken 226 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 223 times.
453 while (m < b &&
1865 226 (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
1866 3 m++;
1867
1868
4/4
✓ Branch 0 taken 223 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 95 times.
✓ Branch 3 taken 128 times.
224 if (m < b && frag_time <= timestamp)
1869 95 a = m;
1870 else
1871 129 b = m0;
1872 }
1873
1874 28 return a;
1875 }
1876
1877 1063 static int update_frag_index(MOVContext *c, int64_t offset)
1878 {
1879 int index, i;
1880 MOVFragmentIndexItem * item;
1881 MOVFragmentStreamInfo * frag_stream_info;
1882
1883 // If moof_offset already exists in frag_index, return index to it
1884 1063 index = search_frag_moof_offset(&c->frag_index, offset);
1885
2/2
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 484 times.
1063 if (index < c->frag_index.nb_items &&
1886
2/2
✓ Branch 0 taken 577 times.
✓ Branch 1 taken 2 times.
579 c->frag_index.item[index].moof_offset == offset)
1887 577 return index;
1888
1889 // offset is not yet in frag index.
1890 // Insert new item at index (sorted by moof offset)
1891 486 item = av_fast_realloc(c->frag_index.item,
1892 486 &c->frag_index.allocated_size,
1893 486 (c->frag_index.nb_items + 1) *
1894 sizeof(*c->frag_index.item));
1895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486 times.
486 if (!item)
1896 ✗ return -1;
1897 486 c->frag_index.item = item;
1898
1899 486 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1900 sizeof(*item->stream_info));
1901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486 times.
486 if (!frag_stream_info)
1902 ✗ return -1;
1903
1904
2/2
✓ Branch 0 taken 786 times.
✓ Branch 1 taken 486 times.
1272 for (i = 0; i < c->fc->nb_streams; i++) {
1905 // Avoid building frag index if streams lack track id.
1906 786 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1907
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 786 times.
786 if (sc->id < 0) {
1908 ✗ av_free(frag_stream_info);
1909 ✗ return AVERROR_INVALIDDATA;
1910 }
1911
1912 786 frag_stream_info[i].id = sc->id;
1913 786 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1914 786 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1915 786 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1916 786 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1917 786 frag_stream_info[i].index_base = -1;
1918 786 frag_stream_info[i].index_entry = -1;
1919 786 frag_stream_info[i].encryption_index = NULL;
1920 786 frag_stream_info[i].stsd_id = -1;
1921 }
1922
1923
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 484 times.
486 if (index < c->frag_index.nb_items)
1924 2 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1925 2 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1926
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 446 times.
486 if (index <= c->frag_index.current)
1927 40 c->frag_index.current++;
1928
1929 486 item = &c->frag_index.item[index];
1930 486 item->headers_read = 0;
1931 486 item->current = 0;
1932 486 item->nb_stream_info = c->fc->nb_streams;
1933 486 item->moof_offset = offset;
1934 486 item->stream_info = frag_stream_info;
1935 486 c->frag_index.nb_items++;
1936
1937 486 return index;
1938 }
1939
1940 706 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1941 int id, int entries)
1942 {
1943 int i;
1944 MOVFragmentStreamInfo * frag_stream_info;
1945
1946
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (index < 0)
1947 706 return;
1948 ✗ for (i = index; i < frag_index->nb_items; i++) {
1949 ✗ frag_stream_info = get_frag_stream_info(frag_index, i, id);
1950 ✗ if (frag_stream_info && frag_stream_info->index_entry >= 0)
1951 ✗ frag_stream_info->index_entry += entries;
1952 }
1953 }
1954
1955 482 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1956 {
1957 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1958 482 c->fragment.found_tfhd = 0;
1959
1960
4/4
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 479 times.
482 if (!c->has_looked_for_mfra && c->use_mfra_for > 0) {
1961 1 c->has_looked_for_mfra = 1;
1962
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1963 int ret;
1964 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1965 "for a mfra\n");
1966
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((ret = mov_read_mfra(c, pb)) < 0) {
1967 ✗ av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1968 "read the mfra (may be a live ismv)\n");
1969 }
1970 } else {
1971 ✗ av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1972 "seekable, can not look for mfra\n");
1973 }
1974 }
1975 482 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1976 482 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1977 482 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1978 482 return mov_read_default(c, pb, atom);
1979 }
1980
1981 1443 static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version)
1982 {
1983 int64_t time;
1984
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1428 times.
1443 if (version == 1) {
1985 15 time = avio_rb64(pb);
1986 15 avio_rb64(pb);
1987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (time < 0) {
1988 ✗ av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n");
1989 ✗ return;
1990 }
1991 } else {
1992 1428 time = avio_rb32(pb);
1993 1428 avio_rb32(pb); /* modification time */
1994
4/4
✓ Branch 0 taken 649 times.
✓ Branch 1 taken 779 times.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 587 times.
1428 if (time > 0 && time < 2082844800) {
1995 62 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1996 62 time += 2082844800;
1997 }
1998 }
1999
2/2
✓ Branch 0 taken 655 times.
✓ Branch 1 taken 788 times.
1443 if (time) {
2000 655 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
2001
2002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 655 times.
655 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
2003 ✗ av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n");
2004 ✗ return;
2005 }
2006
2007 655 ff_dict_set_timestamp(metadata, "creation_time", time * 1000000);
2008 }
2009 }
2010
2011 838 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2012 {
2013 AVStream *st;
2014 MOVStreamContext *sc;
2015 int version;
2016 838 char language[4] = {0};
2017 unsigned lang;
2018
2019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->fc->nb_streams < 1)
2020 ✗ return 0;
2021 838 st = c->fc->streams[c->fc->nb_streams-1];
2022 838 sc = st->priv_data;
2023
2024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (sc->time_scale) {
2025 ✗ av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
2026 ✗ return AVERROR_INVALIDDATA;
2027 }
2028
2029 838 version = avio_r8(pb);
2030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (version > 1) {
2031 ✗ avpriv_request_sample(c->fc, "Version %d", version);
2032 ✗ return AVERROR_PATCHWELCOME;
2033 }
2034 838 avio_rb24(pb); /* flags */
2035 838 mov_metadata_creation_time(c, pb, &st->metadata, version);
2036
2037 838 sc->time_scale = avio_rb32(pb);
2038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (sc->time_scale <= 0) {
2039 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
2040 ✗ sc->time_scale = 1;
2041 }
2042
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 825 times.
838 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
2043
2044
6/6
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 825 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 825 times.
✓ Branch 5 taken 4 times.
838 if ((version == 1 && st->duration == UINT64_MAX) ||
2045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 825 times.
825 (version != 1 && st->duration == UINT32_MAX)) {
2046 9 st->duration = 0;
2047 }
2048
2049 838 lang = avio_rb16(pb); /* language */
2050
2/2
✓ Branch 1 taken 664 times.
✓ Branch 2 taken 174 times.
838 if (ff_mov_lang_to_iso639(lang, language))
2051 664 av_dict_set(&st->metadata, "language", language, 0);
2052 838 avio_rb16(pb); /* quality */
2053
2054 838 return 0;
2055 }
2056
2057 605 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2058 {
2059 int i;
2060 605 int version = avio_r8(pb); /* version */
2061 605 avio_rb24(pb); /* flags */
2062
2063 605 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
2064 605 c->time_scale = avio_rb32(pb); /* time scale */
2065
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 605 times.
605 if (c->time_scale <= 0) {
2066 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
2067 ✗ c->time_scale = 1;
2068 }
2069 605 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
2070
2071
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 603 times.
605 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
2072 605 avio_rb32(pb); /* preferred scale */
2073
2074 605 avio_rb16(pb); /* preferred volume */
2075
2076 605 avio_skip(pb, 10); /* reserved */
2077
2078 /* movie display matrix, store it in main context and use it later on */
2079
2/2
✓ Branch 0 taken 1815 times.
✓ Branch 1 taken 605 times.
2420 for (i = 0; i < 3; i++) {
2080 1815 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
2081 1815 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
2082 1815 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
2083 }
2084
2085 605 avio_rb32(pb); /* preview time */
2086 605 avio_rb32(pb); /* preview duration */
2087 605 avio_rb32(pb); /* poster time */
2088 605 avio_rb32(pb); /* selection time */
2089 605 avio_rb32(pb); /* selection duration */
2090 605 avio_rb32(pb); /* current time */
2091 605 avio_rb32(pb); /* next track ID */
2092
2093 605 return 0;
2094 }
2095
2096 7 static void set_last_stream_little_endian(AVFormatContext *fc)
2097 {
2098 AVStream *st;
2099
2100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (fc->nb_streams < 1)
2101 ✗ return;
2102 7 st = fc->streams[fc->nb_streams-1];
2103
2104
3/6
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
7 switch (st->codecpar->codec_id) {
2105 5 case AV_CODEC_ID_PCM_S16BE:
2106 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2107 5 break;
2108 1 case AV_CODEC_ID_PCM_S24BE:
2109 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
2110 1 break;
2111 ✗ case AV_CODEC_ID_PCM_S32BE:
2112 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
2113 ✗ break;
2114 1 case AV_CODEC_ID_PCM_F32BE:
2115 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
2116 1 break;
2117 ✗ case AV_CODEC_ID_PCM_F64BE:
2118 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
2119 ✗ break;
2120 ✗ default:
2121 ✗ break;
2122 }
2123 }
2124
2125 5 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2126 {
2127 5 int little_endian = avio_rb16(pb) & 0xFF;
2128 5 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
2129
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (little_endian == 1)
2130 1 set_last_stream_little_endian(c->fc);
2131 5 return 0;
2132 }
2133
2134 6 static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2135 {
2136 int format_flags;
2137 int version, flags;
2138 int pcm_sample_size;
2139 6 AVFormatContext *fc = c->fc;
2140 AVStream *st;
2141 MOVStreamContext *sc;
2142
2143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 6) {
2144 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n");
2145 ✗ return AVERROR_INVALIDDATA;
2146 }
2147
2148 6 version = avio_r8(pb);
2149 6 flags = avio_rb24(pb);
2150
2151
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (version != 0 || flags != 0) {
2152 ✗ av_log(c->fc, AV_LOG_ERROR,
2153 "Unsupported 'pcmC' box with version %d, flags: %x",
2154 version, flags);
2155 ✗ return AVERROR_INVALIDDATA;
2156 }
2157
2158 6 format_flags = avio_r8(pb);
2159 6 pcm_sample_size = avio_r8(pb);
2160
2161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fc->nb_streams < 1)
2162 ✗ return AVERROR_INVALIDDATA;
2163
2164 6 st = fc->streams[fc->nb_streams - 1];
2165 6 sc = st->priv_data;
2166
2167
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (sc->format == MOV_MP4_FPCM_TAG) {
2168
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (pcm_sample_size) {
2169 1 case 32:
2170 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE;
2171 1 break;
2172 ✗ case 64:
2173 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE;
2174 ✗ break;
2175 ✗ default:
2176 ✗ av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2177 pcm_sample_size,
2178 ✗ av_fourcc2str(sc->format));
2179 ✗ return AVERROR_INVALIDDATA;
2180 }
2181
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (sc->format == MOV_MP4_IPCM_TAG) {
2182
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 switch (pcm_sample_size) {
2183 5 case 16:
2184 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2185 5 break;
2186 ✗ case 24:
2187 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
2188 ✗ break;
2189 ✗ case 32:
2190 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
2191 ✗ break;
2192 ✗ default:
2193 ✗ av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2194 pcm_sample_size,
2195 ✗ av_fourcc2str(sc->format));
2196 ✗ return AVERROR_INVALIDDATA;
2197 }
2198 } else {
2199 ✗ av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n",
2200 ✗ av_fourcc2str(sc->format));
2201 ✗ return AVERROR_INVALIDDATA;
2202 }
2203
2204
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (format_flags & 1) // indicates little-endian format. If not present, big-endian format is used
2205 6 set_last_stream_little_endian(c->fc);
2206 6 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2207
2208 6 return 0;
2209 }
2210
2211 72 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2212 {
2213 AVStream *st;
2214 72 HEIFItem *item = NULL;
2215 72 char color_parameter_type[5] = { 0 };
2216 uint16_t color_primaries, color_trc, color_matrix;
2217 int ret;
2218
2219 72 st = get_curr_st(c);
2220
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 68 times.
72 if (!st) {
2221 4 item = get_heif_item(c, c->cur_item_id);
2222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!item)
2223 ✗ return 0;
2224 }
2225
2226 72 ret = ffio_read_size(pb, color_parameter_type, 4);
2227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (ret < 0)
2228 ✗ return ret;
2229
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 24 times.
72 if (strncmp(color_parameter_type, "nclx", 4) &&
2230
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 36 times.
48 strncmp(color_parameter_type, "nclc", 4) &&
2231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 strncmp(color_parameter_type, "prof", 4)) {
2232 ✗ av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
2233 color_parameter_type);
2234 ✗ return 0;
2235 }
2236
2237
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 60 times.
72 if (!strncmp(color_parameter_type, "prof", 4)) {
2238 AVPacketSideData *sd;
2239 uint8_t *icc_profile;
2240
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 if (st) {
2241 8 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
2242 8 &st->codecpar->nb_coded_side_data,
2243 AV_PKT_DATA_ICC_PROFILE,
2244 8 atom.size - 4, 0);
2245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!sd)
2246 ✗ return AVERROR(ENOMEM);
2247 8 icc_profile = sd->data;
2248 } else {
2249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->heif_icc_profile_items >= c->fc->max_streams) {
2250 ✗ av_log(c->fc, AV_LOG_WARNING,
2251 "HEIF ICC profile copies exceed cap %d; ignoring further items\n",
2252 ✗ c->fc->max_streams);
2253 ✗ return 0;
2254 }
2255 4 av_freep(&item->icc_profile);
2256 4 icc_profile = item->icc_profile = av_malloc(atom.size - 4);
2257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!icc_profile) {
2258 ✗ item->icc_profile_size = 0;
2259 ✗ return AVERROR(ENOMEM);
2260 }
2261 4 item->icc_profile_size = atom.size - 4;
2262 4 c->heif_icc_profile_items++;
2263 }
2264 12 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
2265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
2266 ✗ return ret;
2267
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 } else if (st) {
2268 60 color_primaries = avio_rb16(pb);
2269 60 color_trc = avio_rb16(pb);
2270 60 color_matrix = avio_rb16(pb);
2271
2272 60 av_log(c->fc, AV_LOG_TRACE,
2273 "%s: pri %d trc %d matrix %d",
2274 color_parameter_type, color_primaries, color_trc, color_matrix);
2275
2276
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 36 times.
60 if (!strncmp(color_parameter_type, "nclx", 4)) {
2277 24 uint8_t color_range = avio_r8(pb) >> 7;
2278 24 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2279
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 20 times.
24 if (color_range)
2280 4 st->codecpar->color_range = AVCOL_RANGE_JPEG;
2281 else
2282 20 st->codecpar->color_range = AVCOL_RANGE_MPEG;
2283 }
2284
2285
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
60 if (!av_color_primaries_name(color_primaries))
2286 ✗ color_primaries = AVCOL_PRI_UNSPECIFIED;
2287
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
60 if (!av_color_transfer_name(color_trc))
2288 ✗ color_trc = AVCOL_TRC_UNSPECIFIED;
2289
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
60 if (!av_color_space_name(color_matrix))
2290 ✗ color_matrix = AVCOL_SPC_UNSPECIFIED;
2291
2292 60 st->codecpar->color_primaries = color_primaries;
2293 60 st->codecpar->color_trc = color_trc;
2294 60 st->codecpar->color_space = color_matrix;
2295 60 av_log(c->fc, AV_LOG_TRACE, "\n");
2296 }
2297 72 return 0;
2298 }
2299
2300 122 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2301 {
2302 AVStream *st;
2303 unsigned mov_field_order;
2304 122 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2305
2306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 122 times.
122 if (c->fc->nb_streams < 1) // will happen with jp2 files
2307 ✗ return 0;
2308 122 st = c->fc->streams[c->fc->nb_streams-1];
2309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 122 times.
122 if (atom.size < 2)
2310 ✗ return AVERROR_INVALIDDATA;
2311 122 mov_field_order = avio_rb16(pb);
2312
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 25 times.
122 if ((mov_field_order & 0xFF00) == 0x0100)
2313 97 decoded_field_order = AV_FIELD_PROGRESSIVE;
2314
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 else if ((mov_field_order & 0xFF00) == 0x0200) {
2315
3/5
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 23 times.
✗ Branch 4 not taken.
25 switch (mov_field_order & 0xFF) {
2316 1 case 0x01: decoded_field_order = AV_FIELD_TT;
2317 1 break;
2318 ✗ case 0x06: decoded_field_order = AV_FIELD_BB;
2319 ✗ break;
2320 1 case 0x09: decoded_field_order = AV_FIELD_TB;
2321 1 break;
2322 23 case 0x0E: decoded_field_order = AV_FIELD_BT;
2323 23 break;
2324 }
2325 }
2326
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 122 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
122 if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) {
2327 ✗ av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
2328 }
2329 122 st->codecpar->field_order = decoded_field_order;
2330
2331 122 return 0;
2332 }
2333
2334 69 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
2335 {
2336 69 int err = 0;
2337 69 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
2338
2/4
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
69 if (size > INT_MAX || (uint64_t)atom.size > INT_MAX)
2339 ✗ return AVERROR_INVALIDDATA;
2340
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
69 if ((err = av_reallocp(&par->extradata, size)) < 0) {
2341 ✗ par->extradata_size = 0;
2342 ✗ return err;
2343 }
2344 69 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
2345 69 return 0;
2346 }
2347
2348 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
2349 65 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2350 AVCodecParameters *par, uint8_t *buf)
2351 {
2352 65 int64_t result = atom.size;
2353 int err;
2354
2355 65 AV_WB32(buf , atom.size + 8);
2356 65 AV_WL32(buf + 4, atom.type);
2357 65 err = ffio_read_size(pb, buf + 8, atom.size);
2358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (err < 0) {
2359 ✗ par->extradata_size -= atom.size;
2360 ✗ return err;
2361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 } else if (err < atom.size) {
2362 ✗ av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
2363 ✗ par->extradata_size -= atom.size - err;
2364 ✗ result = err;
2365 }
2366 65 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2367 65 return result;
2368 }
2369
2370 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
2371 58 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2372 enum AVCodecID codec_id)
2373 {
2374 AVStream *st;
2375 uint64_t original_size;
2376 int err;
2377
2378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (c->fc->nb_streams < 1) // will happen with jp2 files
2379 ✗ return 0;
2380 58 st = c->fc->streams[c->fc->nb_streams-1];
2381
2382
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
58 if (st->codecpar->codec_id != codec_id)
2383 19 return 0; /* unexpected codec_id - don't mess with extradata */
2384
2385 39 original_size = st->codecpar->extradata_size;
2386 39 err = mov_realloc_extradata(st->codecpar, atom);
2387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err)
2388 ✗ return err;
2389
2390 39 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
2391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err < 0)
2392 ✗ return err;
2393 39 return 0; // Note: this is the original behavior to ignore truncation.
2394 }
2395
2396 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
2397 16 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2398 {
2399 16 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
2400 }
2401
2402 ✗ static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2403 {
2404 ✗ return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS);
2405 }
2406
2407 ✗ static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2408 {
2409 ✗ return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
2410 }
2411
2412 ✗ static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2413 {
2414 ✗ return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
2415 }
2416
2417 19 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2418 {
2419 19 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
2420
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!ret)
2421 19 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
2422 19 return ret;
2423 }
2424
2425 ✗ static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2426 {
2427 ✗ int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
2428
2429 ✗ if (!ret && c->fc->nb_streams >= 1) {
2430 ✗ AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2431 ✗ if (par->extradata_size >= 40) {
2432 ✗ par->height = AV_RB16(&par->extradata[36]);
2433 ✗ par->width = AV_RB16(&par->extradata[38]);
2434 }
2435 }
2436 ✗ return ret;
2437 }
2438
2439 16 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2440 {
2441
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (c->fc->nb_streams >= 1) {
2442 16 AVStream *const st = c->fc->streams[c->fc->nb_streams - 1];
2443 16 FFStream *const sti = ffstream(st);
2444 16 AVCodecParameters *par = st->codecpar;
2445
2446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
2447 ✗ par->codec_id == AV_CODEC_ID_H264 &&
2448 ✗ atom.size > 11) {
2449 int cid;
2450 ✗ avio_skip(pb, 10);
2451 ✗ cid = avio_rb16(pb);
2452 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
2453 ✗ if (cid == 0xd4d || cid == 0xd4e)
2454 ✗ par->width = 1440;
2455 ✗ return 0;
2456
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
2457
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
2458
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
2459
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 atom.size >= 24) {
2460 int num, den;
2461 13 avio_skip(pb, 12);
2462 13 num = avio_rb32(pb);
2463 13 den = avio_rb32(pb);
2464
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
13 if (num <= 0 || den <= 0)
2465 ✗ return 0;
2466
2/3
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
13 switch (avio_rb32(pb)) {
2467 12 case 2:
2468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (den >= INT_MAX / 2)
2469 ✗ return 0;
2470 12 den *= 2;
2471 av_fallthrough;
2472 13 case 1:
2473 13 sti->display_aspect_ratio = (AVRational){ num, den };
2474 av_fallthrough;
2475 13 default:
2476 13 return 0;
2477 }
2478 }
2479 }
2480
2481 3 return mov_read_avid(c, pb, atom);
2482 }
2483
2484 26 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2485 {
2486 26 int ret = 0;
2487 26 int length = 0;
2488 uint64_t original_size;
2489
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (c->fc->nb_streams >= 1) {
2490 26 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (par->codec_id == AV_CODEC_ID_H264)
2492 ✗ return 0;
2493
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (atom.size == 16) {
2494 26 original_size = par->extradata_size;
2495 26 ret = mov_realloc_extradata(par, atom);
2496
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!ret) {
2497 26 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
2498
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (length == atom.size) {
2499 26 const uint8_t range_value = par->extradata[original_size + 19];
2500
1/3
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
26 switch (range_value) {
2501 26 case 1:
2502 26 par->color_range = AVCOL_RANGE_MPEG;
2503 26 break;
2504 ✗ case 2:
2505 ✗ par->color_range = AVCOL_RANGE_JPEG;
2506 ✗ break;
2507 ✗ default:
2508 ✗ av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
2509 ✗ break;
2510 }
2511 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
2512 } else {
2513 /* For some reason the whole atom was not added to the extradata */
2514 ✗ av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
2515 }
2516 } else {
2517 ✗ av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
2518 }
2519 } else {
2520 ✗ av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
2521 }
2522 }
2523
2524 26 return ret;
2525 }
2526
2527 4 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2528 {
2529 4 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
2530 }
2531
2532 33 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2533 {
2534 AVStream *st;
2535 int ret;
2536
2537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (c->fc->nb_streams < 1)
2538 ✗ return 0;
2539 33 st = c->fc->streams[c->fc->nb_streams-1];
2540
2541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if ((uint64_t)atom.size > (1<<30))
2542 ✗ return AVERROR_INVALIDDATA;
2543
2544
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 2 times.
33 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2545
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
2547 // pass all frma atom to codec, needed at least for QDMC and QDM2
2548 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2550 ✗ return ret;
2551
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 } else if (atom.size > 8) { /* to read frma, esds atoms */
2552
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
31 if (st->codecpar->codec_id == AV_CODEC_ID_ALAC && atom.size >= 24) {
2553 uint64_t buffer;
2554 10 ret = ffio_ensure_seekback(pb, 8);
2555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2556 ✗ return ret;
2557 10 buffer = avio_rb64(pb);
2558 10 atom.size -= 8;
2559
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
2560
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 <= atom.size
2561
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 >= 8) {
2562 10 avio_skip(pb, -8);
2563 10 atom.size += 8;
2564 ✗ } else if (!st->codecpar->extradata_size) {
2565 #define ALAC_EXTRADATA_SIZE 36
2566 ✗ st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
2567 ✗ if (!st->codecpar->extradata)
2568 ✗ return AVERROR(ENOMEM);
2569 ✗ st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
2570 ✗ AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
2571 ✗ AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
2572 ✗ AV_WB64(st->codecpar->extradata + 12, buffer);
2573 ✗ avio_read(pb, st->codecpar->extradata + 20, 16);
2574 ✗ avio_skip(pb, atom.size - 24);
2575 ✗ return 0;
2576 }
2577 }
2578
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 if ((ret = mov_read_default(c, pb, atom)) < 0)
2579 ✗ return ret;
2580 } else
2581 ✗ avio_skip(pb, atom.size);
2582 33 return 0;
2583 }
2584
2585 /**
2586 * This function reads atom content and puts data in extradata without tag
2587 * nor size unlike mov_read_extradata.
2588 */
2589 211 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2590 {
2591 AVStream *st;
2592 int ret;
2593
2594 211 st = get_curr_st(c);
2595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 211 times.
211 if (!st)
2596 ✗ return 0;
2597
2598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 211 times.
211 if ((uint64_t)atom.size > (1<<30))
2599 ✗ return AVERROR_INVALIDDATA;
2600
2601
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 210 times.
211 if (atom.type == MKTAG('v','v','c','C')) {
2602 1 avio_skip(pb, 4);
2603 1 atom.size -= 4;
2604 }
2605
2606
2/2
✓ Branch 0 taken 207 times.
✓ Branch 1 taken 4 times.
211 if (atom.size >= 10) {
2607 // Broken files created by legacy versions of libavformat will
2608 // wrap a whole fiel atom inside of a glbl atom.
2609 207 unsigned size = avio_rb32(pb);
2610 207 unsigned type = avio_rl32(pb);
2611
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 207 times.
207 if (avio_feof(pb))
2612 ✗ return AVERROR_INVALIDDATA;
2613 207 avio_seek(pb, -8, SEEK_CUR);
2614
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 197 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
207 if (type == MKTAG('f','i','e','l') && size == atom.size)
2615 10 return mov_read_default(c, pb, atom);
2616 }
2617
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 201 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
201 if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
2618 ✗ av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
2619 ✗ return 0;
2620 }
2621 201 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 201 times.
201 if (ret < 0)
2623 ✗ return ret;
2624
3/4
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 118 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 83 times.
201 if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
2625 /* HEVC-based Dolby Vision derived from hvc1.
2626 Happens to match with an identifier
2627 previously utilized for DV. Thus, if we have
2628 the hvcC extradata box available as specified,
2629 set codec to HEVC */
2630 ✗ st->codecpar->codec_id = AV_CODEC_ID_HEVC;
2631
2632 201 return 0;
2633 }
2634
2635 2 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2636 {
2637 AVStream *st;
2638 uint8_t profile_level;
2639 int ret;
2640
2641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
2642 ✗ return 0;
2643 2 st = c->fc->streams[c->fc->nb_streams-1];
2644
2645
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (atom.size >= (1<<28) || atom.size < 7)
2646 ✗ return AVERROR_INVALIDDATA;
2647
2648 2 profile_level = avio_r8(pb);
2649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((profile_level & 0xf0) != 0xc0)
2650 ✗ return 0;
2651
2652 2 avio_seek(pb, 6, SEEK_CUR);
2653 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
2654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2655 ✗ return ret;
2656
2657 2 return 0;
2658 }
2659
2660 70 static int mov_find_tref_id(const MovTref *tag, uint32_t id)
2661 {
2662
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 42 times.
100 for (int i = 0; i < tag->nb_id; i++) {
2663
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 30 times.
58 if (tag->id[i] == id)
2664 28 return 1;
2665 }
2666 42 return 0;
2667 }
2668
2669 42 static int mov_add_tref_id(MovTref *tag, uint32_t id)
2670 {
2671 42 int ret = mov_find_tref_id(tag, id);
2672
2673
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 if (!ret) {
2674 42 uint32_t *tmp = av_realloc_array(tag->id, tag->nb_id + 1, sizeof(*tag->id));
2675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!tmp)
2676 ✗ return AVERROR(ENOMEM);
2677 42 tag->id = tmp;
2678 42 tag->id[tag->nb_id++] = id;
2679 }
2680
2681 42 return 0;
2682 }
2683
2684 1990 static MovTref *mov_find_tref_tag(const MOVStreamContext *sc, uint32_t name)
2685 {
2686
2/2
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 1922 times.
2107 for (int i = 0; i < sc->nb_tref_tags; i++) {
2687 185 MovTref *entry = &sc->tref_tags[i];
2688
2689
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 117 times.
185 if (entry->name == name)
2690 68 return entry;
2691 }
2692 1922 return NULL;
2693 }
2694
2695 32 static MovTref *mov_add_tref_tag(MOVStreamContext *sc, uint32_t name)
2696 {
2697 32 MovTref *tag = mov_find_tref_tag(sc, name);
2698
2699
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (!tag) {
2700 32 MovTref *tmp = av_realloc_array(sc->tref_tags, sc->nb_tref_tags + 1,
2701 sizeof(*sc->tref_tags));
2702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!tmp)
2703 ✗ return NULL;
2704 32 sc->tref_tags = tmp;
2705 32 tag = &sc->tref_tags[sc->nb_tref_tags++];
2706 32 *tag = (MovTref){ .name = name };
2707 }
2708
2709 32 return tag;
2710 }
2711
2712 11 static int mov_read_cdsc_rndr(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2713 {
2714 AVStream* st;
2715 MOVStreamContext* sc;
2716
2717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
2718 ✗ return 0;
2719
2720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size > 4) {
2721 ✗ av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type cdsc/rndr is supported\n");
2722 ✗ return AVERROR_PATCHWELCOME;
2723 }
2724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 4)
2725 ✗ return AVERROR_INVALIDDATA;
2726
2727 11 st = get_curr_st(c);
2728
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!st)
2729 ✗ return AVERROR_INVALIDDATA;
2730 11 sc = st->priv_data;
2731
2732 11 MovTref *tag = mov_add_tref_tag(sc, atom.type);
2733
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!tag)
2734 ✗ return AVERROR(ENOMEM);
2735
2736 11 int ret = mov_add_tref_id(tag, avio_rb32(pb));
2737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0)
2738 ✗ return ret;
2739
2740 11 return 0;
2741 }
2742
2743 ✗ static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2744 {
2745 AVStream* st;
2746 MOVStreamContext* sc;
2747
2748 ✗ if (c->fc->nb_streams < 1)
2749 ✗ return 0;
2750
2751 /* For SBAS this should be fine - though beware if someone implements a
2752 * tref atom processor that doesn't drop down to default then this may
2753 * be lost. */
2754 ✗ if (atom.size > 4) {
2755 ✗ av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2756 ✗ return AVERROR_PATCHWELCOME;
2757 }
2758 ✗ if (atom.size < 4)
2759 ✗ return AVERROR_INVALIDDATA;
2760
2761 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
2762 ✗ sc = st->priv_data;
2763
2764 ✗ MovTref *tag = mov_add_tref_tag(sc, atom.type);
2765 ✗ if (!tag)
2766 ✗ return AVERROR(ENOMEM);
2767
2768 ✗ int ret = mov_add_tref_id(tag, avio_rb32(pb));
2769 ✗ if (ret < 0)
2770 ✗ return ret;
2771
2772 ✗ return 0;
2773 }
2774
2775 ✗ static int mov_read_vdep(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2776 {
2777 AVStream* st;
2778 MOVStreamContext* sc;
2779
2780 ✗ if (c->fc->nb_streams < 1)
2781 ✗ return 0;
2782
2783 ✗ if (atom.size > 4)
2784 ✗ av_log(c->fc, AV_LOG_WARNING, "More than one vdep reference is not supported.\n");
2785 ✗ if (atom.size < 4)
2786 ✗ return AVERROR_INVALIDDATA;
2787
2788 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
2789 ✗ sc = st->priv_data;
2790
2791 ✗ MovTref *tag = mov_add_tref_tag(sc, atom.type);
2792 ✗ if (!tag)
2793 ✗ return AVERROR(ENOMEM);
2794
2795 ✗ int ret = mov_add_tref_id(tag, avio_rb32(pb));
2796 ✗ if (ret < 0)
2797 ✗ return ret;
2798
2799 ✗ return 0;
2800 }
2801
2802 /**
2803 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2804 * but can have extradata appended at the end after the 40 bytes belonging
2805 * to the struct.
2806 */
2807 ✗ static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2808 {
2809 AVStream *st;
2810 int ret;
2811
2812 ✗ if (c->fc->nb_streams < 1)
2813 ✗ return 0;
2814 ✗ if (atom.size <= 40)
2815 ✗ return 0;
2816 ✗ st = c->fc->streams[c->fc->nb_streams-1];
2817
2818 ✗ if ((uint64_t)atom.size > (1<<30))
2819 ✗ return AVERROR_INVALIDDATA;
2820
2821 ✗ avio_skip(pb, 40);
2822 ✗ ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
2823 ✗ if (ret < 0)
2824 ✗ return ret;
2825
2826 ✗ return 0;
2827 }
2828
2829 838 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2830 {
2831 AVStream *st;
2832 MOVStreamContext *sc;
2833 unsigned int i, entries;
2834
2835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->trak_index < 0) {
2836 ✗ av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
2837 ✗ return 0;
2838 }
2839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->fc->nb_streams < 1)
2840 ✗ return 0;
2841 838 st = c->fc->streams[c->fc->nb_streams-1];
2842 838 sc = st->priv_data;
2843
2844 838 avio_r8(pb); /* version */
2845 838 avio_rb24(pb); /* flags */
2846
2847 // Clamp allocation size for `chunk_offsets` -- don't throw an error for an
2848 // invalid count since the EOF path doesn't throw either.
2849 838 entries = avio_rb32(pb);
2850 838 entries =
2851
2/2
✓ Branch 0 taken 833 times.
✓ Branch 1 taken 5 times.
838 FFMIN(entries,
2852 FFMAX(0, (atom.size - 8) /
2853 (atom.type == MKTAG('s', 't', 'c', 'o') ? 4 : 8)));
2854
2855
2/2
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 704 times.
838 if (!entries)
2856 134 return 0;
2857
2858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 704 times.
704 if (sc->chunk_offsets) {
2859 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2860 ✗ return 0;
2861 }
2862
2863 704 av_free(sc->chunk_offsets);
2864 704 sc->chunk_count = 0;
2865 704 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 704 times.
704 if (!sc->chunk_offsets)
2867 ✗ return AVERROR(ENOMEM);
2868 704 sc->chunk_count = entries;
2869
2870
2/2
✓ Branch 0 taken 700 times.
✓ Branch 1 taken 4 times.
704 if (atom.type == MKTAG('s','t','c','o'))
2871
3/4
✓ Branch 0 taken 43956 times.
✓ Branch 1 taken 700 times.
✓ Branch 2 taken 43956 times.
✗ Branch 3 not taken.
44656 for (i = 0; i < entries && !pb->eof_reached; i++)
2872 43956 sc->chunk_offsets[i] = avio_rb32(pb);
2873
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (atom.type == MKTAG('c','o','6','4'))
2874
3/4
✓ Branch 0 taken 136336 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 136336 times.
✗ Branch 3 not taken.
136340 for (i = 0; i < entries && !pb->eof_reached; i++) {
2875 136336 sc->chunk_offsets[i] = avio_rb64(pb);
2876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136336 times.
136336 if (sc->chunk_offsets[i] < 0) {
2877 ✗ av_log(c->fc, AV_LOG_WARNING, "Impossible chunk_offset\n");
2878 ✗ sc->chunk_offsets[i] = 0;
2879 }
2880 }
2881 else
2882 ✗ return AVERROR_INVALIDDATA;
2883
2884 704 sc->chunk_count = i;
2885
2886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 704 times.
704 if (pb->eof_reached) {
2887 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2888 ✗ return AVERROR_EOF;
2889 }
2890
2891 704 return 0;
2892 }
2893
2894 918 static int mov_codec_id(AVStream *st, uint32_t format)
2895 {
2896 918 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2897
2898
2/2
✓ Branch 0 taken 544 times.
✓ Branch 1 taken 374 times.
918 if (id <= 0 &&
2899
2/2
✓ Branch 0 taken 541 times.
✓ Branch 1 taken 3 times.
544 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 541 times.
541 (format & 0xFFFF) == 'T' + ('S' << 8)))
2901 3 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2902
2903
4/4
✓ Branch 0 taken 464 times.
✓ Branch 1 taken 454 times.
✓ Branch 2 taken 377 times.
✓ Branch 3 taken 87 times.
918 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2904 377 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2905
3/4
✓ Branch 0 taken 521 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 521 times.
✗ Branch 3 not taken.
541 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2906 /* skip old ASF MPEG-4 tag */
2907
2/2
✓ Branch 0 taken 517 times.
✓ Branch 1 taken 4 times.
521 format && format != MKTAG('m','p','4','s')) {
2908 517 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2909
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 439 times.
517 if (id <= 0)
2910 78 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2911
2/2
✓ Branch 0 taken 443 times.
✓ Branch 1 taken 74 times.
517 if (id > 0)
2912 443 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2913
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 62 times.
74 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2914
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
12 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2916 62 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2917
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 6 times.
62 if (id <= 0) {
2918
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 4 times.
108 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2919
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 4 times.
108 AV_CODEC_ID_TTML : id;
2920 }
2921
2922
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 48 times.
62 if (id > 0)
2923 14 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2924 else
2925 48 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2926 }
2927 }
2928
2929 918 st->codecpar->codec_tag = format;
2930
2931 918 return id;
2932 }
2933
2934 390 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2935 AVStream *st, MOVStreamContext *sc)
2936 {
2937 390 uint8_t codec_name[32] = { 0 };
2938 int64_t stsd_start;
2939 unsigned int len;
2940 390 uint32_t id = 0;
2941
2942 /* The first 16 bytes of the video sample description are already
2943 * read in ff_mov_read_stsd_entries() */
2944 390 stsd_start = avio_tell(pb) - 16;
2945
2946
2/2
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 261 times.
390 if (c->isom) {
2947 129 avio_skip(pb, 2); /* pre_defined */
2948 129 avio_skip(pb, 2); /* reserved */
2949 129 avio_skip(pb, 12); /* pre_defined */
2950 } else {
2951 261 avio_rb16(pb); /* version */
2952 261 avio_rb16(pb); /* revision level */
2953 261 id = avio_rl32(pb); /* vendor */
2954 261 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2955 261 avio_rb32(pb); /* temporal quality */
2956 261 avio_rb32(pb); /* spatial quality */
2957 }
2958
2959 390 st->codecpar->width = avio_rb16(pb); /* width */
2960 390 st->codecpar->height = avio_rb16(pb); /* height */
2961
2962 390 avio_rb32(pb); /* horiz resolution */
2963 390 avio_rb32(pb); /* vert resolution */
2964 390 avio_rb32(pb); /* data size, always 0 */
2965 390 avio_rb16(pb); /* frames per samples */
2966
2967 390 len = avio_r8(pb); /* codec name, pascal string */
2968
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 389 times.
390 if (len > 31)
2969 1 len = 31;
2970 390 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2971
2/2
✓ Branch 0 taken 387 times.
✓ Branch 1 taken 3 times.
390 if (len < 31)
2972 387 avio_skip(pb, 31 - len);
2973
2974
2/2
✓ Branch 0 taken 297 times.
✓ Branch 1 taken 93 times.
390 if (codec_name[0])
2975 297 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2976
2977 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 390 times.
390 if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2979 ✗ st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2980 ✗ st->codecpar->width &= ~1;
2981 ✗ st->codecpar->height &= ~1;
2982 }
2983 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2984
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 390 times.
390 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2985 ✗ !strncmp(codec_name, "Sorenson H263", 13))
2986 ✗ st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2987
2988 390 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2989
2990 390 avio_seek(pb, stsd_start, SEEK_SET);
2991
2992
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 372 times.
390 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2993 18 st->codecpar->bits_per_coded_sample &= 0x1F;
2994 18 sc->has_palette = 1;
2995 }
2996 390 }
2997
2998 397 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2999 AVStream *st, MOVStreamContext *sc)
3000 {
3001 int bits_per_sample, flags;
3002 397 uint16_t version = avio_rb16(pb);
3003 397 uint32_t id = 0;
3004 397 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
3005 int channel_count;
3006
3007
2/2
✓ Branch 0 taken 307 times.
✓ Branch 1 taken 90 times.
397 if (c->isom)
3008 307 avio_skip(pb, 6); /* reserved */
3009 else {
3010 90 avio_rb16(pb); /* revision level */
3011 90 id = avio_rl32(pb); /* vendor */
3012 90 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
3013 }
3014
3015 397 channel_count = avio_rb16(pb);
3016
3017 397 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3018 397 st->codecpar->ch_layout.nb_channels = channel_count;
3019 397 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
3020 397 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
3021
3022 397 sc->audio_cid = avio_rb16(pb);
3023 397 avio_rb16(pb); /* packet size = 0 */
3024
3025 397 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
3026
3027 // Read QT version 1 fields. In version 0 these do not exist.
3028 397 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
3029
3/4
✓ Branch 0 taken 307 times.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 307 times.
✗ Branch 3 not taken.
397 if (!c->isom ||
3030
1/2
✓ Branch 0 taken 307 times.
✗ Branch 1 not taken.
307 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
3031
4/4
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 298 times.
307 (sc->stsd_version == 0 && version > 0)) {
3032
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 42 times.
94 if (version == 1) {
3033 52 sc->samples_per_frame = avio_rb32(pb);
3034 52 avio_rb32(pb); /* bytes per packet */
3035 52 sc->bytes_per_frame = avio_rb32(pb);
3036 52 avio_rb32(pb); /* bytes per sample */
3037
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 38 times.
42 } else if (version == 2) {
3038 4 avio_rb32(pb); /* sizeof struct only */
3039 4 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
3040 4 channel_count = avio_rb32(pb);
3041 4 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3042 4 st->codecpar->ch_layout.nb_channels = channel_count;
3043 4 avio_rb32(pb); /* always 0x7F000000 */
3044 4 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
3045
3046 4 flags = avio_rb32(pb); /* lpcm format specific flag */
3047 4 sc->bytes_per_frame = avio_rb32(pb);
3048 4 sc->samples_per_frame = avio_rb32(pb);
3049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
3050 ✗ st->codecpar->codec_id =
3051 ✗ ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
3052 flags);
3053 }
3054
6/6
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 25 times.
94 if (version == 0 || (version == 1 && sc->audio_cid != -2)) {
3055 /* can't correctly handle variable sized packet as audio unit */
3056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 switch (st->codecpar->codec_id) {
3057 ✗ case AV_CODEC_ID_MP2:
3058 case AV_CODEC_ID_MP3:
3059 ✗ ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
3060 ✗ break;
3061 }
3062 }
3063 }
3064
3065
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 397 times.
397 if (sc->format == 0) {
3066 ✗ if (st->codecpar->bits_per_coded_sample == 8)
3067 ✗ st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
3068 ✗ else if (st->codecpar->bits_per_coded_sample == 16)
3069 ✗ st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
3070 }
3071
3072
7/7
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 350 times.
397 switch (st->codecpar->codec_id) {
3073 7 case AV_CODEC_ID_PCM_S8:
3074 case AV_CODEC_ID_PCM_U8:
3075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
3076 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
3077 7 break;
3078 24 case AV_CODEC_ID_PCM_S16LE:
3079 case AV_CODEC_ID_PCM_S16BE:
3080
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 if (st->codecpar->bits_per_coded_sample == 8)
3081 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
3082
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 else if (st->codecpar->bits_per_coded_sample == 24)
3083 ✗ st->codecpar->codec_id =
3084 ✗ st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
3085 ✗ AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
3086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 else if (st->codecpar->bits_per_coded_sample == 32)
3087 ✗ st->codecpar->codec_id =
3088 ✗ st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
3089 ✗ AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
3090 24 break;
3091 /* set values for old format before stsd version 1 appeared */
3092 2 case AV_CODEC_ID_MACE3:
3093 2 sc->samples_per_frame = 6;
3094 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
3095 2 break;
3096 8 case AV_CODEC_ID_MACE6:
3097 8 sc->samples_per_frame = 6;
3098 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
3099 8 break;
3100 5 case AV_CODEC_ID_ADPCM_IMA_QT:
3101 5 sc->samples_per_frame = 64;
3102 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
3103 5 break;
3104 1 case AV_CODEC_ID_GSM:
3105 1 sc->samples_per_frame = 160;
3106 1 sc->bytes_per_frame = 33;
3107 1 break;
3108 350 default:
3109 350 break;
3110 }
3111
3112 397 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
3113
3/4
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 344 times.
✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
397 if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->ch_layout.nb_channels <= INT_MAX) {
3114 53 st->codecpar->bits_per_coded_sample = bits_per_sample;
3115 53 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
3116 }
3117 397 }
3118
3119 15 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
3120 AVStream *st, MOVStreamContext *sc,
3121 int64_t size)
3122 {
3123 // ttxt stsd contains display flags, justification, background
3124 // color, fonts, and default styles, so fake an atom to read it
3125 15 MOVAtom fake_atom = { .size = size };
3126 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
3127 // in extradata unlike stpp MP4 TTML.
3128
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
3129
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
15 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
3130 11 mov_read_glbl(c, pb, fake_atom);
3131 15 st->codecpar->width = sc->width;
3132 15 st->codecpar->height = sc->height;
3133 15 }
3134
3135 52 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
3136 AVStream *st, MOVStreamContext *sc,
3137 int64_t size)
3138 {
3139 int ret;
3140
3141
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 24 times.
52 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
3142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if ((int)size != size)
3143 ✗ return AVERROR(ENOMEM);
3144
3145 28 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
3146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
3147 ✗ return ret;
3148
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (size > 16) {
3149 28 MOVStreamContext *tmcd_ctx = st->priv_data;
3150 int val;
3151 28 val = AV_RB32(st->codecpar->extradata + 4);
3152 28 tmcd_ctx->tmcd_flags = val;
3153 28 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
3154 28 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
3155 28 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
3156
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 18 times.
28 if (size > 30) {
3157 10 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
3158 10 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
3159
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 if (format == AV_RB32("name") && (int64_t)size >= (int64_t)len + 18) {
3160 10 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
3161
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 if (str_size > 0 && size >= (int)str_size + 30 &&
3162
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 st->codecpar->extradata[30] /* Don't add empty string */) {
3163 10 char *reel_name = av_malloc(str_size + 1);
3164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!reel_name)
3165 ✗ return AVERROR(ENOMEM);
3166 10 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
3167 10 reel_name[str_size] = 0; /* Add null terminator */
3168 10 av_dict_set(&st->metadata, "reel_name", reel_name,
3169 AV_DICT_DONT_STRDUP_VAL);
3170 }
3171 }
3172 }
3173 }
3174
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 } else if (st->codecpar->codec_id == AV_CODEC_ID_ITUT_T35) {
3175 2 int t35_identifier_length = avio_r8(pb);
3176
3177
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (t35_identifier_length <= 0 || t35_identifier_length >= size)
3178 ✗ return AVERROR_INVALIDDATA;
3179
3180 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, t35_identifier_length);
3181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
3182 ✗ return ret;
3183
3184 2 int hrsd_len = size - t35_identifier_length - 1;
3185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (hrsd_len > 0) {
3186 ✗ uint8_t *hrsd_str = av_malloc(hrsd_len + 1);
3187 ✗ if (!hrsd_str)
3188 ✗ return AVERROR(ENOMEM);
3189
3190 ✗ ret = ffio_read_size(pb, hrsd_str, hrsd_len);
3191 ✗ if (ret < 0) {
3192 ✗ av_free(hrsd_str);
3193 ✗ return ret;
3194 }
3195 ✗ if (hrsd_str[0]) {
3196 ✗ hrsd_str[hrsd_len] = 0;
3197 ✗ ret = av_dict_set(&st->metadata, "description", hrsd_str, AV_DICT_DONT_OVERWRITE);
3198 }
3199 ✗ av_free(hrsd_str);
3200 }
3201 } else {
3202 /* other codec type, just skip (rtp, mp4s ...) */
3203 22 avio_skip(pb, size);
3204 }
3205 52 return 0;
3206 }
3207
3208 838 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
3209 AVStream *st, MOVStreamContext *sc)
3210 {
3211 838 FFStream *const sti = ffstream(st);
3212
3213
2/2
✓ Branch 0 taken 397 times.
✓ Branch 1 taken 441 times.
838 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
3214
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 397 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
397 !st->codecpar->sample_rate && sc->time_scale > 1)
3215 ✗ st->codecpar->sample_rate = sc->time_scale;
3216
3217 /* special codec parameters handling */
3218
7/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 103 times.
✓ Branch 5 taken 15 times.
✓ Branch 6 taken 16 times.
✓ Branch 7 taken 14 times.
✓ Branch 8 taken 119 times.
✓ Branch 9 taken 560 times.
838 switch (st->codecpar->codec_id) {
3219 #if CONFIG_DV_DEMUXER
3220 ✗ case AV_CODEC_ID_DVAUDIO:
3221 ✗ if (c->dv_fctx) {
3222 ✗ avpriv_request_sample(c->fc, "multiple DV audio streams");
3223 ✗ return AVERROR(ENOSYS);
3224 }
3225
3226 ✗ c->dv_fctx = avformat_alloc_context();
3227 ✗ if (!c->dv_fctx) {
3228 ✗ av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
3229 ✗ return AVERROR(ENOMEM);
3230 }
3231 ✗ c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
3232 ✗ if (!c->dv_demux) {
3233 ✗ av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
3234 ✗ return AVERROR(ENOMEM);
3235 }
3236 ✗ sc->dv_audio_container = 1;
3237 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
3238 ✗ break;
3239 #endif
3240 /* no ifdef since parameters are always those */
3241 ✗ case AV_CODEC_ID_QCELP:
3242 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
3243 ✗ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3244 // force sample rate for qcelp when not stored in mov
3245 ✗ if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
3246 ✗ st->codecpar->sample_rate = 8000;
3247 // FIXME: Why is the following needed for some files?
3248 ✗ sc->samples_per_frame = 160;
3249 ✗ if (!sc->bytes_per_frame)
3250 ✗ sc->bytes_per_frame = 35;
3251 ✗ break;
3252 ✗ case AV_CODEC_ID_AMR_NB:
3253 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
3254 ✗ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3255 /* force sample rate for amr, stsd in 3gp does not store sample rate */
3256 ✗ st->codecpar->sample_rate = 8000;
3257 ✗ break;
3258 11 case AV_CODEC_ID_AMR_WB:
3259 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
3260 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3261 11 st->codecpar->sample_rate = 16000;
3262 11 break;
3263 103 case AV_CODEC_ID_MP2:
3264 case AV_CODEC_ID_MP3:
3265 /* force type after stsd for m1a hdlr */
3266 103 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
3267 103 break;
3268 15 case AV_CODEC_ID_GSM:
3269 case AV_CODEC_ID_ADPCM_MS:
3270 case AV_CODEC_ID_ADPCM_IMA_WAV:
3271 case AV_CODEC_ID_ILBC:
3272 case AV_CODEC_ID_MACE3:
3273 case AV_CODEC_ID_MACE6:
3274 case AV_CODEC_ID_QDM2:
3275 15 st->codecpar->block_align = sc->bytes_per_frame;
3276 15 break;
3277 16 case AV_CODEC_ID_ALAC:
3278
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
3279 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
3280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
3281 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
3282 ✗ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3283 ✗ st->codecpar->ch_layout.nb_channels = channel_count;
3284 }
3285 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
3286 }
3287 16 break;
3288 14 case AV_CODEC_ID_AC3:
3289 case AV_CODEC_ID_EAC3:
3290 case AV_CODEC_ID_MPEG1VIDEO:
3291 case AV_CODEC_ID_VC1:
3292 case AV_CODEC_ID_VP8:
3293 case AV_CODEC_ID_VP9:
3294 14 sti->need_parsing = AVSTREAM_PARSE_FULL;
3295 14 break;
3296 119 case AV_CODEC_ID_PRORES_RAW:
3297 case AV_CODEC_ID_PRORES:
3298 case AV_CODEC_ID_APV:
3299 case AV_CODEC_ID_EVC:
3300 case AV_CODEC_ID_LCEVC:
3301 case AV_CODEC_ID_AV1:
3302 /* field_order detection of H264 requires parsing */
3303 case AV_CODEC_ID_H264:
3304 119 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3305 119 break;
3306 560 default:
3307 560 break;
3308 }
3309 838 return 0;
3310 }
3311
3312 855 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
3313 int codec_tag, int format,
3314 int64_t size)
3315 {
3316
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 838 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 16 times.
855 if (codec_tag &&
3317 1 (codec_tag != format &&
3318 // AVID 1:1 samples with differing data format and codec tag exist
3319
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
3320 // prores is allowed to have differing data format and codec tag
3321
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
3322 // so is dv (sigh)
3323
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
3324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 (c->fc->video_codec_id ? ff_codec_get_id(ff_codec_movvideo_tags, format) != c->fc->video_codec_id
3325 : codec_tag != MKTAG('j','p','e','g')))) {
3326 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3327 * export it as a separate AVStream but this needs a few changes
3328 * in the MOV demuxer, patch welcome. */
3329
3330 1 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3331 1 avio_skip(pb, size);
3332 1 return 1;
3333 }
3334
3335 854 return 0;
3336 }
3337
3338 854 static int mov_finalize_stsd_entry(MOVContext *c, AVStream *st)
3339 {
3340 int ret;
3341
3342 /* special codec parameters handling */
3343
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 763 times.
854 switch (st->codecpar->codec_id) {
3344 91 case AV_CODEC_ID_H264:
3345 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
3346
1/30
✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
91 if (!st->codecpar->extradata_size && TAG_IS_AVCI(st->codecpar->codec_tag)) {
3347 ✗ ret = ff_generate_avci_extradata(st);
3348 ✗ if (ret < 0)
3349 ✗ return ret;
3350 }
3351 91 break;
3352 763 default:
3353 763 break;
3354 }
3355
3356 854 return 0;
3357 }
3358
3359 838 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3360 {
3361 AVStream *st;
3362 MOVStreamContext *sc;
3363 int pseudo_stream_id;
3364
3365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 av_assert0 (c->fc->nb_streams >= 1);
3366 838 st = c->fc->streams[c->fc->nb_streams-1];
3367 838 sc = st->priv_data;
3368
3369 838 for (pseudo_stream_id = 0;
3370
3/4
✓ Branch 0 taken 855 times.
✓ Branch 1 taken 838 times.
✓ Branch 2 taken 855 times.
✗ Branch 3 not taken.
1693 pseudo_stream_id < entries && !pb->eof_reached;
3371 855 pseudo_stream_id++) {
3372 //Parsing Sample description table
3373 enum AVCodecID id;
3374 855 int ret, dref_id = 1;
3375 855 MOVAtom a = { AV_RL32("stsd") };
3376 855 int64_t start_pos = avio_tell(pb);
3377 855 int64_t size = avio_rb32(pb); /* size */
3378 855 uint32_t format = avio_rl32(pb); /* data format */
3379
3380
1/2
✓ Branch 0 taken 855 times.
✗ Branch 1 not taken.
855 if (size >= 16) {
3381 855 avio_rb32(pb); /* reserved */
3382 855 avio_rb16(pb); /* reserved */
3383 855 dref_id = avio_rb16(pb);
3384 ✗ } else if (size <= 7) {
3385 ✗ av_log(c->fc, AV_LOG_ERROR,
3386 "invalid size %"PRId64" in stsd\n", size);
3387 ✗ return AVERROR_INVALIDDATA;
3388 }
3389
3390
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 854 times.
855 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3391 855 size - (avio_tell(pb) - start_pos))) {
3392 1 sc->stsd_count++;
3393 1 continue;
3394 }
3395
3396
2/2
✓ Branch 0 taken 838 times.
✓ Branch 1 taken 16 times.
854 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
3397 854 sc->dref_id= dref_id;
3398 854 sc->format = format;
3399
3400 854 id = mov_codec_id(st, format);
3401
3402 854 av_log(c->fc, AV_LOG_TRACE,
3403 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3404 854 av_fourcc2str(format), st->codecpar->codec_type);
3405
3406 854 st->codecpar->codec_id = id;
3407
2/2
✓ Branch 0 taken 390 times.
✓ Branch 1 taken 464 times.
854 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3408 390 mov_parse_stsd_video(c, pb, st, sc);
3409
2/2
✓ Branch 0 taken 397 times.
✓ Branch 1 taken 67 times.
464 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3410 397 mov_parse_stsd_audio(c, pb, st, sc);
3411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 397 times.
397 if (st->codecpar->sample_rate < 0) {
3412 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3413 ✗ return AVERROR_INVALIDDATA;
3414 }
3415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 397 times.
397 if (st->codecpar->ch_layout.nb_channels < 0) {
3416 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3417 ✗ return AVERROR_INVALIDDATA;
3418 }
3419
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 52 times.
67 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3420 15 mov_parse_stsd_subtitle(c, pb, st, sc,
3421 15 size - (avio_tell(pb) - start_pos));
3422 } else {
3423 52 ret = mov_parse_stsd_data(c, pb, st, sc,
3424 52 size - (avio_tell(pb) - start_pos));
3425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (ret < 0)
3426 ✗ return ret;
3427 }
3428 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3429 854 a.size = size - (avio_tell(pb) - start_pos);
3430
2/2
✓ Branch 0 taken 686 times.
✓ Branch 1 taken 168 times.
854 if (a.size > 8) {
3431
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 686 times.
686 if ((ret = mov_read_default(c, pb, a)) < 0)
3432 ✗ return ret;
3433
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 167 times.
168 } else if (a.size > 0)
3434 1 avio_skip(pb, a.size);
3435
3436 854 ret = mov_finalize_stsd_entry(c, st);
3437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 854 times.
854 if (ret < 0)
3438 ✗ return ret;
3439
3440
3/4
✓ Branch 0 taken 854 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 452 times.
✓ Branch 3 taken 402 times.
854 if (sc->extradata && st->codecpar->extradata) {
3441 452 int extra_size = st->codecpar->extradata_size;
3442
3443 /* Move the current stream extradata to the stream context one. */
3444 452 sc->extradata_size[pseudo_stream_id] = extra_size;
3445 452 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3446 452 st->codecpar->extradata = NULL;
3447 452 st->codecpar->extradata_size = 0;
3448 }
3449 854 sc->stsd_count++;
3450 }
3451
3452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (pb->eof_reached) {
3453 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3454 ✗ return AVERROR_EOF;
3455 }
3456
3457 838 return 0;
3458 }
3459
3460 838 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3461 {
3462 AVStream *st;
3463 MOVStreamContext *sc;
3464 int ret, entries;
3465
3466
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->fc->nb_streams < 1)
3467 ✗ return 0;
3468 838 st = c->fc->streams[c->fc->nb_streams - 1];
3469 838 sc = st->priv_data;
3470
3471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (sc->extradata) {
3472 ✗ av_log(c->fc, AV_LOG_ERROR,
3473 "Duplicate stsd found in this track.\n");
3474 ✗ return AVERROR_INVALIDDATA;
3475 }
3476
3477 838 sc->stsd_version = avio_r8(pb);
3478 838 avio_rb24(pb); /* flags */
3479 838 entries = avio_rb32(pb);
3480
3481 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3482
3/6
✓ Branch 0 taken 838 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 838 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 838 times.
838 if (entries <= 0 || entries > atom.size / 8 || entries > 1024) {
3483 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3484 ✗ return AVERROR_INVALIDDATA;
3485 }
3486
3487 /* Prepare space for hosting multiple extradata. */
3488 838 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (!sc->extradata)
3490 ✗ return AVERROR(ENOMEM);
3491
3492 838 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (!sc->extradata_size) {
3494 ✗ ret = AVERROR(ENOMEM);
3495 ✗ goto fail;
3496 }
3497
3498 838 ret = ff_mov_read_stsd_entries(c, pb, entries);
3499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (ret < 0)
3500 ✗ goto fail;
3501
3502 /* Restore back the primary extradata. */
3503 838 av_freep(&st->codecpar->extradata);
3504 838 st->codecpar->extradata_size = sc->extradata_size[0];
3505
2/2
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 401 times.
838 if (sc->extradata_size[0]) {
3506 437 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 437 times.
437 if (!st->codecpar->extradata)
3508 ✗ return AVERROR(ENOMEM);
3509 437 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3510 }
3511
3512 838 return mov_finalize_stsd_codec(c, pb, st, sc);
3513 ✗ fail:
3514 ✗ if (sc->extradata) {
3515 int j;
3516 ✗ for (j = 0; j < sc->stsd_count; j++)
3517 ✗ av_freep(&sc->extradata[j]);
3518 }
3519
3520 ✗ sc->stsd_count = 0;
3521 ✗ av_freep(&sc->extradata);
3522 ✗ av_freep(&sc->extradata_size);
3523 ✗ return ret;
3524 }
3525
3526 838 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3527 {
3528 AVStream *st;
3529 MOVStreamContext *sc;
3530 unsigned int i, entries;
3531
3532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->trak_index < 0) {
3533 ✗ av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3534 ✗ return 0;
3535 }
3536
3537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->fc->nb_streams < 1)
3538 ✗ return 0;
3539 838 st = c->fc->streams[c->fc->nb_streams-1];
3540 838 sc = st->priv_data;
3541
3542 838 avio_r8(pb); /* version */
3543 838 avio_rb24(pb); /* flags */
3544
3545 838 entries = avio_rb32(pb);
3546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if ((uint64_t)entries * 12 + 4 > atom.size)
3547 ✗ return AVERROR_INVALIDDATA;
3548
3549 838 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3550
3551
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 705 times.
838 if (!entries)
3552 133 return 0;
3553
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 705 times.
705 if (sc->stsc_data) {
3554 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3555 ✗ return 0;
3556 }
3557 705 av_free(sc->stsc_data);
3558 705 sc->stsc_count = 0;
3559 705 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 705 times.
705 if (!sc->stsc_data)
3561 ✗ return AVERROR(ENOMEM);
3562
3563
3/4
✓ Branch 0 taken 3932 times.
✓ Branch 1 taken 705 times.
✓ Branch 2 taken 3932 times.
✗ Branch 3 not taken.
4637 for (i = 0; i < entries && !pb->eof_reached; i++) {
3564 3932 sc->stsc_data[i].first = avio_rb32(pb);
3565 3932 sc->stsc_data[i].count = avio_rb32(pb);
3566 3932 sc->stsc_data[i].id = avio_rb32(pb);
3567 }
3568
3569 705 sc->stsc_count = i;
3570
2/2
✓ Branch 0 taken 3932 times.
✓ Branch 1 taken 705 times.
4637 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3571 3932 int64_t first_min = i + 1;
3572
5/6
✓ Branch 0 taken 3227 times.
✓ Branch 1 taken 705 times.
✓ Branch 2 taken 3227 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3227 times.
✓ Branch 5 taken 705 times.
3932 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
3573
1/2
✓ Branch 0 taken 3227 times.
✗ Branch 1 not taken.
3227 (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) ||
3574
1/2
✓ Branch 0 taken 3932 times.
✗ Branch 1 not taken.
3932 sc->stsc_data[i].first < first_min ||
3575
1/2
✓ Branch 0 taken 3932 times.
✗ Branch 1 not taken.
3932 sc->stsc_data[i].count < 1 ||
3576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3932 times.
3932 sc->stsc_data[i].id < 1) {
3577 ✗ av_log(c->fc, AV_LOG_WARNING, "STSC entry %d is invalid (first=%d count=%d id=%d)\n", i, sc->stsc_data[i].first, sc->stsc_data[i].count, sc->stsc_data[i].id);
3578 ✗ if (i+1 >= sc->stsc_count) {
3579 ✗ if (sc->stsc_data[i].count == 0 && i > 0) {
3580 ✗ sc->stsc_count --;
3581 ✗ continue;
3582 }
3583 ✗ sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3584 ✗ if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3585 ✗ sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3586 ✗ sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3587 ✗ sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3588 ✗ continue;
3589 }
3590 ✗ av_assert0(sc->stsc_data[i+1].first >= 2);
3591 // We replace this entry by the next valid
3592 ✗ sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3593 ✗ sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3594 ✗ sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3595 }
3596 }
3597
3598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 705 times.
705 if (pb->eof_reached) {
3599 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3600 ✗ return AVERROR_EOF;
3601 }
3602
3603 705 return 0;
3604 }
3605
3606 355574 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3607 {
3608 355574 return index < count - 1;
3609 }
3610
3611 /* Compute the samples value for the stsc entry at the given index. */
3612 57207 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3613 {
3614 int chunk_count;
3615
3616
2/2
✓ Branch 1 taken 57009 times.
✓ Branch 2 taken 198 times.
57207 if (mov_stsc_index_valid(index, sc->stsc_count))
3617 57009 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3618 else {
3619 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3621 198 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3622 }
3623
3624 57207 return sc->stsc_data[index].count * (int64_t)chunk_count;
3625 }
3626
3627 ✗ static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3628 {
3629 AVStream *st;
3630 MOVStreamContext *sc;
3631 unsigned i, entries;
3632
3633 ✗ if (c->trak_index < 0) {
3634 ✗ av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3635 ✗ return 0;
3636 }
3637
3638 ✗ if (c->fc->nb_streams < 1)
3639 ✗ return 0;
3640 ✗ st = c->fc->streams[c->fc->nb_streams-1];
3641 ✗ sc = st->priv_data;
3642
3643 ✗ avio_rb32(pb); // version + flags
3644
3645 ✗ entries = avio_rb32(pb);
3646 ✗ if (sc->stps_data)
3647 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3648 ✗ av_free(sc->stps_data);
3649 ✗ sc->stps_count = 0;
3650 ✗ sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3651 ✗ if (!sc->stps_data)
3652 ✗ return AVERROR(ENOMEM);
3653
3654 ✗ for (i = 0; i < entries && !pb->eof_reached; i++) {
3655 ✗ sc->stps_data[i] = avio_rb32(pb);
3656 }
3657
3658 ✗ sc->stps_count = i;
3659
3660 ✗ if (pb->eof_reached) {
3661 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3662 ✗ return AVERROR_EOF;
3663 }
3664
3665 ✗ return 0;
3666 }
3667
3668 185 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3669 {
3670 AVStream *st;
3671 FFStream *sti;
3672 MOVStreamContext *sc;
3673 unsigned int i, entries;
3674
3675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 185 times.
185 if (c->trak_index < 0) {
3676 ✗ av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3677 ✗ return 0;
3678 }
3679
3680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 185 times.
185 if (c->fc->nb_streams < 1)
3681 ✗ return 0;
3682 185 st = c->fc->streams[c->fc->nb_streams-1];
3683 185 sti = ffstream(st);
3684 185 sc = st->priv_data;
3685
3686 185 avio_r8(pb); /* version */
3687 185 avio_rb24(pb); /* flags */
3688
3689 185 entries = avio_rb32(pb);
3690
3691 185 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3692
3693
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 171 times.
185 if (!entries) {
3694 14 sc->keyframe_absent = 1;
3695
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
14 if (!sti->need_parsing && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
3696 ✗ sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3697 14 return 0;
3698 }
3699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 171 times.
171 if (sc->keyframes)
3700 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 171 times.
171 if (entries >= UINT_MAX / sizeof(int))
3702 ✗ return AVERROR_INVALIDDATA;
3703 171 av_freep(&sc->keyframes);
3704 171 sc->keyframe_count = 0;
3705 171 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 171 times.
171 if (!sc->keyframes)
3707 ✗ return AVERROR(ENOMEM);
3708
3709
3/4
✓ Branch 0 taken 5772 times.
✓ Branch 1 taken 171 times.
✓ Branch 2 taken 5772 times.
✗ Branch 3 not taken.
5943 for (i = 0; i < entries && !pb->eof_reached; i++) {
3710 5772 sc->keyframes[i] = avio_rb32(pb);
3711 }
3712
3713 171 sc->keyframe_count = i;
3714
3715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 171 times.
171 if (pb->eof_reached) {
3716 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3717 ✗ return AVERROR_EOF;
3718 }
3719
3720 171 return 0;
3721 }
3722
3723 838 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3724 {
3725 AVStream *st;
3726 MOVStreamContext *sc;
3727 unsigned int i, entries, sample_size, field_size, num_bytes;
3728 GetBitContext gb;
3729 unsigned char* buf;
3730 int ret;
3731
3732
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->trak_index < 0) {
3733 ✗ av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3734 ✗ return 0;
3735 }
3736
3737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->fc->nb_streams < 1)
3738 ✗ return 0;
3739 838 st = c->fc->streams[c->fc->nb_streams-1];
3740 838 sc = st->priv_data;
3741
3742 838 avio_r8(pb); /* version */
3743 838 avio_rb24(pb); /* flags */
3744
3745
1/2
✓ Branch 0 taken 838 times.
✗ Branch 1 not taken.
838 if (atom.type == MKTAG('s','t','s','z')) {
3746 838 sample_size = avio_rb32(pb);
3747
2/2
✓ Branch 0 taken 792 times.
✓ Branch 1 taken 46 times.
838 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3748 792 sc->sample_size = sample_size;
3749 838 sc->stsz_sample_size = sample_size;
3750 838 field_size = 32;
3751 } else {
3752 ✗ sample_size = 0;
3753 ✗ avio_rb24(pb); /* reserved */
3754 ✗ field_size = avio_r8(pb);
3755 }
3756 838 entries = avio_rb32(pb);
3757
3758 838 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3759
3760 838 sc->sample_count = entries;
3761
2/2
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 604 times.
838 if (sample_size)
3762 234 return 0;
3763
3764
4/8
✓ Branch 0 taken 604 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 604 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 604 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 604 times.
604 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
3765 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3766 ✗ return AVERROR_INVALIDDATA;
3767 }
3768
3769
2/2
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 470 times.
604 if (!entries)
3770 134 return 0;
3771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 if (entries >= (INT_MAX - 4 - 8 * AV_INPUT_BUFFER_PADDING_SIZE) / field_size)
3772 ✗ return AVERROR_INVALIDDATA;
3773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 if (sc->sample_sizes)
3774 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3775 470 av_free(sc->sample_sizes);
3776 470 sc->sample_count = 0;
3777 470 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 if (!sc->sample_sizes)
3779 ✗ return AVERROR(ENOMEM);
3780
3781 470 num_bytes = (entries*field_size+4)>>3;
3782
3783 470 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 if (!buf) {
3785 ✗ av_freep(&sc->sample_sizes);
3786 ✗ return AVERROR(ENOMEM);
3787 }
3788
3789 470 ret = ffio_read_size(pb, buf, num_bytes);
3790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 if (ret < 0) {
3791 ✗ av_freep(&sc->sample_sizes);
3792 ✗ av_free(buf);
3793 ✗ av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3794 ✗ return 0;
3795 }
3796
3797 470 init_get_bits(&gb, buf, 8*num_bytes);
3798
3799
2/2
✓ Branch 0 taken 240774 times.
✓ Branch 1 taken 470 times.
241244 for (i = 0; i < entries; i++) {
3800 240774 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240774 times.
240774 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3802 ✗ av_free(buf);
3803 ✗ av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3804 ✗ return AVERROR_INVALIDDATA;
3805 }
3806 240774 sc->data_size += sc->sample_sizes[i];
3807 }
3808
3809 470 sc->sample_count = i;
3810
3811 470 av_free(buf);
3812
3813 470 return 0;
3814 }
3815
3816 838 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3817 {
3818 AVStream *st;
3819 MOVStreamContext *sc;
3820 unsigned int i, entries;
3821 838 int64_t duration = 0;
3822 838 int64_t total_sample_count = 0;
3823 838 int64_t current_dts = 0;
3824 838 int64_t corrected_dts = 0;
3825
3826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->trak_index < 0) {
3827 ✗ av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3828 ✗ return 0;
3829 }
3830
3831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->fc->nb_streams < 1)
3832 ✗ return 0;
3833 838 st = c->fc->streams[c->fc->nb_streams-1];
3834 838 sc = st->priv_data;
3835
3836 838 avio_r8(pb); /* version */
3837 838 avio_rb24(pb); /* flags */
3838 838 entries = avio_rb32(pb);
3839
3840 838 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3841 838 c->fc->nb_streams-1, entries);
3842
3843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (sc->stts_data)
3844 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3845 838 av_freep(&sc->stts_data);
3846 838 sc->stts_count = 0;
3847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3848 ✗ return AVERROR(ENOMEM);
3849
3850
3/4
✓ Branch 0 taken 3127 times.
✓ Branch 1 taken 838 times.
✓ Branch 2 taken 3127 times.
✗ Branch 3 not taken.
3965 for (i = 0; i < entries && !pb->eof_reached; i++) {
3851 unsigned int sample_duration;
3852 unsigned int sample_count;
3853 3127 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3854 3127 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3855 min_entries * sizeof(*sc->stts_data));
3856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3127 times.
3127 if (!stts_data) {
3857 ✗ av_freep(&sc->stts_data);
3858 ✗ sc->stts_count = 0;
3859 ✗ return AVERROR(ENOMEM);
3860 }
3861 3127 sc->stts_count = min_entries;
3862 3127 sc->stts_data = stts_data;
3863
3864 3127 sample_count = avio_rb32(pb);
3865 3127 sample_duration = avio_rb32(pb);
3866
3867 3127 sc->stts_data[i].count= sample_count;
3868 3127 sc->stts_data[i].duration= sample_duration;
3869
3870 3127 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3871 sample_count, sample_duration);
3872
3873 /* STTS sample offsets are uint32 but some files store it as int32
3874 * with negative values used to correct DTS delays.
3875 There may be abnormally large values as well. */
3876
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3126 times.
3127 if (sample_duration > c->max_stts_delta) {
3877 // assume high delta is a correction if negative when cast as int32
3878 1 int32_t delta_magnitude = (int32_t)sample_duration;
3879 1 av_log(c->fc, AV_LOG_WARNING, "Too large sample offset %u in stts entry %u with count %u in st:%d. Clipping to 1.\n",
3880 sample_duration, i, sample_count, st->index);
3881 1 sc->stts_data[i].duration = 1;
3882
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 corrected_dts = av_sat_add64(corrected_dts, (delta_magnitude < 0 ? (int64_t)delta_magnitude : 1) * sample_count);
3883 } else {
3884 3126 corrected_dts += sample_duration * (uint64_t)sample_count;
3885 }
3886
3887 3127 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3888
3889
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 3105 times.
3127 if (current_dts > corrected_dts) {
3890 22 int64_t drift = av_sat_sub64(current_dts, corrected_dts) / FFMAX(sample_count, 1);
3891
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 1 times.
22 uint32_t correction = (sc->stts_data[i].duration > drift) ? drift : sc->stts_data[i].duration - 1;
3892 22 current_dts -= correction * (uint64_t)sample_count;
3893 22 sc->stts_data[i].duration -= correction;
3894 }
3895
3896 3127 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3897 3127 total_sample_count+=sc->stts_data[i].count;
3898 }
3899
3900 838 sc->stts_count = i;
3901
3902
2/2
✓ Branch 0 taken 704 times.
✓ Branch 1 taken 134 times.
838 if (duration > 0 &&
3903
1/2
✓ Branch 0 taken 704 times.
✗ Branch 1 not taken.
704 duration <= INT64_MAX - sc->duration_for_fps &&
3904
1/2
✓ Branch 0 taken 704 times.
✗ Branch 1 not taken.
704 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3905 704 sc->duration_for_fps += duration;
3906 704 sc->nb_frames_for_fps += total_sample_count;
3907 }
3908
3909
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (pb->eof_reached) {
3910 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3911 ✗ return AVERROR_EOF;
3912 }
3913
3914 838 st->nb_frames= total_sample_count;
3915
2/2
✓ Branch 0 taken 704 times.
✓ Branch 1 taken 134 times.
838 if (duration)
3916 704 st->duration= FFMIN(st->duration, duration);
3917
3918 // All samples have zero duration. They have higher chance be chose by
3919 // mov_find_next_sample, which leads to seek again and again.
3920 //
3921 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3922 // So only mark data stream as discarded for safety.
3923
3/4
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 704 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 134 times.
838 if (!duration && sc->stts_count &&
3924 ✗ st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3925 ✗ av_log(c->fc, AV_LOG_WARNING,
3926 "All samples in data stream index:id [%d:%d] have zero "
3927 "duration, stream set to be discarded by default. Override "
3928 "using AVStream->discard or -discard for ffmpeg command.\n",
3929 st->index, sc->id);
3930 ✗ st->discard = AVDISCARD_ALL;
3931 }
3932 838 sc->track_end = duration;
3933 838 return 0;
3934 }
3935
3936 46 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3937 {
3938 AVStream *st;
3939 MOVStreamContext *sc;
3940 unsigned int i;
3941 int64_t entries;
3942
3943
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (c->fc->nb_streams < 1)
3944 ✗ return 0;
3945 46 st = c->fc->streams[c->fc->nb_streams - 1];
3946 46 sc = st->priv_data;
3947
3948 46 avio_r8(pb); /* version */
3949 46 avio_rb24(pb); /* flags */
3950 46 entries = atom.size - 4;
3951
3952 46 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3953 46 c->fc->nb_streams - 1, entries);
3954
3955
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 38 times.
46 if (sc->sdtp_data)
3956 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3957 46 av_freep(&sc->sdtp_data);
3958 46 sc->sdtp_count = 0;
3959
3960
2/4
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
46 if (entries < 0 || entries > UINT_MAX)
3961 ✗ return AVERROR(ERANGE);
3962
3963 46 sc->sdtp_data = av_malloc(entries);
3964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!sc->sdtp_data)
3965 ✗ return AVERROR(ENOMEM);
3966
3967
3/4
✓ Branch 0 taken 3823 times.
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 3823 times.
✗ Branch 3 not taken.
3869 for (i = 0; i < entries && !pb->eof_reached; i++)
3968 3823 sc->sdtp_data[i] = avio_r8(pb);
3969 46 sc->sdtp_count = i;
3970
3971 46 return 0;
3972 }
3973
3974 17509 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3975 {
3976
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 16373 times.
17509 if (duration < 0) {
3977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3978 ✗ av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3979 ✗ duration++;
3980 }
3981 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3982 }
3983 17509 }
3984
3985 84 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3986 {
3987 AVStream *st;
3988 MOVStreamContext *sc;
3989 84 unsigned int i, entries, ctts_count = 0;
3990
3991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (c->trak_index < 0) {
3992 ✗ av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
3993 ✗ return 0;
3994 }
3995
3996
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (c->fc->nb_streams < 1)
3997 ✗ return 0;
3998 84 st = c->fc->streams[c->fc->nb_streams-1];
3999 84 sc = st->priv_data;
4000
4001 84 avio_r8(pb); /* version */
4002 84 avio_rb24(pb); /* flags */
4003 84 entries = avio_rb32(pb);
4004
4005 84 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
4006
4007
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 80 times.
84 if (!entries)
4008 4 return 0;
4009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
4010 ✗ return AVERROR_INVALIDDATA;
4011 80 av_freep(&sc->ctts_data);
4012 80 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
4013
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!sc->ctts_data)
4014 ✗ return AVERROR(ENOMEM);
4015
4016
3/4
✓ Branch 0 taken 5266 times.
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 5266 times.
✗ Branch 3 not taken.
5346 for (i = 0; i < entries && !pb->eof_reached; i++) {
4017 MOVCtts *ctts_data;
4018 5266 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
4019 5266 const size_t requested_size =
4020 5266 min_size_needed > sc->ctts_allocated_size ?
4021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5266 times.
5266 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
4022 min_size_needed;
4023 5266 int count = avio_rb32(pb);
4024 5266 int duration = avio_rb32(pb);
4025
4026
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5266 times.
5266 if (count <= 0) {
4027 ✗ av_log(c->fc, AV_LOG_TRACE,
4028 "ignoring CTTS entry with count=%d duration=%d\n",
4029 count, duration);
4030 ✗ continue;
4031 }
4032
4033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5266 times.
5266 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
4034 ✗ return AVERROR(ENOMEM);
4035
4036 5266 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
4037
4038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5266 times.
5266 if (!ctts_data)
4039 ✗ return AVERROR(ENOMEM);
4040
4041 5266 sc->ctts_data = ctts_data;
4042
4043 5266 ctts_data[ctts_count].count = count;
4044 5266 ctts_data[ctts_count].offset = duration;
4045 5266 ctts_count++;
4046
4047 5266 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
4048 count, duration);
4049
4050
2/2
✓ Branch 0 taken 5118 times.
✓ Branch 1 taken 148 times.
5266 if (i+2<entries)
4051 5118 mov_update_dts_shift(sc, duration, c->fc);
4052 }
4053
4054 80 sc->ctts_count = ctts_count;
4055
4056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (pb->eof_reached) {
4057 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
4058 ✗ return AVERROR_EOF;
4059 }
4060
4061 80 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
4062
4063 80 return 0;
4064 }
4065
4066 54 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4067 {
4068 AVStream *st;
4069 MOVStreamContext *sc;
4070 uint8_t version;
4071 uint32_t grouping_type;
4072 uint32_t default_length;
4073 av_unused uint32_t default_group_description_index;
4074 uint32_t entry_count;
4075
4076
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (c->fc->nb_streams < 1)
4077 ✗ return 0;
4078 54 st = c->fc->streams[c->fc->nb_streams - 1];
4079 54 sc = st->priv_data;
4080
4081 54 version = avio_r8(pb); /* version */
4082 54 avio_rb24(pb); /* flags */
4083 54 grouping_type = avio_rl32(pb);
4084
4085 /*
4086 * This function only supports "sync" boxes, but the code is able to parse
4087 * other boxes (such as "tscl", "tsas" and "stsa")
4088 */
4089
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 5 times.
54 if (grouping_type != MKTAG('s','y','n','c'))
4090 49 return 0;
4091
4092
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
4093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
4094 5 entry_count = avio_rb32(pb);
4095
4096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (entry_count > atom.size)
4097 ✗ return AVERROR_INVALIDDATA;
4098
4099 5 av_freep(&sc->sgpd_sync);
4100 5 sc->sgpd_sync_count = entry_count;
4101 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
4102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
4103 ✗ return AVERROR(ENOMEM);
4104
4105
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
13 for (uint32_t i = 0; i < entry_count && !pb->eof_reached; i++) {
4106 8 uint32_t description_length = default_length;
4107
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (version >= 1 && default_length == 0)
4108 ✗ description_length = avio_rb32(pb);
4109
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
4110 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
4111 8 sc->sgpd_sync[i] = nal_unit_type;
4112 8 description_length -= 1;
4113 }
4114 8 avio_skip(pb, description_length);
4115 }
4116
4117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
4118 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
4119 ✗ return AVERROR_EOF;
4120 }
4121
4122 5 return 0;
4123 }
4124
4125 50 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4126 {
4127 AVStream *st;
4128 MOVStreamContext *sc;
4129 unsigned int i, entries;
4130 uint8_t version;
4131 uint32_t grouping_type;
4132 MOVSbgp *table, **tablep;
4133 int *table_count;
4134
4135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (c->fc->nb_streams < 1)
4136 ✗ return 0;
4137 50 st = c->fc->streams[c->fc->nb_streams-1];
4138 50 sc = st->priv_data;
4139
4140 50 version = avio_r8(pb); /* version */
4141 50 avio_rb24(pb); /* flags */
4142 50 grouping_type = avio_rl32(pb);
4143
4144
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 49 times.
50 if (grouping_type == MKTAG('r','a','p',' ')) {
4145 1 tablep = &sc->rap_group;
4146 1 table_count = &sc->rap_group_count;
4147
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 44 times.
49 } else if (grouping_type == MKTAG('s','y','n','c')) {
4148 5 tablep = &sc->sync_group;
4149 5 table_count = &sc->sync_group_count;
4150 } else {
4151 44 return 0;
4152 }
4153
4154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
4155 ✗ avio_rb32(pb); /* grouping_type_parameter */
4156
4157 6 entries = avio_rb32(pb);
4158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
4159 ✗ return 0;
4160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
4161 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
4162 6 av_freep(tablep);
4163 6 table = av_malloc_array(entries, sizeof(*table));
4164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
4165 ✗ return AVERROR(ENOMEM);
4166 6 *tablep = table;
4167
4168
3/4
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
38 for (i = 0; i < entries && !pb->eof_reached; i++) {
4169 32 table[i].count = avio_rb32(pb); /* sample_count */
4170 32 table[i].index = avio_rb32(pb); /* group_description_index */
4171 }
4172
4173 6 *table_count = i;
4174
4175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
4176 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
4177 ✗ return AVERROR_EOF;
4178 }
4179
4180 6 return 0;
4181 }
4182
4183 /**
4184 * Get ith edit list entry (media time, duration).
4185 */
4186 1121 static int get_edit_list_entry(MOVContext *mov,
4187 const MOVStreamContext *msc,
4188 unsigned int edit_list_index,
4189 int64_t *edit_list_media_time,
4190 int64_t *edit_list_duration,
4191 int64_t global_timescale)
4192 {
4193
2/2
✓ Branch 0 taken 546 times.
✓ Branch 1 taken 575 times.
1121 if (edit_list_index == msc->elst_count) {
4194 546 return 0;
4195 }
4196 575 *edit_list_media_time = msc->elst_data[edit_list_index].time;
4197 575 *edit_list_duration = msc->elst_data[edit_list_index].duration;
4198
4199 /* duration is in global timescale units;convert to msc timescale */
4200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 if (global_timescale == 0) {
4201 ✗ avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
4202 ✗ return 0;
4203 }
4204 575 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
4205 global_timescale);
4206
4207
1/2
✓ Branch 0 taken 575 times.
✗ Branch 1 not taken.
575 if (*edit_list_duration < 0 ||
4208
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 *edit_list_media_time > INT64_MAX - *edit_list_duration)
4209 ✗ *edit_list_duration = 0;
4210
4211 575 return 1;
4212 }
4213
4214 /**
4215 * Find the closest previous frame to the timestamp_pts, in e_old index
4216 * entries. Searching for just any frame / just key frames can be controlled by
4217 * last argument 'flag'.
4218 * Note that if ctts_data is not NULL, we will always search for a key frame
4219 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
4220 * return the first frame of the video.
4221 *
4222 * Here the timestamp_pts is considered to be a presentation timestamp and
4223 * the timestamp of index entries are considered to be decoding timestamps.
4224 *
4225 * Returns 0 if successful in finding a frame, else returns -1.
4226 * Places the found index corresponding output arg.
4227 *
4228 * If ctts_old is not NULL, then refines the searched entry by searching
4229 * backwards from the found timestamp, to find the frame with correct PTS.
4230 *
4231 * Places the found ctts_index and ctts_sample in corresponding output args.
4232 */
4233 575 static int find_prev_closest_index(AVStream *st,
4234 AVIndexEntry *e_old,
4235 int nb_old,
4236 MOVTimeToSample *tts_data,
4237 int64_t tts_count,
4238 int64_t timestamp_pts,
4239 int flag,
4240 int64_t* index,
4241 int64_t* tts_index,
4242 int64_t* tts_sample)
4243 {
4244 575 MOVStreamContext *msc = st->priv_data;
4245 575 FFStream *const sti = ffstream(st);
4246 575 AVIndexEntry *e_keep = sti->index_entries;
4247 575 int nb_keep = sti->nb_index_entries;
4248 575 int64_t i = 0;
4249
4250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 av_assert0(index);
4251
4252 // If dts_shift > 0, then all the index timestamps will have to be offset by
4253 // at least dts_shift amount to obtain PTS.
4254 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
4255
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 566 times.
575 if (msc->dts_shift > 0) {
4256 9 timestamp_pts -= msc->dts_shift;
4257 }
4258
4259 575 sti->index_entries = e_old;
4260 575 sti->nb_index_entries = nb_old;
4261 575 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
4262
4263 // Keep going backwards in the index entries until the timestamp is the same.
4264
2/2
✓ Branch 0 taken 574 times.
✓ Branch 1 taken 1 times.
575 if (*index >= 0) {
4265
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 546 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
574 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
4266 ✗ i--) {
4267 ✗ if ((flag & AVSEEK_FLAG_ANY) ||
4268 ✗ (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
4269 ✗ *index = i - 1;
4270 }
4271 }
4272 }
4273
4274 // If we have CTTS then refine the search, by searching backwards over PTS
4275 // computed by adding corresponding CTTS durations to index timestamps.
4276
4/4
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 487 times.
✓ Branch 2 taken 87 times.
✓ Branch 3 taken 1 times.
575 if (msc->ctts_count && *index >= 0) {
4277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
87 av_assert0(tts_index);
4278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
87 av_assert0(tts_sample);
4279 // Find out the ctts_index for the found frame.
4280 87 *tts_index = FFMIN(*index, tts_count);
4281 87 *tts_sample = 0;
4282
4283
4/6
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 98 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 98 times.
✗ Branch 5 not taken.
105 while (*index >= 0 && (*tts_index) >= 0 && (*tts_index) < tts_count) {
4284 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
4285 // No need to add dts_shift to the timestamp here because timestamp_pts has already been
4286 // compensated by dts_shift above.
4287
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 13 times.
98 if ((e_old[*index].timestamp + tts_data[*tts_index].offset) <= timestamp_pts &&
4288
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 5 times.
85 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
4289 80 break;
4290 }
4291
4292 18 (*index)--;
4293
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (*tts_sample == 0) {
4294 18 (*tts_index)--;
4295
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 7 times.
18 if (*tts_index >= 0)
4296 11 *tts_sample = tts_data[*tts_index].count - 1;
4297 } else {
4298 ✗ (*tts_sample)--;
4299 }
4300 }
4301 }
4302
4303 /* restore AVStream state*/
4304 575 sti->index_entries = e_keep;
4305 575 sti->nb_index_entries = nb_keep;
4306
2/2
✓ Branch 0 taken 567 times.
✓ Branch 1 taken 8 times.
575 return *index >= 0 ? 0 : -1;
4307 }
4308
4309 /**
4310 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
4311 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
4312 *
4313 * This function is similar to ff_add_index_entry in libavformat/utils.c
4314 * except that here we are always unconditionally adding an index entry to
4315 * the end, instead of searching the entries list and skipping the add if
4316 * there is an existing entry with the same timestamp.
4317 * This is needed because the mov_fix_index calls this func with the same
4318 * unincremented timestamp for successive discarded frames.
4319 */
4320 362304 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
4321 int size, int distance, int flags)
4322 {
4323 362304 FFStream *const sti = ffstream(st);
4324 AVIndexEntry *entries, *ie;
4325 362304 int64_t index = -1;
4326 362304 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
4327
4328 // Double the allocation each time, to lower memory fragmentation.
4329 // Another difference from ff_add_index_entry function.
4330 362304 const size_t requested_size =
4331 362304 min_size_needed > sti->index_entries_allocated_size ?
4332
2/2
✓ Branch 0 taken 2430 times.
✓ Branch 1 taken 359874 times.
362304 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
4333 min_size_needed;
4334
4335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 362304 times.
362304 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
4336 ✗ return -1;
4337
4338 362304 entries = av_fast_realloc(sti->index_entries,
4339 &sti->index_entries_allocated_size,
4340 requested_size);
4341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 362304 times.
362304 if (!entries)
4342 ✗ return -1;
4343
4344 362304 sti->index_entries = entries;
4345
4346 362304 index = sti->nb_index_entries++;
4347 362304 ie= &entries[index];
4348
4349 362304 ie->pos = pos;
4350 362304 ie->timestamp = timestamp;
4351 362304 ie->min_distance= distance;
4352 362304 ie->size= size;
4353 362304 ie->flags = flags;
4354 362304 return index;
4355 }
4356
4357 /**
4358 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4359 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4360 */
4361 51 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4362 int64_t* frame_duration_buffer,
4363 int frame_duration_buffer_size) {
4364 51 FFStream *const sti = ffstream(st);
4365 51 int i = 0;
4366
2/4
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 51 times.
51 av_assert0(end_index >= 0 && end_index <= sti->nb_index_entries);
4367
2/2
✓ Branch 0 taken 196 times.
✓ Branch 1 taken 51 times.
247 for (i = 0; i < frame_duration_buffer_size; i++) {
4368 196 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4369 196 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4370 }
4371 51 }
4372
4373 197056 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4374 int count, int offset, unsigned int duration)
4375 {
4376 MOVTimeToSample *tts_buf_new;
4377 197056 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4378 197056 const size_t requested_size =
4379 197056 min_size_needed > *allocated_size ?
4380
2/2
✓ Branch 0 taken 1729 times.
✓ Branch 1 taken 195327 times.
197056 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4381 min_size_needed;
4382
4383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197056 times.
197056 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4384 ✗ return -1;
4385
4386 197056 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4387
4388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197056 times.
197056 if (!tts_buf_new)
4389 ✗ return -1;
4390
4391 197056 *tts_data = tts_buf_new;
4392
4393 197056 tts_buf_new[*tts_count].count = count;
4394 197056 tts_buf_new[*tts_count].offset = offset;
4395 197056 tts_buf_new[*tts_count].duration = duration;
4396
4397 197056 *tts_count = (*tts_count) + 1;
4398 197056 return 0;
4399 }
4400
4401 #define MAX_REORDER_DELAY 16
4402 757 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4403 {
4404 757 MOVStreamContext *msc = st->priv_data;
4405 757 FFStream *const sti = ffstream(st);
4406 757 int ctts_ind = 0;
4407 757 int ctts_sample = 0;
4408 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4409 757 int buf_start = 0;
4410 int j, r, num_swaps;
4411
4412
2/2
✓ Branch 0 taken 12869 times.
✓ Branch 1 taken 757 times.
13626 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4413 12869 pts_buf[j] = INT64_MIN;
4414
4415
3/4
✓ Branch 0 taken 757 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
✓ Branch 3 taken 677 times.
757 if (st->codecpar->video_delay <= 0 && msc->ctts_count &&
4416
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 28 times.
80 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4417 52 st->codecpar->video_delay = 0;
4418
3/4
✓ Branch 0 taken 138527 times.
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 138527 times.
✗ Branch 3 not taken.
138579 for (int ind = 0; ind < sti->nb_index_entries && ctts_ind < msc->tts_count; ++ind) {
4419 // Point j to the last elem of the buffer and insert the current pts there.
4420 138527 j = buf_start;
4421 138527 buf_start = (buf_start + 1);
4422
2/2
✓ Branch 0 taken 8121 times.
✓ Branch 1 taken 130406 times.
138527 if (buf_start == MAX_REORDER_DELAY + 1)
4423 8121 buf_start = 0;
4424
4425 138527 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4426
4427 // The timestamps that are already in the sorted buffer, and are greater than the
4428 // current pts, are exactly the timestamps that need to be buffered to output PTS
4429 // in correct sorted order.
4430 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4431 // can be computed as the maximum no. of swaps any particular timestamp needs to
4432 // go through, to keep this buffer in sorted order.
4433 138527 num_swaps = 0;
4434
2/2
✓ Branch 0 taken 142881 times.
✓ Branch 1 taken 4 times.
142885 while (j != buf_start) {
4435 142881 r = j - 1;
4436
2/2
✓ Branch 0 taken 8426 times.
✓ Branch 1 taken 134455 times.
142881 if (r < 0) r = MAX_REORDER_DELAY;
4437
2/2
✓ Branch 0 taken 4358 times.
✓ Branch 1 taken 138523 times.
142881 if (pts_buf[j] < pts_buf[r]) {
4438 4358 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4439 4358 ++num_swaps;
4440 } else {
4441 138523 break;
4442 }
4443 4358 j = r;
4444 }
4445 138527 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4446
4447 138527 ctts_sample++;
4448
1/2
✓ Branch 0 taken 138527 times.
✗ Branch 1 not taken.
138527 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4449 138527 ctts_ind++;
4450 138527 ctts_sample = 0;
4451 }
4452 }
4453 52 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4454 52 st->codecpar->video_delay, st->index);
4455 }
4456 757 }
4457
4458 120932 static void mov_current_sample_inc(MOVStreamContext *sc)
4459 {
4460 120932 sc->current_sample++;
4461 120932 sc->current_index++;
4462
2/2
✓ Branch 0 taken 72059 times.
✓ Branch 1 taken 48873 times.
120932 if (sc->index_ranges &&
4463
2/2
✓ Branch 0 taken 501 times.
✓ Branch 1 taken 71558 times.
72059 sc->current_index >= sc->current_index_range->end &&
4464
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 sc->current_index_range->end) {
4465 501 sc->current_index_range++;
4466 501 sc->current_index = sc->current_index_range->start;
4467 }
4468 120932 }
4469
4470 ✗ static void mov_current_sample_dec(MOVStreamContext *sc)
4471 {
4472 ✗ sc->current_sample--;
4473 ✗ sc->current_index--;
4474 ✗ if (sc->index_ranges &&
4475 ✗ sc->current_index < sc->current_index_range->start &&
4476 ✗ sc->current_index_range > sc->index_ranges) {
4477 ✗ sc->current_index_range--;
4478 ✗ sc->current_index = sc->current_index_range->end - 1;
4479 }
4480 ✗ }
4481
4482 339 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4483 {
4484 int64_t range_size;
4485
4486 339 sc->current_sample = current_sample;
4487 339 sc->current_index = current_sample;
4488
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 311 times.
339 if (!sc->index_ranges) {
4489 28 return;
4490 }
4491
4492 311 for (sc->current_index_range = sc->index_ranges;
4493
1/2
✓ Branch 0 taken 311 times.
✗ Branch 1 not taken.
311 sc->current_index_range->end;
4494 ✗ sc->current_index_range++) {
4495 311 range_size = sc->current_index_range->end - sc->current_index_range->start;
4496
1/2
✓ Branch 0 taken 311 times.
✗ Branch 1 not taken.
311 if (range_size > current_sample) {
4497 311 sc->current_index = sc->current_index_range->start + current_sample;
4498 311 break;
4499 }
4500 ✗ current_sample -= range_size;
4501 }
4502 }
4503
4504 /**
4505 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4506 * which are needed to decode them) that fall in the edit list time ranges.
4507 * Also fixes the timestamps of the index entries to match the timeline
4508 * specified the edit lists.
4509 */
4510 757 static void mov_fix_index(MOVContext *mov, AVStream *st)
4511 {
4512 757 MOVStreamContext *msc = st->priv_data;
4513 757 FFStream *const sti = ffstream(st);
4514 757 AVIndexEntry *e_old = sti->index_entries;
4515 757 int nb_old = sti->nb_index_entries;
4516 757 const AVIndexEntry *e_old_end = e_old + nb_old;
4517 757 const AVIndexEntry *current = NULL;
4518 757 MOVTimeToSample *tts_data_old = msc->tts_data;
4519 757 int64_t tts_index_old = 0;
4520 757 int64_t tts_sample_old = 0;
4521 757 int64_t tts_count_old = msc->tts_count;
4522 757 int64_t edit_list_media_time = 0;
4523 757 int64_t edit_list_duration = 0;
4524 757 int64_t frame_duration = 0;
4525 757 int64_t edit_list_dts_counter = 0;
4526 757 int64_t edit_list_dts_entry_end = 0;
4527 757 int64_t edit_list_start_tts_sample = 0;
4528 int64_t curr_cts;
4529 757 int64_t curr_ctts = 0;
4530 757 int64_t empty_edits_sum_duration = 0;
4531 757 int64_t edit_list_index = 0;
4532 int64_t index;
4533 int flags;
4534 757 int64_t start_dts = 0;
4535 757 int64_t edit_list_start_encountered = 0;
4536 757 int64_t search_timestamp = 0;
4537 757 int64_t* frame_duration_buffer = NULL;
4538 757 int num_discarded_begin = 0;
4539 757 int first_non_zero_audio_edit = -1;
4540 757 int packet_skip_samples = 0;
4541 757 MOVIndexRange *current_index_range = NULL;
4542 757 int found_keyframe_after_edit = 0;
4543 757 int found_non_empty_edit = 0;
4544
4545
4/6
✓ Branch 0 taken 546 times.
✓ Branch 1 taken 211 times.
✓ Branch 2 taken 546 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 546 times.
757 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
4546 211 return;
4547 }
4548
4549 546 int64_t max_entries = nb_old * 16LL + (1 << 16);
4550
4551 // allocate the index ranges array
4552 546 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4553 sizeof(msc->index_ranges[0]));
4554
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 546 times.
546 if (!msc->index_ranges) {
4555 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4556 ✗ return;
4557 }
4558 546 msc->current_index_range = msc->index_ranges;
4559
4560 // Clean AVStream from traces of old index
4561 546 sti->index_entries = NULL;
4562 546 sti->index_entries_allocated_size = 0;
4563 546 sti->nb_index_entries = 0;
4564
4565 // Clean time to sample fields of MOVStreamContext
4566 546 msc->tts_data = NULL;
4567 546 msc->tts_count = 0;
4568 546 msc->tts_index = 0;
4569 546 msc->tts_sample = 0;
4570 546 msc->tts_allocated_size = 0;
4571
4572 // Reinitialize min_corrected_pts so that it can be computed again.
4573 546 msc->min_corrected_pts = -1;
4574
4575 // If the dts_shift is positive (in case of negative ctts values in mov),
4576 // then negate the DTS by dts_shift
4577
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 537 times.
546 if (msc->dts_shift > 0) {
4578 9 edit_list_dts_entry_end -= msc->dts_shift;
4579 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4580 }
4581
4582 546 start_dts = edit_list_dts_entry_end;
4583
4584
2/2
✓ Branch 0 taken 575 times.
✓ Branch 1 taken 546 times.
1667 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
4585 1121 &edit_list_duration, mov->time_scale)) {
4586 575 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4587 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4588 575 edit_list_index++;
4589 575 edit_list_dts_counter = edit_list_dts_entry_end;
4590 575 edit_list_dts_entry_end = av_sat_add64(edit_list_dts_entry_end, edit_list_duration);
4591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 if (edit_list_dts_entry_end == INT64_MAX) {
4592 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot calculate dts entry length with duration %"PRId64"\n",
4593 edit_list_duration);
4594 ✗ break;
4595 }
4596 575 num_discarded_begin = 0;
4597
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 571 times.
575 if (edit_list_media_time == -1) {
4598
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!found_non_empty_edit)
4599 4 empty_edits_sum_duration += edit_list_duration;
4600 4 continue;
4601 }
4602 571 found_non_empty_edit = 1;
4603
4604 // If we encounter a non-negative edit list reset the skip_samples/initial_padding fields and set them
4605 // according to the edit list below.
4606
2/2
✓ Branch 0 taken 167 times.
✓ Branch 1 taken 404 times.
571 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4607
1/2
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
167 if (first_non_zero_audio_edit < 0) {
4608 167 first_non_zero_audio_edit = 1;
4609 } else {
4610 ✗ first_non_zero_audio_edit = 0;
4611 }
4612
4613
1/2
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
167 if (first_non_zero_audio_edit > 0)
4614 167 sti->skip_samples = st->codecpar->initial_padding = 0;
4615 }
4616
4617 // While reordering frame index according to edit list we must handle properly
4618 // the scenario when edit list entry starts from none key frame.
4619 // We find closest previous key frame and preserve it and consequent frames in index.
4620 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4621 571 search_timestamp = edit_list_media_time;
4622
2/2
✓ Branch 0 taken 167 times.
✓ Branch 1 taken 404 times.
571 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4623 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4624 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4625 // edit_list_media_time to cover the decoder delay.
4626
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 166 times.
167 search_timestamp = FFMAX(av_sat_sub64(search_timestamp, msc->time_scale), e_old[0].timestamp);
4627 }
4628
4629
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 567 times.
571 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, 0,
4630 &index, &tts_index_old, &tts_sample_old) < 0) {
4631 4 av_log(mov->fc, AV_LOG_WARNING,
4632 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4633 st->index, edit_list_index, search_timestamp);
4634
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, AVSEEK_FLAG_ANY,
4635 &index, &tts_index_old, &tts_sample_old) < 0) {
4636 4 av_log(mov->fc, AV_LOG_WARNING,
4637 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4638 st->index, edit_list_index, search_timestamp);
4639 4 index = 0;
4640 4 tts_index_old = 0;
4641 4 tts_sample_old = 0;
4642 }
4643 }
4644 571 current = e_old + index;
4645 571 edit_list_start_tts_sample = tts_sample_old;
4646
4647 // Iterate over index and arrange it according to edit list
4648 571 edit_list_start_encountered = 0;
4649 571 found_keyframe_after_edit = 0;
4650
2/2
✓ Branch 0 taken 362304 times.
✓ Branch 1 taken 145 times.
362449 for (; current < e_old_end; current++, index++) {
4651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 362304 times.
362304 if (sti->nb_index_entries >= max_entries) {
4652 ✗ av_log(mov->fc, AV_LOG_ERROR, "Edit list expands the sample index beyond %"PRId64" entries\n",
4653 max_entries);
4654 ✗ goto truncated;
4655 }
4656 // check if frame outside edit list mark it for discard
4657 724608 frame_duration = (current + 1 < e_old_end) ?
4658
2/2
✓ Branch 0 taken 361766 times.
✓ Branch 1 taken 538 times.
362304 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4659
4660 362304 flags = current->flags;
4661
4662 // frames (pts) before or after edit list
4663 362304 curr_cts = current->timestamp + msc->dts_shift;
4664 362304 curr_ctts = 0;
4665
4666
4/4
✓ Branch 0 taken 197068 times.
✓ Branch 1 taken 165236 times.
✓ Branch 2 taken 197056 times.
✓ Branch 3 taken 12 times.
362304 if (tts_data_old && tts_index_old < tts_count_old) {
4667 197056 curr_ctts = tts_data_old[tts_index_old].offset;
4668 197056 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4669 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4670 197056 curr_cts += curr_ctts;
4671 197056 tts_sample_old++;
4672
1/2
✓ Branch 0 taken 197056 times.
✗ Branch 1 not taken.
197056 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197056 times.
197056 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4674 &msc->tts_allocated_size,
4675 197056 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4676 197056 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4677 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4678 tts_index_old,
4679 ✗ tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4680 ✗ tts_data_old[tts_index_old].offset);
4681 ✗ break;
4682 }
4683 197056 tts_index_old++;
4684 197056 tts_sample_old = 0;
4685 197056 edit_list_start_tts_sample = 0;
4686 }
4687 }
4688
4689
4/4
✓ Branch 0 taken 362079 times.
✓ Branch 1 taken 225 times.
✓ Branch 2 taken 158 times.
✓ Branch 3 taken 361921 times.
362304 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
4690
4/4
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 259 times.
✓ Branch 2 taken 80 times.
✓ Branch 3 taken 44 times.
383 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
4691
4/6
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 55 times.
✓ Branch 4 taken 25 times.
✗ Branch 5 not taken.
80 curr_cts < edit_list_media_time && curr_cts + frame_duration > edit_list_media_time &&
4692 first_non_zero_audio_edit > 0) {
4693 25 packet_skip_samples = edit_list_media_time - curr_cts;
4694 25 sti->skip_samples += packet_skip_samples;
4695
4696 // Shift the index entry timestamp by packet_skip_samples to be correct.
4697 25 edit_list_dts_counter -= packet_skip_samples;
4698
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 if (edit_list_start_encountered == 0) {
4699 25 edit_list_start_encountered = 1;
4700 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4701 // discarded packets.
4702
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 10 times.
25 if (frame_duration_buffer) {
4703 15 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4704 frame_duration_buffer, num_discarded_begin);
4705 15 av_freep(&frame_duration_buffer);
4706 }
4707 }
4708
4709 25 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4710 } else {
4711 358 flags |= AVINDEX_DISCARD_FRAME;
4712 358 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4713
4714
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 160 times.
358 if (edit_list_start_encountered == 0) {
4715 198 num_discarded_begin++;
4716
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 198 times.
198 if (av_reallocp_array(&frame_duration_buffer, num_discarded_begin,
4717 sizeof(*frame_duration_buffer)) < 0) {
4718 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4719 ✗ break;
4720 }
4721 198 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4722
4723 // Increment skip_samples for the first non-zero audio edit list
4724
3/4
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 99 times.
✗ Branch 3 not taken.
198 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4725
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 44 times.
99 first_non_zero_audio_edit > 0 && st->codecpar->codec_id != AV_CODEC_ID_VORBIS) {
4726 55 sti->skip_samples += frame_duration;
4727 }
4728 }
4729 }
4730 } else {
4731
2/2
✓ Branch 0 taken 545 times.
✓ Branch 1 taken 361376 times.
361921 if (msc->min_corrected_pts < 0) {
4732 545 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4733 } else {
4734 361376 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4735 }
4736
2/2
✓ Branch 0 taken 544 times.
✓ Branch 1 taken 361377 times.
361921 if (edit_list_start_encountered == 0) {
4737 544 edit_list_start_encountered = 1;
4738 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4739 // discarded packets.
4740
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 508 times.
544 if (frame_duration_buffer) {
4741 36 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4742 frame_duration_buffer, num_discarded_begin);
4743 36 av_freep(&frame_duration_buffer);
4744 }
4745 }
4746 }
4747
4748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 362304 times.
362304 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
4749 362304 current->min_distance, flags) == -1) {
4750 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4751 ✗ break;
4752 }
4753
4754 // Update the index ranges array
4755
4/4
✓ Branch 0 taken 361758 times.
✓ Branch 1 taken 546 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 361735 times.
362304 if (!current_index_range || index != current_index_range->end) {
4756 569 current_index_range = current_index_range ? current_index_range + 1
4757
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 546 times.
569 : msc->index_ranges;
4758 569 current_index_range->start = index;
4759 }
4760 362304 current_index_range->end = index + 1;
4761
4762 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4763
2/2
✓ Branch 0 taken 362106 times.
✓ Branch 1 taken 198 times.
362304 if (edit_list_start_encountered > 0) {
4764 362106 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4765 }
4766
4767 // Break when found first key frame after edit entry completion
4768
2/2
✓ Branch 0 taken 767 times.
✓ Branch 1 taken 361537 times.
362304 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
4769
4/4
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 445 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 319 times.
767 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
4770
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 415 times.
448 if (msc->ctts_count) {
4771 // If we have CTTS and this is the first keyframe after edit elist,
4772 // wait for one more, because there might be trailing B-frames after this I-frame
4773 // that do belong to the edit.
4774
3/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 11 times.
33 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO && found_keyframe_after_edit == 0) {
4775 22 found_keyframe_after_edit = 1;
4776 22 continue;
4777 }
4778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (tts_sample_old != 0) {
4779 ✗ if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4780 &msc->tts_allocated_size,
4781 ✗ tts_sample_old - edit_list_start_tts_sample,
4782 ✗ tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4783 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4784 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4785 ✗ tts_data_old[tts_index_old].offset);
4786 ✗ break;
4787 }
4788 }
4789 }
4790 426 break;
4791 }
4792 }
4793 }
4794 546 truncated:
4795 // If there are empty edits, then msc->min_corrected_pts might be positive
4796 // intentionally. So we subtract the sum duration of empty edits here.
4797 546 msc->min_corrected_pts -= empty_edits_sum_duration;
4798
4799 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4800 // dts by that amount to make the first pts zero.
4801
2/2
✓ Branch 0 taken 328 times.
✓ Branch 1 taken 218 times.
546 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4802
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 266 times.
328 if (msc->min_corrected_pts > 0) {
4803 62 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4804
2/2
✓ Branch 0 taken 3322 times.
✓ Branch 1 taken 62 times.
3384 for (int i = 0; i < sti->nb_index_entries; ++i)
4805 3322 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4806 }
4807 }
4808 // Start time should be equal to zero or the duration of any empty edits.
4809 546 st->start_time = empty_edits_sum_duration;
4810
4811 // Update av stream length, if it ends up shorter than the track's media duration
4812 546 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4813 546 st->codecpar->initial_padding = sti->skip_samples;
4814
4815 // Free the old index and the old CTTS structures
4816 546 av_free(e_old);
4817 546 av_free(tts_data_old);
4818 546 av_freep(&frame_duration_buffer);
4819
4820 // Null terminate the index ranges array
4821 546 current_index_range = current_index_range ? current_index_range + 1
4822
1/2
✓ Branch 0 taken 546 times.
✗ Branch 1 not taken.
546 : msc->index_ranges;
4823 546 current_index_range->start = 0;
4824 546 current_index_range->end = 0;
4825 546 msc->current_index = msc->index_ranges[0].start;
4826 }
4827
4828 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4829 {
4830
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4831
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == nal_unit_type)
4832 5 return i + 1;
4833 ✗ return 0;
4834 }
4835
4836 891 static int build_open_gop_key_points(AVStream *st)
4837 {
4838 int k;
4839 891 int sample_id = 0;
4840 uint32_t cra_index;
4841 891 MOVStreamContext *sc = st->priv_data;
4842
4843
4/4
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 812 times.
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 5 times.
891 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count)
4844 886 return 0;
4845
4846 /* Build an unrolled index of the samples */
4847 5 sc->sample_offsets_count = 0;
4848
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4849
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4850 ✗ return AVERROR(ENOMEM);
4851 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4852 }
4853 5 av_freep(&sc->sample_offsets);
4854 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4856 ✗ return AVERROR(ENOMEM);
4857 5 k = 0;
4858
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4859
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4860 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4861
4862 /* The following HEVC NAL type reveal the use of open GOP sync points
4863 * (TODO: BLA types may also be concerned) */
4864 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4866 ✗ return 0;
4867
4868 /* Build a list of open-GOP key samples */
4869 5 sc->open_key_samples_count = 0;
4870
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4871
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (sc->sync_group[i].count > INT_MAX - sc->open_key_samples_count)
4873 ✗ return AVERROR(ENOMEM);
4874 11 sc->open_key_samples_count += sc->sync_group[i].count;
4875 }
4876 5 av_freep(&sc->open_key_samples);
4877 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4879 ✗ return AVERROR(ENOMEM);
4880 5 k = 0;
4881
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4882 28 const MOVSbgp *sg = &sc->sync_group[i];
4883
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4884
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4885 11 sc->open_key_samples[k++] = sample_id;
4886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4887 ✗ return AVERROR_PATCHWELCOME;
4888 28 sample_id += sg->count;
4889 }
4890
4891 /* Identify the minimal time step between samples */
4892 5 sc->min_sample_duration = UINT_MAX;
4893
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4894 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4895
4896 5 return 0;
4897 }
4898
4899 #define MOV_MERGE_CTTS 1
4900 #define MOV_MERGE_STTS 2
4901 /*
4902 * Merge stts and ctts arrays into a new combined array.
4903 * stts_count and ctts_count may be left untouched as they will be
4904 * used to check for the presence of either of them.
4905 */
4906 757 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4907 {
4908 757 MOVStreamContext *sc = st->priv_data;
4909
3/4
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 677 times.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
757 int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS);
4910
3/4
✓ Branch 0 taken 757 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 686 times.
✓ Branch 3 taken 71 times.
757 int stts = sc->stts_data && (flags & MOV_MERGE_STTS);
4911 757 int idx = 0;
4912
4913
3/4
✓ Branch 0 taken 677 times.
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 677 times.
757 if (!sc->ctts_data && !sc->stts_data)
4914 ✗ return 0;
4915 // Expand time to sample entries such that we have a 1-1 mapping with samples
4916
2/4
✓ Branch 0 taken 757 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 757 times.
757 if (!sc->sample_count || sc->sample_count >= UINT_MAX / sizeof(*sc->tts_data))
4917 ✗ return -1;
4918
4919
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 677 times.
757 if (ctts) {
4920 160 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4921 80 sc->sample_count * sizeof(*sc->tts_data));
4922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!sc->tts_data)
4923 ✗ return -1;
4924
4925 80 memset(sc->tts_data, 0, sc->tts_allocated_size);
4926
4927
2/2
✓ Branch 0 taken 5266 times.
✓ Branch 1 taken 80 times.
5346 for (int i = 0; i < sc->ctts_count &&
4928
1/2
✓ Branch 0 taken 5266 times.
✗ Branch 1 not taken.
10532 idx < sc->sample_count; i++)
4929
2/2
✓ Branch 0 taken 139484 times.
✓ Branch 1 taken 5266 times.
144750 for (int j = 0; j < sc->ctts_data[i].count &&
4930
1/2
✓ Branch 0 taken 139484 times.
✗ Branch 1 not taken.
139484 idx < sc->sample_count; j++) {
4931 139484 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4932 139484 sc->tts_data[idx++].count = 1;
4933 }
4934
4935 80 sc->tts_count = idx;
4936 } else
4937 677 sc->ctts_count = 0;
4938 757 av_freep(&sc->ctts_data);
4939 757 sc->ctts_allocated_size = 0;
4940
4941 757 idx = 0;
4942
2/2
✓ Branch 0 taken 686 times.
✓ Branch 1 taken 71 times.
757 if (stts) {
4943 686 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4944 686 sc->sample_count * sizeof(*sc->tts_data));
4945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 686 times.
686 if (!tts_data)
4946 ✗ return -1;
4947
4948
2/2
✓ Branch 0 taken 606 times.
✓ Branch 1 taken 80 times.
686 if (!sc->tts_data)
4949 606 memset(tts_data, 0, sc->tts_allocated_size);
4950 686 sc->tts_data = tts_data;
4951
4952
2/2
✓ Branch 0 taken 3109 times.
✓ Branch 1 taken 686 times.
3795 for (int i = 0; i < sc->stts_count &&
4953
1/2
✓ Branch 0 taken 3109 times.
✗ Branch 1 not taken.
6218 idx < sc->sample_count; i++)
4954
2/2
✓ Branch 0 taken 250107 times.
✓ Branch 1 taken 3109 times.
253216 for (int j = 0; j < sc->stts_data[i].count &&
4955
1/2
✓ Branch 0 taken 250107 times.
✗ Branch 1 not taken.
250107 idx < sc->sample_count; j++) {
4956 250107 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4957 250107 sc->tts_data[idx++].count = 1;
4958 }
4959
4960 686 sc->tts_count = FFMAX(sc->tts_count, idx);
4961 } else
4962 71 sc->stts_count = 0;
4963 757 av_freep(&sc->stts_data);
4964 757 sc->stts_allocated_size = 0;
4965
4966 757 return 0;
4967 }
4968
4969 891 static void mov_build_index(MOVContext *mov, AVStream *st)
4970 {
4971 891 MOVStreamContext *sc = st->priv_data;
4972 891 FFStream *const sti = ffstream(st);
4973 int64_t current_offset;
4974 891 int64_t current_dts = 0;
4975 891 unsigned int stts_index = 0;
4976 891 unsigned int stsc_index = 0;
4977 891 unsigned int stss_index = 0;
4978 891 unsigned int stps_index = 0;
4979 unsigned int i, j;
4980 891 uint64_t stream_size = 0;
4981
4982 891 int ret = build_open_gop_key_points(st);
4983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 891 times.
891 if (ret < 0)
4984 ✗ return;
4985
4986
2/2
✓ Branch 0 taken 649 times.
✓ Branch 1 taken 242 times.
891 if (sc->elst_count) {
4987 649 int i, edit_start_index = 0, multiple_edits = 0;
4988 649 int64_t empty_duration = 0; // empty duration of the first edit list entry
4989 649 int64_t start_time = 0; // start time of the media
4990
4991
2/2
✓ Branch 0 taken 678 times.
✓ Branch 1 taken 649 times.
1327 for (i = 0; i < sc->elst_count; i++) {
4992 678 const MOVElst *e = &sc->elst_data[i];
4993
4/4
✓ Branch 0 taken 649 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 645 times.
678 if (i == 0 && e->time == -1) {
4994 /* if empty, the first entry is the start time of the stream
4995 * relative to the presentation itself */
4996 4 empty_duration = e->duration;
4997 4 edit_start_index = 1;
4998
3/4
✓ Branch 0 taken 649 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 649 times.
✗ Branch 3 not taken.
674 } else if (i == edit_start_index && e->time >= 0) {
4999 649 start_time = e->time;
5000 } else {
5001 25 multiple_edits = 1;
5002 }
5003 }
5004
5005
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 642 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
649 if (multiple_edits && !mov->advanced_editlist) {
5006 ✗ if (mov->advanced_editlist_autodisabled)
5007 ✗ av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
5008 "not supported in fragmented MP4 files\n");
5009 else
5010 ✗ av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
5011 "Use -advanced_editlist to correctly decode otherwise "
5012 "a/v desync might occur\n");
5013 }
5014
5015 /* adjust first dts according to edit list */
5016
5/6
✓ Branch 0 taken 645 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 119 times.
✓ Branch 3 taken 526 times.
✓ Branch 4 taken 123 times.
✗ Branch 5 not taken.
649 if ((empty_duration || start_time) && mov->time_scale > 0) {
5017
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 119 times.
123 if (empty_duration)
5018 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
5019
5020
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 123 times.
123 if (av_sat_sub64(start_time, empty_duration) != start_time - (uint64_t)empty_duration)
5021 ✗ av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
5022
5023 123 sc->time_offset = start_time - (uint64_t)empty_duration;
5024 123 sc->min_corrected_pts = start_time;
5025
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 122 times.
123 if (!mov->advanced_editlist)
5026 1 current_dts = -av_clip64(sc->time_offset, -INT64_MAX, INT64_MAX);
5027 }
5028
5029
4/4
✓ Branch 0 taken 642 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 103 times.
✓ Branch 3 taken 539 times.
649 if (!multiple_edits && !mov->advanced_editlist &&
5030
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 102 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
103 st->codecpar->codec_id == AV_CODEC_ID_AAC && start_time > 0)
5031 ✗ st->codecpar->initial_padding = av_rescale_q(start_time, st->time_base,
5032 ✗ (AVRational){1, st->codecpar->sample_rate});
5033 }
5034
5035 /* only use old uncompressed audio chunk demuxing when stts specifies it */
5036
2/2
✓ Branch 0 taken 397 times.
✓ Branch 1 taken 494 times.
891 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
5037
5/6
✓ Branch 0 taken 245 times.
✓ Branch 1 taken 152 times.
✓ Branch 2 taken 245 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 174 times.
✓ Branch 5 taken 71 times.
1083 sc->stts_count == 1 && sc->stts_data && sc->stts_data[0].duration == 1)) {
5038 820 unsigned int current_sample = 0;
5039 820 unsigned int stts_sample = 0;
5040 unsigned int sample_size;
5041 820 unsigned int distance = 0;
5042 820 unsigned int rap_group_index = 0;
5043 820 unsigned int rap_group_sample = 0;
5044
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 819 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
820 int rap_group_present = sc->rap_group_count && sc->rap_group;
5045
4/8
✓ Branch 0 taken 171 times.
✓ Branch 1 taken 649 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 171 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 649 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
820 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
5046
5047
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 820 times.
820 av_assert0(sc->dts_shift >= 0);
5048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 820 times.
820 if (current_dts < INT64_MIN + sc->dts_shift)
5049 ✗ return;
5050 820 current_dts -= sc->dts_shift;
5051
4/6
✓ Branch 0 taken 686 times.
✓ Branch 1 taken 134 times.
✓ Branch 2 taken 686 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 686 times.
820 if (!sc->sample_count || sti->nb_index_entries || sc->tts_count)
5052 134 return;
5053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 686 times.
686 if (sc->sample_count >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
5054 ✗ return;
5055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 686 times.
686 if (av_reallocp_array(&sti->index_entries,
5056 686 sti->nb_index_entries + sc->sample_count,
5057 sizeof(*sti->index_entries)) < 0) {
5058 ✗ sti->nb_index_entries = 0;
5059 ✗ return;
5060 }
5061 686 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
5062
5063 686 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
5064
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 686 times.
686 if (ret < 0)
5065 ✗ return;
5066
5067
2/2
✓ Branch 0 taken 174782 times.
✓ Branch 1 taken 686 times.
175468 for (i = 0; i < sc->chunk_count; i++) {
5068
2/2
✓ Branch 0 taken 174096 times.
✓ Branch 1 taken 686 times.
174782 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
5069 174782 current_offset = sc->chunk_offsets[i];
5070
2/2
✓ Branch 1 taken 8723 times.
✓ Branch 2 taken 168615 times.
177338 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
5071
2/2
✓ Branch 0 taken 2556 times.
✓ Branch 1 taken 6167 times.
8723 i + 1 == sc->stsc_data[stsc_index + 1].first)
5072 2556 stsc_index++;
5073
5074
4/6
✓ Branch 0 taken 174782 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7432 times.
✓ Branch 3 taken 167350 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7432 times.
174782 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
5075 ✗ sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
5076 ✗ av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
5077 ✗ sc->stsz_sample_size = sc->sample_size;
5078 }
5079
3/4
✓ Branch 0 taken 7432 times.
✓ Branch 1 taken 167350 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7432 times.
174782 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
5080 ✗ av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
5081 ✗ sc->stsz_sample_size = sc->sample_size;
5082 }
5083
5084
2/2
✓ Branch 0 taken 250107 times.
✓ Branch 1 taken 174782 times.
424889 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
5085 250107 int keyframe = 0;
5086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 250107 times.
250107 if (current_sample >= sc->sample_count) {
5087 ✗ av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
5088 ✗ return;
5089 }
5090
5091
6/6
✓ Branch 0 taken 240396 times.
✓ Branch 1 taken 9711 times.
✓ Branch 2 taken 153411 times.
✓ Branch 3 taken 86985 times.
✓ Branch 4 taken 5772 times.
✓ Branch 5 taken 147639 times.
250107 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
5092 92757 keyframe = 1;
5093
2/2
✓ Branch 0 taken 5601 times.
✓ Branch 1 taken 87156 times.
92757 if (stss_index + 1 < sc->keyframe_count)
5094 5601 stss_index++;
5095
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 157350 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
157350 } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
5096 ✗ keyframe = 1;
5097 ✗ if (stps_index + 1 < sc->stps_count)
5098 ✗ stps_index++;
5099 }
5100
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 249919 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
250107 if (rap_group_present && rap_group_index < sc->rap_group_count) {
5101
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
5102 2 keyframe = 1;
5103
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
5104 4 rap_group_sample = 0;
5105 4 rap_group_index++;
5106 }
5107 }
5108
2/2
✓ Branch 0 taken 9711 times.
✓ Branch 1 taken 240396 times.
250107 if (sc->keyframe_absent
5109
1/2
✓ Branch 0 taken 9711 times.
✗ Branch 1 not taken.
9711 && !sc->stps_count
5110
1/2
✓ Branch 0 taken 9711 times.
✗ Branch 1 not taken.
9711 && !rap_group_present
5111
6/6
✓ Branch 0 taken 874 times.
✓ Branch 1 taken 8837 times.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 824 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 48 times.
9711 && (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || (i==0 && j==0)))
5112 8839 keyframe = 1;
5113
2/2
✓ Branch 0 taken 101596 times.
✓ Branch 1 taken 148511 times.
250107 if (keyframe)
5114 101596 distance = 0;
5115
2/2
✓ Branch 0 taken 9333 times.
✓ Branch 1 taken 240774 times.
250107 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
5116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 250107 times.
250107 if (current_offset > INT64_MAX - sample_size) {
5117 ✗ av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
5118 current_offset,
5119 sample_size);
5120 ✗ return;
5121 }
5122
5123
2/2
✓ Branch 0 taken 250010 times.
✓ Branch 1 taken 97 times.
250107 if (sc->pseudo_stream_id == -1 ||
5124
2/2
✓ Branch 0 taken 250008 times.
✓ Branch 1 taken 2 times.
250010 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
5125 AVIndexEntry *e;
5126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 250105 times.
250105 if (sample_size > 0x3FFFFFFF) {
5127 ✗ av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
5128 ✗ return;
5129 }
5130 250105 e = &sti->index_entries[sti->nb_index_entries++];
5131 250105 e->pos = current_offset;
5132 250105 e->timestamp = current_dts;
5133 250105 e->size = sample_size;
5134 250105 e->min_distance = distance;
5135 250105 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
5136 250105 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
5137 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
5138 current_offset, current_dts, sample_size, distance, keyframe);
5139
4/4
✓ Branch 0 taken 156342 times.
✓ Branch 1 taken 93763 times.
✓ Branch 2 taken 11709 times.
✓ Branch 3 taken 144633 times.
250105 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries < 100)
5140 11709 ff_rfps_add_frame(mov->fc, st, current_dts);
5141 }
5142
5143 250107 current_offset += sample_size;
5144 250107 stream_size += sample_size;
5145
5146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 250107 times.
250107 if (current_dts > INT64_MAX - sc->tts_data[stts_index].duration)
5147 ✗ return;
5148 250107 current_dts += sc->tts_data[stts_index].duration;
5149
5150 250107 distance++;
5151 250107 stts_sample++;
5152 250107 current_sample++;
5153
3/4
✓ Branch 0 taken 249421 times.
✓ Branch 1 taken 686 times.
✓ Branch 2 taken 249421 times.
✗ Branch 3 not taken.
250107 if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) {
5154 249421 stts_sample = 0;
5155 249421 stts_index++;
5156 }
5157 }
5158 }
5159
2/2
✓ Branch 0 taken 633 times.
✓ Branch 1 taken 53 times.
686 if (st->duration > 0)
5160 633 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
5161 } else {
5162 71 unsigned chunk_samples, total = 0;
5163
5164
2/4
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 71 times.
71 if (!sc->chunk_count || sc->tts_count)
5165 ✗ return;
5166
5167 // compute total chunk count
5168
2/2
✓ Branch 0 taken 742 times.
✓ Branch 1 taken 71 times.
813 for (i = 0; i < sc->stsc_count; i++) {
5169 unsigned count, chunk_count;
5170
5171 742 chunk_samples = sc->stsc_data[i].count;
5172
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 71 times.
742 if (i != sc->stsc_count - 1 &&
5173
3/4
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 77 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 594 times.
671 sc->samples_per_frame && chunk_samples % sc->samples_per_frame) {
5174 ✗ av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
5175 ✗ return;
5176 }
5177
5178
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 667 times.
742 if (sc->samples_per_frame >= 160) { // gsm
5179 75 count = chunk_samples / sc->samples_per_frame;
5180
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 136 times.
667 } else if (sc->samples_per_frame > 1) {
5181 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
5182 531 count = (chunk_samples+samples-1) / samples;
5183 } else {
5184 136 count = (chunk_samples+1023) / 1024;
5185 }
5186
5187
2/2
✓ Branch 1 taken 671 times.
✓ Branch 2 taken 71 times.
742 if (mov_stsc_index_valid(i, sc->stsc_count))
5188 671 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
5189 else
5190 71 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
5191 742 total += chunk_count * count;
5192 }
5193
5194 71 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
5195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
5196 ✗ return;
5197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (av_reallocp_array(&sti->index_entries,
5198 71 sti->nb_index_entries + total,
5199 sizeof(*sti->index_entries)) < 0) {
5200 ✗ sti->nb_index_entries = 0;
5201 ✗ return;
5202 }
5203 71 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
5204
5205 // populate index
5206
2/2
✓ Branch 0 taken 5563 times.
✓ Branch 1 taken 71 times.
5634 for (i = 0; i < sc->chunk_count; i++) {
5207 5563 current_offset = sc->chunk_offsets[i];
5208
2/2
✓ Branch 1 taken 5399 times.
✓ Branch 2 taken 164 times.
5563 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
5209
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 4728 times.
5399 i + 1 == sc->stsc_data[stsc_index + 1].first)
5210 671 stsc_index++;
5211 5563 chunk_samples = sc->stsc_data[stsc_index].count;
5212
5213
2/2
✓ Branch 0 taken 165283 times.
✓ Branch 1 taken 5563 times.
170846 while (chunk_samples > 0) {
5214 AVIndexEntry *e;
5215 unsigned size, samples;
5216
5217
3/4
✓ Branch 0 taken 23921 times.
✓ Branch 1 taken 141362 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 23921 times.
165283 if (sc->samples_per_frame > 1 && !sc->bytes_per_frame) {
5218 ✗ avpriv_request_sample(mov->fc,
5219 "Zero bytes per frame, but %d samples per frame",
5220 sc->samples_per_frame);
5221 ✗ return;
5222 }
5223
5224
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 150925 times.
165283 if (sc->samples_per_frame >= 160) { // gsm
5225 14358 samples = sc->samples_per_frame;
5226 14358 size = sc->bytes_per_frame;
5227 } else {
5228
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 141362 times.
150925 if (sc->samples_per_frame > 1) {
5229 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
5230 sc->samples_per_frame, chunk_samples);
5231 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
5232 } else {
5233 141362 samples = FFMIN(1024, chunk_samples);
5234 141362 size = samples * sc->sample_size;
5235 }
5236 }
5237
5238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165283 times.
165283 if (sti->nb_index_entries >= total) {
5239 ✗ av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
5240 ✗ return;
5241 }
5242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165283 times.
165283 if (size > 0x3FFFFFFF) {
5243 ✗ av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
5244 ✗ return;
5245 }
5246 165283 e = &sti->index_entries[sti->nb_index_entries++];
5247 165283 e->pos = current_offset;
5248 165283 e->timestamp = current_dts;
5249 165283 e->size = size;
5250 165283 e->min_distance = 0;
5251 165283 e->flags = AVINDEX_KEYFRAME;
5252 165283 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
5253 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
5254 size, samples);
5255
5256 165283 current_offset += size;
5257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165283 times.
165283 if (current_dts > INT64_MAX - samples)
5258 ✗ return;
5259 165283 current_dts += samples;
5260 165283 chunk_samples -= samples;
5261 }
5262 }
5263
5264 71 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
5265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (ret < 0)
5266 ✗ return;
5267 }
5268
5269
2/4
✓ Branch 0 taken 757 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 757 times.
✗ Branch 3 not taken.
757 if (!mov->ignore_editlist && mov->advanced_editlist) {
5270 // Fix index according to edit lists.
5271 757 mov_fix_index(mov, st);
5272 }
5273
5274 // Update start time of the stream.
5275
5/6
✓ Branch 0 taken 211 times.
✓ Branch 1 taken 546 times.
✓ Branch 2 taken 81 times.
✓ Branch 3 taken 130 times.
✓ Branch 4 taken 81 times.
✗ Branch 5 not taken.
757 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) {
5276 81 st->start_time = av_sat_add64(sti->index_entries[0].timestamp, sc->dts_shift);
5277
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 if (sc->tts_data) {
5278 81 st->start_time = av_sat_add64(st->start_time, sc->tts_data[0].offset);
5279 }
5280 }
5281
5282 757 mov_estimate_video_delay(mov, st);
5283 }
5284
5285 typedef struct MOVPresentationSample {
5286 int index;
5287 int64_t pts;
5288 } MOVPresentationSample;
5289
5290 12202 static int mov_compare_presentation_samples(const void *a, const void *b)
5291 {
5292 12202 const MOVPresentationSample *sa = a;
5293 12202 const MOVPresentationSample *sb = b;
5294
5295
2/2
✓ Branch 0 taken 12198 times.
✓ Branch 1 taken 4 times.
12202 if (sa->pts != sb->pts)
5296 12198 return (sa->pts > sb->pts) - (sa->pts < sb->pts);
5297 4 return (sa->index > sb->index) - (sa->index < sb->index);
5298 }
5299
5300 /*
5301 * Set sample durations from adjacent presentation timestamps.
5302 */
5303 838 static void mov_update_sample_durations(MOVContext *mov, AVStream *st)
5304 {
5305 838 MOVStreamContext *sc = st->priv_data;
5306 838 FFStream *const sti = ffstream(st);
5307 838 MOVPresentationSample *samples = NULL;
5308 838 MOVTimeToSample *tts_data = NULL;
5309 838 unsigned int tts_index = 0, tts_sample = 0;
5310 838 int count = sti->nb_index_entries;
5311
5312 /* A single STTS entry describes a fixed sample delta. */
5313
2/2
✓ Branch 0 taken 375 times.
✓ Branch 1 taken 463 times.
838 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
5314
4/4
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 299 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 64 times.
375 !sc->ctts_count || sc->stts_count < 2 ||
5315
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 !sc->tts_data || count < 2 ||
5316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 count >= UINT_MAX / sizeof(*tts_data))
5317 826 return;
5318
5319 12 samples = av_malloc_array(count, sizeof(*samples));
5320 12 tts_data = av_malloc_array(count, sizeof(*tts_data));
5321
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (!samples || !tts_data)
5322 ✗ goto fail;
5323
5324
2/2
✓ Branch 0 taken 2654 times.
✓ Branch 1 taken 12 times.
2666 for (int i = 0; i < count; i++) {
5325 int64_t dts, offset;
5326
5327
2/4
✓ Branch 0 taken 2654 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2654 times.
2654 if (tts_index >= sc->tts_count || !sc->tts_data[tts_index].count)
5328 ✗ goto fail;
5329
5330 2654 tts_data[i] = sc->tts_data[tts_index];
5331 2654 tts_data[i].count = 1;
5332
5333 2654 dts = sti->index_entries[i].timestamp;
5334 2654 offset = (int64_t)sc->dts_shift + tts_data[i].offset;
5335
3/4
✓ Branch 0 taken 2654 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2613 times.
✓ Branch 3 taken 41 times.
2654 if (dts == AV_NOPTS_VALUE ||
5336
2/4
✓ Branch 0 taken 2613 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2654 times.
2654 (offset > 0 && dts > INT64_MAX - offset) ||
5337 ✗ (offset < 0 && dts < INT64_MIN - offset))
5338 ✗ goto fail;
5339
5340 2654 samples[i].index = i;
5341 2654 samples[i].pts = dts + offset;
5342
5343
1/2
✓ Branch 0 taken 2654 times.
✗ Branch 1 not taken.
2654 if (++tts_sample == sc->tts_data[tts_index].count) {
5344 2654 tts_index++;
5345 2654 tts_sample = 0;
5346 }
5347 }
5348
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (tts_index != sc->tts_count || tts_sample)
5349 ✗ goto fail;
5350
5351 12 qsort(samples, count, sizeof(*samples), mov_compare_presentation_samples);
5352
5353
2/2
✓ Branch 0 taken 2624 times.
✓ Branch 1 taken 10 times.
2634 for (int i = 0; i + 1 < count; i++) {
5354 uint64_t duration;
5355
5356
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2622 times.
2624 if (samples[i].pts >= samples[i + 1].pts)
5357 2 goto fail;
5358
5359 /*
5360 * In VFR streams with reordered frames, STTS deltas follow decode
5361 * order while AVPacket.duration follows presentation order. CTTS
5362 * may produce presentation intervals that cannot be obtained by
5363 * merely permuting the STTS deltas, so derive each known duration
5364 * from adjacent PTS.
5365 */
5366 2622 duration = (uint64_t)samples[i + 1].pts - samples[i].pts;
5367
2/4
✓ Branch 0 taken 2622 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2622 times.
2622 if (!duration || duration > UINT_MAX)
5368 ✗ goto fail;
5369
5370 2622 tts_data[samples[i].index].duration = (unsigned int)duration;
5371 }
5372
5373 10 av_log(mov->fc, AV_LOG_DEBUG,
5374 "Updated sample durations in presentation order for stream %d\n",
5375 st->index);
5376
5377 10 av_freep(&sc->tts_data);
5378 10 sc->tts_data = tts_data;
5379 10 sc->tts_count = count;
5380 10 sc->tts_allocated_size = count * sizeof(*tts_data);
5381 10 tts_data = NULL;
5382
5383 12 fail:
5384 12 av_free(samples);
5385 12 av_free(tts_data);
5386 }
5387
5388 ✗ static int test_same_origin(const char *src, const char *ref) {
5389 char src_proto[64];
5390 char ref_proto[64];
5391 char src_auth[256];
5392 char ref_auth[256];
5393 char src_host[256];
5394 char ref_host[256];
5395 ✗ int src_port=-1;
5396 ✗ int ref_port=-1;
5397
5398 ✗ av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
5399 ✗ av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
5400
5401 ✗ if (strlen(src) == 0) {
5402 ✗ return -1;
5403 ✗ } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
5404 ✗ strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
5405 ✗ strlen(src_host) + 1 >= sizeof(src_host) ||
5406 ✗ strlen(ref_host) + 1 >= sizeof(ref_host)) {
5407 ✗ return 0;
5408 ✗ } else if (strcmp(src_proto, ref_proto) ||
5409 ✗ strcmp(src_auth, ref_auth) ||
5410 ✗ strcmp(src_host, ref_host) ||
5411 ✗ src_port != ref_port) {
5412 ✗ return 0;
5413 } else
5414 ✗ return 1;
5415 }
5416
5417 ✗ static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
5418 {
5419 /* try relative path, we do not try the absolute because it can leak information about our
5420 system to an attacker */
5421 ✗ if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
5422 char filename[1025];
5423 const char *src_path;
5424 int i, l;
5425
5426 /* find a source dir */
5427 ✗ src_path = strrchr(src, '/');
5428 ✗ if (src_path)
5429 ✗ src_path++;
5430 else
5431 ✗ src_path = src;
5432
5433 /* find a next level down to target */
5434 ✗ for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
5435 ✗ if (ref->path[l] == '/') {
5436 ✗ if (i == ref->nlvl_to - 1)
5437 ✗ break;
5438 else
5439 ✗ i++;
5440 }
5441
5442 /* compose filename if next level down to target was found */
5443 ✗ if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
5444 ✗ memcpy(filename, src, src_path - src);
5445 ✗ filename[src_path - src] = 0;
5446
5447 ✗ for (i = 1; i < ref->nlvl_from; i++)
5448 ✗ av_strlcat(filename, "../", sizeof(filename));
5449
5450 ✗ av_strlcat(filename, ref->path + l + 1, sizeof(filename));
5451 ✗ if (!c->use_absolute_path) {
5452 ✗ int same_origin = test_same_origin(src, filename);
5453
5454 ✗ if (!same_origin) {
5455 ✗ av_log(c->fc, AV_LOG_ERROR,
5456 "Reference with mismatching origin, %s not tried for security reasons, "
5457 "set demuxer option use_absolute_path to allow it anyway\n",
5458 ref->path);
5459 ✗ return AVERROR(ENOENT);
5460 }
5461
5462 ✗ if (strstr(ref->path + l + 1, "..") ||
5463 ✗ strstr(ref->path + l + 1, ":") ||
5464 ✗ (ref->nlvl_from > 1 && same_origin < 0) ||
5465 ✗ (filename[0] == '/' && src_path == src))
5466 ✗ return AVERROR(ENOENT);
5467 }
5468
5469 ✗ if (strlen(filename) + 1 == sizeof(filename))
5470 ✗ return AVERROR(ENOENT);
5471 ✗ if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5472 ✗ return 0;
5473 }
5474 ✗ } else if (c->use_absolute_path) {
5475 ✗ av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5476 "this is a possible security issue\n");
5477 ✗ if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5478 ✗ return 0;
5479 } else {
5480 ✗ av_log(c->fc, AV_LOG_ERROR,
5481 "Absolute path %s not tried for security reasons, "
5482 "set demuxer option use_absolute_path to allow absolute paths\n",
5483 ref->path);
5484 }
5485
5486 ✗ return AVERROR(ENOENT);
5487 }
5488
5489 1797 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5490 {
5491
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1781 times.
1797 if (sc->time_scale <= 0) {
5492 16 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5493 16 sc->time_scale = c->time_scale;
5494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (sc->time_scale <= 0)
5495 ✗ sc->time_scale = 1;
5496 }
5497 1797 }
5498
5499 #if CONFIG_IAMFDEC
5500 12 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5501 {
5502 12 const MOVStreamContext *sc = st->priv_data;
5503 12 const IAMFContext *iamf = &sc->iamf->iamf;
5504
5505
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5506 12 const AVStreamGroup *stg = NULL;
5507
5508
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5509
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 if (c->fc->stream_groups[j]->id == iamf->audio_elements[i]->audio_element_id)
5510 12 stg = c->fc->stream_groups[j];
5511
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 av_assert0(stg);
5512
5513
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_entries; j++) {
5514 64 const FFStream *sti = cffstream(st);
5515 64 AVStream *out = stg->entries[j]->stream;
5516 64 FFStream *out_sti = ffstream(stg->entries[j]->stream);
5517
5518 64 out->codecpar->bit_rate = 0;
5519
5520
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 52 times.
64 if (out == st)
5521 12 continue;
5522
5523 52 out->time_base = st->time_base;
5524 52 out->start_time = st->start_time;
5525 52 out->duration = st->duration;
5526 52 out->nb_frames = st->nb_frames;
5527 52 out->discard = st->discard;
5528
5529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 av_assert0(!out_sti->index_entries);
5530 52 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (!out_sti->index_entries)
5532 ✗ return AVERROR(ENOMEM);
5533
5534 52 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5535 52 out_sti->nb_index_entries = sti->nb_index_entries;
5536 52 out_sti->skip_samples = sti->skip_samples;
5537 52 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5538 }
5539 }
5540
5541 12 return 0;
5542 }
5543 #endif
5544
5545 891 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5546 {
5547
4/6
✓ Branch 0 taken 757 times.
✓ Branch 1 taken 134 times.
✓ Branch 2 taken 757 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 757 times.
✗ Branch 5 not taken.
891 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5548
3/4
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 287 times.
✓ Branch 2 taken 470 times.
✗ Branch 3 not taken.
757 (!sc->sample_size && !sc->sample_count))) ||
5549
3/4
✓ Branch 0 taken 757 times.
✓ Branch 1 taken 134 times.
✓ Branch 2 taken 757 times.
✗ Branch 3 not taken.
891 (sc->sample_count && (!sc->chunk_count ||
5550
3/4
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 287 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 470 times.
757 (!sc->sample_size && !sc->sample_sizes)))) {
5551 ✗ av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5552 index);
5553 ✗ return 1;
5554 }
5555
5556
3/4
✓ Branch 0 taken 757 times.
✓ Branch 1 taken 134 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 757 times.
891 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
5557 ✗ av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5558 index);
5559 ✗ return 2;
5560 }
5561 891 return 0;
5562 }
5563
5564 838 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5565 {
5566 AVStream *st;
5567 MOVStreamContext *sc;
5568 int ret;
5569
5570 838 st = avformat_new_stream(c->fc, NULL);
5571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (!st) return AVERROR(ENOMEM);
5572 838 st->id = -1;
5573 838 sc = av_mallocz(sizeof(MOVStreamContext));
5574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (!sc) return AVERROR(ENOMEM);
5575
5576 838 st->priv_data = sc;
5577 838 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5578 838 sc->ffindex = st->index;
5579 838 c->trak_index = st->index;
5580 838 sc->refcount = 1;
5581
5582
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 838 times.
838 if ((ret = mov_read_default(c, pb, atom)) < 0)
5583 ✗ return ret;
5584
5585 838 c->trak_index = -1;
5586
5587 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5588 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5589
5/6
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 704 times.
✓ Branch 2 taken 134 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 133 times.
838 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
5590 1 sc->stsc_count = 0;
5591 1 av_freep(&sc->stsc_data);
5592 }
5593
5594 838 ret = sanity_checks(c->fc, sc, st->index);
5595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (ret)
5596 ✗ return ret > 1 ? AVERROR_INVALIDDATA : 0;
5597
5598 838 fix_timescale(c, sc);
5599
5600 838 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5601
5602 /*
5603 * Advanced edit list support does not work with fragemented MP4s, which
5604 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5605 * In these files, trun atoms may be streamed in.
5606 */
5607
4/4
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 704 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 108 times.
838 if (!sc->stts_count && c->advanced_editlist) {
5608
5609 26 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5610 "MP4. disabling.\n");
5611 26 c->advanced_editlist = 0;
5612 26 c->advanced_editlist_autodisabled = 1;
5613 }
5614
5615 838 mov_build_index(c, st);
5616 /*
5617 * Fragment samples are appended later by mov_read_trun() and are not
5618 * covered by this non-fragmented track update.
5619 */
5620 838 mov_update_sample_durations(c, st);
5621
5622 #if CONFIG_IAMFDEC
5623
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 826 times.
838 if (sc->iamf) {
5624 12 ret = mov_update_iamf_streams(c, st);
5625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
5626 ✗ return ret;
5627 }
5628 #endif
5629
5630
3/4
✓ Branch 0 taken 837 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 837 times.
838 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
5631 ✗ MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5632 ✗ if (c->enable_drefs) {
5633 ✗ if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5634 ✗ av_log(c->fc, AV_LOG_ERROR,
5635 "stream %d, error opening alias: path='%s', dir='%s', "
5636 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5637 ✗ st->index, dref->path, dref->dir, dref->filename,
5638 ✗ dref->volume, dref->nlvl_from, dref->nlvl_to);
5639 } else {
5640 ✗ av_log(c->fc, AV_LOG_WARNING,
5641 "Skipped opening external track: "
5642 "stream %d, alias: path='%s', dir='%s', "
5643 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5644 "Set enable_drefs to allow this.\n",
5645 ✗ st->index, dref->path, dref->dir, dref->filename,
5646 ✗ dref->volume, dref->nlvl_from, dref->nlvl_to);
5647 }
5648 } else {
5649 838 sc->pb = c->fc->pb;
5650 838 sc->pb_is_copied = 1;
5651 }
5652
5653
2/2
✓ Branch 0 taken 375 times.
✓ Branch 1 taken 463 times.
838 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5654
3/4
✓ Branch 0 taken 356 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 356 times.
✗ Branch 3 not taken.
375 int stts_constant = sc->stts_count && sc->tts_count;
5655
3/4
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 280 times.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
375 if (sc->h_spacing && sc->v_spacing)
5656 95 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5657 95 sc->h_spacing, sc->v_spacing, INT_MAX);
5658
4/6
✓ Branch 0 taken 277 times.
✓ Branch 1 taken 98 times.
✓ Branch 2 taken 277 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 277 times.
✗ Branch 5 not taken.
375 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
5659
2/4
✓ Branch 0 taken 277 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 277 times.
✗ Branch 3 not taken.
277 sc->height && sc->width &&
5660
2/4
✓ Branch 0 taken 277 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 277 times.
277 (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
5661 ✗ av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5662 ✗ (int64_t)st->codecpar->height * sc->width,
5663 ✗ (int64_t)st->codecpar->width * sc->height, INT_MAX);
5664 }
5665
5666 #if FF_API_R_FRAME_RATE
5667
4/4
✓ Branch 0 taken 156120 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 155764 times.
✓ Branch 3 taken 356 times.
156139 for (unsigned int i = 1; sc->stts_count && i + 1 < sc->tts_count; i++) {
5668
2/2
✓ Branch 0 taken 153269 times.
✓ Branch 1 taken 2495 times.
155764 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5669 153269 continue;
5670 2495 stts_constant = 0;
5671 }
5672
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 38 times.
375 if (stts_constant)
5673 337 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5674 337 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5675 #endif
5676 }
5677
5678 #if CONFIG_H261_DECODER || CONFIG_H263_DECODER || CONFIG_MPEG4_DECODER
5679
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 807 times.
838 switch (st->codecpar->codec_id) {
5680 #if CONFIG_H261_DECODER
5681 31 case AV_CODEC_ID_H261:
5682 #endif
5683 #if CONFIG_H263_DECODER
5684 case AV_CODEC_ID_H263:
5685 #endif
5686 #if CONFIG_MPEG4_DECODER
5687 case AV_CODEC_ID_MPEG4:
5688 #endif
5689 31 st->codecpar->width = 0; /* let decoder init width/height */
5690 31 st->codecpar->height= 0;
5691 31 break;
5692 }
5693 #endif
5694
5695 // If the duration of the mp3 packets is not constant, then they could need a parser
5696
2/2
✓ Branch 0 taken 103 times.
✓ Branch 1 taken 735 times.
838 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5697
1/2
✓ Branch 0 taken 103 times.
✗ Branch 1 not taken.
103 && sc->time_scale == st->codecpar->sample_rate) {
5698 103 int stts_constant = 1;
5699
4/4
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 100 times.
✓ Branch 2 taken 365 times.
✓ Branch 3 taken 3 times.
468 for (int i = 1; sc->stts_count && i < sc->tts_count; i++) {
5700
1/2
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
365 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5701 365 continue;
5702 ✗ stts_constant = 0;
5703 }
5704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103 times.
103 if (!stts_constant)
5705 ✗ ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5706 }
5707 /* Do not need those anymore. */
5708 838 av_freep(&sc->chunk_offsets);
5709 838 av_freep(&sc->sample_sizes);
5710 838 av_freep(&sc->keyframes);
5711 838 av_freep(&sc->stps_data);
5712 838 av_freep(&sc->elst_data);
5713 838 av_freep(&sc->rap_group);
5714 838 av_freep(&sc->sync_group);
5715 838 av_freep(&sc->sgpd_sync);
5716
5717 838 return 0;
5718 }
5719
5720 201 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5721 {
5722 int ret;
5723 201 c->itunes_metadata = 1;
5724 201 ret = mov_read_default(c, pb, atom);
5725 201 c->itunes_metadata = 0;
5726 201 return ret;
5727 }
5728
5729 14 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5730 {
5731 uint32_t count;
5732 uint32_t i;
5733
5734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (atom.size < 8)
5735 ✗ return 0;
5736
5737 14 avio_skip(pb, 4);
5738 14 count = avio_rb32(pb);
5739 14 atom.size -= 8;
5740
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
14 if (count > atom.size / 8 || count >= UINT_MAX / sizeof(*c->meta_keys)) {
5741 ✗ av_log(c->fc, AV_LOG_ERROR,
5742 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5743 ✗ return AVERROR_INVALIDDATA;
5744 }
5745
5746 14 c->meta_keys = av_malloc_array(count + 1, sizeof(*c->meta_keys));
5747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!c->meta_keys)
5748 ✗ return AVERROR(ENOMEM);
5749
5750 14 c->meta_keys[0] = NULL;
5751 14 c->meta_keys_count = 1;
5752
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 14 times.
114 for (i = 1; i <= count; ++i) {
5753 100 uint32_t key_size = avio_rb32(pb);
5754 100 uint32_t type = avio_rl32(pb);
5755 100 c->meta_keys[i] = NULL;
5756 100 c->meta_keys_count = i + 1;
5757
2/4
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 100 times.
100 if (key_size < 8 || key_size > atom.size) {
5758 ✗ av_log(c->fc, AV_LOG_ERROR,
5759 "The key# %"PRIu32" in meta has invalid size:"
5760 "%"PRIu32"\n", i, key_size);
5761 ✗ return AVERROR_INVALIDDATA;
5762 }
5763 100 atom.size -= key_size;
5764 100 key_size -= 8;
5765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (type != MKTAG('m','d','t','a')) {
5766 ✗ avio_skip(pb, key_size);
5767 ✗ continue;
5768 }
5769 100 c->meta_keys[i] = av_malloc(key_size + 1);
5770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (!c->meta_keys[i])
5771 ✗ return AVERROR(ENOMEM);
5772 100 int ret = ffio_read_size(pb, c->meta_keys[i], key_size);
5773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (ret < 0)
5774 ✗ return ret;
5775 100 c->meta_keys[i][key_size] = 0;
5776 }
5777
5778 14 return 0;
5779 }
5780
5781 80 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5782 {
5783 80 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5784 80 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5785 int i;
5786 80 int ret = 0;
5787 AVStream *st;
5788
5789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (c->fc->nb_streams < 1)
5790 ✗ return 0;
5791 80 st = c->fc->streams[c->fc->nb_streams-1];
5792
5793
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 80 times.
320 for (i = 0; i < 3; i++) {
5794 uint8_t **p;
5795 uint32_t len, tag;
5796
5797
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 240 times.
240 if (end - avio_tell(pb) <= 12)
5798 ✗ break;
5799
5800 240 len = avio_rb32(pb);
5801 240 tag = avio_rl32(pb);
5802 240 avio_skip(pb, 4); // flags
5803
5804
2/4
✓ Branch 0 taken 240 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 240 times.
✗ Branch 4 not taken.
240 if (len < 12 || len - 12 > end - avio_tell(pb))
5805 break;
5806 240 len -= 12;
5807
5808
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 160 times.
240 if (tag == MKTAG('m', 'e', 'a', 'n'))
5809 80 p = &mean;
5810
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 80 times.
160 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5811 80 p = &key;
5812
2/4
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
80 else if (tag == MKTAG('d', 'a', 't', 'a') && len > 4) {
5813 80 avio_skip(pb, 4);
5814 80 len -= 4;
5815 80 p = &val;
5816 } else
5817 break;
5818
5819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (*p)
5820 ✗ break;
5821
5822 240 *p = av_malloc(len + 1);
5823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (!*p) {
5824 ✗ ret = AVERROR(ENOMEM);
5825 ✗ break;
5826 }
5827 240 ret = ffio_read_size(pb, *p, len);
5828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (ret < 0) {
5829 ✗ av_freep(p);
5830 ✗ break;
5831 }
5832 240 (*p)[len] = 0;
5833 }
5834
5835
3/6
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 80 times.
✗ Branch 5 not taken.
80 if (mean && key && val) {
5836
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 38 times.
80 if (strcmp(key, "iTunSMPB") == 0) {
5837 int64_t priming, remainder, samples;
5838
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 if (ff_itunes_parse_smpb(val, &priming, &remainder, &samples) >= 0) {
5839
2/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
42 if(priming>0 && priming<16384)
5840 42 st->codecpar->initial_padding = priming = av_rescale_q(priming, st->time_base,
5841 42 (AVRational){ 1, st->codecpar->sample_rate });
5842
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 if (remainder > 0) {
5843 42 int64_t duration = av_rescale_q(st->duration, st->time_base,
5844 42 (AVRational){ 1, st->codecpar->sample_rate });
5845 42 remainder = av_rescale_q(remainder, st->time_base,
5846 42 (AVRational){ 1, st->codecpar->sample_rate });
5847 42 samples = av_rescale_q(samples, st->time_base,
5848 42 (AVRational){ 1, st->codecpar->sample_rate });
5849
2/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
42 if (duration > remainder && duration > samples) {
5850 42 ffstream(st)->first_discard_sample = duration - remainder;
5851 42 ffstream(st)->last_discard_sample = duration;
5852 }
5853 }
5854 42 av_log(c->fc, AV_LOG_DEBUG, "Parsed iTunSMPB: priming %"PRId64", "
5855 "remainder %"PRId64" samples %"PRId64"\n",
5856 priming, remainder, samples);
5857 }
5858 }
5859
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 if (strcmp(mean, "com.apple.iTunes") == 0 &&
5860
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 78 times.
80 strcmp(key, "DISCSUBTITLE") == 0) {
5861 2 av_dict_set(&c->fc->metadata, "disc_subtitle", val,
5862 AV_DICT_DONT_STRDUP_VAL);
5863 2 val = NULL;
5864 }
5865
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 10 times.
150 if (strcmp(key, "cdec") != 0) {
5866 70 av_dict_set(&c->fc->metadata, key, val,
5867 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5868 70 key = val = NULL;
5869 }
5870 } else {
5871 ✗ av_log(c->fc, AV_LOG_VERBOSE,
5872 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5873 }
5874
5875 80 avio_seek(pb, end, SEEK_SET);
5876 80 av_freep(&key);
5877 80 av_freep(&val);
5878 80 av_freep(&mean);
5879 80 return ret;
5880 }
5881
5882 53 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5883 {
5884 MOVStreamContext *sc;
5885 AVStream *st;
5886
5887 53 st = avformat_new_stream(c->fc, NULL);
5888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (!st)
5889 ✗ return AVERROR(ENOMEM);
5890 53 sc = av_mallocz(sizeof(MOVStreamContext));
5891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (!sc)
5892 ✗ goto fail;
5893
5894 53 item->st = st;
5895 53 st->id = item->item_id;
5896 53 st->priv_data = sc;
5897 53 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5898 53 st->codecpar->codec_id = mov_codec_id(st, item->type);
5899 53 sc->id = st->id;
5900 53 sc->ffindex = st->index;
5901 53 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5902 53 st->time_base.num = st->time_base.den = 1;
5903 53 st->nb_frames = 1;
5904 53 sc->time_scale = 1;
5905 53 sc->pb = c->fc->pb;
5906 53 sc->pb_is_copied = 1;
5907 53 sc->refcount = 1;
5908
5909
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 10 times.
53 if (item->name)
5910 43 av_dict_set(&st->metadata, "title", item->name, 0);
5911
5912 // Populate the necessary fields used by mov_build_index.
5913 53 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (!sc->stsc_data)
5915 ✗ goto fail;
5916 53 sc->stsc_count = 1;
5917 53 sc->stsc_data[0].first = 1;
5918 53 sc->stsc_data[0].count = 1;
5919 53 sc->stsc_data[0].id = 1;
5920 53 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5921
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (!sc->chunk_offsets)
5922 ✗ goto fail;
5923 53 sc->chunk_count = 1;
5924 53 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5925
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (!sc->stts_data)
5926 ✗ goto fail;
5927 53 sc->stts_count = 1;
5928 53 sc->stts_data[0].count = 1;
5929 // Not used for still images. But needed by mov_build_index.
5930 53 sc->stts_data[0].duration = 0;
5931
5932 53 return 0;
5933 ✗ fail:
5934 ✗ mov_free_stream_context(c->fc, st);
5935 ✗ ff_remove_stream(c->fc, st);
5936 ✗ item->st = NULL;
5937
5938 ✗ return AVERROR(ENOMEM);
5939 }
5940
5941 228 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5942 {
5943
1/2
✓ Branch 0 taken 664 times.
✗ Branch 1 not taken.
664 while (atom.size > 8) {
5944 uint32_t tag;
5945
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 664 times.
664 if (avio_feof(pb))
5946 ✗ return AVERROR_EOF;
5947 664 tag = avio_rl32(pb);
5948 664 atom.size -= 4;
5949
2/2
✓ Branch 0 taken 228 times.
✓ Branch 1 taken 436 times.
664 if (tag == MKTAG('h','d','l','r')) {
5950 228 avio_seek(pb, -8, SEEK_CUR);
5951 228 atom.size += 8;
5952 228 return mov_read_default(c, pb, atom);
5953 }
5954 }
5955 ✗ return 0;
5956 }
5957
5958 // return 1 when matrix is identity, 0 otherwise
5959 #define IS_MATRIX_IDENT(matrix) \
5960 ( (matrix)[0][0] == (1 << 16) && \
5961 (matrix)[1][1] == (1 << 16) && \
5962 (matrix)[2][2] == (1 << 30) && \
5963 !(matrix)[0][1] && !(matrix)[0][2] && \
5964 !(matrix)[1][0] && !(matrix)[1][2] && \
5965 !(matrix)[2][0] && !(matrix)[2][1])
5966
5967 838 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5968 {
5969 int i, j, e;
5970 int width;
5971 int height;
5972 int display_matrix[3][3];
5973 838 int res_display_matrix[3][3] = { { 0 } };
5974 AVStream *st;
5975 MOVStreamContext *sc;
5976 int version;
5977 int flags;
5978
5979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->fc->nb_streams < 1)
5980 ✗ return 0;
5981 838 st = c->fc->streams[c->fc->nb_streams-1];
5982 838 sc = st->priv_data;
5983
5984 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5985 // avoids corrupting AVStreams mapped to an earlier tkhd.
5986
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (st->id != -1)
5987 ✗ return AVERROR_INVALIDDATA;
5988
5989 838 version = avio_r8(pb);
5990 838 flags = avio_rb24(pb);
5991 838 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5992
5993
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 825 times.
838 if (version == 1) {
5994 13 avio_rb64(pb);
5995 13 avio_rb64(pb);
5996 } else {
5997 825 avio_rb32(pb); /* creation time */
5998 825 avio_rb32(pb); /* modification time */
5999 }
6000 838 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
6001 838 sc->id = st->id;
6002 838 avio_rb32(pb); /* reserved */
6003
6004 /* highlevel (considering edits) duration in movie timebase */
6005
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 825 times.
838 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
6006 838 avio_rb32(pb); /* reserved */
6007 838 avio_rb32(pb); /* reserved */
6008
6009 838 avio_rb16(pb); /* layer */
6010 838 avio_rb16(pb); /* alternate group */
6011 838 avio_rb16(pb); /* volume */
6012 838 avio_rb16(pb); /* reserved */
6013
6014 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
6015 // they're kept in fixed point format through all calculations
6016 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
6017 // side data, but the scale factor is not needed to calculate aspect ratio
6018
2/2
✓ Branch 0 taken 2514 times.
✓ Branch 1 taken 838 times.
3352 for (i = 0; i < 3; i++) {
6019 2514 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
6020 2514 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
6021 2514 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
6022 }
6023
6024 838 width = avio_rb32(pb); // 16.16 fixed point track width
6025 838 height = avio_rb32(pb); // 16.16 fixed point track height
6026 838 sc->width = width >> 16;
6027 838 sc->height = height >> 16;
6028
6029 // apply the moov display matrix (after the tkhd one)
6030
2/2
✓ Branch 0 taken 2514 times.
✓ Branch 1 taken 838 times.
3352 for (i = 0; i < 3; i++) {
6031 2514 const int sh[3] = { 16, 16, 30 };
6032
2/2
✓ Branch 0 taken 7542 times.
✓ Branch 1 taken 2514 times.
10056 for (j = 0; j < 3; j++) {
6033
2/2
✓ Branch 0 taken 22626 times.
✓ Branch 1 taken 7542 times.
30168 for (e = 0; e < 3; e++) {
6034 22626 res_display_matrix[i][j] +=
6035 22626 ((int64_t) display_matrix[i][e] *
6036 22626 c->movie_display_matrix[e][j]) >> sh[e];
6037 }
6038 }
6039 }
6040
6041 // save the matrix when it is not the default identity
6042
10/18
✓ Branch 0 taken 829 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 829 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 829 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 829 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 829 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 829 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 829 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 829 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 829 times.
838 if (!IS_MATRIX_IDENT(res_display_matrix)) {
6043 9 av_freep(&sc->display_matrix);
6044 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
6045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
6046 ✗ return AVERROR(ENOMEM);
6047
6048
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
6049
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
6050 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
6051 }
6052
6053 // transform the display width/height according to the matrix
6054 // to keep the same scale, use [width height 1<<16]
6055
5/6
✓ Branch 0 taken 394 times.
✓ Branch 1 taken 444 times.
✓ Branch 2 taken 394 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 386 times.
838 if (width && height && sc->display_matrix) {
6056 double disp_transform[2];
6057
6058
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
6059 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
6060 16 sc->display_matrix[3 + i]);
6061
6062
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 if (disp_transform[0] > 1 && disp_transform[1] > 1 &&
6063
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 disp_transform[0] < (1<<24) && disp_transform[1] < (1<<24) &&
6064
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
6065 3 st->sample_aspect_ratio = av_d2q(
6066 3 disp_transform[0] / disp_transform[1],
6067 INT_MAX);
6068 }
6069 838 return 0;
6070 }
6071
6072 706 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6073 {
6074 706 MOVFragment *frag = &c->fragment;
6075 706 MOVTrackExt *trex = NULL;
6076 int flags, track_id, i;
6077 MOVFragmentStreamInfo * frag_stream_info;
6078
6079 706 avio_r8(pb); /* version */
6080 706 flags = avio_rb24(pb);
6081
6082 706 track_id = avio_rb32(pb);
6083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (!track_id)
6084 ✗ return AVERROR_INVALIDDATA;
6085
1/2
✓ Branch 0 taken 10665 times.
✗ Branch 1 not taken.
10665 for (i = 0; i < c->trex_count; i++)
6086
2/2
✓ Branch 0 taken 706 times.
✓ Branch 1 taken 9959 times.
10665 if (c->trex_data[i].track_id == track_id) {
6087 706 trex = &c->trex_data[i];
6088 706 break;
6089 }
6090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (!trex) {
6091 ✗ av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
6092 ✗ return 0;
6093 }
6094 706 c->fragment.found_tfhd = 1;
6095 706 frag->track_id = track_id;
6096 706 set_frag_stream(&c->frag_index, track_id);
6097
6098 1412 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
6099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
1412 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
6100
2/2
✓ Branch 0 taken 633 times.
✓ Branch 1 taken 73 times.
706 frag->moof_offset : frag->implicit_offset;
6101
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 642 times.
706 frag->stsd_id = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id;
6102
6103 1412 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
6104
2/2
✓ Branch 0 taken 271 times.
✓ Branch 1 taken 435 times.
706 avio_rb32(pb) : trex->duration;
6105 1412 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
6106
2/2
✓ Branch 0 taken 263 times.
✓ Branch 1 taken 443 times.
706 avio_rb32(pb) : trex->size;
6107 1412 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
6108
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 369 times.
706 avio_rb32(pb) : trex->flags;
6109 706 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
6110
6111 706 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6112
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (frag_stream_info) {
6113 706 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
6114 706 frag_stream_info->stsd_id = frag->stsd_id;
6115 }
6116 706 return 0;
6117 }
6118
6119 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6120 {
6121 unsigned i, num;
6122 void *new_tracks;
6123
6124 2 num = atom.size / 4;
6125
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
6126 ✗ return AVERROR(ENOMEM);
6127
6128 2 av_free(c->chapter_tracks);
6129 2 c->chapter_tracks = new_tracks;
6130 2 c->nb_chapter_tracks = num;
6131
6132
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 for (i = 0; i < num && !pb->eof_reached; i++)
6133 2 c->chapter_tracks[i] = avio_rb32(pb);
6134
6135 2 c->nb_chapter_tracks = i;
6136
6137 2 return 0;
6138 }
6139
6140 133 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6141 {
6142 MOVTrackExt *trex;
6143 int err;
6144
6145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
133 if ((uint64_t)c->trex_count+1 >= UINT_MAX / sizeof(*c->trex_data))
6146 ✗ return AVERROR_INVALIDDATA;
6147
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 133 times.
133 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
6148 sizeof(*c->trex_data))) < 0) {
6149 ✗ c->trex_count = 0;
6150 ✗ return err;
6151 }
6152
6153 133 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
6154
6155 133 trex = &c->trex_data[c->trex_count++];
6156 133 avio_r8(pb); /* version */
6157 133 avio_rb24(pb); /* flags */
6158 133 trex->track_id = avio_rb32(pb);
6159 133 trex->stsd_id = avio_rb32(pb);
6160 133 trex->duration = avio_rb32(pb);
6161 133 trex->size = avio_rb32(pb);
6162 133 trex->flags = avio_rb32(pb);
6163 133 return 0;
6164 }
6165
6166 633 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6167 {
6168 633 MOVFragment *frag = &c->fragment;
6169 633 AVStream *st = NULL;
6170 MOVStreamContext *sc;
6171 int version, i;
6172 MOVFragmentStreamInfo * frag_stream_info;
6173 int64_t base_media_decode_time;
6174
6175
1/2
✓ Branch 0 taken 10560 times.
✗ Branch 1 not taken.
10560 for (i = 0; i < c->fc->nb_streams; i++) {
6176 10560 sc = c->fc->streams[i]->priv_data;
6177
2/2
✓ Branch 0 taken 633 times.
✓ Branch 1 taken 9927 times.
10560 if (sc->id == frag->track_id) {
6178 633 st = c->fc->streams[i];
6179 633 break;
6180 }
6181 }
6182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 633 times.
633 if (!st) {
6183 ✗ av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
6184 ✗ return 0;
6185 }
6186 633 sc = st->priv_data;
6187
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 629 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
633 if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1)
6188 ✗ return 0;
6189 633 version = avio_r8(pb);
6190 633 avio_rb24(pb); /* flags */
6191
2/2
✓ Branch 0 taken 260 times.
✓ Branch 1 taken 373 times.
633 if (version) {
6192 260 base_media_decode_time = avio_rb64(pb);
6193 } else {
6194 373 base_media_decode_time = avio_rb32(pb);
6195 }
6196
6197 633 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6198
1/2
✓ Branch 0 taken 633 times.
✗ Branch 1 not taken.
633 if (frag_stream_info)
6199 633 frag_stream_info->tfdt_dts = base_media_decode_time;
6200 633 sc->track_end = base_media_decode_time;
6201
6202 633 return 0;
6203 }
6204
6205 706 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6206 {
6207 706 MOVFragment *frag = &c->fragment;
6208 706 AVStream *st = NULL;
6209 706 FFStream *sti = NULL;
6210 MOVStreamContext *sc;
6211 MOVTimeToSample *tts_data;
6212 uint64_t offset;
6213 706 int64_t dts, pts = AV_NOPTS_VALUE;
6214 706 int data_offset = 0;
6215 706 unsigned entries, first_sample_flags = frag->flags;
6216 int flags, distance, i;
6217 706 int64_t prev_dts = AV_NOPTS_VALUE;
6218 706 int next_frag_index = -1, index_entry_pos;
6219 size_t requested_size;
6220 AVIndexEntry *new_entries;
6221 MOVFragmentStreamInfo * frag_stream_info;
6222
6223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (!frag->found_tfhd) {
6224 ✗ av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
6225 ✗ return AVERROR_INVALIDDATA;
6226 }
6227
6228
1/2
✓ Branch 0 taken 10665 times.
✗ Branch 1 not taken.
10665 for (i = 0; i < c->fc->nb_streams; i++) {
6229 10665 sc = c->fc->streams[i]->priv_data;
6230
2/2
✓ Branch 0 taken 706 times.
✓ Branch 1 taken 9959 times.
10665 if (sc->id == frag->track_id) {
6231 706 st = c->fc->streams[i];
6232 706 sti = ffstream(st);
6233 706 break;
6234 }
6235 }
6236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (!st) {
6237 ✗ av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
6238 ✗ return 0;
6239 }
6240 706 sc = st->priv_data;
6241
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 702 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
706 if (sc->pseudo_stream_id+1 != frag->stsd_id && sc->pseudo_stream_id != -1)
6242 ✗ return 0;
6243
6244 // Find the next frag_index index that has a valid index_entry for
6245 // the current track_id.
6246 //
6247 // A valid index_entry means the trun for the fragment was read
6248 // and it's samples are in index_entries at the given position.
6249 // New index entries will be inserted before the index_entry found.
6250 706 index_entry_pos = sti->nb_index_entries;
6251
2/2
✓ Branch 0 taken 1634 times.
✓ Branch 1 taken 706 times.
2340 for (i = c->frag_index.current + 1; i < c->frag_index.nb_items; i++) {
6252 1634 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
6253
2/4
✓ Branch 0 taken 1634 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1634 times.
1634 if (frag_stream_info && frag_stream_info->index_entry >= 0) {
6254 ✗ next_frag_index = i;
6255 ✗ index_entry_pos = frag_stream_info->index_entry;
6256 ✗ break;
6257 }
6258 }
6259
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 av_assert0(index_entry_pos <= sti->nb_index_entries);
6260
6261 706 avio_r8(pb); /* version */
6262 706 flags = avio_rb24(pb);
6263 706 entries = avio_rb32(pb);
6264 706 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
6265
6266 /* Explicit zero sizes are bounded by the trun payload. Reject a zero
6267 * default size before allocating or updating the sample index. */
6268
4/6
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 443 times.
✓ Branch 3 taken 263 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 443 times.
706 if (entries && !frag->size && !(flags & MOV_TRUN_SAMPLE_SIZE))
6269 ✗ return AVERROR_INVALIDDATA;
6270
6271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if ((uint64_t)entries+sc->tts_count >= UINT_MAX/sizeof(*sc->tts_data))
6272 ✗ return AVERROR_INVALIDDATA;
6273
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
6274
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 627 times.
706 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb);
6275
6276 706 int entry_size = !!(flags & MOV_TRUN_SAMPLE_DURATION) * 4
6277 706 + !!(flags & MOV_TRUN_SAMPLE_SIZE) * 4
6278 706 + !!(flags & MOV_TRUN_SAMPLE_FLAGS) * 4
6279 706 + !!(flags & MOV_TRUN_SAMPLE_CTS) * 4;
6280 706 int64_t sample_data_size = avio_size(sc->pb);
6281 706 int64_t max_entries = INT64_MAX;
6282
6283
2/2
✓ Branch 0 taken 505 times.
✓ Branch 1 taken 201 times.
706 if (sample_data_size > 0)
6284 505 max_entries = sample_data_size - sti->nb_index_entries;
6285
2/2
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 226 times.
706 if (entry_size) {
6286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 480 times.
480 int64_t size = sc->pb == pb ? sample_data_size : avio_size(pb);
6287 480 int64_t pos = avio_tell(pb);
6288 480 int64_t left = atom.size - 8 - !!(flags & MOV_TRUN_DATA_OFFSET) * 4
6289 480 - !!(flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) * 4;
6290
6291
3/4
✓ Branch 0 taken 480 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 479 times.
✓ Branch 3 taken 1 times.
480 if (pos >= 0 && size >= pos)
6292 479 left = FFMIN(left, size - pos);
6293 480 max_entries = FFMIN(max_entries, left / entry_size);
6294 }
6295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (entries > max_entries) {
6296 ✗ av_log(c->fc, AV_LOG_ERROR, "trun sample count %u exceeds the %"PRId64" "
6297 "samples the input can hold\n", entries, max_entries);
6298 ✗ return AVERROR_INVALIDDATA;
6299 }
6300
6301 706 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6302
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (frag_stream_info) {
6303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
6304 ✗ dts = frag_stream_info->next_trun_dts - sc->time_offset;
6305
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 703 times.
706 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
6306
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
6307 3 pts = frag_stream_info->first_tfra_pts;
6308 3 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
6309 ", using it for pts\n", pts);
6310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 703 times.
703 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
6311 ✗ c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
6312 ✗ dts = frag_stream_info->first_tfra_pts;
6313 ✗ av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
6314 ", using it for dts\n", pts);
6315 } else {
6316 703 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
6317 703 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
6318
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 703 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
703 int fallback_tfdt = !c->use_tfdt && !has_sidx && has_tfdt;
6319
4/6
✓ Branch 0 taken 703 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 630 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
703 int fallback_sidx = c->use_tfdt && !has_tfdt && has_sidx;
6320
6321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 703 times.
703 if (fallback_sidx) {
6322 ✗ av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
6323 }
6324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 703 times.
703 if (fallback_tfdt) {
6325 ✗ av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
6326 }
6327
6328
4/6
✓ Branch 0 taken 630 times.
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 630 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
703 if (has_tfdt && c->use_tfdt || fallback_tfdt) {
6329 630 dts = frag_stream_info->tfdt_dts - sc->time_offset;
6330 630 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
6331 ", using it for dts\n", dts);
6332
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
73 } else if (has_sidx && !c->use_tfdt || fallback_sidx) {
6333 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
6334 // pts = frag_stream_info->sidx_pts;
6335 ✗ dts = frag_stream_info->sidx_pts;
6336 ✗ av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
6337 ", using it for dts\n", frag_stream_info->sidx_pts);
6338 } else {
6339 73 dts = sc->track_end - sc->time_offset;
6340 73 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
6341 ", using it for dts\n", dts);
6342 }
6343 }
6344 } else {
6345 ✗ dts = sc->track_end - sc->time_offset;
6346 ✗ av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
6347 ", using it for dts\n", dts);
6348 }
6349 706 offset = frag->base_data_offset + data_offset;
6350 706 distance = 0;
6351 706 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
6352
6353 // realloc space for new index entries
6354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
6355 ✗ entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
6356 ✗ av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
6357 }
6358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (entries == 0)
6359 ✗ return 0;
6360
6361 706 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
6362 706 new_entries = av_fast_realloc(sti->index_entries,
6363 &sti->index_entries_allocated_size,
6364 requested_size);
6365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (!new_entries)
6366 ✗ return AVERROR(ENOMEM);
6367 706 sti->index_entries= new_entries;
6368
6369 706 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
6370 706 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
6371 requested_size);
6372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (!tts_data)
6373 ✗ return AVERROR(ENOMEM);
6374 706 sc->tts_data = tts_data;
6375
6376 // In case there were samples without time to sample entries, ensure they get
6377 // zero valued entries. This ensures clips which mix boxes with and
6378 // without time to sample entries don't pickup uninitialized data.
6379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (sc->tts_count < sti->nb_index_entries)
6380 ✗ memset(sc->tts_data + sc->tts_count, 0,
6381 ✗ sizeof(*sc->tts_data) * (sti->nb_index_entries - sc->tts_count));
6382
6383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (index_entry_pos < sti->nb_index_entries) {
6384 // Make hole in index_entries and tts_data for new samples
6385 ✗ memmove(sti->index_entries + index_entry_pos + entries,
6386 ✗ sti->index_entries + index_entry_pos,
6387 sizeof(*sti->index_entries) *
6388 ✗ (sti->nb_index_entries - index_entry_pos));
6389 ✗ memmove(sc->tts_data + index_entry_pos + entries,
6390 ✗ sc->tts_data + index_entry_pos,
6391 ✗ sizeof(*sc->tts_data) * (sti->nb_index_entries - index_entry_pos));
6392 ✗ if (index_entry_pos < sc->current_sample) {
6393 ✗ sc->current_sample += entries;
6394 }
6395 }
6396
6397 706 sti->nb_index_entries += entries;
6398 706 sc->tts_count = sti->nb_index_entries;
6399 706 sc->stts_count = sti->nb_index_entries;
6400
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 320 times.
706 if (flags & MOV_TRUN_SAMPLE_CTS)
6401 386 sc->ctts_count = sti->nb_index_entries;
6402
6403 // Record the index_entry position in frag_index of this fragment
6404
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (frag_stream_info) {
6405 706 frag_stream_info->index_entry = index_entry_pos;
6406
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (frag_stream_info->index_base < 0)
6407 706 frag_stream_info->index_base = index_entry_pos;
6408 }
6409
6410
2/2
✓ Branch 0 taken 574 times.
✓ Branch 1 taken 132 times.
706 if (index_entry_pos > 0)
6411 574 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6412
6413
3/4
✓ Branch 0 taken 12391 times.
✓ Branch 1 taken 706 times.
✓ Branch 2 taken 12391 times.
✗ Branch 3 not taken.
13097 for (i = 0; i < entries && !pb->eof_reached; i++) {
6414 12391 unsigned sample_size = frag->size;
6415
2/2
✓ Branch 0 taken 11685 times.
✓ Branch 1 taken 706 times.
12391 int sample_flags = i ? frag->flags : first_sample_flags;
6416 12391 unsigned sample_duration = frag->duration;
6417 12391 unsigned ctts_duration = 0;
6418 12391 int keyframe = 0;
6419 12391 int index_entry_flags = 0;
6420
6421
2/2
✓ Branch 0 taken 1694 times.
✓ Branch 1 taken 10697 times.
12391 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
6422
2/2
✓ Branch 0 taken 9533 times.
✓ Branch 1 taken 2858 times.
12391 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
6423
2/2
✓ Branch 0 taken 1845 times.
✓ Branch 1 taken 10546 times.
12391 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
6424
2/2
✓ Branch 0 taken 6576 times.
✓ Branch 1 taken 5815 times.
12391 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
6425
6426
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12390 times.
12391 if (sample_duration > c->max_stts_delta) {
6427 1 av_log(c->fc, AV_LOG_WARNING,
6428 "Too large sample duration %u in trun entry %u in st:%d. Clipping to 1.\n",
6429 sample_duration, i, st->index);
6430 1 sample_duration = 1;
6431 }
6432
6433 12391 mov_update_dts_shift(sc, ctts_duration, c->fc);
6434
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 12388 times.
12391 if (pts != AV_NOPTS_VALUE) {
6435 3 dts = pts - sc->dts_shift;
6436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (flags & MOV_TRUN_SAMPLE_CTS) {
6437 ✗ dts -= ctts_duration;
6438 } else {
6439 3 dts -= sc->time_offset;
6440 }
6441 3 av_log(c->fc, AV_LOG_DEBUG,
6442 "pts %"PRId64" calculated dts %"PRId64
6443 " sc->dts_shift %d ctts.duration %d"
6444 " sc->time_offset %"PRId64
6445 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
6446 pts, dts,
6447 sc->dts_shift, ctts_duration,
6448 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
6449 3 pts = AV_NOPTS_VALUE;
6450 }
6451
6452 12391 keyframe =
6453 12391 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
6454 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
6455
2/2
✓ Branch 0 taken 3468 times.
✓ Branch 1 taken 8923 times.
12391 if (keyframe) {
6456 3468 distance = 0;
6457 3468 index_entry_flags |= AVINDEX_KEYFRAME;
6458 }
6459 // Fragments can overlap in time. Discard overlapping frames after
6460 // decoding.
6461
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12367 times.
12391 if (prev_dts >= dts)
6462 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
6463
6464 12391 sti->index_entries[index_entry_pos].pos = offset;
6465 12391 sti->index_entries[index_entry_pos].timestamp = dts;
6466 12391 sti->index_entries[index_entry_pos].size = sample_size;
6467 12391 sti->index_entries[index_entry_pos].min_distance = distance;
6468 12391 sti->index_entries[index_entry_pos].flags = index_entry_flags;
6469
6470 12391 sc->tts_data[index_entry_pos].count = 1;
6471 12391 sc->tts_data[index_entry_pos].offset = ctts_duration;
6472 12391 sc->tts_data[index_entry_pos].duration = sample_duration;
6473 12391 index_entry_pos++;
6474
6475 12391 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
6476 "size %u, distance %d, keyframe %d\n", st->index,
6477 index_entry_pos, offset, dts, sample_size, distance, keyframe);
6478 12391 distance++;
6479
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12391 times.
12391 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
6480 ✗ return AVERROR_INVALIDDATA;
6481 12391 dts += sample_duration;
6482 12391 offset += sample_size;
6483 12391 sc->data_size += sample_size;
6484
6485
1/2
✓ Branch 0 taken 12391 times.
✗ Branch 1 not taken.
12391 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
6486
1/2
✓ Branch 0 taken 12391 times.
✗ Branch 1 not taken.
12391 1 <= INT_MAX - sc->nb_frames_for_fps
6487 ) {
6488 12391 sc->duration_for_fps += sample_duration;
6489 12391 sc->nb_frames_for_fps ++;
6490 }
6491 }
6492
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (frag_stream_info)
6493 706 frag_stream_info->next_trun_dts = dts + sc->time_offset;
6494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (i < entries) {
6495 // EOF found before reading all entries. Fix the hole this would
6496 // leave in index_entries and tts_data
6497 ✗ int gap = entries - i;
6498 ✗ memmove(sti->index_entries + index_entry_pos,
6499 ✗ sti->index_entries + index_entry_pos + gap,
6500 sizeof(*sti->index_entries) *
6501 ✗ (sti->nb_index_entries - (index_entry_pos + gap)));
6502 ✗ memmove(sc->tts_data + index_entry_pos,
6503 ✗ sc->tts_data + index_entry_pos + gap,
6504 sizeof(*sc->tts_data) *
6505 ✗ (sc->tts_count - (index_entry_pos + gap)));
6506
6507 ✗ sti->nb_index_entries -= gap;
6508 ✗ sc->tts_count -= gap;
6509 ✗ if (index_entry_pos < sc->current_sample) {
6510 ✗ sc->current_sample -= gap;
6511 }
6512 ✗ entries = i;
6513 }
6514
6515 // The end of this new fragment may overlap in time with the start
6516 // of the next fragment in index_entries. Mark the samples in the next
6517 // fragment that overlap with AVINDEX_DISCARD_FRAME
6518 706 prev_dts = AV_NOPTS_VALUE;
6519
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (index_entry_pos > 0)
6520 706 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
6522 ✗ if (prev_dts < sti->index_entries[i].timestamp)
6523 ✗ break;
6524 ✗ sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6525 }
6526
6527 // If a hole was created to insert the new index_entries into,
6528 // the index_entry recorded for all subsequent moof must
6529 // be incremented by the number of entries inserted.
6530 706 fix_frag_index_entries(&c->frag_index, next_frag_index,
6531 706 frag->track_id, entries);
6532
6533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (pb->eof_reached) {
6534 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6535 ✗ return AVERROR_EOF;
6536 }
6537
6538 706 frag->implicit_offset = offset;
6539
6540 706 sc->track_end = dts + sc->time_offset;
6541
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 586 times.
706 if (st->duration < sc->track_end)
6542 120 st->duration = sc->track_end;
6543
6544 706 return 0;
6545 }
6546
6547 249 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6548 {
6549 249 int64_t stream_size = avio_size(pb);
6550 249 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6551 uint8_t version, is_complete;
6552 int64_t offadd;
6553 unsigned i, j, track_id, item_count;
6554 249 AVStream *st = NULL;
6555 249 AVStream *ref_st = NULL;
6556 249 MOVStreamContext *sc, *ref_sc = NULL;
6557 AVRational timescale;
6558
6559 249 version = avio_r8(pb);
6560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if (version > 1) {
6561 ✗ avpriv_request_sample(c->fc, "sidx version %u", version);
6562 ✗ return 0;
6563 }
6564
6565 249 avio_rb24(pb); // flags
6566
6567 249 track_id = avio_rb32(pb); // Reference ID
6568
1/2
✓ Branch 0 taken 10149 times.
✗ Branch 1 not taken.
10149 for (i = 0; i < c->fc->nb_streams; i++) {
6569 10149 sc = c->fc->streams[i]->priv_data;
6570
2/2
✓ Branch 0 taken 249 times.
✓ Branch 1 taken 9900 times.
10149 if (sc->id == track_id) {
6571 249 st = c->fc->streams[i];
6572 249 break;
6573 }
6574 }
6575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if (!st) {
6576 ✗ av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6577 ✗ return 0;
6578 }
6579
6580 249 sc = st->priv_data;
6581
6582 249 timescale = av_make_q(1, avio_rb32(pb));
6583
6584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if (timescale.den <= 0) {
6585 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6586 ✗ return AVERROR_INVALIDDATA;
6587 }
6588
6589
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 201 times.
249 if (version == 0) {
6590 48 pts = avio_rb32(pb);
6591 48 offadd= avio_rb32(pb);
6592 } else {
6593 201 pts = avio_rb64(pb);
6594 201 offadd= avio_rb64(pb);
6595 }
6596
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 249 times.
249 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6597 ✗ return AVERROR_INVALIDDATA;
6598
6599 249 offset += (uint64_t)offadd;
6600
6601 249 avio_rb16(pb); // reserved
6602
6603 249 item_count = avio_rb16(pb);
6604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if (item_count == 0)
6605 ✗ return AVERROR_INVALIDDATA;
6606
6607
2/2
✓ Branch 0 taken 575 times.
✓ Branch 1 taken 249 times.
824 for (i = 0; i < item_count; i++) {
6608 int index;
6609 MOVFragmentStreamInfo * frag_stream_info;
6610 575 uint32_t size = avio_rb32(pb);
6611 575 uint32_t duration = avio_rb32(pb);
6612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 if (size & 0x80000000) {
6613 ✗ avpriv_request_sample(c->fc, "sidx reference_type 1");
6614 ✗ return AVERROR_PATCHWELCOME;
6615 }
6616 575 avio_rb32(pb); // sap_flags
6617 575 timestamp = av_rescale_q(pts, timescale, st->time_base);
6618
6619 575 index = update_frag_index(c, offset);
6620 575 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6621
1/2
✓ Branch 0 taken 575 times.
✗ Branch 1 not taken.
575 if (frag_stream_info)
6622 575 frag_stream_info->sidx_pts = timestamp;
6623
6624
1/2
✓ Branch 1 taken 575 times.
✗ Branch 2 not taken.
575 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6625
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 575 times.
575 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6626 )
6627 ✗ return AVERROR_INVALIDDATA;
6628 575 offset += size;
6629 575 pts += duration;
6630 }
6631
6632 249 st->duration = sc->track_end = pts;
6633
6634 249 sc->has_sidx = 1;
6635
6636 // See if the remaining bytes are just an mfra which we can ignore.
6637 249 is_complete = offset == stream_size;
6638
5/6
✓ Branch 0 taken 242 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 201 times.
✓ Branch 4 taken 41 times.
✗ Branch 5 not taken.
249 if (!is_complete && (pb->seekable & AVIO_SEEKABLE_NORMAL) && stream_size > 0 ) {
6639 int64_t ret;
6640 41 int64_t original_pos = avio_tell(pb);
6641
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 35 times.
41 if (!c->have_read_mfra_size) {
6642
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6643 ✗ return ret;
6644 6 c->mfra_size = avio_rb32(pb);
6645 6 c->have_read_mfra_size = 1;
6646
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6647 ✗ return ret;
6648 }
6649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (offset == stream_size - c->mfra_size)
6650 ✗ is_complete = 1;
6651 }
6652
6653
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 242 times.
249 if (is_complete) {
6654 // Find first entry in fragment index that came from an sidx.
6655 // This will pretty much always be the first entry.
6656
2/2
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 7 times.
378 for (i = 0; i < c->frag_index.nb_items; i++) {
6657 371 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6658
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 364 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
371 for (j = 0; ref_st == NULL && j < item->nb_stream_info; j++) {
6659 MOVFragmentStreamInfo * si;
6660 7 si = &item->stream_info[j];
6661
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (si->sidx_pts != AV_NOPTS_VALUE) {
6662 7 ref_st = c->fc->streams[j];
6663 7 ref_sc = ref_st->priv_data;
6664 7 break;
6665 }
6666 }
6667 }
6668
3/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 7 times.
14 if (ref_st) for (i = 0; i < c->fc->nb_streams; i++) {
6669 7 st = c->fc->streams[i];
6670 7 sc = st->priv_data;
6671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sc->has_sidx) {
6672 ✗ st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6673 }
6674 }
6675
6676
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (offadd == 0)
6677 7 c->frag_index.complete = 1;
6678 }
6679
6680 249 return 0;
6681 }
6682
6683 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6684 /* like the files created with Adobe Premiere 5.0, for samples see */
6685 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6686 299 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6687 {
6688 int err;
6689
6690
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 if (atom.size < 8)
6691 299 return 0; /* continue */
6692 ✗ if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6693 ✗ avio_skip(pb, atom.size - 4);
6694 ✗ return 0;
6695 }
6696 ✗ atom.type = avio_rl32(pb);
6697 ✗ atom.size -= 8;
6698 ✗ if (atom.type != MKTAG('m','d','a','t')) {
6699 ✗ avio_skip(pb, atom.size);
6700 ✗ return 0;
6701 }
6702 ✗ err = mov_read_mdat(c, pb, atom);
6703 ✗ return err;
6704 }
6705
6706 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6707 {
6708 #if CONFIG_ZLIB
6709 FFIOContext ctx;
6710 uint8_t *cmov_data;
6711 uint8_t *moov_data; /* uncompressed data */
6712 long cmov_len, moov_len;
6713 3 int ret = -1;
6714
6715 3 avio_rb32(pb); /* dcom atom */
6716
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6717 ✗ return AVERROR_INVALIDDATA;
6718
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6719 ✗ av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6720 ✗ return AVERROR_INVALIDDATA;
6721 }
6722 3 avio_rb32(pb); /* cmvd atom */
6723
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6724 ✗ return AVERROR_INVALIDDATA;
6725 3 moov_len = avio_rb32(pb); /* uncompressed size */
6726 3 cmov_len = atom.size - 6 * 4;
6727
6728 3 cmov_data = av_malloc(cmov_len);
6729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6730 ✗ return AVERROR(ENOMEM);
6731 3 moov_data = av_malloc(moov_len);
6732
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6733 ✗ av_free(cmov_data);
6734 ✗ return AVERROR(ENOMEM);
6735 }
6736 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6738 ✗ goto free_and_return;
6739
6740 3 ret = AVERROR_INVALIDDATA;
6741
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
6742 ✗ goto free_and_return;
6743 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6744 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6745 3 atom.type = MKTAG('m','o','o','v');
6746 3 atom.size = moov_len;
6747 3 ret = mov_read_default(c, &ctx.pub, atom);
6748 3 free_and_return:
6749 3 av_free(moov_data);
6750 3 av_free(cmov_data);
6751 3 return ret;
6752 #else
6753 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6754 return AVERROR(ENOSYS);
6755 #endif
6756 }
6757
6758 /* edit list atom */
6759 649 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6760 {
6761 MOVStreamContext *sc;
6762 int i, edit_count, version;
6763 int64_t elst_entry_size;
6764
6765
2/4
✓ Branch 0 taken 649 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 649 times.
649 if (c->fc->nb_streams < 1 || c->ignore_editlist)
6766 ✗ return 0;
6767 649 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6768
6769 649 version = avio_r8(pb); /* version */
6770 649 avio_rb24(pb); /* flags */
6771 649 edit_count = avio_rb32(pb); /* entries */
6772 649 atom.size -= 8;
6773
6774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 649 times.
649 elst_entry_size = version == 1 ? 20 : 12;
6775
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 648 times.
649 if (atom.size != edit_count * elst_entry_size) {
6776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6777 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6778 ✗ edit_count, atom.size + 8);
6779 ✗ return AVERROR_INVALIDDATA;
6780 } else {
6781 1 edit_count = atom.size / elst_entry_size;
6782
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6783 ✗ av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6784 }
6785 }
6786 }
6787
6788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 649 times.
649 if (!edit_count)
6789 ✗ return 0;
6790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 649 times.
649 if (sc->elst_data)
6791 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6792 649 av_free(sc->elst_data);
6793 649 sc->elst_count = 0;
6794 649 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6795
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 649 times.
649 if (!sc->elst_data)
6796 ✗ return AVERROR(ENOMEM);
6797
6798 649 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6799
4/6
✓ Branch 0 taken 678 times.
✓ Branch 1 taken 649 times.
✓ Branch 2 taken 678 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 678 times.
✗ Branch 5 not taken.
1327 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
6800 678 MOVElst *e = &sc->elst_data[i];
6801
6802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 678 times.
678 if (version == 1) {
6803 ✗ e->duration = avio_rb64(pb);
6804 ✗ e->time = avio_rb64(pb);
6805 ✗ atom.size -= 16;
6806 } else {
6807 678 e->duration = avio_rb32(pb); /* segment duration */
6808 678 e->time = (int32_t)avio_rb32(pb); /* media time */
6809 678 atom.size -= 8;
6810 }
6811 678 e->rate = avio_rb32(pb) / 65536.0;
6812 678 atom.size -= 4;
6813 678 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6814 678 e->duration, e->time, e->rate);
6815
6816
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 674 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
678 if (e->time < 0 && e->time != -1 &&
6817 ✗ c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6818 ✗ av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6819 ✗ c->fc->nb_streams-1, i, e->time);
6820 ✗ return AVERROR_INVALIDDATA;
6821 }
6822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 678 times.
678 if (e->duration < 0) {
6823 ✗ av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list duration=%"PRId64"\n",
6824 ✗ c->fc->nb_streams-1, i, e->duration);
6825 ✗ return AVERROR_INVALIDDATA;
6826 }
6827 }
6828 649 sc->elst_count = i;
6829
6830 649 return 0;
6831 }
6832
6833 21 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6834 {
6835 MOVStreamContext *sc;
6836 int err;
6837
6838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (c->fc->nb_streams < 1)
6839 ✗ return AVERROR_INVALIDDATA;
6840 21 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6841
6842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (atom.size % sizeof(uint32_t))
6843 ✗ return AVERROR_INVALIDDATA;
6844
6845 21 MovTref *tag = mov_add_tref_tag(sc, atom.type);
6846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!tag)
6847 ✗ return AVERROR(ENOMEM);
6848
6849 21 int nb_timecode_track = atom.size >> 2;
6850
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 21 times.
52 for (int i = 0; i < nb_timecode_track; i++) {
6851
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 if (avio_feof(pb))
6852 ✗ return AVERROR_INVALIDDATA;
6853 31 err = mov_add_tref_id(tag, avio_rb32(pb));
6854
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (err < 0)
6855 ✗ return err;
6856 }
6857
6858 21 return 0;
6859 }
6860
6861 ✗ static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6862 {
6863 AVStream *st;
6864 int version, color_range, color_primaries, color_trc, color_space;
6865
6866 ✗ if (c->fc->nb_streams < 1)
6867 ✗ return 0;
6868 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
6869
6870 ✗ if (atom.size < 5) {
6871 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6872 ✗ return AVERROR_INVALIDDATA;
6873 }
6874
6875 ✗ version = avio_r8(pb);
6876 ✗ if (version != 1) {
6877 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6878 ✗ return 0;
6879 }
6880 ✗ avio_skip(pb, 3); /* flags */
6881
6882 ✗ avio_skip(pb, 2); /* profile + level */
6883 ✗ color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6884 ✗ color_primaries = avio_r8(pb);
6885 ✗ color_trc = avio_r8(pb);
6886 ✗ color_space = avio_r8(pb);
6887 ✗ if (avio_rb16(pb)) /* codecIntializationDataSize */
6888 ✗ return AVERROR_INVALIDDATA;
6889
6890 ✗ if (!av_color_primaries_name(color_primaries))
6891 ✗ color_primaries = AVCOL_PRI_UNSPECIFIED;
6892 ✗ if (!av_color_transfer_name(color_trc))
6893 ✗ color_trc = AVCOL_TRC_UNSPECIFIED;
6894 ✗ if (!av_color_space_name(color_space))
6895 ✗ color_space = AVCOL_SPC_UNSPECIFIED;
6896
6897 ✗ st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6898 ✗ st->codecpar->color_primaries = color_primaries;
6899 ✗ st->codecpar->color_trc = color_trc;
6900 ✗ st->codecpar->color_space = color_space;
6901
6902 ✗ return 0;
6903 }
6904
6905 ✗ static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6906 {
6907 MOVStreamContext *sc;
6908 int i, version;
6909
6910 ✗ if (c->fc->nb_streams < 1)
6911 ✗ return AVERROR_INVALIDDATA;
6912
6913 ✗ sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6914
6915 ✗ if (atom.size < 5) {
6916 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6917 ✗ return AVERROR_INVALIDDATA;
6918 }
6919
6920 ✗ version = avio_r8(pb);
6921 ✗ if (version) {
6922 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6923 ✗ return 0;
6924 }
6925 ✗ if (sc->mastering) {
6926 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6927 ✗ return 0;
6928 }
6929
6930 ✗ avio_skip(pb, 3); /* flags */
6931
6932 ✗ sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6933 ✗ if (!sc->mastering)
6934 ✗ return AVERROR(ENOMEM);
6935
6936 ✗ for (i = 0; i < 3; i++) {
6937 ✗ sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6938 ✗ sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6939 }
6940 ✗ sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6941 ✗ sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6942
6943 ✗ sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6944 ✗ sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6945
6946 ✗ sc->mastering->has_primaries = 1;
6947 ✗ sc->mastering->has_luminance = 1;
6948
6949 ✗ return 0;
6950 }
6951
6952 ✗ static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6953 {
6954 MOVStreamContext *sc;
6955 ✗ const int mapping[3] = {1, 2, 0};
6956 ✗ const int chroma_den = 50000;
6957 ✗ const int luma_den = 10000;
6958 int i;
6959
6960 ✗ if (c->fc->nb_streams < 1)
6961 ✗ return AVERROR_INVALIDDATA;
6962
6963 ✗ sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6964
6965 ✗ if (atom.size < 24) {
6966 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6967 ✗ return AVERROR_INVALIDDATA;
6968 }
6969
6970 ✗ if (sc->mastering) {
6971 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6972 ✗ return 0;
6973 }
6974
6975 ✗ sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6976 ✗ if (!sc->mastering)
6977 ✗ return AVERROR(ENOMEM);
6978
6979 ✗ for (i = 0; i < 3; i++) {
6980 ✗ const int j = mapping[i];
6981 ✗ sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6982 ✗ sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6983 }
6984 ✗ sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6985 ✗ sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6986
6987 ✗ sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6988 ✗ sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6989
6990 ✗ sc->mastering->has_luminance = 1;
6991 ✗ sc->mastering->has_primaries = 1;
6992
6993 ✗ return 0;
6994 }
6995
6996 ✗ static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6997 {
6998 MOVStreamContext *sc;
6999 int version;
7000
7001 ✗ if (c->fc->nb_streams < 1)
7002 ✗ return AVERROR_INVALIDDATA;
7003
7004 ✗ sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7005
7006 ✗ if (atom.size < 5) {
7007 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
7008 ✗ return AVERROR_INVALIDDATA;
7009 }
7010
7011 ✗ version = avio_r8(pb);
7012 ✗ if (version) {
7013 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
7014 ✗ return 0;
7015 }
7016 ✗ avio_skip(pb, 3); /* flags */
7017
7018 ✗ if (sc->coll){
7019 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
7020 ✗ return 0;
7021 }
7022
7023 ✗ sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
7024 ✗ if (!sc->coll)
7025 ✗ return AVERROR(ENOMEM);
7026
7027 ✗ sc->coll->MaxCLL = avio_rb16(pb);
7028 ✗ sc->coll->MaxFALL = avio_rb16(pb);
7029
7030 ✗ return 0;
7031 }
7032
7033 ✗ static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7034 {
7035 MOVStreamContext *sc;
7036
7037 ✗ if (c->fc->nb_streams < 1)
7038 ✗ return AVERROR_INVALIDDATA;
7039
7040 ✗ sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7041
7042 ✗ if (atom.size < 4) {
7043 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
7044 ✗ return AVERROR_INVALIDDATA;
7045 }
7046
7047 ✗ if (sc->coll){
7048 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
7049 ✗ return 0;
7050 }
7051
7052 ✗ sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
7053 ✗ if (!sc->coll)
7054 ✗ return AVERROR(ENOMEM);
7055
7056 ✗ sc->coll->MaxCLL = avio_rb16(pb);
7057 ✗ sc->coll->MaxFALL = avio_rb16(pb);
7058
7059 ✗ return 0;
7060 }
7061
7062 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7063 {
7064 MOVStreamContext *sc;
7065 4 const int illuminance_den = 10000;
7066 4 const int ambient_den = 50000;
7067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
7068 ✗ return AVERROR_INVALIDDATA;
7069 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7070
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
7071 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
7072 ✗ return AVERROR_INVALIDDATA;
7073 }
7074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
7075 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
7076 ✗ return 0;
7077 }
7078 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
7079
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
7080 ✗ return AVERROR(ENOMEM);
7081 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
7082 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
7083 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
7084 4 return 0;
7085 }
7086
7087 3 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7088 {
7089 AVStream *st;
7090 MOVStreamContext *sc;
7091 enum AVStereo3DType type;
7092 int mode;
7093
7094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7095 ✗ return 0;
7096
7097 3 st = c->fc->streams[c->fc->nb_streams - 1];
7098 3 sc = st->priv_data;
7099
7100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 5) {
7101 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
7102 ✗ return AVERROR_INVALIDDATA;
7103 }
7104
7105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->stereo3d)
7106 ✗ return AVERROR_INVALIDDATA;
7107
7108 3 avio_skip(pb, 4); /* version + flags */
7109
7110 3 mode = avio_r8(pb);
7111
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
3 switch (mode) {
7112 1 case 0:
7113 1 type = AV_STEREO3D_2D;
7114 1 break;
7115 ✗ case 1:
7116 ✗ type = AV_STEREO3D_TOPBOTTOM;
7117 ✗ break;
7118 2 case 2:
7119 2 type = AV_STEREO3D_SIDEBYSIDE;
7120 2 break;
7121 ✗ default:
7122 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
7123 ✗ return 0;
7124 }
7125
7126 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7128 ✗ return AVERROR(ENOMEM);
7129
7130 3 sc->stereo3d->type = type;
7131 3 return 0;
7132 }
7133
7134 ✗ static int mov_read_pack(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7135 {
7136 AVStream *st;
7137 MOVStreamContext *sc;
7138 ✗ int size = 0;
7139 int64_t remaining;
7140 ✗ uint32_t tag = 0;
7141 ✗ enum AVStereo3DType type = AV_STEREO3D_2D;
7142
7143 ✗ if (c->fc->nb_streams < 1)
7144 ✗ return 0;
7145
7146 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
7147 ✗ sc = st->priv_data;
7148
7149 ✗ remaining = atom.size;
7150 ✗ while (remaining > 0) {
7151 ✗ size = avio_rb32(pb);
7152 ✗ if (size < 8 || size > remaining ) {
7153 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid child size in pack box\n");
7154 ✗ return AVERROR_INVALIDDATA;
7155 }
7156
7157 ✗ tag = avio_rl32(pb);
7158 ✗ switch (tag) {
7159 ✗ case MKTAG('p','k','i','n'): {
7160 ✗ if (size != 16) {
7161 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of pkin box: %d\n", size);
7162 ✗ return AVERROR_INVALIDDATA;
7163 }
7164 ✗ avio_skip(pb, 1); // version
7165 ✗ avio_skip(pb, 3); // flags
7166
7167 ✗ tag = avio_rl32(pb);
7168 ✗ switch (tag) {
7169 ✗ case MKTAG('s','i','d','e'):
7170 ✗ type = AV_STEREO3D_SIDEBYSIDE;
7171 ✗ break;
7172 ✗ case MKTAG('o','v','e','r'):
7173 ✗ type = AV_STEREO3D_TOPBOTTOM;
7174 ✗ break;
7175 ✗ case 0:
7176 // This means value will be set in another layer
7177 ✗ break;
7178 ✗ default:
7179 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pkin: %s\n",
7180 ✗ av_fourcc2str(tag));
7181 ✗ avio_skip(pb, size - 8);
7182 ✗ break;
7183 }
7184
7185 ✗ break;
7186 }
7187 ✗ default:
7188 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pack: %s\n",
7189 ✗ av_fourcc2str(tag));
7190 ✗ avio_skip(pb, size - 8);
7191 ✗ break;
7192 }
7193 ✗ remaining -= size;
7194 }
7195
7196 ✗ if (remaining != 0) {
7197 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken pack box\n");
7198 ✗ return AVERROR_INVALIDDATA;
7199 }
7200
7201 ✗ if (type == AV_STEREO3D_2D)
7202 ✗ return 0;
7203
7204 ✗ if (!sc->stereo3d) {
7205 ✗ sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7206 ✗ if (!sc->stereo3d)
7207 ✗ return AVERROR(ENOMEM);
7208 }
7209
7210 ✗ sc->stereo3d->type = type;
7211
7212 ✗ return 0;
7213 }
7214
7215 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7216 {
7217 AVStream *st;
7218 MOVStreamContext *sc;
7219 int size, version, layout;
7220 int32_t yaw, pitch, roll;
7221 1 uint32_t l = 0, t = 0, r = 0, b = 0;
7222 1 uint32_t tag, padding = 0;
7223 enum AVSphericalProjection projection;
7224
7225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
7226 ✗ return 0;
7227
7228 1 st = c->fc->streams[c->fc->nb_streams - 1];
7229 1 sc = st->priv_data;
7230
7231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
7232 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
7233 ✗ return AVERROR_INVALIDDATA;
7234 }
7235
7236 1 size = avio_rb32(pb);
7237
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (size <= 12 || size > atom.size)
7238 ✗ return AVERROR_INVALIDDATA;
7239
7240 1 tag = avio_rl32(pb);
7241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
7242 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
7243 ✗ return 0;
7244 }
7245 1 version = avio_r8(pb);
7246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7247 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7248 version);
7249 ✗ return 0;
7250 }
7251 1 avio_skip(pb, 3); /* flags */
7252 1 avio_skip(pb, size - 12); /* metadata_source */
7253
7254 1 size = avio_rb32(pb);
7255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7256 ✗ return AVERROR_INVALIDDATA;
7257
7258 1 tag = avio_rl32(pb);
7259
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
7260 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
7261 ✗ return 0;
7262 }
7263
7264 1 size = avio_rb32(pb);
7265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7266 ✗ return AVERROR_INVALIDDATA;
7267
7268 1 tag = avio_rl32(pb);
7269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
7270 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
7271 ✗ return 0;
7272 }
7273 1 version = avio_r8(pb);
7274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7275 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7276 version);
7277 ✗ return 0;
7278 }
7279 1 avio_skip(pb, 3); /* flags */
7280
7281 /* 16.16 fixed point */
7282 1 yaw = avio_rb32(pb);
7283 1 pitch = avio_rb32(pb);
7284 1 roll = avio_rb32(pb);
7285
7286 1 size = avio_rb32(pb);
7287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7288 ✗ return AVERROR_INVALIDDATA;
7289
7290 1 tag = avio_rl32(pb);
7291 1 version = avio_r8(pb);
7292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7293 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7294 version);
7295 ✗ return 0;
7296 }
7297 1 avio_skip(pb, 3); /* flags */
7298
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
7299 ✗ case MKTAG('c','b','m','p'):
7300 ✗ layout = avio_rb32(pb);
7301 ✗ if (layout) {
7302 ✗ av_log(c->fc, AV_LOG_WARNING,
7303 "Unsupported cubemap layout %d\n", layout);
7304 ✗ return 0;
7305 }
7306 ✗ projection = AV_SPHERICAL_CUBEMAP;
7307 ✗ padding = avio_rb32(pb);
7308 ✗ break;
7309 1 case MKTAG('e','q','u','i'):
7310 1 t = avio_rb32(pb);
7311 1 b = avio_rb32(pb);
7312 1 l = avio_rb32(pb);
7313 1 r = avio_rb32(pb);
7314
7315
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (b >= UINT_MAX - t || r >= UINT_MAX - l) {
7316 ✗ av_log(c->fc, AV_LOG_ERROR,
7317 "Invalid bounding rectangle coordinates "
7318 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
7319 ✗ return AVERROR_INVALIDDATA;
7320 }
7321
7322
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1 if (l || t || r || b)
7323 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
7324 else
7325 ✗ projection = AV_SPHERICAL_EQUIRECTANGULAR;
7326 1 break;
7327 ✗ default:
7328 ✗ av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
7329 ✗ return 0;
7330 }
7331
7332 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
7334 ✗ return AVERROR(ENOMEM);
7335
7336 1 sc->spherical->projection = projection;
7337
7338 1 sc->spherical->yaw = yaw;
7339 1 sc->spherical->pitch = pitch;
7340 1 sc->spherical->roll = roll;
7341
7342 1 sc->spherical->padding = padding;
7343
7344 1 sc->spherical->bound_left = l;
7345 1 sc->spherical->bound_top = t;
7346 1 sc->spherical->bound_right = r;
7347 1 sc->spherical->bound_bottom = b;
7348
7349 1 return 0;
7350 }
7351
7352 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7353 {
7354 AVStream *st;
7355 MOVStreamContext *sc;
7356 int size;
7357 uint32_t tag;
7358 enum AVSphericalProjection projection;
7359
7360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7361 ✗ return 0;
7362
7363 3 st = c->fc->streams[c->fc->nb_streams - 1];
7364 3 sc = st->priv_data;
7365
7366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 16) {
7367 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
7368 ✗ return AVERROR_INVALIDDATA;
7369 }
7370
7371 3 size = avio_rb32(pb);
7372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size < 16) {
7373 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
7374 ✗ return AVERROR_INVALIDDATA;
7375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (size > 16) {
7376 ✗ av_log(c->fc, AV_LOG_WARNING, "Box has more bytes (%d) than prji box required (16) \n", size);
7377 }
7378
7379 3 tag = avio_rl32(pb);
7380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
7381 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: %s\n",
7382 ✗ av_fourcc2str(tag));
7383 ✗ return AVERROR_INVALIDDATA;
7384 }
7385
7386 // version and flags, only support (0, 0)
7387 3 unsigned n = avio_rl32(pb);
7388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (n != 0) {
7389 ✗ av_log(c->fc, AV_LOG_ERROR, "prji version %u, flag %u are not supported\n",
7390 n & 0xFF, n >> 8);
7391 ✗ return AVERROR_PATCHWELCOME;
7392 }
7393
7394 3 tag = avio_rl32(pb);
7395
1/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3 switch (tag) {
7396 3 case MKTAG('r','e','c','t'):
7397 3 projection = AV_SPHERICAL_RECTILINEAR;
7398 3 break;
7399 ✗ case MKTAG('e','q','u','i'):
7400 ✗ projection = AV_SPHERICAL_EQUIRECTANGULAR;
7401 ✗ break;
7402 ✗ case MKTAG('h','e','q','u'):
7403 ✗ projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
7404 ✗ break;
7405 ✗ case MKTAG('f','i','s','h'):
7406 ✗ projection = AV_SPHERICAL_FISHEYE;
7407 ✗ break;
7408 ✗ case MKTAG('p','r','i','m'):
7409 ✗ projection = AV_SPHERICAL_PARAMETRIC_IMMERSIVE;
7410 ✗ break;
7411 ✗ default:
7412 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: %s\n", av_fourcc2str(tag));
7413 ✗ return AVERROR_INVALIDDATA;
7414 }
7415
7416 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
7418 ✗ return AVERROR(ENOMEM);
7419
7420 3 sc->spherical->projection = projection;
7421
7422 3 return 0;
7423 }
7424
7425 5 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7426 {
7427 AVStream *st;
7428 MOVStreamContext *sc;
7429 5 int size, flags = 0;
7430 int64_t remaining;
7431 5 uint32_t tag, baseline = 0;
7432 5 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
7433 5 enum AVStereo3DType type = AV_STEREO3D_2D;
7434 5 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
7435 5 AVRational horizontal_disparity_adjustment = { 0, 1 };
7436
7437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
7438 ✗ return 0;
7439
7440 5 st = c->fc->streams[c->fc->nb_streams - 1];
7441 5 sc = st->priv_data;
7442
7443 5 remaining = atom.size;
7444
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 while (remaining > 0) {
7445 11 size = avio_rb32(pb);
7446
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if (size < 8 || size > remaining ) {
7447 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
7448 ✗ return AVERROR_INVALIDDATA;
7449 }
7450
7451 11 tag = avio_rl32(pb);
7452
3/5
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
11 switch (tag) {
7453 5 case MKTAG('s','t','r','i'): {
7454 int has_right, has_left;
7455 uint8_t tmp;
7456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (size != 13) {
7457 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
7458 ✗ return AVERROR_INVALIDDATA;
7459 }
7460 5 avio_skip(pb, 1); // version
7461 5 avio_skip(pb, 3); // flags
7462
7463 5 tmp = avio_r8(pb);
7464
7465 // eye_views_reversed
7466
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (tmp & 8) {
7467 ✗ flags |= AV_STEREO3D_FLAG_INVERT;
7468 }
7469 // has_additional_views
7470 5 if (tmp & 4) {
7471 // skip...
7472 }
7473
7474 5 has_right = tmp & 2; // has_right_eye_view
7475 5 has_left = tmp & 1; // has_left_eye_view
7476
7477
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 if (has_left && has_right)
7478 5 view = AV_STEREO3D_VIEW_PACKED;
7479 ✗ else if (has_left)
7480 ✗ view = AV_STEREO3D_VIEW_LEFT;
7481 ✗ else if (has_right)
7482 ✗ view = AV_STEREO3D_VIEW_RIGHT;
7483
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 if (has_left || has_right)
7484 5 type = AV_STEREO3D_UNSPEC;
7485
7486 5 break;
7487 }
7488 ✗ case MKTAG('h','e','r','o'): {
7489 int tmp;
7490 ✗ if (size != 13) {
7491 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
7492 ✗ return AVERROR_INVALIDDATA;
7493 }
7494 ✗ avio_skip(pb, 1); // version
7495 ✗ avio_skip(pb, 3); // flags
7496
7497 ✗ tmp = avio_r8(pb);
7498 ✗ if (tmp == 0)
7499 ✗ primary_eye = AV_PRIMARY_EYE_NONE;
7500 ✗ else if (tmp == 1)
7501 ✗ primary_eye = AV_PRIMARY_EYE_LEFT;
7502 ✗ else if (tmp == 2)
7503 ✗ primary_eye = AV_PRIMARY_EYE_RIGHT;
7504 else
7505 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
7506
7507 ✗ break;
7508 }
7509 3 case MKTAG('c','a','m','s'): {
7510 uint32_t subtag;
7511 int subsize;
7512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7513 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
7514 ✗ return AVERROR_INVALIDDATA;
7515 }
7516
7517 3 subsize = avio_rb32(pb);
7518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7519 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
7520 ✗ return AVERROR_INVALIDDATA;
7521 }
7522
7523 3 subtag = avio_rl32(pb);
7524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
7525 ✗ av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got %s\n",
7526 ✗ av_fourcc2str(subtag));
7527 ✗ return AVERROR_INVALIDDATA;
7528 }
7529
7530 3 avio_skip(pb, 1); // version
7531 3 avio_skip(pb, 3); // flags
7532
7533 3 baseline = avio_rb32(pb);
7534
7535 3 break;
7536 }
7537 3 case MKTAG('c','m','f','y'): {
7538 uint32_t subtag;
7539 int subsize;
7540 int32_t adjustment;
7541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7542 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
7543 ✗ return AVERROR_INVALIDDATA;
7544 }
7545
7546 3 subsize = avio_rb32(pb);
7547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7548 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
7549 ✗ return AVERROR_INVALIDDATA;
7550 }
7551
7552 3 subtag = avio_rl32(pb);
7553
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
7554 ✗ av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got %s\n",
7555 ✗ av_fourcc2str(subtag));
7556 ✗ return AVERROR_INVALIDDATA;
7557 }
7558
7559 3 avio_skip(pb, 1); // version
7560 3 avio_skip(pb, 3); // flags
7561
7562 3 adjustment = (int32_t) avio_rb32(pb);
7563
7564 3 horizontal_disparity_adjustment.num = (int) adjustment;
7565 3 horizontal_disparity_adjustment.den = 10000;
7566
7567 3 break;
7568 }
7569 ✗ default:
7570 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: %s\n",
7571 ✗ av_fourcc2str(tag));
7572 ✗ avio_skip(pb, size - 8);
7573 ✗ break;
7574 }
7575 11 remaining -= size;
7576 }
7577
7578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (remaining != 0) {
7579 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
7580 ✗ return AVERROR_INVALIDDATA;
7581 }
7582
7583
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (type == AV_STEREO3D_2D)
7584 ✗ return 0;
7585
7586
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (!sc->stereo3d) {
7587 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7589 ✗ return AVERROR(ENOMEM);
7590 }
7591
7592 5 sc->stereo3d->flags = flags;
7593 /* eyes/stri only records packed vs single-eye, not SBS/TB. Keep a more
7594 * specific type already set by st3d. */
7595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (type != AV_STEREO3D_UNSPEC)
7596 ✗ sc->stereo3d->type = type;
7597
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 else if (sc->stereo3d->type == AV_STEREO3D_2D)
7598 3 sc->stereo3d->type = type;
7599 5 sc->stereo3d->view = view;
7600 5 sc->stereo3d->primary_eye = primary_eye;
7601 5 sc->stereo3d->baseline = baseline;
7602 5 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
7603
7604 5 return 0;
7605 }
7606
7607 5 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7608 {
7609 int size;
7610 int64_t remaining;
7611 uint32_t tag;
7612
7613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
7614 ✗ return 0;
7615
7616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (atom.size < 8) {
7617 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
7618 ✗ return AVERROR_INVALIDDATA;
7619 }
7620
7621 5 remaining = atom.size;
7622
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5 times.
13 while (remaining > 0) {
7623 8 size = avio_rb32(pb);
7624
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (size < 8 || size > remaining ) {
7625 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
7626 ✗ return AVERROR_INVALIDDATA;
7627 }
7628
7629 8 tag = avio_rl32(pb);
7630
2/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 switch (tag) {
7631 3 case MKTAG('p','r','o','j'): {
7632 3 MOVAtom proj = { tag, size - 8 };
7633 3 int ret = mov_read_vexu_proj(c, pb, proj);
7634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7635 ✗ return ret;
7636 3 break;
7637 }
7638 5 case MKTAG('e','y','e','s'): {
7639 5 MOVAtom eyes = { tag, size - 8 };
7640 5 int ret = mov_read_eyes(c, pb, eyes);
7641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
7642 ✗ return ret;
7643 5 break;
7644 }
7645 ✗ case MKTAG('p','a','c','k'): {
7646 ✗ MOVAtom pack = { tag, size - 8 };
7647 ✗ int ret = mov_read_pack(c, pb, pack);
7648 ✗ if (ret < 0)
7649 ✗ return ret;
7650 ✗ break;
7651 }
7652 ✗ default:
7653 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: %s\n",
7654 ✗ av_fourcc2str(tag));
7655 ✗ avio_skip(pb, size - 8);
7656 ✗ break;
7657 }
7658 8 remaining -= size;
7659 }
7660
7661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (remaining != 0) {
7662 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7663 ✗ return AVERROR_INVALIDDATA;
7664 }
7665
7666 5 return 0;
7667 }
7668
7669 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7670 {
7671 AVStream *st;
7672 MOVStreamContext *sc;
7673
7674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7675 ✗ return 0;
7676
7677 3 st = c->fc->streams[c->fc->nb_streams - 1];
7678 3 sc = st->priv_data;
7679
7680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7681 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7682 ✗ return AVERROR_INVALIDDATA;
7683 }
7684
7685
7686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7687 ✗ sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7688 ✗ if (!sc->stereo3d)
7689 ✗ return AVERROR(ENOMEM);
7690 }
7691
7692 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7693 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7694
7695 3 return 0;
7696 }
7697
7698 ✗ static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7699 {
7700 ✗ int ret = 0;
7701 ✗ uint8_t *buffer = av_malloc(len + 1);
7702 const char *val;
7703
7704 ✗ if (!buffer)
7705 ✗ return AVERROR(ENOMEM);
7706 ✗ buffer[len] = '\0';
7707
7708 ✗ ret = ffio_read_size(pb, buffer, len);
7709 ✗ if (ret < 0)
7710 ✗ goto out;
7711
7712 /* Check for mandatory keys and values, try to support XML as best-effort */
7713 ✗ if (!sc->spherical &&
7714 ✗ av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7715 ✗ (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7716 ✗ av_stristr(val, "true") &&
7717 ✗ (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7718 ✗ av_stristr(val, "true") &&
7719 ✗ (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7720 ✗ av_stristr(val, "equirectangular")) {
7721 ✗ sc->spherical = av_spherical_alloc(&sc->spherical_size);
7722 ✗ if (!sc->spherical)
7723 ✗ goto out;
7724
7725 ✗ sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7726
7727 ✗ if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7728 enum AVStereo3DType mode;
7729
7730 ✗ if (av_stristr(buffer, "left-right"))
7731 ✗ mode = AV_STEREO3D_SIDEBYSIDE;
7732 ✗ else if (av_stristr(buffer, "top-bottom"))
7733 ✗ mode = AV_STEREO3D_TOPBOTTOM;
7734 else
7735 ✗ mode = AV_STEREO3D_2D;
7736
7737 ✗ sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7738 ✗ if (!sc->stereo3d)
7739 ✗ goto out;
7740
7741 ✗ sc->stereo3d->type = mode;
7742 }
7743
7744 /* orientation */
7745 ✗ val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7746 ✗ if (val)
7747 ✗ sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7748 ✗ val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7749 ✗ if (val)
7750 ✗ sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7751 ✗ val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7752 ✗ if (val)
7753 ✗ sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7754 }
7755
7756 ✗ out:
7757 ✗ av_free(buffer);
7758 ✗ return ret;
7759 }
7760
7761 69 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7762 {
7763 AVStream *st;
7764 MOVStreamContext *sc;
7765 int64_t ret;
7766 AVUUID uuid;
7767 static const AVUUID uuid_isml_manifest = {
7768 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7769 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7770 };
7771 static const AVUUID uuid_xmp = {
7772 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7773 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7774 };
7775 static const AVUUID uuid_spherical = {
7776 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7777 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7778 };
7779
7780
2/4
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
69 if (atom.size < AV_UUID_LEN || atom.size >= FFMIN(INT_MAX, SIZE_MAX))
7781 ✗ return AVERROR_INVALIDDATA;
7782
7783
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 66 times.
69 if (c->fc->nb_streams < 1)
7784 3 return 0;
7785 66 st = c->fc->streams[c->fc->nb_streams - 1];
7786 66 sc = st->priv_data;
7787
7788 66 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
7790 ✗ return ret;
7791
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7792 uint8_t *buffer, *ptr;
7793 char *endptr;
7794 ✗ size_t len = atom.size - AV_UUID_LEN;
7795
7796 ✗ if (len < 4) {
7797 ✗ return AVERROR_INVALIDDATA;
7798 }
7799 ✗ ret = avio_skip(pb, 4); // zeroes
7800 ✗ len -= 4;
7801
7802 ✗ buffer = av_mallocz(len + 1);
7803 ✗ if (!buffer) {
7804 ✗ return AVERROR(ENOMEM);
7805 }
7806 ✗ ret = ffio_read_size(pb, buffer, len);
7807 ✗ if (ret < 0) {
7808 ✗ av_free(buffer);
7809 ✗ return ret;
7810 }
7811
7812 ✗ ptr = buffer;
7813 ✗ while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7814 ✗ ptr += sizeof("systemBitrate=\"") - 1;
7815 ✗ c->bitrates_count++;
7816 ✗ c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7817 ✗ if (!c->bitrates) {
7818 ✗ c->bitrates_count = 0;
7819 ✗ av_free(buffer);
7820 ✗ return AVERROR(ENOMEM);
7821 }
7822 ✗ errno = 0;
7823 ✗ ret = strtol(ptr, &endptr, 10);
7824 ✗ if (ret < 0 || errno || *endptr != '"') {
7825 ✗ c->bitrates[c->bitrates_count - 1] = 0;
7826 } else {
7827 ✗ c->bitrates[c->bitrates_count - 1] = ret;
7828 }
7829 }
7830
7831 ✗ av_free(buffer);
7832
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7833 uint8_t *buffer;
7834 ✗ size_t len = atom.size - AV_UUID_LEN;
7835 ✗ if (c->export_xmp) {
7836 ✗ buffer = av_mallocz(len + 1);
7837 ✗ if (!buffer) {
7838 ✗ return AVERROR(ENOMEM);
7839 }
7840 ✗ ret = ffio_read_size(pb, buffer, len);
7841 ✗ if (ret < 0) {
7842 ✗ av_free(buffer);
7843 ✗ return ret;
7844 }
7845 ✗ buffer[len] = '\0';
7846 ✗ av_dict_set(&c->fc->metadata, "xmp",
7847 buffer, AV_DICT_DONT_STRDUP_VAL);
7848 } else {
7849 // skip all uuid atom, which makes it fast for long uuid-xmp file
7850 ✗ ret = avio_skip(pb, len);
7851 ✗ if (ret < 0)
7852 ✗ return ret;
7853 }
7854
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7855 ✗ size_t len = atom.size - AV_UUID_LEN;
7856 ✗ ret = mov_parse_uuid_spherical(sc, pb, len);
7857 ✗ if (ret < 0)
7858 ✗ return ret;
7859 ✗ if (!sc->spherical)
7860 ✗ av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7861 }
7862
7863 66 return 0;
7864 }
7865
7866 265 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7867 {
7868 int ret;
7869 uint8_t content[16];
7870
7871
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 118 times.
265 if (atom.size < 8)
7872 147 return 0;
7873
7874 118 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (ret < 0)
7876 ✗ return ret;
7877
7878
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 73 times.
118 if ( !c->found_moov
7879
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 23 times.
45 && !c->found_mdat
7880
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 && !memcmp(content, "Anevia\x1A\x1A", 8)
7881 ✗ && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7882 ✗ c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7883 }
7884
7885 118 return 0;
7886 }
7887
7888 42 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7889 {
7890 42 uint32_t format = avio_rl32(pb);
7891 MOVStreamContext *sc;
7892 enum AVCodecID id;
7893 AVStream *st;
7894
7895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (c->fc->nb_streams < 1)
7896 ✗ return 0;
7897 42 st = c->fc->streams[c->fc->nb_streams - 1];
7898 42 sc = st->priv_data;
7899
7900
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 31 times.
42 switch (sc->format)
7901 {
7902 11 case MKTAG('e','n','c','v'): // encrypted video
7903 case MKTAG('e','n','c','a'): // encrypted audio
7904 11 id = mov_codec_id(st, format);
7905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7906 ✗ st->codecpar->codec_id != id) {
7907 ✗ av_log(c->fc, AV_LOG_WARNING,
7908 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7909 ✗ (char*)&format, st->codecpar->codec_id);
7910 ✗ break;
7911 }
7912
7913 11 st->codecpar->codec_id = id;
7914 11 sc->format = format;
7915 11 break;
7916
7917 31 default:
7918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (format != sc->format) {
7919 ✗ av_log(c->fc, AV_LOG_WARNING,
7920 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7921 ✗ (char*)&format, (char*)&sc->format);
7922 }
7923 31 break;
7924 }
7925
7926 42 return 0;
7927 }
7928
7929 /**
7930 * Gets the current encryption info and associated current stream context. If
7931 * we are parsing a track fragment, this will return the specific encryption
7932 * info for this fragment; otherwise this will return the global encryption
7933 * info for the current stream.
7934 */
7935 27 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7936 {
7937 MOVFragmentStreamInfo *frag_stream_info;
7938 AVStream *st;
7939 int i;
7940
7941 27 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7942
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 21 times.
27 if (frag_stream_info) {
7943
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 for (i = 0; i < c->fc->nb_streams; i++) {
7944 6 *sc = c->fc->streams[i]->priv_data;
7945
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if ((*sc)->id == frag_stream_info->id) {
7946 6 st = c->fc->streams[i];
7947 6 break;
7948 }
7949 }
7950
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (i == c->fc->nb_streams)
7951 ✗ return 0;
7952 6 *sc = st->priv_data;
7953
7954
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (!frag_stream_info->encryption_index) {
7955 // If this stream isn't encrypted, don't create the index.
7956
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(*sc)->cenc.default_encrypted_sample)
7957 ✗ return 0;
7958 2 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!frag_stream_info->encryption_index)
7960 ✗ return AVERROR(ENOMEM);
7961 }
7962 6 *encryption_index = frag_stream_info->encryption_index;
7963 6 return 1;
7964 } else {
7965 // No current track fragment, using stream level encryption info.
7966
7967
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (c->fc->nb_streams < 1)
7968 ✗ return 0;
7969 21 st = c->fc->streams[c->fc->nb_streams - 1];
7970 21 *sc = st->priv_data;
7971
7972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!(*sc)->cenc.encryption_index) {
7973 // If this stream isn't encrypted, don't create the index.
7974 ✗ if (!(*sc)->cenc.default_encrypted_sample)
7975 ✗ return 0;
7976 ✗ (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7977 ✗ if (!(*sc)->cenc.encryption_index)
7978 ✗ return AVERROR(ENOMEM);
7979 }
7980
7981 21 *encryption_index = (*sc)->cenc.encryption_index;
7982 21 return 1;
7983 }
7984 }
7985
7986 195 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7987 {
7988 int i, ret;
7989 unsigned int subsample_count;
7990 AVSubsampleEncryptionInfo *subsamples;
7991
7992
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!sc->cenc.default_encrypted_sample) {
7993 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7994 ✗ return AVERROR_INVALIDDATA;
7995 }
7996
7997
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
195 if (sc->cenc.per_sample_iv_size || use_subsamples) {
7998 195 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7999
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*sample)
8000 ✗ return AVERROR(ENOMEM);
8001 } else
8002 ✗ *sample = NULL;
8003
8004
1/2
✓ Branch 0 taken 195 times.
✗ Branch 1 not taken.
195 if (sc->cenc.per_sample_iv_size != 0) {
8005
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 195 times.
195 if ((ret = ffio_read_size(pb, (*sample)->iv, sc->cenc.per_sample_iv_size)) < 0) {
8006 ✗ av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
8007 ✗ av_encryption_info_free(*sample);
8008 ✗ *sample = NULL;
8009 ✗ return ret;
8010 }
8011 }
8012
8013
1/2
✓ Branch 0 taken 195 times.
✗ Branch 1 not taken.
195 if (use_subsamples) {
8014 195 subsample_count = avio_rb16(pb);
8015 195 av_free((*sample)->subsamples);
8016 195 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
8017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!(*sample)->subsamples) {
8018 ✗ av_encryption_info_free(*sample);
8019 ✗ *sample = NULL;
8020 ✗ return AVERROR(ENOMEM);
8021 }
8022
8023
3/4
✓ Branch 0 taken 272 times.
✓ Branch 1 taken 195 times.
✓ Branch 2 taken 272 times.
✗ Branch 3 not taken.
467 for (i = 0; i < subsample_count && !pb->eof_reached; i++) {
8024 272 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
8025 272 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
8026 }
8027
8028
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (pb->eof_reached) {
8029 ✗ av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
8030 ✗ av_encryption_info_free(*sample);
8031 ✗ *sample = NULL;
8032 ✗ return AVERROR_INVALIDDATA;
8033 }
8034 195 (*sample)->subsample_count = subsample_count;
8035 }
8036
8037 195 return 0;
8038 }
8039
8040 9 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8041 {
8042 AVEncryptionInfo **encrypted_samples;
8043 MOVEncryptionIndex *encryption_index;
8044 MOVStreamContext *sc;
8045 int use_subsamples, ret;
8046 9 unsigned int sample_count, i, alloc_size = 0;
8047
8048 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8050 ✗ return ret;
8051
8052
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (encryption_index->nb_encrypted_samples) {
8053 // This can happen if we have both saio/saiz and senc atoms.
8054 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
8055 2 return 0;
8056 }
8057
8058 7 avio_r8(pb); /* version */
8059 7 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
8060
8061 7 sample_count = avio_rb32(pb);
8062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
8063 ✗ return AVERROR(ENOMEM);
8064
8065
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 7 times.
154 for (i = 0; i < sample_count; i++) {
8066 147 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
8067 147 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
8068 min_samples * sizeof(*encrypted_samples));
8069
1/2
✓ Branch 0 taken 147 times.
✗ Branch 1 not taken.
147 if (encrypted_samples) {
8070 147 encryption_index->encrypted_samples = encrypted_samples;
8071
8072 147 ret = mov_read_sample_encryption_info(
8073 147 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
8074 } else {
8075 ✗ ret = AVERROR(ENOMEM);
8076 }
8077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
147 if (pb->eof_reached) {
8078 ✗ av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
8079 ✗ if (ret >= 0)
8080 ✗ av_encryption_info_free(encryption_index->encrypted_samples[i]);
8081 ✗ ret = AVERROR_INVALIDDATA;
8082 }
8083
8084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
147 if (ret < 0) {
8085 ✗ for (; i > 0; i--)
8086 ✗ av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
8087 ✗ av_freep(&encryption_index->encrypted_samples);
8088 ✗ return ret;
8089 }
8090 }
8091 7 encryption_index->nb_encrypted_samples = sample_count;
8092
8093 7 return 0;
8094 }
8095
8096 2 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
8097 {
8098 AVEncryptionInfo **sample, **encrypted_samples;
8099 int64_t prev_pos;
8100 size_t sample_count, sample_info_size, i;
8101 2 int ret = 0;
8102 2 unsigned int alloc_size = 0;
8103
8104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->nb_encrypted_samples)
8105 ✗ return 0;
8106 2 sample_count = encryption_index->auxiliary_info_sample_count;
8107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count != 1) {
8108 ✗ av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
8109 ✗ return AVERROR_PATCHWELCOME;
8110 }
8111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
8112 ✗ return AVERROR(ENOMEM);
8113
8114 2 prev_pos = avio_tell(pb);
8115
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
8116
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 avio_seek(pb, encryption_index->auxiliary_offsets[0], SEEK_SET) != encryption_index->auxiliary_offsets[0]) {
8117 ✗ av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
8118 ✗ goto finish;
8119 }
8120
8121
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
50 for (i = 0; i < sample_count && !pb->eof_reached; i++) {
8122 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
8123 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
8124 min_samples * sizeof(*encrypted_samples));
8125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (!encrypted_samples) {
8126 ✗ ret = AVERROR(ENOMEM);
8127 ✗ goto finish;
8128 }
8129 48 encryption_index->encrypted_samples = encrypted_samples;
8130
8131 48 sample = &encryption_index->encrypted_samples[i];
8132 96 sample_info_size = encryption_index->auxiliary_info_default_size
8133 48 ? encryption_index->auxiliary_info_default_size
8134
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 : encryption_index->auxiliary_info_sizes[i];
8135
8136 48 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
8137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0)
8138 ✗ goto finish;
8139 }
8140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
8141 ✗ av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
8142 ✗ ret = AVERROR_INVALIDDATA;
8143 } else {
8144 2 encryption_index->nb_encrypted_samples = sample_count;
8145 }
8146
8147 2 finish:
8148 2 avio_seek(pb, prev_pos, SEEK_SET);
8149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
8150 ✗ for (; i > 0; i--) {
8151 ✗ av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
8152 }
8153 ✗ av_freep(&encryption_index->encrypted_samples);
8154 }
8155 2 return ret;
8156 }
8157
8158 9 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8159 {
8160 MOVEncryptionIndex *encryption_index;
8161 MOVStreamContext *sc;
8162 int ret;
8163 unsigned int sample_count, aux_info_type, aux_info_param;
8164
8165 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8167 ✗ return ret;
8168
8169
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (encryption_index->nb_encrypted_samples) {
8170 // This can happen if we have both saio/saiz and senc atoms.
8171 7 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
8172 7 return 0;
8173 }
8174
8175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_sample_count) {
8176 ✗ av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
8177 ✗ return AVERROR_INVALIDDATA;
8178 }
8179
8180 2 avio_r8(pb); /* version */
8181
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
8182 ✗ aux_info_type = avio_rb32(pb);
8183 ✗ aux_info_param = avio_rb32(pb);
8184 ✗ if (sc->cenc.default_encrypted_sample) {
8185 ✗ if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
8186 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
8187 ✗ return 0;
8188 }
8189 ✗ if (aux_info_param != 0) {
8190 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
8191 ✗ return 0;
8192 }
8193 } else {
8194 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8195 ✗ if ((aux_info_type == MKBETAG('c','e','n','c') ||
8196 ✗ aux_info_type == MKBETAG('c','e','n','s') ||
8197 ✗ aux_info_type == MKBETAG('c','b','c','1') ||
8198 ✗ aux_info_type == MKBETAG('c','b','c','s')) &&
8199 aux_info_param == 0) {
8200 ✗ av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
8201 ✗ return AVERROR_INVALIDDATA;
8202 } else {
8203 ✗ return 0;
8204 }
8205 }
8206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
8207 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8208 ✗ return 0;
8209 }
8210
8211 2 encryption_index->auxiliary_info_default_size = avio_r8(pb);
8212 2 sample_count = avio_rb32(pb);
8213
8214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_default_size == 0) {
8215 ✗ if (sample_count == 0)
8216 ✗ return AVERROR_INVALIDDATA;
8217
8218 ✗ encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
8219 ✗ if (!encryption_index->auxiliary_info_sizes)
8220 ✗ return AVERROR(ENOMEM);
8221
8222 ✗ ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
8223 ✗ if (ret != sample_count) {
8224 ✗ av_freep(&encryption_index->auxiliary_info_sizes);
8225
8226 ✗ if (ret >= 0)
8227 ✗ ret = AVERROR_INVALIDDATA;
8228 ✗ av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
8229 ✗ av_err2str(ret));
8230 ✗ return ret;
8231 }
8232 }
8233 2 encryption_index->auxiliary_info_sample_count = sample_count;
8234
8235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
8236 ✗ return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
8237 }
8238
8239 2 return 0;
8240 }
8241
8242 9 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8243 {
8244 uint64_t *auxiliary_offsets;
8245 MOVEncryptionIndex *encryption_index;
8246 MOVStreamContext *sc;
8247 int i, ret;
8248 unsigned int version, entry_count, aux_info_type, aux_info_param;
8249 9 unsigned int alloc_size = 0;
8250
8251 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8253 ✗ return ret;
8254
8255
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (encryption_index->nb_encrypted_samples) {
8256 // This can happen if we have both saio/saiz and senc atoms.
8257 7 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
8258 7 return 0;
8259 }
8260
8261
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
8262 ✗ av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
8263 ✗ return AVERROR_INVALIDDATA;
8264 }
8265
8266 2 version = avio_r8(pb); /* version */
8267
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
8268 ✗ aux_info_type = avio_rb32(pb);
8269 ✗ aux_info_param = avio_rb32(pb);
8270 ✗ if (sc->cenc.default_encrypted_sample) {
8271 ✗ if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
8272 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
8273 ✗ return 0;
8274 }
8275 ✗ if (aux_info_param != 0) {
8276 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
8277 ✗ return 0;
8278 }
8279 } else {
8280 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8281 ✗ if ((aux_info_type == MKBETAG('c','e','n','c') ||
8282 ✗ aux_info_type == MKBETAG('c','e','n','s') ||
8283 ✗ aux_info_type == MKBETAG('c','b','c','1') ||
8284 ✗ aux_info_type == MKBETAG('c','b','c','s')) &&
8285 aux_info_param == 0) {
8286 ✗ av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
8287 ✗ return AVERROR_INVALIDDATA;
8288 } else {
8289 ✗ return 0;
8290 }
8291 }
8292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
8293 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8294 ✗ return 0;
8295 }
8296
8297 2 entry_count = avio_rb32(pb);
8298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
8299 ✗ return AVERROR(ENOMEM);
8300
8301
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 for (i = 0; i < entry_count && !pb->eof_reached; i++) {
8302
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 unsigned int min_offsets = FFMIN(FFMAX(i + 1, 1024), entry_count);
8303 2 auxiliary_offsets = av_fast_realloc(
8304 2 encryption_index->auxiliary_offsets, &alloc_size,
8305 min_offsets * sizeof(*auxiliary_offsets));
8306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!auxiliary_offsets) {
8307 ✗ av_freep(&encryption_index->auxiliary_offsets);
8308 ✗ return AVERROR(ENOMEM);
8309 }
8310 2 encryption_index->auxiliary_offsets = auxiliary_offsets;
8311
8312
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version == 0) {
8313 2 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
8314 } else {
8315 ✗ encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
8316 }
8317
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (c->frag_index.current >= 0) {
8318 2 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
8319 }
8320 }
8321
8322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
8323 ✗ av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
8324 ✗ av_freep(&encryption_index->auxiliary_offsets);
8325 ✗ return AVERROR_INVALIDDATA;
8326 }
8327
8328 2 encryption_index->auxiliary_offsets_count = entry_count;
8329
8330
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (encryption_index->auxiliary_info_sample_count) {
8331 2 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
8332 }
8333
8334 ✗ return 0;
8335 }
8336
8337 4 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8338 {
8339 AVEncryptionInitInfo *info, *old_init_info;
8340 uint8_t **key_ids;
8341 AVStream *st;
8342 const AVPacketSideData *old_side_data;
8343 uint8_t *side_data, *extra_data;
8344 size_t side_data_size;
8345 4 int ret = 0;
8346 4 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
8347
8348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8349 ✗ return 0;
8350 4 st = c->fc->streams[c->fc->nb_streams-1];
8351
8352 4 version = avio_r8(pb); /* version */
8353 4 avio_rb24(pb); /* flags */
8354
8355 4 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
8356 /* key_id_size */ 16, /* data_size */ 0);
8357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info)
8358 ✗ return AVERROR(ENOMEM);
8359
8360
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
8361 ✗ av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
8362 ✗ goto finish;
8363 }
8364
8365
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (version > 0) {
8366 4 kid_count = avio_rb32(pb);
8367
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
8368 ✗ ret = AVERROR(ENOMEM);
8369 ✗ goto finish;
8370 }
8371
8372
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 for (unsigned int i = 0; i < kid_count && !pb->eof_reached; i++) {
8373 4 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
8374 4 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
8375 min_kid_count * sizeof(*key_ids));
8376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!key_ids) {
8377 ✗ ret = AVERROR(ENOMEM);
8378 ✗ goto finish;
8379 }
8380 4 info->key_ids = key_ids;
8381
8382 4 info->key_ids[i] = av_mallocz(16);
8383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info->key_ids[i]) {
8384 ✗ ret = AVERROR(ENOMEM);
8385 ✗ goto finish;
8386 }
8387 4 info->num_key_ids = i + 1;
8388
8389
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
8390 ✗ av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
8391 ✗ goto finish;
8392 }
8393 }
8394
8395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pb->eof_reached) {
8396 ✗ av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
8397 ✗ ret = AVERROR_INVALIDDATA;
8398 ✗ goto finish;
8399 }
8400 }
8401
8402 4 extra_data_size = avio_rb32(pb);
8403 4 extra_data = av_malloc(extra_data_size);
8404
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!extra_data) {
8405 ✗ ret = AVERROR(ENOMEM);
8406 ✗ goto finish;
8407 }
8408 4 ret = avio_read(pb, extra_data, extra_data_size);
8409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != extra_data_size) {
8410 ✗ av_free(extra_data);
8411
8412 ✗ if (ret >= 0)
8413 ✗ ret = AVERROR_INVALIDDATA;
8414 ✗ goto finish;
8415 }
8416
8417 4 av_freep(&info->data); // malloc(0) may still allocate something.
8418 4 info->data = extra_data;
8419 4 info->data_size = extra_data_size;
8420
8421 // If there is existing initialization data, append to the list.
8422 4 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
8423 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
8424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (old_side_data) {
8425 ✗ old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
8426 ✗ if (old_init_info) {
8427 // Append to the end of the list.
8428 ✗ for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
8429 ✗ if (!cur->next) {
8430 ✗ cur->next = info;
8431 ✗ break;
8432 }
8433 }
8434 ✗ info = old_init_info;
8435 } else {
8436 // Assume existing side-data will be valid, so the only error we could get is OOM.
8437 ✗ ret = AVERROR(ENOMEM);
8438 ✗ goto finish;
8439 }
8440 }
8441
8442 4 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
8443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!side_data) {
8444 ✗ ret = AVERROR(ENOMEM);
8445 ✗ goto finish;
8446 }
8447
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
8448 4 &st->codecpar->nb_coded_side_data,
8449 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
8450 side_data, side_data_size, 0))
8451 ✗ av_free(side_data);
8452
8453 4 finish:
8454 4 av_encryption_init_info_free(info);
8455 4 return ret;
8456 }
8457
8458 11 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8459 {
8460 AVStream *st;
8461 MOVStreamContext *sc;
8462
8463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
8464 ✗ return 0;
8465 11 st = c->fc->streams[c->fc->nb_streams-1];
8466 11 sc = st->priv_data;
8467
8468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (sc->pseudo_stream_id != 0) {
8469 ✗ av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
8470 ✗ return AVERROR_PATCHWELCOME;
8471 }
8472
8473
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
8474 ✗ return AVERROR_INVALIDDATA;
8475
8476 11 avio_rb32(pb); /* version and flags */
8477
8478
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (!sc->cenc.default_encrypted_sample) {
8479 11 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.default_encrypted_sample) {
8481 ✗ return AVERROR(ENOMEM);
8482 }
8483 }
8484
8485 11 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
8486 11 return 0;
8487 }
8488
8489 11 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8490 {
8491 AVStream *st;
8492 MOVStreamContext *sc;
8493 unsigned int version, pattern, is_protected, iv_size;
8494
8495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
8496 ✗ return 0;
8497 11 st = c->fc->streams[c->fc->nb_streams-1];
8498 11 sc = st->priv_data;
8499
8500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (sc->pseudo_stream_id != 0) {
8501 ✗ av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
8502 ✗ return AVERROR_PATCHWELCOME;
8503 }
8504
8505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.default_encrypted_sample) {
8506 ✗ sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8507 ✗ if (!sc->cenc.default_encrypted_sample) {
8508 ✗ return AVERROR(ENOMEM);
8509 }
8510 }
8511
8512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 20)
8513 ✗ return AVERROR_INVALIDDATA;
8514
8515 11 version = avio_r8(pb); /* version */
8516 11 avio_rb24(pb); /* flags */
8517
8518 11 avio_r8(pb); /* reserved */
8519 11 pattern = avio_r8(pb);
8520
8521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (version > 0) {
8522 ✗ sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
8523 ✗ sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
8524 }
8525
8526 11 is_protected = avio_r8(pb);
8527
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
11 if (is_protected && !sc->cenc.encryption_index) {
8528 // The whole stream should be by-default encrypted.
8529 11 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
8530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.encryption_index)
8531 ✗ return AVERROR(ENOMEM);
8532 }
8533 11 iv_size = avio_r8(pb);
8534
3/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
11 if (iv_size != 0 && iv_size != 8 && iv_size != 16) {
8535 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
8536 ✗ return AVERROR_INVALIDDATA;
8537 }
8538 11 sc->cenc.per_sample_iv_size = iv_size;
8539
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (avio_read(pb, sc->cenc.default_encrypted_sample->key_id, 16) != 16) {
8540 ✗ av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
8541 ✗ return AVERROR_INVALIDDATA;
8542 }
8543
8544
3/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 9 times.
11 if (is_protected && !sc->cenc.per_sample_iv_size) {
8545 2 iv_size = avio_r8(pb);
8546
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (iv_size != 8 && iv_size != 16) {
8547 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
8548 ✗ return AVERROR_INVALIDDATA;
8549 }
8550
8551
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_read(pb, sc->cenc.default_encrypted_sample->iv, iv_size) != iv_size) {
8552 ✗ av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
8553 ✗ return AVERROR_INVALIDDATA;
8554 }
8555 }
8556
8557 11 return 0;
8558 }
8559
8560 ✗ static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8561 {
8562 AVStream *st;
8563 int last, type, size, ret;
8564 uint8_t buf[4];
8565
8566 ✗ if (c->fc->nb_streams < 1)
8567 ✗ return 0;
8568 ✗ st = c->fc->streams[c->fc->nb_streams-1];
8569
8570 ✗ if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
8571 ✗ return AVERROR_INVALIDDATA;
8572
8573 /* Check FlacSpecificBox version. */
8574 ✗ if (avio_r8(pb) != 0)
8575 ✗ return AVERROR_INVALIDDATA;
8576
8577 ✗ avio_rb24(pb); /* Flags */
8578
8579 ✗ if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
8580 ✗ av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
8581 ✗ return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
8582 }
8583 ✗ flac_parse_block_header(buf, &last, &type, &size);
8584
8585 ✗ if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
8586 ✗ av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
8587 ✗ return AVERROR_INVALIDDATA;
8588 }
8589
8590 ✗ ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
8591 ✗ if (ret < 0)
8592 ✗ return ret;
8593
8594 ✗ if (!last)
8595 ✗ av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
8596
8597 ✗ return 0;
8598 }
8599
8600 11 static int get_key_from_kid(uint8_t* out, int len, MOVContext *c, AVEncryptionInfo *sample) {
8601 AVDictionaryEntry *key_entry_hex;
8602 char kid_hex[16*2+1];
8603
8604
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
11 if (c->decryption_default_key && c->decryption_default_key_len != len) {
8605 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid default decryption key length: got %d, expected %d\n", c->decryption_default_key_len, len);
8606 ✗ return -1;
8607 }
8608
8609
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
11 if (!c->decryption_keys) {
8610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 av_assert0(c->decryption_default_key);
8611 8 memcpy(out, c->decryption_default_key, len);
8612 8 return 0;
8613 }
8614
8615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sample->key_id_size != 16) {
8616 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid key ID size: got %u, expected 16\n", sample->key_id_size);
8617 ✗ return -1;
8618 }
8619
8620 3 ff_data_to_hex(kid_hex, sample->key_id, 16, 1);
8621 3 key_entry_hex = av_dict_get(c->decryption_keys, kid_hex, NULL, AV_DICT_DONT_STRDUP_KEY|AV_DICT_DONT_STRDUP_VAL);
8622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!key_entry_hex) {
8623 ✗ if (!c->decryption_default_key) {
8624 ✗ av_log(c->fc, AV_LOG_ERROR, "unable to find KID %s\n", kid_hex);
8625 ✗ return -1;
8626 }
8627 ✗ memcpy(out, c->decryption_default_key, len);
8628 ✗ return 0;
8629 }
8630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (strlen(key_entry_hex->value) != len*2) {
8631 ✗ return -1;
8632 }
8633 3 ff_hex_to_data(out, key_entry_hex->value);
8634 3 return 0;
8635 }
8636
8637 341 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8638 {
8639 int i, ret;
8640 int bytes_of_protected_data;
8641 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8642
8643
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 330 times.
341 if (!sc->cenc.aes_ctr) {
8644 11 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0) {
8646 ✗ return ret;
8647 }
8648
8649 /* initialize the cipher */
8650 11 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.aes_ctr) {
8652 ✗ return AVERROR(ENOMEM);
8653 }
8654
8655 11 ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0) {
8657 ✗ return ret;
8658 }
8659 }
8660
8661 341 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8662
8663
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 245 times.
341 if (!sample->subsample_count) {
8664 /* decrypt the whole packet */
8665 96 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8666 96 return 0;
8667 }
8668
8669
2/2
✓ Branch 0 taken 321 times.
✓ Branch 1 taken 245 times.
566 for (i = 0; i < sample->subsample_count; i++) {
8670
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 321 times.
321 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8671 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8672 ✗ return AVERROR_INVALIDDATA;
8673 }
8674
8675 /* skip the clear bytes */
8676 321 input += sample->subsamples[i].bytes_of_clear_data;
8677 321 size -= sample->subsamples[i].bytes_of_clear_data;
8678
8679 /* decrypt the encrypted bytes */
8680
8681 321 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
8682 321 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
8683
8684 321 input += bytes_of_protected_data;
8685 321 size -= bytes_of_protected_data;
8686 }
8687
8688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
245 if (size > 0) {
8689 ✗ av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8690 ✗ return AVERROR_INVALIDDATA;
8691 }
8692
8693 245 return 0;
8694 }
8695
8696 ✗ static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8697 {
8698 int i, ret;
8699 int num_of_encrypted_blocks;
8700 uint8_t iv[16];
8701 uint8_t decryption_key[16];
8702
8703 ✗ if (!sc->cenc.aes_ctx) {
8704 ✗ ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8705 ✗ if (ret < 0) {
8706 ✗ return ret;
8707 }
8708
8709 /* initialize the cipher */
8710 ✗ sc->cenc.aes_ctx = av_aes_alloc();
8711 ✗ if (!sc->cenc.aes_ctx) {
8712 ✗ return AVERROR(ENOMEM);
8713 }
8714
8715 ✗ ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8716 ✗ if (ret < 0) {
8717 ✗ return ret;
8718 }
8719 }
8720
8721 ✗ memcpy(iv, sample->iv, 16);
8722
8723 /* whole-block full sample encryption */
8724 ✗ if (!sample->subsample_count) {
8725 /* decrypt the whole packet */
8726 ✗ av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8727 ✗ return 0;
8728 }
8729
8730 ✗ for (i = 0; i < sample->subsample_count; i++) {
8731 ✗ if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8732 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8733 ✗ return AVERROR_INVALIDDATA;
8734 }
8735
8736 ✗ if (sample->subsamples[i].bytes_of_protected_data % 16) {
8737 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8738 ✗ return AVERROR_INVALIDDATA;
8739 }
8740
8741 /* skip the clear bytes */
8742 ✗ input += sample->subsamples[i].bytes_of_clear_data;
8743 ✗ size -= sample->subsamples[i].bytes_of_clear_data;
8744
8745 /* decrypt the encrypted bytes */
8746 ✗ num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8747 ✗ if (num_of_encrypted_blocks > 0) {
8748 ✗ av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8749 }
8750 ✗ input += sample->subsamples[i].bytes_of_protected_data;
8751 ✗ size -= sample->subsamples[i].bytes_of_protected_data;
8752 }
8753
8754 ✗ if (size > 0) {
8755 ✗ av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8756 ✗ return AVERROR_INVALIDDATA;
8757 }
8758
8759 ✗ return 0;
8760 }
8761
8762 ✗ static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8763 {
8764 int i, ret, rem_bytes;
8765 uint8_t *data;
8766 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8767
8768 ✗ if (!sc->cenc.aes_ctr) {
8769 ✗ ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8770 ✗ if (ret < 0) {
8771 ✗ return ret;
8772 }
8773
8774 /* initialize the cipher */
8775 ✗ sc->cenc.aes_ctr = av_aes_ctr_alloc();
8776 ✗ if (!sc->cenc.aes_ctr) {
8777 ✗ return AVERROR(ENOMEM);
8778 }
8779
8780 ✗ ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8781 ✗ if (ret < 0) {
8782 ✗ return ret;
8783 }
8784 }
8785
8786 ✗ av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8787
8788 /* whole-block full sample encryption */
8789 ✗ if (!sample->subsample_count) {
8790 /* decrypt the whole packet */
8791 ✗ av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8792 ✗ return 0;
8793 ✗ } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8794 ✗ av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8795 ✗ return AVERROR_INVALIDDATA;
8796 }
8797
8798 ✗ for (i = 0; i < sample->subsample_count; i++) {
8799 ✗ if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8800 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8801 ✗ return AVERROR_INVALIDDATA;
8802 }
8803
8804 /* skip the clear bytes */
8805 ✗ input += sample->subsamples[i].bytes_of_clear_data;
8806 ✗ size -= sample->subsamples[i].bytes_of_clear_data;
8807
8808 /* decrypt the encrypted bytes */
8809 ✗ data = input;
8810 ✗ rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8811 ✗ while (rem_bytes > 0) {
8812 ✗ if (rem_bytes < 16*sample->crypt_byte_block) {
8813 ✗ break;
8814 }
8815 ✗ av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8816 ✗ data += 16*sample->crypt_byte_block;
8817 ✗ rem_bytes -= 16*sample->crypt_byte_block;
8818 ✗ data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8819 ✗ rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8820 }
8821 ✗ input += sample->subsamples[i].bytes_of_protected_data;
8822 ✗ size -= sample->subsamples[i].bytes_of_protected_data;
8823 }
8824
8825 ✗ if (size > 0) {
8826 ✗ av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8827 ✗ return AVERROR_INVALIDDATA;
8828 }
8829
8830 ✗ return 0;
8831 }
8832
8833 ✗ static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8834 {
8835 int i, ret, rem_bytes;
8836 uint8_t iv[16];
8837 uint8_t *data;
8838 uint8_t decryption_key[16];
8839
8840 ✗ if (!sc->cenc.aes_ctx) {
8841 ✗ ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8842 ✗ if (ret < 0) {
8843 ✗ return ret;
8844 }
8845
8846 /* initialize the cipher */
8847 ✗ sc->cenc.aes_ctx = av_aes_alloc();
8848 ✗ if (!sc->cenc.aes_ctx) {
8849 ✗ return AVERROR(ENOMEM);
8850 }
8851
8852 ✗ ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8853 ✗ if (ret < 0) {
8854 ✗ return ret;
8855 }
8856 }
8857
8858 /* whole-block full sample encryption */
8859 ✗ if (!sample->subsample_count) {
8860 /* decrypt the whole packet */
8861 ✗ memcpy(iv, sample->iv, 16);
8862 ✗ av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8863 ✗ return 0;
8864 ✗ } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8865 ✗ av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8866 ✗ return AVERROR_INVALIDDATA;
8867 }
8868
8869 ✗ for (i = 0; i < sample->subsample_count; i++) {
8870 ✗ if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8871 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8872 ✗ return AVERROR_INVALIDDATA;
8873 }
8874
8875 /* skip the clear bytes */
8876 ✗ input += sample->subsamples[i].bytes_of_clear_data;
8877 ✗ size -= sample->subsamples[i].bytes_of_clear_data;
8878
8879 /* decrypt the encrypted bytes */
8880 ✗ memcpy(iv, sample->iv, 16);
8881 ✗ data = input;
8882 ✗ rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8883 ✗ while (rem_bytes > 0) {
8884 ✗ if (rem_bytes < 16*sample->crypt_byte_block) {
8885 ✗ break;
8886 }
8887 ✗ av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8888 ✗ data += 16*sample->crypt_byte_block;
8889 ✗ rem_bytes -= 16*sample->crypt_byte_block;
8890 ✗ data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8891 ✗ rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8892 }
8893 ✗ input += sample->subsamples[i].bytes_of_protected_data;
8894 ✗ size -= sample->subsamples[i].bytes_of_protected_data;
8895 }
8896
8897 ✗ if (size > 0) {
8898 ✗ av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8899 ✗ return AVERROR_INVALIDDATA;
8900 }
8901
8902 ✗ return 0;
8903 }
8904
8905 341 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8906 {
8907
3/6
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 341 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 341 times.
✗ Branch 5 not taken.
341 if (sample->scheme == MKBETAG('c','e','n','c') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8908 341 return cenc_scheme_decrypt(c, sc, sample, input, size);
8909 ✗ } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8910 ✗ return cbc1_scheme_decrypt(c, sc, sample, input, size);
8911 ✗ } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8912 ✗ return cens_scheme_decrypt(c, sc, sample, input, size);
8913 ✗ } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8914 ✗ return cbcs_scheme_decrypt(c, sc, sample, input, size);
8915 } else {
8916 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8917 ✗ return AVERROR_INVALIDDATA;
8918 }
8919 }
8920
8921 111614 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8922 {
8923 111614 int current = frag_index->current;
8924
8925
2/2
✓ Branch 0 taken 107816 times.
✓ Branch 1 taken 3798 times.
111614 if (!frag_index->nb_items)
8926 107816 return NULL;
8927
8928 // Check frag_index->current is the right one for pkt. It can out of sync.
8929
2/4
✓ Branch 0 taken 3798 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3798 times.
✗ Branch 3 not taken.
3798 if (current >= 0 && current < frag_index->nb_items) {
8930
2/2
✓ Branch 0 taken 3770 times.
✓ Branch 1 taken 28 times.
3798 if (frag_index->item[current].moof_offset < pkt->pos &&
8931
2/2
✓ Branch 0 taken 611 times.
✓ Branch 1 taken 3159 times.
3770 (current + 1 == frag_index->nb_items ||
8932
2/2
✓ Branch 0 taken 534 times.
✓ Branch 1 taken 77 times.
611 frag_index->item[current + 1].moof_offset > pkt->pos))
8933 3693 return get_frag_stream_info(frag_index, current, id);
8934 }
8935
8936
8937
2/2
✓ Branch 0 taken 4561 times.
✓ Branch 1 taken 10 times.
4571 for (int i = 0; i < frag_index->nb_items; i++) {
8938
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 4466 times.
4561 if (frag_index->item[i].moof_offset > pkt->pos)
8939 95 break;
8940 4466 current = i;
8941 }
8942 105 frag_index->current = current;
8943 105 return get_frag_stream_info(frag_index, current, id);
8944 }
8945
8946 111614 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8947 {
8948 MOVFragmentStreamInfo *frag_stream_info;
8949 MOVEncryptionIndex *encryption_index;
8950 AVEncryptionInfo *encrypted_sample;
8951 int encrypted_index, ret;
8952
8953 111614 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8954 111614 encrypted_index = current_index;
8955 111614 encryption_index = NULL;
8956
2/2
✓ Branch 0 taken 3798 times.
✓ Branch 1 taken 107816 times.
111614 if (frag_stream_info) {
8957 // Note this only supports encryption info in the first sample descriptor.
8958
2/2
✓ Branch 0 taken 3750 times.
✓ Branch 1 taken 48 times.
3798 if (frag_stream_info->stsd_id == 1) {
8959
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3702 times.
3750 if (frag_stream_info->encryption_index) {
8960 48 encrypted_index = current_index - frag_stream_info->index_base;
8961 48 encryption_index = frag_stream_info->encryption_index;
8962 } else {
8963 3702 encryption_index = sc->cenc.encryption_index;
8964 }
8965 }
8966 } else {
8967 107816 encryption_index = sc->cenc.encryption_index;
8968 }
8969
8970
2/2
✓ Branch 0 taken 341 times.
✓ Branch 1 taken 111273 times.
111614 if (encryption_index) {
8971
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 293 times.
341 if (encryption_index->auxiliary_info_sample_count &&
8972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8973 ✗ av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8974 ✗ return AVERROR_INVALIDDATA;
8975 }
8976
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 293 times.
341 if (encryption_index->auxiliary_offsets_count &&
8977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8978 ✗ av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8979 ✗ return AVERROR_INVALIDDATA;
8980 }
8981
8982 341 encrypted_sample = NULL;
8983
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 245 times.
341 if (!encryption_index->nb_encrypted_samples) {
8984 // Full-sample encryption with default settings.
8985 96 encrypted_sample = sc->cenc.default_encrypted_sample;
8986
2/4
✓ Branch 0 taken 245 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 245 times.
✗ Branch 3 not taken.
245 } else if (encrypted_index >= 0 && encrypted_index < encryption_index->nb_encrypted_samples) {
8987 // Per-sample setting override.
8988 245 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8989
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
245 if (!encrypted_sample) {
8990 ✗ encrypted_sample = sc->cenc.default_encrypted_sample;
8991 }
8992 }
8993
8994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
341 if (!encrypted_sample) {
8995 ✗ av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8996 ✗ return AVERROR_INVALIDDATA;
8997 }
8998
8999
3/4
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 146 times.
✓ Branch 2 taken 195 times.
✗ Branch 3 not taken.
341 if (mov->decryption_keys || mov->decryption_default_key) {
9000 341 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
9001 } else {
9002 size_t size;
9003 ✗ uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
9004 ✗ if (!side_data)
9005 ✗ return AVERROR(ENOMEM);
9006 ✗ ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
9007 ✗ if (ret < 0)
9008 ✗ av_free(side_data);
9009 ✗ return ret;
9010 }
9011 }
9012
9013 111273 return 0;
9014 }
9015
9016 ✗ static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9017 {
9018 ✗ const int OPUS_SEEK_PREROLL_MS = 80;
9019 int ret;
9020 AVStream *st;
9021 size_t size;
9022 uint16_t pre_skip;
9023
9024 ✗ if (c->fc->nb_streams < 1)
9025 ✗ return 0;
9026 ✗ st = c->fc->streams[c->fc->nb_streams-1];
9027
9028 ✗ if ((uint64_t)atom.size > (1<<30) || atom.size < 11 || st->codecpar->extradata)
9029 ✗ return AVERROR_INVALIDDATA;
9030
9031 /* Check OpusSpecificBox version. */
9032 ✗ if (avio_r8(pb) != 0) {
9033 ✗ av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
9034 ✗ return AVERROR_INVALIDDATA;
9035 }
9036
9037 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
9038 ✗ size = atom.size + 8;
9039
9040 ✗ if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
9041 ✗ return ret;
9042
9043 ✗ AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
9044 ✗ AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
9045 ✗ AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
9046 ✗ if ((ret = ffio_read_size(pb, st->codecpar->extradata + 9, size - 9)) < 0) {
9047 ✗ av_freep(&st->codecpar->extradata);
9048 ✗ st->codecpar->extradata_size = 0;
9049 ✗ return ret;
9050 }
9051
9052 /* OpusSpecificBox is stored in big-endian, but OpusHead is
9053 little-endian; aside from the preceding magic and version they're
9054 otherwise currently identical. Data after output gain at offset 16
9055 doesn't need to be bytewapped. */
9056 ✗ pre_skip = AV_RB16A(st->codecpar->extradata + 10);
9057 ✗ AV_WL16A(st->codecpar->extradata + 10, pre_skip);
9058 ✗ AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
9059 ✗ AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
9060
9061 ✗ st->codecpar->initial_padding = pre_skip;
9062 ✗ st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
9063 ✗ (AVRational){1, 1000},
9064 ✗ (AVRational){1, 48000});
9065
9066 ✗ return 0;
9067 }
9068
9069 ✗ static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9070 {
9071 AVStream *st;
9072 unsigned format_info;
9073 int channel_assignment, channel_assignment1, channel_assignment2;
9074 int ratebits;
9075 uint64_t chmask;
9076
9077 ✗ if (c->fc->nb_streams < 1)
9078 ✗ return 0;
9079 ✗ st = c->fc->streams[c->fc->nb_streams-1];
9080
9081 ✗ if (atom.size < 10)
9082 ✗ return AVERROR_INVALIDDATA;
9083
9084 ✗ format_info = avio_rb32(pb);
9085
9086 ✗ ratebits = (format_info >> 28) & 0xF;
9087 ✗ channel_assignment1 = (format_info >> 15) & 0x1F;
9088 ✗ channel_assignment2 = format_info & 0x1FFF;
9089 ✗ if (channel_assignment2)
9090 ✗ channel_assignment = channel_assignment2;
9091 else
9092 ✗ channel_assignment = channel_assignment1;
9093
9094 ✗ st->codecpar->frame_size = 40 << (ratebits & 0x7);
9095 ✗ st->codecpar->sample_rate = mlp_samplerate(ratebits);
9096
9097 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
9098 ✗ chmask = truehd_layout(channel_assignment);
9099 ✗ av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
9100
9101 ✗ return 0;
9102 }
9103
9104 11 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9105 {
9106 AVStream *st;
9107 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
9108 int ret;
9109 11 int64_t read_size = atom.size;
9110
9111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
9112 ✗ return 0;
9113 11 st = c->fc->streams[c->fc->nb_streams-1];
9114
9115 // At most 24 bytes
9116 11 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
9117
9118
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
9119 ✗ return ret;
9120
9121 11 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
9122 }
9123
9124 7 static int mov_read_hvce(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9125 {
9126 AVStream *st;
9127 AVPacketSideData *sd;
9128 int ret;
9129
9130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (c->fc->nb_streams < 1)
9131 ✗ return 0;
9132 7 st = c->fc->streams[c->fc->nb_streams - 1];
9133
9134
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (atom.size < 23 || atom.size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
9135 ✗ return AVERROR_INVALIDDATA;
9136
9137 7 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
9138 7 &st->codecpar->nb_coded_side_data,
9139 AV_PKT_DATA_HEVC_CONF,
9140 7 atom.size, 0);
9141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sd)
9142 ✗ return AVERROR(ENOMEM);
9143
9144 7 ret = ffio_read_size(pb, sd->data, atom.size);
9145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
9146 ✗ return ret;
9147
9148 7 return 0;
9149 }
9150
9151 4 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9152 {
9153 AVStream *st;
9154 uint8_t *buf;
9155 int ret, old_size, num_arrays;
9156
9157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
9158 ✗ return 0;
9159 4 st = c->fc->streams[c->fc->nb_streams-1];
9160
9161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!st->codecpar->extradata_size)
9162 // TODO: handle lhvC when present before hvcC
9163 ✗ return 0;
9164
9165
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if (atom.size < 6 || st->codecpar->extradata_size < 23 ||
9166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 atom.size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
9167 ✗ return AVERROR_INVALIDDATA;
9168 }
9169
9170 4 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
9171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!buf)
9172 ✗ return AVERROR(ENOMEM);
9173 4 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
9174
9175 4 ret = ffio_read_size(pb, buf, atom.size);
9176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
9177 ✗ av_free(buf);
9178 ✗ av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
9179 ✗ return 0;
9180 }
9181
9182 4 num_arrays = buf[5];
9183 4 old_size = st->codecpar->extradata_size;
9184 4 atom.size -= 8 /* account for mov_realloc_extradata offsetting */
9185 + 6 /* lhvC bytes before the arrays*/;
9186
9187 4 ret = mov_realloc_extradata(st->codecpar, atom);
9188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
9189 ✗ av_free(buf);
9190 ✗ return ret;
9191 }
9192
9193 4 st->codecpar->extradata[22] += num_arrays;
9194 4 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
9195
9196 4 st->disposition |= AV_DISPOSITION_MULTILAYER;
9197
9198 4 av_free(buf);
9199 4 return 0;
9200 }
9201
9202 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9203 {
9204 4 AVFormatContext *ctx = c->fc;
9205 4 AVStream *st = NULL;
9206 AVBPrint scheme_buf, value_buf;
9207 4 int64_t scheme_str_len = 0, value_str_len = 0;
9208 4 int version, flags, ret = AVERROR_BUG;
9209 4 int64_t size = atom.size;
9210
9211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
9212 // 4 bytes for version + flags, 2x 1 byte for null
9213 ✗ return AVERROR_INVALIDDATA;
9214
9215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
9216 ✗ return 0;
9217 4 st = c->fc->streams[c->fc->nb_streams-1];
9218
9219 4 version = avio_r8(pb);
9220 4 flags = avio_rb24(pb);
9221 4 size -= 4;
9222
9223
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (version != 0 || flags != 0) {
9224 ✗ av_log(ctx, AV_LOG_ERROR,
9225 "Unsupported 'kind' box with version %d, flags: %x",
9226 version, flags);
9227 ✗ return AVERROR_INVALIDDATA;
9228 }
9229
9230 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
9231 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
9232
9233
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((scheme_str_len = ff_read_string_to_bprint_overwrite(pb, &scheme_buf,
9234 size)) < 0) {
9235 ✗ ret = scheme_str_len;
9236 ✗ goto cleanup;
9237 }
9238
9239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
9240 // we need to have another string, even if nullptr.
9241 // we check with + 1 since we expect that if size was not hit,
9242 // an additional null was read.
9243 ✗ ret = AVERROR_INVALIDDATA;
9244 ✗ goto cleanup;
9245 }
9246
9247 4 size -= scheme_str_len + 1;
9248
9249
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((value_str_len = ff_read_string_to_bprint_overwrite(pb, &value_buf,
9250 size)) < 0) {
9251 ✗ ret = value_str_len;
9252 ✗ goto cleanup;
9253 }
9254
9255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
9256 // in case of no trailing null, box is not valid.
9257 ✗ ret = AVERROR_INVALIDDATA;
9258 ✗ goto cleanup;
9259 }
9260
9261 4 av_log(ctx, AV_LOG_TRACE,
9262 "%s stream %d KindBox(scheme: %s, value: %s)\n",
9263 4 av_get_media_type_string(st->codecpar->codec_type),
9264 st->index,
9265 scheme_buf.str, value_buf.str);
9266
9267
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 for (int i = 0; ff_mov_track_kind_table[i].scheme_uri; i++) {
9268 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
9269
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
9270 ✗ continue;
9271
9272
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
9273 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
9274
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
9275 16 continue;
9276
9277 4 st->disposition |= value_map.disposition;
9278 }
9279 }
9280
9281 4 ret = 0;
9282
9283 4 cleanup:
9284
9285 4 av_bprint_finalize(&scheme_buf, NULL);
9286 4 av_bprint_finalize(&value_buf, NULL);
9287
9288 4 return ret;
9289 }
9290
9291 ✗ static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9292 {
9293 AVStream *st;
9294 ✗ AVChannelLayout ch_layout = { 0 };
9295 int ret, i, version, type;
9296 int ambisonic_order, channel_order, normalization, channel_count;
9297 int ambi_channels, non_diegetic_channels;
9298
9299 ✗ if (c->fc->nb_streams < 1)
9300 ✗ return 0;
9301
9302 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
9303
9304 ✗ if (atom.size < 16) {
9305 ✗ av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
9306 ✗ return AVERROR_INVALIDDATA;
9307 }
9308
9309 ✗ version = avio_r8(pb);
9310 ✗ if (version) {
9311 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
9312 ✗ return 0;
9313 }
9314
9315 ✗ type = avio_r8(pb);
9316 ✗ if (type & 0x7f) {
9317 ✗ av_log(c->fc, AV_LOG_WARNING,
9318 "Unsupported ambisonic type %d\n", type & 0x7f);
9319 ✗ return 0;
9320 }
9321 ✗ non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
9322
9323 ✗ ambisonic_order = avio_rb32(pb);
9324
9325 ✗ channel_order = avio_r8(pb);
9326 ✗ if (channel_order) {
9327 ✗ av_log(c->fc, AV_LOG_WARNING,
9328 "Unsupported channel_order %d\n", channel_order);
9329 ✗ return 0;
9330 }
9331
9332 ✗ normalization = avio_r8(pb);
9333 ✗ if (normalization) {
9334 ✗ av_log(c->fc, AV_LOG_WARNING,
9335 "Unsupported normalization %d\n", normalization);
9336 ✗ return 0;
9337 }
9338
9339 ✗ channel_count = avio_rb32(pb);
9340 ✗ if (ambisonic_order < 0 || ambisonic_order > 31 ||
9341 ✗ channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
9342 non_diegetic_channels)) {
9343 ✗ av_log(c->fc, AV_LOG_ERROR,
9344 "Invalid number of channels (%d / %d)\n",
9345 channel_count, ambisonic_order);
9346 ✗ return 0;
9347 }
9348 ✗ ambi_channels = channel_count - non_diegetic_channels;
9349
9350 ✗ ret = av_channel_layout_custom_init(&ch_layout, channel_count);
9351 ✗ if (ret < 0)
9352 ✗ return 0;
9353
9354 ✗ for (i = 0; i < channel_count; i++) {
9355 ✗ unsigned channel = avio_rb32(pb);
9356
9357 ✗ if (channel >= channel_count) {
9358 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
9359 channel, ambisonic_order);
9360 ✗ av_channel_layout_uninit(&ch_layout);
9361 ✗ return 0;
9362 }
9363 ✗ if (channel >= ambi_channels)
9364 ✗ ch_layout.u.map[i].id = channel - ambi_channels;
9365 else
9366 ✗ ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
9367 }
9368
9369 ✗ ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
9370 ✗ if (ret < 0) {
9371 ✗ av_channel_layout_uninit(&ch_layout);
9372 ✗ return 0;
9373 }
9374
9375 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
9376 ✗ st->codecpar->ch_layout = ch_layout;
9377
9378 ✗ return 0;
9379 }
9380
9381 ✗ static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9382 {
9383 AVStream *st;
9384 int version;
9385
9386 ✗ if (c->fc->nb_streams < 1)
9387 ✗ return 0;
9388
9389 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
9390
9391 ✗ if (atom.size < 5) {
9392 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
9393 ✗ return AVERROR_INVALIDDATA;
9394 }
9395
9396 ✗ version = avio_r8(pb);
9397 ✗ if (version) {
9398 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
9399 ✗ return 0;
9400 }
9401
9402 ✗ st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
9403
9404 ✗ return 0;
9405 }
9406
9407 231 static int rb_size(AVIOContext *pb, int64_t *value, int size)
9408 {
9409
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 200 times.
231 if (size == 0)
9410 31 *value = 0;
9411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 else if (size == 1)
9412 ✗ *value = avio_r8(pb);
9413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 else if (size == 2)
9414 ✗ *value = avio_rb16(pb);
9415
1/2
✓ Branch 0 taken 200 times.
✗ Branch 1 not taken.
200 else if (size == 4)
9416 200 *value = avio_rb32(pb);
9417 ✗ else if (size == 8) {
9418 ✗ *value = avio_rb64(pb);
9419 ✗ if (*value < 0)
9420 ✗ return -1;
9421 } else
9422 ✗ return -1;
9423 231 return size;
9424 }
9425
9426 2 static int mov_read_auxc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9427 {
9428 AVBPrint aux_type;
9429 HEIFItem *item;
9430
9431 2 avio_r8(pb); /* version */
9432 2 avio_rb24(pb); /* flags */
9433
9434 2 av_bprint_init(&aux_type, 0, AV_BPRINT_SIZE_AUTOMATIC);
9435 2 ff_read_string_to_bprint_overwrite(pb, &aux_type, atom.size - 4);
9436
9437 2 av_log(c->fc, AV_LOG_TRACE, "auxC: item_id %d, aux_type %s\n",
9438 c->cur_item_id, aux_type.str);
9439
9440 2 item = get_heif_item(c, c->cur_item_id);
9441
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
2 if (item && (av_stristr(aux_type.str, "hdrgainmap")))
9442 2 item->is_gainmap = 1;
9443
9444 2 return 0;
9445 }
9446
9447 20 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9448 {
9449 20 avio_rb32(pb); // version & flags.
9450 20 c->primary_item_id = avio_rb16(pb);
9451 20 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
9452 20 return atom.size;
9453 }
9454
9455 11 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9456 {
9457 11 c->idat_offset = avio_tell(pb);
9458 11 return 0;
9459 }
9460
9461 20 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9462 {
9463 HEIFItem **heif_item;
9464 int version, offset_size, length_size, base_offset_size, index_size;
9465 int item_count, extent_count;
9466 int64_t base_offset, extent_offset, extent_length;
9467 uint8_t value;
9468
9469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (c->found_iloc) {
9470 ✗ av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
9471 ✗ return 0;
9472 }
9473
9474 20 version = avio_r8(pb);
9475 20 avio_rb24(pb); // flags.
9476
9477 20 value = avio_r8(pb);
9478 20 offset_size = (value >> 4) & 0xF;
9479 20 length_size = value & 0xF;
9480 20 value = avio_r8(pb);
9481 20 base_offset_size = (value >> 4) & 0xF;
9482
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 7 times.
20 index_size = !version ? 0 : (value & 0xF);
9483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (index_size) {
9484 ✗ avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
9485 ✗ return AVERROR_PATCHWELCOME;
9486 }
9487
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9488
9489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (item_count > atom.size)
9490 ✗ return AVERROR_INVALIDDATA;
9491
9492 20 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
9493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (!heif_item)
9494 ✗ return AVERROR(ENOMEM);
9495 20 c->heif_item = heif_item;
9496
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2 times.
20 if (item_count > c->nb_heif_item)
9497 18 memset(&c->heif_item[c->nb_heif_item], 0,
9498 18 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
9499 20 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
9500
9501 20 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
9502
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 20 times.
97 for (int i = 0; i < item_count; i++) {
9503 77 HEIFItem *item = NULL;
9504
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9505
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 12 times.
77 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
9506 int j;
9507
9508
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
77 if (avio_feof(pb))
9509 ✗ return AVERROR_INVALIDDATA;
9510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (offset_type > 1) {
9511 ✗ avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
9512 ✗ return AVERROR_PATCHWELCOME;
9513 }
9514
9515 77 avio_rb16(pb); // data_reference_index.
9516
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
77 if (rb_size(pb, &base_offset, base_offset_size) < 0)
9517 ✗ return AVERROR_INVALIDDATA;
9518 77 extent_count = avio_rb16(pb);
9519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (extent_count > 1) {
9520 // For still AVIF images, we only support one extent item.
9521 ✗ avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
9522 ✗ return AVERROR_PATCHWELCOME;
9523 }
9524
9525
2/4
✓ Branch 1 taken 77 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 77 times.
✗ Branch 4 not taken.
154 if (rb_size(pb, &extent_offset, offset_size) < 0 ||
9526 77 rb_size(pb, &extent_length, length_size) < 0 ||
9527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 base_offset > INT64_MAX - extent_offset)
9528 ✗ return AVERROR_INVALIDDATA;
9529
9530
1/2
✓ Branch 0 taken 250 times.
✗ Branch 1 not taken.
250 for (j = 0; j < c->nb_heif_item; j++) {
9531 250 item = c->heif_item[j];
9532
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 193 times.
250 if (!item)
9533 57 item = c->heif_item[j] = av_mallocz(sizeof(*item));
9534
2/2
✓ Branch 0 taken 173 times.
✓ Branch 1 taken 20 times.
193 else if (item->item_id != item_id)
9535 173 continue;
9536 77 break;
9537 }
9538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (!item)
9539 ✗ return AVERROR(ENOMEM);
9540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (j == c->nb_heif_item)
9541 ✗ return AVERROR_INVALIDDATA;
9542
9543 77 item->item_id = item_id;
9544
9545
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 64 times.
77 if (offset_type == 1)
9546 13 item->is_idat_relative = 1;
9547 77 item->extent_length = extent_length;
9548 77 item->extent_offset = base_offset + extent_offset;
9549 77 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, item->item_id %d, offset_type %d, "
9550 "extent_offset %"PRId64", extent_length %"PRId64"\n",
9551 i, item->item_id, offset_type, item->extent_offset, item->extent_length);
9552 }
9553
9554 20 c->found_iloc = 1;
9555 20 return atom.size;
9556 }
9557
9558 77 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9559 {
9560 77 HEIFItem *item = NULL;
9561 AVBPrint item_name;
9562 77 int64_t size = atom.size;
9563 uint32_t item_type;
9564 int item_id;
9565 int i, version, flags, ret;
9566
9567 77 version = avio_r8(pb);
9568 77 flags = avio_rb24(pb);
9569 77 size -= 4;
9570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (size < 0)
9571 ✗ return AVERROR_INVALIDDATA;
9572
9573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (version < 2) {
9574 ✗ avpriv_report_missing_feature(c->fc, "infe version < 2");
9575 ✗ avio_skip(pb, size);
9576 ✗ return 1;
9577 }
9578
9579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
9580 77 avio_rb16(pb); // item_protection_index
9581 77 item_type = avio_rl32(pb);
9582 77 size -= 8;
9583
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (size < 1)
9584 ✗ return AVERROR_INVALIDDATA;
9585
9586 77 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
9587 77 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
9588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (ret < 0) {
9589 ✗ av_bprint_finalize(&item_name, NULL);
9590 ✗ return ret;
9591 }
9592
9593 77 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
9594 77 item_id, av_fourcc2str(item_type), item_name.str);
9595
9596 77 size -= ret + 1;
9597
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 71 times.
77 if (size > 0)
9598 6 avio_skip(pb, size);
9599
9600
1/2
✓ Branch 0 taken 250 times.
✗ Branch 1 not taken.
250 for (i = 0; i < c->nb_heif_item; i++) {
9601 250 item = c->heif_item[i];
9602
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 230 times.
250 if (!item)
9603 20 item = c->heif_item[i] = av_mallocz(sizeof(*item));
9604
2/2
✓ Branch 0 taken 173 times.
✓ Branch 1 taken 57 times.
230 else if (item->item_id != item_id)
9605 173 continue;
9606 77 break;
9607 }
9608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (!item) {
9609 ✗ av_bprint_finalize(&item_name, NULL);
9610 ✗ return AVERROR(ENOMEM);
9611 }
9612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (i == c->nb_heif_item) {
9613 ✗ av_bprint_finalize(&item_name, NULL);
9614 ✗ return AVERROR_INVALIDDATA;
9615 }
9616
9617 77 av_freep(&item->name);
9618
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 21 times.
77 av_bprint_finalize(&item_name, ret ? &item->name : NULL);
9619 77 item->item_id = item_id;
9620 77 item->type = item_type;
9621 77 item->flags = flags;
9622
9623
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 24 times.
77 switch (item_type) {
9624 53 case MKTAG('a','v','0','1'):
9625 case MKTAG('j','p','e','g'):
9626 case MKTAG('h','v','c','1'):
9627 53 ret = heif_add_stream(c, item);
9628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (ret < 0)
9629 ✗ return ret;
9630 53 break;
9631 }
9632
9633 77 return 0;
9634 }
9635
9636 20 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9637 {
9638 HEIFItem **heif_item;
9639 int entry_count;
9640 20 int version, got_stream = 0, ret, i;
9641
9642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (c->found_iinf) {
9643 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
9644 ✗ return 0;
9645 }
9646
9647 20 version = avio_r8(pb);
9648 20 avio_rb24(pb); // flags.
9649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
9650
9651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (entry_count > atom.size)
9652 ✗ return AVERROR_INVALIDDATA;
9653
9654 /* account for the version/flags/entry_count fields already consumed,
9655 * so the per-entry loop below can bound each infe box by what is
9656 * actually left in this iinf box, the same way mov_read_iprp() bounds
9657 * ipco/ipma entries by the remaining iprp size. */
9658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 atom.size -= version ? 8 : 6;
9659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (atom.size < 0)
9660 ✗ return AVERROR_INVALIDDATA;
9661
9662 20 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
9663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (!heif_item)
9664 ✗ return AVERROR(ENOMEM);
9665 20 c->heif_item = heif_item;
9666
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
20 if (entry_count > c->nb_heif_item)
9667 2 memset(&c->heif_item[c->nb_heif_item], 0,
9668 2 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
9669 20 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
9670
9671
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 20 times.
97 for (i = 0; i < entry_count; i++) {
9672 MOVAtom infe;
9673
9674 77 infe.size = avio_rb32(pb);
9675 77 infe.type = avio_rl32(pb);
9676
3/6
✓ Branch 1 taken 77 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 77 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 77 times.
✗ Branch 6 not taken.
77 if (avio_feof(pb) || infe.size < 8 || infe.size > atom.size ||
9677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 infe.type != MKTAG('i','n','f','e')) {
9678 ✗ ret = AVERROR_INVALIDDATA;
9679 ✗ goto fail;
9680 }
9681
9682 77 atom.size -= infe.size;
9683 77 infe.size -= 8;
9684
9685 77 ret = mov_read_infe(c, pb, infe);
9686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (ret < 0)
9687 ✗ goto fail;
9688
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 if (!ret)
9689 77 got_stream = 1;
9690 }
9691
9692 20 c->found_iinf = got_stream;
9693 20 return 0;
9694 ✗ fail:
9695 ✗ for (; i >= 0; i--) {
9696 ✗ HEIFItem *item = c->heif_item[i];
9697
9698 ✗ if (!item)
9699 ✗ continue;
9700
9701 ✗ av_freep(&item->name);
9702 }
9703 ✗ return ret;
9704 }
9705
9706 2 static int mov_read_iref_dimg_tmap(MOVContext *c, AVIOContext *pb,
9707 HEIFItem *item, int version, int entries)
9708 {
9709 2 HEIFGroup *tmap = av_realloc_array(c->heif_group, c->nb_heif_group + 1U,
9710 sizeof(*c->heif_group));
9711 int ret;
9712
9713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!tmap)
9714 ✗ return AVERROR(ENOMEM);
9715 2 c->heif_group = tmap;
9716
9717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (entries != 2) {
9718 ✗ avpriv_report_missing_feature(c->fc, "Derived image item of type %s with an "
9719 "item reference count other than 2",
9720 ✗ av_fourcc2str(item->type));
9721 ✗ return 0;
9722 }
9723
9724 2 tmap = &tmap[c->nb_heif_group];
9725
9726 2 tmap->item_idx_list = NULL; // Not needed
9727 2 tmap->item_id_list = av_malloc_array(entries, sizeof(*tmap->item_id_list));
9728 2 tmap->item_list = av_calloc(entries, sizeof(*tmap->item_list));
9729
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (!tmap->item_id_list || !tmap->item_list) {
9730 ✗ ret = AVERROR(ENOMEM);
9731 ✗ goto fail;
9732 }
9733
9734 /* 'to' item ids */
9735
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < entries; i++) {
9736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 tmap->item_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
9737
9738
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (avio_feof(pb)) {
9739 ✗ ret = AVERROR_INVALIDDATA;
9740 ✗ goto fail;
9741 }
9742 }
9743
9744 2 tmap->nb_items = entries;
9745 2 tmap->item = item;
9746 2 ++c->nb_heif_group;
9747
9748 2 return 0;
9749 ✗ fail:
9750 ✗ av_freep(&tmap->item_id_list);
9751 ✗ av_freep(&tmap->item_list);
9752
9753 ✗ return ret;
9754 }
9755
9756 11 static int mov_read_iref_dimg_grid(MOVContext *c, AVIOContext *pb,
9757 HEIFItem *item, int version, int entries)
9758 {
9759 11 HEIFGroup *grid = av_realloc_array(c->heif_group, c->nb_heif_group + 1U,
9760 sizeof(*c->heif_group));
9761 int ret;
9762
9763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!grid)
9764 ✗ return AVERROR(ENOMEM);
9765 11 c->heif_group = grid;
9766 11 grid = &grid[c->nb_heif_group];
9767
9768 11 grid->item_id_list = av_malloc_array(entries, sizeof(*grid->item_id_list));
9769 11 grid->item_idx_list = av_calloc(entries, sizeof(*grid->item_idx_list));
9770 11 grid->item_list = av_calloc(entries, sizeof(*grid->item_list));
9771
3/6
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 11 times.
11 if (!grid->item_id_list || !grid->item_list || !grid->item_idx_list) {
9772 ✗ ret = AVERROR(ENOMEM);
9773 ✗ goto fail;
9774 }
9775 /* 'to' item ids */
9776
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 11 times.
47 for (int i = 0; i < entries; i++) {
9777
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 grid->item_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
9778
9779
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
36 if (avio_feof(pb)) {
9780 ✗ ret = AVERROR_INVALIDDATA;
9781 ✗ goto fail;
9782 }
9783 }
9784
9785 11 grid->nb_items = entries;
9786 11 grid->item = item;
9787 11 ++c->nb_heif_group;
9788
9789 11 return 0;
9790 ✗ fail:
9791 ✗ av_freep(&grid->item_id_list);
9792 ✗ av_freep(&grid->item_idx_list);
9793 ✗ av_freep(&grid->item_list);
9794
9795 ✗ return ret;
9796 }
9797
9798 13 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
9799 {
9800 13 HEIFItem *item = NULL;
9801 int entries;
9802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9803 int ret;
9804
9805
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 13 times.
15 for (int i = 0; i < c->nb_heif_group; i++) {
9806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->heif_group[i].item->item_id == from_item_id) {
9807 ✗ av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
9808 "referencing the same Derived Image item\n");
9809 ✗ return AVERROR_INVALIDDATA;
9810 }
9811 }
9812
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 for (int i = 0; i < c->nb_heif_item; i++) {
9813
3/4
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 13 times.
59 if (!c->heif_item[i] || c->heif_item[i]->item_id != from_item_id)
9814 46 continue;
9815 13 item = c->heif_item[i];
9816
9817
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 switch (item->type) {
9818 13 case MKTAG('g','r','i','d'):
9819 case MKTAG('i','o','v','l'):
9820 case MKTAG('t','m','a','p'):
9821 13 break;
9822 ✗ default:
9823 ✗ avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
9824 ✗ av_fourcc2str(item->type));
9825 ✗ return 0;
9826 }
9827 13 break;
9828 }
9829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!item) {
9830 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing derived image information\n");
9831 ✗ return AVERROR_INVALIDDATA;
9832 }
9833
9834 13 entries = avio_rb16(pb);
9835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!entries) {
9836 ✗ av_log(c->fc, AV_LOG_ERROR,
9837 "Derived image item references no input images\n");
9838 ✗ return AVERROR_INVALIDDATA;
9839 }
9840
9841 13 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
9842 from_item_id, entries);
9843
9844
2/3
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
13 switch (item->type) {
9845 11 case MKTAG('g','r','i','d'):
9846 case MKTAG('i','o','v','l'):
9847 11 ret = mov_read_iref_dimg_grid(c, pb, item, version, entries);
9848 11 break;
9849 2 case MKTAG('t','m','a','p'):
9850 2 ret = mov_read_iref_dimg_tmap(c, pb, item, version, entries);
9851 2 break;
9852 ✗ default:
9853 ✗ av_unreachable("item->type should have been checked above");
9854 }
9855
9856 13 return ret;
9857 }
9858
9859 10 static int mov_read_iref_cdsc(MOVContext *c, AVIOContext *pb, uint32_t type,
9860 int version, uint32_t size)
9861 {
9862 10 HEIFItem *from_item = NULL;
9863 int entries;
9864
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 int item_id_size = version ? 4 : 2;
9865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9866 10 const HEIFItemRef ref = { type, from_item_id };
9867
9868 10 from_item = get_heif_item(c, from_item_id);
9869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!from_item) {
9870 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing stream referenced by %s iref\n",
9871 ✗ av_fourcc2str(type));
9872 ✗ return AVERROR_INVALIDDATA;
9873 }
9874
9875 10 entries = avio_rb16(pb);
9876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if ((int64_t)entries * item_id_size > (int64_t)size - item_id_size - 2) {
9877 ✗ av_log(c->fc, AV_LOG_ERROR, "iref %s entry count %d exceeds the sub-box size\n",
9878 ✗ av_fourcc2str(type), entries);
9879 ✗ return AVERROR_INVALIDDATA;
9880 }
9881 /* 'to' item ids */
9882
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < entries; i++) {
9883
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 HEIFItem *item = get_heif_item(c, version ? avio_rb32(pb) : avio_rb16(pb));
9884
9885
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (avio_feof(pb))
9886 ✗ return AVERROR_INVALIDDATA;
9887
9888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!item) {
9889 ✗ av_log(c->fc, AV_LOG_WARNING, "Missing stream referenced by %s item\n",
9890 ✗ av_fourcc2str(type));
9891 ✗ continue;
9892 }
9893
9894
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (!av_dynarray2_add((void **)&item->iref_from_list, &item->nb_iref_from_list,
9895 sizeof(*item->iref_from_list), (const uint8_t *)&ref))
9896 ✗ return AVERROR(ENOMEM);
9897 }
9898
9899 10 av_log(c->fc, AV_LOG_TRACE, "%s: from_item_id %d, entries %d\n",
9900 10 av_fourcc2str(type), from_item_id, entries);
9901
9902 10 return 0;
9903 }
9904
9905 9 static int mov_read_iref_auxl(MOVContext *c, AVIOContext *pb, uint32_t type,
9906 int version, uint32_t size)
9907 {
9908 9 HEIFItem *from_item = NULL;
9909 int entries;
9910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 unsigned from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9911
9912 9 from_item = get_heif_item(c, from_item_id);
9913
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!from_item) {
9914 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing item referenced by %s iref\n",
9915 ✗ av_fourcc2str(type));
9916 ✗ return AVERROR_INVALIDDATA;
9917 }
9918
9919 9 entries = avio_rb16(pb);
9920
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (entries != 1) {
9921 ✗ avpriv_report_missing_feature(c->fc, "%s iref with an item reference "
9922 "count other than 1",
9923 ✗ av_fourcc2str(type));
9924 ✗ return 0;
9925 }
9926
9927 /* 'to' item ids */
9928
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for (int i = 0; i < entries; i++) {
9929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 unsigned to_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9930 9 const HEIFItemRef ref = { type, to_item_id };
9931 9 HEIFItem *item = get_heif_item(c, to_item_id);
9932
9933
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 if (avio_feof(pb))
9934 ✗ return AVERROR_INVALIDDATA;
9935
9936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!item) {
9937 ✗ av_log(c->fc, AV_LOG_WARNING, "Missing item referenced by %s iref\n",
9938 ✗ av_fourcc2str(type));
9939 ✗ continue;
9940 }
9941
9942
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 if (!av_dynarray2_add((void **)&from_item->iref_to_list, &from_item->nb_iref_to_list,
9943 sizeof(*from_item->iref_to_list), (const uint8_t *)&ref))
9944 ✗ return AVERROR(ENOMEM);
9945 }
9946
9947 9 av_log(c->fc, AV_LOG_TRACE, "%s: from_item_id %d, entries %d\n",
9948 9 av_fourcc2str(type), from_item_id, entries);
9949
9950 9 return 0;
9951 }
9952
9953 16 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9954 {
9955 16 int version = avio_r8(pb);
9956 int ret;
9957
9958 16 avio_rb24(pb); // flags
9959 16 atom.size -= 4;
9960
9961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (version > 1) {
9962 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
9963 ✗ return 0;
9964 }
9965
9966
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 16 times.
48 while (atom.size) {
9967 32 int64_t next = avio_tell(pb);
9968 32 uint32_t type, size = avio_rb32(pb);
9969
9970
3/6
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 32 times.
32 if (size < 14 || size > atom.size || next > INT64_MAX - size)
9971 ✗ return AVERROR_INVALIDDATA;
9972
9973 32 next += size;
9974 32 type = avio_rl32(pb);
9975
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
32 switch (type) {
9976 13 case MKTAG('d','i','m','g'):
9977 13 ret = mov_read_iref_dimg(c, pb, version);
9978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (ret < 0)
9979 ✗ return ret;
9980 32 break;
9981 10 case MKTAG('c','d','s','c'):
9982 10 ret = mov_read_iref_cdsc(c, pb, type, version, size - 8);
9983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
9984 ✗ return ret;
9985 10 break;
9986 9 case MKTAG('a','u','x','l'):
9987 case MKTAG('t','h','m','b'):
9988 9 ret = mov_read_iref_auxl(c, pb, type, version, size - 8);
9989
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret < 0)
9990 ✗ return ret;
9991 9 break;
9992 ✗ default:
9993 ✗ av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
9994 ✗ av_fourcc2str(type), size);
9995 }
9996
9997 32 atom.size -= size;
9998 32 avio_seek(pb, next, SEEK_SET);
9999 }
10000 16 return 0;
10001 }
10002
10003 66 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10004 {
10005 HEIFItem *item;
10006 uint32_t width, height;
10007
10008 66 avio_r8(pb); /* version */
10009 66 avio_rb24(pb); /* flags */
10010 66 width = avio_rb32(pb);
10011 66 height = avio_rb32(pb);
10012
10013 66 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %"PRIu32", height %"PRIu32"\n",
10014 c->cur_item_id, width, height);
10015
10016
4/8
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 66 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 66 times.
66 if (!width || !height || width > INT_MAX || height > INT_MAX) {
10017 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid ispe dimensions %"PRIu32"x%"PRIu32"\n",
10018 width, height);
10019 ✗ return AVERROR_INVALIDDATA;
10020 }
10021
10022 66 item = get_heif_item(c, c->cur_item_id);
10023
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if (item) {
10024 66 item->width = width;
10025 66 item->height = height;
10026 }
10027
10028 66 return 0;
10029 }
10030
10031 10 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10032 {
10033 HEIFItem *item;
10034 int angle;
10035
10036 10 angle = avio_r8(pb) & 0x3;
10037
10038 10 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
10039 c->cur_item_id, angle);
10040
10041 10 item = get_heif_item(c, c->cur_item_id);
10042
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (item) {
10043 // angle * 90 specifies the angle (in anti-clockwise direction)
10044 // in units of degrees.
10045 10 item->rotation = angle * 90;
10046 }
10047
10048 10 return 0;
10049 }
10050
10051 6 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10052 {
10053 HEIFItem *item;
10054 int axis;
10055
10056 6 axis = avio_r8(pb) & 0x1;
10057
10058 6 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
10059 c->cur_item_id, axis);
10060
10061 6 item = get_heif_item(c, c->cur_item_id);
10062
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
10063 6 item->hflip = axis;
10064 6 item->vflip = !axis;
10065 }
10066
10067 6 return 0;
10068 }
10069
10070 20 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10071 {
10072 typedef struct MOVAtoms {
10073 FFIOContext b;
10074 uint32_t type;
10075 int64_t size;
10076 uint8_t *data;
10077 } MOVAtoms;
10078 20 MOVAtoms *atoms = NULL;
10079 MOVAtom a;
10080 unsigned count;
10081 20 int nb_atoms = 0;
10082 int version, flags;
10083 int ret;
10084
10085 20 a.size = avio_rb32(pb);
10086 20 a.type = avio_rl32(pb);
10087
10088
3/6
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
20 if (a.size < 8 || a.size > atom.size || a.type != MKTAG('i','p','c','o'))
10089 ✗ return AVERROR_INVALIDDATA;
10090
10091 20 atom.size -= a.size;
10092 20 a.size -= 8;
10093
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 20 times.
120 while (a.size >= 8) {
10094 100 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
10095
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (!ref) {
10096 ✗ ret = AVERROR(ENOMEM);
10097 ✗ goto fail;
10098 }
10099 100 ref->data = NULL;
10100 100 ref->size = avio_rb32(pb);
10101 100 ref->type = avio_rl32(pb);
10102
2/4
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
100 if (ref->size > a.size || ref->size < 8)
10103 break;
10104 100 ref->data = av_malloc(ref->size);
10105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (!ref->data) {
10106 ✗ ret = AVERROR_INVALIDDATA;
10107 ✗ goto fail;
10108 }
10109 100 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
10110 100 AV_WB32(ref->data, ref->size);
10111 100 AV_WL32(ref->data + 4, ref->type);
10112
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 100 times.
100 if (avio_read(pb, ref->data + 8, ref->size - 8) != ref->size - 8) {
10113 ✗ ret = AVERROR_INVALIDDATA;
10114 ✗ goto fail;
10115 }
10116 100 ffio_init_read_context(&ref->b, ref->data, ref->size);
10117 100 a.size -= ref->size;
10118 }
10119
10120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (a.size) {
10121 ✗ ret = AVERROR_INVALIDDATA;
10122 ✗ goto fail;
10123 }
10124
10125 20 a.size = avio_rb32(pb);
10126 20 a.type = avio_rl32(pb);
10127
10128
3/6
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
20 if (a.size < 16 || a.size > atom.size || a.type != MKTAG('i','p','m','a')) {
10129 ✗ ret = AVERROR_INVALIDDATA;
10130 ✗ goto fail;
10131 }
10132
10133 20 version = avio_r8(pb);
10134 20 flags = avio_rb24(pb);
10135 20 count = avio_rb32(pb);
10136 20 a.size -= 16;
10137
10138
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 20 times.
86 for (int i = 0; i < count; i++) {
10139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
10140 66 int assoc_count = avio_r8(pb);
10141
10142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 a.size -= (version ? 5 : 3) + assoc_count * (1 + (flags & 1));
10143
2/4
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 66 times.
66 if (avio_feof(pb) || a.size < 0) {
10144 ✗ ret = AVERROR_INVALIDDATA;
10145 ✗ goto fail;
10146 }
10147
10148
2/2
✓ Branch 0 taken 173 times.
✓ Branch 1 taken 66 times.
239 for (int j = 0; j < assoc_count; j++) {
10149 MOVAtoms *ref;
10150 173 int index = avio_r8(pb) & 0x7f;
10151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 173 times.
173 if (flags & 1) {
10152 ✗ index <<= 8;
10153 ✗ index |= avio_r8(pb);
10154 }
10155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 173 times.
173 if (!index)
10156 ✗ continue;
10157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 173 times.
173 if (index > nb_atoms) {
10158 ✗ ret = AVERROR_INVALIDDATA;
10159 ✗ goto fail;
10160 }
10161 173 ref = &atoms[--index];
10162
10163 173 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
10164 173 index + 1, item_id, av_fourcc2str(ref->type));
10165
10166 173 c->cur_item_id = item_id;
10167
10168 173 ret = mov_read_default(c, &ref->b.pub,
10169 173 (MOVAtom) { .size = ref->size,
10170 .type = MKTAG('i','p','c','o') });
10171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 173 times.
173 if (ret < 0)
10172 ✗ goto fail;
10173 173 ffio_init_read_context(&ref->b, ref->data, ref->size);
10174 }
10175 }
10176
10177 20 ret = 0;
10178 20 fail:
10179 20 c->cur_item_id = -1;
10180
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 20 times.
120 for (int i = 0; i < nb_atoms; i++)
10181 100 av_free(atoms[i].data);
10182 20 av_free(atoms);
10183
10184 20 return ret;
10185 }
10186
10187 375 static int mov_read_vmhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10188 {
10189 375 avio_rb32(pb); // version & flags
10190 375 uint16_t graphics_mode = avio_rb16(pb);
10191 // ignored: opcolor[3]
10192
10193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 375 times.
375 if (c->fc->nb_streams < 1)
10194 ✗ return 0;
10195 375 AVStream *st = c->fc->streams[c->fc->nb_streams - 1];
10196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 375 times.
375 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
10197 ✗ return 0;
10198
10199
2/4
✓ Branch 0 taken 374 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
375 switch (graphics_mode) {
10200 374 case MOV_GRAPHICS_MODE_COPY:
10201 case MOV_GRAPHICS_MODE_DITHER_COPY:
10202 374 st->codecpar->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
10203 374 break;
10204 ✗ case MOV_GRAPHICS_MODE_STRAIGHT_ALPHA:
10205 ✗ st->codecpar->alpha_mode = AVALPHA_MODE_STRAIGHT;
10206 ✗ break;
10207 ✗ case MOV_GRAPHICS_MODE_PREMUL_BLACK_ALPHA:
10208 ✗ st->codecpar->alpha_mode = AVALPHA_MODE_PREMULTIPLIED;
10209 ✗ break;
10210 1 default:
10211 1 st->codecpar->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
10212 1 av_log(c->fc, AV_LOG_WARNING, "Unhandled graphics mode: 0x%x\n",
10213 graphics_mode);
10214 1 break;
10215 }
10216
10217 375 return 0;
10218 }
10219
10220 5 static int mov_read_mhac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10221 {
10222 5 AVFormatContext *ctx = c->fc;
10223 AVStream *st;
10224 int profile_level_indication, reference_ch_layout, config_length;
10225 5 int ret = 0;
10226
10227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ctx->nb_streams < 1)
10228 ✗ return 0;
10229
10230 5 st = ctx->streams[ctx->nb_streams - 1];
10231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
10232 ✗ return 0;
10233
10234
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_r8(pb) != 1) // ConfigurationVersion
10235 ✗ return 0;
10236
10237 5 profile_level_indication = avio_r8(pb);
10238 5 st->codecpar->profile = (profile_level_indication - 1) / 5;
10239 5 st->codecpar->level = ((profile_level_indication - 1) % 5) + 1;
10240
10241 5 reference_ch_layout = avio_r8(pb);
10242 5 config_length = avio_rb16(pb);
10243
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (config_length)
10244 5 ret = ff_get_extradata(ctx, st->codecpar, pb, config_length);
10245
10246
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (!reference_ch_layout ||
10247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 reference_ch_layout >= FF_ARRAY_ELEMS(ff_mpa_cicp_channel_layout_masks)) {
10248 ✗ av_log(ctx, AV_LOG_WARNING, "Unknown referenceChannelLayout value: %d\n", reference_ch_layout);
10249 ✗ return ret;
10250 }
10251
10252 5 av_channel_layout_from_mask(&st->codecpar->ch_layout,
10253 5 ff_mpa_cicp_channel_layout_masks[reference_ch_layout]);
10254
10255 5 return ret;
10256 }
10257
10258 static const MOVParseTableEntry mov_default_parse_table[] = {
10259 { MKTAG('A','C','L','R'), mov_read_aclr },
10260 { MKTAG('A','P','R','G'), mov_read_avid },
10261 { MKTAG('A','A','L','P'), mov_read_avid },
10262 { MKTAG('A','R','E','S'), mov_read_ares },
10263 { MKTAG('a','v','s','s'), mov_read_avss },
10264 { MKTAG('a','v','1','C'), mov_read_glbl },
10265 { MKTAG('c','h','p','l'), mov_read_chpl },
10266 { MKTAG('c','o','6','4'), mov_read_stco },
10267 { MKTAG('c','o','l','r'), mov_read_colr },
10268 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
10269 { MKTAG('d','i','n','f'), mov_read_default },
10270 { MKTAG('D','p','x','E'), mov_read_dpxe },
10271 { MKTAG('d','r','e','f'), mov_read_dref },
10272 { MKTAG('e','d','t','s'), mov_read_default },
10273 { MKTAG('e','l','s','t'), mov_read_elst },
10274 { MKTAG('e','n','d','a'), mov_read_enda },
10275 { MKTAG('f','i','e','l'), mov_read_fiel },
10276 { MKTAG('a','d','r','m'), mov_read_adrm },
10277 { MKTAG('f','t','y','p'), mov_read_ftyp },
10278 { MKTAG('g','l','b','l'), mov_read_glbl },
10279 { MKTAG('h','d','l','r'), mov_read_hdlr },
10280 { MKTAG('i','l','s','t'), mov_read_ilst },
10281 { MKTAG('j','p','2','h'), mov_read_jp2h },
10282 { MKTAG('m','d','a','t'), mov_read_mdat },
10283 { MKTAG('m','d','h','d'), mov_read_mdhd },
10284 { MKTAG('m','d','i','a'), mov_read_default },
10285 { MKTAG('m','e','t','a'), mov_read_meta },
10286 { MKTAG('m','i','n','f'), mov_read_default },
10287 { MKTAG('m','o','o','f'), mov_read_moof },
10288 { MKTAG('m','o','o','v'), mov_read_moov },
10289 { MKTAG('m','v','e','x'), mov_read_default },
10290 { MKTAG('m','v','h','d'), mov_read_mvhd },
10291 { MKTAG('S','M','I',' '), mov_read_svq3 },
10292 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
10293 { MKTAG('a','v','c','C'), mov_read_glbl },
10294 { MKTAG('p','a','s','p'), mov_read_pasp },
10295 { MKTAG('c','l','a','p'), mov_read_clap },
10296 { MKTAG('c','d','s','c'), mov_read_cdsc_rndr },
10297 { MKTAG('r','n','d','r'), mov_read_cdsc_rndr },
10298 { MKTAG('s','b','a','s'), mov_read_sbas },
10299 { MKTAG('v','d','e','p'), mov_read_vdep },
10300 { MKTAG('s','i','d','x'), mov_read_sidx },
10301 { MKTAG('s','t','b','l'), mov_read_default },
10302 { MKTAG('s','t','c','o'), mov_read_stco },
10303 { MKTAG('s','t','p','s'), mov_read_stps },
10304 { MKTAG('s','t','r','f'), mov_read_strf },
10305 { MKTAG('s','t','s','c'), mov_read_stsc },
10306 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
10307 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
10308 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
10309 { MKTAG('s','t','t','s'), mov_read_stts },
10310 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
10311 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
10312 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
10313 { MKTAG('t','f','d','t'), mov_read_tfdt },
10314 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
10315 { MKTAG('t','r','a','k'), mov_read_trak },
10316 { MKTAG('t','r','a','f'), mov_read_default },
10317 { MKTAG('t','r','e','f'), mov_read_default },
10318 { MKTAG('t','m','c','d'), mov_read_tmcd },
10319 { MKTAG('c','h','a','p'), mov_read_chap },
10320 { MKTAG('t','r','e','x'), mov_read_trex },
10321 { MKTAG('t','r','u','n'), mov_read_trun },
10322 { MKTAG('u','d','t','a'), mov_read_default },
10323 { MKTAG('w','a','v','e'), mov_read_wave },
10324 { MKTAG('e','s','d','s'), mov_read_esds },
10325 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
10326 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
10327 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
10328 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
10329 { MKTAG('w','f','e','x'), mov_read_wfex },
10330 { MKTAG('c','m','o','v'), mov_read_cmov },
10331 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
10332 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
10333 { MKTAG('d','v','c','1'), mov_read_dvc1 },
10334 { MKTAG('s','g','p','d'), mov_read_sgpd },
10335 { MKTAG('s','b','g','p'), mov_read_sbgp },
10336 { MKTAG('h','v','c','C'), mov_read_glbl },
10337 { MKTAG('v','v','c','C'), mov_read_glbl },
10338 { MKTAG('u','u','i','d'), mov_read_uuid },
10339 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
10340 { MKTAG('f','r','e','e'), mov_read_free },
10341 { MKTAG('-','-','-','-'), mov_read_custom },
10342 { MKTAG('s','i','n','f'), mov_read_default },
10343 { MKTAG('f','r','m','a'), mov_read_frma },
10344 { MKTAG('s','e','n','c'), mov_read_senc },
10345 { MKTAG('s','a','i','z'), mov_read_saiz },
10346 { MKTAG('s','a','i','o'), mov_read_saio },
10347 { MKTAG('p','s','s','h'), mov_read_pssh },
10348 { MKTAG('s','c','h','m'), mov_read_schm },
10349 { MKTAG('s','c','h','i'), mov_read_default },
10350 { MKTAG('t','e','n','c'), mov_read_tenc },
10351 { MKTAG('d','f','L','a'), mov_read_dfla },
10352 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
10353 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
10354 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
10355 { MKTAG('h','f','o','v'), mov_read_hfov },
10356 { MKTAG('d','O','p','s'), mov_read_dops },
10357 { MKTAG('d','m','l','p'), mov_read_dmlp },
10358 { MKTAG('S','m','D','m'), mov_read_smdm },
10359 { MKTAG('C','o','L','L'), mov_read_coll },
10360 { MKTAG('v','p','c','C'), mov_read_vpcc },
10361 { MKTAG('m','d','c','v'), mov_read_mdcv },
10362 { MKTAG('c','l','l','i'), mov_read_clli },
10363 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
10364 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
10365 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
10366 { MKTAG('h','v','c','E'), mov_read_hvce },
10367 { MKTAG('k','i','n','d'), mov_read_kind },
10368 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
10369 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
10370 { MKTAG('i','l','o','c'), mov_read_iloc },
10371 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
10372 { MKTAG('p','i','t','m'), mov_read_pitm },
10373 { MKTAG('e','v','c','C'), mov_read_glbl },
10374 { MKTAG('a','u','x','C'), mov_read_auxc },
10375 { MKTAG('i','d','a','t'), mov_read_idat },
10376 { MKTAG('i','m','i','r'), mov_read_imir },
10377 { MKTAG('i','r','e','f'), mov_read_iref },
10378 { MKTAG('i','s','p','e'), mov_read_ispe },
10379 { MKTAG('i','r','o','t'), mov_read_irot },
10380 { MKTAG('i','p','r','p'), mov_read_iprp },
10381 { MKTAG('i','i','n','f'), mov_read_iinf },
10382 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
10383 { MKTAG('l','h','v','C'), mov_read_lhvc },
10384 { MKTAG('l','v','c','C'), mov_read_glbl },
10385 { MKTAG('a','p','v','C'), mov_read_glbl },
10386 #if CONFIG_IAMFDEC
10387 { MKTAG('i','a','c','b'), mov_read_iacb },
10388 #endif
10389 { MKTAG('s','r','a','t'), mov_read_srat },
10390 { MKTAG('v','m','h','d'), mov_read_vmhd },
10391 { MKTAG('m','h','a','C'), mov_read_mhac },
10392 { 0, NULL }
10393 };
10394
10395 9029 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10396 {
10397 9029 int64_t total_size = 0;
10398 MOVAtom a;
10399 int i;
10400
10401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9029 times.
9029 if (c->atom_depth > 10) {
10402 ✗ av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
10403 ✗ return AVERROR_INVALIDDATA;
10404 }
10405 9029 c->atom_depth ++;
10406
10407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9029 times.
9029 if (atom.size < 0)
10408 ✗ atom.size = INT64_MAX;
10409
2/2
✓ Branch 0 taken 26099 times.
✓ Branch 1 taken 8422 times.
34521 while (total_size <= atom.size - 8) {
10410 26099 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
10411 26099 a.size = avio_rb32(pb);
10412 26099 a.type = avio_rl32(pb);
10413
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 26091 times.
26099 if (avio_feof(pb))
10414 8 break;
10415
3/4
✓ Branch 0 taken 265 times.
✓ Branch 1 taken 25826 times.
✓ Branch 2 taken 265 times.
✗ Branch 3 not taken.
26091 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
10416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26091 times.
26091 a.type == MKTAG('h','o','o','v')) &&
10417 ✗ a.size >= 8 &&
10418 ✗ c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
10419 uint32_t type;
10420 ✗ avio_skip(pb, 4);
10421 ✗ type = avio_rl32(pb);
10422 ✗ if (avio_feof(pb))
10423 ✗ break;
10424 ✗ avio_seek(pb, -8, SEEK_CUR);
10425 ✗ if (type == MKTAG('m','v','h','d') ||
10426 type == MKTAG('c','m','o','v')) {
10427 ✗ av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
10428 ✗ a.type = MKTAG('m','o','o','v');
10429 }
10430 }
10431
2/2
✓ Branch 0 taken 22523 times.
✓ Branch 1 taken 3568 times.
26091 if (atom.type != MKTAG('r','o','o','t') &&
10432
2/2
✓ Branch 0 taken 20640 times.
✓ Branch 1 taken 1883 times.
22523 atom.type != MKTAG('m','o','o','v')) {
10433
1/2
✓ Branch 0 taken 20640 times.
✗ Branch 1 not taken.
20640 if (a.type == MKTAG('t','r','a','k') ||
10434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20640 times.
20640 a.type == MKTAG('m','d','a','t')) {
10435 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
10436 ✗ avio_skip(pb, -8);
10437 ✗ c->atom_depth --;
10438 599 return 0;
10439 }
10440 }
10441 26091 total_size += 8;
10442
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 26062 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
26091 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
10443 29 a.size = avio_rb64(pb) - 8;
10444 29 total_size += 8;
10445 }
10446 26091 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
10447 26091 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
10448
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 26086 times.
26091 if (a.size == 0) {
10449 5 a.size = atom.size - total_size + 8;
10450 }
10451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26091 times.
26091 if (a.size < 0)
10452 ✗ break;
10453 26091 a.size -= 8;
10454
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26091 times.
26091 if (a.size < 0)
10455 ✗ break;
10456 26091 a.size = FFMIN(a.size, atom.size - total_size);
10457
10458
2/2
✓ Branch 0 taken 1266442 times.
✓ Branch 1 taken 2183 times.
1268625 for (i = 0; mov_default_parse_table[i].type; i++)
10459
2/2
✓ Branch 0 taken 23908 times.
✓ Branch 1 taken 1242534 times.
1266442 if (mov_default_parse_table[i].type == a.type) {
10460 23908 parse = mov_default_parse_table[i].parse;
10461 23908 break;
10462 }
10463
10464 // container is user data
10465
4/4
✓ Branch 0 taken 2183 times.
✓ Branch 1 taken 23908 times.
✓ Branch 2 taken 1983 times.
✓ Branch 3 taken 200 times.
26091 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
10466
2/2
✓ Branch 0 taken 434 times.
✓ Branch 1 taken 1549 times.
1983 atom.type == MKTAG('i','l','s','t')))
10467 634 parse = mov_read_udta_string;
10468
10469 // Supports parsing the QuickTime Metadata Keys.
10470 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
10471
4/4
✓ Branch 0 taken 1549 times.
✓ Branch 1 taken 24542 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 1535 times.
26091 if (!parse && c->found_hdlr_mdta &&
10472
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 atom.type == MKTAG('m','e','t','a') &&
10473
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 a.type == MKTAG('k','e','y','s') &&
10474
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 c->meta_keys_count == 0) {
10475 14 parse = mov_read_keys;
10476 }
10477
10478
2/2
✓ Branch 0 taken 1535 times.
✓ Branch 1 taken 24556 times.
26091 if (!parse) { /* skip leaf atoms data */
10479 1535 avio_skip(pb, a.size);
10480 } else {
10481 24556 int64_t start_pos = avio_tell(pb);
10482 int64_t left;
10483 24556 int err = parse(c, pb, a);
10484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24556 times.
24556 if (err < 0) {
10485 ✗ c->atom_depth --;
10486 ✗ return err;
10487 }
10488
5/6
✓ Branch 0 taken 4923 times.
✓ Branch 1 taken 19633 times.
✓ Branch 2 taken 3467 times.
✓ Branch 3 taken 1456 times.
✓ Branch 4 taken 3467 times.
✗ Branch 5 not taken.
24556 if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos &&
10489
7/8
✓ Branch 0 taken 3464 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3464 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3450 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 582 times.
✓ Branch 7 taken 2868 times.
6917 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
10490 3450 start_pos + a.size == avio_size(pb))) {
10491
5/6
✓ Branch 0 taken 596 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 596 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 582 times.
599 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
10492 17 c->next_root_atom = start_pos + a.size;
10493 599 c->atom_depth --;
10494 599 return 0;
10495 }
10496 23957 left = a.size - avio_tell(pb) + start_pos;
10497
2/2
✓ Branch 0 taken 2275 times.
✓ Branch 1 taken 21682 times.
23957 if (left > 0) /* skip garbage at atom end */
10498 2275 avio_skip(pb, left);
10499
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 21680 times.
21682 else if (left < 0) {
10500 2 av_log(c->fc, AV_LOG_WARNING,
10501 "overread end of atom '%s' by %"PRId64" bytes\n",
10502 2 av_fourcc2str(a.type), -left);
10503 2 avio_seek(pb, left, SEEK_CUR);
10504 }
10505 }
10506
10507 25492 total_size += a.size;
10508 }
10509
10510
4/4
✓ Branch 0 taken 131 times.
✓ Branch 1 taken 8299 times.
✓ Branch 2 taken 123 times.
✓ Branch 3 taken 8 times.
8430 if (total_size < atom.size && atom.size < 0x7ffff)
10511 123 avio_skip(pb, atom.size - total_size);
10512
10513 8430 c->atom_depth --;
10514 8430 return 0;
10515 }
10516
10517 8152 static int mov_probe(const AVProbeData *p)
10518 {
10519 int64_t offset;
10520 uint32_t tag;
10521 8152 int score = 0;
10522 8152 int moov_offset = -1;
10523
10524 /* check file header */
10525 8152 offset = 0;
10526 10070 for (;;) {
10527 int64_t size;
10528 18222 int minsize = 8;
10529 /* ignore invalid offset */
10530
2/2
✓ Branch 0 taken 8152 times.
✓ Branch 1 taken 10070 times.
18222 if ((offset + 8ULL) > (unsigned int)p->buf_size)
10531 8152 break;
10532 10070 size = AV_RB32(p->buf + offset);
10533
3/4
✓ Branch 0 taken 547 times.
✓ Branch 1 taken 9523 times.
✓ Branch 2 taken 547 times.
✗ Branch 3 not taken.
10070 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
10534 547 size = AV_RB64(p->buf+offset + 8);
10535 547 minsize = 16;
10536
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 9451 times.
9523 } else if (size == 0) {
10537 72 size = p->buf_size - offset;
10538 }
10539
2/2
✓ Branch 0 taken 416 times.
✓ Branch 1 taken 9654 times.
10070 if (size < minsize) {
10540 416 offset += 4;
10541 416 continue;
10542 }
10543 9654 tag = AV_RL32(p->buf + offset + 4);
10544
5/6
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 1021 times.
✓ Branch 2 taken 434 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 8038 times.
9654 switch(tag) {
10545 /* check for obvious tags */
10546 160 case MKTAG('m','o','o','v'):
10547 160 moov_offset = offset + 4;
10548 av_fallthrough;
10549 1181 case MKTAG('m','d','a','t'):
10550 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
10551 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
10552 case MKTAG('f','t','y','p'):
10553
2/2
✓ Branch 0 taken 529 times.
✓ Branch 1 taken 652 times.
1181 if (tag == MKTAG('f','t','y','p') &&
10554
1/2
✓ Branch 0 taken 529 times.
✗ Branch 1 not taken.
529 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
10555
1/2
✓ Branch 0 taken 529 times.
✗ Branch 1 not taken.
529 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
10556
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 522 times.
529 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
10557 )) {
10558 7 score = FFMAX(score, 5);
10559 } else {
10560 1174 score = AVPROBE_SCORE_MAX;
10561 }
10562 1181 break;
10563 /* those are more common words, so rate then a bit less */
10564 434 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
10565 case MKTAG('w','i','d','e'):
10566 case MKTAG('f','r','e','e'):
10567 case MKTAG('j','u','n','k'):
10568 case MKTAG('p','i','c','t'):
10569 434 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
10570 434 break;
10571 ✗ case MKTAG(0x82,0x82,0x7f,0x7d):
10572 ✗ score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
10573 ✗ break;
10574 1 case MKTAG('s','k','i','p'):
10575 case MKTAG('u','u','i','d'):
10576 case MKTAG('p','r','f','l'):
10577 /* if we only find those cause probedata is too small at least rate them */
10578 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
10579 1 break;
10580 }
10581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9654 times.
9654 if (size > INT64_MAX - offset)
10582 ✗ break;
10583 9654 offset += size;
10584 }
10585
4/4
✓ Branch 0 taken 576 times.
✓ Branch 1 taken 7576 times.
✓ Branch 2 taken 160 times.
✓ Branch 3 taken 416 times.
8152 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
10586 /* moov atom in the header - we should make sure that this is not a
10587 * MOV-packed MPEG-PS */
10588 160 offset = moov_offset;
10589
10590
2/2
✓ Branch 0 taken 156244 times.
✓ Branch 1 taken 160 times.
156404 while (offset < (p->buf_size - 16)) { /* Sufficient space */
10591 /* We found an actual hdlr atom */
10592
2/2
✓ Branch 0 taken 178 times.
✓ Branch 1 taken 156066 times.
156244 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
10593
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 153 times.
178 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
10594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
10595 ✗ av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
10596 /* We found a media handler reference atom describing an
10597 * MPEG-PS-in-MOV, return a
10598 * low score to force expanding the probe window until
10599 * mpegps_probe finds what it needs */
10600 ✗ return 5;
10601 } else {
10602 /* Keep looking */
10603 156244 offset += 2;
10604 }
10605 }
10606 }
10607
10608 8152 return score;
10609 }
10610
10611 // must be done after parsing all trak because there's no order requirement
10612 2 static void mov_read_chapters(AVFormatContext *s)
10613 {
10614 2 MOVContext *mov = s->priv_data;
10615 MOVStreamContext *sc;
10616 int64_t cur_pos;
10617 int i, j;
10618 int chapter_track;
10619
10620
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
10621 2 AVStream *st = NULL;
10622 2 FFStream *sti = NULL;
10623 2 chapter_track = mov->chapter_tracks[j];
10624
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
10625 4 sc = mov->fc->streams[i]->priv_data;
10626
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
10627 2 st = s->streams[i];
10628 2 break;
10629 }
10630 }
10631
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
10632 ✗ av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
10633 ✗ continue;
10634 }
10635 2 sti = ffstream(st);
10636
10637 2 sc = st->priv_data;
10638 2 cur_pos = avio_tell(sc->pb);
10639
10640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
10641 ✗ st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
10642 ✗ if (!st->attached_pic.data && sti->nb_index_entries) {
10643 // Retrieve the first frame, if possible
10644 ✗ AVIndexEntry *sample = &sti->index_entries[0];
10645 ✗ if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10646 ✗ av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
10647 ✗ goto finish;
10648 }
10649
10650 ✗ if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
10651 ✗ goto finish;
10652 }
10653 } else {
10654 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10655 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
10656 2 st->discard = AVDISCARD_ALL;
10657
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
10658 8 AVIndexEntry *sample = &sti->index_entries[i];
10659
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 int64_t end = i+1 < sti->nb_index_entries ? sti->index_entries[i+1].timestamp : st->duration;
10660 uint8_t *title;
10661 uint16_t ch;
10662 int len, title_len;
10663
10664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
10665 ✗ av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
10666 ✗ end = AV_NOPTS_VALUE;
10667 }
10668
10669
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10670 ✗ av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
10671 ✗ goto finish;
10672 }
10673
10674 // the first two bytes are the length of the title
10675 8 len = avio_rb16(sc->pb);
10676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
10677 ✗ continue;
10678 8 title_len = 2*len + 1;
10679
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
10680 ✗ goto finish;
10681
10682 // The samples could theoretically be in any encoding if there's an encd
10683 // atom following, but in practice are only utf-8 or utf-16, distinguished
10684 // instead by the presence of a BOM
10685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
10686 ✗ title[0] = 0;
10687 } else {
10688 8 ch = avio_rb16(sc->pb);
10689
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
10690 ✗ avio_get_str16be(sc->pb, len, title, title_len);
10691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
10692 ✗ avio_get_str16le(sc->pb, len, title, title_len);
10693 else {
10694 8 AV_WB16(title, ch);
10695
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (len == 1 || len == 2)
10696 ✗ title[len] = 0;
10697 else
10698 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
10699 }
10700 }
10701
10702 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
10703 8 av_freep(&title);
10704 }
10705 }
10706 2 finish:
10707 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
10708 }
10709 2 }
10710
10711 28 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
10712 int64_t value, int flags)
10713 {
10714 AVTimecode tc;
10715 char buf[AV_TIMECODE_STR_SIZE];
10716 28 AVRational rate = st->avg_frame_rate;
10717 28 int ret = av_timecode_init(&tc, rate, flags, 0, s);
10718
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
10719 ✗ return ret;
10720 28 av_dict_set(&st->metadata, "timecode",
10721 28 av_timecode_make_string(&tc, buf, value), 0);
10722 28 return 0;
10723 }
10724
10725 ✗ static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
10726 {
10727 ✗ MOVStreamContext *sc = st->priv_data;
10728 ✗ FFStream *const sti = ffstream(st);
10729 char buf[AV_TIMECODE_STR_SIZE];
10730 ✗ int64_t cur_pos = avio_tell(sc->pb);
10731 int hh, mm, ss, ff, drop;
10732
10733 ✗ if (!sti->nb_index_entries)
10734 ✗ return -1;
10735
10736 ✗ avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10737 ✗ avio_skip(s->pb, 13);
10738 ✗ hh = avio_r8(s->pb);
10739 ✗ mm = avio_r8(s->pb);
10740 ✗ ss = avio_r8(s->pb);
10741 ✗ drop = avio_r8(s->pb);
10742 ✗ ff = avio_r8(s->pb);
10743 ✗ snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
10744 hh, mm, ss, drop ? ';' : ':', ff);
10745 ✗ av_dict_set(&st->metadata, "timecode", buf, 0);
10746
10747 ✗ avio_seek(sc->pb, cur_pos, SEEK_SET);
10748 ✗ return 0;
10749 }
10750
10751 28 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
10752 {
10753 28 MOVStreamContext *sc = st->priv_data;
10754 28 FFStream *const sti = ffstream(st);
10755 28 int flags = 0;
10756 28 int64_t cur_pos = avio_tell(sc->pb);
10757 int64_t value;
10758 28 AVRational tc_rate = st->avg_frame_rate;
10759 28 int tmcd_nb_frames = sc->tmcd_nb_frames;
10760 int rounded_tc_rate;
10761
10762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!sti->nb_index_entries)
10763 ✗ return -1;
10764
10765
3/6
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 28 times.
28 if (!tc_rate.num || !tc_rate.den || !tmcd_nb_frames)
10766 ✗ return -1;
10767
10768 28 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10769 28 value = avio_rb32(s->pb);
10770
10771
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 10 times.
28 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
10772
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
10773
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
10774
10775 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
10776 * not the case) and thus assume "frame number format" instead of QT one.
10777 * No sample with tmcd track can be found with a QT timecode at the moment,
10778 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
10779 * format). */
10780
10781 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
10782 * we multiply the frame number with the quotient.
10783 * See tickets #9492, #9710. */
10784 28 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
10785 /* Work around files where tmcd_nb_frames is rounded down from frame rate
10786 * instead of up. See ticket #5978. */
10787
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 18 times.
28 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
10788
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
10789 10 tmcd_nb_frames = rounded_tc_rate;
10790 28 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
10791
10792 28 parse_timecode_in_framenum_format(s, st, value, flags);
10793
10794 28 avio_seek(sc->pb, cur_pos, SEEK_SET);
10795 28 return 0;
10796 }
10797
10798 1693 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
10799 int i;
10800
3/4
✓ Branch 0 taken 1693 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1680 times.
✓ Branch 3 taken 13 times.
1693 if (!index || !*index) return;
10801
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 13 times.
208 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
10802 195 av_encryption_info_free((*index)->encrypted_samples[i]);
10803 }
10804 13 av_freep(&(*index)->encrypted_samples);
10805 13 av_freep(&(*index)->auxiliary_info_sizes);
10806 13 av_freep(&(*index)->auxiliary_offsets);
10807 13 av_freep(index);
10808 }
10809
10810 959 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
10811 {
10812 959 MOVStreamContext *sc = st->priv_data;
10813
10814
3/4
✓ Branch 0 taken 959 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 907 times.
959 if (!sc || --sc->refcount) {
10815 52 st->priv_data = NULL;
10816 52 return;
10817 }
10818
10819 907 av_freep(&sc->tts_data);
10820
2/2
✓ Branch 0 taken 838 times.
✓ Branch 1 taken 907 times.
1745 for (int i = 0; i < sc->drefs_count; i++) {
10821 838 av_freep(&sc->drefs[i].path);
10822 838 av_freep(&sc->drefs[i].dir);
10823 }
10824 907 av_freep(&sc->drefs);
10825
10826 907 sc->drefs_count = 0;
10827
10828
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 891 times.
907 if (!sc->pb_is_copied)
10829 16 ff_format_io_close(s, &sc->pb);
10830
10831 907 sc->pb = NULL;
10832 907 av_freep(&sc->chunk_offsets);
10833 907 av_freep(&sc->stsc_data);
10834 907 av_freep(&sc->sample_sizes);
10835 907 av_freep(&sc->keyframes);
10836 907 av_freep(&sc->ctts_data);
10837 907 av_freep(&sc->stts_data);
10838 907 av_freep(&sc->sdtp_data);
10839 907 av_freep(&sc->stps_data);
10840 907 av_freep(&sc->elst_data);
10841 907 av_freep(&sc->rap_group);
10842 907 av_freep(&sc->sync_group);
10843 907 av_freep(&sc->sgpd_sync);
10844 907 av_freep(&sc->sample_offsets);
10845 907 av_freep(&sc->open_key_samples);
10846 907 av_freep(&sc->display_matrix);
10847 907 av_freep(&sc->index_ranges);
10848
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 907 times.
939 for (int i = 0; i < sc->nb_tref_tags; i++)
10849 32 av_freep(&sc->tref_tags[i].id);
10850 907 av_freep(&sc->tref_tags);
10851
10852
2/2
✓ Branch 0 taken 838 times.
✓ Branch 1 taken 69 times.
907 if (sc->extradata)
10853
2/2
✓ Branch 0 taken 855 times.
✓ Branch 1 taken 838 times.
1693 for (int i = 0; i < sc->stsd_count; i++)
10854 855 av_free(sc->extradata[i]);
10855 907 av_freep(&sc->extradata);
10856 907 av_freep(&sc->extradata_size);
10857
10858 907 mov_free_encryption_index(&sc->cenc.encryption_index);
10859 907 av_encryption_info_free(sc->cenc.default_encrypted_sample);
10860 907 av_aes_ctr_free(sc->cenc.aes_ctr);
10861
10862 907 av_freep(&sc->stereo3d);
10863 907 av_freep(&sc->spherical);
10864 907 av_freep(&sc->mastering);
10865 907 av_freep(&sc->coll);
10866 907 av_freep(&sc->ambient);
10867
10868 #if CONFIG_IAMFDEC
10869
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 895 times.
907 if (sc->iamf)
10870 12 ff_iamf_read_deinit(sc->iamf);
10871 #endif
10872 907 av_freep(&sc->iamf);
10873 }
10874
10875 625 static int mov_read_close(AVFormatContext *s)
10876 {
10877 625 MOVContext *mov = s->priv_data;
10878 int i, j;
10879
10880
2/2
✓ Branch 0 taken 959 times.
✓ Branch 1 taken 625 times.
1584 for (i = 0; i < s->nb_streams; i++) {
10881 959 AVStream *st = s->streams[i];
10882
10883 959 mov_free_stream_context(s, st);
10884 }
10885
10886 625 av_freep(&mov->dv_demux);
10887 625 avformat_free_context(mov->dv_fctx);
10888 625 mov->dv_fctx = NULL;
10889
10890
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 611 times.
625 if (mov->meta_keys) {
10891
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 14 times.
114 for (i = 1; i < mov->meta_keys_count; i++) {
10892 100 av_freep(&mov->meta_keys[i]);
10893 }
10894 14 av_freep(&mov->meta_keys);
10895 }
10896
10897 625 av_freep(&mov->trex_data);
10898 625 av_freep(&mov->bitrates);
10899
10900
2/2
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 625 times.
1111 for (i = 0; i < mov->frag_index.nb_items; i++) {
10901 486 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
10902
2/2
✓ Branch 0 taken 786 times.
✓ Branch 1 taken 486 times.
1272 for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) {
10903 786 mov_free_encryption_index(&frag[j].encryption_index);
10904 }
10905 486 av_freep(&mov->frag_index.item[i].stream_info);
10906 }
10907 625 av_freep(&mov->frag_index.item);
10908
10909 625 av_freep(&mov->aes_decrypt);
10910 625 av_freep(&mov->chapter_tracks);
10911
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 625 times.
702 for (i = 0; i < mov->nb_heif_item; i++) {
10912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (!mov->heif_item[i])
10913 ✗ continue;
10914 77 av_freep(&mov->heif_item[i]->name);
10915 77 av_freep(&mov->heif_item[i]->iref_from_list);
10916 77 av_freep(&mov->heif_item[i]->iref_to_list);
10917 77 av_freep(&mov->heif_item[i]->icc_profile);
10918 77 av_exif_free(&mov->heif_item[i]->ifd);
10919 77 av_freep(&mov->heif_item[i]);
10920 }
10921 625 av_freep(&mov->heif_item);
10922
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 625 times.
638 for (i = 0; i < mov->nb_heif_group; i++) {
10923 13 av_freep(&mov->heif_group[i].item_id_list);
10924 13 av_freep(&mov->heif_group[i].item_idx_list);
10925 13 av_freep(&mov->heif_group[i].item_list);
10926 }
10927 625 av_freep(&mov->heif_group);
10928
10929 625 return 0;
10930 }
10931
10932 28 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
10933 {
10934 int i;
10935
10936
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 for (i = 0; i < s->nb_streams; i++) {
10937 28 AVStream *st = s->streams[i];
10938 28 MOVStreamContext *sc = st->priv_data;
10939 28 MovTref *tag = mov_find_tref_tag(sc, MKTAG('t','m','c','d'));
10940
10941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!tag)
10942 ✗ continue;
10943
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 if (mov_find_tref_id(tag, tmcd_id))
10944 28 return 1;
10945 }
10946 ✗ return 0;
10947 }
10948
10949 /* look for a tmcd track not referenced by any video track, and export it globally */
10950 625 static void export_orphan_timecode(AVFormatContext *s)
10951 {
10952 int i;
10953
10954
2/2
✓ Branch 0 taken 959 times.
✓ Branch 1 taken 625 times.
1584 for (i = 0; i < s->nb_streams; i++) {
10955 959 AVStream *st = s->streams[i];
10956
10957
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 931 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
987 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
10958 28 !tmcd_is_referenced(s, st->id)) {
10959 ✗ AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
10960 ✗ if (tcr) {
10961 ✗ av_dict_set(&s->metadata, "timecode", tcr->value, 0);
10962 ✗ break;
10963 }
10964 }
10965 }
10966 625 }
10967
10968 3 static int read_tfra(MOVContext *mov, AVIOContext *f)
10969 {
10970 int version, fieldlength, i, j;
10971 3 int64_t pos = avio_tell(f);
10972 3 uint32_t size = avio_rb32(f);
10973 unsigned track_id, item_count;
10974
10975
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
10976 1 return 1;
10977 }
10978 2 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
10979
10980 2 version = avio_r8(f);
10981 2 avio_rb24(f);
10982 2 track_id = avio_rb32(f);
10983 2 fieldlength = avio_rb32(f);
10984 2 item_count = avio_rb32(f);
10985
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (i = 0; i < item_count; i++) {
10986 int64_t time, offset;
10987 int index;
10988 MOVFragmentStreamInfo * frag_stream_info;
10989
10990
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (avio_feof(f)) {
10991 ✗ return AVERROR_INVALIDDATA;
10992 }
10993
10994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1) {
10995 ✗ time = avio_rb64(f);
10996 ✗ offset = avio_rb64(f);
10997 } else {
10998 6 time = avio_rb32(f);
10999 6 offset = avio_rb32(f);
11000 }
11001
11002 // The first sample of each stream in a fragment is always a random
11003 // access sample. So it's entry in the tfra can be used as the
11004 // initial PTS of the fragment.
11005 6 index = update_frag_index(mov, offset);
11006 6 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
11007
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (frag_stream_info &&
11008
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
11009 6 frag_stream_info->first_tfra_pts = time;
11010
11011
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
11012 6 avio_r8(f);
11013
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
11014 6 avio_r8(f);
11015
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
11016 6 avio_r8(f);
11017 }
11018
11019 2 avio_seek(f, pos + size, SEEK_SET);
11020 2 return 0;
11021 }
11022
11023 1 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
11024 {
11025 1 int64_t stream_size = avio_size(f);
11026 1 int64_t original_pos = avio_tell(f);
11027 int64_t seek_ret;
11028 1 int ret = -1;
11029
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
11030 ✗ ret = seek_ret;
11031 ✗ goto fail;
11032 }
11033 1 c->mfra_size = avio_rb32(f);
11034 1 c->have_read_mfra_size = 1;
11035
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!c->mfra_size || c->mfra_size > stream_size) {
11036 ✗ av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
11037 ✗ goto fail;
11038 }
11039
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((seek_ret = avio_seek(f, -((int64_t) c->mfra_size), SEEK_CUR)) < 0) {
11040 ✗ ret = seek_ret;
11041 ✗ goto fail;
11042 }
11043
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != c->mfra_size) {
11044 ✗ av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
11045 ✗ goto fail;
11046 }
11047
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
11048 ✗ av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
11049 ✗ goto fail;
11050 }
11051 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
11052 do {
11053 3 ret = read_tfra(c, f);
11054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
11055 ✗ goto fail;
11056
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 } while (!ret);
11057 1 ret = 0;
11058 1 c->frag_index.complete = 1;
11059 1 fail:
11060 1 seek_ret = avio_seek(f, original_pos, SEEK_SET);
11061
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (seek_ret < 0) {
11062 ✗ av_log(c->fc, AV_LOG_ERROR,
11063 "failed to seek back after looking for mfra\n");
11064 ✗ ret = seek_ret;
11065 }
11066 1 return ret;
11067 }
11068
11069 4 static int set_exif_from_item(AVFormatContext *s,
11070 AVPacketSideData **coded_side_data, int *nb_coded_side_data,
11071 const HEIFItem *item)
11072 {
11073 AVPacketSideData *sd =
11074 4 (AVPacketSideData *)av_packet_side_data_get(*coded_side_data,
11075 *nb_coded_side_data,
11076 AV_PKT_DATA_EXIF);
11077 4 const AVExifMetadata *ifd = &item->ifd;
11078 4 AVBufferRef *buf = NULL;
11079 int64_t offset;
11080 int err;
11081
11082
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sd)
11083 ✗ return 0;
11084
11085 4 err = av_exif_write(s, ifd, &buf, AV_EXIF_T_OFF);
11086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
11087 ✗ return err;
11088
11089 4 offset = AV_RB32(buf->data) + 4;
11090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (offset >= buf->size) {
11091 ✗ av_buffer_unref(&buf);
11092 ✗ return AVERROR_INVALIDDATA;
11093 }
11094 4 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
11095 4 AV_PKT_DATA_EXIF, buf->size - offset, 0);
11096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sd) {
11097 ✗ av_buffer_unref(&buf);
11098 ✗ return AVERROR(ENOMEM);
11099 }
11100 4 memcpy(sd->data, buf->data + offset, buf->size - offset);
11101
11102 4 av_buffer_unref(&buf);
11103
11104 4 return 0;
11105 }
11106
11107 4 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
11108 const HEIFItem *item)
11109 {
11110 AVPacketSideData *sd =
11111 4 (AVPacketSideData *)av_packet_side_data_get(*coded_side_data,
11112 *nb_coded_side_data,
11113 AV_PKT_DATA_ICC_PROFILE);
11114
11115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sd)
11116 ✗ return 0;
11117
11118 4 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
11119 AV_PKT_DATA_ICC_PROFILE,
11120 4 item->icc_profile_size, 0);
11121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sd)
11122 ✗ return AVERROR(ENOMEM);
11123
11124 4 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
11125
11126 4 return 0;
11127 }
11128
11129 6 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
11130 const HEIFItem *item)
11131 {
11132 int32_t *matrix;
11133 AVPacketSideData *sd =
11134 6 (AVPacketSideData *)av_packet_side_data_get(*coded_side_data,
11135 *nb_coded_side_data,
11136 AV_PKT_DATA_DISPLAYMATRIX);
11137
11138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (sd)
11139 ✗ return 0;
11140
11141 6 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
11142 AV_PKT_DATA_DISPLAYMATRIX,
11143 9 * sizeof(*matrix), 0);
11144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sd)
11145 ✗ return AVERROR(ENOMEM);
11146
11147 6 matrix = (int32_t*)sd->data;
11148 /* rotation is in the counter-clockwise direction whereas
11149 * av_display_rotation_set() expects its argument to be
11150 * oriented clockwise, so we need to negate it. */
11151 6 av_display_rotation_set(matrix, -item->rotation);
11152 6 av_display_matrix_flip(matrix, item->hflip, item->vflip);
11153
11154 6 return 0;
11155 }
11156
11157 7 static int read_image_grid(AVFormatContext *s, const HEIFGroup *grid,
11158 AVStreamGroupTileGrid *tile_grid)
11159 {
11160 7 MOVContext *c = s->priv_data;
11161 7 const HEIFItem *item = grid->item;
11162 7 int64_t coded_width = 0, coded_height = 0;
11163 7 int64_t offset = 0, pos = avio_tell(s->pb);
11164 7 int64_t x = 0, y = 0;
11165 7 int i = 0;
11166 int tile_rows, tile_cols;
11167 int flags, size;
11168
11169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11170 ✗ av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
11171 ✗ return AVERROR_PATCHWELCOME;
11172 }
11173
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (item->is_idat_relative) {
11174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!c->idat_offset) {
11175 ✗ av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
11176 ✗ return AVERROR_INVALIDDATA;
11177 }
11178 7 offset = c->idat_offset;
11179 }
11180
11181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (offset > INT64_MAX - item->extent_offset)
11182 ✗ return AVERROR_INVALIDDATA;
11183
11184 7 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
11185
11186 7 avio_r8(s->pb); /* version */
11187 7 flags = avio_r8(s->pb);
11188
11189 7 tile_rows = avio_r8(s->pb) + 1;
11190 7 tile_cols = avio_r8(s->pb) + 1;
11191 /* actual width and height of output image */
11192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 tile_grid->width = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
11193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 tile_grid->height = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
11194
11195 7 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
11196 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
11197
11198 7 avio_seek(s->pb, pos, SEEK_SET);
11199
11200 7 size = tile_rows * tile_cols;
11201 7 tile_grid->nb_tiles = grid->nb_items;
11202
11203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (tile_grid->nb_tiles != size)
11204 ✗ return AVERROR_INVALIDDATA;
11205
11206
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
21 for (int i = 0; i < tile_cols; i++)
11207 14 coded_width += grid->item_list[i]->width;
11208
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
21 for (int i = 0; i < size; i += tile_cols)
11209 14 coded_height += grid->item_list[i]->height;
11210
11211
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (coded_width > INT_MAX || coded_height > INT_MAX)
11212 ✗ return AVERROR_INVALIDDATA;
11213
11214 7 tile_grid->coded_width = coded_width;
11215 7 tile_grid->coded_height = coded_height;
11216
11217 7 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
11218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!tile_grid->offsets)
11219 ✗ return AVERROR(ENOMEM);
11220
11221
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
21 while (y < tile_grid->coded_height) {
11222 14 int left_col = i;
11223
11224
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 14 times.
42 while (x < tile_grid->coded_width) {
11225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (i == tile_grid->nb_tiles)
11226 ✗ return AVERROR_INVALIDDATA;
11227
11228 28 tile_grid->offsets[i].idx = grid->item_idx_list[i];
11229 28 tile_grid->offsets[i].horizontal = x;
11230 28 tile_grid->offsets[i].vertical = y;
11231
11232 28 x += grid->item_list[i++]->width;
11233 }
11234
11235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (x > tile_grid->coded_width) {
11236 ✗ av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
11237 ✗ return AVERROR_INVALIDDATA;
11238 }
11239
11240 14 x = 0;
11241 14 y += grid->item_list[left_col]->height;
11242 }
11243
11244
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (y > tile_grid->coded_height || i != tile_grid->nb_tiles) {
11245 ✗ av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
11246 ✗ return AVERROR_INVALIDDATA;
11247 }
11248
11249 7 return 0;
11250 }
11251
11252 4 static int read_image_iovl(AVFormatContext *s, const HEIFGroup *grid,
11253 AVStreamGroupTileGrid *tile_grid)
11254 {
11255 4 MOVContext *c = s->priv_data;
11256 4 const HEIFItem *item = grid->item;
11257 uint16_t canvas_fill_value[4];
11258 4 int64_t offset = 0, pos = avio_tell(s->pb);
11259 4 int ret = 0, flags;
11260
11261
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11262 ✗ av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
11263 ✗ return AVERROR_PATCHWELCOME;
11264 }
11265
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
11266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
11267 ✗ av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
11268 ✗ return AVERROR_INVALIDDATA;
11269 }
11270 4 offset = c->idat_offset;
11271 }
11272
11273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (offset > INT64_MAX - item->extent_offset)
11274 ✗ return AVERROR_INVALIDDATA;
11275
11276 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
11277
11278 4 avio_r8(s->pb); /* version */
11279 4 flags = avio_r8(s->pb);
11280
11281
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
11282 16 canvas_fill_value[i] = avio_rb16(s->pb);
11283 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
11284 4 canvas_fill_value[0], canvas_fill_value[1],
11285 4 canvas_fill_value[2], canvas_fill_value[3]);
11286
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
11287 16 tile_grid->background[i] = canvas_fill_value[i];
11288
11289 /* actual width and height of output image */
11290 4 tile_grid->width =
11291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 tile_grid->coded_width = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
11292 4 tile_grid->height =
11293
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 tile_grid->coded_height = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
11294
11295 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
11296 tile_grid->width, tile_grid->height);
11297
11298 4 tile_grid->nb_tiles = grid->nb_items;
11299 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
11300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
11301 ✗ ret = AVERROR(ENOMEM);
11302 ✗ goto fail;
11303 }
11304
11305
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
11306 8 tile_grid->offsets[i].idx = grid->item_idx_list[i];
11307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 tile_grid->offsets[i].horizontal = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
11308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 tile_grid->offsets[i].vertical = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
11309 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
11310 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
11311 8 i, tile_grid->offsets[i].idx,
11312 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
11313 }
11314
11315 4 fail:
11316 4 avio_seek(s->pb, pos, SEEK_SET);
11317
11318 4 return ret;
11319 }
11320
11321 4 static int mov_parse_exif_item(AVFormatContext *s, HEIFItem *item, const HEIFItem *ref)
11322 {
11323 4 MOVContext *c = s->priv_data;
11324 4 AVExifMetadata *ifd = &item->ifd;
11325 uint8_t *buf;
11326 4 int64_t offset = 0, pos = avio_tell(s->pb);
11327 4 unsigned orientation_id = av_exif_get_tag_id("Orientation");
11328 int err;
11329
11330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11331 ✗ av_log(c->fc, AV_LOG_WARNING, "Exif metadata with non seekable input\n");
11332 ✗ return AVERROR_PATCHWELCOME;
11333 }
11334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ref->is_idat_relative) {
11335 ✗ if (!c->idat_offset) {
11336 ✗ av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the Exif metadata\n");
11337 ✗ return AVERROR_INVALIDDATA;
11338 }
11339 ✗ offset = c->idat_offset;
11340 }
11341
11342 4 buf = av_malloc(ref->extent_length);
11343
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!buf)
11344 ✗ return AVERROR(ENOMEM);
11345
11346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (offset > INT64_MAX - ref->extent_offset) {
11347 ✗ err = AVERROR(ENOMEM);
11348 ✗ goto fail;
11349 }
11350
11351 4 avio_seek(s->pb, ref->extent_offset + offset, SEEK_SET);
11352 4 err = avio_read(s->pb, buf, ref->extent_length);
11353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err != ref->extent_length) {
11354 ✗ if (err > 0)
11355 ✗ err = AVERROR_INVALIDDATA;
11356 ✗ goto fail;
11357 }
11358
11359 // HEIF spec states that Exif metadata is informative. The irot item property is
11360 // the normative source of rotation information. So we remove any Orientation tag
11361 // present in the Exif buffer.
11362 4 err = av_exif_parse_buffer(s, buf, ref->extent_length, ifd, AV_EXIF_T_OFF);
11363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0) {
11364 ✗ av_log(s, AV_LOG_ERROR, "Unable to parse Exif metadata\n");
11365 ✗ goto fail;
11366 }
11367
11368 4 err = av_exif_remove_entry(s, ifd, orientation_id, 0);
11369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
11370 ✗ goto fail;
11371
11372 4 err = 0;
11373 4 fail:
11374 4 av_free(buf);
11375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
11376 ✗ av_exif_free(ifd);
11377 4 avio_seek(s->pb, pos, SEEK_SET);
11378
11379 4 return err;
11380 }
11381
11382 66 static int mov_apply_heif_item_references(AVFormatContext *s, HEIFItem *item,
11383 AVPacketSideData **coded_side_data,
11384 int *nb_coded_side_data)
11385 {
11386 int err;
11387
11388 /* exif */
11389
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 62 times.
66 if (item->ifd.count) {
11390 4 err = set_exif_from_item(s, coded_side_data, nb_coded_side_data, item);
11391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
11392 ✗ return err;
11393 }
11394
11395 /* rotation */
11396
4/6
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 60 times.
66 if (item->rotation || item->hflip || item->vflip) {
11397 6 err = set_display_matrix_from_item(coded_side_data, nb_coded_side_data, item);
11398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
11399 ✗ return err;
11400 }
11401
11402 /* ICC profile */
11403
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 62 times.
66 if (item->icc_profile_size) {
11404 4 err = set_icc_profile_from_item(coded_side_data, nb_coded_side_data, item);
11405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
11406 ✗ return err;
11407 }
11408
11409 66 return 0;
11410 }
11411
11412 66 static int mov_parse_heif_item_references(AVFormatContext *s, HEIFItem *item,
11413 AVPacketSideData **coded_side_data,
11414 int *nb_coded_side_data)
11415 {
11416 66 MOVContext *mov = s->priv_data;
11417 int err;
11418
11419
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 66 times.
76 for (int j = 0; j < item->nb_iref_from_list; j++) {
11420 10 HEIFItem *ref = get_heif_item(mov, item->iref_from_list[j].item_id);
11421
11422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 av_assert0(ref);
11423
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
10 switch(ref->type) {
11424 4 case MKTAG('E','x','i','f'):
11425 4 err = mov_parse_exif_item(s, item, ref);
11426
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 if (err < 0 && (s->error_recognition & AV_EF_EXPLODE))
11427 ✗ return err;
11428 4 break;
11429 6 default:
11430 6 break;
11431 }
11432 }
11433
11434 66 err = mov_apply_heif_item_references(s, item, coded_side_data, nb_coded_side_data);
11435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (err < 0)
11436 ✗ return err;
11437
11438 66 return 0;
11439 }
11440
11441 11 static int mov_parse_tiles(AVFormatContext *s)
11442 {
11443 11 MOVContext *mov = s->priv_data;
11444
11445
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 11 times.
24 for (int i = 0; i < mov->nb_heif_group; i++) {
11446 AVStreamGroup *stg;
11447 AVStreamGroupTileGrid *tile_grid;
11448 13 const HEIFGroup *grid = &mov->heif_group[i];
11449 int err;
11450
11451
3/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 7 times.
13 if (!grid->item || (grid->item->type != MKTAG('g','r','i','d') &&
11452
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 grid->item->type != MKTAG('i','o','v','l')))
11453 2 continue;
11454
11455 11 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
11456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!stg)
11457 ✗ return AVERROR(ENOMEM);
11458
11459 11 stg->id = grid->item->item_id;
11460 11 tile_grid = stg->params.tile_grid;
11461
11462
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 11 times.
47 for (int j = 0; j < grid->nb_items; j++) {
11463 36 int tile_id = grid->item_id_list[j];
11464 36 HEIFItem *item = get_heif_item(mov, tile_id);
11465 AVStream *st;
11466
11467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!item) {
11468 ✗ av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
11469 "exist\n",
11470 ✗ tile_id, grid->item->item_id);
11471 ✗ ff_remove_stream_group(s, stg);
11472 ✗ stg = NULL;
11473 ✗ break;
11474 }
11475
11476 36 st = item->st;
11477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!st) {
11478 ✗ av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
11479 "reference a stream\n",
11480 ✗ tile_id, grid->item->item_id);
11481 ✗ ff_remove_stream_group(s, stg);
11482 ✗ stg = NULL;
11483 ✗ break;
11484 }
11485
11486 36 grid->item_list[j] = item;
11487 36 grid->item_idx_list[j] = stg->nb_entries;
11488
11489 36 err = avformat_stream_group_add_stream(stg, st);
11490
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 34 times.
36 if (err < 0) {
11491 int l;
11492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
11493 ✗ return err;
11494
11495
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_entries; l++)
11496
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->entries[l]->stream->index == st->index)
11497 2 break;
11498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_entries);
11499 2 grid->item_idx_list[j] = l;
11500 }
11501
11502
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 6 times.
36 if (item->item_id != mov->primary_item_id)
11503 30 st->disposition |= AV_DISPOSITION_DEPENDENT;
11504 }
11505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!stg)
11506 ✗ continue;
11507
11508
2/3
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
11 switch (grid->item->type) {
11509 7 case MKTAG('g','r','i','d'):
11510 7 err = read_image_grid(s, grid, tile_grid);
11511 7 break;
11512 4 case MKTAG('i','o','v','l'):
11513 4 err = read_image_iovl(s, grid, tile_grid);
11514 4 break;
11515 ✗ default:
11516 ✗ av_assert0(0);
11517 }
11518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11519 ✗ return err;
11520
11521 11 err = mov_parse_heif_item_references(s, grid->item, &stg->coded_side_data,
11522 &stg->nb_coded_side_data);
11523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11524 ✗ return err;
11525
11526
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 if (grid->item->name)
11527 9 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
11528
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
11 if (grid->item->item_id == mov->primary_item_id)
11529 7 stg->disposition |= AV_DISPOSITION_DEFAULT;
11530
11531 11 grid->item->stg = stg;
11532 }
11533
11534 11 return 0;
11535 }
11536
11537 2 static int mov_parse_heif_layered_video_tmap(AVFormatContext *s, const HEIFGroup *tmap)
11538 {
11539 2 MOVContext *mov = s->priv_data;
11540 AVStreamGroup *stg;
11541 AVStreamGroupLayeredVideo *layered_video;
11542 2 AVGainMapParams *gain = NULL;
11543 2 uint8_t *payload = NULL;
11544 2 int64_t pos, offset = 0;
11545 size_t gain_size;
11546 int64_t err64;
11547 int err;
11548
11549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11550 ✗ av_log(s, AV_LOG_WARNING, "tmap box with non seekable input\n");
11551 ✗ return 0;
11552 }
11553
11554 2 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_GAIN_MAP, NULL);
11555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!stg)
11556 ✗ return AVERROR(ENOMEM);
11557
11558 2 stg->id = tmap->item->item_id;
11559 2 layered_video = stg->params.layered_video;
11560
11561
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int j = 0; j < tmap->nb_items; j++) {
11562 4 int item_id = tmap->item_id_list[j];
11563 4 HEIFItem *item = get_heif_item(mov, item_id);
11564 AVStreamGroup *child_stg;
11565 AVStream *st;
11566
11567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!item) {
11568 ✗ av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by tmap id %d doesn't "
11569 "exist\n",
11570 ✗ item_id, tmap->item->item_id);
11571 ✗ ff_remove_stream_group(s, stg);
11572 ✗ return 0;
11573 }
11574
11575 4 st = item->st;
11576 4 child_stg = item->stg;
11577
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
4 if (!st && !child_stg) {
11578 ✗ av_log(s, AV_LOG_WARNING, "HEIF item id %d from tmap id %d doesn't "
11579 "reference a stream or tmap\n",
11580 ✗ item_id, tmap->item->item_id);
11581 ✗ ff_remove_stream_group(s, stg);
11582 ✗ return 0;
11583 }
11584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 av_assert0(!st != !child_stg);
11585
11586 4 tmap->item_list[j] = item;
11587
11588
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (st)
11589 2 err = avformat_stream_group_add_stream(stg, st);
11590 else
11591 2 err = avformat_stream_group_add_stream_group(stg, child_stg);
11592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0) {
11593 ✗ if (err == AVERROR(EEXIST))
11594 ✗ err = AVERROR_INVALIDDATA;
11595
11596 ✗ return err;
11597 }
11598
11599
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if ((item->flags & MOV_INFE_FLAG_HIDDEN)) {
11600
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (st)
11601 2 st->disposition |= AV_DISPOSITION_DEPENDENT;
11602 else
11603 ✗ child_stg->disposition |= AV_DISPOSITION_DEPENDENT;
11604 }
11605 }
11606
11607 2 layered_video->width = tmap->item->width;
11608 2 layered_video->height = tmap->item->height;
11609
11610
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (tmap->item->is_idat_relative) {
11611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!mov->idat_offset) {
11612 ✗ av_log(s, AV_LOG_ERROR, "Missing idat box required by the tmap\n");
11613 ✗ return AVERROR_INVALIDDATA;
11614 }
11615 2 offset = mov->idat_offset;
11616 }
11617
11618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset > INT64_MAX - tmap->item->extent_offset)
11619 ✗ return AVERROR_INVALIDDATA;
11620
11621 2 gain = av_gain_map_params_alloc(&gain_size);
11622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!gain)
11623 ✗ return AVERROR(ENOMEM);
11624
11625 2 payload = av_malloc(tmap->item->extent_length);
11626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!payload) {
11627 ✗ return AVERROR(ENOMEM);
11628 goto fail;
11629 }
11630
11631 2 pos = avio_tell(s->pb);
11632 2 err64 = avio_seek(s->pb, tmap->item->extent_offset + offset, SEEK_SET);
11633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err64 != tmap->item->extent_offset + offset) {
11634 ✗ err64 = err64 < 0 ? err64 : AVERROR_INVALIDDATA;
11635 ✗ goto fail;
11636 }
11637 2 avio_r8(s->pb); /* version */
11638
11639 2 err = avio_read(s->pb, payload, tmap->item->extent_length);
11640
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (err == tmap->item->extent_length)
11641 2 err64 = avio_seek(s->pb, pos, SEEK_SET);
11642 else {
11643 ✗ err = err < 0 ? err : AVERROR_INVALIDDATA;
11644 ✗ goto fail;
11645 }
11646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err64 != pos) {
11647 ✗ err = err64 < 0 ? err64 : AVERROR_INVALIDDATA;
11648 ✗ goto fail;
11649 }
11650
11651 2 err = av_gain_map_params_from_iso21496(gain, payload, tmap->item->extent_length);
11652 2 av_freep(&payload);
11653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11654 ✗ goto fail;
11655
11656
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (int j = 0; j < tmap->nb_items; j++) {
11657 4 HEIFItem *item = tmap->item_list[j];
11658 AVPacketSideData *sd;
11659 AVPacketSideData **coded_side_data;
11660 int *nb_coded_side_data;
11661
11662
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (!(item->flags & MOV_INFE_FLAG_HIDDEN))
11663 2 continue;
11664
11665 2 layered_video->el_index = j;
11666
11667
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (item->st) {
11668 2 coded_side_data = &item->st->codecpar->coded_side_data;
11669 2 nb_coded_side_data = &item->st->codecpar->nb_coded_side_data;
11670 } else {
11671 ✗ av_assert0(item->stg);
11672 ✗ coded_side_data = &item->stg->coded_side_data;
11673 ✗ nb_coded_side_data = &item->stg->nb_coded_side_data;
11674 }
11675
11676 2 sd = av_packet_side_data_add(coded_side_data, nb_coded_side_data,
11677 AV_PKT_DATA_GAIN_MAP_PARAMS,
11678 (uint8_t *)gain, gain_size, 0);
11679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!sd) {
11680 ✗ av_free(gain);
11681 ✗ return AVERROR(ENOMEM);
11682 }
11683 2 gain = NULL;
11684
11685 2 break;
11686 }
11687 2 av_free(gain);
11688
11689 2 err = mov_parse_heif_item_references(s, tmap->item, &stg->coded_side_data,
11690 &stg->nb_coded_side_data);
11691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11692 ✗ return err;
11693
11694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tmap->item->name)
11695 ✗ av_dict_set(&stg->metadata, "title", tmap->item->name, 0);
11696
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tmap->item->item_id == mov->primary_item_id)
11697 ✗ stg->disposition |= AV_DISPOSITION_DEFAULT;
11698
11699 2 tmap->item->stg = stg;
11700
11701 2 return 0;
11702 ✗ fail:
11703 ✗ av_free(gain);
11704 ✗ av_free(payload);
11705
11706 ✗ return err;
11707 }
11708
11709 // Parse Apple style Gain Map metadata from Exif values
11710 // See https://developer.apple.com/documentation/appkit/applying-apple-hdr-effect-to-your-photos
11711 2 static int mov_parse_heif_layered_video_auxl(AVFormatContext *s,
11712 HEIFItem *base, HEIFItem *gain_map)
11713 {
11714 AVStreamGroupLayeredVideo *layered_video;
11715 AVStreamGroup *stg;
11716 AVGainMapParams *gain;
11717 AVPacketSideData **coded_side_data;
11718 int *nb_coded_side_data;
11719 2 AVExifEntry *entry, *maker33 = NULL, *maker48 = NULL;
11720 2 double maker_33 = 0.0, maker_48 = 0.0, headroom;
11721 size_t gain_size;
11722 int err;
11723
11724
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if ((!gain_map->st && !gain_map->stg) ||
11725
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 (!base->st && !base->stg)) {
11726 ✗ av_log(s, AV_LOG_WARNING, "HEIF gain_map id %d or its base doesn't reference "
11727 "a stream or group\n",
11728 gain_map->item_id);
11729 ✗ return 0;
11730 }
11731
11732
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!base->ifd.count)
11733 ✗ return 0;
11734
11735 2 err = av_exif_get_entry(s, &base->ifd, 0x8769, 0, &entry);
11736
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (err > 0)
11737 2 err = av_exif_get_entry(s, &entry->value.ifd, 0x927c, 0, &entry);
11738
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (err > 0) {
11739 2 av_exif_get_entry(s, &entry->value.ifd, 0x21, 0, &maker33);
11740 2 av_exif_get_entry(s, &entry->value.ifd, 0x30, 0, &maker48);
11741 }
11742
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if ((!maker33 && !maker48) ||
11743 ✗ (maker33 && maker33->type != AV_TIFF_SRATIONAL) ||
11744 ✗ (maker48 && maker48->type != AV_TIFF_SRATIONAL))
11745 2 return 0;
11746
11747 ✗ if (maker33)
11748 ✗ maker_33 = av_q2d(*maker33->value.rat);
11749 ✗ if (maker48)
11750 ✗ maker_48 = av_q2d(*maker48->value.rat);
11751
11752 ✗ if (maker_33 < 1.0) {
11753 ✗ if (maker_48 <= 0.01) {
11754 ✗ headroom = -20.0 * maker_48 + 1.8;
11755 } else {
11756 ✗ headroom = -0.101 * maker_48 + 1.601;
11757 }
11758 } else {
11759 ✗ if (maker_48 <= 0.01) {
11760 ✗ headroom = -70.0 * maker_48 + 3.0;
11761 } else {
11762 ✗ headroom = -0.303 * maker_48 + 2.303;
11763 }
11764 }
11765 ✗ if (headroom <= 0.0)
11766 ✗ return 0;
11767
11768 ✗ stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_GAIN_MAP, NULL);
11769 ✗ if (!stg)
11770 ✗ return AVERROR(ENOMEM);
11771
11772 ✗ stg->id = gain_map->item_id;
11773 ✗ layered_video = stg->params.layered_video;
11774
11775 ✗ layered_video->width = base->width;
11776 ✗ layered_video->height = base->height;
11777 ✗ layered_video->el_index = 1;
11778
11779 ✗ av_assert0(!base->st != !base->stg);
11780 ✗ if (base->st)
11781 ✗ err = avformat_stream_group_add_stream(stg, base->st);
11782 else
11783 ✗ err = avformat_stream_group_add_stream_group(stg, base->stg);
11784 ✗ if (err < 0) {
11785 ✗ if (err == AVERROR(EEXIST))
11786 ✗ err = AVERROR_INVALIDDATA;
11787 ✗ return err;
11788 }
11789
11790 ✗ av_assert0(!gain_map->st != !gain_map->stg);
11791 ✗ if (gain_map->st) {
11792 ✗ coded_side_data = &gain_map->st->codecpar->coded_side_data;
11793 ✗ nb_coded_side_data = &gain_map->st->codecpar->nb_coded_side_data;
11794 ✗ err = avformat_stream_group_add_stream(stg, gain_map->st);
11795 } else {
11796 ✗ coded_side_data = &gain_map->stg->coded_side_data;
11797 ✗ nb_coded_side_data = &gain_map->stg->nb_coded_side_data;
11798 ✗ err = avformat_stream_group_add_stream_group(stg, gain_map->stg);
11799 }
11800 ✗ if (err < 0) {
11801 ✗ if (err == AVERROR(EEXIST))
11802 ✗ err = AVERROR_INVALIDDATA;
11803 ✗ return err;
11804 }
11805
11806 ✗ gain = av_gain_map_params_alloc(&gain_size);
11807 ✗ if (!gain)
11808 ✗ return AVERROR(ENOMEM);
11809
11810 ✗ gain->use_base_color_space = 1;
11811 ✗ gain->alternate_hdr_headroom = av_d2q(headroom, INT_MAX);
11812 ✗ gain->nb_channels = 1;
11813 ✗ gain->channels[0].base_offset = (AVRational) { 0, 1 };
11814 ✗ gain->channels[0].alternate_offset = (AVRational) { 0, 1 };
11815 ✗ gain->channels[0].gain_map_max = gain->alternate_hdr_headroom;
11816
11817 ✗ AVPacketSideData *sd = av_packet_side_data_add(coded_side_data, nb_coded_side_data,
11818 AV_PKT_DATA_GAIN_MAP_PARAMS,
11819 (uint8_t *)gain, gain_size, 0);
11820 ✗ if (!sd) {
11821 ✗ av_free(gain);
11822 ✗ return AVERROR(ENOMEM);
11823 }
11824
11825 // Apply all references from the base image except Exif to the Gain Map group
11826 ✗ int count = base->ifd.count;
11827 ✗ base->ifd.count = 0;
11828 ✗ err = mov_apply_heif_item_references(s, base, &stg->coded_side_data,
11829 &stg->nb_coded_side_data);
11830 ✗ base->ifd.count = count;
11831 ✗ if (err < 0)
11832 ✗ return err;
11833
11834 ✗ return 0;
11835 }
11836
11837 11 static int mov_parse_heif_layered_video(AVFormatContext *s)
11838 {
11839 11 MOVContext *mov = s->priv_data;
11840 int err;
11841
11842
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 11 times.
24 for (int i = 0; i < mov->nb_heif_group; i++) {
11843 13 const HEIFGroup *tmap = &mov->heif_group[i];
11844
11845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!tmap->item)
11846 ✗ continue;
11847
11848
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
13 switch (tmap->item->type) {
11849 2 case MKTAG('t','m','a','p'):
11850 2 err = mov_parse_heif_layered_video_tmap(s, tmap);
11851
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11852 ✗ return err;
11853 2 break;
11854 11 default:
11855 11 break;
11856 }
11857 }
11858
11859
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 11 times.
66 for (int i = 0; i < mov->nb_heif_item; i++) {
11860 55 HEIFItem *item = mov->heif_item[i];
11861 int err;
11862
11863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
55 if (!item)
11864 ✗ continue;
11865
11866
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 55 times.
57 for (int j = 0; j < item->nb_iref_to_list; j++) {
11867 2 HEIFItem *ref = get_heif_item(mov, item->iref_to_list[j].item_id);
11868
11869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(ref);
11870
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 switch(item->iref_to_list[j].type) {
11871 2 case MKTAG('a','u','x','l'):
11872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!item->is_gainmap)
11873 ✗ break;
11874
11875 2 err = mov_parse_heif_layered_video_auxl(s, ref, item);
11876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11877 ✗ return err;
11878 2 break;
11879 }
11880 }
11881 }
11882
11883 11 return 0;
11884 }
11885
11886 20 static int mov_parse_heif_items(AVFormatContext *s)
11887 {
11888 20 MOVContext *mov = s->priv_data;
11889 int err;
11890
11891
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 20 times.
97 for (int i = 0; i < mov->nb_heif_item; i++) {
11892 77 HEIFItem *item = mov->heif_item[i];
11893 MOVStreamContext *sc;
11894 AVStream *st;
11895 77 int64_t offset = 0;
11896
11897
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (!item)
11898 ✗ continue;
11899
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 53 times.
77 if (!item->st) {
11900 24 continue;
11901 }
11902
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (item->is_idat_relative) {
11903 ✗ if (!mov->idat_offset) {
11904 ✗ av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
11905 ✗ return AVERROR_INVALIDDATA;
11906 }
11907 ✗ offset = mov->idat_offset;
11908 }
11909
11910 53 st = item->st;
11911 53 sc = st->priv_data;
11912 53 st->codecpar->width = item->width;
11913 53 st->codecpar->height = item->height;
11914
11915 53 sc->sample_size = sc->stsz_sample_size = item->extent_length;
11916 53 sc->sample_count = 1;
11917
11918 53 err = sanity_checks(s, sc, st->index);
11919
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (err)
11920 ✗ return AVERROR_INVALIDDATA;
11921
11922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (offset > INT64_MAX - item->extent_offset)
11923 ✗ return AVERROR_INVALIDDATA;
11924
11925 53 sc->chunk_offsets[0] = item->extent_offset + offset;
11926
11927 53 err = mov_parse_heif_item_references(s, item, &st->codecpar->coded_side_data,
11928 53 &st->codecpar->nb_coded_side_data);
11929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (err < 0)
11930 ✗ return err;
11931
11932
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 10 times.
53 if (item->name)
11933 43 av_dict_set(&st->metadata, "title", item->name, 0);
11934
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 40 times.
53 if (item->item_id == mov->primary_item_id)
11935 13 st->disposition |= AV_DISPOSITION_DEFAULT;
11936
11937 53 mov_build_index(mov, st);
11938 }
11939
11940
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 9 times.
20 if (mov->nb_heif_group) {
11941 11 err = mov_parse_tiles(s);
11942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11943 ✗ return err;
11944
11945 11 err = mov_parse_heif_layered_video(s);
11946
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11947 ✗ return err;
11948 }
11949
11950 20 return 0;
11951 }
11952
11953 625 static int mov_parse_tmcd_streams(AVFormatContext *s)
11954 {
11955 int err;
11956
11957
2/2
✓ Branch 0 taken 959 times.
✓ Branch 1 taken 625 times.
1584 for (int i = 0; i < s->nb_streams; i++) {
11958 AVStreamGroup *stg;
11959 const AVDictionaryEntry *tcr;
11960 959 AVStream *st = s->streams[i];
11961
11962
2/2
✓ Branch 0 taken 931 times.
✓ Branch 1 taken 28 times.
959 if (st->codecpar->codec_tag != MKTAG('t','m','c','d'))
11963 931 continue;
11964
11965 28 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TREF, NULL);
11966
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!stg)
11967 ✗ return AVERROR(ENOMEM);
11968
11969 28 stg->id = st->id;
11970 28 tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
11971
11972
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 28 times.
134 for (int j = 0; j < s->nb_streams; j++) {
11973 106 AVStream *st2 = s->streams[j];
11974 106 MOVStreamContext *sc2 = st2->priv_data;
11975 106 MovTref *tag = mov_find_tref_tag(sc2, MKTAG('t','m','c','d'));
11976
11977
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 29 times.
106 if (!tag)
11978 77 continue;
11979
11980
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 29 times.
88 for (int k = 0; k < tag->nb_id; k++) {
11981
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 29 times.
59 if (tag->id[k] != st->id)
11982 30 continue;
11983
11984 29 err = avformat_stream_group_add_stream(stg, st2);
11985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (err < 0)
11986 ✗ return err;
11987
11988
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (tcr)
11989 29 av_dict_set(&st2->metadata, "timecode", tcr->value, AV_DICT_DONT_OVERWRITE);
11990 }
11991 }
11992
11993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!stg->nb_entries) {
11994 ✗ ff_remove_stream_group(s, stg);
11995 ✗ continue;
11996 }
11997
11998 28 err = avformat_stream_group_add_stream(stg, st);
11999
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (err < 0)
12000 ✗ return err;
12001
12002 28 stg->params.tref->metadata_index = stg->nb_entries - 1;
12003 }
12004 625 export_orphan_timecode(s);
12005
12006 625 return 0;
12007 }
12008
12009 11 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
12010 uint32_t *tref_id, int nb_tref_id, int first_index)
12011 {
12012
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!nb_tref_id)
12013 ✗ return NULL;
12014
12015
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 for (int i = first_index; i < s->nb_streams; i++)
12016
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 for (int j = 0; j < nb_tref_id; j++)
12017
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (s->streams[i]->index != st->index &&
12018
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 s->streams[i]->id == tref_id[j])
12019 11 return s->streams[i];
12020
12021 ✗ return NULL;
12022 }
12023
12024 625 static int mov_parse_cdsc_and_rndr_streams(AVFormatContext *s)
12025 {
12026 static const uint32_t tref_tags[] = {
12027 MKTAG('c','d','s','c'),
12028 MKTAG('r','n','d','r'),
12029 };
12030
12031 int err;
12032
12033 // Don't try to add a group if there's only one track
12034
2/2
✓ Branch 0 taken 503 times.
✓ Branch 1 taken 122 times.
625 if (s->nb_streams <= 1)
12035 503 return 0;
12036
12037
2/2
✓ Branch 0 taken 456 times.
✓ Branch 1 taken 122 times.
578 for (int i = 0; i < s->nb_streams; i++) {
12038 456 AVStream *st = s->streams[i];
12039 456 MOVStreamContext *sc = st->priv_data;
12040
12041
2/2
✓ Branch 0 taken 912 times.
✓ Branch 1 taken 456 times.
1368 for (int c = 0; c < FF_ARRAY_ELEMS(tref_tags); c++) {
12042 AVStreamGroup *stg;
12043 AVStream *st_ref;
12044 912 MovTref *tag = mov_find_tref_tag(sc, tref_tags[c]);
12045
12046
2/2
✓ Branch 0 taken 901 times.
✓ Branch 1 taken 11 times.
912 if (!tag)
12047 901 continue;
12048
12049 11 st_ref = mov_find_reference_track(s, st, tag->id, tag->nb_id, 0);
12050
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!st_ref) {
12051 ✗ av_log(s, AV_LOG_WARNING, "Failed to find referenced stream\n");
12052 ✗ continue;
12053 }
12054
12055 11 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TREF, NULL);
12056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!stg)
12057 ✗ return AVERROR(ENOMEM);
12058
12059 11 stg->id = st_ref->id;
12060
12061 11 err = avformat_stream_group_add_stream(stg, st_ref);
12062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
12063 ✗ return err;
12064
12065 11 err = avformat_stream_group_add_stream(stg, st);
12066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
12067 ✗ return err;
12068
12069 11 stg->params.tref->metadata_index = stg->nb_entries - 1;
12070 }
12071 }
12072
12073 122 return 0;
12074 }
12075
12076 625 static int mov_parse_lcevc_streams(AVFormatContext *s)
12077 {
12078 int err;
12079
12080 // Don't try to add a group if there's only one track
12081
2/2
✓ Branch 0 taken 503 times.
✓ Branch 1 taken 122 times.
625 if (s->nb_streams <= 1)
12082 503 return 0;
12083
12084
2/2
✓ Branch 0 taken 456 times.
✓ Branch 1 taken 122 times.
578 for (int i = 0; i < s->nb_streams; i++) {
12085 AVStreamGroup *stg;
12086 456 AVStream *st = s->streams[i];
12087 AVStream *st_base;
12088 456 MOVStreamContext *sc = st->priv_data;
12089 456 MovTref *tag = mov_find_tref_tag(sc, MKTAG('s','b','a','s'));
12090 456 int j = 0;
12091
12092 /* Find an enhancement stream. */
12093
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 456 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
456 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC || !tag)
12094 456 continue;
12095
12096 ✗ stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
12097 ✗ if (!stg)
12098 ✗ return AVERROR(ENOMEM);
12099
12100 ✗ stg->id = st->id;
12101 ✗ stg->params.layered_video->width = st->codecpar->width;
12102 ✗ stg->params.layered_video->height = st->codecpar->height;
12103
12104 ✗ while (st_base = mov_find_reference_track(s, st, tag->id, tag->nb_id, j)) {
12105 ✗ err = avformat_stream_group_add_stream(stg, st_base);
12106 ✗ if (err < 0)
12107 ✗ return err;
12108
12109 ✗ j = st_base->index + 1;
12110 }
12111 ✗ if (!j) {
12112 ✗ int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
12113 ✗ av_log(s, loglevel, "Failed to find base stream for LCEVC stream\n");
12114 ✗ ff_remove_stream_group(s, stg);
12115 ✗ if (s->error_recognition & AV_EF_EXPLODE)
12116 ✗ return AVERROR_INVALIDDATA;
12117 ✗ continue;
12118 }
12119
12120 ✗ err = avformat_stream_group_add_stream(stg, st);
12121 ✗ if (err < 0)
12122 ✗ return err;
12123
12124 ✗ stg->params.layered_video->el_index = stg->nb_entries - 1;
12125 }
12126
12127 122 return 0;
12128 }
12129
12130 625 static int mov_parse_dovi_streams(AVFormatContext *s)
12131 {
12132 int err;
12133
12134
2/2
✓ Branch 0 taken 503 times.
✓ Branch 1 taken 122 times.
625 if (s->nb_streams <= 1)
12135 503 return 0;
12136
12137 /* Identify legacy dual-track Dolby Vision profile 7 carriage per Annex
12138 * C of "Dolby Vision Streams Within the ISO Base Media File Format",
12139 * v2.7.1. The 'vdep' track reference type is shared with depth video
12140 * and multi-view dependencies. The spec-mandated DV-specific sample
12141 * entry combined with the dvcC configuration record disambiguates
12142 * those uses. */
12143
2/2
✓ Branch 0 taken 456 times.
✓ Branch 1 taken 122 times.
578 for (int i = 0; i < s->nb_streams; i++) {
12144 AVStreamGroup *stg;
12145 456 AVStream *st = s->streams[i];
12146 AVStream *st_base;
12147 456 MOVStreamContext *sc = st->priv_data;
12148 456 MovTref *tag = mov_find_tref_tag(sc, MKTAG('v','d','e','p'));
12149 const AVPacketSideData *sd;
12150 const AVDOVIDecoderConfigurationRecord *dovi;
12151
12152
3/4
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 404 times.
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
456 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !tag)
12153 456 continue;
12154
12155 ✗ if (st->codecpar->codec_tag != MKTAG('d','v','h','e') &&
12156 ✗ st->codecpar->codec_tag != MKTAG('d','v','h','1'))
12157 ✗ continue;
12158
12159 ✗ sd = av_packet_side_data_get(st->codecpar->coded_side_data,
12160 ✗ st->codecpar->nb_coded_side_data,
12161 AV_PKT_DATA_DOVI_CONF);
12162 ✗ if (!sd)
12163 ✗ continue;
12164 ✗ dovi = (const AVDOVIDecoderConfigurationRecord *)sd->data;
12165
12166 /* EL track of a dual-track stream: rpu_present_flag = 1,
12167 * el_present_flag = 1, bl_present_flag = 0, dv_profile = 7. */
12168 ✗ if (dovi->dv_profile != 7 || !dovi->rpu_present_flag ||
12169 ✗ !dovi->el_present_flag || dovi->bl_present_flag)
12170 ✗ continue;
12171
12172 ✗ st_base = mov_find_reference_track(s, st, tag->id, tag->nb_id, 0);
12173 ✗ if (!st_base) {
12174 ✗ int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
12175 ✗ av_log(s, loglevel, "Failed to find base layer for Dolby Vision EL stream\n");
12176 ✗ if (s->error_recognition & AV_EF_EXPLODE)
12177 ✗ return AVERROR_INVALIDDATA;
12178 ✗ continue;
12179 }
12180
12181 ✗ stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_DOLBY_VISION, NULL);
12182 ✗ if (!stg)
12183 ✗ return AVERROR(ENOMEM);
12184
12185 ✗ stg->id = st->id;
12186
12187 ✗ err = avformat_stream_group_add_stream(stg, st_base);
12188 ✗ if (err < 0)
12189 ✗ return err;
12190
12191 ✗ err = avformat_stream_group_add_stream(stg, st);
12192 ✗ if (err < 0)
12193 ✗ return err;
12194
12195 ✗ stg->params.layered_video->el_index = stg->nb_entries - 1;
12196 ✗ stg->params.layered_video->width = st_base->codecpar->width;
12197 ✗ stg->params.layered_video->height = st_base->codecpar->height;
12198 }
12199
12200 122 return 0;
12201 }
12202
12203 625 static void fix_stream_ids(AVFormatContext *s)
12204 {
12205 625 int highest_id = 0, lowest_iamf_id = INT_MAX;
12206
12207
2/2
✓ Branch 0 taken 959 times.
✓ Branch 1 taken 625 times.
1584 for (int i = 0; i < s->nb_streams; i++) {
12208 959 const AVStream *st = s->streams[i];
12209 959 const MOVStreamContext *sc = st->priv_data;
12210
2/2
✓ Branch 0 taken 895 times.
✓ Branch 1 taken 64 times.
959 if (!sc->iamf)
12211 895 highest_id = FFMAX(highest_id, st->id);
12212 }
12213
12214
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 625 times.
701 for (int i = 0; i < s->nb_stream_groups; i++) {
12215 76 AVStreamGroup *stg = s->stream_groups[i];
12216
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
12217 64 continue;
12218
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_entries; j++) {
12219 64 AVStream *st = stg->entries[j]->stream;
12220 64 lowest_iamf_id = FFMIN(lowest_iamf_id, st->id);
12221 }
12222 }
12223
12224
2/2
✓ Branch 0 taken 617 times.
✓ Branch 1 taken 8 times.
625 if (highest_id < lowest_iamf_id)
12225 617 return;
12226
12227 8 highest_id += !lowest_iamf_id;
12228
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
12 for (int i = 0; highest_id > 1 && i < s->nb_stream_groups; i++) {
12229 4 AVStreamGroup *stg = s->stream_groups[i];
12230
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
12231 2 continue;
12232
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_entries; j++) {
12233 14 AVStream *st = stg->entries[j]->stream;
12234 14 MOVStreamContext *sc = st->priv_data;
12235 14 st->id += highest_id;
12236 14 sc->iamf_stream_offset = highest_id;
12237 }
12238 }
12239 }
12240
12241 625 static int mov_read_header(AVFormatContext *s)
12242 {
12243 625 MOVContext *mov = s->priv_data;
12244 625 AVIOContext *pb = s->pb;
12245 int j, err;
12246 625 MOVAtom atom = { AV_RL32("root") };
12247 int i;
12248
12249 625 mov->fc = s;
12250 625 mov->trak_index = -1;
12251 625 mov->primary_item_id = -1;
12252 625 mov->cur_item_id = -1;
12253 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
12254
2/2
✓ Branch 0 taken 623 times.
✓ Branch 1 taken 2 times.
625 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
12255 623 atom.size = avio_size(pb);
12256 else
12257 2 atom.size = INT64_MAX;
12258
12259 /* check MOV header */
12260 do {
12261
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
625 if (mov->moov_retry)
12262 ✗ avio_seek(pb, 0, SEEK_SET);
12263
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 625 times.
625 if ((err = mov_read_default(mov, pb, atom)) < 0) {
12264 ✗ av_log(s, AV_LOG_ERROR, "error reading header\n");
12265 ✗ return err;
12266 }
12267 1248 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
12268
6/10
✓ Branch 0 taken 623 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 603 times.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
625 !mov->found_moov && (!mov->found_iloc || !mov->found_iinf) && !mov->moov_retry++);
12269
3/6
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 605 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
625 if (!mov->found_moov && !mov->found_iloc && !mov->found_iinf) {
12270 ✗ av_log(s, AV_LOG_ERROR, "moov atom not found\n");
12271 ✗ return AVERROR_INVALIDDATA;
12272 }
12273 625 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
12274
12275
3/4
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 605 times.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
625 if (mov->found_iloc && mov->found_iinf) {
12276 20 err = mov_parse_heif_items(s);
12277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (err < 0)
12278 ✗ return err;
12279 }
12280 // prevent iloc and iinf boxes from being parsed while reading packets.
12281 // this is needed because an iinf box may have been parsed but ignored
12282 // for having old infe boxes which create no streams.
12283 625 mov->found_iloc = mov->found_iinf = 1;
12284
12285
2/2
✓ Branch 0 taken 623 times.
✓ Branch 1 taken 2 times.
625 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
12286
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 621 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
623 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
12287 2 mov_read_chapters(s);
12288
2/2
✓ Branch 0 taken 858 times.
✓ Branch 1 taken 623 times.
1481 for (i = 0; i < s->nb_streams; i++)
12289
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 830 times.
858 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
12290 28 mov_read_timecode_track(s, s->streams[i]);
12291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 830 times.
830 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
12292 ✗ mov_read_rtmd_track(s, s->streams[i]);
12293 }
12294 }
12295
12296 /* Create metadata stream groups. */
12297 625 err = mov_parse_cdsc_and_rndr_streams(s);
12298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
625 if (err < 0)
12299 ✗ return err;
12300
12301 /* copy timecode metadata from tmcd tracks to the related video streams */
12302 625 err = mov_parse_tmcd_streams(s);
12303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
625 if (err < 0)
12304 ✗ return err;
12305
12306 /* Create LCEVC stream groups. */
12307 625 err = mov_parse_lcevc_streams(s);
12308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
625 if (err < 0)
12309 ✗ return err;
12310
12311 /* Create Dolby Vision Profile 7 stream groups. */
12312 625 err = mov_parse_dovi_streams(s);
12313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
625 if (err < 0)
12314 ✗ return err;
12315
12316
2/2
✓ Branch 0 taken 959 times.
✓ Branch 1 taken 625 times.
1584 for (i = 0; i < s->nb_streams; i++) {
12317 959 AVStream *st = s->streams[i];
12318 959 FFStream *const sti = ffstream(st);
12319 959 MOVStreamContext *sc = st->priv_data;
12320 959 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
12321 959 fix_timescale(mov, sc);
12322
12323 /* Set the primary extradata based on the first Sample if it doesn't reference the first stsd entry. */
12324
6/6
✓ Branch 0 taken 809 times.
✓ Branch 1 taken 150 times.
✓ Branch 2 taken 756 times.
✓ Branch 3 taken 53 times.
✓ Branch 4 taken 692 times.
✓ Branch 5 taken 64 times.
959 if (sc->stsc_count && sc->extradata_size && !sc->iamf &&
12325
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 689 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
692 sc->stsc_data[0].id > 1 && sc->stsc_data[0].id <= sc->stsd_count) {
12326 3 sc->last_stsd_index = sc->stsc_data[0].id - 1;
12327 3 av_freep(&st->codecpar->extradata);
12328 3 st->codecpar->extradata_size = sc->extradata_size[sc->last_stsd_index];
12329
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (sc->extradata_size[sc->last_stsd_index]) {
12330 3 st->codecpar->extradata = av_mallocz(sc->extradata_size[sc->last_stsd_index] + AV_INPUT_BUFFER_PADDING_SIZE);
12331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata)
12332 ✗ return AVERROR(ENOMEM);
12333 3 memcpy(st->codecpar->extradata, sc->extradata[sc->last_stsd_index], sc->extradata_size[sc->last_stsd_index]);
12334 }
12335 }
12336
12337
2/2
✓ Branch 0 taken 449 times.
✓ Branch 1 taken 510 times.
959 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
12338
2/2
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 295 times.
449 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
12339 154 sti->skip_samples = st->codecpar->initial_padding;
12340 }
12341
5/6
✓ Branch 0 taken 444 times.
✓ Branch 1 taken 515 times.
✓ Branch 2 taken 375 times.
✓ Branch 3 taken 69 times.
✓ Branch 4 taken 375 times.
✗ Branch 5 not taken.
959 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
12342 375 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
12343 375 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
12344
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 947 times.
959 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
12345
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
12 if (st->codecpar->width <= 0 || st->codecpar->height <= 0) {
12346 8 st->codecpar->width = sc->width;
12347 8 st->codecpar->height = sc->height;
12348 }
12349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
12350 ✗ st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
12351
12352 ✗ for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
12353 ✗ dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
12354
12355 ✗ err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
12356 ✗ if (err < 0)
12357 ✗ return err;
12358
12359 ✗ av_freep(&st->codecpar->extradata);
12360 ✗ st->codecpar->extradata_size = 0;
12361
12362 ✗ err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
12363 st->codecpar);
12364 ✗ if (err < 0)
12365 ✗ return err;
12366 }
12367 }
12368
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 958 times.
959 if (mov->handbrake_version &&
12369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
12370 ✗ st->codecpar->codec_id == AV_CODEC_ID_MP3) {
12371 ✗ av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
12372 ✗ sti->need_parsing = AVSTREAM_PARSE_FULL;
12373 }
12374 }
12375
12376
3/4
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 600 times.
625 if (mov->trex_data || mov->use_mfra_for > 0) {
12377
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 25 times.
158 for (i = 0; i < s->nb_streams; i++) {
12378 133 AVStream *st = s->streams[i];
12379 133 MOVStreamContext *sc = st->priv_data;
12380
2/2
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 4 times.
133 if (sc->duration_for_fps > 0) {
12381 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
12382 129 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
12383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 129 times.
129 if (st->codecpar->bit_rate == INT64_MIN) {
12384 ✗ av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
12385 sc->data_size, sc->time_scale);
12386 ✗ st->codecpar->bit_rate = 0;
12387 ✗ if (s->error_recognition & AV_EF_EXPLODE)
12388 ✗ return AVERROR_INVALIDDATA;
12389 }
12390 }
12391 }
12392 }
12393
12394
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
625 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
12395 ✗ if (mov->bitrates[i]) {
12396 ✗ s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
12397 }
12398 }
12399
12400 625 ff_rfps_calculate(s);
12401
12402
2/2
✓ Branch 0 taken 959 times.
✓ Branch 1 taken 625 times.
1584 for (i = 0; i < s->nb_streams; i++) {
12403 959 AVStream *st = s->streams[i];
12404 959 MOVStreamContext *sc = st->priv_data;
12405
12406
3/3
✓ Branch 0 taken 449 times.
✓ Branch 1 taken 444 times.
✓ Branch 2 taken 66 times.
959 switch (st->codecpar->codec_type) {
12407 449 case AVMEDIA_TYPE_AUDIO:
12408 449 err = ff_replaygain_export(st, s->metadata);
12409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 449 times.
449 if (err < 0)
12410 ✗ return err;
12411 449 break;
12412 444 case AVMEDIA_TYPE_VIDEO:
12413
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 436 times.
444 if (sc->display_matrix) {
12414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
12415 AV_PKT_DATA_DISPLAYMATRIX,
12416 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
12417 ✗ return AVERROR(ENOMEM);
12418
12419 8 sc->display_matrix = NULL;
12420 }
12421
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 438 times.
444 if (sc->stereo3d) {
12422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
12423 AV_PKT_DATA_STEREO3D,
12424 6 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
12425 ✗ return AVERROR(ENOMEM);
12426
12427 6 sc->stereo3d = NULL;
12428 }
12429
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 440 times.
444 if (sc->spherical) {
12430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
12431 AV_PKT_DATA_SPHERICAL,
12432 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
12433 ✗ return AVERROR(ENOMEM);
12434
12435 4 sc->spherical = NULL;
12436 }
12437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 444 times.
444 if (sc->mastering) {
12438 ✗ if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
12439 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
12440 ✗ (uint8_t *)sc->mastering, sc->mastering_size, 0))
12441 ✗ return AVERROR(ENOMEM);
12442
12443 ✗ sc->mastering = NULL;
12444 }
12445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 444 times.
444 if (sc->coll) {
12446 ✗ if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
12447 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
12448 ✗ (uint8_t *)sc->coll, sc->coll_size, 0))
12449 ✗ return AVERROR(ENOMEM);
12450
12451 ✗ sc->coll = NULL;
12452 }
12453
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 440 times.
444 if (sc->ambient) {
12454
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
12455 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
12456 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
12457 ✗ return AVERROR(ENOMEM);
12458
12459 4 sc->ambient = NULL;
12460 }
12461 444 break;
12462 }
12463 }
12464
12465 625 fix_stream_ids(s);
12466
12467 625 ff_configure_buffers_for_index(s, AV_TIME_BASE);
12468
12469
2/2
✓ Branch 0 taken 485 times.
✓ Branch 1 taken 625 times.
1110 for (i = 0; i < mov->frag_index.nb_items; i++)
12470
2/2
✓ Branch 0 taken 475 times.
✓ Branch 1 taken 10 times.
485 if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset)
12471 475 mov->frag_index.item[i].headers_read = 1;
12472
12473 625 return 0;
12474 }
12475
12476 121563 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
12477 {
12478 121563 AVIndexEntry *sample = NULL;
12479 121563 int64_t best_dts = INT64_MAX;
12480 int i;
12481 121563 MOVContext *mov = s->priv_data;
12482
3/4
✓ Branch 0 taken 121563 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2847 times.
✓ Branch 3 taken 118716 times.
121563 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
12483
2/2
✓ Branch 0 taken 433041 times.
✓ Branch 1 taken 121563 times.
554604 for (i = 0; i < s->nb_streams; i++) {
12484 433041 AVStream *avst = s->streams[i];
12485 433041 FFStream *const avsti = ffstream(avst);
12486 433041 MOVStreamContext *msc = avst->priv_data;
12487
4/4
✓ Branch 0 taken 423524 times.
✓ Branch 1 taken 9517 times.
✓ Branch 2 taken 281172 times.
✓ Branch 3 taken 142352 times.
433041 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
12488 281172 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
12489 281172 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
12490
2/2
✓ Branch 0 taken 255980 times.
✓ Branch 1 taken 25192 times.
281172 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
12491 281172 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
12492
5/6
✓ Branch 0 taken 160204 times.
✓ Branch 1 taken 120968 times.
✓ Branch 2 taken 138600 times.
✓ Branch 3 taken 21604 times.
✓ Branch 4 taken 138600 times.
✗ Branch 5 not taken.
281172 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
12493
2/2
✓ Branch 0 taken 21604 times.
✓ Branch 1 taken 138600 times.
160204 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
12494
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 21604 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 21604 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 21604 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19411 times.
✓ Branch 9 taken 2193 times.
21604 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
12495
4/4
✓ Branch 0 taken 11303 times.
✓ Branch 1 taken 8108 times.
✓ Branch 2 taken 2193 times.
✓ Branch 3 taken 11303 times.
21604 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
12496
3/4
✓ Branch 0 taken 761 times.
✓ Branch 1 taken 1432 times.
✓ Branch 2 taken 761 times.
✗ Branch 3 not taken.
2193 (dtsdiff > AV_TIME_BASE && dts < best_dts && mov->interleaved_read)))))) {
12497 129837 sample = current_sample;
12498 129837 best_dts = dts;
12499 129837 *st = avst;
12500 }
12501 }
12502 }
12503 121563 return sample;
12504 }
12505
12506 11 static int should_retry(AVIOContext *pb, int error_code) {
12507
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
11 if (error_code == AVERROR_EOF || avio_feof(pb))
12508 11 return 0;
12509
12510 ✗ return 1;
12511 }
12512
12513 51 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
12514 {
12515 int ret;
12516 51 MOVContext *mov = s->priv_data;
12517
12518
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 50 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
51 if (index >= 0 && index < mov->frag_index.nb_items)
12519 1 target = mov->frag_index.item[index].moof_offset;
12520
2/4
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 51 times.
51 if (target >= 0 && avio_seek(s->pb, target, SEEK_SET) != target) {
12521 ✗ av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
12522 ✗ return AVERROR_INVALIDDATA;
12523 }
12524
12525 51 mov->next_root_atom = 0;
12526
4/6
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 50 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
51 if ((index < 0 && target >= 0) || index >= mov->frag_index.nb_items)
12527 50 index = search_frag_moof_offset(&mov->frag_index, target);
12528
3/4
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 9 times.
51 if (index >= 0 && index < mov->frag_index.nb_items &&
12529
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 mov->frag_index.item[index].moof_offset == target) {
12530
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 4 times.
42 if (index + 1 < mov->frag_index.nb_items)
12531 38 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
12532
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 6 times.
42 if (mov->frag_index.item[index].headers_read)
12533 36 return 0;
12534 6 mov->frag_index.item[index].headers_read = 1;
12535 }
12536
12537 15 mov->found_mdat = 0;
12538
12539 15 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
12540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (ret < 0)
12541 ✗ return ret;
12542
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 7 times.
15 if (avio_feof(s->pb))
12543 8 return AVERROR_EOF;
12544 7 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
12545
12546 7 return 1;
12547 }
12548
12549 17 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
12550 {
12551 17 MOVStreamContext *sc = st->priv_data;
12552 uint8_t *side, *extradata;
12553 int extradata_size;
12554
12555 /* Save the current index. */
12556 17 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
12557
12558 /* Notify the decoder that extradata changed. */
12559 17 extradata_size = sc->extradata_size[sc->last_stsd_index];
12560 17 extradata = sc->extradata[sc->last_stsd_index];
12561
4/6
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
17 if (st->discard != AVDISCARD_ALL && extradata_size > 0 && extradata) {
12562 14 side = av_packet_new_side_data(pkt,
12563 AV_PKT_DATA_NEW_EXTRADATA,
12564 extradata_size);
12565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!side)
12566 ✗ return AVERROR(ENOMEM);
12567 14 memcpy(side, extradata, extradata_size);
12568 }
12569
12570 17 return 0;
12571 }
12572
12573 ✗ static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
12574 {
12575 /* We can't make assumptions about the structure of the payload,
12576 because it may include multiple cdat and cdt2 samples. */
12577 ✗ const uint32_t cdat = AV_RB32("cdat");
12578 ✗ const uint32_t cdt2 = AV_RB32("cdt2");
12579 ✗ int ret, out_size = 0;
12580
12581 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
12582 ✗ if (src_size < 10)
12583 ✗ return AVERROR_INVALIDDATA;
12584
12585 /* avoid an int overflow: */
12586 ✗ if ((src_size - 8) / 2 >= INT_MAX / 3)
12587 ✗ return AVERROR_INVALIDDATA;
12588
12589 ✗ ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
12590 ✗ if (ret < 0)
12591 ✗ return ret;
12592
12593 /* parse and re-format the c608 payload in one pass. */
12594 ✗ while (src_size >= 10) {
12595 ✗ const uint32_t atom_size = avio_rb32(pb);
12596 ✗ const uint32_t atom_type = avio_rb32(pb);
12597 ✗ const uint32_t data_size = atom_size - 8;
12598 ✗ const uint8_t cc_field =
12599 atom_type == cdat ? 1 :
12600 atom_type == cdt2 ? 2 :
12601 0;
12602
12603 /* account for bytes consumed for atom size and type. */
12604 ✗ src_size -= 8;
12605
12606 /* make sure the data size stays within the buffer boundaries. */
12607 ✗ if (data_size < 2 || data_size > src_size) {
12608 ✗ ret = AVERROR_INVALIDDATA;
12609 ✗ break;
12610 }
12611
12612 /* make sure the data size is consistent with N byte pairs. */
12613 ✗ if (data_size % 2 != 0) {
12614 ✗ ret = AVERROR_INVALIDDATA;
12615 ✗ break;
12616 }
12617
12618 ✗ if (!cc_field) {
12619 /* neither cdat or cdt2 ... skip it */
12620 ✗ avio_skip(pb, data_size);
12621 ✗ src_size -= data_size;
12622 ✗ continue;
12623 }
12624
12625 ✗ for (uint32_t i = 0; i < data_size; i += 2) {
12626 ✗ pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
12627 ✗ pkt->data[out_size + 1] = avio_r8(pb);
12628 ✗ pkt->data[out_size + 2] = avio_r8(pb);
12629 ✗ out_size += 3;
12630 ✗ src_size -= 2;
12631 }
12632 }
12633
12634 ✗ if (src_size > 0)
12635 /* skip any remaining unread portion of the input payload */
12636 ✗ avio_skip(pb, src_size);
12637
12638 ✗ av_shrink_packet(pkt, out_size);
12639 ✗ return ret;
12640 }
12641
12642 120921 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
12643 int64_t current_index, AVPacket *pkt)
12644 {
12645 120921 MOVContext *mov = s->priv_data;
12646 120921 MOVStreamContext *sc = st->priv_data;
12647
12648 120921 pkt->stream_index = sc->ffindex;
12649 120921 pkt->dts = sample->timestamp;
12650
2/2
✓ Branch 0 taken 301 times.
✓ Branch 1 taken 120620 times.
120921 if (sample->flags & AVINDEX_DISCARD_FRAME) {
12651 301 pkt->flags |= AV_PKT_FLAG_DISCARD;
12652 }
12653
4/4
✓ Branch 0 taken 101062 times.
✓ Branch 1 taken 19859 times.
✓ Branch 2 taken 101050 times.
✓ Branch 3 taken 12 times.
120921 if (sc->stts_count && sc->tts_index < sc->tts_count)
12654 101050 pkt->duration = sc->tts_data[sc->tts_index].duration;
12655
3/4
✓ Branch 0 taken 4628 times.
✓ Branch 1 taken 116293 times.
✓ Branch 2 taken 4628 times.
✗ Branch 3 not taken.
120921 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
12656 4628 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
12657 } else {
12658
2/2
✓ Branch 0 taken 15815 times.
✓ Branch 1 taken 100478 times.
116293 if (pkt->duration == 0) {
12659 15815 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
12660
2/2
✓ Branch 0 taken 15710 times.
✓ Branch 1 taken 105 times.
15815 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
12661
2/2
✓ Branch 0 taken 15759 times.
✓ Branch 1 taken 56 times.
15815 if (next_dts >= pkt->dts)
12662 15759 pkt->duration = next_dts - pkt->dts;
12663 }
12664 116293 pkt->pts = pkt->dts;
12665 }
12666
12667
4/4
✓ Branch 0 taken 102206 times.
✓ Branch 1 taken 18715 times.
✓ Branch 2 taken 99319 times.
✓ Branch 3 taken 2887 times.
120921 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && !mov->fragment.found_tfhd &&
12668
2/2
✓ Branch 1 taken 235 times.
✓ Branch 2 taken 99084 times.
99319 sc->current_sample >= ffstream(st)->nb_index_entries) {
12669 235 int64_t pts = av_rescale_q(pkt->pts, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12670 235 int64_t total = av_rescale_q(st->duration, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12671 235 int64_t duration = pkt->duration;
12672
12673
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 233 times.
235 if (st->duration < pkt->pts) {
12674 2 duration = 0;
12675 } else
12676 233 duration = FFMIN(duration, (uint64_t)st->duration - pkt->pts);
12677
12678 235 duration = av_rescale_q(duration, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12679
12680
2/2
✓ Branch 1 taken 196 times.
✓ Branch 2 taken 39 times.
235 if (!ffstream(st)->first_discard_sample)
12681 196 ffstream(st)->first_discard_sample = av_sat_add64(pts, duration);
12682
2/2
✓ Branch 1 taken 196 times.
✓ Branch 2 taken 39 times.
235 if (!ffstream(st)->last_discard_sample)
12683 196 ffstream(st)->last_discard_sample = total;
12684 }
12685
12686
4/4
✓ Branch 0 taken 101062 times.
✓ Branch 1 taken 19859 times.
✓ Branch 2 taken 101050 times.
✓ Branch 3 taken 12 times.
120921 if (sc->tts_data && sc->tts_index < sc->tts_count) {
12687 /* update tts context */
12688 101050 sc->tts_sample++;
12689
1/2
✓ Branch 0 taken 101050 times.
✗ Branch 1 not taken.
101050 if (sc->tts_index < sc->tts_count &&
12690
1/2
✓ Branch 0 taken 101050 times.
✗ Branch 1 not taken.
101050 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
12691 101050 sc->tts_index++;
12692 101050 sc->tts_sample = 0;
12693 }
12694 }
12695
12696
4/4
✓ Branch 0 taken 1044 times.
✓ Branch 1 taken 119877 times.
✓ Branch 2 taken 912 times.
✓ Branch 3 taken 132 times.
120921 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
12697 912 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
12698 912 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
12699
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 598 times.
912 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
12700 }
12701 120921 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
12702 120921 pkt->pos = sample->pos;
12703
12704 /* Multiple stsd handling. */
12705
2/2
✓ Branch 0 taken 114724 times.
✓ Branch 1 taken 6197 times.
120921 if (sc->stsc_data) {
12706
1/2
✓ Branch 0 taken 114724 times.
✗ Branch 1 not taken.
114724 if (sc->stsc_data[sc->stsc_index].id > 0 &&
12707
2/2
✓ Branch 0 taken 114671 times.
✓ Branch 1 taken 53 times.
114724 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
12708
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 114654 times.
114671 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
12709 17 int ret = mov_change_extradata(st, pkt);
12710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (ret < 0)
12711 ✗ return ret;
12712 }
12713
12714 /* Update the stsc index for the next sample */
12715 114724 sc->stsc_sample++;
12716
2/2
✓ Branch 1 taken 56824 times.
✓ Branch 2 taken 57900 times.
114724 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
12717
2/2
✓ Branch 1 taken 1212 times.
✓ Branch 2 taken 55612 times.
56824 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
12718 1212 sc->stsc_index++;
12719 1212 sc->stsc_sample = 0;
12720 }
12721 }
12722
12723 120921 return 0;
12724 }
12725
12726 112296 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
12727 {
12728 112296 MOVContext *mov = s->priv_data;
12729 MOVStreamContext *sc;
12730 AVIndexEntry *sample;
12731 112296 AVStream *st = NULL;
12732 112296 FFStream *avsti = NULL;
12733 int64_t current_index;
12734 int ret;
12735 int i;
12736 112296 mov->fc = s;
12737 9267 retry:
12738
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 121563 times.
121563 if (s->pb->pos == 0) {
12739
12740 // Discard current fragment index
12741 ✗ if (mov->frag_index.allocated_size > 0) {
12742 ✗ for(int i = 0; i < mov->frag_index.nb_items; i++) {
12743 ✗ av_freep(&mov->frag_index.item[i].stream_info);
12744 }
12745 ✗ av_freep(&mov->frag_index.item);
12746 ✗ mov->frag_index.nb_items = 0;
12747 ✗ mov->frag_index.allocated_size = 0;
12748 ✗ mov->frag_index.current = -1;
12749 ✗ mov->frag_index.complete = 0;
12750 }
12751
12752 ✗ for (i = 0; i < s->nb_streams; i++) {
12753 ✗ AVStream *avst = s->streams[i];
12754 ✗ MOVStreamContext *msc = avst->priv_data;
12755
12756 // Clear current sample
12757 ✗ mov_current_sample_set(msc, 0);
12758 ✗ msc->tts_index = 0;
12759
12760 // Discard current index entries
12761 ✗ avsti = ffstream(avst);
12762 ✗ if (avsti->index_entries_allocated_size > 0) {
12763 ✗ av_freep(&avsti->index_entries);
12764 ✗ avsti->index_entries_allocated_size = 0;
12765 ✗ avsti->nb_index_entries = 0;
12766 }
12767 }
12768
12769 ✗ if ((ret = mov_switch_root(s, -1, -1)) < 0)
12770 ✗ return ret;
12771 }
12772 121563 sample = mov_find_next_sample(s, &st);
12773
6/6
✓ Branch 0 taken 120968 times.
✓ Branch 1 taken 595 times.
✓ Branch 2 taken 3446 times.
✓ Branch 3 taken 117522 times.
✓ Branch 4 taken 36 times.
✓ Branch 5 taken 3410 times.
121563 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
12774
2/2
✓ Branch 0 taken 581 times.
✓ Branch 1 taken 50 times.
631 if (!mov->next_root_atom)
12775 581 return AVERROR_EOF;
12776
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 42 times.
50 if ((ret = mov_switch_root(s, mov->next_root_atom, -1)) < 0)
12777 8 return ret;
12778 42 goto retry;
12779 }
12780 120932 sc = st->priv_data;
12781 /* must be done just before reading, to avoid infinite loop on sample */
12782 120932 current_index = sc->current_index;
12783 120932 mov_current_sample_inc(sc);
12784
12785
2/2
✓ Branch 0 taken 3410 times.
✓ Branch 1 taken 117522 times.
120932 if (mov->next_root_atom) {
12786 3410 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
12787 3410 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
12788 }
12789
12790
4/4
✓ Branch 0 taken 9235 times.
✓ Branch 1 taken 111697 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 9225 times.
120932 if (st->discard != AVDISCARD_ALL || sc->iamf) {
12791 111707 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
12792
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 111700 times.
111707 if (ret64 != sample->pos) {
12793 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
12794 sc->ffindex, sample->pos);
12795
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
12796 ✗ mov_current_sample_dec(sc);
12797
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
12798 7 return (int)ret64;
12799 }
12800 ✗ return AVERROR_INVALIDDATA;
12801 }
12802
12803
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 111700 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
111700 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
12804 ✗ av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
12805 ✗ goto retry;
12806 }
12807
12808
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 111700 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
111700 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
12809 ✗ ret = get_eia608_packet(sc->pb, pkt, sample->size);
12810 #if CONFIG_IAMFDEC
12811
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 111618 times.
111700 else if (sc->iamf) {
12812 int64_t pts, dts, pos, duration;
12813 82 int flags, size = sample->size;
12814 82 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
12815 82 pts = pkt->pts; dts = pkt->dts;
12816 82 pos = pkt->pos; flags = pkt->flags;
12817 82 duration = pkt->duration;
12818
3/4
✓ Branch 0 taken 536 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 454 times.
✓ Branch 3 taken 82 times.
536 while (!ret && size > 0) {
12819 454 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
12820
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 454 times.
454 if (ret < 0) {
12821 ✗ if (should_retry(sc->pb, ret))
12822 ✗ mov_current_sample_dec(sc);
12823 ✗ return ret;
12824 }
12825 454 size -= ret;
12826
12827
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 334 times.
454 if (pkt->flags & AV_PKT_FLAG_DISCARD) {
12828 120 av_packet_unref(pkt);
12829 120 ret = 0;
12830 120 continue;
12831 }
12832 334 pkt->pts = pts; pkt->dts = dts;
12833 334 pkt->pos = pos; pkt->flags |= flags;
12834 334 pkt->duration = duration;
12835 334 ret = ff_buffer_packet(s, pkt);
12836 }
12837
1/2
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
82 if (!ret)
12838 82 return FFERROR_REDO;
12839 }
12840 #endif
12841
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 111615 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
111621 else if (st->codecpar->codec_id == AV_CODEC_ID_APV && sample->size > 4) {
12842 3 uint32_t au_size = avio_rb32(sc->pb);
12843 3 int explode = !!(mov->fc->error_recognition & AV_EF_EXPLODE);
12844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (au_size > sample->size - 4) {
12845 ✗ av_log(s, explode ? AV_LOG_ERROR : AV_LOG_WARNING,
12846 "APV au_size %u exceeds sample body %d\n",
12847 ✗ au_size, sample->size - 4);
12848 ✗ if (explode)
12849 ✗ return AVERROR_INVALIDDATA;
12850 ✗ au_size = sample->size - 4;
12851 }
12852 3 ret = av_get_packet(sc->pb, pkt, au_size);
12853 } else
12854 111615 ret = av_get_packet(sc->pb, pkt, sample->size);
12855
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 111614 times.
111618 if (ret < 0) {
12856
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (should_retry(sc->pb, ret)) {
12857 ✗ mov_current_sample_dec(sc);
12858 }
12859 4 return ret;
12860 }
12861 #if CONFIG_DV_DEMUXER
12862
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 111614 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
111614 if (mov->dv_demux && sc->dv_audio_container) {
12863 ✗ ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
12864 ✗ av_packet_unref(pkt);
12865 ✗ if (ret < 0)
12866 ✗ return ret;
12867 ✗ ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
12868 ✗ if (ret < 0)
12869 ✗ return ret;
12870 }
12871 #endif
12872
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 111596 times.
111614 if (sc->has_palette) {
12873 uint8_t *pal;
12874
12875 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
12876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
12877 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
12878 } else {
12879 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
12880 18 sc->has_palette = 0;
12881 }
12882 }
12883
4/6
✓ Branch 0 taken 3129 times.
✓ Branch 1 taken 108485 times.
✓ Branch 3 taken 3129 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3129 times.
✗ Branch 6 not taken.
111614 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
12884
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3129 times.
3129 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
12885 ✗ ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
12886 }
12887 }
12888
12889 120839 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
12890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 120839 times.
120839 if (ret < 0)
12891 ✗ return ret;
12892
12893
2/2
✓ Branch 0 taken 9225 times.
✓ Branch 1 taken 111614 times.
120839 if (st->discard == AVDISCARD_ALL)
12894 9225 goto retry;
12895
12896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111614 times.
111614 if (mov->aax_mode)
12897 ✗ aax_filter(pkt->data, pkt->size, mov);
12898
12899 111614 ret = cenc_filter(mov, st, sc, pkt, current_index);
12900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111614 times.
111614 if (ret < 0) {
12901 ✗ return ret;
12902 }
12903
12904 111614 return 0;
12905 }
12906
12907 365 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
12908 {
12909 365 MOVContext *mov = s->priv_data;
12910 int index;
12911
12912
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 28 times.
365 if (!mov->frag_index.complete)
12913 337 return 0;
12914
12915 28 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
12916
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 24 times.
28 if (index < 0)
12917 4 index = 0;
12918
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (!mov->frag_index.item[index].headers_read)
12919 1 return mov_switch_root(s, -1, index);
12920
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (index + 1 < mov->frag_index.nb_items)
12921 27 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
12922
12923 27 return 0;
12924 }
12925
12926 ✗ static int is_open_key_sample(const MOVStreamContext *sc, int sample)
12927 {
12928 // TODO: a bisect search would scale much better
12929 ✗ for (int i = 0; i < sc->open_key_samples_count; i++) {
12930 ✗ const int oks = sc->open_key_samples[i];
12931 ✗ if (oks == sample)
12932 ✗ return 1;
12933 ✗ if (oks > sample) /* list is monotically increasing so we can stop early */
12934 ✗ break;
12935 }
12936 ✗ return 0;
12937 }
12938
12939 /*
12940 * Some key sample may be key frames but not IDR frames, so a random access to
12941 * them may not be allowed.
12942 */
12943 231 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
12944 {
12945 231 MOVStreamContext *sc = st->priv_data;
12946 231 FFStream *const sti = ffstream(st);
12947 int64_t key_sample_dts, key_sample_pts;
12948
12949
1/2
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
231 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
12950 231 return 1;
12951
12952 ✗ if (sample >= sc->sample_offsets_count)
12953 ✗ return 1;
12954
12955 ✗ av_assert0(sample >= 0);
12956 ✗ key_sample_dts = sti->index_entries[sample].timestamp;
12957 ✗ key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
12958
12959 /*
12960 * If the sample needs to be presented before an open key sample, they may
12961 * not be decodable properly, even though they come after in decoding
12962 * order.
12963 */
12964 ✗ if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
12965 ✗ return 0;
12966
12967 ✗ return 1;
12968 }
12969
12970 365 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
12971 {
12972 365 MOVStreamContext *sc = st->priv_data;
12973 365 FFStream *const sti = ffstream(st);
12974 int sample, time_sample, ret, requested_sample;
12975 int64_t next_ts;
12976 unsigned int i;
12977
12978 // Here we consider timestamp to be PTS, hence try to offset it so that we
12979 // can search over the DTS timeline.
12980 365 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
12981
12982 365 ret = mov_seek_fragment(s, st, timestamp);
12983
1/2
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
365 if (ret < 0)
12984 ✗ return ret;
12985
12986 for (;;) {
12987 365 sample = av_index_search_timestamp(st, timestamp, flags);
12988 365 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
12989
5/6
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 296 times.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
✓ Branch 5 taken 26 times.
365 if (sample < 0 && sti->nb_index_entries && timestamp < sti->index_entries[0].timestamp)
12990 43 sample = 0;
12991
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 339 times.
365 if (sample < 0) /* not sure what to do */
12992 26 return AVERROR_INVALIDDATA;
12993
12994
3/4
✓ Branch 0 taken 231 times.
✓ Branch 1 taken 108 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 231 times.
339 if (!sample || can_seek_to_key_sample(st, sample, timestamp))
12995 break;
12996
12997 ✗ next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
12998 ✗ requested_sample = av_index_search_timestamp(st, next_ts, flags);
12999 ✗ if (requested_sample < 0)
13000 ✗ return AVERROR_INVALIDDATA;
13001
13002 // If we've reached a different sample trying to find a good pts to
13003 // seek to, give up searching because we'll end up seeking back to
13004 // sample 0 on every seek.
13005 ✗ if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
13006 ✗ break;
13007
13008 ✗ timestamp = next_ts;
13009 }
13010
13011 339 mov_current_sample_set(sc, sample);
13012 339 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
13013 /* adjust time to sample index */
13014
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 125 times.
339 if (sc->tts_data) {
13015 214 time_sample = 0;
13016
1/2
✓ Branch 0 taken 60310 times.
✗ Branch 1 not taken.
60310 for (i = 0; i < sc->tts_count; i++) {
13017 60310 int next = time_sample + sc->tts_data[i].count;
13018
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 60096 times.
60310 if (next > sc->current_sample) {
13019 214 sc->tts_index = i;
13020 214 sc->tts_sample = sc->current_sample - time_sample;
13021 214 break;
13022 }
13023 60096 time_sample = next;
13024 }
13025 }
13026
13027 /* adjust stsd index */
13028
2/2
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 28 times.
339 if (sc->chunk_count) {
13029 311 time_sample = 0;
13030
1/2
✓ Branch 0 taken 383 times.
✗ Branch 1 not taken.
383 for (i = 0; i < sc->stsc_count; i++) {
13031 383 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
13032
2/2
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 72 times.
383 if (next > sc->current_sample) {
13033 311 sc->stsc_index = i;
13034 311 sc->stsc_sample = sc->current_sample - time_sample;
13035 311 break;
13036 }
13037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
13038 72 time_sample = next;
13039 }
13040 }
13041
13042 339 return sample;
13043 }
13044
13045 339 static int64_t mov_get_skip_samples(AVStream *st, int sample)
13046 {
13047 339 FFStream *const sti = ffstream(st);
13048 339 int64_t first_ts = sti->index_entries[0].timestamp;
13049 339 int64_t ts = sti->index_entries[sample].timestamp;
13050 int64_t off;
13051
13052
2/2
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 152 times.
339 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
13053 187 return 0;
13054
13055 /* compute skip samples according to stream initial_padding, seek ts and first ts */
13056 152 off = av_rescale_q(ts - first_ts, st->time_base,
13057 152 (AVRational){1, st->codecpar->sample_rate});
13058 152 return FFMAX(st->codecpar->initial_padding - off, 0);
13059 }
13060
13061 343 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
13062 {
13063 343 MOVContext *mc = s->priv_data;
13064 AVStream *st;
13065 FFStream *sti;
13066 int sample;
13067 int i;
13068
13069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 343 times.
343 if (stream_index >= s->nb_streams)
13070 ✗ return AVERROR_INVALIDDATA;
13071
13072 343 st = s->streams[stream_index];
13073 343 sti = ffstream(st);
13074 343 sample = mov_seek_stream(s, st, sample_time, flags);
13075
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 317 times.
343 if (sample < 0)
13076 26 return sample;
13077
13078
1/2
✓ Branch 0 taken 317 times.
✗ Branch 1 not taken.
317 if (mc->seek_individually) {
13079 /* adjust seek timestamp to found sample timestamp */
13080 317 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
13081 317 sti->skip_samples = mov_get_skip_samples(st, sample);
13082
13083
2/2
✓ Branch 0 taken 339 times.
✓ Branch 1 taken 317 times.
656 for (i = 0; i < s->nb_streams; i++) {
13084 339 AVStream *const st = s->streams[i];
13085 339 FFStream *const sti = ffstream(st);
13086 int64_t timestamp;
13087
13088
2/2
✓ Branch 0 taken 317 times.
✓ Branch 1 taken 22 times.
339 if (stream_index == i)
13089 317 continue;
13090
13091 22 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
13092 22 sample = mov_seek_stream(s, st, timestamp, flags);
13093
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (sample >= 0)
13094 22 sti->skip_samples = mov_get_skip_samples(st, sample);
13095 }
13096 } else {
13097 ✗ for (i = 0; i < s->nb_streams; i++) {
13098 MOVStreamContext *sc;
13099 ✗ st = s->streams[i];
13100 ✗ sc = st->priv_data;
13101 ✗ mov_current_sample_set(sc, 0);
13102 }
13103 ✗ while (1) {
13104 MOVStreamContext *sc;
13105 ✗ AVIndexEntry *entry = mov_find_next_sample(s, &st);
13106 ✗ if (!entry)
13107 ✗ return AVERROR_INVALIDDATA;
13108 ✗ sc = st->priv_data;
13109 ✗ if (sc->ffindex == stream_index && sc->current_sample == sample)
13110 ✗ break;
13111 ✗ mov_current_sample_inc(sc);
13112 }
13113 }
13114 317 return 0;
13115 }
13116
13117 #define OFFSET(x) offsetof(MOVContext, x)
13118 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
13119 static const AVOption mov_options[] = {
13120 {"use_absolute_path",
13121 "allow using absolute path when opening alias, this is a possible security issue",
13122 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
13123 0, 1, FLAGS},
13124 {"seek_streams_individually",
13125 "Seek each stream individually to the closest point",
13126 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
13127 0, 1, FLAGS},
13128 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
13129 0, 1, FLAGS},
13130 {"advanced_editlist",
13131 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
13132 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
13133 0, 1, FLAGS},
13134 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
13135 0, 1, FLAGS},
13136 {"use_mfra_for",
13137 "use mfra for fragment timestamps",
13138 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
13139 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
13140 .unit = "use_mfra_for"},
13141 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
13142 FLAGS, .unit = "use_mfra_for" },
13143 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
13144 FLAGS, .unit = "use_mfra_for" },
13145 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
13146 FLAGS, .unit = "use_mfra_for" },
13147 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
13148 0, 1, FLAGS},
13149 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
13150 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
13151 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
13152 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
13153 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
13154 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
13155 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
13156 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
13157 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
13158 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
13159 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
13160 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
13161 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
13162 .flags = AV_OPT_FLAG_DECODING_PARAM },
13163 { "decryption_key", "The default media decryption key (hex)", OFFSET(decryption_default_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
13164 { "decryption_keys", "The media decryption keys by KID (hex)", OFFSET(decryption_keys), AV_OPT_TYPE_DICT, .flags = AV_OPT_FLAG_DECODING_PARAM },
13165 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
13166 {.i64 = 0}, 0, 1, FLAGS },
13167 { "max_stts_delta", "treat offsets above this value as invalid", OFFSET(max_stts_delta), AV_OPT_TYPE_INT, {.i64 = UINT_MAX-48000*10 }, 0, UINT_MAX, .flags = AV_OPT_FLAG_DECODING_PARAM },
13168 { "interleaved_read", "Interleave packets from multiple tracks at demuxer level", OFFSET(interleaved_read), AV_OPT_TYPE_BOOL, {.i64 = 1 }, 0, 1, .flags = AV_OPT_FLAG_DECODING_PARAM },
13169
13170 { NULL },
13171 };
13172
13173 static const AVClass mov_class = {
13174 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
13175 .item_name = av_default_item_name,
13176 .option = mov_options,
13177 .version = LIBAVUTIL_VERSION_INT,
13178 };
13179
13180 const FFInputFormat ff_mov_demuxer = {
13181 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
13182 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
13183 .p.priv_class = &mov_class,
13184 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4v,m4b,ism,ismv,isma,f4v,avif,heic,heif",
13185 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
13186 .priv_data_size = sizeof(MOVContext),
13187 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
13188 .read_probe = mov_probe,
13189 .read_header = mov_read_header,
13190 .read_packet = mov_read_packet,
13191 .read_close = mov_read_close,
13192 .read_seek = mov_read_seek,
13193 };
13194