FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2026-10-30 23:38:52
Exec Total Coverage
Lines: 5143 7929 64.9%
Functions: 208 246 84.6%
Branches: 2962 5373 55.1%

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 416 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
174 char *dst, int dstlen)
175 {
176 416 char *p = dst;
177 416 char *end = dst+dstlen-1;
178 int i;
179
180
2/2
✓ Branch 0 taken 3474 times.
✓ Branch 1 taken 416 times.
3890 for (i = 0; i < len; i++) {
181 3474 uint8_t t, c = avio_r8(pb);
182
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3474 times.
3474 if (p >= end)
184 ✗ continue;
185
186
2/2
✓ Branch 0 taken 3466 times.
✓ Branch 1 taken 8 times.
3474 if (c < 0x80)
187 3466 *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 416 *p = 0;
192 416 return p - dst;
193 }
194
195 /**
196 * Get the requested item.
197 */
198 516 static HEIFItem *get_heif_item(MOVContext *c, unsigned id)
199 {
200 516 HEIFItem *item = NULL;
201
202
2/2
✓ Branch 0 taken 4025 times.
✓ Branch 1 taken 16 times.
4041 for (int i = 0; i < c->nb_heif_item; i++) {
203
3/4
✓ Branch 0 taken 4025 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3525 times.
✓ Branch 3 taken 500 times.
4025 if (!c->heif_item[i] || c->heif_item[i]->item_id != id)
204 3525 continue;
205
206 500 item = c->heif_item[i];
207 500 break;
208 }
209
210 516 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 416 static AVStream *get_curr_st(MOVContext *c)
218 {
219 416 AVStream *st = NULL;
220 HEIFItem *item;
221
222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 416 times.
416 if (c->fc->nb_streams < 1)
223 ✗ return NULL;
224
225
2/2
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 158 times.
416 if (c->cur_item_id == -1)
226 258 return c->fc->streams[c->fc->nb_streams-1];
227
228 158 item = get_heif_item(c, c->cur_item_id);
229
1/2
✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
158 if (item)
230 158 st = item->st;
231
232 158 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 703 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
350 {
351 703 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
352 703 char key2[32], language[4] = {0};
353 703 char *str = NULL;
354 703 const char *key = NULL;
355 703 uint16_t langcode = 0;
356 703 uint32_t data_type = 0, str_size_alloc;
357 uint64_t str_size;
358 703 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
359 703 int raw = 0;
360 703 int num = 0;
361 AVDictionary **metadata;
362
363
3/4
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 646 times.
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
703 if (c->trak_index >= 0 && c->trak_index < c->fc->nb_streams)
364 57 metadata = &c->fc->streams[c->trak_index]->metadata;
365 else
366 646 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 253 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 25 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 24 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 30 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 11 times.
✓ Branch 60 taken 11 times.
✓ Branch 61 taken 52 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 68 times.
✓ Branch 69 taken 84 times.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✓ Branch 73 taken 3 times.
✓ Branch 74 taken 11 times.
703 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 25 case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
425 ✗ case MKTAG(0xa9,'P','R','D'): key = "producer"; break;
426 24 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 30 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 11 case MKTAG(0xa9,'m','a','k'): key = "make"; break;
444 11 case MKTAG(0xa9,'m','o','d'): key = "model"; break;
445 52 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 68 case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
453 84 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 11 case MKTAG(0xa9,'x','y','z'): key = "location"; break;
459 }
460 7 retry:
461
3/4
✓ Branch 0 taken 475 times.
✓ Branch 1 taken 235 times.
✓ Branch 2 taken 475 times.
✗ Branch 3 not taken.
1169 if (c->itunes_metadata && atom.size > 8) {
462 475 int data_size = avio_rb32(pb);
463 475 int tag = avio_rl32(pb);
464
3/6
✓ Branch 0 taken 475 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 475 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 475 times.
✗ Branch 5 not taken.
475 if (tag == MKTAG('d','a','t','a') && data_size <= atom.size && data_size >= 16) {
465 475 data_type = avio_rb32(pb); // type
466 475 avio_rb32(pb); // unknown
467 475 str_size = data_size - 16;
468 475 atom.size -= 16;
469
470
5/6
✓ Branch 0 taken 171 times.
✓ Branch 1 taken 304 times.
✓ Branch 2 taken 114 times.
✓ Branch 3 taken 57 times.
✓ Branch 4 taken 114 times.
✗ Branch 5 not taken.
475 if (!key && c->found_hdlr_mdta && c->meta_keys) {
471 114 uint32_t index = av_bswap32(atom.type); // BE number has been read as LE
472
2/4
✓ Branch 0 taken 114 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 114 times.
✗ Branch 3 not taken.
114 if (index < c->meta_keys_count && index > 0) {
473 114 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 459 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 418 times.
✓ Branch 3 taken 41 times.
475 if (atom.type == MKTAG('c', 'o', 'v', 'r') ||
481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 418 times.
418 (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 205 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 56 times.
✓ Branch 3 taken 149 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 56 times.
✓ Branch 6 taken 149 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 138 times.
✓ Branch 9 taken 11 times.
235 } else if (atom.size > 4 && (key || c->export_all) && !c->itunes_metadata && !raw) {
494 138 str_size = avio_rb16(pb); // string length
495
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 133 times.
138 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 133 langcode = avio_rb16(pb);
502 133 ff_mov_lang_to_iso639(langcode, language);
503 133 atom.size -= 4;
504 } else
505 97 str_size = atom.size;
506
507
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 689 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
689 if (c->export_all && !key) {
508 ✗ key = av_fourcc_make_string(tmp_key, atom.type);
509 }
510
511
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 562 times.
689 if (!key)
512 127 return 0;
513
2/4
✓ Branch 0 taken 562 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 562 times.
562 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 490 times.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
562 num = (data_type >= 21 && data_type <= 23);
519
4/4
✓ Branch 0 taken 490 times.
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 479 times.
✓ Branch 3 taken 11 times.
562 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
520 562 str = av_mallocz(str_size_alloc);
521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 562 times.
562 if (!str)
522 ✗ return AVERROR(ENOMEM);
523
524
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 488 times.
562 if (parse)
525 74 parse(c, pb, str_size, key);
526 else {
527
8/10
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 477 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 137 times.
✓ Branch 5 taken 340 times.
✓ Branch 6 taken 120 times.
✓ Branch 7 taken 17 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 120 times.
488 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 469 times.
471 } 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 469 times.
469 } 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 429 times.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
509 } 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 429 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
429 } 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 429 int ret = ffio_read_size(pb, str, str_size);
579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 429 times.
429 if (ret < 0) {
580 ✗ av_free(str);
581 ✗ return ret;
582 }
583 429 str[str_size] = 0;
584 }
585 488 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
586
4/4
✓ Branch 0 taken 344 times.
✓ Branch 1 taken 144 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 340 times.
488 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 344 times.
✓ Branch 1 taken 144 times.
488 av_dict_set(metadata, key, str, c->itunes_metadata ? AV_DICT_APPEND : 0);
589
4/4
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 355 times.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 70 times.
488 if (*language && strcmp(language, "und")) {
590 63 snprintf(key2, sizeof(key2), "%s-%s", key, language);
591 63 av_dict_set(metadata, key2, str, 0);
592 }
593
2/2
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 334 times.
488 if (!strcmp(key, "encoder")) {
594 int major, minor, micro;
595
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 153 times.
154 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 488 atom.size -= str_size;
601 488 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 344 times.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 344 times.
488 if (c->itunes_metadata && atom.size > 8)
610 ✗ goto retry;
611 }
612
613 562 av_freep(&str);
614 562 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 882 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 882 times.
882 if (c->fc->nb_streams < 1)
663 ✗ return 0;
664 882 st = c->fc->streams[c->fc->nb_streams-1];
665 882 sc = st->priv_data;
666
667 882 avio_rb32(pb); // version + flags
668 882 entries = avio_rb32(pb);
669
1/2
✓ Branch 0 taken 882 times.
✗ Branch 1 not taken.
882 if (!entries ||
670
1/2
✓ Branch 0 taken 882 times.
✗ Branch 1 not taken.
882 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 entries >= UINT_MAX / sizeof(*sc->drefs))
672 ✗ return AVERROR_INVALIDDATA;
673
674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 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 882 av_free(sc->drefs);
680 882 sc->drefs_count = 0;
681 882 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 if (!sc->drefs)
683 ✗ return AVERROR(ENOMEM);
684 882 sc->drefs_count = entries;
685
686
2/2
✓ Branch 0 taken 882 times.
✓ Branch 1 taken 882 times.
1764 for (i = 0; i < entries; i++) {
687 882 MOVDref *dref = &sc->drefs[i];
688 882 uint32_t size = avio_rb32(pb);
689 882 int64_t next = avio_tell(pb);
690
691
3/6
✓ Branch 0 taken 882 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 882 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 882 times.
882 if (size < 12 || next < 0 || next > INT64_MAX - size)
692 ✗ return AVERROR_INVALIDDATA;
693
694 882 next += size - 4;
695
696 882 dref->type = avio_rl32(pb);
697 882 avio_rb32(pb); // version + flags
698
699
3/4
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 726 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 156 times.
882 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 882 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
791 dref->type, size);
792 882 entries--;
793 882 i--;
794 }
795 882 avio_seek(pb, next, SEEK_SET);
796 }
797 882 return 0;
798 }
799
800 1551 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 1551 avio_r8(pb); /* version */
810 1551 avio_rb24(pb); /* flags */
811
812 /* component type */
813 1551 ctype = avio_rl32(pb);
814 1551 type = avio_rl32(pb); /* component subtype */
815
816 1551 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
817 1551 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
818
819
2/2
✓ Branch 0 taken 246 times.
✓ Branch 1 taken 1305 times.
1551 if (c->trak_index < 0) { // meta not inside a trak
820
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 230 times.
246 if (type == MKTAG('m','d','t','a')) {
821 16 c->found_hdlr_mdta = 1;
822 }
823 246 return 0;
824 }
825
826 1305 st = c->fc->streams[c->fc->nb_streams-1];
827
828
2/2
✓ Branch 0 taken 384 times.
✓ Branch 1 taken 921 times.
1305 if (type == MKTAG('v','i','d','e'))
829 384 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
830
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 489 times.
921 else if (type == MKTAG('s','o','u','n'))
831 432 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 489 times.
489 else if (type == MKTAG('m','1','a',' '))
833 ✗ st->codecpar->codec_id = AV_CODEC_ID_MP2;
834
2/4
✓ Branch 0 taken 489 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 489 times.
489 else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
835 ✗ st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
836
837 1305 avio_rb32(pb); /* component manufacture */
838 1305 avio_rb32(pb); /* component flags */
839 1305 avio_rb32(pb); /* component flags mask */
840
841 1305 title_size = atom.size - 24;
842
2/2
✓ Branch 0 taken 1299 times.
✓ Branch 1 taken 6 times.
1305 if (title_size > 0) {
843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1299 times.
1299 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
844 ✗ return AVERROR_INVALIDDATA;
845 1299 title_str = av_malloc(title_size + 1); /* Add null terminator */
846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1299 times.
1299 if (!title_str)
847 ✗ return AVERROR(ENOMEM);
848
849 1299 ret = ffio_read_size(pb, title_str, title_size);
850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1299 times.
1299 if (ret < 0) {
851 ✗ av_freep(&title_str);
852 ✗ return ret;
853 }
854 1299 title_str[title_size] = 0;
855
2/2
✓ Branch 0 taken 1222 times.
✓ Branch 1 taken 77 times.
1299 if (title_str[0]) {
856
4/4
✓ Branch 0 taken 812 times.
✓ Branch 1 taken 410 times.
✓ Branch 2 taken 810 times.
✓ Branch 3 taken 2 times.
1222 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 1222 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
859 }
860 1299 av_freep(&title_str);
861 }
862
863 1305 return 0;
864 }
865
866 330 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
867 {
868 330 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 14 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 14 times.
14 if (atom.size < 5)
924 ✗ return AVERROR_INVALIDDATA;
925
926
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (c->fc->nb_streams < 1)
927 ✗ return 0;
928
929 14 version = avio_r8(pb);
930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 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 14 descriptors_size = ffio_read_leb(pb);
937
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
14 if (!descriptors_size || descriptors_size > INT_MAX)
938 ✗ return AVERROR_INVALIDDATA;
939
940 14 st = c->fc->streams[c->fc->nb_streams - 1];
941 14 sc = st->priv_data;
942
943
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (st->codecpar->extradata) {
944 ✗ av_log(c->fc, AV_LOG_WARNING, "ignoring iacb\n");
945 ✗ return 0;
946 }
947
948 14 sc->iamf = av_mallocz(sizeof(*sc->iamf));
949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!sc->iamf)
950 ✗ return AVERROR(ENOMEM);
951 14 iamf = &sc->iamf->iamf;
952
953 14 ret = ff_alloc_extradata(st->codecpar, descriptors_size);
954
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0)
955 ✗ return ret;
956
957 14 ret = avio_read(pb, st->codecpar->extradata, descriptors_size);
958
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret != descriptors_size)
959 ✗ return ret < 0 ? ret : AVERROR_INVALIDDATA;
960
961 14 ffio_init_read_context(&b, st->codecpar->extradata, descriptors_size);
962 14 descriptor_pb = &b.pub;
963
964 14 ret = ff_iamfdec_read_descriptors(iamf, descriptor_pb, descriptors_size, c->fc);
965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0)
966 ✗ return ret;
967
968 14 metadata = st->metadata;
969 14 st->metadata = NULL;
970 14 start_time = st->start_time;
971 14 nb_frames = st->nb_frames;
972 14 duration = st->duration;
973 14 disposition = st->disposition;
974
975
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 14 times.
30 for (int i = 0; i < iamf->nb_audio_elements; i++) {
976 16 IAMFAudioElement *audio_element = iamf->audio_elements[i];
977 const AVIAMFAudioElement *element;
978 AVStreamGroup *stg =
979 16 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 16 times.
16 if (!stg) {
982 ✗ ret = AVERROR(ENOMEM);
983 ✗ goto fail;
984 }
985
986 16 av_iamf_audio_element_free(&stg->params.iamf_audio_element);
987 16 stg->id = audio_element->audio_element_id;
988 /* Transfer ownership */
989 16 element = stg->params.iamf_audio_element = audio_element->element;
990 16 audio_element->element = NULL;
991
992
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 16 times.
84 for (int j = 0; j < audio_element->nb_substreams; j++) {
993 68 IAMFSubStream *substream = &audio_element->substreams[j];
994 AVStream *stream;
995
996
4/4
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 52 times.
68 if (!i && !j) {
997
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (audio_element->layers[0].substream_count != 1)
998 2 disposition &= ~AV_DISPOSITION_DEFAULT;
999 14 stream = st;
1000 } else
1001 54 stream = avformat_new_stream(c->fc, NULL);
1002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (!stream) {
1003 ✗ ret = AVERROR(ENOMEM);
1004 ✗ goto fail;
1005 }
1006
1007 68 stream->start_time = start_time;
1008 68 stream->nb_frames = nb_frames;
1009 68 stream->duration = duration;
1010 68 stream->disposition = disposition;
1011
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 14 times.
68 if (stream != st) {
1012 54 stream->priv_data = sc;
1013 54 sc->refcount++;
1014 }
1015
1016
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 60 times.
68 if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
1017 8 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1018
4/4
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 14 times.
68 if (i || j) {
1019 54 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1020
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 6 times.
54 if (audio_element->layers[0].substream_count == 1)
1021 48 stream->disposition &= ~AV_DISPOSITION_DEFAULT;
1022 }
1023
1024 68 ret = avcodec_parameters_copy(stream->codecpar, substream->codecpar);
1025
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (ret < 0)
1026 ✗ goto fail;
1027
1028 68 stream->id = substream->audio_substream_id;
1029
1030 68 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
1031
1032 68 ret = avformat_stream_group_add_stream(stg, stream);
1033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (ret < 0)
1034 ✗ goto fail;
1035 }
1036
1037 16 ret = av_dict_copy(&stg->metadata, metadata, 0);
1038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0)
1039 ✗ goto fail;
1040 }
1041
1042
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
28 for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1043 14 IAMFMixPresentation *mix_presentation = iamf->mix_presentations[i];
1044 14 const AVIAMFMixPresentation *mix = mix_presentation->cmix;
1045 AVStreamGroup *stg =
1046 14 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 14 times.
14 if (!stg) {
1049 ✗ ret = AVERROR(ENOMEM);
1050 ✗ goto fail;
1051 }
1052
1053 14 av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
1054 14 stg->id = mix_presentation->mix_presentation_id;
1055 /* Transfer ownership */
1056 14 stg->params.iamf_mix_presentation = mix_presentation->mix;
1057 14 mix_presentation->mix = NULL;
1058
1059
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 14 times.
30 for (int j = 0; j < mix->nb_submixes; j++) {
1060 16 const AVIAMFSubmix *submix = mix->submixes[j];
1061
1062
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 16 times.
34 for (int k = 0; k < submix->nb_elements; k++) {
1063 18 const AVIAMFSubmixElement *submix_element = submix->elements[k];
1064 18 const AVStreamGroup *audio_element = NULL;
1065
1066
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 for (int l = 0; l < c->fc->nb_stream_groups; l++)
1067
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (c->fc->stream_groups[l]->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT &&
1068
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2 times.
20 c->fc->stream_groups[l]->id == submix_element->audio_element_id) {
1069 18 audio_element = c->fc->stream_groups[l];
1070 18 break;
1071 }
1072
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 av_assert0(audio_element);
1073
1074
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 18 times.
88 for (int l = 0; l < audio_element->nb_entries; l++) {
1075 70 ret = avformat_stream_group_add_stream(stg, audio_element->entries[l]->stream);
1076
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
70 if (ret < 0 && ret != AVERROR(EEXIST))
1077 ✗ goto fail;
1078 }
1079 }
1080 }
1081
1082 14 ret = av_dict_copy(&stg->metadata, metadata, 0);
1083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0)
1084 ✗ goto fail;
1085 }
1086
1087 14 ret = 0;
1088 14 fail:
1089 14 av_dict_free(&metadata);
1090
1091 14 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 58 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 58 times.
58 if (c->fc->nb_streams < 1)
1311 ✗ return 0;
1312 58 st = c->fc->streams[c->fc->nb_streams-1];
1313
1314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (atom.size < 16)
1315 ✗ return 0;
1316
1317 /* skip version and flags */
1318 58 avio_skip(pb, 4);
1319
1320 58 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
1321
1322 58 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 22 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1375 {
1376 AVStream *st;
1377 HEIFItem *item;
1378 AVPacketSideData *sd;
1379 22 int width, height, err = 0;
1380 AVRational aperture_width, aperture_height, horiz_off, vert_off;
1381 AVRational pc_x, pc_y;
1382 int64_t top, bottom, left, right;
1383
1384 22 item = get_heif_item(c, c->cur_item_id);
1385 22 st = get_curr_st(c);
1386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (!st)
1387 ✗ return 0;
1388
1389 22 width = st->codecpar->width;
1390 22 height = st->codecpar->height;
1391
4/6
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
22 if ((!width || !height) && item) {
1392 6 width = item->width;
1393 6 height = item->height;
1394 }
1395
2/4
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
22 if (!width || !height) {
1396 ✗ err = AVERROR_INVALIDDATA;
1397 ✗ goto fail;
1398 }
1399
1400 22 aperture_width.num = avio_rb32(pb);
1401 22 aperture_width.den = avio_rb32(pb);
1402 22 aperture_height.num = avio_rb32(pb);
1403 22 aperture_height.den = avio_rb32(pb);
1404
1405 22 horiz_off.num = avio_rb32(pb);
1406 22 horiz_off.den = avio_rb32(pb);
1407 22 vert_off.num = avio_rb32(pb);
1408 22 vert_off.den = avio_rb32(pb);
1409
1410
2/4
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
22 if (aperture_width.num < 0 || aperture_width.den <= 0 ||
1411
2/4
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
22 aperture_height.num < 0 || aperture_height.den <= 0 ||
1412
2/4
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
22 horiz_off.den <= 0 || vert_off.den <= 0) {
1413 ✗ err = AVERROR_INVALIDDATA;
1414 ✗ goto fail;
1415 }
1416
3/4
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
41 if ((av_cmp_q((AVRational) { width, 1 }, aperture_width) < 0) ||
1417 19 (av_cmp_q((AVRational) { height, 1 }, aperture_height) < 0)) {
1418 3 err = AVERROR_INVALIDDATA;
1419 3 goto fail;
1420 }
1421 19 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 19 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1427 19 pc_x = av_add_q(pc_x, horiz_off);
1428 19 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1429 19 pc_y = av_add_q(pc_y, vert_off);
1430
1431 19 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1432 19 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1433 19 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1434 19 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1435
1436 19 left = av_q2d(av_sub_q(pc_x, aperture_width));
1437 19 right = av_q2d(av_add_q(pc_x, aperture_width));
1438 19 top = av_q2d(av_sub_q(pc_y, aperture_height));
1439 19 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1440
1441
4/8
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 19 times.
✗ Branch 7 not taken.
19 if (top < 0 || bottom < 0 || bottom > (height - 1) ||
1442
2/4
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
19 left < 0 || right < 0 || right > (width - 1)) {
1443 ✗ err = AVERROR_INVALIDDATA;
1444 ✗ goto fail;
1445 }
1446
1447 19 bottom = height - 1 - bottom;
1448 19 right = width - 1 - right;
1449
1450
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 12 times.
19 if (!(left | right | top | bottom))
1451 7 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 110 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1484 {
1485 110 const int num = avio_rb32(pb);
1486 110 const int den = avio_rb32(pb);
1487 AVStream *st;
1488 MOVStreamContext *sc;
1489
1490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
110 if (c->fc->nb_streams < 1)
1491 ✗ return 0;
1492 110 st = c->fc->streams[c->fc->nb_streams-1];
1493 110 sc = st->priv_data;
1494
1495 110 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1496
1497
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 3 times.
110 if (den != 0) {
1498 107 sc->h_spacing = num;
1499 107 sc->v_spacing = den;
1500 }
1501 110 return 0;
1502 }
1503
1504 /* this atom contains actual media data */
1505 1125 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1506 {
1507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1125 times.
1125 if (atom.size == 0) /* wrong one (MP4) */
1508 ✗ return 0;
1509 1125 c->found_mdat=1;
1510 1125 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 608 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 608 uint8_t type[5] = {0};
1661 608 int ret = ffio_read_size(pb, type, 4);
1662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if (ret < 0)
1663 ✗ return ret;
1664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 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 349 times.
✓ Branch 1 taken 259 times.
608 if (strcmp(type, "qt "))
1672 349 c->isom = 1;
1673 608 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1674 608 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1675 608 minor_ver = avio_rb32(pb); /* minor version */
1676 608 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1677
1678 608 comp_brand_size = atom.size - 8;
1679
2/4
✓ Branch 0 taken 608 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 608 times.
608 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1680 ✗ return AVERROR_INVALIDDATA;
1681 608 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if (!comp_brands_str)
1683 ✗ return AVERROR(ENOMEM);
1684
1685 608 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if (ret < 0) {
1687 ✗ av_freep(&comp_brands_str);
1688 ✗ return ret;
1689 }
1690 608 comp_brands_str[comp_brand_size] = 0;
1691 608 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 608 times.
608 if (!strcmp(type, "aaxc")) {
1696 ✗ mov_aaxc_crypto(c);
1697 }
1698
1699 608 return 0;
1700 }
1701
1702 /* this atom should contain all header atoms */
1703 647 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 647 times.
647 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
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 644 times.
647 if ((ret = mov_read_default(c, pb, atom)) < 0)
1714 3 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 644 c->found_moov=1;
1718 644 return 0; /* now go for mdat */
1719 }
1720
1721 6235 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 6235 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6235 times.
6235 if (index < 0 || index >= frag_index->nb_items)
1730 ✗ return NULL;
1731 6235 item = &frag_index->item[index];
1732
1/2
✓ Branch 0 taken 154919 times.
✗ Branch 1 not taken.
154919 for (i = 0; i < item->nb_stream_info; i++)
1733
2/2
✓ Branch 0 taken 6235 times.
✓ Branch 1 taken 148684 times.
154919 if (item->stream_info[i].id == id)
1734 6235 return &item->stream_info[i];
1735
1736 // This shouldn't happen
1737 ✗ return NULL;
1738 }
1739
1740 707 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1741 {
1742 int i;
1743 MOVFragmentIndexItem * item;
1744
1745
1/2
✓ Branch 0 taken 707 times.
✗ Branch 1 not taken.
707 if (frag_index->current < 0 ||
1746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 frag_index->current >= frag_index->nb_items)
1747 ✗ return;
1748
1749 707 item = &frag_index->item[frag_index->current];
1750
1/2
✓ Branch 0 taken 10666 times.
✗ Branch 1 not taken.
10666 for (i = 0; i < item->nb_stream_info; i++)
1751
2/2
✓ Branch 0 taken 707 times.
✓ Branch 1 taken 9959 times.
10666 if (item->stream_info[i].id == id) {
1752 707 item->current = i;
1753 707 return;
1754 }
1755
1756 // id not found. This shouldn't happen.
1757 ✗ item->current = -1;
1758 }
1759
1760 2075 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1761 MOVFragmentIndex *frag_index)
1762 {
1763 MOVFragmentIndexItem *item;
1764
1/2
✓ Branch 0 taken 2075 times.
✗ Branch 1 not taken.
2075 if (frag_index->current < 0 ||
1765
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 2054 times.
2075 frag_index->current >= frag_index->nb_items)
1766 21 return NULL;
1767
1768 2054 item = &frag_index->item[frag_index->current];
1769
2/4
✓ Branch 0 taken 2054 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2054 times.
✗ Branch 3 not taken.
2054 if (item->current >= 0 && item->current < item->nb_stream_info)
1770 2054 return &item->stream_info[item->current];
1771
1772 // This shouldn't happen
1773 ✗ return NULL;
1774 }
1775
1776 1114 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 25 times.
1114 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 494 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 1064 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 1064 index = search_frag_moof_offset(&c->frag_index, offset);
1885
2/2
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 485 times.
1064 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 487 item = av_fast_realloc(c->frag_index.item,
1892 487 &c->frag_index.allocated_size,
1893 487 (c->frag_index.nb_items + 1) *
1894 sizeof(*c->frag_index.item));
1895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 487 times.
487 if (!item)
1896 ✗ return -1;
1897 487 c->frag_index.item = item;
1898
1899 487 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 487 times.
487 if (!frag_stream_info)
1902 ✗ return -1;
1903
1904
2/2
✓ Branch 0 taken 787 times.
✓ Branch 1 taken 487 times.
1274 for (i = 0; i < c->fc->nb_streams; i++) {
1905 // Avoid building frag index if streams lack track id.
1906 787 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1907
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 787 times.
787 if (sc->id < 0) {
1908 ✗ av_free(frag_stream_info);
1909 ✗ return AVERROR_INVALIDDATA;
1910 }
1911
1912 787 frag_stream_info[i].id = sc->id;
1913 787 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1914 787 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1915 787 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1916 787 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1917 787 frag_stream_info[i].index_base = -1;
1918 787 frag_stream_info[i].index_entry = -1;
1919 787 frag_stream_info[i].encryption_index = NULL;
1920 787 frag_stream_info[i].stsd_id = -1;
1921 }
1922
1923
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 485 times.
487 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 41 times.
✓ Branch 1 taken 446 times.
487 if (index <= c->frag_index.current)
1927 41 c->frag_index.current++;
1928
1929 487 item = &c->frag_index.item[index];
1930 487 item->headers_read = 0;
1931 487 item->current = 0;
1932 487 item->nb_stream_info = c->fc->nb_streams;
1933 487 item->moof_offset = offset;
1934 487 item->stream_info = frag_stream_info;
1935 487 c->frag_index.nb_items++;
1936
1937 487 return index;
1938 }
1939
1940 707 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 707 times.
✗ Branch 1 not taken.
707 if (index < 0)
1947 707 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 483 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 483 c->fragment.found_tfhd = 0;
1959
1960
4/4
✓ Branch 0 taken 481 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 480 times.
483 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 483 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1976 483 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1977 483 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1978 483 return mov_read_default(c, pb, atom);
1979 }
1980
1981 1526 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 1511 times.
1526 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 1511 time = avio_rb32(pb);
1993 1511 avio_rb32(pb); /* modification time */
1994
4/4
✓ Branch 0 taken 700 times.
✓ Branch 1 taken 811 times.
✓ Branch 2 taken 68 times.
✓ Branch 3 taken 632 times.
1511 if (time > 0 && time < 2082844800) {
1995 68 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1996 68 time += 2082844800;
1997 }
1998 }
1999
2/2
✓ Branch 0 taken 706 times.
✓ Branch 1 taken 820 times.
1526 if (time) {
2000 706 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
2001
2002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 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 706 ff_dict_set_timestamp(metadata, "creation_time", time * 1000000);
2008 }
2009 }
2010
2011 882 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2012 {
2013 AVStream *st;
2014 MOVStreamContext *sc;
2015 int version;
2016 882 char language[4] = {0};
2017 unsigned lang;
2018
2019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 if (c->fc->nb_streams < 1)
2020 ✗ return 0;
2021 882 st = c->fc->streams[c->fc->nb_streams-1];
2022 882 sc = st->priv_data;
2023
2024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 if (sc->time_scale) {
2025 ✗ av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
2026 ✗ return AVERROR_INVALIDDATA;
2027 }
2028
2029 882 version = avio_r8(pb);
2030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 if (version > 1) {
2031 ✗ avpriv_request_sample(c->fc, "Version %d", version);
2032 ✗ return AVERROR_PATCHWELCOME;
2033 }
2034 882 avio_rb24(pb); /* flags */
2035 882 mov_metadata_creation_time(c, pb, &st->metadata, version);
2036
2037 882 sc->time_scale = avio_rb32(pb);
2038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 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 869 times.
882 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
2043
2044
6/6
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 869 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 869 times.
✓ Branch 5 taken 4 times.
882 if ((version == 1 && st->duration == UINT64_MAX) ||
2045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 869 times.
869 (version != 1 && st->duration == UINT32_MAX)) {
2046 9 st->duration = 0;
2047 }
2048
2049 882 lang = avio_rb16(pb); /* language */
2050
2/2
✓ Branch 1 taken 698 times.
✓ Branch 2 taken 184 times.
882 if (ff_mov_lang_to_iso639(lang, language))
2051 698 av_dict_set(&st->metadata, "language", language, 0);
2052 882 avio_rb16(pb); /* quality */
2053
2054 882 return 0;
2055 }
2056
2057 644 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2058 {
2059 int i;
2060 644 int version = avio_r8(pb); /* version */
2061 644 avio_rb24(pb); /* flags */
2062
2063 644 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
2064 644 c->time_scale = avio_rb32(pb); /* time scale */
2065
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 644 times.
644 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 644 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 642 times.
644 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
2072 644 avio_rb32(pb); /* preferred scale */
2073
2074 644 avio_rb16(pb); /* preferred volume */
2075
2076 644 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 1932 times.
✓ Branch 1 taken 644 times.
2576 for (i = 0; i < 3; i++) {
2080 1932 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
2081 1932 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
2082 1932 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
2083 }
2084
2085 644 avio_rb32(pb); /* preview time */
2086 644 avio_rb32(pb); /* preview duration */
2087 644 avio_rb32(pb); /* poster time */
2088 644 avio_rb32(pb); /* selection time */
2089 644 avio_rb32(pb); /* selection duration */
2090 644 avio_rb32(pb); /* current time */
2091 644 avio_rb32(pb); /* next track ID */
2092
2093 644 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 110 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2212 {
2213 AVStream *st;
2214 110 HEIFItem *item = NULL;
2215 110 char color_parameter_type[5] = { 0 };
2216 uint16_t color_primaries, color_trc, color_matrix;
2217 int ret;
2218
2219 110 st = get_curr_st(c);
2220
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 102 times.
110 if (!st) {
2221 8 item = get_heif_item(c, c->cur_item_id);
2222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!item)
2223 ✗ return 0;
2224 }
2225
2226 110 ret = ffio_read_size(pb, color_parameter_type, 4);
2227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
110 if (ret < 0)
2228 ✗ return ret;
2229
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 56 times.
110 if (strncmp(color_parameter_type, "nclx", 4) &&
2230
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 42 times.
54 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 98 times.
110 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
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 4 times.
98 } else if (st) {
2268 94 color_primaries = avio_rb16(pb);
2269 94 color_trc = avio_rb16(pb);
2270 94 color_matrix = avio_rb16(pb);
2271
2272 94 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 52 times.
✓ Branch 1 taken 42 times.
94 if (!strncmp(color_parameter_type, "nclx", 4)) {
2277 52 uint8_t color_range = avio_r8(pb) >> 7;
2278 52 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2279
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 20 times.
52 if (color_range)
2280 32 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 94 times.
94 if (!av_color_primaries_name(color_primaries))
2286 ✗ color_primaries = AVCOL_PRI_UNSPECIFIED;
2287
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 94 times.
94 if (!av_color_transfer_name(color_trc))
2288 ✗ color_trc = AVCOL_TRC_UNSPECIFIED;
2289
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 94 times.
94 if (!av_color_space_name(color_matrix))
2290 ✗ color_matrix = AVCOL_SPC_UNSPECIFIED;
2291
2292 94 st->codecpar->color_primaries = color_primaries;
2293 94 st->codecpar->color_trc = color_trc;
2294 94 st->codecpar->color_space = color_matrix;
2295 94 av_log(c->fc, AV_LOG_TRACE, "\n");
2296 }
2297 110 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 40 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 40 times.
40 if (c->fc->nb_streams < 1)
2538 ✗ return 0;
2539 40 st = c->fc->streams[c->fc->nb_streams-1];
2540
2541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if ((uint64_t)atom.size > (1<<30))
2542 ✗ return AVERROR_INVALIDDATA;
2543
2544
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 2 times.
40 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2545
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 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 38 times.
✗ Branch 1 not taken.
38 } else if (atom.size > 8) { /* to read frma, esds atoms */
2552
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
38 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 38 times.
38 if ((ret = mov_read_default(c, pb, atom)) < 0)
2579 ✗ return ret;
2580 } else
2581 ✗ avio_skip(pb, atom.size);
2582 40 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 273 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2590 {
2591 AVStream *st;
2592 int ret;
2593
2594 273 st = get_curr_st(c);
2595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 273 times.
273 if (!st)
2596 ✗ return 0;
2597
2598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 273 times.
273 if ((uint64_t)atom.size > (1<<30))
2599 ✗ return AVERROR_INVALIDDATA;
2600
2601
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 272 times.
273 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 218 times.
✓ Branch 1 taken 55 times.
273 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 218 unsigned size = avio_rb32(pb);
2610 218 unsigned type = avio_rl32(pb);
2611
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 218 times.
218 if (avio_feof(pb))
2612 ✗ return AVERROR_INVALIDDATA;
2613 218 avio_seek(pb, -8, SEEK_CUR);
2614
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 208 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
218 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 263 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
263 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 263 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 263 times.
263 if (ret < 0)
2623 ✗ return ret;
2624
3/4
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 178 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 85 times.
263 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 263 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 71 static int mov_find_tref_id(const MovTref *tag, uint32_t id)
2661 {
2662
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 43 times.
101 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 43 return 0;
2667 }
2668
2669 43 static int mov_add_tref_id(MovTref *tag, uint32_t id)
2670 {
2671 43 int ret = mov_find_tref_id(tag, id);
2672
2673
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (!ret) {
2674 43 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 43 times.
43 if (!tmp)
2676 ✗ return AVERROR(ENOMEM);
2677 43 tag->id = tmp;
2678 43 tag->id[tag->nb_id++] = id;
2679 }
2680
2681 43 return 0;
2682 }
2683
2684 2255 static MovTref *mov_find_tref_tag(const MOVStreamContext *sc, uint32_t name)
2685 {
2686
2/2
✓ Branch 0 taken 189 times.
✓ Branch 1 taken 2186 times.
2375 for (int i = 0; i < sc->nb_tref_tags; i++) {
2687 189 MovTref *entry = &sc->tref_tags[i];
2688
2689
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 120 times.
189 if (entry->name == name)
2690 69 return entry;
2691 }
2692 2186 return NULL;
2693 }
2694
2695 33 static MovTref *mov_add_tref_tag(MOVStreamContext *sc, uint32_t name)
2696 {
2697 33 MovTref *tag = mov_find_tref_tag(sc, name);
2698
2699
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if (!tag) {
2700 33 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 33 times.
33 if (!tmp)
2703 ✗ return NULL;
2704 33 sc->tref_tags = tmp;
2705 33 tag = &sc->tref_tags[sc->nb_tref_tags++];
2706 33 *tag = (MovTref){ .name = name };
2707 }
2708
2709 33 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 1 static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2744 {
2745 AVStream* st;
2746 MOVStreamContext* sc;
2747
2748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 4)
2759 ✗ return AVERROR_INVALIDDATA;
2760
2761 1 st = c->fc->streams[c->fc->nb_streams - 1];
2762 1 sc = st->priv_data;
2763
2764 1 MovTref *tag = mov_add_tref_tag(sc, atom.type);
2765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!tag)
2766 ✗ return AVERROR(ENOMEM);
2767
2768 1 int ret = mov_add_tref_id(tag, avio_rb32(pb));
2769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
2770 ✗ return ret;
2771
2772 1 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 879 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 879 times.
879 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 879 times.
879 if (c->fc->nb_streams < 1)
2840 ✗ return 0;
2841 879 st = c->fc->streams[c->fc->nb_streams-1];
2842 879 sc = st->priv_data;
2843
2844 879 avio_r8(pb); /* version */
2845 879 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 879 entries = avio_rb32(pb);
2850 879 entries =
2851
2/2
✓ Branch 0 taken 874 times.
✓ Branch 1 taken 5 times.
879 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 135 times.
✓ Branch 1 taken 744 times.
879 if (!entries)
2856 135 return 0;
2857
2858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 744 times.
744 if (sc->chunk_offsets) {
2859 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2860 ✗ return 0;
2861 }
2862
2863 744 av_free(sc->chunk_offsets);
2864 744 sc->chunk_count = 0;
2865 744 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 744 times.
744 if (!sc->chunk_offsets)
2867 ✗ return AVERROR(ENOMEM);
2868 744 sc->chunk_count = entries;
2869
2870
2/2
✓ Branch 0 taken 740 times.
✓ Branch 1 taken 4 times.
744 if (atom.type == MKTAG('s','t','c','o'))
2871
3/4
✓ Branch 0 taken 48406 times.
✓ Branch 1 taken 740 times.
✓ Branch 2 taken 48406 times.
✗ Branch 3 not taken.
49146 for (i = 0; i < entries && !pb->eof_reached; i++)
2872 48406 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 744 sc->chunk_count = i;
2885
2886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 744 times.
744 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 744 return 0;
2892 }
2893
2894 1015 static int mov_codec_id(AVStream *st, uint32_t format)
2895 {
2896 1015 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2897
2898
2/2
✓ Branch 0 taken 608 times.
✓ Branch 1 taken 407 times.
1015 if (id <= 0 &&
2899
2/2
✓ Branch 0 taken 605 times.
✓ Branch 1 taken 3 times.
608 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 605 times.
605 (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 499 times.
✓ Branch 1 taken 516 times.
✓ Branch 2 taken 410 times.
✓ Branch 3 taken 89 times.
1015 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2904 410 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2905
3/4
✓ Branch 0 taken 583 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 583 times.
✗ Branch 3 not taken.
605 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2906 /* skip old ASF MPEG-4 tag */
2907
2/2
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 4 times.
583 format && format != MKTAG('m','p','4','s')) {
2908 579 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2909
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 501 times.
579 if (id <= 0)
2910 78 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2911
2/2
✓ Branch 0 taken 505 times.
✓ Branch 1 taken 74 times.
579 if (id > 0)
2912 505 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 1015 st->codecpar->codec_tag = format;
2930
2931 1015 return id;
2932 }
2933
2934 399 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2935 AVStream *st, MOVStreamContext *sc)
2936 {
2937 399 uint8_t codec_name[32] = { 0 };
2938 int64_t stsd_start;
2939 unsigned int len;
2940 399 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 399 stsd_start = avio_tell(pb) - 16;
2945
2946
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 267 times.
399 if (c->isom) {
2947 132 avio_skip(pb, 2); /* pre_defined */
2948 132 avio_skip(pb, 2); /* reserved */
2949 132 avio_skip(pb, 12); /* pre_defined */
2950 } else {
2951 267 avio_rb16(pb); /* version */
2952 267 avio_rb16(pb); /* revision level */
2953 267 id = avio_rl32(pb); /* vendor */
2954 267 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2955 267 avio_rb32(pb); /* temporal quality */
2956 267 avio_rb32(pb); /* spatial quality */
2957 }
2958
2959 399 st->codecpar->width = avio_rb16(pb); /* width */
2960 399 st->codecpar->height = avio_rb16(pb); /* height */
2961
2962 399 avio_rb32(pb); /* horiz resolution */
2963 399 avio_rb32(pb); /* vert resolution */
2964 399 avio_rb32(pb); /* data size, always 0 */
2965 399 avio_rb16(pb); /* frames per samples */
2966
2967 399 len = avio_r8(pb); /* codec name, pascal string */
2968
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 398 times.
399 if (len > 31)
2969 1 len = 31;
2970 399 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2971
2/2
✓ Branch 0 taken 396 times.
✓ Branch 1 taken 3 times.
399 if (len < 31)
2972 396 avio_skip(pb, 31 - len);
2973
2974
2/2
✓ Branch 0 taken 304 times.
✓ Branch 1 taken 95 times.
399 if (codec_name[0])
2975 304 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 399 times.
399 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 399 times.
399 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 399 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2989
2990 399 avio_seek(pb, stsd_start, SEEK_SET);
2991
2992
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 381 times.
399 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 399 }
2997
2998 432 static int mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2999 AVStream *st, MOVStreamContext *sc)
3000 {
3001 int bits_per_sample, flags;
3002 432 uint16_t version = avio_rb16(pb);
3003 432 uint32_t id = 0;
3004 432 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 331 times.
✓ Branch 1 taken 101 times.
432 if (c->isom)
3008 331 avio_skip(pb, 6); /* reserved */
3009 else {
3010 101 avio_rb16(pb); /* revision level */
3011 101 id = avio_rl32(pb); /* vendor */
3012 101 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
3013 }
3014
3015 432 channel_count = avio_rb16(pb);
3016
3017 432 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3018 432 st->codecpar->ch_layout.nb_channels = channel_count;
3019 432 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
3020 432 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
3021
3022 432 sc->audio_cid = avio_rb16(pb);
3023 432 avio_rb16(pb); /* packet size = 0 */
3024
3025 432 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
3026
3027 // Read QT version 1 fields. In version 0 these do not exist.
3028 432 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
3029
3/4
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 101 times.
✓ Branch 2 taken 331 times.
✗ Branch 3 not taken.
432 if (!c->isom ||
3030
1/2
✓ Branch 0 taken 331 times.
✗ Branch 1 not taken.
331 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
3031
4/4
✓ Branch 0 taken 326 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 322 times.
331 (sc->stsd_version == 0 && version > 0)) {
3032
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 46 times.
105 if (version == 1) {
3033 59 sc->samples_per_frame = avio_rb32(pb);
3034 59 avio_rb32(pb); /* bytes per packet */
3035 59 sc->bytes_per_frame = avio_rb32(pb);
3036 59 avio_rb32(pb); /* bytes per sample */
3037
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 38 times.
46 } else if (version == 2) {
3038 double sample_rate;
3039
3040 8 avio_rb32(pb); /* sizeof struct only */
3041 8 sample_rate = av_int2double(avio_rb64(pb));
3042
3043
6/6
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 5 times.
8 if (sample_rate < 0 || sample_rate > INT_MAX ||
3044 isnan(sample_rate)) {
3045 3 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %g\n",
3046 sample_rate);
3047 3 return AVERROR_INVALIDDATA;
3048 }
3049 5 st->codecpar->sample_rate = sample_rate;
3050 5 channel_count = avio_rb32(pb);
3051 5 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3052 5 st->codecpar->ch_layout.nb_channels = channel_count;
3053 5 avio_rb32(pb); /* always 0x7F000000 */
3054 5 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
3055
3056 5 flags = avio_rb32(pb); /* lpcm format specific flag */
3057 5 sc->bytes_per_frame = avio_rb32(pb);
3058 5 sc->samples_per_frame = avio_rb32(pb);
3059
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
3060 1 st->codecpar->codec_id =
3061 1 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
3062 flags);
3063 }
3064
6/6
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 32 times.
102 if (version == 0 || (version == 1 && sc->audio_cid != -2)) {
3065 /* can't correctly handle variable sized packet as audio unit */
3066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 switch (st->codecpar->codec_id) {
3067 ✗ case AV_CODEC_ID_MP2:
3068 case AV_CODEC_ID_MP3:
3069 ✗ ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
3070 ✗ break;
3071 }
3072 }
3073 }
3074
3075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 429 times.
429 if (sc->format == 0) {
3076 ✗ if (st->codecpar->bits_per_coded_sample == 8)
3077 ✗ st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
3078 ✗ else if (st->codecpar->bits_per_coded_sample == 16)
3079 ✗ st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
3080 }
3081
3082
7/7
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 381 times.
429 switch (st->codecpar->codec_id) {
3083 7 case AV_CODEC_ID_PCM_S8:
3084 case AV_CODEC_ID_PCM_U8:
3085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
3086 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
3087 7 break;
3088 25 case AV_CODEC_ID_PCM_S16LE:
3089 case AV_CODEC_ID_PCM_S16BE:
3090
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23 times.
25 if (st->codecpar->bits_per_coded_sample == 8)
3091 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
3092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 else if (st->codecpar->bits_per_coded_sample == 24)
3093 ✗ st->codecpar->codec_id =
3094 ✗ st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
3095 ✗ AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
3096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 else if (st->codecpar->bits_per_coded_sample == 32)
3097 ✗ st->codecpar->codec_id =
3098 ✗ st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
3099 ✗ AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
3100 25 break;
3101 /* set values for old format before stsd version 1 appeared */
3102 2 case AV_CODEC_ID_MACE3:
3103 2 sc->samples_per_frame = 6;
3104 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
3105 2 break;
3106 8 case AV_CODEC_ID_MACE6:
3107 8 sc->samples_per_frame = 6;
3108 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
3109 8 break;
3110 5 case AV_CODEC_ID_ADPCM_IMA_QT:
3111 5 sc->samples_per_frame = 64;
3112 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
3113 5 break;
3114 1 case AV_CODEC_ID_GSM:
3115 1 sc->samples_per_frame = 160;
3116 1 sc->bytes_per_frame = 33;
3117 1 break;
3118 381 default:
3119 381 break;
3120 }
3121
3122 429 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
3123
3/4
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 375 times.
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
429 if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->ch_layout.nb_channels <= INT_MAX) {
3124 54 st->codecpar->bits_per_coded_sample = bits_per_sample;
3125 54 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
3126 }
3127
3128 429 return 0;
3129 }
3130
3131 15 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
3132 AVStream *st, MOVStreamContext *sc,
3133 int64_t size)
3134 {
3135 // ttxt stsd contains display flags, justification, background
3136 // color, fonts, and default styles, so fake an atom to read it
3137 15 MOVAtom fake_atom = { .size = size };
3138 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
3139 // in extradata unlike stpp MP4 TTML.
3140
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
3141
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
15 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
3142 11 mov_read_glbl(c, pb, fake_atom);
3143 15 st->codecpar->width = sc->width;
3144 15 st->codecpar->height = sc->height;
3145 15 }
3146
3147 52 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
3148 AVStream *st, MOVStreamContext *sc,
3149 int64_t size)
3150 {
3151 int ret;
3152
3153
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 24 times.
52 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
3154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if ((int)size != size)
3155 ✗ return AVERROR(ENOMEM);
3156
3157 28 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
3158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
3159 ✗ return ret;
3160
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (size > 16) {
3161 28 MOVStreamContext *tmcd_ctx = st->priv_data;
3162 int val;
3163 28 val = AV_RB32(st->codecpar->extradata + 4);
3164 28 tmcd_ctx->tmcd_flags = val;
3165 28 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
3166 28 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
3167 28 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
3168
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 18 times.
28 if (size > 30) {
3169 10 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
3170 10 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
3171
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) {
3172 10 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
3173
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 &&
3174
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 st->codecpar->extradata[30] /* Don't add empty string */) {
3175 10 char *reel_name = av_malloc(str_size + 1);
3176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!reel_name)
3177 ✗ return AVERROR(ENOMEM);
3178 10 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
3179 10 reel_name[str_size] = 0; /* Add null terminator */
3180 10 av_dict_set(&st->metadata, "reel_name", reel_name,
3181 AV_DICT_DONT_STRDUP_VAL);
3182 }
3183 }
3184 }
3185 }
3186
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 } else if (st->codecpar->codec_id == AV_CODEC_ID_ITUT_T35) {
3187 2 int t35_identifier_length = avio_r8(pb);
3188
3189
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)
3190 ✗ return AVERROR_INVALIDDATA;
3191
3192 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, t35_identifier_length);
3193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
3194 ✗ return ret;
3195
3196 2 int hrsd_len = size - t35_identifier_length - 1;
3197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (hrsd_len > 0) {
3198 ✗ uint8_t *hrsd_str = av_malloc(hrsd_len + 1);
3199 ✗ if (!hrsd_str)
3200 ✗ return AVERROR(ENOMEM);
3201
3202 ✗ ret = ffio_read_size(pb, hrsd_str, hrsd_len);
3203 ✗ if (ret < 0) {
3204 ✗ av_free(hrsd_str);
3205 ✗ return ret;
3206 }
3207 ✗ if (hrsd_str[0]) {
3208 ✗ hrsd_str[hrsd_len] = 0;
3209 ✗ ret = av_dict_set(&st->metadata, "description", hrsd_str, AV_DICT_DONT_OVERWRITE);
3210 }
3211 ✗ av_free(hrsd_str);
3212 }
3213 } else {
3214 /* other codec type, just skip (rtp, mp4s ...) */
3215 22 avio_skip(pb, size);
3216 }
3217 52 return 0;
3218 }
3219
3220 879 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
3221 AVStream *st, MOVStreamContext *sc)
3222 {
3223 879 FFStream *const sti = ffstream(st);
3224
3225
2/2
✓ Branch 0 taken 429 times.
✓ Branch 1 taken 450 times.
879 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
3226
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 428 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
429 !st->codecpar->sample_rate && sc->time_scale > 1)
3227 1 st->codecpar->sample_rate = sc->time_scale;
3228
3229 /* special codec parameters handling */
3230
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 128 times.
✓ Branch 9 taken 592 times.
879 switch (st->codecpar->codec_id) {
3231 #if CONFIG_DV_DEMUXER
3232 ✗ case AV_CODEC_ID_DVAUDIO:
3233 ✗ if (c->dv_fctx) {
3234 ✗ avpriv_request_sample(c->fc, "multiple DV audio streams");
3235 ✗ return AVERROR(ENOSYS);
3236 }
3237
3238 ✗ c->dv_fctx = avformat_alloc_context();
3239 ✗ if (!c->dv_fctx) {
3240 ✗ av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
3241 ✗ return AVERROR(ENOMEM);
3242 }
3243 ✗ c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
3244 ✗ if (!c->dv_demux) {
3245 ✗ av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
3246 ✗ return AVERROR(ENOMEM);
3247 }
3248 ✗ sc->dv_audio_container = 1;
3249 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
3250 ✗ break;
3251 #endif
3252 /* no ifdef since parameters are always those */
3253 ✗ case AV_CODEC_ID_QCELP:
3254 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
3255 ✗ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3256 // force sample rate for qcelp when not stored in mov
3257 ✗ if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
3258 ✗ st->codecpar->sample_rate = 8000;
3259 // FIXME: Why is the following needed for some files?
3260 ✗ sc->samples_per_frame = 160;
3261 ✗ if (!sc->bytes_per_frame)
3262 ✗ sc->bytes_per_frame = 35;
3263 ✗ break;
3264 ✗ case AV_CODEC_ID_AMR_NB:
3265 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
3266 ✗ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3267 /* force sample rate for amr, stsd in 3gp does not store sample rate */
3268 ✗ st->codecpar->sample_rate = 8000;
3269 ✗ break;
3270 11 case AV_CODEC_ID_AMR_WB:
3271 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
3272 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3273 11 st->codecpar->sample_rate = 16000;
3274 11 break;
3275 103 case AV_CODEC_ID_MP2:
3276 case AV_CODEC_ID_MP3:
3277 /* force type after stsd for m1a hdlr */
3278 103 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
3279 103 break;
3280 15 case AV_CODEC_ID_GSM:
3281 case AV_CODEC_ID_ADPCM_MS:
3282 case AV_CODEC_ID_ADPCM_IMA_WAV:
3283 case AV_CODEC_ID_ILBC:
3284 case AV_CODEC_ID_MACE3:
3285 case AV_CODEC_ID_MACE6:
3286 case AV_CODEC_ID_QDM2:
3287 15 st->codecpar->block_align = sc->bytes_per_frame;
3288 15 break;
3289 16 case AV_CODEC_ID_ALAC:
3290
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
3291 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
3292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
3293 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
3294 ✗ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3295 ✗ st->codecpar->ch_layout.nb_channels = channel_count;
3296 }
3297 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
3298 }
3299 16 break;
3300 14 case AV_CODEC_ID_AC3:
3301 case AV_CODEC_ID_EAC3:
3302 case AV_CODEC_ID_MPEG1VIDEO:
3303 case AV_CODEC_ID_VC1:
3304 case AV_CODEC_ID_VP8:
3305 case AV_CODEC_ID_VP9:
3306 14 sti->need_parsing = AVSTREAM_PARSE_FULL;
3307 14 break;
3308 128 case AV_CODEC_ID_PRORES_RAW:
3309 case AV_CODEC_ID_PRORES:
3310 case AV_CODEC_ID_APV:
3311 case AV_CODEC_ID_EVC:
3312 case AV_CODEC_ID_LCEVC:
3313 case AV_CODEC_ID_AV1:
3314 /* field_order detection of H264 requires parsing */
3315 case AV_CODEC_ID_H264:
3316 128 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3317 128 break;
3318 592 default:
3319 592 break;
3320 }
3321 879 return 0;
3322 }
3323
3324 899 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
3325 int codec_tag, int format,
3326 int64_t size)
3327 {
3328
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 882 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 16 times.
899 if (codec_tag &&
3329 1 (codec_tag != format &&
3330 // AVID 1:1 samples with differing data format and codec tag exist
3331
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")) &&
3332 // prores is allowed to have differing data format and codec tag
3333
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") &&
3334 // so is dv (sigh)
3335
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") &&
3336
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
3337 : codec_tag != MKTAG('j','p','e','g')))) {
3338 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3339 * export it as a separate AVStream but this needs a few changes
3340 * in the MOV demuxer, patch welcome. */
3341
3342 1 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3343 1 avio_skip(pb, size);
3344 1 return 1;
3345 }
3346
3347 898 return 0;
3348 }
3349
3350 895 static int mov_finalize_stsd_entry(MOVContext *c, AVStream *st)
3351 {
3352 int ret;
3353
3354 /* special codec parameters handling */
3355
2/2
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 796 times.
895 switch (st->codecpar->codec_id) {
3356 99 case AV_CODEC_ID_H264:
3357 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
3358
1/30
✗ Branch 0 not taken.
✓ Branch 1 taken 99 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.
99 if (!st->codecpar->extradata_size && TAG_IS_AVCI(st->codecpar->codec_tag)) {
3359 ✗ ret = ff_generate_avci_extradata(st);
3360 ✗ if (ret < 0)
3361 ✗ return ret;
3362 }
3363 99 break;
3364 796 default:
3365 796 break;
3366 }
3367
3368 895 return 0;
3369 }
3370
3371 882 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3372 {
3373 AVStream *st;
3374 MOVStreamContext *sc;
3375 int pseudo_stream_id;
3376
3377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 av_assert0 (c->fc->nb_streams >= 1);
3378 882 st = c->fc->streams[c->fc->nb_streams-1];
3379 882 sc = st->priv_data;
3380
3381 882 for (pseudo_stream_id = 0;
3382
3/4
✓ Branch 0 taken 899 times.
✓ Branch 1 taken 879 times.
✓ Branch 2 taken 899 times.
✗ Branch 3 not taken.
1778 pseudo_stream_id < entries && !pb->eof_reached;
3383 896 pseudo_stream_id++) {
3384 //Parsing Sample description table
3385 enum AVCodecID id;
3386 899 int ret, dref_id = 1;
3387 899 MOVAtom a = { AV_RL32("stsd") };
3388 899 int64_t start_pos = avio_tell(pb);
3389 899 int64_t size = avio_rb32(pb); /* size */
3390 899 uint32_t format = avio_rl32(pb); /* data format */
3391
3392
1/2
✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
899 if (size >= 16) {
3393 899 avio_rb32(pb); /* reserved */
3394 899 avio_rb16(pb); /* reserved */
3395 899 dref_id = avio_rb16(pb);
3396 ✗ } else if (size <= 7) {
3397 ✗ av_log(c->fc, AV_LOG_ERROR,
3398 "invalid size %"PRId64" in stsd\n", size);
3399 3 return AVERROR_INVALIDDATA;
3400 }
3401
3402
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 898 times.
899 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3403 899 size - (avio_tell(pb) - start_pos))) {
3404 1 sc->stsd_count++;
3405 1 continue;
3406 }
3407
3408
2/2
✓ Branch 0 taken 882 times.
✓ Branch 1 taken 16 times.
898 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
3409 898 sc->dref_id= dref_id;
3410 898 sc->format = format;
3411
3412 898 id = mov_codec_id(st, format);
3413
3414 898 av_log(c->fc, AV_LOG_TRACE,
3415 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3416 898 av_fourcc2str(format), st->codecpar->codec_type);
3417
3418 898 st->codecpar->codec_id = id;
3419
2/2
✓ Branch 0 taken 399 times.
✓ Branch 1 taken 499 times.
898 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3420 399 mov_parse_stsd_video(c, pb, st, sc);
3421
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 67 times.
499 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3422 432 ret = mov_parse_stsd_audio(c, pb, st, sc);
3423
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 429 times.
432 if (ret < 0)
3424 3 return ret;
3425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 429 times.
429 if (st->codecpar->sample_rate < 0) {
3426 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3427 ✗ return AVERROR_INVALIDDATA;
3428 }
3429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 429 times.
429 if (st->codecpar->ch_layout.nb_channels < 0) {
3430 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3431 ✗ return AVERROR_INVALIDDATA;
3432 }
3433
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 52 times.
67 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3434 15 mov_parse_stsd_subtitle(c, pb, st, sc,
3435 15 size - (avio_tell(pb) - start_pos));
3436 } else {
3437 52 ret = mov_parse_stsd_data(c, pb, st, sc,
3438 52 size - (avio_tell(pb) - start_pos));
3439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (ret < 0)
3440 ✗ return ret;
3441 }
3442 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3443 895 a.size = size - (avio_tell(pb) - start_pos);
3444
2/2
✓ Branch 0 taken 727 times.
✓ Branch 1 taken 168 times.
895 if (a.size > 8) {
3445
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 727 times.
727 if ((ret = mov_read_default(c, pb, a)) < 0)
3446 ✗ return ret;
3447
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 167 times.
168 } else if (a.size > 0)
3448 1 avio_skip(pb, a.size);
3449
3450 895 ret = mov_finalize_stsd_entry(c, st);
3451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 895 times.
895 if (ret < 0)
3452 ✗ return ret;
3453
3454
3/4
✓ Branch 0 taken 895 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 492 times.
✓ Branch 3 taken 403 times.
895 if (sc->extradata && st->codecpar->extradata) {
3455 492 int extra_size = st->codecpar->extradata_size;
3456
3457 /* Move the current stream extradata to the stream context one. */
3458 492 sc->extradata_size[pseudo_stream_id] = extra_size;
3459 492 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3460 492 st->codecpar->extradata = NULL;
3461 492 st->codecpar->extradata_size = 0;
3462 }
3463 895 sc->stsd_count++;
3464 }
3465
3466
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 879 times.
879 if (pb->eof_reached) {
3467 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3468 ✗ return AVERROR_EOF;
3469 }
3470
3471 879 return 0;
3472 }
3473
3474 882 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3475 {
3476 AVStream *st;
3477 MOVStreamContext *sc;
3478 int ret, entries;
3479
3480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 if (c->fc->nb_streams < 1)
3481 ✗ return 0;
3482 882 st = c->fc->streams[c->fc->nb_streams - 1];
3483 882 sc = st->priv_data;
3484
3485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 if (sc->extradata) {
3486 ✗ av_log(c->fc, AV_LOG_ERROR,
3487 "Duplicate stsd found in this track.\n");
3488 ✗ return AVERROR_INVALIDDATA;
3489 }
3490
3491 882 sc->stsd_version = avio_r8(pb);
3492 882 avio_rb24(pb); /* flags */
3493 882 entries = avio_rb32(pb);
3494
3495 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3496
3/6
✓ Branch 0 taken 882 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 882 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 882 times.
882 if (entries <= 0 || entries > atom.size / 8 || entries > 1024) {
3497 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3498 ✗ return AVERROR_INVALIDDATA;
3499 }
3500
3501 /* Prepare space for hosting multiple extradata. */
3502 882 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3503
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 if (!sc->extradata)
3504 ✗ return AVERROR(ENOMEM);
3505
3506 882 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 if (!sc->extradata_size) {
3508 ✗ ret = AVERROR(ENOMEM);
3509 ✗ goto fail;
3510 }
3511
3512 882 ret = ff_mov_read_stsd_entries(c, pb, entries);
3513
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 879 times.
882 if (ret < 0)
3514 3 goto fail;
3515
3516 /* Restore back the primary extradata. */
3517 879 av_freep(&st->codecpar->extradata);
3518 879 st->codecpar->extradata_size = sc->extradata_size[0];
3519
2/2
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 402 times.
879 if (sc->extradata_size[0]) {
3520 477 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 477 times.
477 if (!st->codecpar->extradata)
3522 ✗ return AVERROR(ENOMEM);
3523 477 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3524 }
3525
3526 879 return mov_finalize_stsd_codec(c, pb, st, sc);
3527 3 fail:
3528
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (sc->extradata) {
3529 int j;
3530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 for (j = 0; j < sc->stsd_count; j++)
3531 ✗ av_freep(&sc->extradata[j]);
3532 }
3533
3534 3 sc->stsd_count = 0;
3535 3 av_freep(&sc->extradata);
3536 3 av_freep(&sc->extradata_size);
3537 3 return ret;
3538 }
3539
3540 879 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3541 {
3542 AVStream *st;
3543 MOVStreamContext *sc;
3544 unsigned int i, entries;
3545
3546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 879 times.
879 if (c->trak_index < 0) {
3547 ✗ av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3548 ✗ return 0;
3549 }
3550
3551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 879 times.
879 if (c->fc->nb_streams < 1)
3552 ✗ return 0;
3553 879 st = c->fc->streams[c->fc->nb_streams-1];
3554 879 sc = st->priv_data;
3555
3556 879 avio_r8(pb); /* version */
3557 879 avio_rb24(pb); /* flags */
3558
3559 879 entries = avio_rb32(pb);
3560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 879 times.
879 if ((uint64_t)entries * 12 + 4 > atom.size)
3561 ✗ return AVERROR_INVALIDDATA;
3562
3563 879 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3564
3565
2/2
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 745 times.
879 if (!entries)
3566 134 return 0;
3567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 745 times.
745 if (sc->stsc_data) {
3568 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3569 ✗ return 0;
3570 }
3571 745 av_free(sc->stsc_data);
3572 745 sc->stsc_count = 0;
3573 745 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 745 times.
745 if (!sc->stsc_data)
3575 ✗ return AVERROR(ENOMEM);
3576
3577
3/4
✓ Branch 0 taken 3998 times.
✓ Branch 1 taken 745 times.
✓ Branch 2 taken 3998 times.
✗ Branch 3 not taken.
4743 for (i = 0; i < entries && !pb->eof_reached; i++) {
3578 3998 sc->stsc_data[i].first = avio_rb32(pb);
3579 3998 sc->stsc_data[i].count = avio_rb32(pb);
3580 3998 sc->stsc_data[i].id = avio_rb32(pb);
3581 }
3582
3583 745 sc->stsc_count = i;
3584
2/2
✓ Branch 0 taken 3998 times.
✓ Branch 1 taken 745 times.
4743 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3585 3998 int64_t first_min = i + 1;
3586
5/6
✓ Branch 0 taken 3253 times.
✓ Branch 1 taken 745 times.
✓ Branch 2 taken 3253 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3253 times.
✓ Branch 5 taken 745 times.
3998 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
3587
1/2
✓ Branch 0 taken 3253 times.
✗ Branch 1 not taken.
3253 (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) ||
3588
1/2
✓ Branch 0 taken 3998 times.
✗ Branch 1 not taken.
3998 sc->stsc_data[i].first < first_min ||
3589
1/2
✓ Branch 0 taken 3998 times.
✗ Branch 1 not taken.
3998 sc->stsc_data[i].count < 1 ||
3590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3998 times.
3998 sc->stsc_data[i].id < 1) {
3591 ✗ 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);
3592 ✗ if (i+1 >= sc->stsc_count) {
3593 ✗ if (sc->stsc_data[i].count == 0 && i > 0) {
3594 ✗ sc->stsc_count --;
3595 ✗ continue;
3596 }
3597 ✗ sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3598 ✗ if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3599 ✗ sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3600 ✗ sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3601 ✗ sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3602 ✗ continue;
3603 }
3604 ✗ av_assert0(sc->stsc_data[i+1].first >= 2);
3605 // We replace this entry by the next valid
3606 ✗ sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3607 ✗ sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3608 ✗ sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3609 }
3610 }
3611
3612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 745 times.
745 if (pb->eof_reached) {
3613 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3614 ✗ return AVERROR_EOF;
3615 }
3616
3617 745 return 0;
3618 }
3619
3620 362137 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3621 {
3622 362137 return index < count - 1;
3623 }
3624
3625 /* Compute the samples value for the stsc entry at the given index. */
3626 58132 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3627 {
3628 int chunk_count;
3629
3630
2/2
✓ Branch 1 taken 57868 times.
✓ Branch 2 taken 264 times.
58132 if (mov_stsc_index_valid(index, sc->stsc_count))
3631 57868 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3632 else {
3633 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 264 times.
264 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3635 264 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3636 }
3637
3638 58132 return sc->stsc_data[index].count * (int64_t)chunk_count;
3639 }
3640
3641 ✗ static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3642 {
3643 AVStream *st;
3644 MOVStreamContext *sc;
3645 unsigned i, entries;
3646
3647 ✗ if (c->trak_index < 0) {
3648 ✗ av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3649 ✗ return 0;
3650 }
3651
3652 ✗ if (c->fc->nb_streams < 1)
3653 ✗ return 0;
3654 ✗ st = c->fc->streams[c->fc->nb_streams-1];
3655 ✗ sc = st->priv_data;
3656
3657 ✗ avio_rb32(pb); // version + flags
3658
3659 ✗ entries = avio_rb32(pb);
3660 ✗ if (sc->stps_data)
3661 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3662 ✗ av_free(sc->stps_data);
3663 ✗ sc->stps_count = 0;
3664 ✗ sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3665 ✗ if (!sc->stps_data)
3666 ✗ return AVERROR(ENOMEM);
3667
3668 ✗ for (i = 0; i < entries && !pb->eof_reached; i++) {
3669 ✗ sc->stps_data[i] = avio_rb32(pb);
3670 }
3671
3672 ✗ sc->stps_count = i;
3673
3674 ✗ if (pb->eof_reached) {
3675 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3676 ✗ return AVERROR_EOF;
3677 }
3678
3679 ✗ return 0;
3680 }
3681
3682 194 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3683 {
3684 AVStream *st;
3685 FFStream *sti;
3686 MOVStreamContext *sc;
3687 unsigned int i, entries;
3688
3689
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 194 times.
194 if (c->trak_index < 0) {
3690 ✗ av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3691 ✗ return 0;
3692 }
3693
3694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 194 times.
194 if (c->fc->nb_streams < 1)
3695 ✗ return 0;
3696 194 st = c->fc->streams[c->fc->nb_streams-1];
3697 194 sti = ffstream(st);
3698 194 sc = st->priv_data;
3699
3700 194 avio_r8(pb); /* version */
3701 194 avio_rb24(pb); /* flags */
3702
3703 194 entries = avio_rb32(pb);
3704
3705 194 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3706
3707
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 180 times.
194 if (!entries) {
3708 14 sc->keyframe_absent = 1;
3709
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)
3710 ✗ sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3711 14 return 0;
3712 }
3713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 180 times.
180 if (sc->keyframes)
3714 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 180 times.
180 if (entries >= UINT_MAX / sizeof(int))
3716 ✗ return AVERROR_INVALIDDATA;
3717 180 av_freep(&sc->keyframes);
3718 180 sc->keyframe_count = 0;
3719 180 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 180 times.
180 if (!sc->keyframes)
3721 ✗ return AVERROR(ENOMEM);
3722
3723
3/4
✓ Branch 0 taken 5791 times.
✓ Branch 1 taken 180 times.
✓ Branch 2 taken 5791 times.
✗ Branch 3 not taken.
5971 for (i = 0; i < entries && !pb->eof_reached; i++) {
3724 5791 sc->keyframes[i] = avio_rb32(pb);
3725 }
3726
3727 180 sc->keyframe_count = i;
3728
3729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 180 times.
180 if (pb->eof_reached) {
3730 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3731 ✗ return AVERROR_EOF;
3732 }
3733
3734 180 return 0;
3735 }
3736
3737 879 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3738 {
3739 AVStream *st;
3740 MOVStreamContext *sc;
3741 unsigned int i, entries, sample_size, field_size, num_bytes;
3742 GetBitContext gb;
3743 unsigned char* buf;
3744 int ret;
3745
3746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 879 times.
879 if (c->trak_index < 0) {
3747 ✗ av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3748 ✗ return 0;
3749 }
3750
3751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 879 times.
879 if (c->fc->nb_streams < 1)
3752 ✗ return 0;
3753 879 st = c->fc->streams[c->fc->nb_streams-1];
3754 879 sc = st->priv_data;
3755
3756 879 avio_r8(pb); /* version */
3757 879 avio_rb24(pb); /* flags */
3758
3759
1/2
✓ Branch 0 taken 879 times.
✗ Branch 1 not taken.
879 if (atom.type == MKTAG('s','t','s','z')) {
3760 879 sample_size = avio_rb32(pb);
3761
2/2
✓ Branch 0 taken 832 times.
✓ Branch 1 taken 47 times.
879 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3762 832 sc->sample_size = sample_size;
3763 879 sc->stsz_sample_size = sample_size;
3764 879 field_size = 32;
3765 } else {
3766 ✗ sample_size = 0;
3767 ✗ avio_rb24(pb); /* reserved */
3768 ✗ field_size = avio_r8(pb);
3769 }
3770 879 entries = avio_rb32(pb);
3771
3772 879 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3773
3774 879 sc->sample_count = entries;
3775
2/2
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 645 times.
879 if (sample_size)
3776 234 return 0;
3777
3778
4/8
✓ Branch 0 taken 645 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 645 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 645 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 645 times.
645 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
3779 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3780 ✗ return AVERROR_INVALIDDATA;
3781 }
3782
3783
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 510 times.
645 if (!entries)
3784 135 return 0;
3785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 510 times.
510 if (entries >= (INT_MAX - 4 - 8 * AV_INPUT_BUFFER_PADDING_SIZE) / field_size)
3786 ✗ return AVERROR_INVALIDDATA;
3787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 510 times.
510 if (sc->sample_sizes)
3788 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3789 510 av_free(sc->sample_sizes);
3790 510 sc->sample_count = 0;
3791 510 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 510 times.
510 if (!sc->sample_sizes)
3793 ✗ return AVERROR(ENOMEM);
3794
3795 510 num_bytes = (entries*field_size+4)>>3;
3796
3797 510 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 510 times.
510 if (!buf) {
3799 ✗ av_freep(&sc->sample_sizes);
3800 ✗ return AVERROR(ENOMEM);
3801 }
3802
3803 510 ret = ffio_read_size(pb, buf, num_bytes);
3804
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 510 times.
510 if (ret < 0) {
3805 ✗ av_freep(&sc->sample_sizes);
3806 ✗ av_free(buf);
3807 ✗ av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3808 ✗ return 0;
3809 }
3810
3811 510 init_get_bits(&gb, buf, 8*num_bytes);
3812
3813
2/2
✓ Branch 0 taken 251029 times.
✓ Branch 1 taken 510 times.
251539 for (i = 0; i < entries; i++) {
3814 251029 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3815
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 251029 times.
251029 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3816 ✗ av_free(buf);
3817 ✗ av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3818 ✗ return AVERROR_INVALIDDATA;
3819 }
3820 251029 sc->data_size += sc->sample_sizes[i];
3821 }
3822
3823 510 sc->sample_count = i;
3824
3825 510 av_free(buf);
3826
3827 510 return 0;
3828 }
3829
3830 879 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3831 {
3832 AVStream *st;
3833 MOVStreamContext *sc;
3834 unsigned int i, entries;
3835 879 int64_t duration = 0;
3836 879 int64_t total_sample_count = 0;
3837 879 int64_t current_dts = 0;
3838 879 int64_t corrected_dts = 0;
3839
3840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 879 times.
879 if (c->trak_index < 0) {
3841 ✗ av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3842 ✗ return 0;
3843 }
3844
3845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 879 times.
879 if (c->fc->nb_streams < 1)
3846 ✗ return 0;
3847 879 st = c->fc->streams[c->fc->nb_streams-1];
3848 879 sc = st->priv_data;
3849
3850 879 avio_r8(pb); /* version */
3851 879 avio_rb24(pb); /* flags */
3852 879 entries = avio_rb32(pb);
3853
3854 879 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3855 879 c->fc->nb_streams-1, entries);
3856
3857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 879 times.
879 if (sc->stts_data)
3858 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3859 879 av_freep(&sc->stts_data);
3860 879 sc->stts_count = 0;
3861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 879 times.
879 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3862 ✗ return AVERROR(ENOMEM);
3863
3864
3/4
✓ Branch 0 taken 3171 times.
✓ Branch 1 taken 879 times.
✓ Branch 2 taken 3171 times.
✗ Branch 3 not taken.
4050 for (i = 0; i < entries && !pb->eof_reached; i++) {
3865 unsigned int sample_duration;
3866 unsigned int sample_count;
3867 3171 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3868 3171 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3869 min_entries * sizeof(*sc->stts_data));
3870
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3171 times.
3171 if (!stts_data) {
3871 ✗ av_freep(&sc->stts_data);
3872 ✗ sc->stts_count = 0;
3873 ✗ return AVERROR(ENOMEM);
3874 }
3875 3171 sc->stts_count = min_entries;
3876 3171 sc->stts_data = stts_data;
3877
3878 3171 sample_count = avio_rb32(pb);
3879 3171 sample_duration = avio_rb32(pb);
3880
3881 3171 sc->stts_data[i].count= sample_count;
3882 3171 sc->stts_data[i].duration= sample_duration;
3883
3884 3171 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3885 sample_count, sample_duration);
3886
3887 /* STTS sample offsets are uint32 but some files store it as int32
3888 * with negative values used to correct DTS delays.
3889 There may be abnormally large values as well. */
3890
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3170 times.
3171 if (sample_duration > c->max_stts_delta) {
3891 // assume high delta is a correction if negative when cast as int32
3892 1 int32_t delta_magnitude = (int32_t)sample_duration;
3893 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",
3894 sample_duration, i, sample_count, st->index);
3895 1 sc->stts_data[i].duration = 1;
3896
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);
3897 } else {
3898 3170 corrected_dts += sample_duration * (uint64_t)sample_count;
3899 }
3900
3901 3171 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3902
3903
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 3149 times.
3171 if (current_dts > corrected_dts) {
3904 22 int64_t drift = av_sat_sub64(current_dts, corrected_dts) / FFMAX(sample_count, 1);
3905
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;
3906 22 current_dts -= correction * (uint64_t)sample_count;
3907 22 sc->stts_data[i].duration -= correction;
3908 }
3909
3910 3171 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3911 3171 total_sample_count+=sc->stts_data[i].count;
3912 }
3913
3914 879 sc->stts_count = i;
3915
3916
2/2
✓ Branch 0 taken 744 times.
✓ Branch 1 taken 135 times.
879 if (duration > 0 &&
3917
1/2
✓ Branch 0 taken 744 times.
✗ Branch 1 not taken.
744 duration <= INT64_MAX - sc->duration_for_fps &&
3918
1/2
✓ Branch 0 taken 744 times.
✗ Branch 1 not taken.
744 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3919 744 sc->duration_for_fps += duration;
3920 744 sc->nb_frames_for_fps += total_sample_count;
3921 }
3922
3923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 879 times.
879 if (pb->eof_reached) {
3924 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3925 ✗ return AVERROR_EOF;
3926 }
3927
3928 879 st->nb_frames= total_sample_count;
3929
2/2
✓ Branch 0 taken 744 times.
✓ Branch 1 taken 135 times.
879 if (duration)
3930 744 st->duration= FFMIN(st->duration, duration);
3931
3932 // All samples have zero duration. They have higher chance be chose by
3933 // mov_find_next_sample, which leads to seek again and again.
3934 //
3935 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3936 // So only mark data stream as discarded for safety.
3937
4/4
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 744 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 134 times.
879 if (!duration && sc->stts_count &&
3938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3939 ✗ av_log(c->fc, AV_LOG_WARNING,
3940 "All samples in data stream index:id [%d:%d] have zero "
3941 "duration, stream set to be discarded by default. Override "
3942 "using AVStream->discard or -discard for ffmpeg command.\n",
3943 st->index, sc->id);
3944 ✗ st->discard = AVDISCARD_ALL;
3945 }
3946 879 sc->track_end = duration;
3947 879 return 0;
3948 }
3949
3950 49 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3951 {
3952 AVStream *st;
3953 MOVStreamContext *sc;
3954 unsigned int i;
3955 int64_t entries;
3956
3957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if (c->fc->nb_streams < 1)
3958 ✗ return 0;
3959 49 st = c->fc->streams[c->fc->nb_streams - 1];
3960 49 sc = st->priv_data;
3961
3962 49 avio_r8(pb); /* version */
3963 49 avio_rb24(pb); /* flags */
3964 49 entries = atom.size - 4;
3965
3966 49 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3967 49 c->fc->nb_streams - 1, entries);
3968
3969
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 41 times.
49 if (sc->sdtp_data)
3970 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3971 49 av_freep(&sc->sdtp_data);
3972 49 sc->sdtp_count = 0;
3973
3974
2/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
49 if (entries < 0 || entries > UINT_MAX)
3975 ✗ return AVERROR(ERANGE);
3976
3977 49 sc->sdtp_data = av_malloc(entries);
3978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if (!sc->sdtp_data)
3979 ✗ return AVERROR(ENOMEM);
3980
3981
3/4
✓ Branch 0 taken 4182 times.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 4182 times.
✗ Branch 3 not taken.
4231 for (i = 0; i < entries && !pb->eof_reached; i++)
3982 4182 sc->sdtp_data[i] = avio_r8(pb);
3983 49 sc->sdtp_count = i;
3984
3985 49 return 0;
3986 }
3987
3988 17701 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3989 {
3990
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 16565 times.
17701 if (duration < 0) {
3991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3992 ✗ av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3993 ✗ duration++;
3994 }
3995 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3996 }
3997 17701 }
3998
3999 87 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4000 {
4001 AVStream *st;
4002 MOVStreamContext *sc;
4003 87 unsigned int i, entries, ctts_count = 0;
4004
4005
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
87 if (c->trak_index < 0) {
4006 ✗ av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
4007 ✗ return 0;
4008 }
4009
4010
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
87 if (c->fc->nb_streams < 1)
4011 ✗ return 0;
4012 87 st = c->fc->streams[c->fc->nb_streams-1];
4013 87 sc = st->priv_data;
4014
4015 87 avio_r8(pb); /* version */
4016 87 avio_rb24(pb); /* flags */
4017 87 entries = avio_rb32(pb);
4018
4019 87 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
4020
4021
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 83 times.
87 if (!entries)
4022 4 return 0;
4023
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
4024 ✗ return AVERROR_INVALIDDATA;
4025 83 av_freep(&sc->ctts_data);
4026 83 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
4027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if (!sc->ctts_data)
4028 ✗ return AVERROR(ENOMEM);
4029
4030
3/4
✓ Branch 0 taken 5463 times.
✓ Branch 1 taken 83 times.
✓ Branch 2 taken 5463 times.
✗ Branch 3 not taken.
5546 for (i = 0; i < entries && !pb->eof_reached; i++) {
4031 MOVCtts *ctts_data;
4032 5463 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
4033 5463 const size_t requested_size =
4034 5463 min_size_needed > sc->ctts_allocated_size ?
4035
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5463 times.
5463 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
4036 min_size_needed;
4037 5463 int count = avio_rb32(pb);
4038 5463 int duration = avio_rb32(pb);
4039
4040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5463 times.
5463 if (count <= 0) {
4041 ✗ av_log(c->fc, AV_LOG_TRACE,
4042 "ignoring CTTS entry with count=%d duration=%d\n",
4043 count, duration);
4044 ✗ continue;
4045 }
4046
4047
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5463 times.
5463 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
4048 ✗ return AVERROR(ENOMEM);
4049
4050 5463 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
4051
4052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5463 times.
5463 if (!ctts_data)
4053 ✗ return AVERROR(ENOMEM);
4054
4055 5463 sc->ctts_data = ctts_data;
4056
4057 5463 ctts_data[ctts_count].count = count;
4058 5463 ctts_data[ctts_count].offset = duration;
4059 5463 ctts_count++;
4060
4061 5463 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
4062 count, duration);
4063
4064
2/2
✓ Branch 0 taken 5309 times.
✓ Branch 1 taken 154 times.
5463 if (i+2<entries)
4065 5309 mov_update_dts_shift(sc, duration, c->fc);
4066 }
4067
4068 83 sc->ctts_count = ctts_count;
4069
4070
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if (pb->eof_reached) {
4071 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
4072 ✗ return AVERROR_EOF;
4073 }
4074
4075 83 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
4076
4077 83 return 0;
4078 }
4079
4080 56 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4081 {
4082 AVStream *st;
4083 MOVStreamContext *sc;
4084 uint8_t version;
4085 uint32_t grouping_type;
4086 uint32_t default_length;
4087 av_unused uint32_t default_group_description_index;
4088 uint32_t entry_count;
4089
4090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if (c->fc->nb_streams < 1)
4091 ✗ return 0;
4092 56 st = c->fc->streams[c->fc->nb_streams - 1];
4093 56 sc = st->priv_data;
4094
4095 56 version = avio_r8(pb); /* version */
4096 56 avio_rb24(pb); /* flags */
4097 56 grouping_type = avio_rl32(pb);
4098
4099 /*
4100 * This function only supports "sync" boxes, but the code is able to parse
4101 * other boxes (such as "tscl", "tsas" and "stsa")
4102 */
4103
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 5 times.
56 if (grouping_type != MKTAG('s','y','n','c'))
4104 51 return 0;
4105
4106
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
4107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
4108 5 entry_count = avio_rb32(pb);
4109
4110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (entry_count > atom.size)
4111 ✗ return AVERROR_INVALIDDATA;
4112
4113 5 av_freep(&sc->sgpd_sync);
4114 5 sc->sgpd_sync_count = entry_count;
4115 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
4116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
4117 ✗ return AVERROR(ENOMEM);
4118
4119
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++) {
4120 8 uint32_t description_length = default_length;
4121
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)
4122 ✗ description_length = avio_rb32(pb);
4123
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
4124 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
4125 8 sc->sgpd_sync[i] = nal_unit_type;
4126 8 description_length -= 1;
4127 }
4128 8 avio_skip(pb, description_length);
4129 }
4130
4131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
4132 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
4133 ✗ return AVERROR_EOF;
4134 }
4135
4136 5 return 0;
4137 }
4138
4139 52 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4140 {
4141 AVStream *st;
4142 MOVStreamContext *sc;
4143 unsigned int i, entries;
4144 uint8_t version;
4145 uint32_t grouping_type;
4146 MOVSbgp *table, **tablep;
4147 int *table_count;
4148
4149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (c->fc->nb_streams < 1)
4150 ✗ return 0;
4151 52 st = c->fc->streams[c->fc->nb_streams-1];
4152 52 sc = st->priv_data;
4153
4154 52 version = avio_r8(pb); /* version */
4155 52 avio_rb24(pb); /* flags */
4156 52 grouping_type = avio_rl32(pb);
4157
4158
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 51 times.
52 if (grouping_type == MKTAG('r','a','p',' ')) {
4159 1 tablep = &sc->rap_group;
4160 1 table_count = &sc->rap_group_count;
4161
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 46 times.
51 } else if (grouping_type == MKTAG('s','y','n','c')) {
4162 5 tablep = &sc->sync_group;
4163 5 table_count = &sc->sync_group_count;
4164 } else {
4165 46 return 0;
4166 }
4167
4168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
4169 ✗ avio_rb32(pb); /* grouping_type_parameter */
4170
4171 6 entries = avio_rb32(pb);
4172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
4173 ✗ return 0;
4174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
4175 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
4176 6 av_freep(tablep);
4177 6 table = av_malloc_array(entries, sizeof(*table));
4178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
4179 ✗ return AVERROR(ENOMEM);
4180 6 *tablep = table;
4181
4182
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++) {
4183 32 table[i].count = avio_rb32(pb); /* sample_count */
4184 32 table[i].index = avio_rb32(pb); /* group_description_index */
4185 }
4186
4187 6 *table_count = i;
4188
4189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
4190 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
4191 ✗ return AVERROR_EOF;
4192 }
4193
4194 6 return 0;
4195 }
4196
4197 /**
4198 * Get ith edit list entry (media time, duration).
4199 */
4200 1160 static int get_edit_list_entry(MOVContext *mov,
4201 const MOVStreamContext *msc,
4202 unsigned int edit_list_index,
4203 int64_t *edit_list_media_time,
4204 int64_t *edit_list_duration,
4205 int64_t global_timescale)
4206 {
4207
2/2
✓ Branch 0 taken 565 times.
✓ Branch 1 taken 595 times.
1160 if (edit_list_index == msc->elst_count) {
4208 565 return 0;
4209 }
4210 595 *edit_list_media_time = msc->elst_data[edit_list_index].time;
4211 595 *edit_list_duration = msc->elst_data[edit_list_index].duration;
4212
4213 /* duration is in global timescale units;convert to msc timescale */
4214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 595 times.
595 if (global_timescale == 0) {
4215 ✗ avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
4216 ✗ return 0;
4217 }
4218 595 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
4219 global_timescale);
4220
4221
1/2
✓ Branch 0 taken 595 times.
✗ Branch 1 not taken.
595 if (*edit_list_duration < 0 ||
4222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 595 times.
595 *edit_list_media_time > INT64_MAX - *edit_list_duration)
4223 ✗ *edit_list_duration = 0;
4224
4225 595 return 1;
4226 }
4227
4228 /**
4229 * Find the closest previous frame to the timestamp_pts, in e_old index
4230 * entries. Searching for just any frame / just key frames can be controlled by
4231 * last argument 'flag'.
4232 * Note that if ctts_data is not NULL, we will always search for a key frame
4233 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
4234 * return the first frame of the video.
4235 *
4236 * Here the timestamp_pts is considered to be a presentation timestamp and
4237 * the timestamp of index entries are considered to be decoding timestamps.
4238 *
4239 * Returns 0 if successful in finding a frame, else returns -1.
4240 * Places the found index corresponding output arg.
4241 *
4242 * If ctts_old is not NULL, then refines the searched entry by searching
4243 * backwards from the found timestamp, to find the frame with correct PTS.
4244 *
4245 * Places the found ctts_index and ctts_sample in corresponding output args.
4246 */
4247 595 static int find_prev_closest_index(AVStream *st,
4248 AVIndexEntry *e_old,
4249 int nb_old,
4250 MOVTimeToSample *tts_data,
4251 int64_t tts_count,
4252 int64_t timestamp_pts,
4253 int flag,
4254 int64_t* index,
4255 int64_t* tts_index,
4256 int64_t* tts_sample)
4257 {
4258 595 MOVStreamContext *msc = st->priv_data;
4259 595 FFStream *const sti = ffstream(st);
4260 595 AVIndexEntry *e_keep = sti->index_entries;
4261 595 int nb_keep = sti->nb_index_entries;
4262 595 int64_t i = 0;
4263
4264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 595 times.
595 av_assert0(index);
4265
4266 // If dts_shift > 0, then all the index timestamps will have to be offset by
4267 // at least dts_shift amount to obtain PTS.
4268 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
4269
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 586 times.
595 if (msc->dts_shift > 0) {
4270 9 timestamp_pts -= msc->dts_shift;
4271 }
4272
4273 595 sti->index_entries = e_old;
4274 595 sti->nb_index_entries = nb_old;
4275 595 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
4276
4277 // Keep going backwards in the index entries until the timestamp is the same.
4278
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 1 times.
595 if (*index >= 0) {
4279
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 565 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 29 times.
594 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
4280 ✗ i--) {
4281 ✗ if ((flag & AVSEEK_FLAG_ANY) ||
4282 ✗ (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
4283 ✗ *index = i - 1;
4284 }
4285 }
4286 }
4287
4288 // If we have CTTS then refine the search, by searching backwards over PTS
4289 // computed by adding corresponding CTTS durations to index timestamps.
4290
4/4
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 503 times.
✓ Branch 2 taken 91 times.
✓ Branch 3 taken 1 times.
595 if (msc->ctts_count && *index >= 0) {
4291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
91 av_assert0(tts_index);
4292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
91 av_assert0(tts_sample);
4293 // Find out the ctts_index for the found frame.
4294 91 *tts_index = FFMIN(*index, tts_count);
4295 91 *tts_sample = 0;
4296
4297
4/6
✓ Branch 0 taken 103 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 103 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 103 times.
✗ Branch 5 not taken.
112 while (*index >= 0 && (*tts_index) >= 0 && (*tts_index) < tts_count) {
4298 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
4299 // No need to add dts_shift to the timestamp here because timestamp_pts has already been
4300 // compensated by dts_shift above.
4301
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 15 times.
103 if ((e_old[*index].timestamp + tts_data[*tts_index].offset) <= timestamp_pts &&
4302
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 6 times.
88 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
4303 82 break;
4304 }
4305
4306 21 (*index)--;
4307
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (*tts_sample == 0) {
4308 21 (*tts_index)--;
4309
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 9 times.
21 if (*tts_index >= 0)
4310 12 *tts_sample = tts_data[*tts_index].count - 1;
4311 } else {
4312 ✗ (*tts_sample)--;
4313 }
4314 }
4315 }
4316
4317 /* restore AVStream state*/
4318 595 sti->index_entries = e_keep;
4319 595 sti->nb_index_entries = nb_keep;
4320
2/2
✓ Branch 0 taken 585 times.
✓ Branch 1 taken 10 times.
595 return *index >= 0 ? 0 : -1;
4321 }
4322
4323 /**
4324 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
4325 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
4326 *
4327 * This function is similar to ff_add_index_entry in libavformat/utils.c
4328 * except that here we are always unconditionally adding an index entry to
4329 * the end, instead of searching the entries list and skipping the add if
4330 * there is an existing entry with the same timestamp.
4331 * This is needed because the mov_fix_index calls this func with the same
4332 * unincremented timestamp for successive discarded frames.
4333 */
4334 367300 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
4335 int size, int distance, int flags)
4336 {
4337 367300 FFStream *const sti = ffstream(st);
4338 AVIndexEntry *entries, *ie;
4339 367300 int64_t index = -1;
4340 367300 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
4341
4342 // Double the allocation each time, to lower memory fragmentation.
4343 // Another difference from ff_add_index_entry function.
4344 367300 const size_t requested_size =
4345 367300 min_size_needed > sti->index_entries_allocated_size ?
4346
2/2
✓ Branch 0 taken 2534 times.
✓ Branch 1 taken 364766 times.
367300 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
4347 min_size_needed;
4348
4349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367300 times.
367300 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
4350 ✗ return -1;
4351
4352 367300 entries = av_fast_realloc(sti->index_entries,
4353 &sti->index_entries_allocated_size,
4354 requested_size);
4355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367300 times.
367300 if (!entries)
4356 ✗ return -1;
4357
4358 367300 sti->index_entries = entries;
4359
4360 367300 index = sti->nb_index_entries++;
4361 367300 ie= &entries[index];
4362
4363 367300 ie->pos = pos;
4364 367300 ie->timestamp = timestamp;
4365 367300 ie->min_distance= distance;
4366 367300 ie->size= size;
4367 367300 ie->flags = flags;
4368 367300 return index;
4369 }
4370
4371 /**
4372 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4373 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4374 */
4375 57 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4376 int64_t* frame_duration_buffer,
4377 int frame_duration_buffer_size) {
4378 57 FFStream *const sti = ffstream(st);
4379 57 int i = 0;
4380
2/4
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 57 times.
57 av_assert0(end_index >= 0 && end_index <= sti->nb_index_entries);
4381
2/2
✓ Branch 0 taken 206 times.
✓ Branch 1 taken 57 times.
263 for (i = 0; i < frame_duration_buffer_size; i++) {
4382 206 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4383 206 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4384 }
4385 57 }
4386
4387 202052 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4388 int count, int offset, unsigned int duration)
4389 {
4390 MOVTimeToSample *tts_buf_new;
4391 202052 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4392 202052 const size_t requested_size =
4393 202052 min_size_needed > *allocated_size ?
4394
2/2
✓ Branch 0 taken 1821 times.
✓ Branch 1 taken 200231 times.
202052 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4395 min_size_needed;
4396
4397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 202052 times.
202052 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4398 ✗ return -1;
4399
4400 202052 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4401
4402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 202052 times.
202052 if (!tts_buf_new)
4403 ✗ return -1;
4404
4405 202052 *tts_data = tts_buf_new;
4406
4407 202052 tts_buf_new[*tts_count].count = count;
4408 202052 tts_buf_new[*tts_count].offset = offset;
4409 202052 tts_buf_new[*tts_count].duration = duration;
4410
4411 202052 *tts_count = (*tts_count) + 1;
4412 202052 return 0;
4413 }
4414
4415 #define MAX_REORDER_DELAY 16
4416 850 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4417 {
4418 850 MOVStreamContext *msc = st->priv_data;
4419 850 FFStream *const sti = ffstream(st);
4420 850 int ctts_ind = 0;
4421 850 int ctts_sample = 0;
4422 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4423 850 int buf_start = 0;
4424 int j, r, num_swaps;
4425
4426
2/2
✓ Branch 0 taken 14450 times.
✓ Branch 1 taken 850 times.
15300 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4427 14450 pts_buf[j] = INT64_MIN;
4428
4429
3/4
✓ Branch 0 taken 850 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 83 times.
✓ Branch 3 taken 767 times.
850 if (st->codecpar->video_delay <= 0 && msc->ctts_count &&
4430
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 29 times.
83 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4431 54 st->codecpar->video_delay = 0;
4432
3/4
✓ Branch 0 taken 138704 times.
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 138704 times.
✗ Branch 3 not taken.
138758 for (int ind = 0; ind < sti->nb_index_entries && ctts_ind < msc->tts_count; ++ind) {
4433 // Point j to the last elem of the buffer and insert the current pts there.
4434 138704 j = buf_start;
4435 138704 buf_start = (buf_start + 1);
4436
2/2
✓ Branch 0 taken 8130 times.
✓ Branch 1 taken 130574 times.
138704 if (buf_start == MAX_REORDER_DELAY + 1)
4437 8130 buf_start = 0;
4438
4439 138704 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4440
4441 // The timestamps that are already in the sorted buffer, and are greater than the
4442 // current pts, are exactly the timestamps that need to be buffered to output PTS
4443 // in correct sorted order.
4444 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4445 // can be computed as the maximum no. of swaps any particular timestamp needs to
4446 // go through, to keep this buffer in sorted order.
4447 138704 num_swaps = 0;
4448
2/2
✓ Branch 0 taken 143185 times.
✓ Branch 1 taken 4 times.
143189 while (j != buf_start) {
4449 143185 r = j - 1;
4450
2/2
✓ Branch 0 taken 8444 times.
✓ Branch 1 taken 134741 times.
143185 if (r < 0) r = MAX_REORDER_DELAY;
4451
2/2
✓ Branch 0 taken 4485 times.
✓ Branch 1 taken 138700 times.
143185 if (pts_buf[j] < pts_buf[r]) {
4452 4485 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4453 4485 ++num_swaps;
4454 } else {
4455 138700 break;
4456 }
4457 4485 j = r;
4458 }
4459 138704 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4460
4461 138704 ctts_sample++;
4462
1/2
✓ Branch 0 taken 138704 times.
✗ Branch 1 not taken.
138704 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4463 138704 ctts_ind++;
4464 138704 ctts_sample = 0;
4465 }
4466 }
4467 54 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4468 54 st->codecpar->video_delay, st->index);
4469 }
4470 850 }
4471
4472 122044 static void mov_current_sample_inc(MOVStreamContext *sc)
4473 {
4474 122044 sc->current_sample++;
4475 122044 sc->current_index++;
4476
2/2
✓ Branch 0 taken 72551 times.
✓ Branch 1 taken 49493 times.
122044 if (sc->index_ranges &&
4477
2/2
✓ Branch 0 taken 506 times.
✓ Branch 1 taken 72045 times.
72551 sc->current_index >= sc->current_index_range->end &&
4478
1/2
✓ Branch 0 taken 506 times.
✗ Branch 1 not taken.
506 sc->current_index_range->end) {
4479 506 sc->current_index_range++;
4480 506 sc->current_index = sc->current_index_range->start;
4481 }
4482 122044 }
4483
4484 ✗ static void mov_current_sample_dec(MOVStreamContext *sc)
4485 {
4486 ✗ sc->current_sample--;
4487 ✗ sc->current_index--;
4488 ✗ if (sc->index_ranges &&
4489 ✗ sc->current_index < sc->current_index_range->start &&
4490 ✗ sc->current_index_range > sc->index_ranges) {
4491 ✗ sc->current_index_range--;
4492 ✗ sc->current_index = sc->current_index_range->end - 1;
4493 }
4494 ✗ }
4495
4496 511 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4497 {
4498 int64_t range_size;
4499
4500 511 sc->current_sample = current_sample;
4501 511 sc->current_index = current_sample;
4502
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 394 times.
511 if (!sc->index_ranges) {
4503 117 return;
4504 }
4505
4506 394 for (sc->current_index_range = sc->index_ranges;
4507
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 sc->current_index_range->end;
4508 ✗ sc->current_index_range++) {
4509 394 range_size = sc->current_index_range->end - sc->current_index_range->start;
4510
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 if (range_size > current_sample) {
4511 394 sc->current_index = sc->current_index_range->start + current_sample;
4512 394 break;
4513 }
4514 ✗ current_sample -= range_size;
4515 }
4516 }
4517
4518 /**
4519 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4520 * which are needed to decode them) that fall in the edit list time ranges.
4521 * Also fixes the timestamps of the index entries to match the timeline
4522 * specified the edit lists.
4523 */
4524 850 static void mov_fix_index(MOVContext *mov, AVStream *st)
4525 {
4526 850 MOVStreamContext *msc = st->priv_data;
4527 850 FFStream *const sti = ffstream(st);
4528 850 AVIndexEntry *e_old = sti->index_entries;
4529 850 int nb_old = sti->nb_index_entries;
4530 850 const AVIndexEntry *e_old_end = e_old + nb_old;
4531 850 const AVIndexEntry *current = NULL;
4532 850 MOVTimeToSample *tts_data_old = msc->tts_data;
4533 850 int64_t tts_index_old = 0;
4534 850 int64_t tts_sample_old = 0;
4535 850 int64_t tts_count_old = msc->tts_count;
4536 850 int64_t edit_list_media_time = 0;
4537 850 int64_t edit_list_duration = 0;
4538 850 int64_t frame_duration = 0;
4539 850 int64_t edit_list_dts_counter = 0;
4540 850 int64_t edit_list_dts_entry_end = 0;
4541 850 int64_t edit_list_start_tts_sample = 0;
4542 int64_t curr_cts;
4543 850 int64_t curr_ctts = 0;
4544 850 int64_t empty_edits_sum_duration = 0;
4545 850 int64_t edit_list_index = 0;
4546 int64_t index;
4547 int flags;
4548 850 int64_t start_dts = 0;
4549 850 int64_t edit_list_start_encountered = 0;
4550 850 int64_t search_timestamp = 0;
4551 850 int64_t* frame_duration_buffer = NULL;
4552 850 int num_discarded_begin = 0;
4553 850 int first_non_zero_audio_edit = -1;
4554 850 int packet_skip_samples = 0;
4555 850 MOVIndexRange *current_index_range = NULL;
4556 850 int found_keyframe_after_edit = 0;
4557 850 int found_non_empty_edit = 0;
4558
4559
4/6
✓ Branch 0 taken 565 times.
✓ Branch 1 taken 285 times.
✓ Branch 2 taken 565 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 565 times.
850 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
4560 285 return;
4561 }
4562
4563 565 int64_t max_entries = nb_old * 16LL + (1 << 16);
4564
4565 // allocate the index ranges array
4566 565 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4567 sizeof(msc->index_ranges[0]));
4568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 565 times.
565 if (!msc->index_ranges) {
4569 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4570 ✗ return;
4571 }
4572 565 msc->current_index_range = msc->index_ranges;
4573
4574 // Clean AVStream from traces of old index
4575 565 sti->index_entries = NULL;
4576 565 sti->index_entries_allocated_size = 0;
4577 565 sti->nb_index_entries = 0;
4578
4579 // Clean time to sample fields of MOVStreamContext
4580 565 msc->tts_data = NULL;
4581 565 msc->tts_count = 0;
4582 565 msc->tts_index = 0;
4583 565 msc->tts_sample = 0;
4584 565 msc->tts_allocated_size = 0;
4585
4586 // Reinitialize min_corrected_pts so that it can be computed again.
4587 565 msc->min_corrected_pts = -1;
4588
4589 // If the dts_shift is positive (in case of negative ctts values in mov),
4590 // then negate the DTS by dts_shift
4591
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 556 times.
565 if (msc->dts_shift > 0) {
4592 9 edit_list_dts_entry_end -= msc->dts_shift;
4593 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4594 }
4595
4596 565 start_dts = edit_list_dts_entry_end;
4597
4598
2/2
✓ Branch 0 taken 595 times.
✓ Branch 1 taken 565 times.
1725 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
4599 1160 &edit_list_duration, mov->time_scale)) {
4600 595 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4601 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4602 595 edit_list_index++;
4603 595 edit_list_dts_counter = edit_list_dts_entry_end;
4604 595 edit_list_dts_entry_end = av_sat_add64(edit_list_dts_entry_end, edit_list_duration);
4605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 595 times.
595 if (edit_list_dts_entry_end == INT64_MAX) {
4606 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot calculate dts entry length with duration %"PRId64"\n",
4607 edit_list_duration);
4608 ✗ break;
4609 }
4610 595 num_discarded_begin = 0;
4611
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 590 times.
595 if (edit_list_media_time == -1) {
4612
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (!found_non_empty_edit)
4613 5 empty_edits_sum_duration += edit_list_duration;
4614 5 continue;
4615 }
4616 590 found_non_empty_edit = 1;
4617
4618 // If we encounter a non-negative edit list reset the skip_samples/initial_padding fields and set them
4619 // according to the edit list below.
4620
2/2
✓ Branch 0 taken 177 times.
✓ Branch 1 taken 413 times.
590 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4621
1/2
✓ Branch 0 taken 177 times.
✗ Branch 1 not taken.
177 if (first_non_zero_audio_edit < 0) {
4622 177 first_non_zero_audio_edit = 1;
4623 } else {
4624 ✗ first_non_zero_audio_edit = 0;
4625 }
4626
4627
1/2
✓ Branch 0 taken 177 times.
✗ Branch 1 not taken.
177 if (first_non_zero_audio_edit > 0)
4628 177 sti->skip_samples = st->codecpar->initial_padding = 0;
4629 }
4630
4631 // While reordering frame index according to edit list we must handle properly
4632 // the scenario when edit list entry starts from none key frame.
4633 // We find closest previous key frame and preserve it and consequent frames in index.
4634 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4635 590 search_timestamp = edit_list_media_time;
4636
2/2
✓ Branch 0 taken 177 times.
✓ Branch 1 taken 413 times.
590 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4637 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4638 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4639 // edit_list_media_time to cover the decoder delay.
4640
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 176 times.
177 search_timestamp = FFMAX(av_sat_sub64(search_timestamp, msc->time_scale), e_old[0].timestamp);
4641 }
4642
4643
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 585 times.
590 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, 0,
4644 &index, &tts_index_old, &tts_sample_old) < 0) {
4645 5 av_log(mov->fc, AV_LOG_WARNING,
4646 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4647 st->index, edit_list_index, search_timestamp);
4648
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, AVSEEK_FLAG_ANY,
4649 &index, &tts_index_old, &tts_sample_old) < 0) {
4650 5 av_log(mov->fc, AV_LOG_WARNING,
4651 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4652 st->index, edit_list_index, search_timestamp);
4653 5 index = 0;
4654 5 tts_index_old = 0;
4655 5 tts_sample_old = 0;
4656 }
4657 }
4658 590 current = e_old + index;
4659 590 edit_list_start_tts_sample = tts_sample_old;
4660
4661 // Iterate over index and arrange it according to edit list
4662 590 edit_list_start_encountered = 0;
4663 590 found_keyframe_after_edit = 0;
4664
2/2
✓ Branch 0 taken 367300 times.
✓ Branch 1 taken 154 times.
367454 for (; current < e_old_end; current++, index++) {
4665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367300 times.
367300 if (sti->nb_index_entries >= max_entries) {
4666 ✗ av_log(mov->fc, AV_LOG_ERROR, "Edit list expands the sample index beyond %"PRId64" entries\n",
4667 max_entries);
4668 ✗ goto truncated;
4669 }
4670 // check if frame outside edit list mark it for discard
4671 734600 frame_duration = (current + 1 < e_old_end) ?
4672
2/2
✓ Branch 0 taken 366743 times.
✓ Branch 1 taken 557 times.
367300 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4673
4674 367300 flags = current->flags;
4675
4676 // frames (pts) before or after edit list
4677 367300 curr_cts = current->timestamp + msc->dts_shift;
4678 367300 curr_ctts = 0;
4679
4680
4/4
✓ Branch 0 taken 202064 times.
✓ Branch 1 taken 165236 times.
✓ Branch 2 taken 202052 times.
✓ Branch 3 taken 12 times.
367300 if (tts_data_old && tts_index_old < tts_count_old) {
4681 202052 curr_ctts = tts_data_old[tts_index_old].offset;
4682 202052 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4683 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4684 202052 curr_cts += curr_ctts;
4685 202052 tts_sample_old++;
4686
1/2
✓ Branch 0 taken 202052 times.
✗ Branch 1 not taken.
202052 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 202052 times.
202052 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4688 &msc->tts_allocated_size,
4689 202052 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4690 202052 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4691 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4692 tts_index_old,
4693 ✗ tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4694 ✗ tts_data_old[tts_index_old].offset);
4695 ✗ break;
4696 }
4697 202052 tts_index_old++;
4698 202052 tts_sample_old = 0;
4699 202052 edit_list_start_tts_sample = 0;
4700 }
4701 }
4702
4703
4/4
✓ Branch 0 taken 367064 times.
✓ Branch 1 taken 236 times.
✓ Branch 2 taken 160 times.
✓ Branch 3 taken 366904 times.
367300 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
4704
4/4
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 261 times.
✓ Branch 2 taken 89 times.
✓ Branch 3 taken 46 times.
396 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
4705
4/6
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 63 times.
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
89 curr_cts < edit_list_media_time && curr_cts + frame_duration > edit_list_media_time &&
4706 first_non_zero_audio_edit > 0) {
4707 26 packet_skip_samples = edit_list_media_time - curr_cts;
4708 26 sti->skip_samples += packet_skip_samples;
4709
4710 // Shift the index entry timestamp by packet_skip_samples to be correct.
4711 26 edit_list_dts_counter -= packet_skip_samples;
4712
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (edit_list_start_encountered == 0) {
4713 26 edit_list_start_encountered = 1;
4714 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4715 // discarded packets.
4716
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 10 times.
26 if (frame_duration_buffer) {
4717 16 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4718 frame_duration_buffer, num_discarded_begin);
4719 16 av_freep(&frame_duration_buffer);
4720 }
4721 }
4722
4723 26 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4724 } else {
4725 370 flags |= AVINDEX_DISCARD_FRAME;
4726 370 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4727
4728
2/2
✓ Branch 0 taken 208 times.
✓ Branch 1 taken 162 times.
370 if (edit_list_start_encountered == 0) {
4729 208 num_discarded_begin++;
4730
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 208 times.
208 if (av_reallocp_array(&frame_duration_buffer, num_discarded_begin,
4731 sizeof(*frame_duration_buffer)) < 0) {
4732 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4733 ✗ break;
4734 }
4735 208 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4736
4737 // Increment skip_samples for the first non-zero audio edit list
4738
3/4
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 109 times.
✗ Branch 3 not taken.
208 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4739
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 46 times.
109 first_non_zero_audio_edit > 0 && st->codecpar->codec_id != AV_CODEC_ID_VORBIS) {
4740 63 sti->skip_samples += frame_duration;
4741 }
4742 }
4743 }
4744 } else {
4745
2/2
✓ Branch 0 taken 564 times.
✓ Branch 1 taken 366340 times.
366904 if (msc->min_corrected_pts < 0) {
4746 564 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4747 } else {
4748 366340 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4749 }
4750
2/2
✓ Branch 0 taken 562 times.
✓ Branch 1 taken 366342 times.
366904 if (edit_list_start_encountered == 0) {
4751 562 edit_list_start_encountered = 1;
4752 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4753 // discarded packets.
4754
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 521 times.
562 if (frame_duration_buffer) {
4755 41 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4756 frame_duration_buffer, num_discarded_begin);
4757 41 av_freep(&frame_duration_buffer);
4758 }
4759 }
4760 }
4761
4762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367300 times.
367300 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
4763 367300 current->min_distance, flags) == -1) {
4764 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4765 ✗ break;
4766 }
4767
4768 // Update the index ranges array
4769
4/4
✓ Branch 0 taken 366735 times.
✓ Branch 1 taken 565 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 366712 times.
367300 if (!current_index_range || index != current_index_range->end) {
4770 588 current_index_range = current_index_range ? current_index_range + 1
4771
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 565 times.
588 : msc->index_ranges;
4772 588 current_index_range->start = index;
4773 }
4774 367300 current_index_range->end = index + 1;
4775
4776 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4777
2/2
✓ Branch 0 taken 367092 times.
✓ Branch 1 taken 208 times.
367300 if (edit_list_start_encountered > 0) {
4778 367092 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4779 }
4780
4781 // Break when found first key frame after edit entry completion
4782
2/2
✓ Branch 0 taken 791 times.
✓ Branch 1 taken 366509 times.
367300 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
4783
4/4
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 455 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 333 times.
791 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
4784
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 425 times.
458 if (msc->ctts_count) {
4785 // If we have CTTS and this is the first keyframe after edit elist,
4786 // wait for one more, because there might be trailing B-frames after this I-frame
4787 // that do belong to the edit.
4788
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) {
4789 22 found_keyframe_after_edit = 1;
4790 22 continue;
4791 }
4792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (tts_sample_old != 0) {
4793 ✗ if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4794 &msc->tts_allocated_size,
4795 ✗ tts_sample_old - edit_list_start_tts_sample,
4796 ✗ tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4797 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4798 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4799 ✗ tts_data_old[tts_index_old].offset);
4800 ✗ break;
4801 }
4802 }
4803 }
4804 436 break;
4805 }
4806 }
4807 }
4808 565 truncated:
4809 // If there are empty edits, then msc->min_corrected_pts might be positive
4810 // intentionally. So we subtract the sum duration of empty edits here.
4811 565 msc->min_corrected_pts -= empty_edits_sum_duration;
4812
4813 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4814 // dts by that amount to make the first pts zero.
4815
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 228 times.
565 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4816
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 272 times.
337 if (msc->min_corrected_pts > 0) {
4817 65 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4818
2/2
✓ Branch 0 taken 3529 times.
✓ Branch 1 taken 65 times.
3594 for (int i = 0; i < sti->nb_index_entries; ++i)
4819 3529 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4820 }
4821 }
4822 // Start time should be equal to zero or the duration of any empty edits.
4823 565 st->start_time = empty_edits_sum_duration;
4824
4825 // Update av stream length, if it ends up shorter than the track's media duration
4826 565 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4827 565 st->codecpar->initial_padding = sti->skip_samples;
4828
4829 // Free the old index and the old CTTS structures
4830 565 av_free(e_old);
4831 565 av_free(tts_data_old);
4832 565 av_freep(&frame_duration_buffer);
4833
4834 // Null terminate the index ranges array
4835 565 current_index_range = current_index_range ? current_index_range + 1
4836
1/2
✓ Branch 0 taken 565 times.
✗ Branch 1 not taken.
565 : msc->index_ranges;
4837 565 current_index_range->start = 0;
4838 565 current_index_range->end = 0;
4839 565 msc->current_index = msc->index_ranges[0].start;
4840 }
4841
4842 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4843 {
4844
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4845
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == nal_unit_type)
4846 5 return i + 1;
4847 ✗ return 0;
4848 }
4849
4850 985 static int build_open_gop_key_points(AVStream *st)
4851 {
4852 int k;
4853 985 int sample_id = 0;
4854 uint32_t cra_index;
4855 985 MOVStreamContext *sc = st->priv_data;
4856
4857
4/4
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 904 times.
✓ Branch 2 taken 76 times.
✓ Branch 3 taken 5 times.
985 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count)
4858 980 return 0;
4859
4860 /* Build an unrolled index of the samples */
4861 5 sc->sample_offsets_count = 0;
4862
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4864 ✗ return AVERROR(ENOMEM);
4865 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4866 }
4867 5 av_freep(&sc->sample_offsets);
4868 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4870 ✗ return AVERROR(ENOMEM);
4871 5 k = 0;
4872
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4873
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4874 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4875
4876 /* The following HEVC NAL type reveal the use of open GOP sync points
4877 * (TODO: BLA types may also be concerned) */
4878 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4880 ✗ return 0;
4881
4882 /* Build a list of open-GOP key samples */
4883 5 sc->open_key_samples_count = 0;
4884
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4885
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4886
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)
4887 ✗ return AVERROR(ENOMEM);
4888 11 sc->open_key_samples_count += sc->sync_group[i].count;
4889 }
4890 5 av_freep(&sc->open_key_samples);
4891 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4892
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4893 ✗ return AVERROR(ENOMEM);
4894 5 k = 0;
4895
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4896 28 const MOVSbgp *sg = &sc->sync_group[i];
4897
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4898
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4899 11 sc->open_key_samples[k++] = sample_id;
4900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4901 ✗ return AVERROR_PATCHWELCOME;
4902 28 sample_id += sg->count;
4903 }
4904
4905 /* Identify the minimal time step between samples */
4906 5 sc->min_sample_duration = UINT_MAX;
4907
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4908 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4909
4910 5 return 0;
4911 }
4912
4913 #define MOV_MERGE_CTTS 1
4914 #define MOV_MERGE_STTS 2
4915 /*
4916 * Merge stts and ctts arrays into a new combined array.
4917 * stts_count and ctts_count may be left untouched as they will be
4918 * used to check for the presence of either of them.
4919 */
4920 850 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4921 {
4922 850 MOVStreamContext *sc = st->priv_data;
4923
3/4
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 767 times.
✓ Branch 2 taken 83 times.
✗ Branch 3 not taken.
850 int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS);
4924
3/4
✓ Branch 0 taken 850 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 779 times.
✓ Branch 3 taken 71 times.
850 int stts = sc->stts_data && (flags & MOV_MERGE_STTS);
4925 850 int idx = 0;
4926
4927
3/4
✓ Branch 0 taken 767 times.
✓ Branch 1 taken 83 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 767 times.
850 if (!sc->ctts_data && !sc->stts_data)
4928 ✗ return 0;
4929 // Expand time to sample entries such that we have a 1-1 mapping with samples
4930
2/4
✓ Branch 0 taken 850 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 850 times.
850 if (!sc->sample_count || sc->sample_count >= UINT_MAX / sizeof(*sc->tts_data))
4931 ✗ return -1;
4932
4933
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 767 times.
850 if (ctts) {
4934 166 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4935 83 sc->sample_count * sizeof(*sc->tts_data));
4936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if (!sc->tts_data)
4937 ✗ return -1;
4938
4939 83 memset(sc->tts_data, 0, sc->tts_allocated_size);
4940
4941
2/2
✓ Branch 0 taken 5463 times.
✓ Branch 1 taken 83 times.
5546 for (int i = 0; i < sc->ctts_count &&
4942
1/2
✓ Branch 0 taken 5463 times.
✗ Branch 1 not taken.
10926 idx < sc->sample_count; i++)
4943
2/2
✓ Branch 0 taken 139691 times.
✓ Branch 1 taken 5463 times.
145154 for (int j = 0; j < sc->ctts_data[i].count &&
4944
1/2
✓ Branch 0 taken 139691 times.
✗ Branch 1 not taken.
139691 idx < sc->sample_count; j++) {
4945 139691 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4946 139691 sc->tts_data[idx++].count = 1;
4947 }
4948
4949 83 sc->tts_count = idx;
4950 } else
4951 767 sc->ctts_count = 0;
4952 850 av_freep(&sc->ctts_data);
4953 850 sc->ctts_allocated_size = 0;
4954
4955 850 idx = 0;
4956
2/2
✓ Branch 0 taken 779 times.
✓ Branch 1 taken 71 times.
850 if (stts) {
4957 779 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4958 779 sc->sample_count * sizeof(*sc->tts_data));
4959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 779 times.
779 if (!tts_data)
4960 ✗ return -1;
4961
4962
2/2
✓ Branch 0 taken 696 times.
✓ Branch 1 taken 83 times.
779 if (!sc->tts_data)
4963 696 memset(tts_data, 0, sc->tts_allocated_size);
4964 779 sc->tts_data = tts_data;
4965
4966
2/2
✓ Branch 0 taken 3205 times.
✓ Branch 1 taken 779 times.
3984 for (int i = 0; i < sc->stts_count &&
4967
1/2
✓ Branch 0 taken 3205 times.
✗ Branch 1 not taken.
6410 idx < sc->sample_count; i++)
4968
2/2
✓ Branch 0 taken 260415 times.
✓ Branch 1 taken 3205 times.
263620 for (int j = 0; j < sc->stts_data[i].count &&
4969
1/2
✓ Branch 0 taken 260415 times.
✗ Branch 1 not taken.
260415 idx < sc->sample_count; j++) {
4970 260415 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4971 260415 sc->tts_data[idx++].count = 1;
4972 }
4973
4974 779 sc->tts_count = FFMAX(sc->tts_count, idx);
4975 } else
4976 71 sc->stts_count = 0;
4977 850 av_freep(&sc->stts_data);
4978 850 sc->stts_allocated_size = 0;
4979
4980 850 return 0;
4981 }
4982
4983 985 static void mov_build_index(MOVContext *mov, AVStream *st)
4984 {
4985 985 MOVStreamContext *sc = st->priv_data;
4986 985 FFStream *const sti = ffstream(st);
4987 int64_t current_offset;
4988 985 int64_t current_dts = 0;
4989 985 unsigned int stts_index = 0;
4990 985 unsigned int stsc_index = 0;
4991 985 unsigned int stss_index = 0;
4992 985 unsigned int stps_index = 0;
4993 unsigned int i, j;
4994 985 uint64_t stream_size = 0;
4995
4996 985 int ret = build_open_gop_key_points(st);
4997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 985 times.
985 if (ret < 0)
4998 ✗ return;
4999
5000
2/2
✓ Branch 0 taken 668 times.
✓ Branch 1 taken 317 times.
985 if (sc->elst_count) {
5001 668 int i, edit_start_index = 0, multiple_edits = 0;
5002 668 int64_t empty_duration = 0; // empty duration of the first edit list entry
5003 668 int64_t start_time = 0; // start time of the media
5004
5005
2/2
✓ Branch 0 taken 698 times.
✓ Branch 1 taken 668 times.
1366 for (i = 0; i < sc->elst_count; i++) {
5006 698 const MOVElst *e = &sc->elst_data[i];
5007
4/4
✓ Branch 0 taken 668 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 663 times.
698 if (i == 0 && e->time == -1) {
5008 /* if empty, the first entry is the start time of the stream
5009 * relative to the presentation itself */
5010 5 empty_duration = e->duration;
5011 5 edit_start_index = 1;
5012
3/4
✓ Branch 0 taken 668 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 668 times.
✗ Branch 3 not taken.
693 } else if (i == edit_start_index && e->time >= 0) {
5013 668 start_time = e->time;
5014 } else {
5015 25 multiple_edits = 1;
5016 }
5017 }
5018
5019
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 661 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
668 if (multiple_edits && !mov->advanced_editlist) {
5020 ✗ if (mov->advanced_editlist_autodisabled)
5021 ✗ av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
5022 "not supported in fragmented MP4 files\n");
5023 else
5024 ✗ av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
5025 "Use -advanced_editlist to correctly decode otherwise "
5026 "a/v desync might occur\n");
5027 }
5028
5029 /* adjust first dts according to edit list */
5030
5/6
✓ Branch 0 taken 663 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 128 times.
✓ Branch 3 taken 535 times.
✓ Branch 4 taken 133 times.
✗ Branch 5 not taken.
668 if ((empty_duration || start_time) && mov->time_scale > 0) {
5031
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 128 times.
133 if (empty_duration)
5032 5 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
5033
5034
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 133 times.
133 if (av_sat_sub64(start_time, empty_duration) != start_time - (uint64_t)empty_duration)
5035 ✗ av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
5036
5037 133 sc->time_offset = start_time - (uint64_t)empty_duration;
5038 133 sc->min_corrected_pts = start_time;
5039
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 132 times.
133 if (!mov->advanced_editlist)
5040 1 current_dts = -av_clip64(sc->time_offset, -INT64_MAX, INT64_MAX);
5041 }
5042
5043
4/4
✓ Branch 0 taken 661 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 103 times.
✓ Branch 3 taken 558 times.
668 if (!multiple_edits && !mov->advanced_editlist &&
5044
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)
5045 ✗ st->codecpar->initial_padding = av_rescale_q(start_time, st->time_base,
5046 ✗ (AVRational){1, st->codecpar->sample_rate});
5047 }
5048
5049 /* only use old uncompressed audio chunk demuxing when stts specifies it */
5050
2/2
✓ Branch 0 taken 429 times.
✓ Branch 1 taken 556 times.
985 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
5051
5/6
✓ Branch 0 taken 274 times.
✓ Branch 1 taken 155 times.
✓ Branch 2 taken 274 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 202 times.
✓ Branch 5 taken 72 times.
1208 sc->stts_count == 1 && sc->stts_data && sc->stts_data[0].duration == 1)) {
5052 913 unsigned int current_sample = 0;
5053 913 unsigned int stts_sample = 0;
5054 unsigned int sample_size;
5055 913 unsigned int distance = 0;
5056 913 unsigned int rap_group_index = 0;
5057 913 unsigned int rap_group_sample = 0;
5058
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 912 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
913 int rap_group_present = sc->rap_group_count && sc->rap_group;
5059
4/8
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 733 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 180 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 733 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
913 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
5060
5061
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 913 times.
913 av_assert0(sc->dts_shift >= 0);
5062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 913 times.
913 if (current_dts < INT64_MIN + sc->dts_shift)
5063 ✗ return;
5064 913 current_dts -= sc->dts_shift;
5065
4/6
✓ Branch 0 taken 779 times.
✓ Branch 1 taken 134 times.
✓ Branch 2 taken 779 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 779 times.
913 if (!sc->sample_count || sti->nb_index_entries || sc->tts_count)
5066 134 return;
5067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 779 times.
779 if (sc->sample_count >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
5068 ✗ return;
5069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 779 times.
779 if (av_reallocp_array(&sti->index_entries,
5070 779 sti->nb_index_entries + sc->sample_count,
5071 sizeof(*sti->index_entries)) < 0) {
5072 ✗ sti->nb_index_entries = 0;
5073 ✗ return;
5074 }
5075 779 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
5076
5077 779 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
5078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 779 times.
779 if (ret < 0)
5079 ✗ return;
5080
5081
2/2
✓ Branch 0 taken 179285 times.
✓ Branch 1 taken 779 times.
180064 for (i = 0; i < sc->chunk_count; i++) {
5082
2/2
✓ Branch 0 taken 178506 times.
✓ Branch 1 taken 779 times.
179285 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
5083 179285 current_offset = sc->chunk_offsets[i];
5084
2/2
✓ Branch 1 taken 9246 times.
✓ Branch 2 taken 172621 times.
181867 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
5085
2/2
✓ Branch 0 taken 2582 times.
✓ Branch 1 taken 6664 times.
9246 i + 1 == sc->stsc_data[stsc_index + 1].first)
5086 2582 stsc_index++;
5087
5088
4/6
✓ Branch 0 taken 179285 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7485 times.
✓ Branch 3 taken 171800 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7485 times.
179285 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
5089 ✗ sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
5090 ✗ av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
5091 ✗ sc->stsz_sample_size = sc->sample_size;
5092 }
5093
3/4
✓ Branch 0 taken 7485 times.
✓ Branch 1 taken 171800 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7485 times.
179285 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
5094 ✗ av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
5095 ✗ sc->stsz_sample_size = sc->sample_size;
5096 }
5097
5098
2/2
✓ Branch 0 taken 260415 times.
✓ Branch 1 taken 179285 times.
439700 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
5099 260415 int keyframe = 0;
5100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 260415 times.
260415 if (current_sample >= sc->sample_count) {
5101 ✗ av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
5102 ✗ return;
5103 }
5104
5105
6/6
✓ Branch 0 taken 250704 times.
✓ Branch 1 taken 9711 times.
✓ Branch 2 taken 153890 times.
✓ Branch 3 taken 96814 times.
✓ Branch 4 taken 5791 times.
✓ Branch 5 taken 148099 times.
260415 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
5106 102605 keyframe = 1;
5107
2/2
✓ Branch 0 taken 5611 times.
✓ Branch 1 taken 96994 times.
102605 if (stss_index + 1 < sc->keyframe_count)
5108 5611 stss_index++;
5109
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 157810 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
157810 } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
5110 ✗ keyframe = 1;
5111 ✗ if (stps_index + 1 < sc->stps_count)
5112 ✗ stps_index++;
5113 }
5114
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 260227 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
260415 if (rap_group_present && rap_group_index < sc->rap_group_count) {
5115
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
5116 2 keyframe = 1;
5117
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
5118 4 rap_group_sample = 0;
5119 4 rap_group_index++;
5120 }
5121 }
5122
2/2
✓ Branch 0 taken 9711 times.
✓ Branch 1 taken 250704 times.
260415 if (sc->keyframe_absent
5123
1/2
✓ Branch 0 taken 9711 times.
✗ Branch 1 not taken.
9711 && !sc->stps_count
5124
1/2
✓ Branch 0 taken 9711 times.
✗ Branch 1 not taken.
9711 && !rap_group_present
5125
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)))
5126 8839 keyframe = 1;
5127
2/2
✓ Branch 0 taken 111444 times.
✓ Branch 1 taken 148971 times.
260415 if (keyframe)
5128 111444 distance = 0;
5129
2/2
✓ Branch 0 taken 9386 times.
✓ Branch 1 taken 251029 times.
260415 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
5130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 260415 times.
260415 if (current_offset > INT64_MAX - sample_size) {
5131 ✗ av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
5132 current_offset,
5133 sample_size);
5134 ✗ return;
5135 }
5136
5137
2/2
✓ Branch 0 taken 260318 times.
✓ Branch 1 taken 97 times.
260415 if (sc->pseudo_stream_id == -1 ||
5138
2/2
✓ Branch 0 taken 260316 times.
✓ Branch 1 taken 2 times.
260318 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
5139 AVIndexEntry *e;
5140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 260413 times.
260413 if (sample_size > 0x3FFFFFFF) {
5141 ✗ av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
5142 ✗ return;
5143 }
5144 260413 e = &sti->index_entries[sti->nb_index_entries++];
5145 260413 e->pos = current_offset;
5146 260413 e->timestamp = current_dts;
5147 260413 e->size = sample_size;
5148 260413 e->min_distance = distance;
5149 260413 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
5150 260413 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
5151 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
5152 current_offset, current_dts, sample_size, distance, keyframe);
5153
4/4
✓ Branch 0 taken 156874 times.
✓ Branch 1 taken 103539 times.
✓ Branch 2 taken 12179 times.
✓ Branch 3 taken 144695 times.
260413 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries < 100)
5154 12179 ff_rfps_add_frame(mov->fc, st, current_dts);
5155 }
5156
5157 260415 current_offset += sample_size;
5158 260415 stream_size += sample_size;
5159
5160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 260415 times.
260415 if (current_dts > INT64_MAX - sc->tts_data[stts_index].duration)
5161 ✗ return;
5162 260415 current_dts += sc->tts_data[stts_index].duration;
5163
5164 260415 distance++;
5165 260415 stts_sample++;
5166 260415 current_sample++;
5167
3/4
✓ Branch 0 taken 259636 times.
✓ Branch 1 taken 779 times.
✓ Branch 2 taken 259636 times.
✗ Branch 3 not taken.
260415 if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) {
5168 259636 stts_sample = 0;
5169 259636 stts_index++;
5170 }
5171 }
5172 }
5173
2/2
✓ Branch 0 taken 673 times.
✓ Branch 1 taken 106 times.
779 if (st->duration > 0)
5174 673 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
5175 } else {
5176 72 unsigned chunk_samples, total = 0;
5177
5178
3/4
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 71 times.
72 if (!sc->chunk_count || sc->tts_count)
5179 1 return;
5180
5181 // compute total chunk count
5182
2/2
✓ Branch 0 taken 742 times.
✓ Branch 1 taken 71 times.
813 for (i = 0; i < sc->stsc_count; i++) {
5183 unsigned count, chunk_count;
5184
5185 742 chunk_samples = sc->stsc_data[i].count;
5186
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 71 times.
742 if (i != sc->stsc_count - 1 &&
5187
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) {
5188 ✗ av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
5189 ✗ return;
5190 }
5191
5192
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 667 times.
742 if (sc->samples_per_frame >= 160) { // gsm
5193 75 count = chunk_samples / sc->samples_per_frame;
5194
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 136 times.
667 } else if (sc->samples_per_frame > 1) {
5195 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
5196 531 count = (chunk_samples+samples-1) / samples;
5197 } else {
5198 136 count = (chunk_samples+1023) / 1024;
5199 }
5200
5201
2/2
✓ Branch 1 taken 671 times.
✓ Branch 2 taken 71 times.
742 if (mov_stsc_index_valid(i, sc->stsc_count))
5202 671 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
5203 else
5204 71 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
5205 742 total += chunk_count * count;
5206 }
5207
5208 71 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
5209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
5210 ✗ return;
5211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (av_reallocp_array(&sti->index_entries,
5212 71 sti->nb_index_entries + total,
5213 sizeof(*sti->index_entries)) < 0) {
5214 ✗ sti->nb_index_entries = 0;
5215 ✗ return;
5216 }
5217 71 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
5218
5219 // populate index
5220
2/2
✓ Branch 0 taken 5563 times.
✓ Branch 1 taken 71 times.
5634 for (i = 0; i < sc->chunk_count; i++) {
5221 5563 current_offset = sc->chunk_offsets[i];
5222
2/2
✓ Branch 1 taken 5399 times.
✓ Branch 2 taken 164 times.
5563 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
5223
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 4728 times.
5399 i + 1 == sc->stsc_data[stsc_index + 1].first)
5224 671 stsc_index++;
5225 5563 chunk_samples = sc->stsc_data[stsc_index].count;
5226
5227
2/2
✓ Branch 0 taken 165283 times.
✓ Branch 1 taken 5563 times.
170846 while (chunk_samples > 0) {
5228 AVIndexEntry *e;
5229 unsigned size, samples;
5230
5231
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) {
5232 ✗ avpriv_request_sample(mov->fc,
5233 "Zero bytes per frame, but %d samples per frame",
5234 sc->samples_per_frame);
5235 ✗ return;
5236 }
5237
5238
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 150925 times.
165283 if (sc->samples_per_frame >= 160) { // gsm
5239 14358 samples = sc->samples_per_frame;
5240 14358 size = sc->bytes_per_frame;
5241 } else {
5242
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 141362 times.
150925 if (sc->samples_per_frame > 1) {
5243 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
5244 sc->samples_per_frame, chunk_samples);
5245 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
5246 } else {
5247 141362 samples = FFMIN(1024, chunk_samples);
5248 141362 size = samples * sc->sample_size;
5249 }
5250 }
5251
5252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165283 times.
165283 if (sti->nb_index_entries >= total) {
5253 ✗ av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
5254 ✗ return;
5255 }
5256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165283 times.
165283 if (size > 0x3FFFFFFF) {
5257 ✗ av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
5258 ✗ return;
5259 }
5260 165283 e = &sti->index_entries[sti->nb_index_entries++];
5261 165283 e->pos = current_offset;
5262 165283 e->timestamp = current_dts;
5263 165283 e->size = size;
5264 165283 e->min_distance = 0;
5265 165283 e->flags = AVINDEX_KEYFRAME;
5266 165283 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
5267 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
5268 size, samples);
5269
5270 165283 current_offset += size;
5271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165283 times.
165283 if (current_dts > INT64_MAX - samples)
5272 ✗ return;
5273 165283 current_dts += samples;
5274 165283 chunk_samples -= samples;
5275 }
5276 }
5277
5278 71 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
5279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (ret < 0)
5280 ✗ return;
5281 }
5282
5283
2/4
✓ Branch 0 taken 850 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 850 times.
✗ Branch 3 not taken.
850 if (!mov->ignore_editlist && mov->advanced_editlist) {
5284 // Fix index according to edit lists.
5285 850 mov_fix_index(mov, st);
5286 }
5287
5288 // Update start time of the stream.
5289
5/6
✓ Branch 0 taken 285 times.
✓ Branch 1 taken 565 times.
✓ Branch 2 taken 134 times.
✓ Branch 3 taken 151 times.
✓ Branch 4 taken 134 times.
✗ Branch 5 not taken.
850 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) {
5290 134 st->start_time = av_sat_add64(sti->index_entries[0].timestamp, sc->dts_shift);
5291
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 if (sc->tts_data) {
5292 134 st->start_time = av_sat_add64(st->start_time, sc->tts_data[0].offset);
5293 }
5294 }
5295
5296 850 mov_estimate_video_delay(mov, st);
5297 }
5298
5299 typedef struct MOVPresentationSample {
5300 int index;
5301 int64_t pts;
5302 } MOVPresentationSample;
5303
5304 12202 static int mov_compare_presentation_samples(const void *a, const void *b)
5305 {
5306 12202 const MOVPresentationSample *sa = a;
5307 12202 const MOVPresentationSample *sb = b;
5308
5309
2/2
✓ Branch 0 taken 12198 times.
✓ Branch 1 taken 4 times.
12202 if (sa->pts != sb->pts)
5310 12198 return (sa->pts > sb->pts) - (sa->pts < sb->pts);
5311 4 return (sa->index > sb->index) - (sa->index < sb->index);
5312 }
5313
5314 /*
5315 * Set sample durations from adjacent presentation timestamps.
5316 */
5317 879 static void mov_update_sample_durations(MOVContext *mov, AVStream *st)
5318 {
5319 879 MOVStreamContext *sc = st->priv_data;
5320 879 FFStream *const sti = ffstream(st);
5321 879 MOVPresentationSample *samples = NULL;
5322 879 MOVTimeToSample *tts_data = NULL;
5323 879 unsigned int tts_index = 0, tts_sample = 0;
5324 879 int count = sti->nb_index_entries;
5325
5326 /* A single STTS entry describes a fixed sample delta. */
5327
2/2
✓ Branch 0 taken 384 times.
✓ Branch 1 taken 495 times.
879 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
5328
4/4
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 305 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 67 times.
384 !sc->ctts_count || sc->stts_count < 2 ||
5329
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 ||
5330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 count >= UINT_MAX / sizeof(*tts_data))
5331 867 return;
5332
5333 12 samples = av_malloc_array(count, sizeof(*samples));
5334 12 tts_data = av_malloc_array(count, sizeof(*tts_data));
5335
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)
5336 ✗ goto fail;
5337
5338
2/2
✓ Branch 0 taken 2654 times.
✓ Branch 1 taken 12 times.
2666 for (int i = 0; i < count; i++) {
5339 int64_t dts, offset;
5340
5341
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)
5342 ✗ goto fail;
5343
5344 2654 tts_data[i] = sc->tts_data[tts_index];
5345 2654 tts_data[i].count = 1;
5346
5347 2654 dts = sti->index_entries[i].timestamp;
5348 2654 offset = (int64_t)sc->dts_shift + tts_data[i].offset;
5349
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 ||
5350
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) ||
5351 ✗ (offset < 0 && dts < INT64_MIN - offset))
5352 ✗ goto fail;
5353
5354 2654 samples[i].index = i;
5355 2654 samples[i].pts = dts + offset;
5356
5357
1/2
✓ Branch 0 taken 2654 times.
✗ Branch 1 not taken.
2654 if (++tts_sample == sc->tts_data[tts_index].count) {
5358 2654 tts_index++;
5359 2654 tts_sample = 0;
5360 }
5361 }
5362
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)
5363 ✗ goto fail;
5364
5365 12 qsort(samples, count, sizeof(*samples), mov_compare_presentation_samples);
5366
5367
2/2
✓ Branch 0 taken 2624 times.
✓ Branch 1 taken 10 times.
2634 for (int i = 0; i + 1 < count; i++) {
5368 uint64_t duration;
5369
5370
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2622 times.
2624 if (samples[i].pts >= samples[i + 1].pts)
5371 2 goto fail;
5372
5373 /*
5374 * In VFR streams with reordered frames, STTS deltas follow decode
5375 * order while AVPacket.duration follows presentation order. CTTS
5376 * may produce presentation intervals that cannot be obtained by
5377 * merely permuting the STTS deltas, so derive each known duration
5378 * from adjacent PTS.
5379 */
5380 2622 duration = (uint64_t)samples[i + 1].pts - samples[i].pts;
5381
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)
5382 ✗ goto fail;
5383
5384 2622 tts_data[samples[i].index].duration = (unsigned int)duration;
5385 }
5386
5387 10 av_log(mov->fc, AV_LOG_DEBUG,
5388 "Updated sample durations in presentation order for stream %d\n",
5389 st->index);
5390
5391 10 av_freep(&sc->tts_data);
5392 10 sc->tts_data = tts_data;
5393 10 sc->tts_count = count;
5394 10 sc->tts_allocated_size = count * sizeof(*tts_data);
5395 10 tts_data = NULL;
5396
5397 12 fail:
5398 12 av_free(samples);
5399 12 av_free(tts_data);
5400 }
5401
5402 ✗ static int test_same_origin(const char *src, const char *ref) {
5403 char src_proto[64];
5404 char ref_proto[64];
5405 char src_auth[256];
5406 char ref_auth[256];
5407 char src_host[256];
5408 char ref_host[256];
5409 ✗ int src_port=-1;
5410 ✗ int ref_port=-1;
5411
5412 ✗ av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
5413 ✗ av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
5414
5415 ✗ if (strlen(src) == 0) {
5416 ✗ return -1;
5417 ✗ } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
5418 ✗ strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
5419 ✗ strlen(src_host) + 1 >= sizeof(src_host) ||
5420 ✗ strlen(ref_host) + 1 >= sizeof(ref_host)) {
5421 ✗ return 0;
5422 ✗ } else if (strcmp(src_proto, ref_proto) ||
5423 ✗ strcmp(src_auth, ref_auth) ||
5424 ✗ strcmp(src_host, ref_host) ||
5425 ✗ src_port != ref_port) {
5426 ✗ return 0;
5427 } else
5428 ✗ return 1;
5429 }
5430
5431 ✗ static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
5432 {
5433 /* try relative path, we do not try the absolute because it can leak information about our
5434 system to an attacker */
5435 ✗ if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
5436 char filename[1025];
5437 const char *src_path;
5438 int i, l;
5439
5440 /* find a source dir */
5441 ✗ src_path = strrchr(src, '/');
5442 ✗ if (src_path)
5443 ✗ src_path++;
5444 else
5445 ✗ src_path = src;
5446
5447 /* find a next level down to target */
5448 ✗ for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
5449 ✗ if (ref->path[l] == '/') {
5450 ✗ if (i == ref->nlvl_to - 1)
5451 ✗ break;
5452 else
5453 ✗ i++;
5454 }
5455
5456 /* compose filename if next level down to target was found */
5457 ✗ if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
5458 ✗ memcpy(filename, src, src_path - src);
5459 ✗ filename[src_path - src] = 0;
5460
5461 ✗ for (i = 1; i < ref->nlvl_from; i++)
5462 ✗ av_strlcat(filename, "../", sizeof(filename));
5463
5464 ✗ av_strlcat(filename, ref->path + l + 1, sizeof(filename));
5465 ✗ if (!c->use_absolute_path) {
5466 ✗ int same_origin = test_same_origin(src, filename);
5467
5468 ✗ if (!same_origin) {
5469 ✗ av_log(c->fc, AV_LOG_ERROR,
5470 "Reference with mismatching origin, %s not tried for security reasons, "
5471 "set demuxer option use_absolute_path to allow it anyway\n",
5472 ref->path);
5473 ✗ return AVERROR(ENOENT);
5474 }
5475
5476 ✗ if (strstr(ref->path + l + 1, "..") ||
5477 ✗ strstr(ref->path + l + 1, ":") ||
5478 ✗ (ref->nlvl_from > 1 && same_origin < 0) ||
5479 ✗ (filename[0] == '/' && src_path == src))
5480 ✗ return AVERROR(ENOENT);
5481 }
5482
5483 ✗ if (strlen(filename) + 1 == sizeof(filename))
5484 ✗ return AVERROR(ENOENT);
5485 ✗ if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5486 ✗ return 0;
5487 }
5488 ✗ } else if (c->use_absolute_path) {
5489 ✗ av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5490 "this is a possible security issue\n");
5491 ✗ if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5492 ✗ return 0;
5493 } else {
5494 ✗ av_log(c->fc, AV_LOG_ERROR,
5495 "Absolute path %s not tried for security reasons, "
5496 "set demuxer option use_absolute_path to allow absolute paths\n",
5497 ref->path);
5498 }
5499
5500 ✗ return AVERROR(ENOENT);
5501 }
5502
5503 1934 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5504 {
5505
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1918 times.
1934 if (sc->time_scale <= 0) {
5506 16 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5507 16 sc->time_scale = c->time_scale;
5508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (sc->time_scale <= 0)
5509 ✗ sc->time_scale = 1;
5510 }
5511 1934 }
5512
5513 #if CONFIG_IAMFDEC
5514 14 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5515 {
5516 14 const MOVStreamContext *sc = st->priv_data;
5517 14 const IAMFContext *iamf = &sc->iamf->iamf;
5518
5519
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 14 times.
30 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5520 16 const AVStreamGroup *stg = NULL;
5521
5522
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 16 times.
52 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5523
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 16 times.
36 if (c->fc->stream_groups[j]->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT &&
5524
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 c->fc->stream_groups[j]->id == iamf->audio_elements[i]->audio_element_id)
5525 16 stg = c->fc->stream_groups[j];
5526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 av_assert0(stg);
5527
5528
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 16 times.
84 for (int j = 0; j < stg->nb_entries; j++) {
5529 68 const FFStream *sti = cffstream(st);
5530 68 AVStream *out = stg->entries[j]->stream;
5531 68 FFStream *out_sti = ffstream(stg->entries[j]->stream);
5532
5533 68 out->codecpar->bit_rate = 0;
5534
5535
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 54 times.
68 if (out == st)
5536 14 continue;
5537
5538 54 out->time_base = st->time_base;
5539 54 out->start_time = st->start_time;
5540 54 out->duration = st->duration;
5541 54 out->nb_frames = st->nb_frames;
5542 54 out->discard = st->discard;
5543
5544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 av_assert0(!out_sti->index_entries);
5545 54 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (!out_sti->index_entries)
5547 ✗ return AVERROR(ENOMEM);
5548
5549 54 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5550 54 out_sti->nb_index_entries = sti->nb_index_entries;
5551 54 out_sti->skip_samples = sti->skip_samples;
5552 54 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5553 }
5554 }
5555
5556 14 return 0;
5557 }
5558 #endif
5559
5560 985 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5561 {
5562
4/6
✓ Branch 0 taken 850 times.
✓ Branch 1 taken 135 times.
✓ Branch 2 taken 850 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 850 times.
✗ Branch 5 not taken.
985 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5563
3/4
✓ Branch 0 taken 510 times.
✓ Branch 1 taken 340 times.
✓ Branch 2 taken 510 times.
✗ Branch 3 not taken.
850 (!sc->sample_size && !sc->sample_count))) ||
5564
3/4
✓ Branch 0 taken 850 times.
✓ Branch 1 taken 135 times.
✓ Branch 2 taken 850 times.
✗ Branch 3 not taken.
985 (sc->sample_count && (!sc->chunk_count ||
5565
3/4
✓ Branch 0 taken 510 times.
✓ Branch 1 taken 340 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 510 times.
850 (!sc->sample_size && !sc->sample_sizes)))) {
5566 ✗ av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5567 index);
5568 ✗ return 1;
5569 }
5570
5571
3/4
✓ Branch 0 taken 850 times.
✓ Branch 1 taken 135 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 850 times.
985 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
5572 ✗ av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5573 index);
5574 ✗ return 2;
5575 }
5576 985 return 0;
5577 }
5578
5579 882 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5580 {
5581 AVStream *st;
5582 MOVStreamContext *sc;
5583 int ret;
5584
5585 882 st = avformat_new_stream(c->fc, NULL);
5586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 if (!st) return AVERROR(ENOMEM);
5587 882 st->id = -1;
5588 882 sc = av_mallocz(sizeof(MOVStreamContext));
5589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 if (!sc) return AVERROR(ENOMEM);
5590
5591 882 st->priv_data = sc;
5592 882 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5593 882 sc->ffindex = st->index;
5594 882 c->trak_index = st->index;
5595 882 sc->refcount = 1;
5596
5597
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 879 times.
882 if ((ret = mov_read_default(c, pb, atom)) < 0)
5598 3 return ret;
5599
5600 879 c->trak_index = -1;
5601
5602 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5603 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5604
6/6
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 744 times.
✓ Branch 2 taken 134 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 133 times.
879 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
5605 1 sc->stsc_count = 0;
5606 1 av_freep(&sc->stsc_data);
5607 }
5608
5609 879 ret = sanity_checks(c->fc, sc, st->index);
5610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 879 times.
879 if (ret)
5611 ✗ return ret > 1 ? AVERROR_INVALIDDATA : 0;
5612
5613 879 fix_timescale(c, sc);
5614
5615 879 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5616
5617 /*
5618 * Advanced edit list support does not work with fragemented MP4s, which
5619 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5620 * In these files, trun atoms may be streamed in.
5621 */
5622
4/4
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 745 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 108 times.
879 if (!sc->stts_count && c->advanced_editlist) {
5623
5624 26 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5625 "MP4. disabling.\n");
5626 26 c->advanced_editlist = 0;
5627 26 c->advanced_editlist_autodisabled = 1;
5628 }
5629
5630 879 mov_build_index(c, st);
5631 /*
5632 * Fragment samples are appended later by mov_read_trun() and are not
5633 * covered by this non-fragmented track update.
5634 */
5635 879 mov_update_sample_durations(c, st);
5636
5637 #if CONFIG_IAMFDEC
5638
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 865 times.
879 if (sc->iamf) {
5639 14 ret = mov_update_iamf_streams(c, st);
5640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0)
5641 ✗ return ret;
5642 }
5643 #endif
5644
5645
3/4
✓ Branch 0 taken 878 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 878 times.
879 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
5646 ✗ MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5647 ✗ if (c->enable_drefs) {
5648 ✗ if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5649 ✗ av_log(c->fc, AV_LOG_ERROR,
5650 "stream %d, error opening alias: path='%s', dir='%s', "
5651 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5652 ✗ st->index, dref->path, dref->dir, dref->filename,
5653 ✗ dref->volume, dref->nlvl_from, dref->nlvl_to);
5654 } else {
5655 ✗ av_log(c->fc, AV_LOG_WARNING,
5656 "Skipped opening external track: "
5657 "stream %d, alias: path='%s', dir='%s', "
5658 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5659 "Set enable_drefs to allow this.\n",
5660 ✗ st->index, dref->path, dref->dir, dref->filename,
5661 ✗ dref->volume, dref->nlvl_from, dref->nlvl_to);
5662 }
5663 } else {
5664 879 sc->pb = c->fc->pb;
5665 879 sc->pb_is_copied = 1;
5666 }
5667
5668
2/2
✓ Branch 0 taken 384 times.
✓ Branch 1 taken 495 times.
879 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5669
3/4
✓ Branch 0 taken 365 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 365 times.
✗ Branch 3 not taken.
384 int stts_constant = sc->stts_count && sc->tts_count;
5670
3/4
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 288 times.
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
384 if (sc->h_spacing && sc->v_spacing)
5671 96 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5672 96 sc->h_spacing, sc->v_spacing, INT_MAX);
5673
4/6
✓ Branch 0 taken 285 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 285 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 285 times.
✗ Branch 5 not taken.
384 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
5674
2/4
✓ Branch 0 taken 285 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 285 times.
✗ Branch 3 not taken.
285 sc->height && sc->width &&
5675
2/4
✓ Branch 0 taken 285 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 285 times.
285 (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
5676 ✗ av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5677 ✗ (int64_t)st->codecpar->height * sc->width,
5678 ✗ (int64_t)st->codecpar->width * sc->height, INT_MAX);
5679 }
5680
5681 #if FF_API_R_FRAME_RATE
5682
4/4
✓ Branch 0 taken 156590 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 156225 times.
✓ Branch 3 taken 365 times.
156609 for (unsigned int i = 1; sc->stts_count && i + 1 < sc->tts_count; i++) {
5683
2/2
✓ Branch 0 taken 153730 times.
✓ Branch 1 taken 2495 times.
156225 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5684 153730 continue;
5685 2495 stts_constant = 0;
5686 }
5687
2/2
✓ Branch 0 taken 346 times.
✓ Branch 1 taken 38 times.
384 if (stts_constant)
5688 346 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5689 346 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5690 #endif
5691 }
5692
5693 #if CONFIG_H261_DECODER || CONFIG_H263_DECODER || CONFIG_MPEG4_DECODER
5694
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 848 times.
879 switch (st->codecpar->codec_id) {
5695 #if CONFIG_H261_DECODER
5696 31 case AV_CODEC_ID_H261:
5697 #endif
5698 #if CONFIG_H263_DECODER
5699 case AV_CODEC_ID_H263:
5700 #endif
5701 #if CONFIG_MPEG4_DECODER
5702 case AV_CODEC_ID_MPEG4:
5703 #endif
5704 31 st->codecpar->width = 0; /* let decoder init width/height */
5705 31 st->codecpar->height= 0;
5706 31 break;
5707 }
5708 #endif
5709
5710 // If the duration of the mp3 packets is not constant, then they could need a parser
5711
2/2
✓ Branch 0 taken 103 times.
✓ Branch 1 taken 776 times.
879 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5712
1/2
✓ Branch 0 taken 103 times.
✗ Branch 1 not taken.
103 && sc->time_scale == st->codecpar->sample_rate) {
5713 103 int stts_constant = 1;
5714
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++) {
5715
1/2
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
365 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5716 365 continue;
5717 ✗ stts_constant = 0;
5718 }
5719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103 times.
103 if (!stts_constant)
5720 ✗ ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5721 }
5722 /* Do not need those anymore. */
5723 879 av_freep(&sc->chunk_offsets);
5724 879 av_freep(&sc->sample_sizes);
5725 879 av_freep(&sc->keyframes);
5726 879 av_freep(&sc->stps_data);
5727 879 av_freep(&sc->elst_data);
5728 879 av_freep(&sc->rap_group);
5729 879 av_freep(&sc->sync_group);
5730 879 av_freep(&sc->sgpd_sync);
5731
5732 879 return 0;
5733 }
5734
5735 223 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5736 {
5737 int ret;
5738 223 c->itunes_metadata = 1;
5739 223 ret = mov_read_default(c, pb, atom);
5740 223 c->itunes_metadata = 0;
5741 223 return ret;
5742 }
5743
5744 16 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5745 {
5746 uint32_t count;
5747 uint32_t i;
5748
5749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (atom.size < 8)
5750 ✗ return 0;
5751
5752 16 avio_skip(pb, 4);
5753 16 count = avio_rb32(pb);
5754 16 atom.size -= 8;
5755
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
16 if (count > atom.size / 8 || count >= UINT_MAX / sizeof(*c->meta_keys)) {
5756 ✗ av_log(c->fc, AV_LOG_ERROR,
5757 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5758 ✗ return AVERROR_INVALIDDATA;
5759 }
5760
5761 16 c->meta_keys = av_malloc_array(count + 1, sizeof(*c->meta_keys));
5762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!c->meta_keys)
5763 ✗ return AVERROR(ENOMEM);
5764
5765 16 c->meta_keys[0] = NULL;
5766 16 c->meta_keys_count = 1;
5767
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 16 times.
126 for (i = 1; i <= count; ++i) {
5768 110 uint32_t key_size = avio_rb32(pb);
5769 110 uint32_t type = avio_rl32(pb);
5770 110 c->meta_keys[i] = NULL;
5771 110 c->meta_keys_count = i + 1;
5772
2/4
✓ Branch 0 taken 110 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 110 times.
110 if (key_size < 8 || key_size > atom.size) {
5773 ✗ av_log(c->fc, AV_LOG_ERROR,
5774 "The key# %"PRIu32" in meta has invalid size:"
5775 "%"PRIu32"\n", i, key_size);
5776 ✗ return AVERROR_INVALIDDATA;
5777 }
5778 110 atom.size -= key_size;
5779 110 key_size -= 8;
5780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
110 if (type != MKTAG('m','d','t','a')) {
5781 ✗ avio_skip(pb, key_size);
5782 ✗ continue;
5783 }
5784 110 c->meta_keys[i] = av_malloc(key_size + 1);
5785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
110 if (!c->meta_keys[i])
5786 ✗ return AVERROR(ENOMEM);
5787 110 int ret = ffio_read_size(pb, c->meta_keys[i], key_size);
5788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
110 if (ret < 0)
5789 ✗ return ret;
5790 110 c->meta_keys[i][key_size] = 0;
5791 }
5792
5793 16 return 0;
5794 }
5795
5796 91 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5797 {
5798 91 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5799 91 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5800 int i;
5801 91 int ret = 0;
5802 AVStream *st;
5803
5804
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
91 if (c->fc->nb_streams < 1)
5805 ✗ return 0;
5806 91 st = c->fc->streams[c->fc->nb_streams-1];
5807
5808
2/2
✓ Branch 0 taken 273 times.
✓ Branch 1 taken 91 times.
364 for (i = 0; i < 3; i++) {
5809 uint8_t **p;
5810 uint32_t len, tag;
5811
5812
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 273 times.
273 if (end - avio_tell(pb) <= 12)
5813 ✗ break;
5814
5815 273 len = avio_rb32(pb);
5816 273 tag = avio_rl32(pb);
5817 273 avio_skip(pb, 4); // flags
5818
5819
2/4
✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 273 times.
✗ Branch 4 not taken.
273 if (len < 12 || len - 12 > end - avio_tell(pb))
5820 break;
5821 273 len -= 12;
5822
5823
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 182 times.
273 if (tag == MKTAG('m', 'e', 'a', 'n'))
5824 91 p = &mean;
5825
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 91 times.
182 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5826 91 p = &key;
5827
2/4
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91 times.
✗ Branch 3 not taken.
91 else if (tag == MKTAG('d', 'a', 't', 'a') && len > 4) {
5828 91 avio_skip(pb, 4);
5829 91 len -= 4;
5830 91 p = &val;
5831 } else
5832 break;
5833
5834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 273 times.
273 if (*p)
5835 ✗ break;
5836
5837 273 *p = av_malloc(len + 1);
5838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 273 times.
273 if (!*p) {
5839 ✗ ret = AVERROR(ENOMEM);
5840 ✗ break;
5841 }
5842 273 ret = ffio_read_size(pb, *p, len);
5843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 273 times.
273 if (ret < 0) {
5844 ✗ av_freep(p);
5845 ✗ break;
5846 }
5847 273 (*p)[len] = 0;
5848 }
5849
5850
3/6
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 91 times.
✗ Branch 5 not taken.
91 if (mean && key && val) {
5851
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 38 times.
91 if (strcmp(key, "iTunSMPB") == 0) {
5852 int64_t priming, remainder, samples;
5853
1/2
✓ Branch 1 taken 53 times.
✗ Branch 2 not taken.
53 if (ff_itunes_parse_smpb(val, &priming, &remainder, &samples) >= 0) {
5854
2/4
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
53 if(priming>0 && priming<16384)
5855 53 st->codecpar->initial_padding = priming = av_rescale_q(priming, st->time_base,
5856 53 (AVRational){ 1, st->codecpar->sample_rate });
5857
1/2
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
53 if (remainder > 0) {
5858 53 int64_t duration = av_rescale_q(st->duration, st->time_base,
5859 53 (AVRational){ 1, st->codecpar->sample_rate });
5860 53 remainder = av_rescale_q(remainder, st->time_base,
5861 53 (AVRational){ 1, st->codecpar->sample_rate });
5862 53 samples = av_rescale_q(samples, st->time_base,
5863 53 (AVRational){ 1, st->codecpar->sample_rate });
5864
2/4
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
53 if (duration > remainder && duration > samples) {
5865 53 ffstream(st)->first_discard_sample = duration - remainder;
5866 53 ffstream(st)->last_discard_sample = duration;
5867 }
5868 }
5869 53 av_log(c->fc, AV_LOG_DEBUG, "Parsed iTunSMPB: priming %"PRId64", "
5870 "remainder %"PRId64" samples %"PRId64"\n",
5871 priming, remainder, samples);
5872 }
5873 }
5874
1/2
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
91 if (strcmp(mean, "com.apple.iTunes") == 0 &&
5875
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 89 times.
91 strcmp(key, "DISCSUBTITLE") == 0) {
5876 2 av_dict_set(&c->fc->metadata, "disc_subtitle", val,
5877 AV_DICT_DONT_STRDUP_VAL);
5878 2 val = NULL;
5879 }
5880
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 10 times.
172 if (strcmp(key, "cdec") != 0) {
5881 81 av_dict_set(&c->fc->metadata, key, val,
5882 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5883 81 key = val = NULL;
5884 }
5885 } else {
5886 ✗ av_log(c->fc, AV_LOG_VERBOSE,
5887 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5888 }
5889
5890 91 avio_seek(pb, end, SEEK_SET);
5891 91 av_freep(&key);
5892 91 av_freep(&val);
5893 91 av_freep(&mean);
5894 91 return ret;
5895 }
5896
5897 106 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5898 {
5899 MOVStreamContext *sc;
5900 AVStream *st;
5901
5902 106 st = avformat_new_stream(c->fc, NULL);
5903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
106 if (!st)
5904 ✗ return AVERROR(ENOMEM);
5905 106 sc = av_mallocz(sizeof(MOVStreamContext));
5906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
106 if (!sc)
5907 ✗ goto fail;
5908
5909 106 item->st = st;
5910 106 st->id = item->item_id;
5911 106 st->priv_data = sc;
5912 106 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5913 106 st->codecpar->codec_id = mov_codec_id(st, item->type);
5914 106 sc->id = st->id;
5915 106 sc->ffindex = st->index;
5916 106 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5917 106 st->time_base.num = st->time_base.den = 1;
5918 106 st->nb_frames = 1;
5919 106 sc->time_scale = 1;
5920 106 sc->pb = c->fc->pb;
5921 106 sc->pb_is_copied = 1;
5922 106 sc->refcount = 1;
5923
5924
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 12 times.
106 if (item->name)
5925 94 av_dict_set(&st->metadata, "title", item->name, 0);
5926
5927 // Populate the necessary fields used by mov_build_index.
5928 106 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
106 if (!sc->stsc_data)
5930 ✗ goto fail;
5931 106 sc->stsc_count = 1;
5932 106 sc->stsc_data[0].first = 1;
5933 106 sc->stsc_data[0].count = 1;
5934 106 sc->stsc_data[0].id = 1;
5935 106 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
106 if (!sc->chunk_offsets)
5937 ✗ goto fail;
5938 106 sc->chunk_count = 1;
5939 106 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
106 if (!sc->stts_data)
5941 ✗ goto fail;
5942 106 sc->stts_count = 1;
5943 106 sc->stts_data[0].count = 1;
5944 // Not used for still images. But needed by mov_build_index.
5945 106 sc->stts_data[0].duration = 0;
5946
5947 106 return 0;
5948 ✗ fail:
5949 ✗ mov_free_stream_context(c->fc, st);
5950 ✗ ff_remove_stream(c->fc, st);
5951 ✗ item->st = NULL;
5952
5953 ✗ return AVERROR(ENOMEM);
5954 }
5955
5956 254 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5957 {
5958
1/2
✓ Branch 0 taken 738 times.
✗ Branch 1 not taken.
738 while (atom.size > 8) {
5959 uint32_t tag;
5960
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 738 times.
738 if (avio_feof(pb))
5961 ✗ return AVERROR_EOF;
5962 738 tag = avio_rl32(pb);
5963 738 atom.size -= 4;
5964
2/2
✓ Branch 0 taken 254 times.
✓ Branch 1 taken 484 times.
738 if (tag == MKTAG('h','d','l','r')) {
5965 254 avio_seek(pb, -8, SEEK_CUR);
5966 254 atom.size += 8;
5967 254 return mov_read_default(c, pb, atom);
5968 }
5969 }
5970 ✗ return 0;
5971 }
5972
5973 // return 1 when matrix is identity, 0 otherwise
5974 #define IS_MATRIX_IDENT(matrix) \
5975 ( (matrix)[0][0] == (1 << 16) && \
5976 (matrix)[1][1] == (1 << 16) && \
5977 (matrix)[2][2] == (1 << 30) && \
5978 !(matrix)[0][1] && !(matrix)[0][2] && \
5979 !(matrix)[1][0] && !(matrix)[1][2] && \
5980 !(matrix)[2][0] && !(matrix)[2][1])
5981
5982 882 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5983 {
5984 int i, j, e;
5985 int width;
5986 int height;
5987 int display_matrix[3][3];
5988 882 int res_display_matrix[3][3] = { { 0 } };
5989 AVStream *st;
5990 MOVStreamContext *sc;
5991 int version;
5992 int flags;
5993
5994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 if (c->fc->nb_streams < 1)
5995 ✗ return 0;
5996 882 st = c->fc->streams[c->fc->nb_streams-1];
5997 882 sc = st->priv_data;
5998
5999 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
6000 // avoids corrupting AVStreams mapped to an earlier tkhd.
6001
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 if (st->id != -1)
6002 ✗ return AVERROR_INVALIDDATA;
6003
6004 882 version = avio_r8(pb);
6005 882 flags = avio_rb24(pb);
6006 882 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
6007
6008
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 869 times.
882 if (version == 1) {
6009 13 avio_rb64(pb);
6010 13 avio_rb64(pb);
6011 } else {
6012 869 avio_rb32(pb); /* creation time */
6013 869 avio_rb32(pb); /* modification time */
6014 }
6015 882 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
6016 882 sc->id = st->id;
6017 882 avio_rb32(pb); /* reserved */
6018
6019 /* highlevel (considering edits) duration in movie timebase */
6020
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 869 times.
882 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
6021 882 avio_rb32(pb); /* reserved */
6022 882 avio_rb32(pb); /* reserved */
6023
6024 882 avio_rb16(pb); /* layer */
6025 882 avio_rb16(pb); /* alternate group */
6026 882 avio_rb16(pb); /* volume */
6027 882 avio_rb16(pb); /* reserved */
6028
6029 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
6030 // they're kept in fixed point format through all calculations
6031 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
6032 // side data, but the scale factor is not needed to calculate aspect ratio
6033
2/2
✓ Branch 0 taken 2646 times.
✓ Branch 1 taken 882 times.
3528 for (i = 0; i < 3; i++) {
6034 2646 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
6035 2646 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
6036 2646 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
6037 }
6038
6039 882 width = avio_rb32(pb); // 16.16 fixed point track width
6040 882 height = avio_rb32(pb); // 16.16 fixed point track height
6041 882 sc->width = width >> 16;
6042 882 sc->height = height >> 16;
6043
6044 // apply the moov display matrix (after the tkhd one)
6045
2/2
✓ Branch 0 taken 2646 times.
✓ Branch 1 taken 882 times.
3528 for (i = 0; i < 3; i++) {
6046 2646 const int sh[3] = { 16, 16, 30 };
6047
2/2
✓ Branch 0 taken 7938 times.
✓ Branch 1 taken 2646 times.
10584 for (j = 0; j < 3; j++) {
6048
2/2
✓ Branch 0 taken 23814 times.
✓ Branch 1 taken 7938 times.
31752 for (e = 0; e < 3; e++) {
6049 23814 res_display_matrix[i][j] +=
6050 23814 ((int64_t) display_matrix[i][e] *
6051 23814 c->movie_display_matrix[e][j]) >> sh[e];
6052 }
6053 }
6054 }
6055
6056 // save the matrix when it is not the default identity
6057
10/18
✓ Branch 0 taken 869 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 869 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 869 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 869 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 869 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 869 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 869 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 869 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 869 times.
882 if (!IS_MATRIX_IDENT(res_display_matrix)) {
6058 13 av_freep(&sc->display_matrix);
6059 13 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
6060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!sc->display_matrix)
6061 ✗ return AVERROR(ENOMEM);
6062
6063
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 13 times.
52 for (i = 0; i < 3; i++)
6064
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 39 times.
156 for (j = 0; j < 3; j++)
6065 117 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
6066 }
6067
6068 // transform the display width/height according to the matrix
6069 // to keep the same scale, use [width height 1<<16]
6070
5/6
✓ Branch 0 taken 403 times.
✓ Branch 1 taken 479 times.
✓ Branch 2 taken 403 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 391 times.
882 if (width && height && sc->display_matrix) {
6071 double disp_transform[2];
6072
6073
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (i = 0; i < 2; i++)
6074 24 disp_transform[i] = hypot(sc->display_matrix[0 + i],
6075 24 sc->display_matrix[3 + i]);
6076
6077
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 if (disp_transform[0] > 1 && disp_transform[1] > 1 &&
6078
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 disp_transform[0] < (1<<24) && disp_transform[1] < (1<<24) &&
6079
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
6080 3 st->sample_aspect_ratio = av_d2q(
6081 3 disp_transform[0] / disp_transform[1],
6082 INT_MAX);
6083 }
6084 882 return 0;
6085 }
6086
6087 707 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6088 {
6089 707 MOVFragment *frag = &c->fragment;
6090 707 MOVTrackExt *trex = NULL;
6091 int flags, track_id, i;
6092 MOVFragmentStreamInfo * frag_stream_info;
6093
6094 707 avio_r8(pb); /* version */
6095 707 flags = avio_rb24(pb);
6096
6097 707 track_id = avio_rb32(pb);
6098
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 if (!track_id)
6099 ✗ return AVERROR_INVALIDDATA;
6100
1/2
✓ Branch 0 taken 10666 times.
✗ Branch 1 not taken.
10666 for (i = 0; i < c->trex_count; i++)
6101
2/2
✓ Branch 0 taken 707 times.
✓ Branch 1 taken 9959 times.
10666 if (c->trex_data[i].track_id == track_id) {
6102 707 trex = &c->trex_data[i];
6103 707 break;
6104 }
6105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 if (!trex) {
6106 ✗ av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
6107 ✗ return 0;
6108 }
6109 707 c->fragment.found_tfhd = 1;
6110 707 frag->track_id = track_id;
6111 707 set_frag_stream(&c->frag_index, track_id);
6112
6113 1414 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
6114
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 706 times.
1413 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
6115
2/2
✓ Branch 0 taken 633 times.
✓ Branch 1 taken 73 times.
706 frag->moof_offset : frag->implicit_offset;
6116
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 643 times.
707 frag->stsd_id = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id;
6117
6118 1414 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
6119
2/2
✓ Branch 0 taken 272 times.
✓ Branch 1 taken 435 times.
707 avio_rb32(pb) : trex->duration;
6120 1414 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
6121
2/2
✓ Branch 0 taken 264 times.
✓ Branch 1 taken 443 times.
707 avio_rb32(pb) : trex->size;
6122 1414 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
6123
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 369 times.
707 avio_rb32(pb) : trex->flags;
6124 707 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
6125
6126 707 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6127
1/2
✓ Branch 0 taken 707 times.
✗ Branch 1 not taken.
707 if (frag_stream_info) {
6128 707 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
6129 707 frag_stream_info->stsd_id = frag->stsd_id;
6130 }
6131 707 return 0;
6132 }
6133
6134 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6135 {
6136 unsigned i, num;
6137 void *new_tracks;
6138
6139 2 num = atom.size / 4;
6140
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
6141 ✗ return AVERROR(ENOMEM);
6142
6143 2 av_free(c->chapter_tracks);
6144 2 c->chapter_tracks = new_tracks;
6145 2 c->nb_chapter_tracks = num;
6146
6147
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++)
6148 2 c->chapter_tracks[i] = avio_rb32(pb);
6149
6150 2 c->nb_chapter_tracks = i;
6151
6152 2 return 0;
6153 }
6154
6155 134 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6156 {
6157 MOVTrackExt *trex;
6158 int err;
6159
6160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 134 times.
134 if ((uint64_t)c->trex_count+1 >= UINT_MAX / sizeof(*c->trex_data))
6161 ✗ return AVERROR_INVALIDDATA;
6162
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 134 times.
134 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
6163 sizeof(*c->trex_data))) < 0) {
6164 ✗ c->trex_count = 0;
6165 ✗ return err;
6166 }
6167
6168 134 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
6169
6170 134 trex = &c->trex_data[c->trex_count++];
6171 134 avio_r8(pb); /* version */
6172 134 avio_rb24(pb); /* flags */
6173 134 trex->track_id = avio_rb32(pb);
6174 134 trex->stsd_id = avio_rb32(pb);
6175 134 trex->duration = avio_rb32(pb);
6176 134 trex->size = avio_rb32(pb);
6177 134 trex->flags = avio_rb32(pb);
6178 134 return 0;
6179 }
6180
6181 634 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6182 {
6183 634 MOVFragment *frag = &c->fragment;
6184 634 AVStream *st = NULL;
6185 MOVStreamContext *sc;
6186 int version, i;
6187 MOVFragmentStreamInfo * frag_stream_info;
6188 int64_t base_media_decode_time;
6189
6190
1/2
✓ Branch 0 taken 10561 times.
✗ Branch 1 not taken.
10561 for (i = 0; i < c->fc->nb_streams; i++) {
6191 10561 sc = c->fc->streams[i]->priv_data;
6192
2/2
✓ Branch 0 taken 634 times.
✓ Branch 1 taken 9927 times.
10561 if (sc->id == frag->track_id) {
6193 634 st = c->fc->streams[i];
6194 634 break;
6195 }
6196 }
6197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 634 times.
634 if (!st) {
6198 ✗ av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
6199 ✗ return 0;
6200 }
6201 634 sc = st->priv_data;
6202
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 630 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
634 if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1)
6203 ✗ return 0;
6204 634 version = avio_r8(pb);
6205 634 avio_rb24(pb); /* flags */
6206
2/2
✓ Branch 0 taken 261 times.
✓ Branch 1 taken 373 times.
634 if (version) {
6207 261 base_media_decode_time = avio_rb64(pb);
6208 } else {
6209 373 base_media_decode_time = avio_rb32(pb);
6210 }
6211
6212 634 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6213
1/2
✓ Branch 0 taken 634 times.
✗ Branch 1 not taken.
634 if (frag_stream_info)
6214 634 frag_stream_info->tfdt_dts = base_media_decode_time;
6215 634 sc->track_end = base_media_decode_time;
6216
6217 634 return 0;
6218 }
6219
6220 707 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6221 {
6222 707 MOVFragment *frag = &c->fragment;
6223 707 AVStream *st = NULL;
6224 707 FFStream *sti = NULL;
6225 MOVStreamContext *sc;
6226 MOVTimeToSample *tts_data;
6227 uint64_t offset;
6228 707 int64_t dts, pts = AV_NOPTS_VALUE;
6229 707 int data_offset = 0;
6230 707 unsigned entries, first_sample_flags = frag->flags;
6231 int flags, distance, i;
6232 707 int64_t prev_dts = AV_NOPTS_VALUE;
6233 707 int next_frag_index = -1, index_entry_pos;
6234 size_t requested_size;
6235 AVIndexEntry *new_entries;
6236 MOVFragmentStreamInfo * frag_stream_info;
6237
6238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 if (!frag->found_tfhd) {
6239 ✗ av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
6240 ✗ return AVERROR_INVALIDDATA;
6241 }
6242
6243
1/2
✓ Branch 0 taken 10666 times.
✗ Branch 1 not taken.
10666 for (i = 0; i < c->fc->nb_streams; i++) {
6244 10666 sc = c->fc->streams[i]->priv_data;
6245
2/2
✓ Branch 0 taken 707 times.
✓ Branch 1 taken 9959 times.
10666 if (sc->id == frag->track_id) {
6246 707 st = c->fc->streams[i];
6247 707 sti = ffstream(st);
6248 707 break;
6249 }
6250 }
6251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 if (!st) {
6252 ✗ av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
6253 ✗ return 0;
6254 }
6255 707 sc = st->priv_data;
6256
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 703 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
707 if (sc->pseudo_stream_id+1 != frag->stsd_id && sc->pseudo_stream_id != -1)
6257 ✗ return 0;
6258
6259 // Find the next frag_index index that has a valid index_entry for
6260 // the current track_id.
6261 //
6262 // A valid index_entry means the trun for the fragment was read
6263 // and it's samples are in index_entries at the given position.
6264 // New index entries will be inserted before the index_entry found.
6265 707 index_entry_pos = sti->nb_index_entries;
6266
2/2
✓ Branch 0 taken 1634 times.
✓ Branch 1 taken 707 times.
2341 for (i = c->frag_index.current + 1; i < c->frag_index.nb_items; i++) {
6267 1634 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
6268
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) {
6269 ✗ next_frag_index = i;
6270 ✗ index_entry_pos = frag_stream_info->index_entry;
6271 ✗ break;
6272 }
6273 }
6274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 av_assert0(index_entry_pos <= sti->nb_index_entries);
6275
6276 707 avio_r8(pb); /* version */
6277 707 flags = avio_rb24(pb);
6278 707 entries = avio_rb32(pb);
6279 707 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
6280
6281 /* Explicit zero sizes are bounded by the trun payload. Reject a zero
6282 * default size before allocating or updating the sample index. */
6283
4/6
✓ Branch 0 taken 707 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 443 times.
✓ Branch 3 taken 264 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 443 times.
707 if (entries && !frag->size && !(flags & MOV_TRUN_SAMPLE_SIZE))
6284 ✗ return AVERROR_INVALIDDATA;
6285
6286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 if ((uint64_t)entries+sc->tts_count >= UINT_MAX/sizeof(*sc->tts_data))
6287 ✗ return AVERROR_INVALIDDATA;
6288
1/2
✓ Branch 0 taken 707 times.
✗ Branch 1 not taken.
707 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
6289
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 628 times.
707 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb);
6290
6291 707 int entry_size = !!(flags & MOV_TRUN_SAMPLE_DURATION) * 4
6292 707 + !!(flags & MOV_TRUN_SAMPLE_SIZE) * 4
6293 707 + !!(flags & MOV_TRUN_SAMPLE_FLAGS) * 4
6294 707 + !!(flags & MOV_TRUN_SAMPLE_CTS) * 4;
6295 707 int64_t sample_data_size = avio_size(sc->pb);
6296 707 int64_t max_entries = INT64_MAX;
6297
6298
2/2
✓ Branch 0 taken 506 times.
✓ Branch 1 taken 201 times.
707 if (sample_data_size > 0)
6299 506 max_entries = sample_data_size - sti->nb_index_entries;
6300
2/2
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 227 times.
707 if (entry_size) {
6301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 480 times.
480 int64_t size = sc->pb == pb ? sample_data_size : avio_size(pb);
6302 480 int64_t pos = avio_tell(pb);
6303 480 int64_t left = atom.size - 8 - !!(flags & MOV_TRUN_DATA_OFFSET) * 4
6304 480 - !!(flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) * 4;
6305
6306
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)
6307 479 left = FFMIN(left, size - pos);
6308 480 max_entries = FFMIN(max_entries, left / entry_size);
6309 }
6310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 if (entries > max_entries) {
6311 ✗ av_log(c->fc, AV_LOG_ERROR, "trun sample count %u exceeds the %"PRId64" "
6312 "samples the input can hold\n", entries, max_entries);
6313 ✗ return AVERROR_INVALIDDATA;
6314 }
6315
6316 707 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6317
1/2
✓ Branch 0 taken 707 times.
✗ Branch 1 not taken.
707 if (frag_stream_info) {
6318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
6319 ✗ dts = av_sat_sub64(frag_stream_info->next_trun_dts, sc->time_offset);
6320
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 704 times.
707 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
6321
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
6322 3 pts = frag_stream_info->first_tfra_pts;
6323 3 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
6324 ", using it for pts\n", pts);
6325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 704 times.
704 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
6326 ✗ c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
6327 ✗ dts = frag_stream_info->first_tfra_pts;
6328 ✗ av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
6329 ", using it for dts\n", pts);
6330 } else {
6331 704 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
6332 704 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
6333
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 704 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
704 int fallback_tfdt = !c->use_tfdt && !has_sidx && has_tfdt;
6334
4/6
✓ Branch 0 taken 704 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 631 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
704 int fallback_sidx = c->use_tfdt && !has_tfdt && has_sidx;
6335
6336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 704 times.
704 if (fallback_sidx) {
6337 ✗ av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
6338 }
6339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 704 times.
704 if (fallback_tfdt) {
6340 ✗ av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
6341 }
6342
6343
4/6
✓ Branch 0 taken 631 times.
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 631 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
704 if (has_tfdt && c->use_tfdt || fallback_tfdt) {
6344 631 dts = av_sat_sub64(frag_stream_info->tfdt_dts, sc->time_offset);
6345 631 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
6346 ", using it for dts\n", dts);
6347
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) {
6348 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
6349 // pts = frag_stream_info->sidx_pts;
6350 ✗ dts = frag_stream_info->sidx_pts;
6351 ✗ av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
6352 ", using it for dts\n", frag_stream_info->sidx_pts);
6353 } else {
6354 73 dts = av_sat_sub64(sc->track_end, sc->time_offset);
6355 73 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
6356 ", using it for dts\n", dts);
6357 }
6358 }
6359 } else {
6360 ✗ dts = av_sat_sub64(sc->track_end, sc->time_offset);
6361 ✗ av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
6362 ", using it for dts\n", dts);
6363 }
6364 707 offset = frag->base_data_offset + data_offset;
6365 707 distance = 0;
6366 707 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
6367
6368 // realloc space for new index entries
6369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
6370 ✗ entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
6371 ✗ av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
6372 }
6373
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 if (entries == 0)
6374 ✗ return 0;
6375
6376 707 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
6377 707 new_entries = av_fast_realloc(sti->index_entries,
6378 &sti->index_entries_allocated_size,
6379 requested_size);
6380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 if (!new_entries)
6381 ✗ return AVERROR(ENOMEM);
6382 707 sti->index_entries= new_entries;
6383
6384 707 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
6385 707 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
6386 requested_size);
6387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 if (!tts_data)
6388 ✗ return AVERROR(ENOMEM);
6389 707 sc->tts_data = tts_data;
6390
6391 // In case there were samples without time to sample entries, ensure they get
6392 // zero valued entries. This ensures clips which mix boxes with and
6393 // without time to sample entries don't pickup uninitialized data.
6394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 if (sc->tts_count < sti->nb_index_entries)
6395 ✗ memset(sc->tts_data + sc->tts_count, 0,
6396 ✗ sizeof(*sc->tts_data) * (sti->nb_index_entries - sc->tts_count));
6397
6398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 if (index_entry_pos < sti->nb_index_entries) {
6399 // Make hole in index_entries and tts_data for new samples
6400 ✗ memmove(sti->index_entries + index_entry_pos + entries,
6401 ✗ sti->index_entries + index_entry_pos,
6402 sizeof(*sti->index_entries) *
6403 ✗ (sti->nb_index_entries - index_entry_pos));
6404 ✗ memmove(sc->tts_data + index_entry_pos + entries,
6405 ✗ sc->tts_data + index_entry_pos,
6406 ✗ sizeof(*sc->tts_data) * (sti->nb_index_entries - index_entry_pos));
6407 ✗ if (index_entry_pos < sc->current_sample) {
6408 ✗ sc->current_sample += entries;
6409 }
6410 }
6411
6412 707 sti->nb_index_entries += entries;
6413 707 sc->tts_count = sti->nb_index_entries;
6414 707 sc->stts_count = sti->nb_index_entries;
6415
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 321 times.
707 if (flags & MOV_TRUN_SAMPLE_CTS)
6416 386 sc->ctts_count = sti->nb_index_entries;
6417
6418 // Record the index_entry position in frag_index of this fragment
6419
1/2
✓ Branch 0 taken 707 times.
✗ Branch 1 not taken.
707 if (frag_stream_info) {
6420 707 frag_stream_info->index_entry = index_entry_pos;
6421
1/2
✓ Branch 0 taken 707 times.
✗ Branch 1 not taken.
707 if (frag_stream_info->index_base < 0)
6422 707 frag_stream_info->index_base = index_entry_pos;
6423 }
6424
6425
2/2
✓ Branch 0 taken 574 times.
✓ Branch 1 taken 133 times.
707 if (index_entry_pos > 0)
6426 574 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6427
6428
3/4
✓ Branch 0 taken 12392 times.
✓ Branch 1 taken 707 times.
✓ Branch 2 taken 12392 times.
✗ Branch 3 not taken.
13099 for (i = 0; i < entries && !pb->eof_reached; i++) {
6429 12392 unsigned sample_size = frag->size;
6430
2/2
✓ Branch 0 taken 11685 times.
✓ Branch 1 taken 707 times.
12392 int sample_flags = i ? frag->flags : first_sample_flags;
6431 12392 unsigned sample_duration = frag->duration;
6432 12392 unsigned ctts_duration = 0;
6433 12392 int keyframe = 0;
6434 12392 int index_entry_flags = 0;
6435
6436
2/2
✓ Branch 0 taken 1694 times.
✓ Branch 1 taken 10698 times.
12392 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
6437
2/2
✓ Branch 0 taken 9533 times.
✓ Branch 1 taken 2859 times.
12392 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
6438
2/2
✓ Branch 0 taken 1845 times.
✓ Branch 1 taken 10547 times.
12392 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
6439
2/2
✓ Branch 0 taken 6576 times.
✓ Branch 1 taken 5816 times.
12392 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
6440
6441
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12391 times.
12392 if (sample_duration > c->max_stts_delta) {
6442 1 av_log(c->fc, AV_LOG_WARNING,
6443 "Too large sample duration %u in trun entry %u in st:%d. Clipping to 1.\n",
6444 sample_duration, i, st->index);
6445 1 sample_duration = 1;
6446 }
6447
6448 12392 mov_update_dts_shift(sc, ctts_duration, c->fc);
6449
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 12389 times.
12392 if (pts != AV_NOPTS_VALUE) {
6450 3 dts = av_sat_sub64(pts, sc->dts_shift);
6451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (flags & MOV_TRUN_SAMPLE_CTS) {
6452 ✗ dts = av_sat_sub64(dts, ctts_duration);
6453 } else {
6454 3 dts = av_sat_sub64(dts, sc->time_offset);
6455 }
6456 3 av_log(c->fc, AV_LOG_DEBUG,
6457 "pts %"PRId64" calculated dts %"PRId64
6458 " sc->dts_shift %d ctts.duration %d"
6459 " sc->time_offset %"PRId64
6460 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
6461 pts, dts,
6462 sc->dts_shift, ctts_duration,
6463 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
6464 3 pts = AV_NOPTS_VALUE;
6465 }
6466
6467 12392 keyframe =
6468 12392 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
6469 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
6470
2/2
✓ Branch 0 taken 3469 times.
✓ Branch 1 taken 8923 times.
12392 if (keyframe) {
6471 3469 distance = 0;
6472 3469 index_entry_flags |= AVINDEX_KEYFRAME;
6473 }
6474 // Fragments can overlap in time. Discard overlapping frames after
6475 // decoding.
6476
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12368 times.
12392 if (prev_dts >= dts)
6477 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
6478
6479 12392 sti->index_entries[index_entry_pos].pos = offset;
6480 12392 sti->index_entries[index_entry_pos].timestamp = dts;
6481 12392 sti->index_entries[index_entry_pos].size = sample_size;
6482 12392 sti->index_entries[index_entry_pos].min_distance = distance;
6483 12392 sti->index_entries[index_entry_pos].flags = index_entry_flags;
6484
6485 12392 sc->tts_data[index_entry_pos].count = 1;
6486 12392 sc->tts_data[index_entry_pos].offset = ctts_duration;
6487 12392 sc->tts_data[index_entry_pos].duration = sample_duration;
6488 12392 index_entry_pos++;
6489
6490 12392 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
6491 "size %u, distance %d, keyframe %d\n", st->index,
6492 index_entry_pos, offset, dts, sample_size, distance, keyframe);
6493 12392 distance++;
6494
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12392 times.
12392 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
6495 ✗ return AVERROR_INVALIDDATA;
6496 12392 dts += sample_duration;
6497 12392 offset += sample_size;
6498 12392 sc->data_size += sample_size;
6499
6500
1/2
✓ Branch 0 taken 12392 times.
✗ Branch 1 not taken.
12392 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
6501
1/2
✓ Branch 0 taken 12392 times.
✗ Branch 1 not taken.
12392 1 <= INT_MAX - sc->nb_frames_for_fps
6502 ) {
6503 12392 sc->duration_for_fps += sample_duration;
6504 12392 sc->nb_frames_for_fps ++;
6505 }
6506 }
6507
1/2
✓ Branch 0 taken 707 times.
✗ Branch 1 not taken.
707 if (frag_stream_info)
6508 707 frag_stream_info->next_trun_dts = av_sat_add64(dts, sc->time_offset);
6509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 if (i < entries) {
6510 // EOF found before reading all entries. Fix the hole this would
6511 // leave in index_entries and tts_data
6512 ✗ int gap = entries - i;
6513 ✗ memmove(sti->index_entries + index_entry_pos,
6514 ✗ sti->index_entries + index_entry_pos + gap,
6515 sizeof(*sti->index_entries) *
6516 ✗ (sti->nb_index_entries - (index_entry_pos + gap)));
6517 ✗ memmove(sc->tts_data + index_entry_pos,
6518 ✗ sc->tts_data + index_entry_pos + gap,
6519 sizeof(*sc->tts_data) *
6520 ✗ (sc->tts_count - (index_entry_pos + gap)));
6521
6522 ✗ sti->nb_index_entries -= gap;
6523 ✗ sc->tts_count -= gap;
6524 ✗ if (index_entry_pos < sc->current_sample) {
6525 ✗ sc->current_sample -= gap;
6526 }
6527 ✗ entries = i;
6528 }
6529
6530 // The end of this new fragment may overlap in time with the start
6531 // of the next fragment in index_entries. Mark the samples in the next
6532 // fragment that overlap with AVINDEX_DISCARD_FRAME
6533 707 prev_dts = AV_NOPTS_VALUE;
6534
1/2
✓ Branch 0 taken 707 times.
✗ Branch 1 not taken.
707 if (index_entry_pos > 0)
6535 707 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
6537 ✗ if (prev_dts < sti->index_entries[i].timestamp)
6538 ✗ break;
6539 ✗ sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6540 }
6541
6542 // If a hole was created to insert the new index_entries into,
6543 // the index_entry recorded for all subsequent moof must
6544 // be incremented by the number of entries inserted.
6545 707 fix_frag_index_entries(&c->frag_index, next_frag_index,
6546 707 frag->track_id, entries);
6547
6548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
707 if (pb->eof_reached) {
6549 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6550 ✗ return AVERROR_EOF;
6551 }
6552
6553 707 frag->implicit_offset = offset;
6554
6555 707 sc->track_end = av_sat_add64(dts, sc->time_offset);
6556
2/2
✓ Branch 0 taken 121 times.
✓ Branch 1 taken 586 times.
707 if (st->duration < sc->track_end)
6557 121 st->duration = sc->track_end;
6558
6559 707 return 0;
6560 }
6561
6562 249 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6563 {
6564 249 int64_t stream_size = avio_size(pb);
6565 249 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6566 uint8_t version, is_complete;
6567 int64_t offadd;
6568 unsigned i, j, track_id, item_count;
6569 249 AVStream *st = NULL;
6570 249 AVStream *ref_st = NULL;
6571 249 MOVStreamContext *sc, *ref_sc = NULL;
6572 AVRational timescale;
6573
6574 249 version = avio_r8(pb);
6575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if (version > 1) {
6576 ✗ avpriv_request_sample(c->fc, "sidx version %u", version);
6577 ✗ return 0;
6578 }
6579
6580 249 avio_rb24(pb); // flags
6581
6582 249 track_id = avio_rb32(pb); // Reference ID
6583
1/2
✓ Branch 0 taken 10149 times.
✗ Branch 1 not taken.
10149 for (i = 0; i < c->fc->nb_streams; i++) {
6584 10149 sc = c->fc->streams[i]->priv_data;
6585
2/2
✓ Branch 0 taken 249 times.
✓ Branch 1 taken 9900 times.
10149 if (sc->id == track_id) {
6586 249 st = c->fc->streams[i];
6587 249 break;
6588 }
6589 }
6590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if (!st) {
6591 ✗ av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6592 ✗ return 0;
6593 }
6594
6595 249 sc = st->priv_data;
6596
6597 249 timescale = av_make_q(1, avio_rb32(pb));
6598
6599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if (timescale.den <= 0) {
6600 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6601 ✗ return AVERROR_INVALIDDATA;
6602 }
6603
6604
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 201 times.
249 if (version == 0) {
6605 48 pts = avio_rb32(pb);
6606 48 offadd= avio_rb32(pb);
6607 } else {
6608 201 pts = avio_rb64(pb);
6609 201 offadd= avio_rb64(pb);
6610 }
6611
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 249 times.
249 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6612 ✗ return AVERROR_INVALIDDATA;
6613
6614 249 offset += (uint64_t)offadd;
6615
6616 249 avio_rb16(pb); // reserved
6617
6618 249 item_count = avio_rb16(pb);
6619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if (item_count == 0)
6620 ✗ return AVERROR_INVALIDDATA;
6621
6622
2/2
✓ Branch 0 taken 575 times.
✓ Branch 1 taken 249 times.
824 for (i = 0; i < item_count; i++) {
6623 int index;
6624 MOVFragmentStreamInfo * frag_stream_info;
6625 575 uint32_t size = avio_rb32(pb);
6626 575 uint32_t duration = avio_rb32(pb);
6627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 if (size & 0x80000000) {
6628 ✗ avpriv_request_sample(c->fc, "sidx reference_type 1");
6629 ✗ return AVERROR_PATCHWELCOME;
6630 }
6631 575 avio_rb32(pb); // sap_flags
6632 575 timestamp = av_rescale_q(pts, timescale, st->time_base);
6633
6634 575 index = update_frag_index(c, offset);
6635 575 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6636
1/2
✓ Branch 0 taken 575 times.
✗ Branch 1 not taken.
575 if (frag_stream_info)
6637 575 frag_stream_info->sidx_pts = timestamp;
6638
6639
1/2
✓ Branch 1 taken 575 times.
✗ Branch 2 not taken.
575 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6640
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 575 times.
575 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6641 )
6642 ✗ return AVERROR_INVALIDDATA;
6643 575 offset += size;
6644 575 pts += duration;
6645 }
6646
6647 249 st->duration = sc->track_end = pts;
6648
6649 249 sc->has_sidx = 1;
6650
6651 // See if the remaining bytes are just an mfra which we can ignore.
6652 249 is_complete = offset == stream_size;
6653
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 ) {
6654 int64_t ret;
6655 41 int64_t original_pos = avio_tell(pb);
6656
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 35 times.
41 if (!c->have_read_mfra_size) {
6657
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6658 ✗ return ret;
6659 6 c->mfra_size = avio_rb32(pb);
6660 6 c->have_read_mfra_size = 1;
6661
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6662 ✗ return ret;
6663 }
6664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (offset == stream_size - c->mfra_size)
6665 ✗ is_complete = 1;
6666 }
6667
6668
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 242 times.
249 if (is_complete) {
6669 // Find first entry in fragment index that came from an sidx.
6670 // This will pretty much always be the first entry.
6671
2/2
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 7 times.
378 for (i = 0; i < c->frag_index.nb_items; i++) {
6672 371 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6673
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++) {
6674 MOVFragmentStreamInfo * si;
6675 7 si = &item->stream_info[j];
6676
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (si->sidx_pts != AV_NOPTS_VALUE) {
6677 7 ref_st = c->fc->streams[j];
6678 7 ref_sc = ref_st->priv_data;
6679 7 break;
6680 }
6681 }
6682 }
6683
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++) {
6684 7 st = c->fc->streams[i];
6685 7 sc = st->priv_data;
6686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sc->has_sidx) {
6687 ✗ st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6688 }
6689 }
6690
6691
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (offadd == 0)
6692 7 c->frag_index.complete = 1;
6693 }
6694
6695 249 return 0;
6696 }
6697
6698 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6699 /* like the files created with Adobe Premiere 5.0, for samples see */
6700 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6701 310 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6702 {
6703 int err;
6704
6705
1/2
✓ Branch 0 taken 310 times.
✗ Branch 1 not taken.
310 if (atom.size < 8)
6706 310 return 0; /* continue */
6707 ✗ if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6708 ✗ avio_skip(pb, atom.size - 4);
6709 ✗ return 0;
6710 }
6711 ✗ atom.type = avio_rl32(pb);
6712 ✗ atom.size -= 8;
6713 ✗ if (atom.type != MKTAG('m','d','a','t')) {
6714 ✗ avio_skip(pb, atom.size);
6715 ✗ return 0;
6716 }
6717 ✗ err = mov_read_mdat(c, pb, atom);
6718 ✗ return err;
6719 }
6720
6721 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6722 {
6723 #if CONFIG_ZLIB
6724 FFIOContext ctx;
6725 uint8_t *cmov_data;
6726 uint8_t *moov_data; /* uncompressed data */
6727 long cmov_len, moov_len;
6728 3 int ret = -1;
6729
6730 3 avio_rb32(pb); /* dcom atom */
6731
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6732 ✗ return AVERROR_INVALIDDATA;
6733
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6734 ✗ av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6735 ✗ return AVERROR_INVALIDDATA;
6736 }
6737 3 avio_rb32(pb); /* cmvd atom */
6738
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6739 ✗ return AVERROR_INVALIDDATA;
6740 3 moov_len = avio_rb32(pb); /* uncompressed size */
6741 3 cmov_len = atom.size - 6 * 4;
6742
6743 3 cmov_data = av_malloc(cmov_len);
6744
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6745 ✗ return AVERROR(ENOMEM);
6746 3 moov_data = av_malloc(moov_len);
6747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6748 ✗ av_free(cmov_data);
6749 ✗ return AVERROR(ENOMEM);
6750 }
6751 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6753 ✗ goto free_and_return;
6754
6755 3 ret = AVERROR_INVALIDDATA;
6756
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)
6757 ✗ goto free_and_return;
6758 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6759 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6760 3 atom.type = MKTAG('m','o','o','v');
6761 3 atom.size = moov_len;
6762 3 ret = mov_read_default(c, &ctx.pub, atom);
6763 3 free_and_return:
6764 3 av_free(moov_data);
6765 3 av_free(cmov_data);
6766 3 return ret;
6767 #else
6768 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6769 return AVERROR(ENOSYS);
6770 #endif
6771 }
6772
6773 /* edit list atom */
6774 668 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6775 {
6776 MOVStreamContext *sc;
6777 int i, edit_count, version;
6778 int64_t elst_entry_size;
6779
6780
2/4
✓ Branch 0 taken 668 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 668 times.
668 if (c->fc->nb_streams < 1 || c->ignore_editlist)
6781 ✗ return 0;
6782 668 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6783
6784 668 version = avio_r8(pb); /* version */
6785 668 avio_rb24(pb); /* flags */
6786 668 edit_count = avio_rb32(pb); /* entries */
6787 668 atom.size -= 8;
6788
6789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 668 times.
668 elst_entry_size = version == 1 ? 20 : 12;
6790
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 667 times.
668 if (atom.size != edit_count * elst_entry_size) {
6791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6792 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6793 ✗ edit_count, atom.size + 8);
6794 ✗ return AVERROR_INVALIDDATA;
6795 } else {
6796 1 edit_count = atom.size / elst_entry_size;
6797
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6798 ✗ av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6799 }
6800 }
6801 }
6802
6803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 668 times.
668 if (!edit_count)
6804 ✗ return 0;
6805
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 668 times.
668 if (sc->elst_data)
6806 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6807 668 av_free(sc->elst_data);
6808 668 sc->elst_count = 0;
6809 668 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 668 times.
668 if (!sc->elst_data)
6811 ✗ return AVERROR(ENOMEM);
6812
6813 668 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6814
4/6
✓ Branch 0 taken 698 times.
✓ Branch 1 taken 668 times.
✓ Branch 2 taken 698 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 698 times.
✗ Branch 5 not taken.
1366 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
6815 698 MOVElst *e = &sc->elst_data[i];
6816
6817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 698 times.
698 if (version == 1) {
6818 ✗ e->duration = avio_rb64(pb);
6819 ✗ e->time = avio_rb64(pb);
6820 ✗ atom.size -= 16;
6821 } else {
6822 698 e->duration = avio_rb32(pb); /* segment duration */
6823 698 e->time = (int32_t)avio_rb32(pb); /* media time */
6824 698 atom.size -= 8;
6825 }
6826 698 e->rate = avio_rb32(pb) / 65536.0;
6827 698 atom.size -= 4;
6828 698 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6829 698 e->duration, e->time, e->rate);
6830
6831
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 693 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
698 if (e->time < 0 && e->time != -1 &&
6832 ✗ c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6833 ✗ av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6834 ✗ c->fc->nb_streams-1, i, e->time);
6835 ✗ return AVERROR_INVALIDDATA;
6836 }
6837
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 698 times.
698 if (e->duration < 0) {
6838 ✗ av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list duration=%"PRId64"\n",
6839 ✗ c->fc->nb_streams-1, i, e->duration);
6840 ✗ return AVERROR_INVALIDDATA;
6841 }
6842 }
6843 668 sc->elst_count = i;
6844
6845 668 return 0;
6846 }
6847
6848 21 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6849 {
6850 MOVStreamContext *sc;
6851 int err;
6852
6853
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (c->fc->nb_streams < 1)
6854 ✗ return AVERROR_INVALIDDATA;
6855 21 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6856
6857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (atom.size % sizeof(uint32_t))
6858 ✗ return AVERROR_INVALIDDATA;
6859
6860 21 MovTref *tag = mov_add_tref_tag(sc, atom.type);
6861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!tag)
6862 ✗ return AVERROR(ENOMEM);
6863
6864 21 int nb_timecode_track = atom.size >> 2;
6865
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 21 times.
52 for (int i = 0; i < nb_timecode_track; i++) {
6866
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 if (avio_feof(pb))
6867 ✗ return AVERROR_INVALIDDATA;
6868 31 err = mov_add_tref_id(tag, avio_rb32(pb));
6869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (err < 0)
6870 ✗ return err;
6871 }
6872
6873 21 return 0;
6874 }
6875
6876 ✗ static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6877 {
6878 AVStream *st;
6879 int version, color_range, color_primaries, color_trc, color_space;
6880
6881 ✗ if (c->fc->nb_streams < 1)
6882 ✗ return 0;
6883 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
6884
6885 ✗ if (atom.size < 5) {
6886 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6887 ✗ return AVERROR_INVALIDDATA;
6888 }
6889
6890 ✗ version = avio_r8(pb);
6891 ✗ if (version != 1) {
6892 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6893 ✗ return 0;
6894 }
6895 ✗ avio_skip(pb, 3); /* flags */
6896
6897 ✗ avio_skip(pb, 2); /* profile + level */
6898 ✗ color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6899 ✗ color_primaries = avio_r8(pb);
6900 ✗ color_trc = avio_r8(pb);
6901 ✗ color_space = avio_r8(pb);
6902 ✗ if (avio_rb16(pb)) /* codecIntializationDataSize */
6903 ✗ return AVERROR_INVALIDDATA;
6904
6905 ✗ if (!av_color_primaries_name(color_primaries))
6906 ✗ color_primaries = AVCOL_PRI_UNSPECIFIED;
6907 ✗ if (!av_color_transfer_name(color_trc))
6908 ✗ color_trc = AVCOL_TRC_UNSPECIFIED;
6909 ✗ if (!av_color_space_name(color_space))
6910 ✗ color_space = AVCOL_SPC_UNSPECIFIED;
6911
6912 ✗ st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6913 ✗ st->codecpar->color_primaries = color_primaries;
6914 ✗ st->codecpar->color_trc = color_trc;
6915 ✗ st->codecpar->color_space = color_space;
6916
6917 ✗ return 0;
6918 }
6919
6920 ✗ static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6921 {
6922 MOVStreamContext *sc;
6923 int i, version;
6924
6925 ✗ if (c->fc->nb_streams < 1)
6926 ✗ return AVERROR_INVALIDDATA;
6927
6928 ✗ sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6929
6930 ✗ if (atom.size < 5) {
6931 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6932 ✗ return AVERROR_INVALIDDATA;
6933 }
6934
6935 ✗ version = avio_r8(pb);
6936 ✗ if (version) {
6937 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6938 ✗ return 0;
6939 }
6940 ✗ if (sc->mastering) {
6941 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6942 ✗ return 0;
6943 }
6944
6945 ✗ avio_skip(pb, 3); /* flags */
6946
6947 ✗ sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6948 ✗ if (!sc->mastering)
6949 ✗ return AVERROR(ENOMEM);
6950
6951 ✗ for (i = 0; i < 3; i++) {
6952 ✗ sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6953 ✗ sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6954 }
6955 ✗ sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6956 ✗ sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6957
6958 ✗ sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6959 ✗ sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6960
6961 ✗ sc->mastering->has_primaries = 1;
6962 ✗ sc->mastering->has_luminance = 1;
6963
6964 ✗ return 0;
6965 }
6966
6967 ✗ static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6968 {
6969 MOVStreamContext *sc;
6970 ✗ const int mapping[3] = {1, 2, 0};
6971 ✗ const int chroma_den = 50000;
6972 ✗ const int luma_den = 10000;
6973 int i;
6974
6975 ✗ if (c->fc->nb_streams < 1)
6976 ✗ return AVERROR_INVALIDDATA;
6977
6978 ✗ sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6979
6980 ✗ if (atom.size < 24) {
6981 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6982 ✗ return AVERROR_INVALIDDATA;
6983 }
6984
6985 ✗ if (sc->mastering) {
6986 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6987 ✗ return 0;
6988 }
6989
6990 ✗ sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6991 ✗ if (!sc->mastering)
6992 ✗ return AVERROR(ENOMEM);
6993
6994 ✗ for (i = 0; i < 3; i++) {
6995 ✗ const int j = mapping[i];
6996 ✗ sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6997 ✗ sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6998 }
6999 ✗ sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
7000 ✗ sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
7001
7002 ✗ sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
7003 ✗ sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
7004
7005 ✗ sc->mastering->has_luminance = 1;
7006 ✗ sc->mastering->has_primaries = 1;
7007
7008 ✗ return 0;
7009 }
7010
7011 ✗ static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7012 {
7013 MOVStreamContext *sc;
7014 int version;
7015
7016 ✗ if (c->fc->nb_streams < 1)
7017 ✗ return AVERROR_INVALIDDATA;
7018
7019 ✗ sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7020
7021 ✗ if (atom.size < 5) {
7022 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
7023 ✗ return AVERROR_INVALIDDATA;
7024 }
7025
7026 ✗ version = avio_r8(pb);
7027 ✗ if (version) {
7028 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
7029 ✗ return 0;
7030 }
7031 ✗ avio_skip(pb, 3); /* flags */
7032
7033 ✗ if (sc->coll){
7034 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
7035 ✗ return 0;
7036 }
7037
7038 ✗ sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
7039 ✗ if (!sc->coll)
7040 ✗ return AVERROR(ENOMEM);
7041
7042 ✗ sc->coll->MaxCLL = avio_rb16(pb);
7043 ✗ sc->coll->MaxFALL = avio_rb16(pb);
7044
7045 ✗ return 0;
7046 }
7047
7048 ✗ static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7049 {
7050 MOVStreamContext *sc;
7051
7052 ✗ if (c->fc->nb_streams < 1)
7053 ✗ return AVERROR_INVALIDDATA;
7054
7055 ✗ sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7056
7057 ✗ if (atom.size < 4) {
7058 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
7059 ✗ return AVERROR_INVALIDDATA;
7060 }
7061
7062 ✗ if (sc->coll){
7063 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
7064 ✗ return 0;
7065 }
7066
7067 ✗ sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
7068 ✗ if (!sc->coll)
7069 ✗ return AVERROR(ENOMEM);
7070
7071 ✗ sc->coll->MaxCLL = avio_rb16(pb);
7072 ✗ sc->coll->MaxFALL = avio_rb16(pb);
7073
7074 ✗ return 0;
7075 }
7076
7077 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7078 {
7079 MOVStreamContext *sc;
7080 4 const int illuminance_den = 10000;
7081 4 const int ambient_den = 50000;
7082
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
7083 ✗ return AVERROR_INVALIDDATA;
7084 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
7086 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
7087 ✗ return AVERROR_INVALIDDATA;
7088 }
7089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
7090 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
7091 ✗ return 0;
7092 }
7093 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
7094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
7095 ✗ return AVERROR(ENOMEM);
7096 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
7097 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
7098 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
7099 4 return 0;
7100 }
7101
7102 3 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7103 {
7104 AVStream *st;
7105 MOVStreamContext *sc;
7106 enum AVStereo3DType type;
7107 int mode;
7108
7109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7110 ✗ return 0;
7111
7112 3 st = c->fc->streams[c->fc->nb_streams - 1];
7113 3 sc = st->priv_data;
7114
7115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 5) {
7116 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
7117 ✗ return AVERROR_INVALIDDATA;
7118 }
7119
7120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->stereo3d)
7121 ✗ return AVERROR_INVALIDDATA;
7122
7123 3 avio_skip(pb, 4); /* version + flags */
7124
7125 3 mode = avio_r8(pb);
7126
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
3 switch (mode) {
7127 1 case 0:
7128 1 type = AV_STEREO3D_2D;
7129 1 break;
7130 ✗ case 1:
7131 ✗ type = AV_STEREO3D_TOPBOTTOM;
7132 ✗ break;
7133 2 case 2:
7134 2 type = AV_STEREO3D_SIDEBYSIDE;
7135 2 break;
7136 ✗ default:
7137 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
7138 ✗ return 0;
7139 }
7140
7141 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7143 ✗ return AVERROR(ENOMEM);
7144
7145 3 sc->stereo3d->type = type;
7146 3 return 0;
7147 }
7148
7149 ✗ static int mov_read_pack(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7150 {
7151 AVStream *st;
7152 MOVStreamContext *sc;
7153 ✗ int size = 0;
7154 int64_t remaining;
7155 ✗ uint32_t tag = 0;
7156 ✗ enum AVStereo3DType type = AV_STEREO3D_2D;
7157
7158 ✗ if (c->fc->nb_streams < 1)
7159 ✗ return 0;
7160
7161 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
7162 ✗ sc = st->priv_data;
7163
7164 ✗ remaining = atom.size;
7165 ✗ while (remaining > 0) {
7166 ✗ size = avio_rb32(pb);
7167 ✗ if (size < 8 || size > remaining ) {
7168 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid child size in pack box\n");
7169 ✗ return AVERROR_INVALIDDATA;
7170 }
7171
7172 ✗ tag = avio_rl32(pb);
7173 ✗ switch (tag) {
7174 ✗ case MKTAG('p','k','i','n'): {
7175 ✗ if (size != 16) {
7176 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of pkin box: %d\n", size);
7177 ✗ return AVERROR_INVALIDDATA;
7178 }
7179 ✗ avio_skip(pb, 1); // version
7180 ✗ avio_skip(pb, 3); // flags
7181
7182 ✗ tag = avio_rl32(pb);
7183 ✗ switch (tag) {
7184 ✗ case MKTAG('s','i','d','e'):
7185 ✗ type = AV_STEREO3D_SIDEBYSIDE;
7186 ✗ break;
7187 ✗ case MKTAG('o','v','e','r'):
7188 ✗ type = AV_STEREO3D_TOPBOTTOM;
7189 ✗ break;
7190 ✗ case 0:
7191 // This means value will be set in another layer
7192 ✗ break;
7193 ✗ default:
7194 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pkin: %s\n",
7195 ✗ av_fourcc2str(tag));
7196 ✗ avio_skip(pb, size - 8);
7197 ✗ break;
7198 }
7199
7200 ✗ break;
7201 }
7202 ✗ default:
7203 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pack: %s\n",
7204 ✗ av_fourcc2str(tag));
7205 ✗ avio_skip(pb, size - 8);
7206 ✗ break;
7207 }
7208 ✗ remaining -= size;
7209 }
7210
7211 ✗ if (remaining != 0) {
7212 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken pack box\n");
7213 ✗ return AVERROR_INVALIDDATA;
7214 }
7215
7216 ✗ if (type == AV_STEREO3D_2D)
7217 ✗ return 0;
7218
7219 ✗ if (!sc->stereo3d) {
7220 ✗ sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7221 ✗ if (!sc->stereo3d)
7222 ✗ return AVERROR(ENOMEM);
7223 }
7224
7225 ✗ sc->stereo3d->type = type;
7226
7227 ✗ return 0;
7228 }
7229
7230 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7231 {
7232 AVStream *st;
7233 MOVStreamContext *sc;
7234 int size, version, layout;
7235 int32_t yaw, pitch, roll;
7236 1 uint32_t l = 0, t = 0, r = 0, b = 0;
7237 1 uint32_t tag, padding = 0;
7238 enum AVSphericalProjection projection;
7239
7240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
7241 ✗ return 0;
7242
7243 1 st = c->fc->streams[c->fc->nb_streams - 1];
7244 1 sc = st->priv_data;
7245
7246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
7247 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
7248 ✗ return AVERROR_INVALIDDATA;
7249 }
7250
7251 1 size = avio_rb32(pb);
7252
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)
7253 ✗ return AVERROR_INVALIDDATA;
7254
7255 1 tag = avio_rl32(pb);
7256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
7257 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
7258 ✗ return 0;
7259 }
7260 1 version = avio_r8(pb);
7261
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7262 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7263 version);
7264 ✗ return 0;
7265 }
7266 1 avio_skip(pb, 3); /* flags */
7267 1 avio_skip(pb, size - 12); /* metadata_source */
7268
7269 1 size = avio_rb32(pb);
7270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7271 ✗ return AVERROR_INVALIDDATA;
7272
7273 1 tag = avio_rl32(pb);
7274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
7275 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
7276 ✗ return 0;
7277 }
7278
7279 1 size = avio_rb32(pb);
7280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7281 ✗ return AVERROR_INVALIDDATA;
7282
7283 1 tag = avio_rl32(pb);
7284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
7285 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
7286 ✗ return 0;
7287 }
7288 1 version = avio_r8(pb);
7289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7290 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7291 version);
7292 ✗ return 0;
7293 }
7294 1 avio_skip(pb, 3); /* flags */
7295
7296 /* 16.16 fixed point */
7297 1 yaw = avio_rb32(pb);
7298 1 pitch = avio_rb32(pb);
7299 1 roll = avio_rb32(pb);
7300
7301 1 size = avio_rb32(pb);
7302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7303 ✗ return AVERROR_INVALIDDATA;
7304
7305 1 tag = avio_rl32(pb);
7306 1 version = avio_r8(pb);
7307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7308 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7309 version);
7310 ✗ return 0;
7311 }
7312 1 avio_skip(pb, 3); /* flags */
7313
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
7314 ✗ case MKTAG('c','b','m','p'):
7315 ✗ layout = avio_rb32(pb);
7316 ✗ if (layout) {
7317 ✗ av_log(c->fc, AV_LOG_WARNING,
7318 "Unsupported cubemap layout %d\n", layout);
7319 ✗ return 0;
7320 }
7321 ✗ projection = AV_SPHERICAL_CUBEMAP;
7322 ✗ padding = avio_rb32(pb);
7323 ✗ break;
7324 1 case MKTAG('e','q','u','i'):
7325 1 t = avio_rb32(pb);
7326 1 b = avio_rb32(pb);
7327 1 l = avio_rb32(pb);
7328 1 r = avio_rb32(pb);
7329
7330
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) {
7331 ✗ av_log(c->fc, AV_LOG_ERROR,
7332 "Invalid bounding rectangle coordinates "
7333 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
7334 ✗ return AVERROR_INVALIDDATA;
7335 }
7336
7337
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)
7338 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
7339 else
7340 ✗ projection = AV_SPHERICAL_EQUIRECTANGULAR;
7341 1 break;
7342 ✗ default:
7343 ✗ av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
7344 ✗ return 0;
7345 }
7346
7347 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
7349 ✗ return AVERROR(ENOMEM);
7350
7351 1 sc->spherical->projection = projection;
7352
7353 1 sc->spherical->yaw = yaw;
7354 1 sc->spherical->pitch = pitch;
7355 1 sc->spherical->roll = roll;
7356
7357 1 sc->spherical->padding = padding;
7358
7359 1 sc->spherical->bound_left = l;
7360 1 sc->spherical->bound_top = t;
7361 1 sc->spherical->bound_right = r;
7362 1 sc->spherical->bound_bottom = b;
7363
7364 1 return 0;
7365 }
7366
7367 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7368 {
7369 AVStream *st;
7370 MOVStreamContext *sc;
7371 int size;
7372 uint32_t tag;
7373 enum AVSphericalProjection projection;
7374
7375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7376 ✗ return 0;
7377
7378 3 st = c->fc->streams[c->fc->nb_streams - 1];
7379 3 sc = st->priv_data;
7380
7381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 16) {
7382 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
7383 ✗ return AVERROR_INVALIDDATA;
7384 }
7385
7386 3 size = avio_rb32(pb);
7387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size < 16) {
7388 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
7389 ✗ return AVERROR_INVALIDDATA;
7390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (size > 16) {
7391 ✗ av_log(c->fc, AV_LOG_WARNING, "Box has more bytes (%d) than prji box required (16) \n", size);
7392 }
7393
7394 3 tag = avio_rl32(pb);
7395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
7396 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: %s\n",
7397 ✗ av_fourcc2str(tag));
7398 ✗ return AVERROR_INVALIDDATA;
7399 }
7400
7401 // version and flags, only support (0, 0)
7402 3 unsigned n = avio_rl32(pb);
7403
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (n != 0) {
7404 ✗ av_log(c->fc, AV_LOG_ERROR, "prji version %u, flag %u are not supported\n",
7405 n & 0xFF, n >> 8);
7406 ✗ return AVERROR_PATCHWELCOME;
7407 }
7408
7409 3 tag = avio_rl32(pb);
7410
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) {
7411 3 case MKTAG('r','e','c','t'):
7412 3 projection = AV_SPHERICAL_RECTILINEAR;
7413 3 break;
7414 ✗ case MKTAG('e','q','u','i'):
7415 ✗ projection = AV_SPHERICAL_EQUIRECTANGULAR;
7416 ✗ break;
7417 ✗ case MKTAG('h','e','q','u'):
7418 ✗ projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
7419 ✗ break;
7420 ✗ case MKTAG('f','i','s','h'):
7421 ✗ projection = AV_SPHERICAL_FISHEYE;
7422 ✗ break;
7423 ✗ case MKTAG('p','r','i','m'):
7424 ✗ projection = AV_SPHERICAL_PARAMETRIC_IMMERSIVE;
7425 ✗ break;
7426 ✗ default:
7427 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: %s\n", av_fourcc2str(tag));
7428 ✗ return AVERROR_INVALIDDATA;
7429 }
7430
7431 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
7433 ✗ return AVERROR(ENOMEM);
7434
7435 3 sc->spherical->projection = projection;
7436
7437 3 return 0;
7438 }
7439
7440 5 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7441 {
7442 AVStream *st;
7443 MOVStreamContext *sc;
7444 5 int size, flags = 0;
7445 int64_t remaining;
7446 5 uint32_t tag, baseline = 0;
7447 5 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
7448 5 enum AVStereo3DType type = AV_STEREO3D_2D;
7449 5 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
7450 5 AVRational horizontal_disparity_adjustment = { 0, 1 };
7451
7452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
7453 ✗ return 0;
7454
7455 5 st = c->fc->streams[c->fc->nb_streams - 1];
7456 5 sc = st->priv_data;
7457
7458 5 remaining = atom.size;
7459
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 while (remaining > 0) {
7460 11 size = avio_rb32(pb);
7461
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 ) {
7462 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
7463 ✗ return AVERROR_INVALIDDATA;
7464 }
7465
7466 11 tag = avio_rl32(pb);
7467
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) {
7468 5 case MKTAG('s','t','r','i'): {
7469 int has_right, has_left;
7470 uint8_t tmp;
7471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (size != 13) {
7472 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
7473 ✗ return AVERROR_INVALIDDATA;
7474 }
7475 5 avio_skip(pb, 1); // version
7476 5 avio_skip(pb, 3); // flags
7477
7478 5 tmp = avio_r8(pb);
7479
7480 // eye_views_reversed
7481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (tmp & 8) {
7482 ✗ flags |= AV_STEREO3D_FLAG_INVERT;
7483 }
7484 // has_additional_views
7485 5 if (tmp & 4) {
7486 // skip...
7487 }
7488
7489 5 has_right = tmp & 2; // has_right_eye_view
7490 5 has_left = tmp & 1; // has_left_eye_view
7491
7492
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)
7493 5 view = AV_STEREO3D_VIEW_PACKED;
7494 ✗ else if (has_left)
7495 ✗ view = AV_STEREO3D_VIEW_LEFT;
7496 ✗ else if (has_right)
7497 ✗ view = AV_STEREO3D_VIEW_RIGHT;
7498
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)
7499 5 type = AV_STEREO3D_UNSPEC;
7500
7501 5 break;
7502 }
7503 ✗ case MKTAG('h','e','r','o'): {
7504 int tmp;
7505 ✗ if (size != 13) {
7506 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
7507 ✗ return AVERROR_INVALIDDATA;
7508 }
7509 ✗ avio_skip(pb, 1); // version
7510 ✗ avio_skip(pb, 3); // flags
7511
7512 ✗ tmp = avio_r8(pb);
7513 ✗ if (tmp == 0)
7514 ✗ primary_eye = AV_PRIMARY_EYE_NONE;
7515 ✗ else if (tmp == 1)
7516 ✗ primary_eye = AV_PRIMARY_EYE_LEFT;
7517 ✗ else if (tmp == 2)
7518 ✗ primary_eye = AV_PRIMARY_EYE_RIGHT;
7519 else
7520 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
7521
7522 ✗ break;
7523 }
7524 3 case MKTAG('c','a','m','s'): {
7525 uint32_t subtag;
7526 int subsize;
7527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7528 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
7529 ✗ return AVERROR_INVALIDDATA;
7530 }
7531
7532 3 subsize = avio_rb32(pb);
7533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7534 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
7535 ✗ return AVERROR_INVALIDDATA;
7536 }
7537
7538 3 subtag = avio_rl32(pb);
7539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
7540 ✗ av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got %s\n",
7541 ✗ av_fourcc2str(subtag));
7542 ✗ return AVERROR_INVALIDDATA;
7543 }
7544
7545 3 avio_skip(pb, 1); // version
7546 3 avio_skip(pb, 3); // flags
7547
7548 3 baseline = avio_rb32(pb);
7549
7550 3 break;
7551 }
7552 3 case MKTAG('c','m','f','y'): {
7553 uint32_t subtag;
7554 int subsize;
7555 int32_t adjustment;
7556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7557 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
7558 ✗ return AVERROR_INVALIDDATA;
7559 }
7560
7561 3 subsize = avio_rb32(pb);
7562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7563 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
7564 ✗ return AVERROR_INVALIDDATA;
7565 }
7566
7567 3 subtag = avio_rl32(pb);
7568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
7569 ✗ av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got %s\n",
7570 ✗ av_fourcc2str(subtag));
7571 ✗ return AVERROR_INVALIDDATA;
7572 }
7573
7574 3 avio_skip(pb, 1); // version
7575 3 avio_skip(pb, 3); // flags
7576
7577 3 adjustment = (int32_t) avio_rb32(pb);
7578
7579 3 horizontal_disparity_adjustment.num = (int) adjustment;
7580 3 horizontal_disparity_adjustment.den = 10000;
7581
7582 3 break;
7583 }
7584 ✗ default:
7585 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: %s\n",
7586 ✗ av_fourcc2str(tag));
7587 ✗ avio_skip(pb, size - 8);
7588 ✗ break;
7589 }
7590 11 remaining -= size;
7591 }
7592
7593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (remaining != 0) {
7594 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
7595 ✗ return AVERROR_INVALIDDATA;
7596 }
7597
7598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (type == AV_STEREO3D_2D)
7599 ✗ return 0;
7600
7601
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (!sc->stereo3d) {
7602 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7604 ✗ return AVERROR(ENOMEM);
7605 }
7606
7607 5 sc->stereo3d->flags = flags;
7608 /* eyes/stri only records packed vs single-eye, not SBS/TB. Keep a more
7609 * specific type already set by st3d. */
7610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (type != AV_STEREO3D_UNSPEC)
7611 ✗ sc->stereo3d->type = type;
7612
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 else if (sc->stereo3d->type == AV_STEREO3D_2D)
7613 3 sc->stereo3d->type = type;
7614 5 sc->stereo3d->view = view;
7615 5 sc->stereo3d->primary_eye = primary_eye;
7616 5 sc->stereo3d->baseline = baseline;
7617 5 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
7618
7619 5 return 0;
7620 }
7621
7622 5 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7623 {
7624 int size;
7625 int64_t remaining;
7626 uint32_t tag;
7627
7628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
7629 ✗ return 0;
7630
7631
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (atom.size < 8) {
7632 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
7633 ✗ return AVERROR_INVALIDDATA;
7634 }
7635
7636 5 remaining = atom.size;
7637
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5 times.
13 while (remaining > 0) {
7638 8 size = avio_rb32(pb);
7639
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 ) {
7640 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
7641 ✗ return AVERROR_INVALIDDATA;
7642 }
7643
7644 8 tag = avio_rl32(pb);
7645
2/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 switch (tag) {
7646 3 case MKTAG('p','r','o','j'): {
7647 3 MOVAtom proj = { tag, size - 8 };
7648 3 int ret = mov_read_vexu_proj(c, pb, proj);
7649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7650 ✗ return ret;
7651 3 break;
7652 }
7653 5 case MKTAG('e','y','e','s'): {
7654 5 MOVAtom eyes = { tag, size - 8 };
7655 5 int ret = mov_read_eyes(c, pb, eyes);
7656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
7657 ✗ return ret;
7658 5 break;
7659 }
7660 ✗ case MKTAG('p','a','c','k'): {
7661 ✗ MOVAtom pack = { tag, size - 8 };
7662 ✗ int ret = mov_read_pack(c, pb, pack);
7663 ✗ if (ret < 0)
7664 ✗ return ret;
7665 ✗ break;
7666 }
7667 ✗ default:
7668 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: %s\n",
7669 ✗ av_fourcc2str(tag));
7670 ✗ avio_skip(pb, size - 8);
7671 ✗ break;
7672 }
7673 8 remaining -= size;
7674 }
7675
7676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (remaining != 0) {
7677 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7678 ✗ return AVERROR_INVALIDDATA;
7679 }
7680
7681 5 return 0;
7682 }
7683
7684 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7685 {
7686 AVStream *st;
7687 MOVStreamContext *sc;
7688
7689
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7690 ✗ return 0;
7691
7692 3 st = c->fc->streams[c->fc->nb_streams - 1];
7693 3 sc = st->priv_data;
7694
7695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7696 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7697 ✗ return AVERROR_INVALIDDATA;
7698 }
7699
7700
7701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7702 ✗ sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7703 ✗ if (!sc->stereo3d)
7704 ✗ return AVERROR(ENOMEM);
7705 }
7706
7707 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7708 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7709
7710 3 return 0;
7711 }
7712
7713 ✗ static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7714 {
7715 ✗ int ret = 0;
7716 ✗ uint8_t *buffer = av_malloc(len + 1);
7717 const char *val;
7718
7719 ✗ if (!buffer)
7720 ✗ return AVERROR(ENOMEM);
7721 ✗ buffer[len] = '\0';
7722
7723 ✗ ret = ffio_read_size(pb, buffer, len);
7724 ✗ if (ret < 0)
7725 ✗ goto out;
7726
7727 /* Check for mandatory keys and values, try to support XML as best-effort */
7728 ✗ if (!sc->spherical &&
7729 ✗ av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7730 ✗ (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7731 ✗ av_stristr(val, "true") &&
7732 ✗ (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7733 ✗ av_stristr(val, "true") &&
7734 ✗ (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7735 ✗ av_stristr(val, "equirectangular")) {
7736 ✗ sc->spherical = av_spherical_alloc(&sc->spherical_size);
7737 ✗ if (!sc->spherical)
7738 ✗ goto out;
7739
7740 ✗ sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7741
7742 ✗ if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7743 enum AVStereo3DType mode;
7744
7745 ✗ if (av_stristr(buffer, "left-right"))
7746 ✗ mode = AV_STEREO3D_SIDEBYSIDE;
7747 ✗ else if (av_stristr(buffer, "top-bottom"))
7748 ✗ mode = AV_STEREO3D_TOPBOTTOM;
7749 else
7750 ✗ mode = AV_STEREO3D_2D;
7751
7752 ✗ sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7753 ✗ if (!sc->stereo3d)
7754 ✗ goto out;
7755
7756 ✗ sc->stereo3d->type = mode;
7757 }
7758
7759 /* orientation */
7760 ✗ val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7761 ✗ if (val)
7762 ✗ sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7763 ✗ val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7764 ✗ if (val)
7765 ✗ sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7766 ✗ val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7767 ✗ if (val)
7768 ✗ sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7769 }
7770
7771 ✗ out:
7772 ✗ av_free(buffer);
7773 ✗ return ret;
7774 }
7775
7776 69 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7777 {
7778 AVStream *st;
7779 MOVStreamContext *sc;
7780 int64_t ret;
7781 AVUUID uuid;
7782 static const AVUUID uuid_isml_manifest = {
7783 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7784 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7785 };
7786 static const AVUUID uuid_xmp = {
7787 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7788 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7789 };
7790 static const AVUUID uuid_spherical = {
7791 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7792 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7793 };
7794
7795
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))
7796 ✗ return AVERROR_INVALIDDATA;
7797
7798
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 66 times.
69 if (c->fc->nb_streams < 1)
7799 3 return 0;
7800 66 st = c->fc->streams[c->fc->nb_streams - 1];
7801 66 sc = st->priv_data;
7802
7803 66 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7804
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
7805 ✗ return ret;
7806
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7807 uint8_t *buffer, *ptr;
7808 char *endptr;
7809 ✗ size_t len = atom.size - AV_UUID_LEN;
7810
7811 ✗ if (len < 4) {
7812 ✗ return AVERROR_INVALIDDATA;
7813 }
7814 ✗ ret = avio_skip(pb, 4); // zeroes
7815 ✗ len -= 4;
7816
7817 ✗ buffer = av_mallocz(len + 1);
7818 ✗ if (!buffer) {
7819 ✗ return AVERROR(ENOMEM);
7820 }
7821 ✗ ret = ffio_read_size(pb, buffer, len);
7822 ✗ if (ret < 0) {
7823 ✗ av_free(buffer);
7824 ✗ return ret;
7825 }
7826
7827 ✗ ptr = buffer;
7828 ✗ while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7829 ✗ ptr += sizeof("systemBitrate=\"") - 1;
7830 ✗ c->bitrates_count++;
7831 ✗ c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7832 ✗ if (!c->bitrates) {
7833 ✗ c->bitrates_count = 0;
7834 ✗ av_free(buffer);
7835 ✗ return AVERROR(ENOMEM);
7836 }
7837 ✗ errno = 0;
7838 ✗ ret = strtol(ptr, &endptr, 10);
7839 ✗ if (ret < 0 || errno || *endptr != '"') {
7840 ✗ c->bitrates[c->bitrates_count - 1] = 0;
7841 } else {
7842 ✗ c->bitrates[c->bitrates_count - 1] = ret;
7843 }
7844 }
7845
7846 ✗ av_free(buffer);
7847
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7848 uint8_t *buffer;
7849 ✗ size_t len = atom.size - AV_UUID_LEN;
7850 ✗ if (c->export_xmp) {
7851 ✗ buffer = av_mallocz(len + 1);
7852 ✗ if (!buffer) {
7853 ✗ return AVERROR(ENOMEM);
7854 }
7855 ✗ ret = ffio_read_size(pb, buffer, len);
7856 ✗ if (ret < 0) {
7857 ✗ av_free(buffer);
7858 ✗ return ret;
7859 }
7860 ✗ buffer[len] = '\0';
7861 ✗ av_dict_set(&c->fc->metadata, "xmp",
7862 buffer, AV_DICT_DONT_STRDUP_VAL);
7863 } else {
7864 // skip all uuid atom, which makes it fast for long uuid-xmp file
7865 ✗ ret = avio_skip(pb, len);
7866 ✗ if (ret < 0)
7867 ✗ return ret;
7868 }
7869
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7870 ✗ size_t len = atom.size - AV_UUID_LEN;
7871 ✗ ret = mov_parse_uuid_spherical(sc, pb, len);
7872 ✗ if (ret < 0)
7873 ✗ return ret;
7874 ✗ if (!sc->spherical)
7875 ✗ av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7876 }
7877
7878 66 return 0;
7879 }
7880
7881 273 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7882 {
7883 int ret;
7884 uint8_t content[16];
7885
7886
2/2
✓ Branch 0 taken 150 times.
✓ Branch 1 taken 123 times.
273 if (atom.size < 8)
7887 150 return 0;
7888
7889 123 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 123 times.
123 if (ret < 0)
7891 ✗ return ret;
7892
7893
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 76 times.
123 if ( !c->found_moov
7894
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 23 times.
47 && !c->found_mdat
7895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 && !memcmp(content, "Anevia\x1A\x1A", 8)
7896 ✗ && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7897 ✗ c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7898 }
7899
7900 123 return 0;
7901 }
7902
7903 49 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7904 {
7905 49 uint32_t format = avio_rl32(pb);
7906 MOVStreamContext *sc;
7907 enum AVCodecID id;
7908 AVStream *st;
7909
7910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if (c->fc->nb_streams < 1)
7911 ✗ return 0;
7912 49 st = c->fc->streams[c->fc->nb_streams - 1];
7913 49 sc = st->priv_data;
7914
7915
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 38 times.
49 switch (sc->format)
7916 {
7917 11 case MKTAG('e','n','c','v'): // encrypted video
7918 case MKTAG('e','n','c','a'): // encrypted audio
7919 11 id = mov_codec_id(st, format);
7920
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7921 ✗ st->codecpar->codec_id != id) {
7922 ✗ av_log(c->fc, AV_LOG_WARNING,
7923 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7924 ✗ (char*)&format, st->codecpar->codec_id);
7925 ✗ break;
7926 }
7927
7928 11 st->codecpar->codec_id = id;
7929 11 sc->format = format;
7930 11 break;
7931
7932 38 default:
7933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (format != sc->format) {
7934 ✗ av_log(c->fc, AV_LOG_WARNING,
7935 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7936 ✗ (char*)&format, (char*)&sc->format);
7937 }
7938 38 break;
7939 }
7940
7941 49 return 0;
7942 }
7943
7944 /**
7945 * Gets the current encryption info and associated current stream context. If
7946 * we are parsing a track fragment, this will return the specific encryption
7947 * info for this fragment; otherwise this will return the global encryption
7948 * info for the current stream.
7949 */
7950 27 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7951 {
7952 MOVFragmentStreamInfo *frag_stream_info;
7953 AVStream *st;
7954 int i;
7955
7956 27 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7957
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 21 times.
27 if (frag_stream_info) {
7958
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 for (i = 0; i < c->fc->nb_streams; i++) {
7959 6 *sc = c->fc->streams[i]->priv_data;
7960
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if ((*sc)->id == frag_stream_info->id) {
7961 6 st = c->fc->streams[i];
7962 6 break;
7963 }
7964 }
7965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (i == c->fc->nb_streams)
7966 ✗ return 0;
7967 6 *sc = st->priv_data;
7968
7969
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (!frag_stream_info->encryption_index) {
7970 // If this stream isn't encrypted, don't create the index.
7971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(*sc)->cenc.default_encrypted_sample)
7972 ✗ return 0;
7973 2 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!frag_stream_info->encryption_index)
7975 ✗ return AVERROR(ENOMEM);
7976 }
7977 6 *encryption_index = frag_stream_info->encryption_index;
7978 6 return 1;
7979 } else {
7980 // No current track fragment, using stream level encryption info.
7981
7982
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (c->fc->nb_streams < 1)
7983 ✗ return 0;
7984 21 st = c->fc->streams[c->fc->nb_streams - 1];
7985 21 *sc = st->priv_data;
7986
7987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!(*sc)->cenc.encryption_index) {
7988 // If this stream isn't encrypted, don't create the index.
7989 ✗ if (!(*sc)->cenc.default_encrypted_sample)
7990 ✗ return 0;
7991 ✗ (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7992 ✗ if (!(*sc)->cenc.encryption_index)
7993 ✗ return AVERROR(ENOMEM);
7994 }
7995
7996 21 *encryption_index = (*sc)->cenc.encryption_index;
7997 21 return 1;
7998 }
7999 }
8000
8001 195 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
8002 {
8003 int i, ret;
8004 unsigned int subsample_count;
8005 AVSubsampleEncryptionInfo *subsamples;
8006
8007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!sc->cenc.default_encrypted_sample) {
8008 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
8009 ✗ return AVERROR_INVALIDDATA;
8010 }
8011
8012
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) {
8013 195 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
8014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*sample)
8015 ✗ return AVERROR(ENOMEM);
8016 } else
8017 ✗ *sample = NULL;
8018
8019
1/2
✓ Branch 0 taken 195 times.
✗ Branch 1 not taken.
195 if (sc->cenc.per_sample_iv_size != 0) {
8020
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) {
8021 ✗ av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
8022 ✗ av_encryption_info_free(*sample);
8023 ✗ *sample = NULL;
8024 ✗ return ret;
8025 }
8026 }
8027
8028
1/2
✓ Branch 0 taken 195 times.
✗ Branch 1 not taken.
195 if (use_subsamples) {
8029 195 subsample_count = avio_rb16(pb);
8030 195 av_free((*sample)->subsamples);
8031 195 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
8032
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!(*sample)->subsamples) {
8033 ✗ av_encryption_info_free(*sample);
8034 ✗ *sample = NULL;
8035 ✗ return AVERROR(ENOMEM);
8036 }
8037
8038
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++) {
8039 272 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
8040 272 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
8041 }
8042
8043
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (pb->eof_reached) {
8044 ✗ av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
8045 ✗ av_encryption_info_free(*sample);
8046 ✗ *sample = NULL;
8047 ✗ return AVERROR_INVALIDDATA;
8048 }
8049 195 (*sample)->subsample_count = subsample_count;
8050 }
8051
8052 195 return 0;
8053 }
8054
8055 9 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8056 {
8057 AVEncryptionInfo **encrypted_samples;
8058 MOVEncryptionIndex *encryption_index;
8059 MOVStreamContext *sc;
8060 int use_subsamples, ret;
8061 9 unsigned int sample_count, i, alloc_size = 0;
8062
8063 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8064
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8065 ✗ return ret;
8066
8067
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (encryption_index->nb_encrypted_samples) {
8068 // This can happen if we have both saio/saiz and senc atoms.
8069 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
8070 2 return 0;
8071 }
8072
8073 7 avio_r8(pb); /* version */
8074 7 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
8075
8076 7 sample_count = avio_rb32(pb);
8077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
8078 ✗ return AVERROR(ENOMEM);
8079
8080
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 7 times.
154 for (i = 0; i < sample_count; i++) {
8081 147 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
8082 147 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
8083 min_samples * sizeof(*encrypted_samples));
8084
1/2
✓ Branch 0 taken 147 times.
✗ Branch 1 not taken.
147 if (encrypted_samples) {
8085 147 encryption_index->encrypted_samples = encrypted_samples;
8086
8087 147 ret = mov_read_sample_encryption_info(
8088 147 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
8089 } else {
8090 ✗ ret = AVERROR(ENOMEM);
8091 }
8092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
147 if (pb->eof_reached) {
8093 ✗ av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
8094 ✗ if (ret >= 0)
8095 ✗ av_encryption_info_free(encryption_index->encrypted_samples[i]);
8096 ✗ ret = AVERROR_INVALIDDATA;
8097 }
8098
8099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
147 if (ret < 0) {
8100 ✗ for (; i > 0; i--)
8101 ✗ av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
8102 ✗ av_freep(&encryption_index->encrypted_samples);
8103 ✗ return ret;
8104 }
8105 }
8106 7 encryption_index->nb_encrypted_samples = sample_count;
8107
8108 7 return 0;
8109 }
8110
8111 2 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
8112 {
8113 AVEncryptionInfo **sample, **encrypted_samples;
8114 int64_t prev_pos;
8115 size_t sample_count, sample_info_size, i;
8116 2 int ret = 0;
8117 2 unsigned int alloc_size = 0;
8118
8119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->nb_encrypted_samples)
8120 ✗ return 0;
8121 2 sample_count = encryption_index->auxiliary_info_sample_count;
8122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count != 1) {
8123 ✗ av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
8124 ✗ return AVERROR_PATCHWELCOME;
8125 }
8126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
8127 ✗ return AVERROR(ENOMEM);
8128
8129 2 prev_pos = avio_tell(pb);
8130
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
8131
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]) {
8132 ✗ av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
8133 ✗ goto finish;
8134 }
8135
8136
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++) {
8137 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
8138 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
8139 min_samples * sizeof(*encrypted_samples));
8140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (!encrypted_samples) {
8141 ✗ ret = AVERROR(ENOMEM);
8142 ✗ goto finish;
8143 }
8144 48 encryption_index->encrypted_samples = encrypted_samples;
8145
8146 48 sample = &encryption_index->encrypted_samples[i];
8147 96 sample_info_size = encryption_index->auxiliary_info_default_size
8148 48 ? encryption_index->auxiliary_info_default_size
8149
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 : encryption_index->auxiliary_info_sizes[i];
8150
8151 48 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
8152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0)
8153 ✗ goto finish;
8154 }
8155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
8156 ✗ av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
8157 ✗ ret = AVERROR_INVALIDDATA;
8158 } else {
8159 2 encryption_index->nb_encrypted_samples = sample_count;
8160 }
8161
8162 2 finish:
8163 2 avio_seek(pb, prev_pos, SEEK_SET);
8164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
8165 ✗ for (; i > 0; i--) {
8166 ✗ av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
8167 }
8168 ✗ av_freep(&encryption_index->encrypted_samples);
8169 }
8170 2 return ret;
8171 }
8172
8173 9 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8174 {
8175 MOVEncryptionIndex *encryption_index;
8176 MOVStreamContext *sc;
8177 int ret;
8178 unsigned int sample_count, aux_info_type, aux_info_param;
8179
8180 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8182 ✗ return ret;
8183
8184
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (encryption_index->nb_encrypted_samples) {
8185 // This can happen if we have both saio/saiz and senc atoms.
8186 7 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
8187 7 return 0;
8188 }
8189
8190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_sample_count) {
8191 ✗ av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
8192 ✗ return AVERROR_INVALIDDATA;
8193 }
8194
8195 2 avio_r8(pb); /* version */
8196
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
8197 ✗ aux_info_type = avio_rb32(pb);
8198 ✗ aux_info_param = avio_rb32(pb);
8199 ✗ if (sc->cenc.default_encrypted_sample) {
8200 ✗ if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
8201 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
8202 ✗ return 0;
8203 }
8204 ✗ if (aux_info_param != 0) {
8205 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
8206 ✗ return 0;
8207 }
8208 } else {
8209 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8210 ✗ if ((aux_info_type == MKBETAG('c','e','n','c') ||
8211 ✗ aux_info_type == MKBETAG('c','e','n','s') ||
8212 ✗ aux_info_type == MKBETAG('c','b','c','1') ||
8213 ✗ aux_info_type == MKBETAG('c','b','c','s')) &&
8214 aux_info_param == 0) {
8215 ✗ av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
8216 ✗ return AVERROR_INVALIDDATA;
8217 } else {
8218 ✗ return 0;
8219 }
8220 }
8221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
8222 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8223 ✗ return 0;
8224 }
8225
8226 2 encryption_index->auxiliary_info_default_size = avio_r8(pb);
8227 2 sample_count = avio_rb32(pb);
8228
8229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_default_size == 0) {
8230 ✗ if (sample_count == 0)
8231 ✗ return AVERROR_INVALIDDATA;
8232
8233 ✗ encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
8234 ✗ if (!encryption_index->auxiliary_info_sizes)
8235 ✗ return AVERROR(ENOMEM);
8236
8237 ✗ ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
8238 ✗ if (ret != sample_count) {
8239 ✗ av_freep(&encryption_index->auxiliary_info_sizes);
8240
8241 ✗ if (ret >= 0)
8242 ✗ ret = AVERROR_INVALIDDATA;
8243 ✗ av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
8244 ✗ av_err2str(ret));
8245 ✗ return ret;
8246 }
8247 }
8248 2 encryption_index->auxiliary_info_sample_count = sample_count;
8249
8250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
8251 ✗ return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
8252 }
8253
8254 2 return 0;
8255 }
8256
8257 9 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8258 {
8259 uint64_t *auxiliary_offsets;
8260 MOVEncryptionIndex *encryption_index;
8261 MOVStreamContext *sc;
8262 int i, ret;
8263 unsigned int version, entry_count, aux_info_type, aux_info_param;
8264 9 unsigned int alloc_size = 0;
8265
8266 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8268 ✗ return ret;
8269
8270
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (encryption_index->nb_encrypted_samples) {
8271 // This can happen if we have both saio/saiz and senc atoms.
8272 7 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
8273 7 return 0;
8274 }
8275
8276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
8277 ✗ av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
8278 ✗ return AVERROR_INVALIDDATA;
8279 }
8280
8281 2 version = avio_r8(pb); /* version */
8282
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
8283 ✗ aux_info_type = avio_rb32(pb);
8284 ✗ aux_info_param = avio_rb32(pb);
8285 ✗ if (sc->cenc.default_encrypted_sample) {
8286 ✗ if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
8287 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
8288 ✗ return 0;
8289 }
8290 ✗ if (aux_info_param != 0) {
8291 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
8292 ✗ return 0;
8293 }
8294 } else {
8295 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8296 ✗ if ((aux_info_type == MKBETAG('c','e','n','c') ||
8297 ✗ aux_info_type == MKBETAG('c','e','n','s') ||
8298 ✗ aux_info_type == MKBETAG('c','b','c','1') ||
8299 ✗ aux_info_type == MKBETAG('c','b','c','s')) &&
8300 aux_info_param == 0) {
8301 ✗ av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
8302 ✗ return AVERROR_INVALIDDATA;
8303 } else {
8304 ✗ return 0;
8305 }
8306 }
8307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
8308 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8309 ✗ return 0;
8310 }
8311
8312 2 entry_count = avio_rb32(pb);
8313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
8314 ✗ return AVERROR(ENOMEM);
8315
8316
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++) {
8317
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);
8318 2 auxiliary_offsets = av_fast_realloc(
8319 2 encryption_index->auxiliary_offsets, &alloc_size,
8320 min_offsets * sizeof(*auxiliary_offsets));
8321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!auxiliary_offsets) {
8322 ✗ av_freep(&encryption_index->auxiliary_offsets);
8323 ✗ return AVERROR(ENOMEM);
8324 }
8325 2 encryption_index->auxiliary_offsets = auxiliary_offsets;
8326
8327
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version == 0) {
8328 2 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
8329 } else {
8330 ✗ encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
8331 }
8332
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (c->frag_index.current >= 0) {
8333 2 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
8334 }
8335 }
8336
8337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
8338 ✗ av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
8339 ✗ av_freep(&encryption_index->auxiliary_offsets);
8340 ✗ return AVERROR_INVALIDDATA;
8341 }
8342
8343 2 encryption_index->auxiliary_offsets_count = entry_count;
8344
8345
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (encryption_index->auxiliary_info_sample_count) {
8346 2 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
8347 }
8348
8349 ✗ return 0;
8350 }
8351
8352 4 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8353 {
8354 AVEncryptionInitInfo *info;
8355 uint8_t **key_ids;
8356 AVStream *st;
8357 4 AVPacketSideData *old_side_data = NULL;
8358 4 uint8_t *side_data = NULL, *extra_data;
8359 4 size_t side_data_size = 0;
8360 4 int ret = 0;
8361 4 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
8362
8363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8364 ✗ return 0;
8365 4 st = c->fc->streams[c->fc->nb_streams-1];
8366
8367 4 version = avio_r8(pb); /* version */
8368 4 avio_rb24(pb); /* flags */
8369
8370 4 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
8371 /* key_id_size */ 16, /* data_size */ 0);
8372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info)
8373 ✗ return AVERROR(ENOMEM);
8374
8375
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
8376 ✗ av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
8377 ✗ goto finish;
8378 }
8379
8380
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (version > 0) {
8381 4 kid_count = avio_rb32(pb);
8382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
8383 ✗ ret = AVERROR(ENOMEM);
8384 ✗ goto finish;
8385 }
8386
8387
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++) {
8388 4 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
8389 4 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
8390 min_kid_count * sizeof(*key_ids));
8391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!key_ids) {
8392 ✗ ret = AVERROR(ENOMEM);
8393 ✗ goto finish;
8394 }
8395 4 info->key_ids = key_ids;
8396
8397 4 info->key_ids[i] = av_mallocz(16);
8398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info->key_ids[i]) {
8399 ✗ ret = AVERROR(ENOMEM);
8400 ✗ goto finish;
8401 }
8402 4 info->num_key_ids = i + 1;
8403
8404
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
8405 ✗ av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
8406 ✗ goto finish;
8407 }
8408 }
8409
8410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pb->eof_reached) {
8411 ✗ av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
8412 ✗ ret = AVERROR_INVALIDDATA;
8413 ✗ goto finish;
8414 }
8415 }
8416
8417 4 extra_data_size = avio_rb32(pb);
8418 4 extra_data = av_malloc(extra_data_size);
8419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!extra_data) {
8420 ✗ ret = AVERROR(ENOMEM);
8421 ✗ goto finish;
8422 }
8423 4 ret = avio_read(pb, extra_data, extra_data_size);
8424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != extra_data_size) {
8425 ✗ av_free(extra_data);
8426
8427 ✗ if (ret >= 0)
8428 ✗ ret = AVERROR_INVALIDDATA;
8429 ✗ goto finish;
8430 }
8431
8432 4 av_freep(&info->data); // malloc(0) may still allocate something.
8433 4 info->data = extra_data;
8434 4 info->data_size = extra_data_size;
8435
8436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 for (int i = 0; i < st->codecpar->nb_coded_side_data; i++)
8437 ✗ if (st->codecpar->coded_side_data[i].type == AV_PKT_DATA_ENCRYPTION_INIT_INFO)
8438 ✗ old_side_data = &st->codecpar->coded_side_data[i];
8439
8440 // If there is existing initialization data, append the new record to it.
8441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (old_side_data) {
8442 ✗ side_data = old_side_data->data;
8443 ✗ side_data_size = old_side_data->size;
8444 }
8445
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 if (!old_side_data || side_data != c->pssh_side_data)
8446 4 c->pssh_side_data_allocated = 0;
8447
8448 4 ret = av_encryption_init_info_append_side_data(&side_data, &side_data_size,
8449 &c->pssh_side_data_allocated, info);
8450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
8451 ✗ goto finish;
8452
8453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (old_side_data) {
8454 ✗ old_side_data->data = side_data;
8455 ✗ old_side_data->size = side_data_size;
8456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 } else if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
8457 4 &st->codecpar->nb_coded_side_data,
8458 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
8459 side_data, side_data_size, 0)) {
8460 ✗ av_free(side_data);
8461 ✗ ret = AVERROR(ENOMEM);
8462 ✗ goto finish;
8463 }
8464 4 c->pssh_side_data = side_data;
8465
8466 4 finish:
8467 4 av_encryption_init_info_free(info);
8468 4 return ret;
8469 }
8470
8471 11 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8472 {
8473 AVStream *st;
8474 MOVStreamContext *sc;
8475
8476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
8477 ✗ return 0;
8478 11 st = c->fc->streams[c->fc->nb_streams-1];
8479 11 sc = st->priv_data;
8480
8481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (sc->pseudo_stream_id != 0) {
8482 ✗ av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
8483 ✗ return AVERROR_PATCHWELCOME;
8484 }
8485
8486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
8487 ✗ return AVERROR_INVALIDDATA;
8488
8489 11 avio_rb32(pb); /* version and flags */
8490
8491
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (!sc->cenc.default_encrypted_sample) {
8492 11 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.default_encrypted_sample) {
8494 ✗ return AVERROR(ENOMEM);
8495 }
8496 }
8497
8498 11 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
8499 11 return 0;
8500 }
8501
8502 11 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8503 {
8504 AVStream *st;
8505 MOVStreamContext *sc;
8506 unsigned int version, pattern, is_protected, iv_size;
8507
8508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
8509 ✗ return 0;
8510 11 st = c->fc->streams[c->fc->nb_streams-1];
8511 11 sc = st->priv_data;
8512
8513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (sc->pseudo_stream_id != 0) {
8514 ✗ av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
8515 ✗ return AVERROR_PATCHWELCOME;
8516 }
8517
8518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.default_encrypted_sample) {
8519 ✗ sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8520 ✗ if (!sc->cenc.default_encrypted_sample) {
8521 ✗ return AVERROR(ENOMEM);
8522 }
8523 }
8524
8525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 20)
8526 ✗ return AVERROR_INVALIDDATA;
8527
8528 11 version = avio_r8(pb); /* version */
8529 11 avio_rb24(pb); /* flags */
8530
8531 11 avio_r8(pb); /* reserved */
8532 11 pattern = avio_r8(pb);
8533
8534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (version > 0) {
8535 ✗ sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
8536 ✗ sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
8537 }
8538
8539 11 is_protected = avio_r8(pb);
8540
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) {
8541 // The whole stream should be by-default encrypted.
8542 11 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
8543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.encryption_index)
8544 ✗ return AVERROR(ENOMEM);
8545 }
8546 11 iv_size = avio_r8(pb);
8547
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) {
8548 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
8549 ✗ return AVERROR_INVALIDDATA;
8550 }
8551 11 sc->cenc.per_sample_iv_size = iv_size;
8552
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) {
8553 ✗ av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
8554 ✗ return AVERROR_INVALIDDATA;
8555 }
8556
8557
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) {
8558 2 iv_size = avio_r8(pb);
8559
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) {
8560 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
8561 ✗ return AVERROR_INVALIDDATA;
8562 }
8563
8564
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) {
8565 ✗ av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
8566 ✗ return AVERROR_INVALIDDATA;
8567 }
8568 }
8569
8570 11 return 0;
8571 }
8572
8573 ✗ static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8574 {
8575 AVStream *st;
8576 int last, type, size, ret;
8577 uint8_t buf[4];
8578
8579 ✗ if (c->fc->nb_streams < 1)
8580 ✗ return 0;
8581 ✗ st = c->fc->streams[c->fc->nb_streams-1];
8582
8583 ✗ if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
8584 ✗ return AVERROR_INVALIDDATA;
8585
8586 /* Check FlacSpecificBox version. */
8587 ✗ if (avio_r8(pb) != 0)
8588 ✗ return AVERROR_INVALIDDATA;
8589
8590 ✗ avio_rb24(pb); /* Flags */
8591
8592 ✗ if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
8593 ✗ av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
8594 ✗ return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
8595 }
8596 ✗ flac_parse_block_header(buf, &last, &type, &size);
8597
8598 ✗ if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
8599 ✗ av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
8600 ✗ return AVERROR_INVALIDDATA;
8601 }
8602
8603 ✗ ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
8604 ✗ if (ret < 0)
8605 ✗ return ret;
8606
8607 ✗ if (!last)
8608 ✗ av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
8609
8610 ✗ return 0;
8611 }
8612
8613 11 static int get_key_from_kid(uint8_t* out, int len, MOVContext *c, AVEncryptionInfo *sample) {
8614 AVDictionaryEntry *key_entry_hex;
8615 char kid_hex[16*2+1];
8616
8617
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) {
8618 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid default decryption key length: got %d, expected %d\n", c->decryption_default_key_len, len);
8619 ✗ return -1;
8620 }
8621
8622
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
11 if (!c->decryption_keys) {
8623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 av_assert0(c->decryption_default_key);
8624 8 memcpy(out, c->decryption_default_key, len);
8625 8 return 0;
8626 }
8627
8628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sample->key_id_size != 16) {
8629 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid key ID size: got %u, expected 16\n", sample->key_id_size);
8630 ✗ return -1;
8631 }
8632
8633 3 ff_data_to_hex(kid_hex, sample->key_id, 16, 1);
8634 3 key_entry_hex = av_dict_get(c->decryption_keys, kid_hex, NULL, AV_DICT_DONT_STRDUP_KEY|AV_DICT_DONT_STRDUP_VAL);
8635
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!key_entry_hex) {
8636 ✗ if (!c->decryption_default_key) {
8637 ✗ av_log(c->fc, AV_LOG_ERROR, "unable to find KID %s\n", kid_hex);
8638 ✗ return -1;
8639 }
8640 ✗ memcpy(out, c->decryption_default_key, len);
8641 ✗ return 0;
8642 }
8643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (strlen(key_entry_hex->value) != len*2) {
8644 ✗ return -1;
8645 }
8646 3 ff_hex_to_data(out, key_entry_hex->value);
8647 3 return 0;
8648 }
8649
8650 341 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8651 {
8652 int i, ret;
8653 int bytes_of_protected_data;
8654 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8655
8656
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 330 times.
341 if (!sc->cenc.aes_ctr) {
8657 11 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0) {
8659 ✗ return ret;
8660 }
8661
8662 /* initialize the cipher */
8663 11 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.aes_ctr) {
8665 ✗ return AVERROR(ENOMEM);
8666 }
8667
8668 11 ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0) {
8670 ✗ return ret;
8671 }
8672 }
8673
8674 341 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8675
8676
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 245 times.
341 if (!sample->subsample_count) {
8677 /* decrypt the whole packet */
8678 96 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8679 96 return 0;
8680 }
8681
8682
2/2
✓ Branch 0 taken 321 times.
✓ Branch 1 taken 245 times.
566 for (i = 0; i < sample->subsample_count; i++) {
8683
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) {
8684 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8685 ✗ return AVERROR_INVALIDDATA;
8686 }
8687
8688 /* skip the clear bytes */
8689 321 input += sample->subsamples[i].bytes_of_clear_data;
8690 321 size -= sample->subsamples[i].bytes_of_clear_data;
8691
8692 /* decrypt the encrypted bytes */
8693
8694 321 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
8695 321 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
8696
8697 321 input += bytes_of_protected_data;
8698 321 size -= bytes_of_protected_data;
8699 }
8700
8701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
245 if (size > 0) {
8702 ✗ av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8703 ✗ return AVERROR_INVALIDDATA;
8704 }
8705
8706 245 return 0;
8707 }
8708
8709 ✗ static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8710 {
8711 int i, ret;
8712 int num_of_encrypted_blocks;
8713 uint8_t iv[16];
8714 uint8_t decryption_key[16];
8715
8716 ✗ if (!sc->cenc.aes_ctx) {
8717 ✗ ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8718 ✗ if (ret < 0) {
8719 ✗ return ret;
8720 }
8721
8722 /* initialize the cipher */
8723 ✗ sc->cenc.aes_ctx = av_aes_alloc();
8724 ✗ if (!sc->cenc.aes_ctx) {
8725 ✗ return AVERROR(ENOMEM);
8726 }
8727
8728 ✗ ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8729 ✗ if (ret < 0) {
8730 ✗ return ret;
8731 }
8732 }
8733
8734 ✗ memcpy(iv, sample->iv, 16);
8735
8736 /* whole-block full sample encryption */
8737 ✗ if (!sample->subsample_count) {
8738 /* decrypt the whole packet */
8739 ✗ av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8740 ✗ return 0;
8741 }
8742
8743 ✗ for (i = 0; i < sample->subsample_count; i++) {
8744 ✗ if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8745 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8746 ✗ return AVERROR_INVALIDDATA;
8747 }
8748
8749 ✗ if (sample->subsamples[i].bytes_of_protected_data % 16) {
8750 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8751 ✗ return AVERROR_INVALIDDATA;
8752 }
8753
8754 /* skip the clear bytes */
8755 ✗ input += sample->subsamples[i].bytes_of_clear_data;
8756 ✗ size -= sample->subsamples[i].bytes_of_clear_data;
8757
8758 /* decrypt the encrypted bytes */
8759 ✗ num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8760 ✗ if (num_of_encrypted_blocks > 0) {
8761 ✗ av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8762 }
8763 ✗ input += sample->subsamples[i].bytes_of_protected_data;
8764 ✗ size -= sample->subsamples[i].bytes_of_protected_data;
8765 }
8766
8767 ✗ if (size > 0) {
8768 ✗ av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8769 ✗ return AVERROR_INVALIDDATA;
8770 }
8771
8772 ✗ return 0;
8773 }
8774
8775 ✗ static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8776 {
8777 int i, ret, rem_bytes;
8778 uint8_t *data;
8779 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8780
8781 ✗ if (!sc->cenc.aes_ctr) {
8782 ✗ ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8783 ✗ if (ret < 0) {
8784 ✗ return ret;
8785 }
8786
8787 /* initialize the cipher */
8788 ✗ sc->cenc.aes_ctr = av_aes_ctr_alloc();
8789 ✗ if (!sc->cenc.aes_ctr) {
8790 ✗ return AVERROR(ENOMEM);
8791 }
8792
8793 ✗ ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8794 ✗ if (ret < 0) {
8795 ✗ return ret;
8796 }
8797 }
8798
8799 ✗ av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8800
8801 /* whole-block full sample encryption */
8802 ✗ if (!sample->subsample_count) {
8803 /* decrypt the whole packet */
8804 ✗ av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8805 ✗ return 0;
8806 ✗ } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8807 ✗ av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8808 ✗ return AVERROR_INVALIDDATA;
8809 }
8810
8811 ✗ for (i = 0; i < sample->subsample_count; i++) {
8812 ✗ if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8813 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8814 ✗ return AVERROR_INVALIDDATA;
8815 }
8816
8817 /* skip the clear bytes */
8818 ✗ input += sample->subsamples[i].bytes_of_clear_data;
8819 ✗ size -= sample->subsamples[i].bytes_of_clear_data;
8820
8821 /* decrypt the encrypted bytes */
8822 ✗ data = input;
8823 ✗ rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8824 ✗ while (rem_bytes > 0) {
8825 ✗ if (rem_bytes < 16*sample->crypt_byte_block) {
8826 ✗ break;
8827 }
8828 ✗ av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8829 ✗ data += 16*sample->crypt_byte_block;
8830 ✗ rem_bytes -= 16*sample->crypt_byte_block;
8831 ✗ data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8832 ✗ rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8833 }
8834 ✗ input += sample->subsamples[i].bytes_of_protected_data;
8835 ✗ size -= sample->subsamples[i].bytes_of_protected_data;
8836 }
8837
8838 ✗ if (size > 0) {
8839 ✗ av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8840 ✗ return AVERROR_INVALIDDATA;
8841 }
8842
8843 ✗ return 0;
8844 }
8845
8846 ✗ static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8847 {
8848 int i, ret, rem_bytes;
8849 uint8_t iv[16];
8850 uint8_t *data;
8851 uint8_t decryption_key[16];
8852
8853 ✗ if (!sc->cenc.aes_ctx) {
8854 ✗ ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8855 ✗ if (ret < 0) {
8856 ✗ return ret;
8857 }
8858
8859 /* initialize the cipher */
8860 ✗ sc->cenc.aes_ctx = av_aes_alloc();
8861 ✗ if (!sc->cenc.aes_ctx) {
8862 ✗ return AVERROR(ENOMEM);
8863 }
8864
8865 ✗ ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8866 ✗ if (ret < 0) {
8867 ✗ return ret;
8868 }
8869 }
8870
8871 /* whole-block full sample encryption */
8872 ✗ if (!sample->subsample_count) {
8873 /* decrypt the whole packet */
8874 ✗ memcpy(iv, sample->iv, 16);
8875 ✗ av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8876 ✗ return 0;
8877 ✗ } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8878 ✗ av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8879 ✗ return AVERROR_INVALIDDATA;
8880 }
8881
8882 ✗ for (i = 0; i < sample->subsample_count; i++) {
8883 ✗ if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8884 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8885 ✗ return AVERROR_INVALIDDATA;
8886 }
8887
8888 /* skip the clear bytes */
8889 ✗ input += sample->subsamples[i].bytes_of_clear_data;
8890 ✗ size -= sample->subsamples[i].bytes_of_clear_data;
8891
8892 /* decrypt the encrypted bytes */
8893 ✗ memcpy(iv, sample->iv, 16);
8894 ✗ data = input;
8895 ✗ rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8896 ✗ while (rem_bytes > 0) {
8897 ✗ if (rem_bytes < 16*sample->crypt_byte_block) {
8898 ✗ break;
8899 }
8900 ✗ av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8901 ✗ data += 16*sample->crypt_byte_block;
8902 ✗ rem_bytes -= 16*sample->crypt_byte_block;
8903 ✗ data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8904 ✗ rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8905 }
8906 ✗ input += sample->subsamples[i].bytes_of_protected_data;
8907 ✗ size -= sample->subsamples[i].bytes_of_protected_data;
8908 }
8909
8910 ✗ if (size > 0) {
8911 ✗ av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8912 ✗ return AVERROR_INVALIDDATA;
8913 }
8914
8915 ✗ return 0;
8916 }
8917
8918 341 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8919 {
8920
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) {
8921 341 return cenc_scheme_decrypt(c, sc, sample, input, size);
8922 ✗ } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8923 ✗ return cbc1_scheme_decrypt(c, sc, sample, input, size);
8924 ✗ } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8925 ✗ return cens_scheme_decrypt(c, sc, sample, input, size);
8926 ✗ } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8927 ✗ return cbcs_scheme_decrypt(c, sc, sample, input, size);
8928 } else {
8929 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8930 ✗ return AVERROR_INVALIDDATA;
8931 }
8932 }
8933
8934 112640 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8935 {
8936 112640 int current = frag_index->current;
8937
8938
2/2
✓ Branch 0 taken 108839 times.
✓ Branch 1 taken 3801 times.
112640 if (!frag_index->nb_items)
8939 108839 return NULL;
8940
8941 // Check frag_index->current is the right one for pkt. It can out of sync.
8942
2/4
✓ Branch 0 taken 3801 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3801 times.
✗ Branch 3 not taken.
3801 if (current >= 0 && current < frag_index->nb_items) {
8943
2/2
✓ Branch 0 taken 3773 times.
✓ Branch 1 taken 28 times.
3801 if (frag_index->item[current].moof_offset < pkt->pos &&
8944
2/2
✓ Branch 0 taken 613 times.
✓ Branch 1 taken 3160 times.
3773 (current + 1 == frag_index->nb_items ||
8945
2/2
✓ Branch 0 taken 536 times.
✓ Branch 1 taken 77 times.
613 frag_index->item[current + 1].moof_offset > pkt->pos))
8946 3696 return get_frag_stream_info(frag_index, current, id);
8947 }
8948
8949
8950
2/2
✓ Branch 0 taken 4561 times.
✓ Branch 1 taken 10 times.
4571 for (int i = 0; i < frag_index->nb_items; i++) {
8951
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 4466 times.
4561 if (frag_index->item[i].moof_offset > pkt->pos)
8952 95 break;
8953 4466 current = i;
8954 }
8955 105 frag_index->current = current;
8956 105 return get_frag_stream_info(frag_index, current, id);
8957 }
8958
8959 112640 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8960 {
8961 MOVFragmentStreamInfo *frag_stream_info;
8962 MOVEncryptionIndex *encryption_index;
8963 AVEncryptionInfo *encrypted_sample;
8964 int encrypted_index, ret;
8965
8966 112640 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8967 112640 encrypted_index = current_index;
8968 112640 encryption_index = NULL;
8969
2/2
✓ Branch 0 taken 3801 times.
✓ Branch 1 taken 108839 times.
112640 if (frag_stream_info) {
8970 // Note this only supports encryption info in the first sample descriptor.
8971
2/2
✓ Branch 0 taken 3753 times.
✓ Branch 1 taken 48 times.
3801 if (frag_stream_info->stsd_id == 1) {
8972
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3705 times.
3753 if (frag_stream_info->encryption_index) {
8973 48 encrypted_index = current_index - frag_stream_info->index_base;
8974 48 encryption_index = frag_stream_info->encryption_index;
8975 } else {
8976 3705 encryption_index = sc->cenc.encryption_index;
8977 }
8978 }
8979 } else {
8980 108839 encryption_index = sc->cenc.encryption_index;
8981 }
8982
8983
2/2
✓ Branch 0 taken 341 times.
✓ Branch 1 taken 112299 times.
112640 if (encryption_index) {
8984
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 293 times.
341 if (encryption_index->auxiliary_info_sample_count &&
8985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8986 ✗ av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8987 ✗ return AVERROR_INVALIDDATA;
8988 }
8989
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 293 times.
341 if (encryption_index->auxiliary_offsets_count &&
8990
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8991 ✗ av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8992 ✗ return AVERROR_INVALIDDATA;
8993 }
8994
8995 341 encrypted_sample = NULL;
8996
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 245 times.
341 if (!encryption_index->nb_encrypted_samples) {
8997 // Full-sample encryption with default settings.
8998 96 encrypted_sample = sc->cenc.default_encrypted_sample;
8999
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) {
9000 // Per-sample setting override.
9001 245 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
9002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
245 if (!encrypted_sample) {
9003 ✗ encrypted_sample = sc->cenc.default_encrypted_sample;
9004 }
9005 }
9006
9007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
341 if (!encrypted_sample) {
9008 ✗ av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
9009 ✗ return AVERROR_INVALIDDATA;
9010 }
9011
9012
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) {
9013 341 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
9014 } else {
9015 size_t size;
9016 ✗ uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
9017 ✗ if (!side_data)
9018 ✗ return AVERROR(ENOMEM);
9019 ✗ ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
9020 ✗ if (ret < 0)
9021 ✗ av_free(side_data);
9022 ✗ return ret;
9023 }
9024 }
9025
9026 112299 return 0;
9027 }
9028
9029 ✗ static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9030 {
9031 ✗ const int OPUS_SEEK_PREROLL_MS = 80;
9032 int ret;
9033 AVStream *st;
9034 size_t size;
9035 uint16_t pre_skip;
9036
9037 ✗ if (c->fc->nb_streams < 1)
9038 ✗ return 0;
9039 ✗ st = c->fc->streams[c->fc->nb_streams-1];
9040
9041 ✗ if ((uint64_t)atom.size > (1<<30) || atom.size < 11 || st->codecpar->extradata)
9042 ✗ return AVERROR_INVALIDDATA;
9043
9044 /* Check OpusSpecificBox version. */
9045 ✗ if (avio_r8(pb) != 0) {
9046 ✗ av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
9047 ✗ return AVERROR_INVALIDDATA;
9048 }
9049
9050 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
9051 ✗ size = atom.size + 8;
9052
9053 ✗ if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
9054 ✗ return ret;
9055
9056 ✗ AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
9057 ✗ AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
9058 ✗ AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
9059 ✗ if ((ret = ffio_read_size(pb, st->codecpar->extradata + 9, size - 9)) < 0) {
9060 ✗ av_freep(&st->codecpar->extradata);
9061 ✗ st->codecpar->extradata_size = 0;
9062 ✗ return ret;
9063 }
9064
9065 /* OpusSpecificBox is stored in big-endian, but OpusHead is
9066 little-endian; aside from the preceding magic and version they're
9067 otherwise currently identical. Data after output gain at offset 16
9068 doesn't need to be bytewapped. */
9069 ✗ pre_skip = AV_RB16A(st->codecpar->extradata + 10);
9070 ✗ AV_WL16A(st->codecpar->extradata + 10, pre_skip);
9071 ✗ AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
9072 ✗ AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
9073
9074 ✗ st->codecpar->initial_padding = pre_skip;
9075 ✗ st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
9076 ✗ (AVRational){1, 1000},
9077 ✗ (AVRational){1, 48000});
9078
9079 ✗ return 0;
9080 }
9081
9082 ✗ static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9083 {
9084 AVStream *st;
9085 unsigned format_info;
9086 int channel_assignment, channel_assignment1, channel_assignment2;
9087 int ratebits;
9088 uint64_t chmask;
9089
9090 ✗ if (c->fc->nb_streams < 1)
9091 ✗ return 0;
9092 ✗ st = c->fc->streams[c->fc->nb_streams-1];
9093
9094 ✗ if (atom.size < 10)
9095 ✗ return AVERROR_INVALIDDATA;
9096
9097 ✗ format_info = avio_rb32(pb);
9098
9099 ✗ ratebits = (format_info >> 28) & 0xF;
9100 ✗ channel_assignment1 = (format_info >> 15) & 0x1F;
9101 ✗ channel_assignment2 = format_info & 0x1FFF;
9102 ✗ if (channel_assignment2)
9103 ✗ channel_assignment = channel_assignment2;
9104 else
9105 ✗ channel_assignment = channel_assignment1;
9106
9107 ✗ st->codecpar->frame_size = 40 << (ratebits & 0x7);
9108 ✗ st->codecpar->sample_rate = mlp_samplerate(ratebits);
9109
9110 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
9111 ✗ chmask = truehd_layout(channel_assignment);
9112 ✗ av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
9113
9114 ✗ return 0;
9115 }
9116
9117 11 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9118 {
9119 AVStream *st;
9120 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
9121 int ret;
9122 11 int64_t read_size = atom.size;
9123
9124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
9125 ✗ return 0;
9126 11 st = c->fc->streams[c->fc->nb_streams-1];
9127
9128 // At most 24 bytes
9129 11 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
9130
9131
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
9132 ✗ return ret;
9133
9134 11 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
9135 }
9136
9137 7 static int mov_read_hvce(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9138 {
9139 AVStream *st;
9140 AVPacketSideData *sd;
9141 int ret;
9142
9143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (c->fc->nb_streams < 1)
9144 ✗ return 0;
9145 7 st = c->fc->streams[c->fc->nb_streams - 1];
9146
9147
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)
9148 ✗ return AVERROR_INVALIDDATA;
9149
9150 7 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
9151 7 &st->codecpar->nb_coded_side_data,
9152 AV_PKT_DATA_HEVC_CONF,
9153 7 atom.size, 0);
9154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sd)
9155 ✗ return AVERROR(ENOMEM);
9156
9157 7 ret = ffio_read_size(pb, sd->data, atom.size);
9158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
9159 ✗ return ret;
9160
9161 7 return 0;
9162 }
9163
9164 4 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9165 {
9166 AVStream *st;
9167 uint8_t *buf;
9168 int ret, old_size, num_arrays;
9169
9170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
9171 ✗ return 0;
9172 4 st = c->fc->streams[c->fc->nb_streams-1];
9173
9174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!st->codecpar->extradata_size)
9175 // TODO: handle lhvC when present before hvcC
9176 ✗ return 0;
9177
9178
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 ||
9179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 atom.size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
9180 ✗ return AVERROR_INVALIDDATA;
9181 }
9182
9183 4 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
9184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!buf)
9185 ✗ return AVERROR(ENOMEM);
9186 4 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
9187
9188 4 ret = ffio_read_size(pb, buf, atom.size);
9189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
9190 ✗ av_free(buf);
9191 ✗ av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
9192 ✗ return 0;
9193 }
9194
9195 4 num_arrays = buf[5];
9196 4 old_size = st->codecpar->extradata_size;
9197 4 atom.size -= 8 /* account for mov_realloc_extradata offsetting */
9198 + 6 /* lhvC bytes before the arrays*/;
9199
9200 4 ret = mov_realloc_extradata(st->codecpar, atom);
9201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
9202 ✗ av_free(buf);
9203 ✗ return ret;
9204 }
9205
9206 4 st->codecpar->extradata[22] += num_arrays;
9207 4 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
9208
9209 4 st->disposition |= AV_DISPOSITION_MULTILAYER;
9210
9211 4 av_free(buf);
9212 4 return 0;
9213 }
9214
9215 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9216 {
9217 4 AVFormatContext *ctx = c->fc;
9218 4 AVStream *st = NULL;
9219 AVBPrint scheme_buf, value_buf;
9220 4 int64_t scheme_str_len = 0, value_str_len = 0;
9221 4 int version, flags, ret = AVERROR_BUG;
9222 4 int64_t size = atom.size;
9223
9224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
9225 // 4 bytes for version + flags, 2x 1 byte for null
9226 ✗ return AVERROR_INVALIDDATA;
9227
9228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
9229 ✗ return 0;
9230 4 st = c->fc->streams[c->fc->nb_streams-1];
9231
9232 4 version = avio_r8(pb);
9233 4 flags = avio_rb24(pb);
9234 4 size -= 4;
9235
9236
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) {
9237 ✗ av_log(ctx, AV_LOG_ERROR,
9238 "Unsupported 'kind' box with version %d, flags: %x",
9239 version, flags);
9240 ✗ return AVERROR_INVALIDDATA;
9241 }
9242
9243 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
9244 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
9245
9246
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,
9247 size)) < 0) {
9248 ✗ ret = scheme_str_len;
9249 ✗ goto cleanup;
9250 }
9251
9252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
9253 // we need to have another string, even if nullptr.
9254 // we check with + 1 since we expect that if size was not hit,
9255 // an additional null was read.
9256 ✗ ret = AVERROR_INVALIDDATA;
9257 ✗ goto cleanup;
9258 }
9259
9260 4 size -= scheme_str_len + 1;
9261
9262
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,
9263 size)) < 0) {
9264 ✗ ret = value_str_len;
9265 ✗ goto cleanup;
9266 }
9267
9268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
9269 // in case of no trailing null, box is not valid.
9270 ✗ ret = AVERROR_INVALIDDATA;
9271 ✗ goto cleanup;
9272 }
9273
9274 4 av_log(ctx, AV_LOG_TRACE,
9275 "%s stream %d KindBox(scheme: %s, value: %s)\n",
9276 4 av_get_media_type_string(st->codecpar->codec_type),
9277 st->index,
9278 scheme_buf.str, value_buf.str);
9279
9280
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++) {
9281 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
9282
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
9283 ✗ continue;
9284
9285
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
9286 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
9287
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
9288 16 continue;
9289
9290 4 st->disposition |= value_map.disposition;
9291 }
9292 }
9293
9294 4 ret = 0;
9295
9296 4 cleanup:
9297
9298 4 av_bprint_finalize(&scheme_buf, NULL);
9299 4 av_bprint_finalize(&value_buf, NULL);
9300
9301 4 return ret;
9302 }
9303
9304 ✗ static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9305 {
9306 AVStream *st;
9307 ✗ AVChannelLayout ch_layout = { 0 };
9308 int ret, i, version, type;
9309 int ambisonic_order, channel_order, normalization, channel_count;
9310 int ambi_channels, non_diegetic_channels;
9311
9312 ✗ if (c->fc->nb_streams < 1)
9313 ✗ return 0;
9314
9315 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
9316
9317 ✗ if (atom.size < 16) {
9318 ✗ av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
9319 ✗ return AVERROR_INVALIDDATA;
9320 }
9321
9322 ✗ version = avio_r8(pb);
9323 ✗ if (version) {
9324 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
9325 ✗ return 0;
9326 }
9327
9328 ✗ type = avio_r8(pb);
9329 ✗ if (type & 0x7f) {
9330 ✗ av_log(c->fc, AV_LOG_WARNING,
9331 "Unsupported ambisonic type %d\n", type & 0x7f);
9332 ✗ return 0;
9333 }
9334 ✗ non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
9335
9336 ✗ ambisonic_order = avio_rb32(pb);
9337
9338 ✗ channel_order = avio_r8(pb);
9339 ✗ if (channel_order) {
9340 ✗ av_log(c->fc, AV_LOG_WARNING,
9341 "Unsupported channel_order %d\n", channel_order);
9342 ✗ return 0;
9343 }
9344
9345 ✗ normalization = avio_r8(pb);
9346 ✗ if (normalization) {
9347 ✗ av_log(c->fc, AV_LOG_WARNING,
9348 "Unsupported normalization %d\n", normalization);
9349 ✗ return 0;
9350 }
9351
9352 ✗ channel_count = avio_rb32(pb);
9353 ✗ if (ambisonic_order < 0 || ambisonic_order > 31 ||
9354 ✗ channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
9355 non_diegetic_channels)) {
9356 ✗ av_log(c->fc, AV_LOG_ERROR,
9357 "Invalid number of channels (%d / %d)\n",
9358 channel_count, ambisonic_order);
9359 ✗ return 0;
9360 }
9361 ✗ ambi_channels = channel_count - non_diegetic_channels;
9362
9363 ✗ ret = av_channel_layout_custom_init(&ch_layout, channel_count);
9364 ✗ if (ret < 0)
9365 ✗ return 0;
9366
9367 ✗ for (i = 0; i < channel_count; i++) {
9368 ✗ unsigned channel = avio_rb32(pb);
9369
9370 ✗ if (channel >= channel_count) {
9371 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
9372 channel, ambisonic_order);
9373 ✗ av_channel_layout_uninit(&ch_layout);
9374 ✗ return 0;
9375 }
9376 ✗ if (channel >= ambi_channels)
9377 ✗ ch_layout.u.map[i].id = channel - ambi_channels;
9378 else
9379 ✗ ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
9380 }
9381
9382 ✗ ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
9383 ✗ if (ret < 0) {
9384 ✗ av_channel_layout_uninit(&ch_layout);
9385 ✗ return 0;
9386 }
9387
9388 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
9389 ✗ st->codecpar->ch_layout = ch_layout;
9390
9391 ✗ return 0;
9392 }
9393
9394 ✗ static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9395 {
9396 AVStream *st;
9397 int version;
9398
9399 ✗ if (c->fc->nb_streams < 1)
9400 ✗ return 0;
9401
9402 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
9403
9404 ✗ if (atom.size < 5) {
9405 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
9406 ✗ return AVERROR_INVALIDDATA;
9407 }
9408
9409 ✗ version = avio_r8(pb);
9410 ✗ if (version) {
9411 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
9412 ✗ return 0;
9413 }
9414
9415 ✗ st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
9416
9417 ✗ return 0;
9418 }
9419
9420 408 static int rb_size(AVIOContext *pb, int64_t *value, int size)
9421 {
9422
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 320 times.
408 if (size == 0)
9423 88 *value = 0;
9424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 320 times.
320 else if (size == 1)
9425 ✗ *value = avio_r8(pb);
9426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 320 times.
320 else if (size == 2)
9427 ✗ *value = avio_rb16(pb);
9428
1/2
✓ Branch 0 taken 320 times.
✗ Branch 1 not taken.
320 else if (size == 4)
9429 320 *value = avio_rb32(pb);
9430 ✗ else if (size == 8) {
9431 ✗ *value = avio_rb64(pb);
9432 ✗ if (*value < 0)
9433 ✗ return -1;
9434 } else
9435 ✗ return -1;
9436 408 return size;
9437 }
9438
9439 29 static int mov_read_auxc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9440 {
9441 AVBPrint aux_type;
9442 HEIFItem *item;
9443
9444 29 avio_r8(pb); /* version */
9445 29 avio_rb24(pb); /* flags */
9446
9447 29 av_bprint_init(&aux_type, 0, AV_BPRINT_SIZE_AUTOMATIC);
9448 29 ff_read_string_to_bprint_overwrite(pb, &aux_type, atom.size - 4);
9449
9450 29 av_log(c->fc, AV_LOG_TRACE, "auxC: item_id %d, aux_type %s\n",
9451 c->cur_item_id, aux_type.str);
9452
9453 29 item = get_heif_item(c, c->cur_item_id);
9454
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (item) {
9455
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 27 times.
29 if ((av_stristr(aux_type.str, "hdrgainmap")))
9456 2 item->is_gainmap = 1;
9457
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 1 times.
27 else if (strstr(aux_type.str, "urn:mpeg:hevc:2015:auxid:1") ||
9458
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 strstr(aux_type.str, "urn:mpeg:mpegB:cicp:systems:auxiliary:alpha"))
9459 27 item->is_alpha = 1;
9460 }
9461 29 return 0;
9462 }
9463
9464 24 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9465 {
9466 24 avio_rb32(pb); // version & flags.
9467 24 c->primary_item_id = avio_rb16(pb);
9468 24 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
9469 24 return atom.size;
9470 }
9471
9472 11 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9473 {
9474 11 c->idat_offset = avio_tell(pb);
9475 11 return 0;
9476 }
9477
9478 24 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9479 {
9480 HEIFItem **heif_item;
9481 int version, offset_size, length_size, base_offset_size, index_size;
9482 int item_count, extent_count;
9483 int64_t base_offset, extent_offset, extent_length;
9484 uint8_t value;
9485
9486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (c->found_iloc) {
9487 ✗ av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
9488 ✗ return 0;
9489 }
9490
9491 24 version = avio_r8(pb);
9492 24 avio_rb24(pb); // flags.
9493
9494 24 value = avio_r8(pb);
9495 24 offset_size = (value >> 4) & 0xF;
9496 24 length_size = value & 0xF;
9497 24 value = avio_r8(pb);
9498 24 base_offset_size = (value >> 4) & 0xF;
9499
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 11 times.
24 index_size = !version ? 0 : (value & 0xF);
9500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (index_size) {
9501 ✗ avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
9502 ✗ return AVERROR_PATCHWELCOME;
9503 }
9504
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9505
9506
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (item_count > atom.size)
9507 ✗ return AVERROR_INVALIDDATA;
9508
9509 24 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
9510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!heif_item)
9511 ✗ return AVERROR(ENOMEM);
9512 24 c->heif_item = heif_item;
9513
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2 times.
24 if (item_count > c->nb_heif_item)
9514 22 memset(&c->heif_item[c->nb_heif_item], 0,
9515 22 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
9516 24 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
9517
9518 24 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
9519
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 24 times.
160 for (int i = 0; i < item_count; i++) {
9520 136 HEIFItem *item = NULL;
9521
1/2
✓ Branch 0 taken 136 times.
✗ Branch 1 not taken.
136 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9522
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 71 times.
136 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
9523 int j;
9524
9525
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 136 times.
136 if (avio_feof(pb))
9526 ✗ return AVERROR_INVALIDDATA;
9527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (offset_type > 1) {
9528 ✗ avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
9529 ✗ return AVERROR_PATCHWELCOME;
9530 }
9531
9532 136 avio_rb16(pb); // data_reference_index.
9533
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 136 times.
136 if (rb_size(pb, &base_offset, base_offset_size) < 0)
9534 ✗ return AVERROR_INVALIDDATA;
9535 136 extent_count = avio_rb16(pb);
9536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (extent_count > 1) {
9537 // For still AVIF images, we only support one extent item.
9538 ✗ avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
9539 ✗ return AVERROR_PATCHWELCOME;
9540 }
9541
9542
2/4
✓ Branch 1 taken 136 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 136 times.
✗ Branch 4 not taken.
272 if (rb_size(pb, &extent_offset, offset_size) < 0 ||
9543 136 rb_size(pb, &extent_length, length_size) < 0 ||
9544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 base_offset > INT64_MAX - extent_offset)
9545 ✗ return AVERROR_INVALIDDATA;
9546
9547
1/2
✓ Branch 0 taken 1066 times.
✗ Branch 1 not taken.
1066 for (j = 0; j < c->nb_heif_item; j++) {
9548 1066 item = c->heif_item[j];
9549
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 950 times.
1066 if (!item)
9550 116 item = c->heif_item[j] = av_mallocz(sizeof(*item));
9551
2/2
✓ Branch 0 taken 930 times.
✓ Branch 1 taken 20 times.
950 else if (item->item_id != item_id)
9552 930 continue;
9553 136 break;
9554 }
9555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (!item)
9556 ✗ return AVERROR(ENOMEM);
9557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (j == c->nb_heif_item)
9558 ✗ return AVERROR_INVALIDDATA;
9559
9560 136 item->item_id = item_id;
9561
9562
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 123 times.
136 if (offset_type == 1)
9563 13 item->is_idat_relative = 1;
9564 136 item->extent_length = extent_length;
9565 136 item->extent_offset = base_offset + extent_offset;
9566 136 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, item->item_id %d, offset_type %d, "
9567 "extent_offset %"PRId64", extent_length %"PRId64"\n",
9568 i, item->item_id, offset_type, item->extent_offset, item->extent_length);
9569 }
9570
9571 24 c->found_iloc = 1;
9572 24 return atom.size;
9573 }
9574
9575 136 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9576 {
9577 136 HEIFItem *item = NULL;
9578 AVBPrint item_name;
9579 136 int64_t size = atom.size;
9580 uint32_t item_type;
9581 int item_id;
9582 int i, version, flags, ret;
9583
9584 136 version = avio_r8(pb);
9585 136 flags = avio_rb24(pb);
9586 136 size -= 4;
9587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (size < 0)
9588 ✗ return AVERROR_INVALIDDATA;
9589
9590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (version < 2) {
9591 ✗ avpriv_report_missing_feature(c->fc, "infe version < 2");
9592 ✗ avio_skip(pb, size);
9593 ✗ return 1;
9594 }
9595
9596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
9597 136 avio_rb16(pb); // item_protection_index
9598 136 item_type = avio_rl32(pb);
9599 136 size -= 8;
9600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (size < 1)
9601 ✗ return AVERROR_INVALIDDATA;
9602
9603 136 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
9604 136 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
9605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (ret < 0) {
9606 ✗ av_bprint_finalize(&item_name, NULL);
9607 ✗ return ret;
9608 }
9609
9610 136 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
9611 136 item_id, av_fourcc2str(item_type), item_name.str);
9612
9613 136 size -= ret + 1;
9614
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 130 times.
136 if (size > 0)
9615 6 avio_skip(pb, size);
9616
9617
1/2
✓ Branch 0 taken 1066 times.
✗ Branch 1 not taken.
1066 for (i = 0; i < c->nb_heif_item; i++) {
9618 1066 item = c->heif_item[i];
9619
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1046 times.
1066 if (!item)
9620 20 item = c->heif_item[i] = av_mallocz(sizeof(*item));
9621
2/2
✓ Branch 0 taken 930 times.
✓ Branch 1 taken 116 times.
1046 else if (item->item_id != item_id)
9622 930 continue;
9623 136 break;
9624 }
9625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (!item) {
9626 ✗ av_bprint_finalize(&item_name, NULL);
9627 ✗ return AVERROR(ENOMEM);
9628 }
9629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (i == c->nb_heif_item) {
9630 ✗ av_bprint_finalize(&item_name, NULL);
9631 ✗ return AVERROR_INVALIDDATA;
9632 }
9633
9634 136 av_freep(&item->name);
9635
2/2
✓ Branch 0 taken 113 times.
✓ Branch 1 taken 23 times.
136 av_bprint_finalize(&item_name, ret ? &item->name : NULL);
9636 136 item->item_id = item_id;
9637 136 item->type = item_type;
9638 136 item->flags = flags;
9639
9640
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 30 times.
136 switch (item_type) {
9641 106 case MKTAG('a','v','0','1'):
9642 case MKTAG('j','p','e','g'):
9643 case MKTAG('h','v','c','1'):
9644 106 ret = heif_add_stream(c, item);
9645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
106 if (ret < 0)
9646 ✗ return ret;
9647 106 break;
9648 }
9649
9650 136 return 0;
9651 }
9652
9653 24 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9654 {
9655 HEIFItem **heif_item;
9656 int entry_count;
9657 24 int version, got_stream = 0, ret, i;
9658
9659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (c->found_iinf) {
9660 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
9661 ✗ return 0;
9662 }
9663
9664 24 version = avio_r8(pb);
9665 24 avio_rb24(pb); // flags.
9666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
9667
9668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (entry_count > atom.size)
9669 ✗ return AVERROR_INVALIDDATA;
9670
9671 /* account for the version/flags/entry_count fields already consumed,
9672 * so the per-entry loop below can bound each infe box by what is
9673 * actually left in this iinf box, the same way mov_read_iprp() bounds
9674 * ipco/ipma entries by the remaining iprp size. */
9675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 atom.size -= version ? 8 : 6;
9676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (atom.size < 0)
9677 ✗ return AVERROR_INVALIDDATA;
9678
9679 24 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
9680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!heif_item)
9681 ✗ return AVERROR(ENOMEM);
9682 24 c->heif_item = heif_item;
9683
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 if (entry_count > c->nb_heif_item)
9684 2 memset(&c->heif_item[c->nb_heif_item], 0,
9685 2 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
9686 24 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
9687
9688
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 24 times.
160 for (i = 0; i < entry_count; i++) {
9689 MOVAtom infe;
9690
9691 136 infe.size = avio_rb32(pb);
9692 136 infe.type = avio_rl32(pb);
9693
3/6
✓ Branch 1 taken 136 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 136 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 136 times.
✗ Branch 6 not taken.
136 if (avio_feof(pb) || infe.size < 8 || infe.size > atom.size ||
9694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 infe.type != MKTAG('i','n','f','e')) {
9695 ✗ ret = AVERROR_INVALIDDATA;
9696 ✗ goto fail;
9697 }
9698
9699 136 atom.size -= infe.size;
9700 136 infe.size -= 8;
9701
9702 136 ret = mov_read_infe(c, pb, infe);
9703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (ret < 0)
9704 ✗ goto fail;
9705
1/2
✓ Branch 0 taken 136 times.
✗ Branch 1 not taken.
136 if (!ret)
9706 136 got_stream = 1;
9707 }
9708
9709 24 c->found_iinf = got_stream;
9710 24 return 0;
9711 ✗ fail:
9712 ✗ for (; i >= 0; i--) {
9713 ✗ HEIFItem *item = c->heif_item[i];
9714
9715 ✗ if (!item)
9716 ✗ continue;
9717
9718 ✗ av_freep(&item->name);
9719 }
9720 ✗ return ret;
9721 }
9722
9723 4 static int mov_read_iref_dimg_tmap(MOVContext *c, AVIOContext *pb,
9724 HEIFItem *item, int version, int entries)
9725 {
9726 4 HEIFGroup *tmap = av_realloc_array(c->heif_group, c->nb_heif_group + 1U,
9727 sizeof(*c->heif_group));
9728 int ret;
9729
9730
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tmap)
9731 ✗ return AVERROR(ENOMEM);
9732 4 c->heif_group = tmap;
9733
9734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (entries != 2) {
9735 ✗ avpriv_report_missing_feature(c->fc, "Derived image item of type %s with an "
9736 "item reference count other than 2",
9737 ✗ av_fourcc2str(item->type));
9738 ✗ return 0;
9739 }
9740
9741 4 tmap = &tmap[c->nb_heif_group];
9742
9743 4 tmap->item_idx_list = NULL; // Not needed
9744 4 tmap->item_id_list = av_malloc_array(entries, sizeof(*tmap->item_id_list));
9745 4 tmap->item_list = av_calloc(entries, sizeof(*tmap->item_list));
9746
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (!tmap->item_id_list || !tmap->item_list) {
9747 ✗ ret = AVERROR(ENOMEM);
9748 ✗ goto fail;
9749 }
9750
9751 /* 'to' item ids */
9752
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < entries; i++) {
9753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 tmap->item_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
9754
9755
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_feof(pb)) {
9756 ✗ ret = AVERROR_INVALIDDATA;
9757 ✗ goto fail;
9758 }
9759 }
9760
9761 4 tmap->nb_items = entries;
9762 4 tmap->item = item;
9763 4 ++c->nb_heif_group;
9764
9765 4 return 0;
9766 ✗ fail:
9767 ✗ av_freep(&tmap->item_id_list);
9768 ✗ av_freep(&tmap->item_list);
9769
9770 ✗ return ret;
9771 }
9772
9773 15 static int mov_read_iref_dimg_grid(MOVContext *c, AVIOContext *pb,
9774 HEIFItem *item, int version, int entries)
9775 {
9776 15 HEIFGroup *grid = av_realloc_array(c->heif_group, c->nb_heif_group + 1U,
9777 sizeof(*c->heif_group));
9778 int ret;
9779
9780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!grid)
9781 ✗ return AVERROR(ENOMEM);
9782 15 c->heif_group = grid;
9783 15 grid = &grid[c->nb_heif_group];
9784
9785 15 grid->item_id_list = av_malloc_array(entries, sizeof(*grid->item_id_list));
9786 15 grid->item_idx_list = av_calloc(entries, sizeof(*grid->item_idx_list));
9787 15 grid->item_list = av_calloc(entries, sizeof(*grid->item_list));
9788
3/6
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15 times.
15 if (!grid->item_id_list || !grid->item_list || !grid->item_idx_list) {
9789 ✗ ret = AVERROR(ENOMEM);
9790 ✗ goto fail;
9791 }
9792 /* 'to' item ids */
9793
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 15 times.
99 for (int i = 0; i < entries; i++) {
9794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 grid->item_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
9795
9796
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
84 if (avio_feof(pb)) {
9797 ✗ ret = AVERROR_INVALIDDATA;
9798 ✗ goto fail;
9799 }
9800 }
9801
9802 15 grid->nb_items = entries;
9803 15 grid->item = item;
9804 15 ++c->nb_heif_group;
9805
9806 15 return 0;
9807 ✗ fail:
9808 ✗ av_freep(&grid->item_id_list);
9809 ✗ av_freep(&grid->item_idx_list);
9810 ✗ av_freep(&grid->item_list);
9811
9812 ✗ return ret;
9813 }
9814
9815 19 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
9816 {
9817 19 HEIFItem *item = NULL;
9818 int entries;
9819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9820 int ret;
9821
9822
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 19 times.
27 for (int i = 0; i < c->nb_heif_group; i++) {
9823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (c->heif_group[i].item->item_id == from_item_id) {
9824 ✗ av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
9825 "referencing the same Derived Image item\n");
9826 ✗ return AVERROR_INVALIDDATA;
9827 }
9828 }
9829
1/2
✓ Branch 0 taken 143 times.
✗ Branch 1 not taken.
143 for (int i = 0; i < c->nb_heif_item; i++) {
9830
3/4
✓ Branch 0 taken 143 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 124 times.
✓ Branch 3 taken 19 times.
143 if (!c->heif_item[i] || c->heif_item[i]->item_id != from_item_id)
9831 124 continue;
9832 19 item = c->heif_item[i];
9833
9834
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 switch (item->type) {
9835 19 case MKTAG('g','r','i','d'):
9836 case MKTAG('i','o','v','l'):
9837 case MKTAG('t','m','a','p'):
9838 19 break;
9839 ✗ default:
9840 ✗ avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
9841 ✗ av_fourcc2str(item->type));
9842 ✗ return 0;
9843 }
9844 19 break;
9845 }
9846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!item) {
9847 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing derived image information\n");
9848 ✗ return AVERROR_INVALIDDATA;
9849 }
9850
9851 19 entries = avio_rb16(pb);
9852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!entries) {
9853 ✗ av_log(c->fc, AV_LOG_ERROR,
9854 "Derived image item references no input images\n");
9855 ✗ return AVERROR_INVALIDDATA;
9856 }
9857
9858 19 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
9859 from_item_id, entries);
9860
9861
2/3
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
19 switch (item->type) {
9862 15 case MKTAG('g','r','i','d'):
9863 case MKTAG('i','o','v','l'):
9864 15 ret = mov_read_iref_dimg_grid(c, pb, item, version, entries);
9865 15 break;
9866 4 case MKTAG('t','m','a','p'):
9867 4 ret = mov_read_iref_dimg_tmap(c, pb, item, version, entries);
9868 4 break;
9869 ✗ default:
9870 ✗ av_unreachable("item->type should have been checked above");
9871 }
9872
9873 19 return ret;
9874 }
9875
9876 10 static int mov_read_iref_cdsc(MOVContext *c, AVIOContext *pb, uint32_t type,
9877 int version, uint32_t size)
9878 {
9879 10 HEIFItem *from_item = NULL;
9880 int entries;
9881
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 int item_id_size = version ? 4 : 2;
9882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9883 10 const HEIFItemRef ref = { type, from_item_id };
9884
9885 10 from_item = get_heif_item(c, from_item_id);
9886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!from_item) {
9887 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing stream referenced by %s iref\n",
9888 ✗ av_fourcc2str(type));
9889 ✗ return AVERROR_INVALIDDATA;
9890 }
9891
9892 10 entries = avio_rb16(pb);
9893
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) {
9894 ✗ av_log(c->fc, AV_LOG_ERROR, "iref %s entry count %d exceeds the sub-box size\n",
9895 ✗ av_fourcc2str(type), entries);
9896 ✗ return AVERROR_INVALIDDATA;
9897 }
9898 /* 'to' item ids */
9899
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < entries; i++) {
9900
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));
9901
9902
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (avio_feof(pb))
9903 ✗ return AVERROR_INVALIDDATA;
9904
9905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!item) {
9906 ✗ av_log(c->fc, AV_LOG_WARNING, "Missing stream referenced by %s item\n",
9907 ✗ av_fourcc2str(type));
9908 ✗ continue;
9909 }
9910
9911
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,
9912 sizeof(*item->iref_from_list), (const uint8_t *)&ref))
9913 ✗ return AVERROR(ENOMEM);
9914 }
9915
9916 10 av_log(c->fc, AV_LOG_TRACE, "%s: from_item_id %d, entries %d\n",
9917 10 av_fourcc2str(type), from_item_id, entries);
9918
9919 10 return 0;
9920 }
9921
9922 12 static int mov_read_iref_auxl(MOVContext *c, AVIOContext *pb, uint32_t type,
9923 int version, uint32_t size)
9924 {
9925 12 HEIFItem *from_item = NULL;
9926 int entries;
9927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 unsigned from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9928
9929 12 from_item = get_heif_item(c, from_item_id);
9930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!from_item) {
9931 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing item referenced by %s iref\n",
9932 ✗ av_fourcc2str(type));
9933 ✗ return AVERROR_INVALIDDATA;
9934 }
9935
9936 12 entries = avio_rb16(pb);
9937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (entries != 1) {
9938 ✗ avpriv_report_missing_feature(c->fc, "%s iref with an item reference "
9939 "count other than 1",
9940 ✗ av_fourcc2str(type));
9941 ✗ return 0;
9942 }
9943
9944 /* 'to' item ids */
9945
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < entries; i++) {
9946
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 unsigned to_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9947 12 const HEIFItemRef ref = { type, to_item_id };
9948 12 HEIFItem *item = get_heif_item(c, to_item_id);
9949
9950
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 if (avio_feof(pb))
9951 ✗ return AVERROR_INVALIDDATA;
9952
9953
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!item) {
9954 ✗ av_log(c->fc, AV_LOG_WARNING, "Missing item referenced by %s iref\n",
9955 ✗ av_fourcc2str(type));
9956 ✗ continue;
9957 }
9958
9959
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 if (!av_dynarray2_add((void **)&from_item->iref_to_list, &from_item->nb_iref_to_list,
9960 sizeof(*from_item->iref_to_list), (const uint8_t *)&ref))
9961 ✗ return AVERROR(ENOMEM);
9962 }
9963
9964 12 av_log(c->fc, AV_LOG_TRACE, "%s: from_item_id %d, entries %d\n",
9965 12 av_fourcc2str(type), from_item_id, entries);
9966
9967 12 return 0;
9968 }
9969
9970 19 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9971 {
9972 19 int version = avio_r8(pb);
9973 int ret;
9974
9975 19 avio_rb24(pb); // flags
9976 19 atom.size -= 4;
9977
9978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (version > 1) {
9979 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
9980 ✗ return 0;
9981 }
9982
9983
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 19 times.
60 while (atom.size) {
9984 41 int64_t next = avio_tell(pb);
9985 41 uint32_t type, size = avio_rb32(pb);
9986
9987
3/6
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 41 times.
41 if (size < 14 || size > atom.size || next > INT64_MAX - size)
9988 ✗ return AVERROR_INVALIDDATA;
9989
9990 41 next += size;
9991 41 type = avio_rl32(pb);
9992
3/4
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
41 switch (type) {
9993 19 case MKTAG('d','i','m','g'):
9994 19 ret = mov_read_iref_dimg(c, pb, version);
9995
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
9996 ✗ return ret;
9997 41 break;
9998 10 case MKTAG('c','d','s','c'):
9999 10 ret = mov_read_iref_cdsc(c, pb, type, version, size - 8);
10000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
10001 ✗ return ret;
10002 10 break;
10003 12 case MKTAG('a','u','x','l'):
10004 case MKTAG('t','h','m','b'):
10005 12 ret = mov_read_iref_auxl(c, pb, type, version, size - 8);
10006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
10007 ✗ return ret;
10008 12 break;
10009 ✗ default:
10010 ✗ av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
10011 ✗ av_fourcc2str(type), size);
10012 }
10013
10014 41 atom.size -= size;
10015 41 avio_seek(pb, next, SEEK_SET);
10016 }
10017 19 return 0;
10018 }
10019
10020 125 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10021 {
10022 HEIFItem *item;
10023 uint32_t width, height;
10024
10025 125 avio_r8(pb); /* version */
10026 125 avio_rb24(pb); /* flags */
10027 125 width = avio_rb32(pb);
10028 125 height = avio_rb32(pb);
10029
10030 125 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %"PRIu32", height %"PRIu32"\n",
10031 c->cur_item_id, width, height);
10032
10033
4/8
✓ Branch 0 taken 125 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 125 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 125 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 125 times.
125 if (!width || !height || width > INT_MAX || height > INT_MAX) {
10034 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid ispe dimensions %"PRIu32"x%"PRIu32"\n",
10035 width, height);
10036 ✗ return AVERROR_INVALIDDATA;
10037 }
10038
10039 125 item = get_heif_item(c, c->cur_item_id);
10040
1/2
✓ Branch 0 taken 125 times.
✗ Branch 1 not taken.
125 if (item) {
10041 125 item->width = width;
10042 125 item->height = height;
10043 }
10044
10045 125 return 0;
10046 }
10047
10048 10 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10049 {
10050 HEIFItem *item;
10051 int angle;
10052
10053 10 angle = avio_r8(pb) & 0x3;
10054
10055 10 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
10056 c->cur_item_id, angle);
10057
10058 10 item = get_heif_item(c, c->cur_item_id);
10059
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (item) {
10060 // angle * 90 specifies the angle (in anti-clockwise direction)
10061 // in units of degrees.
10062 10 item->rotation = angle * 90;
10063 }
10064
10065 10 return 0;
10066 }
10067
10068 6 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10069 {
10070 HEIFItem *item;
10071 int axis;
10072
10073 6 axis = avio_r8(pb) & 0x1;
10074
10075 6 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
10076 c->cur_item_id, axis);
10077
10078 6 item = get_heif_item(c, c->cur_item_id);
10079
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
10080 6 item->hflip = axis;
10081 6 item->vflip = !axis;
10082 }
10083
10084 6 return 0;
10085 }
10086
10087 typedef struct MOVAtomExt {
10088 uint32_t type;
10089 int64_t size;
10090 uint8_t *data;
10091 } MOVAtomExt;
10092
10093 24 static int mov_read_ipco(MOVContext *c, AVIOContext *pb, MOVAtom atom,
10094 MOVAtomExt **atoms, int *nb_atoms)
10095 {
10096
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 24 times.
159 while (atom.size >= 8) {
10097 135 MOVAtomExt *ref = av_dynarray2_add((void**)atoms, nb_atoms, sizeof(MOVAtomExt), NULL);
10098
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 135 times.
135 if (!ref)
10099 ✗ return AVERROR(ENOMEM);
10100
10101 135 ref->data = NULL;
10102 135 ref->size = avio_rb32(pb);
10103 135 ref->type = avio_rl32(pb);
10104
2/4
✓ Branch 0 taken 135 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 135 times.
✗ Branch 3 not taken.
135 if (ref->size > atom.size || ref->size < 8)
10105 break;
10106 135 ref->data = av_malloc(ref->size);
10107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 135 times.
135 if (!ref->data)
10108 ✗ return AVERROR_INVALIDDATA;
10109
10110 135 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", *nb_atoms,
10111 135 av_fourcc2str(ref->type));
10112 135 AV_WB32(ref->data, ref->size);
10113 135 AV_WL32(ref->data + 4, ref->type);
10114
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 135 times.
135 if (avio_read(pb, ref->data + 8, ref->size - 8) != ref->size - 8) {
10115 ✗ return AVERROR_INVALIDDATA;
10116 }
10117 135 atom.size -= ref->size;
10118 }
10119
10120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (atom.size)
10121 ✗ return AVERROR_INVALIDDATA;
10122
10123 24 return 0;
10124 }
10125
10126 24 static int mov_read_ipma(MOVContext *c, AVIOContext *pb, MOVAtom atom,
10127 MOVAtomExt *atoms, int nb_atoms)
10128 {
10129 unsigned count;
10130 int version, flags;
10131 int ret;
10132
10133 24 version = avio_r8(pb);
10134 24 flags = avio_rb24(pb);
10135 24 count = avio_rb32(pb);
10136 24 atom.size -= 8;
10137
10138
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 24 times.
149 for (int i = 0; i < count; i++) {
10139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
10140 125 int assoc_count = avio_r8(pb);
10141
10142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 atom.size -= (version ? 5 : 3) + assoc_count * (1 + (flags & 1));
10143
2/4
✓ Branch 1 taken 125 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 125 times.
125 if (avio_feof(pb) || atom.size < 0)
10144 ✗ return AVERROR_INVALIDDATA;
10145
10146
2/2
✓ Branch 0 taken 403 times.
✓ Branch 1 taken 125 times.
528 for (int j = 0; j < assoc_count; j++) {
10147 FFIOContext b;
10148 MOVAtomExt *ref;
10149 403 int index = avio_r8(pb) & 0x7f;
10150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 403 times.
403 if (flags & 1) {
10151 ✗ index <<= 8;
10152 ✗ index |= avio_r8(pb);
10153 }
10154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 403 times.
403 if (!index)
10155 ✗ continue;
10156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 403 times.
403 if (index > nb_atoms) {
10157 ✗ return AVERROR_INVALIDDATA;
10158 }
10159 403 ref = &atoms[--index];
10160
10161 403 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
10162 403 index + 1, item_id, av_fourcc2str(ref->type));
10163
10164 403 c->cur_item_id = item_id;
10165
10166 403 ffio_init_read_context(&b, ref->data, ref->size);
10167 403 ret = mov_read_default(c, &b.pub,
10168 403 (MOVAtom) { .size = ref->size,
10169 .type = MKTAG('i','p','c','o') });
10170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 403 times.
403 if (ret < 0)
10171 ✗ return ret;
10172 }
10173 }
10174
10175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (atom.size)
10176 ✗ return AVERROR_INVALIDDATA;
10177
10178 24 return 0;
10179 }
10180
10181 24 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10182 {
10183 24 MOVAtomExt *atoms = NULL;
10184 MOVAtom a;
10185 24 int nb_atoms = 0;
10186 int ret;
10187
10188 24 a.size = avio_rb32(pb);
10189 24 a.type = avio_rl32(pb);
10190
10191
3/6
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 24 times.
24 if (a.size <= 8 || a.size > atom.size || a.type != MKTAG('i','p','c','o'))
10192 ✗ return AVERROR_INVALIDDATA;
10193
10194 24 atom.size -= a.size;
10195 24 a.size -= 8;
10196
10197 24 ret = mov_read_ipco(c, pb, a, &atoms, &nb_atoms);
10198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (ret < 0)
10199 ✗ goto fail;
10200
10201 24 a.size = avio_rb32(pb);
10202 24 a.type = avio_rl32(pb);
10203
10204
3/6
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 24 times.
24 if (a.size <= 8 || a.size > atom.size || a.type != MKTAG('i','p','m','a')) {
10205 ✗ ret = AVERROR_INVALIDDATA;
10206 ✗ goto fail;
10207 }
10208
10209 24 a.size -= 8;
10210
10211 24 ret = mov_read_ipma(c, pb, a, atoms, nb_atoms);
10212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (ret < 0)
10213 ✗ goto fail;
10214
10215 24 ret = 0;
10216 24 fail:
10217 24 c->cur_item_id = -1;
10218
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 24 times.
159 for (int i = 0; i < nb_atoms; i++)
10219 135 av_free(atoms[i].data);
10220 24 av_free(atoms);
10221
10222 24 return ret;
10223 }
10224
10225 384 static int mov_read_vmhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10226 {
10227 384 avio_rb32(pb); // version & flags
10228 384 uint16_t graphics_mode = avio_rb16(pb);
10229 // ignored: opcolor[3]
10230
10231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 if (c->fc->nb_streams < 1)
10232 ✗ return 0;
10233 384 AVStream *st = c->fc->streams[c->fc->nb_streams - 1];
10234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
10235 ✗ return 0;
10236
10237
2/4
✓ Branch 0 taken 383 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
384 switch (graphics_mode) {
10238 383 case MOV_GRAPHICS_MODE_COPY:
10239 case MOV_GRAPHICS_MODE_DITHER_COPY:
10240 383 st->codecpar->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
10241 383 break;
10242 ✗ case MOV_GRAPHICS_MODE_STRAIGHT_ALPHA:
10243 ✗ st->codecpar->alpha_mode = AVALPHA_MODE_STRAIGHT;
10244 ✗ break;
10245 ✗ case MOV_GRAPHICS_MODE_PREMUL_BLACK_ALPHA:
10246 ✗ st->codecpar->alpha_mode = AVALPHA_MODE_PREMULTIPLIED;
10247 ✗ break;
10248 1 default:
10249 1 st->codecpar->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
10250 1 av_log(c->fc, AV_LOG_WARNING, "Unhandled graphics mode: 0x%x\n",
10251 graphics_mode);
10252 1 break;
10253 }
10254
10255 384 return 0;
10256 }
10257
10258 5 static int mov_read_mhac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10259 {
10260 5 AVFormatContext *ctx = c->fc;
10261 AVStream *st;
10262 int profile_level_indication, reference_ch_layout, config_length;
10263 5 int ret = 0;
10264
10265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ctx->nb_streams < 1)
10266 ✗ return 0;
10267
10268 5 st = ctx->streams[ctx->nb_streams - 1];
10269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
10270 ✗ return 0;
10271
10272
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_r8(pb) != 1) // ConfigurationVersion
10273 ✗ return 0;
10274
10275 5 profile_level_indication = avio_r8(pb);
10276 5 st->codecpar->profile = (profile_level_indication - 1) / 5;
10277 5 st->codecpar->level = ((profile_level_indication - 1) % 5) + 1;
10278
10279 5 reference_ch_layout = avio_r8(pb);
10280 5 config_length = avio_rb16(pb);
10281
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (config_length)
10282 5 ret = ff_get_extradata(ctx, st->codecpar, pb, config_length);
10283
10284
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (!reference_ch_layout ||
10285
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 reference_ch_layout >= FF_ARRAY_ELEMS(ff_mpa_cicp_channel_layout_masks)) {
10286 ✗ av_log(ctx, AV_LOG_WARNING, "Unknown referenceChannelLayout value: %d\n", reference_ch_layout);
10287 ✗ return ret;
10288 }
10289
10290 5 av_channel_layout_from_mask(&st->codecpar->ch_layout,
10291 5 ff_mpa_cicp_channel_layout_masks[reference_ch_layout]);
10292
10293 5 return ret;
10294 }
10295
10296 static const MOVParseTableEntry mov_default_parse_table[] = {
10297 { MKTAG('A','C','L','R'), mov_read_aclr },
10298 { MKTAG('A','P','R','G'), mov_read_avid },
10299 { MKTAG('A','A','L','P'), mov_read_avid },
10300 { MKTAG('A','R','E','S'), mov_read_ares },
10301 { MKTAG('a','v','s','s'), mov_read_avss },
10302 { MKTAG('a','v','1','C'), mov_read_glbl },
10303 { MKTAG('c','h','p','l'), mov_read_chpl },
10304 { MKTAG('c','o','6','4'), mov_read_stco },
10305 { MKTAG('c','o','l','r'), mov_read_colr },
10306 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
10307 { MKTAG('d','i','n','f'), mov_read_default },
10308 { MKTAG('D','p','x','E'), mov_read_dpxe },
10309 { MKTAG('d','r','e','f'), mov_read_dref },
10310 { MKTAG('e','d','t','s'), mov_read_default },
10311 { MKTAG('e','l','s','t'), mov_read_elst },
10312 { MKTAG('e','n','d','a'), mov_read_enda },
10313 { MKTAG('f','i','e','l'), mov_read_fiel },
10314 { MKTAG('a','d','r','m'), mov_read_adrm },
10315 { MKTAG('f','t','y','p'), mov_read_ftyp },
10316 { MKTAG('g','l','b','l'), mov_read_glbl },
10317 { MKTAG('h','d','l','r'), mov_read_hdlr },
10318 { MKTAG('i','l','s','t'), mov_read_ilst },
10319 { MKTAG('j','p','2','h'), mov_read_jp2h },
10320 { MKTAG('m','d','a','t'), mov_read_mdat },
10321 { MKTAG('m','d','h','d'), mov_read_mdhd },
10322 { MKTAG('m','d','i','a'), mov_read_default },
10323 { MKTAG('m','e','t','a'), mov_read_meta },
10324 { MKTAG('m','i','n','f'), mov_read_default },
10325 { MKTAG('m','o','o','f'), mov_read_moof },
10326 { MKTAG('m','o','o','v'), mov_read_moov },
10327 { MKTAG('m','v','e','x'), mov_read_default },
10328 { MKTAG('m','v','h','d'), mov_read_mvhd },
10329 { MKTAG('S','M','I',' '), mov_read_svq3 },
10330 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
10331 { MKTAG('a','v','c','C'), mov_read_glbl },
10332 { MKTAG('p','a','s','p'), mov_read_pasp },
10333 { MKTAG('c','l','a','p'), mov_read_clap },
10334 { MKTAG('c','d','s','c'), mov_read_cdsc_rndr },
10335 { MKTAG('r','n','d','r'), mov_read_cdsc_rndr },
10336 { MKTAG('s','b','a','s'), mov_read_sbas },
10337 { MKTAG('v','d','e','p'), mov_read_vdep },
10338 { MKTAG('s','i','d','x'), mov_read_sidx },
10339 { MKTAG('s','t','b','l'), mov_read_default },
10340 { MKTAG('s','t','c','o'), mov_read_stco },
10341 { MKTAG('s','t','p','s'), mov_read_stps },
10342 { MKTAG('s','t','r','f'), mov_read_strf },
10343 { MKTAG('s','t','s','c'), mov_read_stsc },
10344 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
10345 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
10346 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
10347 { MKTAG('s','t','t','s'), mov_read_stts },
10348 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
10349 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
10350 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
10351 { MKTAG('t','f','d','t'), mov_read_tfdt },
10352 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
10353 { MKTAG('t','r','a','k'), mov_read_trak },
10354 { MKTAG('t','r','a','f'), mov_read_default },
10355 { MKTAG('t','r','e','f'), mov_read_default },
10356 { MKTAG('t','m','c','d'), mov_read_tmcd },
10357 { MKTAG('c','h','a','p'), mov_read_chap },
10358 { MKTAG('t','r','e','x'), mov_read_trex },
10359 { MKTAG('t','r','u','n'), mov_read_trun },
10360 { MKTAG('u','d','t','a'), mov_read_default },
10361 { MKTAG('w','a','v','e'), mov_read_wave },
10362 { MKTAG('e','s','d','s'), mov_read_esds },
10363 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
10364 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
10365 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
10366 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
10367 { MKTAG('w','f','e','x'), mov_read_wfex },
10368 { MKTAG('c','m','o','v'), mov_read_cmov },
10369 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
10370 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
10371 { MKTAG('d','v','c','1'), mov_read_dvc1 },
10372 { MKTAG('s','g','p','d'), mov_read_sgpd },
10373 { MKTAG('s','b','g','p'), mov_read_sbgp },
10374 { MKTAG('h','v','c','C'), mov_read_glbl },
10375 { MKTAG('v','v','c','C'), mov_read_glbl },
10376 { MKTAG('u','u','i','d'), mov_read_uuid },
10377 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
10378 { MKTAG('f','r','e','e'), mov_read_free },
10379 { MKTAG('-','-','-','-'), mov_read_custom },
10380 { MKTAG('s','i','n','f'), mov_read_default },
10381 { MKTAG('f','r','m','a'), mov_read_frma },
10382 { MKTAG('s','e','n','c'), mov_read_senc },
10383 { MKTAG('s','a','i','z'), mov_read_saiz },
10384 { MKTAG('s','a','i','o'), mov_read_saio },
10385 { MKTAG('p','s','s','h'), mov_read_pssh },
10386 { MKTAG('s','c','h','m'), mov_read_schm },
10387 { MKTAG('s','c','h','i'), mov_read_default },
10388 { MKTAG('t','e','n','c'), mov_read_tenc },
10389 { MKTAG('d','f','L','a'), mov_read_dfla },
10390 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
10391 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
10392 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
10393 { MKTAG('h','f','o','v'), mov_read_hfov },
10394 { MKTAG('d','O','p','s'), mov_read_dops },
10395 { MKTAG('d','m','l','p'), mov_read_dmlp },
10396 { MKTAG('S','m','D','m'), mov_read_smdm },
10397 { MKTAG('C','o','L','L'), mov_read_coll },
10398 { MKTAG('v','p','c','C'), mov_read_vpcc },
10399 { MKTAG('m','d','c','v'), mov_read_mdcv },
10400 { MKTAG('c','l','l','i'), mov_read_clli },
10401 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
10402 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
10403 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
10404 { MKTAG('h','v','c','E'), mov_read_hvce },
10405 { MKTAG('k','i','n','d'), mov_read_kind },
10406 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
10407 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
10408 { MKTAG('i','l','o','c'), mov_read_iloc },
10409 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
10410 { MKTAG('p','i','t','m'), mov_read_pitm },
10411 { MKTAG('e','v','c','C'), mov_read_glbl },
10412 { MKTAG('a','u','x','C'), mov_read_auxc },
10413 { MKTAG('i','d','a','t'), mov_read_idat },
10414 { MKTAG('i','m','i','r'), mov_read_imir },
10415 { MKTAG('i','r','e','f'), mov_read_iref },
10416 { MKTAG('i','s','p','e'), mov_read_ispe },
10417 { MKTAG('i','r','o','t'), mov_read_irot },
10418 { MKTAG('i','p','r','p'), mov_read_iprp },
10419 { MKTAG('i','i','n','f'), mov_read_iinf },
10420 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
10421 { MKTAG('l','h','v','C'), mov_read_lhvc },
10422 { MKTAG('l','v','c','C'), mov_read_glbl },
10423 { MKTAG('a','p','v','C'), mov_read_glbl },
10424 #if CONFIG_IAMFDEC
10425 { MKTAG('i','a','c','b'), mov_read_iacb },
10426 #endif
10427 { MKTAG('s','r','a','t'), mov_read_srat },
10428 { MKTAG('v','m','h','d'), mov_read_vmhd },
10429 { MKTAG('m','h','a','C'), mov_read_mhac },
10430 { 0, NULL }
10431 };
10432
10433 9708 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10434 {
10435 9708 int64_t total_size = 0;
10436 MOVAtom a;
10437 int i;
10438
10439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9708 times.
9708 if (c->atom_depth > 10) {
10440 ✗ av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
10441 ✗ return AVERROR_INVALIDDATA;
10442 }
10443 9708 c->atom_depth ++;
10444
10445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9708 times.
9708 if (atom.size < 0)
10446 ✗ atom.size = INT64_MAX;
10447
2/2
✓ Branch 0 taken 27555 times.
✓ Branch 1 taken 9048 times.
36603 while (total_size <= atom.size - 8) {
10448 27555 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
10449 27555 a.size = avio_rb32(pb);
10450 27555 a.type = avio_rl32(pb);
10451
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 27547 times.
27555 if (avio_feof(pb))
10452 8 break;
10453
3/4
✓ Branch 0 taken 273 times.
✓ Branch 1 taken 27274 times.
✓ Branch 2 taken 273 times.
✗ Branch 3 not taken.
27547 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
10454
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27547 times.
27547 a.type == MKTAG('h','o','o','v')) &&
10455 ✗ a.size >= 8 &&
10456 ✗ c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
10457 uint32_t type;
10458 ✗ avio_skip(pb, 4);
10459 ✗ type = avio_rl32(pb);
10460 ✗ if (avio_feof(pb))
10461 ✗ break;
10462 ✗ avio_seek(pb, -8, SEEK_CUR);
10463 ✗ if (type == MKTAG('m','v','h','d') ||
10464 type == MKTAG('c','m','o','v')) {
10465 ✗ av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
10466 ✗ a.type = MKTAG('m','o','o','v');
10467 }
10468 }
10469
2/2
✓ Branch 0 taken 23834 times.
✓ Branch 1 taken 3713 times.
27547 if (atom.type != MKTAG('r','o','o','t') &&
10470
2/2
✓ Branch 0 taken 21826 times.
✓ Branch 1 taken 2008 times.
23834 atom.type != MKTAG('m','o','o','v')) {
10471
1/2
✓ Branch 0 taken 21826 times.
✗ Branch 1 not taken.
21826 if (a.type == MKTAG('t','r','a','k') ||
10472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21826 times.
21826 a.type == MKTAG('m','d','a','t')) {
10473 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
10474 ✗ avio_skip(pb, -8);
10475 ✗ c->atom_depth --;
10476 652 return 0;
10477 }
10478 }
10479 27547 total_size += 8;
10480
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 27518 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
27547 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
10481 29 a.size = avio_rb64(pb) - 8;
10482 29 total_size += 8;
10483 }
10484 27547 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
10485 27547 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
10486
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 27542 times.
27547 if (a.size == 0) {
10487 5 a.size = atom.size - total_size + 8;
10488 }
10489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27547 times.
27547 if (a.size < 0)
10490 ✗ break;
10491 27547 a.size -= 8;
10492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27547 times.
27547 if (a.size < 0)
10493 ✗ break;
10494 27547 a.size = FFMIN(a.size, atom.size - total_size);
10495
10496
2/2
✓ Branch 0 taken 1346745 times.
✓ Branch 1 taken 2389 times.
1349134 for (i = 0; mov_default_parse_table[i].type; i++)
10497
2/2
✓ Branch 0 taken 25158 times.
✓ Branch 1 taken 1321587 times.
1346745 if (mov_default_parse_table[i].type == a.type) {
10498 25158 parse = mov_default_parse_table[i].parse;
10499 25158 break;
10500 }
10501
10502 // container is user data
10503
4/4
✓ Branch 0 taken 2389 times.
✓ Branch 1 taken 25158 times.
✓ Branch 2 taken 2159 times.
✓ Branch 3 taken 230 times.
27547 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
10504
2/2
✓ Branch 0 taken 473 times.
✓ Branch 1 taken 1686 times.
2159 atom.type == MKTAG('i','l','s','t')))
10505 703 parse = mov_read_udta_string;
10506
10507 // Supports parsing the QuickTime Metadata Keys.
10508 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
10509
4/4
✓ Branch 0 taken 1686 times.
✓ Branch 1 taken 25861 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 1670 times.
27547 if (!parse && c->found_hdlr_mdta &&
10510
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 atom.type == MKTAG('m','e','t','a') &&
10511
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 a.type == MKTAG('k','e','y','s') &&
10512
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 c->meta_keys_count == 0) {
10513 16 parse = mov_read_keys;
10514 }
10515
10516
2/2
✓ Branch 0 taken 1670 times.
✓ Branch 1 taken 25877 times.
27547 if (!parse) { /* skip leaf atoms data */
10517 1670 avio_skip(pb, a.size);
10518 } else {
10519 25877 int64_t start_pos = avio_tell(pb);
10520 int64_t left;
10521 25877 int err = parse(c, pb, a);
10522
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 25859 times.
25877 if (err < 0) {
10523 18 c->atom_depth --;
10524 18 return err;
10525 }
10526
5/6
✓ Branch 0 taken 4989 times.
✓ Branch 1 taken 20870 times.
✓ Branch 2 taken 3503 times.
✓ Branch 3 taken 1486 times.
✓ Branch 4 taken 3503 times.
✗ Branch 5 not taken.
25859 if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos &&
10527
7/8
✓ Branch 0 taken 3500 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3500 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3486 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 617 times.
✓ Branch 7 taken 2869 times.
6989 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
10528 3486 start_pos + a.size == avio_size(pb))) {
10529
5/6
✓ Branch 0 taken 631 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 631 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 617 times.
634 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
10530 17 c->next_root_atom = start_pos + a.size;
10531 634 c->atom_depth --;
10532 634 return 0;
10533 }
10534 25225 left = a.size - avio_tell(pb) + start_pos;
10535
2/2
✓ Branch 0 taken 2374 times.
✓ Branch 1 taken 22851 times.
25225 if (left > 0) /* skip garbage at atom end */
10536 2374 avio_skip(pb, left);
10537
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22849 times.
22851 else if (left < 0) {
10538 2 av_log(c->fc, AV_LOG_WARNING,
10539 "overread end of atom '%s' by %"PRId64" bytes\n",
10540 2 av_fourcc2str(a.type), -left);
10541 2 avio_seek(pb, left, SEEK_CUR);
10542 }
10543 }
10544
10545 26895 total_size += a.size;
10546 }
10547
10548
4/4
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 8923 times.
✓ Branch 2 taken 125 times.
✓ Branch 3 taken 8 times.
9056 if (total_size < atom.size && atom.size < 0x7ffff)
10549 125 avio_skip(pb, atom.size - total_size);
10550
10551 9056 c->atom_depth --;
10552 9056 return 0;
10553 }
10554
10555 8356 static int mov_probe(const AVProbeData *p)
10556 {
10557 int64_t offset;
10558 uint32_t tag;
10559 8356 int score = 0;
10560 8356 int moov_offset = -1;
10561
10562 /* check file header */
10563 8356 offset = 0;
10564 10351 for (;;) {
10565 int64_t size;
10566 18707 int minsize = 8;
10567 /* ignore invalid offset */
10568
2/2
✓ Branch 0 taken 8356 times.
✓ Branch 1 taken 10351 times.
18707 if ((offset + 8ULL) > (unsigned int)p->buf_size)
10569 8356 break;
10570 10351 size = AV_RB32(p->buf + offset);
10571
3/4
✓ Branch 0 taken 547 times.
✓ Branch 1 taken 9804 times.
✓ Branch 2 taken 547 times.
✗ Branch 3 not taken.
10351 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
10572 547 size = AV_RB64(p->buf+offset + 8);
10573 547 minsize = 16;
10574
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 9732 times.
9804 } else if (size == 0) {
10575 72 size = p->buf_size - offset;
10576 }
10577
2/2
✓ Branch 0 taken 416 times.
✓ Branch 1 taken 9935 times.
10351 if (size < minsize) {
10578 416 offset += 4;
10579 416 continue;
10580 }
10581 9935 tag = AV_RL32(p->buf + offset + 4);
10582
5/6
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 1092 times.
✓ Branch 2 taken 449 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 8208 times.
9935 switch(tag) {
10583 /* check for obvious tags */
10584 185 case MKTAG('m','o','o','v'):
10585 185 moov_offset = offset + 4;
10586 av_fallthrough;
10587 1277 case MKTAG('m','d','a','t'):
10588 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
10589 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
10590 case MKTAG('f','t','y','p'):
10591
2/2
✓ Branch 0 taken 569 times.
✓ Branch 1 taken 708 times.
1277 if (tag == MKTAG('f','t','y','p') &&
10592
1/2
✓ Branch 0 taken 569 times.
✗ Branch 1 not taken.
569 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
10593
1/2
✓ Branch 0 taken 569 times.
✗ Branch 1 not taken.
569 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
10594
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 562 times.
569 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
10595 )) {
10596 7 score = FFMAX(score, 5);
10597 } else {
10598 1270 score = AVPROBE_SCORE_MAX;
10599 }
10600 1277 break;
10601 /* those are more common words, so rate then a bit less */
10602 449 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
10603 case MKTAG('w','i','d','e'):
10604 case MKTAG('f','r','e','e'):
10605 case MKTAG('j','u','n','k'):
10606 case MKTAG('p','i','c','t'):
10607 449 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
10608 449 break;
10609 ✗ case MKTAG(0x82,0x82,0x7f,0x7d):
10610 ✗ score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
10611 ✗ break;
10612 1 case MKTAG('s','k','i','p'):
10613 case MKTAG('u','u','i','d'):
10614 case MKTAG('p','r','f','l'):
10615 /* if we only find those cause probedata is too small at least rate them */
10616 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
10617 1 break;
10618 }
10619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9935 times.
9935 if (size > INT64_MAX - offset)
10620 ✗ break;
10621 9935 offset += size;
10622 }
10623
4/4
✓ Branch 0 taken 616 times.
✓ Branch 1 taken 7740 times.
✓ Branch 2 taken 185 times.
✓ Branch 3 taken 431 times.
8356 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
10624 /* moov atom in the header - we should make sure that this is not a
10625 * MOV-packed MPEG-PS */
10626 185 offset = moov_offset;
10627
10628
2/2
✓ Branch 0 taken 181268 times.
✓ Branch 1 taken 185 times.
181453 while (offset < (p->buf_size - 16)) { /* Sufficient space */
10629 /* We found an actual hdlr atom */
10630
2/2
✓ Branch 0 taken 205 times.
✓ Branch 1 taken 181063 times.
181268 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
10631
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 176 times.
205 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
10632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
10633 ✗ av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
10634 /* We found a media handler reference atom describing an
10635 * MPEG-PS-in-MOV, return a
10636 * low score to force expanding the probe window until
10637 * mpegps_probe finds what it needs */
10638 ✗ return 5;
10639 } else {
10640 /* Keep looking */
10641 181268 offset += 2;
10642 }
10643 }
10644 }
10645
10646 8356 return score;
10647 }
10648
10649 // must be done after parsing all trak because there's no order requirement
10650 2 static void mov_read_chapters(AVFormatContext *s)
10651 {
10652 2 MOVContext *mov = s->priv_data;
10653 MOVStreamContext *sc;
10654 int64_t cur_pos;
10655 int i, j;
10656 int chapter_track;
10657
10658
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
10659 2 AVStream *st = NULL;
10660 2 FFStream *sti = NULL;
10661 2 chapter_track = mov->chapter_tracks[j];
10662
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
10663 4 sc = mov->fc->streams[i]->priv_data;
10664
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
10665 2 st = s->streams[i];
10666 2 break;
10667 }
10668 }
10669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
10670 ✗ av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
10671 ✗ continue;
10672 }
10673 2 sti = ffstream(st);
10674
10675 2 sc = st->priv_data;
10676 2 cur_pos = avio_tell(sc->pb);
10677
10678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
10679 ✗ st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
10680 ✗ if (!st->attached_pic.data && sti->nb_index_entries) {
10681 // Retrieve the first frame, if possible
10682 ✗ AVIndexEntry *sample = &sti->index_entries[0];
10683 ✗ if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10684 ✗ av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
10685 ✗ goto finish;
10686 }
10687
10688 ✗ if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
10689 ✗ goto finish;
10690 }
10691 } else {
10692 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10693 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
10694 2 st->discard = AVDISCARD_ALL;
10695
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
10696 8 AVIndexEntry *sample = &sti->index_entries[i];
10697
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;
10698 uint8_t *title;
10699 uint16_t ch;
10700 int len, title_len;
10701
10702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
10703 ✗ av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
10704 ✗ end = AV_NOPTS_VALUE;
10705 }
10706
10707
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10708 ✗ av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
10709 ✗ goto finish;
10710 }
10711
10712 // the first two bytes are the length of the title
10713 8 len = avio_rb16(sc->pb);
10714
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
10715 ✗ continue;
10716 8 title_len = 2*len + 1;
10717
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
10718 ✗ goto finish;
10719
10720 // The samples could theoretically be in any encoding if there's an encd
10721 // atom following, but in practice are only utf-8 or utf-16, distinguished
10722 // instead by the presence of a BOM
10723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
10724 ✗ title[0] = 0;
10725 } else {
10726 8 ch = avio_rb16(sc->pb);
10727
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
10728 ✗ avio_get_str16be(sc->pb, len, title, title_len);
10729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
10730 ✗ avio_get_str16le(sc->pb, len, title, title_len);
10731 else {
10732 8 AV_WB16(title, ch);
10733
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)
10734 ✗ title[len] = 0;
10735 else
10736 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
10737 }
10738 }
10739
10740 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
10741 8 av_freep(&title);
10742 }
10743 }
10744 2 finish:
10745 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
10746 }
10747 2 }
10748
10749 28 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
10750 int64_t value, int flags)
10751 {
10752 AVTimecode tc;
10753 char buf[AV_TIMECODE_STR_SIZE];
10754 28 AVRational rate = st->avg_frame_rate;
10755 28 int ret = av_timecode_init(&tc, rate, flags, 0, s);
10756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
10757 ✗ return ret;
10758 28 av_dict_set(&st->metadata, "timecode",
10759 28 av_timecode_make_string(&tc, buf, value), 0);
10760 28 return 0;
10761 }
10762
10763 ✗ static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
10764 {
10765 ✗ MOVStreamContext *sc = st->priv_data;
10766 ✗ FFStream *const sti = ffstream(st);
10767 char buf[AV_TIMECODE_STR_SIZE];
10768 ✗ int64_t cur_pos = avio_tell(sc->pb);
10769 int hh, mm, ss, ff, drop;
10770
10771 ✗ if (!sti->nb_index_entries)
10772 ✗ return -1;
10773
10774 ✗ avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10775 ✗ avio_skip(s->pb, 13);
10776 ✗ hh = avio_r8(s->pb);
10777 ✗ mm = avio_r8(s->pb);
10778 ✗ ss = avio_r8(s->pb);
10779 ✗ drop = avio_r8(s->pb);
10780 ✗ ff = avio_r8(s->pb);
10781 ✗ snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
10782 hh, mm, ss, drop ? ';' : ':', ff);
10783 ✗ av_dict_set(&st->metadata, "timecode", buf, 0);
10784
10785 ✗ avio_seek(sc->pb, cur_pos, SEEK_SET);
10786 ✗ return 0;
10787 }
10788
10789 28 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
10790 {
10791 28 MOVStreamContext *sc = st->priv_data;
10792 28 FFStream *const sti = ffstream(st);
10793 28 int flags = 0;
10794 28 int64_t cur_pos = avio_tell(sc->pb);
10795 int64_t value;
10796 28 AVRational tc_rate = st->avg_frame_rate;
10797 28 int tmcd_nb_frames = sc->tmcd_nb_frames;
10798 int rounded_tc_rate;
10799
10800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!sti->nb_index_entries)
10801 ✗ return -1;
10802
10803
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)
10804 ✗ return -1;
10805
10806 28 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10807 28 value = avio_rb32(s->pb);
10808
10809
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 10 times.
28 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
10810
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
10811
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
10812
10813 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
10814 * not the case) and thus assume "frame number format" instead of QT one.
10815 * No sample with tmcd track can be found with a QT timecode at the moment,
10816 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
10817 * format). */
10818
10819 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
10820 * we multiply the frame number with the quotient.
10821 * See tickets #9492, #9710. */
10822 28 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
10823 /* Work around files where tmcd_nb_frames is rounded down from frame rate
10824 * instead of up. See ticket #5978. */
10825
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 18 times.
28 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
10826
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
10827 10 tmcd_nb_frames = rounded_tc_rate;
10828 28 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
10829
10830 28 parse_timecode_in_framenum_format(s, st, value, flags);
10831
10832 28 avio_seek(sc->pb, cur_pos, SEEK_SET);
10833 28 return 0;
10834 }
10835
10836 1791 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
10837 int i;
10838
3/4
✓ Branch 0 taken 1791 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1778 times.
✓ Branch 3 taken 13 times.
1791 if (!index || !*index) return;
10839
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 13 times.
208 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
10840 195 av_encryption_info_free((*index)->encrypted_samples[i]);
10841 }
10842 13 av_freep(&(*index)->encrypted_samples);
10843 13 av_freep(&(*index)->auxiliary_info_sizes);
10844 13 av_freep(&(*index)->auxiliary_offsets);
10845 13 av_freep(index);
10846 }
10847
10848 1058 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
10849 {
10850 1058 MOVStreamContext *sc = st->priv_data;
10851
10852
3/4
✓ Branch 0 taken 1058 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 1004 times.
1058 if (!sc || --sc->refcount) {
10853 54 st->priv_data = NULL;
10854 54 return;
10855 }
10856
10857 1004 av_freep(&sc->tts_data);
10858
2/2
✓ Branch 0 taken 882 times.
✓ Branch 1 taken 1004 times.
1886 for (int i = 0; i < sc->drefs_count; i++) {
10859 882 av_freep(&sc->drefs[i].path);
10860 882 av_freep(&sc->drefs[i].dir);
10861 }
10862 1004 av_freep(&sc->drefs);
10863
10864 1004 sc->drefs_count = 0;
10865
10866
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 985 times.
1004 if (!sc->pb_is_copied)
10867 19 ff_format_io_close(s, &sc->pb);
10868
10869 1004 sc->pb = NULL;
10870 1004 av_freep(&sc->chunk_offsets);
10871 1004 av_freep(&sc->stsc_data);
10872 1004 av_freep(&sc->sample_sizes);
10873 1004 av_freep(&sc->keyframes);
10874 1004 av_freep(&sc->ctts_data);
10875 1004 av_freep(&sc->stts_data);
10876 1004 av_freep(&sc->sdtp_data);
10877 1004 av_freep(&sc->stps_data);
10878 1004 av_freep(&sc->elst_data);
10879 1004 av_freep(&sc->rap_group);
10880 1004 av_freep(&sc->sync_group);
10881 1004 av_freep(&sc->sgpd_sync);
10882 1004 av_freep(&sc->sample_offsets);
10883 1004 av_freep(&sc->open_key_samples);
10884 1004 av_freep(&sc->display_matrix);
10885 1004 av_freep(&sc->index_ranges);
10886
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 1004 times.
1037 for (int i = 0; i < sc->nb_tref_tags; i++)
10887 33 av_freep(&sc->tref_tags[i].id);
10888 1004 av_freep(&sc->tref_tags);
10889
10890
2/2
✓ Branch 0 taken 879 times.
✓ Branch 1 taken 125 times.
1004 if (sc->extradata)
10891
2/2
✓ Branch 0 taken 896 times.
✓ Branch 1 taken 879 times.
1775 for (int i = 0; i < sc->stsd_count; i++)
10892 896 av_free(sc->extradata[i]);
10893 1004 av_freep(&sc->extradata);
10894 1004 av_freep(&sc->extradata_size);
10895
10896 1004 mov_free_encryption_index(&sc->cenc.encryption_index);
10897 1004 av_encryption_info_free(sc->cenc.default_encrypted_sample);
10898 1004 av_aes_ctr_free(sc->cenc.aes_ctr);
10899
10900 1004 av_freep(&sc->stereo3d);
10901 1004 av_freep(&sc->spherical);
10902 1004 av_freep(&sc->mastering);
10903 1004 av_freep(&sc->coll);
10904 1004 av_freep(&sc->ambient);
10905
10906 #if CONFIG_IAMFDEC
10907
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 990 times.
1004 if (sc->iamf)
10908 14 ff_iamf_read_deinit(sc->iamf);
10909 #endif
10910 1004 av_freep(&sc->iamf);
10911 }
10912
10913 668 static int mov_read_close(AVFormatContext *s)
10914 {
10915 668 MOVContext *mov = s->priv_data;
10916 int i, j;
10917
10918
2/2
✓ Branch 0 taken 1058 times.
✓ Branch 1 taken 668 times.
1726 for (i = 0; i < s->nb_streams; i++) {
10919 1058 AVStream *st = s->streams[i];
10920
10921 1058 mov_free_stream_context(s, st);
10922 }
10923
10924 668 av_freep(&mov->dv_demux);
10925 668 avformat_free_context(mov->dv_fctx);
10926 668 mov->dv_fctx = NULL;
10927
10928
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 652 times.
668 if (mov->meta_keys) {
10929
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 16 times.
126 for (i = 1; i < mov->meta_keys_count; i++) {
10930 110 av_freep(&mov->meta_keys[i]);
10931 }
10932 16 av_freep(&mov->meta_keys);
10933 }
10934
10935 668 av_freep(&mov->trex_data);
10936 668 av_freep(&mov->bitrates);
10937
10938
2/2
✓ Branch 0 taken 487 times.
✓ Branch 1 taken 668 times.
1155 for (i = 0; i < mov->frag_index.nb_items; i++) {
10939 487 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
10940
2/2
✓ Branch 0 taken 787 times.
✓ Branch 1 taken 487 times.
1274 for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) {
10941 787 mov_free_encryption_index(&frag[j].encryption_index);
10942 }
10943 487 av_freep(&mov->frag_index.item[i].stream_info);
10944 }
10945 668 av_freep(&mov->frag_index.item);
10946
10947 668 av_freep(&mov->aes_decrypt);
10948 668 av_freep(&mov->chapter_tracks);
10949
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 668 times.
804 for (i = 0; i < mov->nb_heif_item; i++) {
10950
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (!mov->heif_item[i])
10951 ✗ continue;
10952 136 av_freep(&mov->heif_item[i]->name);
10953 136 av_freep(&mov->heif_item[i]->iref_from_list);
10954 136 av_freep(&mov->heif_item[i]->iref_to_list);
10955 136 av_freep(&mov->heif_item[i]->icc_profile);
10956 136 av_exif_free(&mov->heif_item[i]->ifd);
10957 136 av_freep(&mov->heif_item[i]);
10958 }
10959 668 av_freep(&mov->heif_item);
10960
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 668 times.
687 for (i = 0; i < mov->nb_heif_group; i++) {
10961 19 av_freep(&mov->heif_group[i].item_id_list);
10962 19 av_freep(&mov->heif_group[i].item_idx_list);
10963 19 av_freep(&mov->heif_group[i].item_list);
10964 }
10965 668 av_freep(&mov->heif_group);
10966
10967 668 return 0;
10968 }
10969
10970 28 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
10971 {
10972 int i;
10973
10974
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 for (i = 0; i < s->nb_streams; i++) {
10975 28 AVStream *st = s->streams[i];
10976 28 MOVStreamContext *sc = st->priv_data;
10977 28 MovTref *tag = mov_find_tref_tag(sc, MKTAG('t','m','c','d'));
10978
10979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!tag)
10980 ✗ continue;
10981
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 if (mov_find_tref_id(tag, tmcd_id))
10982 28 return 1;
10983 }
10984 ✗ return 0;
10985 }
10986
10987 /* look for a tmcd track not referenced by any video track, and export it globally */
10988 665 static void export_orphan_timecode(AVFormatContext *s)
10989 {
10990 int i;
10991
10992
2/2
✓ Branch 0 taken 1055 times.
✓ Branch 1 taken 665 times.
1720 for (i = 0; i < s->nb_streams; i++) {
10993 1055 AVStream *st = s->streams[i];
10994
10995
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 1027 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
1083 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
10996 28 !tmcd_is_referenced(s, st->id)) {
10997 ✗ AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
10998 ✗ if (tcr) {
10999 ✗ av_dict_set(&s->metadata, "timecode", tcr->value, 0);
11000 ✗ break;
11001 }
11002 }
11003 }
11004 665 }
11005
11006 3 static int read_tfra(MOVContext *mov, AVIOContext *f)
11007 {
11008 int version, fieldlength, i, j;
11009 3 int64_t pos = avio_tell(f);
11010 3 uint32_t size = avio_rb32(f);
11011 unsigned track_id, item_count;
11012
11013
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
11014 1 return 1;
11015 }
11016 /* A tfra box can not be smaller than its 24-byte header. A size of 0
11017 * would make mov_read_mfra() re-read the same box forever. */
11018
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (size < 24) {
11019 ✗ av_log(mov->fc, AV_LOG_ERROR, "Invalid tfra size %"PRIu32"\n", size);
11020 ✗ return AVERROR_INVALIDDATA;
11021 }
11022 2 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
11023
11024 2 version = avio_r8(f);
11025 2 avio_rb24(f);
11026 2 track_id = avio_rb32(f);
11027 2 fieldlength = avio_rb32(f);
11028 2 item_count = avio_rb32(f);
11029
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (i = 0; i < item_count; i++) {
11030 int64_t time, offset;
11031 int index;
11032 MOVFragmentStreamInfo * frag_stream_info;
11033
11034
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (avio_feof(f)) {
11035 ✗ return AVERROR_INVALIDDATA;
11036 }
11037
11038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1) {
11039 ✗ time = avio_rb64(f);
11040 ✗ offset = avio_rb64(f);
11041 } else {
11042 6 time = avio_rb32(f);
11043 6 offset = avio_rb32(f);
11044 }
11045
11046 // The first sample of each stream in a fragment is always a random
11047 // access sample. So it's entry in the tfra can be used as the
11048 // initial PTS of the fragment.
11049 6 index = update_frag_index(mov, offset);
11050 6 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
11051
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (frag_stream_info &&
11052
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
11053 6 frag_stream_info->first_tfra_pts = time;
11054
11055
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
11056 6 avio_r8(f);
11057
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
11058 6 avio_r8(f);
11059
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
11060 6 avio_r8(f);
11061 }
11062
11063 2 avio_seek(f, pos + size, SEEK_SET);
11064 2 return 0;
11065 }
11066
11067 1 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
11068 {
11069 1 int64_t stream_size = avio_size(f);
11070 1 int64_t original_pos = avio_tell(f);
11071 int64_t seek_ret;
11072 1 int ret = -1;
11073
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
11074 ✗ ret = seek_ret;
11075 ✗ goto fail;
11076 }
11077 1 c->mfra_size = avio_rb32(f);
11078 1 c->have_read_mfra_size = 1;
11079
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) {
11080 ✗ av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
11081 ✗ goto fail;
11082 }
11083
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) {
11084 ✗ ret = seek_ret;
11085 ✗ goto fail;
11086 }
11087
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != c->mfra_size) {
11088 ✗ av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
11089 ✗ goto fail;
11090 }
11091
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
11092 ✗ av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
11093 ✗ goto fail;
11094 }
11095 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
11096 do {
11097 3 ret = read_tfra(c, f);
11098
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
11099 ✗ goto fail;
11100
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 } while (!ret);
11101 1 ret = 0;
11102 1 c->frag_index.complete = 1;
11103 1 fail:
11104 1 seek_ret = avio_seek(f, original_pos, SEEK_SET);
11105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (seek_ret < 0) {
11106 ✗ av_log(c->fc, AV_LOG_ERROR,
11107 "failed to seek back after looking for mfra\n");
11108 ✗ ret = seek_ret;
11109 }
11110 1 return ret;
11111 }
11112
11113 4 static int set_exif_from_item(AVFormatContext *s,
11114 AVPacketSideData **coded_side_data, int *nb_coded_side_data,
11115 const HEIFItem *item)
11116 {
11117 AVPacketSideData *sd =
11118 4 (AVPacketSideData *)av_packet_side_data_get(*coded_side_data,
11119 *nb_coded_side_data,
11120 AV_PKT_DATA_EXIF);
11121 4 const AVExifMetadata *ifd = &item->ifd;
11122 4 AVBufferRef *buf = NULL;
11123 int err;
11124
11125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sd)
11126 ✗ return 0;
11127
11128 4 err = av_exif_write(s, ifd, &buf, AV_EXIF_TIFF_HEADER);
11129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
11130 ✗ return err;
11131
11132 4 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
11133 4 AV_PKT_DATA_EXIF, buf->size, 0);
11134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sd) {
11135 ✗ av_buffer_unref(&buf);
11136 ✗ return AVERROR(ENOMEM);
11137 }
11138 4 memcpy(sd->data, buf->data, buf->size);
11139
11140 4 av_buffer_unref(&buf);
11141
11142 4 return 0;
11143 }
11144
11145 4 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
11146 const HEIFItem *item)
11147 {
11148 AVPacketSideData *sd =
11149 4 (AVPacketSideData *)av_packet_side_data_get(*coded_side_data,
11150 *nb_coded_side_data,
11151 AV_PKT_DATA_ICC_PROFILE);
11152
11153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sd)
11154 ✗ return 0;
11155
11156 4 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
11157 AV_PKT_DATA_ICC_PROFILE,
11158 4 item->icc_profile_size, 0);
11159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sd)
11160 ✗ return AVERROR(ENOMEM);
11161
11162 4 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
11163
11164 4 return 0;
11165 }
11166
11167 6 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
11168 const HEIFItem *item)
11169 {
11170 int32_t *matrix;
11171 AVPacketSideData *sd =
11172 6 (AVPacketSideData *)av_packet_side_data_get(*coded_side_data,
11173 *nb_coded_side_data,
11174 AV_PKT_DATA_DISPLAYMATRIX);
11175
11176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (sd)
11177 ✗ return 0;
11178
11179 6 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
11180 AV_PKT_DATA_DISPLAYMATRIX,
11181 9 * sizeof(*matrix), 0);
11182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sd)
11183 ✗ return AVERROR(ENOMEM);
11184
11185 6 matrix = (int32_t*)sd->data;
11186 /* rotation is in the counter-clockwise direction whereas
11187 * av_display_rotation_set() expects its argument to be
11188 * oriented clockwise, so we need to negate it. */
11189 6 av_display_rotation_set(matrix, -item->rotation);
11190 6 av_display_matrix_flip(matrix, item->hflip, item->vflip);
11191
11192 6 return 0;
11193 }
11194
11195 11 static int read_image_grid(AVFormatContext *s, const HEIFGroup *grid,
11196 AVStreamGroupTileGrid *tile_grid)
11197 {
11198 11 MOVContext *c = s->priv_data;
11199 11 const HEIFItem *item = grid->item;
11200 11 int64_t coded_width = 0, coded_height = 0;
11201 11 int64_t offset = 0, pos = avio_tell(s->pb);
11202 11 int64_t x = 0, y = 0;
11203 11 int i = 0;
11204 int tile_rows, tile_cols;
11205 int flags, size;
11206
11207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11208 ✗ av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
11209 ✗ return AVERROR_PATCHWELCOME;
11210 }
11211
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
11 if (item->is_idat_relative) {
11212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!c->idat_offset) {
11213 ✗ av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
11214 ✗ return AVERROR_INVALIDDATA;
11215 }
11216 7 offset = c->idat_offset;
11217 }
11218
11219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (offset > INT64_MAX - item->extent_offset)
11220 ✗ return AVERROR_INVALIDDATA;
11221
11222 11 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
11223
11224 11 avio_r8(s->pb); /* version */
11225 11 flags = avio_r8(s->pb);
11226
11227 11 tile_rows = avio_r8(s->pb) + 1;
11228 11 tile_cols = avio_r8(s->pb) + 1;
11229 /* actual width and height of output image */
11230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 tile_grid->width = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
11231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 tile_grid->height = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
11232
11233 11 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
11234 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
11235
11236 11 avio_seek(s->pb, pos, SEEK_SET);
11237
11238 11 size = tile_rows * tile_cols;
11239 11 tile_grid->nb_tiles = grid->nb_items;
11240
11241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (tile_grid->nb_tiles != size)
11242 ✗ return AVERROR_INVALIDDATA;
11243
11244
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 11 times.
41 for (int i = 0; i < tile_cols; i++)
11245 30 coded_width += grid->item_list[i]->width;
11246
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 11 times.
37 for (int i = 0; i < size; i += tile_cols)
11247 26 coded_height += grid->item_list[i]->height;
11248
11249
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if (coded_width > INT_MAX || coded_height > INT_MAX)
11250 ✗ return AVERROR_INVALIDDATA;
11251
11252 11 tile_grid->coded_width = coded_width;
11253 11 tile_grid->coded_height = coded_height;
11254
11255 11 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
11256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!tile_grid->offsets)
11257 ✗ return AVERROR(ENOMEM);
11258
11259
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 11 times.
37 while (y < tile_grid->coded_height) {
11260 26 int left_col = i;
11261
11262
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 26 times.
102 while (x < tile_grid->coded_width) {
11263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (i == tile_grid->nb_tiles)
11264 ✗ return AVERROR_INVALIDDATA;
11265
11266 76 tile_grid->offsets[i].idx = grid->item_idx_list[i];
11267 76 tile_grid->offsets[i].horizontal = x;
11268 76 tile_grid->offsets[i].vertical = y;
11269
11270 76 x += grid->item_list[i++]->width;
11271 }
11272
11273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (x > tile_grid->coded_width) {
11274 ✗ av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
11275 ✗ return AVERROR_INVALIDDATA;
11276 }
11277
11278 26 x = 0;
11279 26 y += grid->item_list[left_col]->height;
11280 }
11281
11282
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if (y > tile_grid->coded_height || i != tile_grid->nb_tiles) {
11283 ✗ av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
11284 ✗ return AVERROR_INVALIDDATA;
11285 }
11286
11287 11 return 0;
11288 }
11289
11290 4 static int read_image_iovl(AVFormatContext *s, const HEIFGroup *grid,
11291 AVStreamGroupTileGrid *tile_grid)
11292 {
11293 4 MOVContext *c = s->priv_data;
11294 4 const HEIFItem *item = grid->item;
11295 uint16_t canvas_fill_value[4];
11296 4 int64_t offset = 0, pos = avio_tell(s->pb);
11297 4 int ret = 0, flags;
11298
11299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11300 ✗ av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
11301 ✗ return AVERROR_PATCHWELCOME;
11302 }
11303
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
11304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
11305 ✗ av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
11306 ✗ return AVERROR_INVALIDDATA;
11307 }
11308 4 offset = c->idat_offset;
11309 }
11310
11311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (offset > INT64_MAX - item->extent_offset)
11312 ✗ return AVERROR_INVALIDDATA;
11313
11314 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
11315
11316 4 avio_r8(s->pb); /* version */
11317 4 flags = avio_r8(s->pb);
11318
11319
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
11320 16 canvas_fill_value[i] = avio_rb16(s->pb);
11321 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
11322 4 canvas_fill_value[0], canvas_fill_value[1],
11323 4 canvas_fill_value[2], canvas_fill_value[3]);
11324
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
11325 16 tile_grid->background[i] = canvas_fill_value[i];
11326
11327 /* actual width and height of output image */
11328 4 tile_grid->width =
11329
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);
11330 4 tile_grid->height =
11331
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);
11332
11333 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
11334 tile_grid->width, tile_grid->height);
11335
11336 4 tile_grid->nb_tiles = grid->nb_items;
11337 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
11338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
11339 ✗ ret = AVERROR(ENOMEM);
11340 ✗ goto fail;
11341 }
11342
11343
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
11344 8 tile_grid->offsets[i].idx = grid->item_idx_list[i];
11345
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);
11346
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);
11347 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
11348 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
11349 8 i, tile_grid->offsets[i].idx,
11350 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
11351 }
11352
11353 4 fail:
11354 4 avio_seek(s->pb, pos, SEEK_SET);
11355
11356 4 return ret;
11357 }
11358
11359 4 static int mov_parse_exif_item(AVFormatContext *s, HEIFItem *item, const HEIFItem *ref)
11360 {
11361 4 MOVContext *c = s->priv_data;
11362 4 AVExifMetadata *ifd = &item->ifd;
11363 uint8_t *buf;
11364 4 int64_t offset = 0, pos = avio_tell(s->pb);
11365 4 unsigned orientation_id = av_exif_get_tag_id("Orientation");
11366 int err;
11367
11368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11369 ✗ av_log(c->fc, AV_LOG_WARNING, "Exif metadata with non seekable input\n");
11370 ✗ return AVERROR_PATCHWELCOME;
11371 }
11372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ref->is_idat_relative) {
11373 ✗ if (!c->idat_offset) {
11374 ✗ av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the Exif metadata\n");
11375 ✗ return AVERROR_INVALIDDATA;
11376 }
11377 ✗ offset = c->idat_offset;
11378 }
11379
11380 4 buf = av_malloc(ref->extent_length);
11381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!buf)
11382 ✗ return AVERROR(ENOMEM);
11383
11384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (offset > INT64_MAX - ref->extent_offset) {
11385 ✗ err = AVERROR(ENOMEM);
11386 ✗ goto fail;
11387 }
11388
11389 4 avio_seek(s->pb, ref->extent_offset + offset, SEEK_SET);
11390 4 err = avio_read(s->pb, buf, ref->extent_length);
11391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err != ref->extent_length) {
11392 ✗ if (err > 0)
11393 ✗ err = AVERROR_INVALIDDATA;
11394 ✗ goto fail;
11395 }
11396
11397 // HEIF spec states that Exif metadata is informative. The irot item property is
11398 // the normative source of rotation information. So we remove any Orientation tag
11399 // present in the Exif buffer.
11400 4 err = av_exif_parse_buffer(s, buf, ref->extent_length, ifd, AV_EXIF_T_OFF);
11401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0) {
11402 ✗ av_log(s, AV_LOG_ERROR, "Unable to parse Exif metadata\n");
11403 ✗ goto fail;
11404 }
11405
11406 4 err = av_exif_remove_entry(s, ifd, orientation_id, 0);
11407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
11408 ✗ goto fail;
11409
11410 4 err = 0;
11411 4 fail:
11412 4 av_free(buf);
11413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
11414 ✗ av_exif_free(ifd);
11415 4 avio_seek(s->pb, pos, SEEK_SET);
11416
11417 4 return err;
11418 }
11419
11420 126 static int mov_apply_heif_item_references(AVFormatContext *s, HEIFItem *item,
11421 AVPacketSideData **coded_side_data,
11422 int *nb_coded_side_data)
11423 {
11424 int err;
11425
11426 /* exif */
11427
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 122 times.
126 if (item->ifd.count) {
11428 4 err = set_exif_from_item(s, coded_side_data, nb_coded_side_data, item);
11429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
11430 ✗ return err;
11431 }
11432
11433 /* rotation */
11434
4/6
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 120 times.
126 if (item->rotation || item->hflip || item->vflip) {
11435 6 err = set_display_matrix_from_item(coded_side_data, nb_coded_side_data, item);
11436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
11437 ✗ return err;
11438 }
11439
11440 /* ICC profile */
11441
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 122 times.
126 if (item->icc_profile_size) {
11442 4 err = set_icc_profile_from_item(coded_side_data, nb_coded_side_data, item);
11443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
11444 ✗ return err;
11445 }
11446
11447 126 return 0;
11448 }
11449
11450 123 static int mov_parse_heif_item_references(AVFormatContext *s, HEIFItem *item,
11451 AVPacketSideData **coded_side_data,
11452 int *nb_coded_side_data)
11453 {
11454 123 MOVContext *mov = s->priv_data;
11455 int err;
11456
11457
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 123 times.
133 for (int j = 0; j < item->nb_iref_from_list; j++) {
11458 10 HEIFItem *ref = get_heif_item(mov, item->iref_from_list[j].item_id);
11459
11460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 av_assert0(ref);
11461
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
10 switch(ref->type) {
11462 4 case MKTAG('E','x','i','f'):
11463 4 err = mov_parse_exif_item(s, item, ref);
11464
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))
11465 ✗ return err;
11466 4 break;
11467 6 default:
11468 6 break;
11469 }
11470 }
11471
11472 123 err = mov_apply_heif_item_references(s, item, coded_side_data, nb_coded_side_data);
11473
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 123 times.
123 if (err < 0)
11474 ✗ return err;
11475
11476 123 return 0;
11477 }
11478
11479 24 static int mov_parse_tiles(AVFormatContext *s)
11480 {
11481 24 MOVContext *mov = s->priv_data;
11482
11483
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 24 times.
43 for (int i = 0; i < mov->nb_heif_group; i++) {
11484 AVStreamGroup *stg;
11485 AVStreamGroupTileGrid *tile_grid;
11486 19 const HEIFGroup *grid = &mov->heif_group[i];
11487 int err;
11488
11489
3/4
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 11 times.
19 if (!grid->item || (grid->item->type != MKTAG('g','r','i','d') &&
11490
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 grid->item->type != MKTAG('i','o','v','l')))
11491 4 continue;
11492
11493 15 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
11494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!stg)
11495 ✗ return AVERROR(ENOMEM);
11496
11497 15 stg->id = grid->item->item_id;
11498 15 tile_grid = stg->params.tile_grid;
11499
11500
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 15 times.
99 for (int j = 0; j < grid->nb_items; j++) {
11501 84 int tile_id = grid->item_id_list[j];
11502 84 HEIFItem *item = get_heif_item(mov, tile_id);
11503 AVStream *st;
11504
11505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (!item) {
11506 ✗ av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
11507 "exist\n",
11508 ✗ tile_id, grid->item->item_id);
11509 ✗ ff_remove_stream_group(s, stg);
11510 ✗ stg = NULL;
11511 ✗ break;
11512 }
11513
11514 84 st = item->st;
11515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (!st) {
11516 ✗ av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
11517 "reference a stream\n",
11518 ✗ tile_id, grid->item->item_id);
11519 ✗ ff_remove_stream_group(s, stg);
11520 ✗ stg = NULL;
11521 ✗ break;
11522 }
11523
11524 84 grid->item_list[j] = item;
11525 84 grid->item_idx_list[j] = stg->nb_entries;
11526
11527 84 err = avformat_stream_group_add_stream(stg, st);
11528
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 82 times.
84 if (err < 0) {
11529 int l;
11530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
11531 ✗ return err;
11532
11533
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_entries; l++)
11534
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->entries[l]->stream->index == st->index)
11535 2 break;
11536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_entries);
11537 2 grid->item_idx_list[j] = l;
11538 }
11539
11540
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 6 times.
84 if (item->item_id != mov->primary_item_id)
11541 78 st->disposition |= AV_DISPOSITION_DEPENDENT;
11542 }
11543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!stg)
11544 ✗ continue;
11545
11546
2/3
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
15 switch (grid->item->type) {
11547 11 case MKTAG('g','r','i','d'):
11548 11 err = read_image_grid(s, grid, tile_grid);
11549 11 break;
11550 4 case MKTAG('i','o','v','l'):
11551 4 err = read_image_iovl(s, grid, tile_grid);
11552 4 break;
11553 ✗ default:
11554 ✗ av_assert0(0);
11555 }
11556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (err < 0)
11557 ✗ return err;
11558
11559 15 err = mov_parse_heif_item_references(s, grid->item, &stg->coded_side_data,
11560 &stg->nb_coded_side_data);
11561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (err < 0)
11562 ✗ return err;
11563
11564
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 2 times.
15 if (grid->item->name)
11565 13 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
11566
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 6 times.
15 if (grid->item->item_id == mov->primary_item_id)
11567 9 stg->disposition |= AV_DISPOSITION_DEFAULT;
11568
11569 15 grid->item->stg = stg;
11570 }
11571
11572 24 return 0;
11573 }
11574
11575 4 static int mov_parse_heif_layered_video_tmap(AVFormatContext *s, const HEIFGroup *tmap)
11576 {
11577 4 MOVContext *mov = s->priv_data;
11578 AVStreamGroup *stg;
11579 AVStreamGroupLayeredVideo *layered_video;
11580 4 AVGainMapParams *gain = NULL;
11581 4 uint8_t *payload = NULL;
11582 4 int64_t pos, offset = 0;
11583 size_t gain_size;
11584 int64_t err64;
11585 int err;
11586
11587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11588 ✗ av_log(s, AV_LOG_WARNING, "tmap box with non seekable input\n");
11589 ✗ return 0;
11590 }
11591
11592 4 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_GAIN_MAP, NULL);
11593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!stg)
11594 ✗ return AVERROR(ENOMEM);
11595
11596 4 stg->id = tmap->item->item_id;
11597 4 layered_video = stg->params.layered_video;
11598
11599
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int j = 0; j < tmap->nb_items; j++) {
11600 8 int item_id = tmap->item_id_list[j];
11601 8 HEIFItem *item = get_heif_item(mov, item_id);
11602 AVStreamGroup *child_stg;
11603 AVStream *st;
11604
11605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!item) {
11606 ✗ av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by tmap id %d doesn't "
11607 "exist\n",
11608 ✗ item_id, tmap->item->item_id);
11609 ✗ ff_remove_stream_group(s, stg);
11610 ✗ return 0;
11611 }
11612
11613 8 st = item->st;
11614 8 child_stg = item->stg;
11615
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
8 if (!st && !child_stg) {
11616 ✗ av_log(s, AV_LOG_WARNING, "HEIF item id %d from tmap id %d doesn't "
11617 "reference a stream or tmap\n",
11618 ✗ item_id, tmap->item->item_id);
11619 ✗ ff_remove_stream_group(s, stg);
11620 ✗ return 0;
11621 }
11622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 av_assert0(!st != !child_stg);
11623
11624 8 tmap->item_list[j] = item;
11625
11626
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (st)
11627 4 err = avformat_stream_group_add_stream(stg, st);
11628 else
11629 4 err = avformat_stream_group_add_stream_group(stg, child_stg);
11630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (err < 0) {
11631 ✗ if (err == AVERROR(EEXIST))
11632 ✗ err = AVERROR_INVALIDDATA;
11633
11634 ✗ return err;
11635 }
11636
11637
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if ((item->flags & MOV_INFE_FLAG_HIDDEN)) {
11638
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (st)
11639 4 st->disposition |= AV_DISPOSITION_DEPENDENT;
11640 else
11641 ✗ child_stg->disposition |= AV_DISPOSITION_DEPENDENT;
11642 }
11643 }
11644
11645 4 layered_video->width = tmap->item->width;
11646 4 layered_video->height = tmap->item->height;
11647
11648
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (tmap->item->is_idat_relative) {
11649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!mov->idat_offset) {
11650 ✗ av_log(s, AV_LOG_ERROR, "Missing idat box required by the tmap\n");
11651 ✗ return AVERROR_INVALIDDATA;
11652 }
11653 2 offset = mov->idat_offset;
11654 }
11655
11656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (offset > INT64_MAX - tmap->item->extent_offset)
11657 ✗ return AVERROR_INVALIDDATA;
11658
11659 4 gain = av_gain_map_params_alloc(&gain_size);
11660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!gain)
11661 ✗ return AVERROR(ENOMEM);
11662
11663 4 payload = av_malloc(tmap->item->extent_length);
11664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!payload) {
11665 ✗ return AVERROR(ENOMEM);
11666 goto fail;
11667 }
11668
11669 4 pos = avio_tell(s->pb);
11670 4 err64 = avio_seek(s->pb, tmap->item->extent_offset + offset, SEEK_SET);
11671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err64 != tmap->item->extent_offset + offset) {
11672 ✗ err64 = err64 < 0 ? err64 : AVERROR_INVALIDDATA;
11673 ✗ goto fail;
11674 }
11675 4 avio_r8(s->pb); /* version */
11676
11677 4 err = avio_read(s->pb, payload, tmap->item->extent_length - 1);
11678
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (err == (tmap->item->extent_length - 1))
11679 4 err64 = avio_seek(s->pb, pos, SEEK_SET);
11680 else {
11681 ✗ err = err < 0 ? err : AVERROR_INVALIDDATA;
11682 ✗ goto fail;
11683 }
11684
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err64 != pos) {
11685 ✗ err = err64 < 0 ? err64 : AVERROR_INVALIDDATA;
11686 ✗ goto fail;
11687 }
11688
11689 4 err = av_gain_map_params_from_iso21496(gain, payload, tmap->item->extent_length - 1);
11690 4 av_freep(&payload);
11691
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (err < 0) {
11692 2 av_log(s, AV_LOG_ERROR, "Invalid ISO 21496-1 gain map payload\n");
11693 2 ff_remove_stream_group(s, stg);
11694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 err = (s->error_recognition & (AV_EF_COMPLIANT|AV_EF_EXPLODE)) ? AVERROR_INVALIDDATA : 0;
11695 2 goto fail;
11696 }
11697
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (int j = 0; j < tmap->nb_items; j++) {
11698 4 HEIFItem *item = tmap->item_list[j];
11699 AVPacketSideData *sd;
11700 AVPacketSideData **coded_side_data;
11701 int *nb_coded_side_data;
11702
11703
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (!(item->flags & MOV_INFE_FLAG_HIDDEN))
11704 2 continue;
11705
11706 2 layered_video->el_index = j;
11707
11708
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (item->st) {
11709 2 coded_side_data = &item->st->codecpar->coded_side_data;
11710 2 nb_coded_side_data = &item->st->codecpar->nb_coded_side_data;
11711 } else {
11712 ✗ av_assert0(item->stg);
11713 ✗ coded_side_data = &item->stg->coded_side_data;
11714 ✗ nb_coded_side_data = &item->stg->nb_coded_side_data;
11715 }
11716
11717 2 sd = av_packet_side_data_add(coded_side_data, nb_coded_side_data,
11718 AV_PKT_DATA_GAIN_MAP_PARAMS,
11719 (uint8_t *)gain, gain_size, 0);
11720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!sd) {
11721 ✗ av_free(gain);
11722 ✗ return AVERROR(ENOMEM);
11723 }
11724 2 gain = NULL;
11725
11726
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (int k = 0; k < item->nb_iref_to_list; k++) {
11727 2 HEIFItem *ref = get_heif_item(mov, item->iref_to_list[k].item_id);
11728
11729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(ref);
11730 // Remove auxl reference so we don't create the same group we made with
11731 // this tmap using it. Strictly speaking, the chances for Apple style
11732 // Exif values being present on a base item referenced by a tmap item
11733 // are very low, but better safe than sorry.
11734
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (item->iref_to_list[k].type == MKTAG('a','u','x','l') &&
11735
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 (ref == tmap->item_list[!j])) {
11736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (k != (item->nb_iref_to_list - 1))
11737 ✗ item->iref_to_list[k] = item->iref_to_list[item->nb_iref_to_list - 1];
11738 2 --item->nb_iref_to_list;
11739 2 break;
11740 }
11741 }
11742 2 break;
11743 }
11744 2 av_free(gain);
11745
11746 2 err = mov_parse_heif_item_references(s, tmap->item, &stg->coded_side_data,
11747 &stg->nb_coded_side_data);
11748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11749 ✗ return err;
11750
11751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tmap->item->name)
11752 ✗ av_dict_set(&stg->metadata, "title", tmap->item->name, 0);
11753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tmap->item->item_id == mov->primary_item_id)
11754 ✗ stg->disposition |= AV_DISPOSITION_DEFAULT;
11755
11756 2 tmap->item->stg = stg;
11757
11758 2 return 0;
11759 2 fail:
11760 2 av_free(gain);
11761 2 av_free(payload);
11762
11763 2 return err;
11764 }
11765
11766 3 static int mov_parse_heif_layered_video_auxl_alpha(AVFormatContext *s,
11767 HEIFItem *base, HEIFItem *alpha)
11768 {
11769 AVStreamGroupLayeredVideo *layered_video;
11770 AVStreamGroup *stg;
11771 int err;
11772
11773
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
3 if ((!alpha->st && !alpha->stg) ||
11774
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
3 (!base->st && !base->stg)) {
11775 ✗ av_log(s, AV_LOG_WARNING, "HEIF alpha id %d or its base doesn't reference "
11776 "a stream or group\n",
11777 alpha->item_id);
11778 ✗ return 0;
11779 }
11780
11781 3 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_ALPHA, NULL);
11782
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!stg)
11783 ✗ return AVERROR(ENOMEM);
11784
11785 3 stg->id = alpha->item_id;
11786 3 layered_video = stg->params.layered_video;
11787
11788 3 layered_video->width = base->width;
11789 3 layered_video->height = base->height;
11790 3 layered_video->el_index = 1;
11791
11792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 av_assert0(!base->st != !base->stg);
11793
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (base->st)
11794 1 err = avformat_stream_group_add_stream(stg, base->st);
11795 else
11796 2 err = avformat_stream_group_add_stream_group(stg, base->stg);
11797
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (err < 0) {
11798 ✗ if (err == AVERROR(EEXIST))
11799 ✗ err = AVERROR_INVALIDDATA;
11800 ✗ return err;
11801 }
11802
11803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 av_assert0(!alpha->st != !alpha->stg);
11804
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (alpha->st)
11805 1 err = avformat_stream_group_add_stream(stg, alpha->st);
11806 else
11807 2 err = avformat_stream_group_add_stream_group(stg, alpha->stg);
11808
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (err < 0) {
11809 ✗ if (err == AVERROR(EEXIST))
11810 ✗ err = AVERROR_INVALIDDATA;
11811 ✗ return err;
11812 }
11813
11814 // Apply all references from the base image to the Alpha group
11815 3 err = mov_apply_heif_item_references(s, base, &stg->coded_side_data,
11816 &stg->nb_coded_side_data);
11817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (err < 0)
11818 ✗ return err;
11819
11820 3 return 0;
11821 }
11822
11823 // Parse Apple style Gain Map metadata from Exif values
11824 // See https://developer.apple.com/documentation/appkit/applying-apple-hdr-effect-to-your-photos
11825 ✗ static int mov_parse_heif_layered_video_auxl_gmap(AVFormatContext *s,
11826 HEIFItem *base, HEIFItem *gain_map)
11827 {
11828 AVStreamGroupLayeredVideo *layered_video;
11829 AVStreamGroup *stg;
11830 AVGainMapParams *gain;
11831 AVPacketSideData **coded_side_data;
11832 int *nb_coded_side_data;
11833 ✗ AVExifEntry *entry, *maker33 = NULL, *maker48 = NULL;
11834 ✗ double maker_33 = 0.0, maker_48 = 0.0, headroom;
11835 size_t gain_size;
11836 int err;
11837
11838 ✗ if ((!gain_map->st && !gain_map->stg) ||
11839 ✗ (!base->st && !base->stg)) {
11840 ✗ av_log(s, AV_LOG_WARNING, "HEIF gain_map id %d or its base doesn't reference "
11841 "a stream or group\n",
11842 gain_map->item_id);
11843 ✗ return 0;
11844 }
11845
11846 ✗ if (!base->ifd.count)
11847 ✗ return 0;
11848
11849 ✗ err = av_exif_get_entry(s, &base->ifd, 0x8769, 0, &entry);
11850 ✗ if (err > 0)
11851 ✗ err = av_exif_get_entry(s, &entry->value.ifd, 0x927c, 0, &entry);
11852 ✗ if (err > 0) {
11853 ✗ av_exif_get_entry(s, &entry->value.ifd, 0x21, 0, &maker33);
11854 ✗ av_exif_get_entry(s, &entry->value.ifd, 0x30, 0, &maker48);
11855 }
11856 ✗ if ((!maker33 && !maker48) ||
11857 ✗ (maker33 && maker33->type != AV_TIFF_SRATIONAL) ||
11858 ✗ (maker48 && maker48->type != AV_TIFF_SRATIONAL))
11859 ✗ return 0;
11860
11861 ✗ if (maker33)
11862 ✗ maker_33 = av_q2d(*maker33->value.rat);
11863 ✗ if (maker48)
11864 ✗ maker_48 = av_q2d(*maker48->value.rat);
11865
11866 ✗ if (maker_33 < 1.0) {
11867 ✗ if (maker_48 <= 0.01) {
11868 ✗ headroom = -20.0 * maker_48 + 1.8;
11869 } else {
11870 ✗ headroom = -0.101 * maker_48 + 1.601;
11871 }
11872 } else {
11873 ✗ if (maker_48 <= 0.01) {
11874 ✗ headroom = -70.0 * maker_48 + 3.0;
11875 } else {
11876 ✗ headroom = -0.303 * maker_48 + 2.303;
11877 }
11878 }
11879 ✗ if (headroom <= 0.0)
11880 ✗ return 0;
11881
11882 ✗ stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_GAIN_MAP, NULL);
11883 ✗ if (!stg)
11884 ✗ return AVERROR(ENOMEM);
11885
11886 ✗ stg->id = gain_map->item_id;
11887 ✗ layered_video = stg->params.layered_video;
11888
11889 ✗ layered_video->width = base->width;
11890 ✗ layered_video->height = base->height;
11891 ✗ layered_video->el_index = 1;
11892
11893 ✗ av_assert0(!base->st != !base->stg);
11894 ✗ if (base->st)
11895 ✗ err = avformat_stream_group_add_stream(stg, base->st);
11896 else
11897 ✗ err = avformat_stream_group_add_stream_group(stg, base->stg);
11898 ✗ if (err < 0) {
11899 ✗ if (err == AVERROR(EEXIST))
11900 ✗ err = AVERROR_INVALIDDATA;
11901 ✗ return err;
11902 }
11903
11904 ✗ av_assert0(!gain_map->st != !gain_map->stg);
11905 ✗ if (gain_map->st) {
11906 ✗ coded_side_data = &gain_map->st->codecpar->coded_side_data;
11907 ✗ nb_coded_side_data = &gain_map->st->codecpar->nb_coded_side_data;
11908 ✗ err = avformat_stream_group_add_stream(stg, gain_map->st);
11909 } else {
11910 ✗ coded_side_data = &gain_map->stg->coded_side_data;
11911 ✗ nb_coded_side_data = &gain_map->stg->nb_coded_side_data;
11912 ✗ err = avformat_stream_group_add_stream_group(stg, gain_map->stg);
11913 }
11914 ✗ if (err < 0) {
11915 ✗ if (err == AVERROR(EEXIST))
11916 ✗ err = AVERROR_INVALIDDATA;
11917 ✗ return err;
11918 }
11919
11920 ✗ gain = av_gain_map_params_alloc(&gain_size);
11921 ✗ if (!gain)
11922 ✗ return AVERROR(ENOMEM);
11923
11924 ✗ gain->use_base_color_space = 1;
11925 ✗ gain->alternate_hdr_headroom = av_d2q(headroom, INT_MAX);
11926 ✗ gain->nb_channels = 1;
11927 ✗ gain->channels[0].base_offset = (AVRational) { 0, 1 };
11928 ✗ gain->channels[0].alternate_offset = (AVRational) { 0, 1 };
11929 ✗ gain->channels[0].gain_map_max = gain->alternate_hdr_headroom;
11930
11931 ✗ AVPacketSideData *sd = av_packet_side_data_add(coded_side_data, nb_coded_side_data,
11932 AV_PKT_DATA_GAIN_MAP_PARAMS,
11933 (uint8_t *)gain, gain_size, 0);
11934 ✗ if (!sd) {
11935 ✗ av_free(gain);
11936 ✗ return AVERROR(ENOMEM);
11937 }
11938
11939 // Apply all references from the base image except Exif to the Gain Map group
11940 ✗ int count = base->ifd.count;
11941 ✗ base->ifd.count = 0;
11942 ✗ err = mov_apply_heif_item_references(s, base, &stg->coded_side_data,
11943 &stg->nb_coded_side_data);
11944 ✗ base->ifd.count = count;
11945 ✗ if (err < 0)
11946 ✗ return err;
11947
11948 ✗ return 0;
11949 }
11950
11951 24 static int mov_parse_heif_layered_video(AVFormatContext *s)
11952 {
11953 24 MOVContext *mov = s->priv_data;
11954 int err;
11955
11956
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 24 times.
43 for (int i = 0; i < mov->nb_heif_group; i++) {
11957 19 const HEIFGroup *tmap = &mov->heif_group[i];
11958
11959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!tmap->item)
11960 ✗ continue;
11961
11962
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 switch (tmap->item->type) {
11963 4 case MKTAG('t','m','a','p'):
11964 4 err = mov_parse_heif_layered_video_tmap(s, tmap);
11965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
11966 ✗ return err;
11967 4 break;
11968 15 default:
11969 15 break;
11970 }
11971 }
11972
11973
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 24 times.
160 for (int i = 0; i < mov->nb_heif_item; i++) {
11974 136 HEIFItem *item = mov->heif_item[i];
11975 int err;
11976
11977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (!item)
11978 ✗ continue;
11979
11980
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 136 times.
146 for (int j = 0; j < item->nb_iref_to_list; j++) {
11981 10 HEIFItem *ref = get_heif_item(mov, item->iref_to_list[j].item_id);
11982
11983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 av_assert0(ref);
11984
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
10 switch(item->iref_to_list[j].type) {
11985 3 case MKTAG('a','u','x','l'):
11986
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (item->is_alpha) {
11987 3 err = mov_parse_heif_layered_video_auxl_alpha(s, ref, item);
11988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (err < 0)
11989 ✗ return err;
11990 3 break;
11991 }
11992 ✗ if (item->is_gainmap) {
11993 ✗ err = mov_parse_heif_layered_video_auxl_gmap(s, ref, item);
11994 ✗ if (err < 0)
11995 ✗ return err;
11996 ✗ break;
11997 }
11998 }
11999 }
12000 }
12001
12002 24 return 0;
12003 }
12004
12005 24 static int mov_parse_heif_items(AVFormatContext *s)
12006 {
12007 24 MOVContext *mov = s->priv_data;
12008 int err;
12009
12010
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 24 times.
160 for (int i = 0; i < mov->nb_heif_item; i++) {
12011 136 HEIFItem *item = mov->heif_item[i];
12012 MOVStreamContext *sc;
12013 AVStream *st;
12014 136 int64_t offset = 0;
12015
12016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (!item)
12017 ✗ continue;
12018
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 106 times.
136 if (!item->st) {
12019 30 continue;
12020 }
12021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
106 if (item->is_idat_relative) {
12022 ✗ if (!mov->idat_offset) {
12023 ✗ av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
12024 ✗ return AVERROR_INVALIDDATA;
12025 }
12026 ✗ offset = mov->idat_offset;
12027 }
12028
12029 106 st = item->st;
12030 106 sc = st->priv_data;
12031 106 st->codecpar->width = item->width;
12032 106 st->codecpar->height = item->height;
12033
12034 106 sc->sample_size = sc->stsz_sample_size = item->extent_length;
12035 106 sc->sample_count = 1;
12036
12037 106 err = sanity_checks(s, sc, st->index);
12038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
106 if (err)
12039 ✗ return AVERROR_INVALIDDATA;
12040
12041
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
106 if (offset > INT64_MAX - item->extent_offset)
12042 ✗ return AVERROR_INVALIDDATA;
12043
12044 106 sc->chunk_offsets[0] = item->extent_offset + offset;
12045
12046 106 err = mov_parse_heif_item_references(s, item, &st->codecpar->coded_side_data,
12047 106 &st->codecpar->nb_coded_side_data);
12048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
106 if (err < 0)
12049 ✗ return err;
12050
12051
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 12 times.
106 if (item->name)
12052 94 av_dict_set(&st->metadata, "title", item->name, 0);
12053
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 91 times.
106 if (item->item_id == mov->primary_item_id)
12054 15 st->disposition |= AV_DISPOSITION_DEFAULT;
12055
12056 106 mov_build_index(mov, st);
12057 }
12058
12059 24 err = mov_parse_tiles(s);
12060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (err < 0)
12061 ✗ return err;
12062
12063 24 err = mov_parse_heif_layered_video(s);
12064
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (err < 0)
12065 ✗ return err;
12066
12067 24 return 0;
12068 }
12069
12070 665 static int mov_parse_tmcd_streams(AVFormatContext *s)
12071 {
12072 int err;
12073
12074
2/2
✓ Branch 0 taken 1055 times.
✓ Branch 1 taken 665 times.
1720 for (int i = 0; i < s->nb_streams; i++) {
12075 AVStreamGroup *stg;
12076 const AVDictionaryEntry *tcr;
12077 1055 AVStream *st = s->streams[i];
12078
12079
2/2
✓ Branch 0 taken 1027 times.
✓ Branch 1 taken 28 times.
1055 if (st->codecpar->codec_tag != MKTAG('t','m','c','d'))
12080 1027 continue;
12081
12082 28 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TREF, NULL);
12083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!stg)
12084 ✗ return AVERROR(ENOMEM);
12085
12086 28 stg->id = st->id;
12087 28 tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
12088
12089
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 28 times.
134 for (int j = 0; j < s->nb_streams; j++) {
12090 106 AVStream *st2 = s->streams[j];
12091 106 MOVStreamContext *sc2 = st2->priv_data;
12092 106 MovTref *tag = mov_find_tref_tag(sc2, MKTAG('t','m','c','d'));
12093
12094
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 29 times.
106 if (!tag)
12095 77 continue;
12096
12097
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 29 times.
88 for (int k = 0; k < tag->nb_id; k++) {
12098
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 29 times.
59 if (tag->id[k] != st->id)
12099 30 continue;
12100
12101 29 err = avformat_stream_group_add_stream(stg, st2);
12102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (err < 0)
12103 ✗ return err;
12104
12105
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (tcr)
12106 29 av_dict_set(&st2->metadata, "timecode", tcr->value, AV_DICT_DONT_OVERWRITE);
12107 }
12108 }
12109
12110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!stg->nb_entries) {
12111 ✗ ff_remove_stream_group(s, stg);
12112 ✗ continue;
12113 }
12114
12115 28 err = avformat_stream_group_add_stream(stg, st);
12116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (err < 0)
12117 ✗ return err;
12118
12119 28 stg->params.tref->metadata_index = stg->nb_entries - 1;
12120 }
12121 665 export_orphan_timecode(s);
12122
12123 665 return 0;
12124 }
12125
12126 13 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
12127 uint32_t *tref_id, int nb_tref_id, int first_index)
12128 {
12129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!nb_tref_id)
12130 ✗ return NULL;
12131
12132
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
14 for (int i = first_index; i < s->nb_streams; i++)
12133
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
14 for (int j = 0; j < nb_tref_id; j++)
12134
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1 times.
13 if (s->streams[i]->index != st->index &&
12135
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 s->streams[i]->id == tref_id[j])
12136 12 return s->streams[i];
12137
12138 1 return NULL;
12139 }
12140
12141 665 static int mov_parse_cdsc_and_rndr_streams(AVFormatContext *s)
12142 {
12143 static const uint32_t tref_tags[] = {
12144 MKTAG('c','d','s','c'),
12145 MKTAG('r','n','d','r'),
12146 };
12147
12148 int err;
12149
12150 // Don't try to add a group if there's only one track
12151
2/2
✓ Branch 0 taken 533 times.
✓ Branch 1 taken 132 times.
665 if (s->nb_streams <= 1)
12152 533 return 0;
12153
12154
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 132 times.
654 for (int i = 0; i < s->nb_streams; i++) {
12155 522 AVStream *st = s->streams[i];
12156 522 MOVStreamContext *sc = st->priv_data;
12157
12158
2/2
✓ Branch 0 taken 1044 times.
✓ Branch 1 taken 522 times.
1566 for (int c = 0; c < FF_ARRAY_ELEMS(tref_tags); c++) {
12159 AVStreamGroup *stg;
12160 AVStream *st_ref;
12161 1044 MovTref *tag = mov_find_tref_tag(sc, tref_tags[c]);
12162
12163
2/2
✓ Branch 0 taken 1033 times.
✓ Branch 1 taken 11 times.
1044 if (!tag)
12164 1033 continue;
12165
12166 11 st_ref = mov_find_reference_track(s, st, tag->id, tag->nb_id, 0);
12167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!st_ref) {
12168 ✗ av_log(s, AV_LOG_WARNING, "Failed to find referenced stream\n");
12169 ✗ continue;
12170 }
12171
12172 11 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TREF, NULL);
12173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!stg)
12174 ✗ return AVERROR(ENOMEM);
12175
12176 11 stg->id = st_ref->id;
12177
12178 11 err = avformat_stream_group_add_stream(stg, st_ref);
12179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
12180 ✗ return err;
12181
12182 11 err = avformat_stream_group_add_stream(stg, st);
12183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
12184 ✗ return err;
12185
12186 11 stg->params.tref->metadata_index = stg->nb_entries - 1;
12187 }
12188 }
12189
12190 132 return 0;
12191 }
12192
12193 665 static int mov_parse_lcevc_streams(AVFormatContext *s)
12194 {
12195 int err;
12196
12197 // Don't try to add a group if there's only one track
12198
2/2
✓ Branch 0 taken 533 times.
✓ Branch 1 taken 132 times.
665 if (s->nb_streams <= 1)
12199 533 return 0;
12200
12201
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 132 times.
654 for (int i = 0; i < s->nb_streams; i++) {
12202 AVStreamGroup *stg;
12203 522 AVStream *st = s->streams[i];
12204 AVStream *st_base;
12205 522 MOVStreamContext *sc = st->priv_data;
12206 522 MovTref *tag = mov_find_tref_tag(sc, MKTAG('s','b','a','s'));
12207 522 int j = 0;
12208
12209 /* Find an enhancement stream. */
12210
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 521 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
522 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC || !tag)
12211 521 continue;
12212
12213 1 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
12214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!stg)
12215 ✗ return AVERROR(ENOMEM);
12216
12217 1 stg->id = st->id;
12218 1 stg->params.layered_video->width = st->codecpar->width;
12219 1 stg->params.layered_video->height = st->codecpar->height;
12220
12221
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 while (st_base = mov_find_reference_track(s, st, tag->id, tag->nb_id, j)) {
12222 1 err = avformat_stream_group_add_stream(stg, st_base);
12223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (err < 0)
12224 ✗ return err;
12225
12226 1 j = st_base->index + 1;
12227 }
12228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!j) {
12229 ✗ int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
12230 ✗ av_log(s, loglevel, "Failed to find base stream for LCEVC stream\n");
12231 ✗ ff_remove_stream_group(s, stg);
12232 ✗ if (s->error_recognition & AV_EF_EXPLODE)
12233 ✗ return AVERROR_INVALIDDATA;
12234 ✗ continue;
12235 }
12236
12237 1 err = avformat_stream_group_add_stream(stg, st);
12238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (err < 0)
12239 ✗ return err;
12240
12241 1 stg->params.layered_video->el_index = stg->nb_entries - 1;
12242 }
12243
12244 132 return 0;
12245 }
12246
12247 665 static int mov_parse_dovi_streams(AVFormatContext *s)
12248 {
12249 int err;
12250
12251
2/2
✓ Branch 0 taken 533 times.
✓ Branch 1 taken 132 times.
665 if (s->nb_streams <= 1)
12252 533 return 0;
12253
12254 /* Identify legacy dual-track Dolby Vision profile 7 carriage per Annex
12255 * C of "Dolby Vision Streams Within the ISO Base Media File Format",
12256 * v2.7.1. The 'vdep' track reference type is shared with depth video
12257 * and multi-view dependencies. The spec-mandated DV-specific sample
12258 * entry combined with the dvcC configuration record disambiguates
12259 * those uses. */
12260
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 132 times.
654 for (int i = 0; i < s->nb_streams; i++) {
12261 AVStreamGroup *stg;
12262 522 AVStream *st = s->streams[i];
12263 AVStream *st_base;
12264 522 MOVStreamContext *sc = st->priv_data;
12265 522 MovTref *tag = mov_find_tref_tag(sc, MKTAG('v','d','e','p'));
12266 const AVPacketSideData *sd;
12267 const AVDOVIDecoderConfigurationRecord *dovi;
12268
12269
3/4
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 468 times.
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
522 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !tag)
12270 522 continue;
12271
12272 ✗ if (st->codecpar->codec_tag != MKTAG('d','v','h','e') &&
12273 ✗ st->codecpar->codec_tag != MKTAG('d','v','h','1'))
12274 ✗ continue;
12275
12276 ✗ sd = av_packet_side_data_get(st->codecpar->coded_side_data,
12277 ✗ st->codecpar->nb_coded_side_data,
12278 AV_PKT_DATA_DOVI_CONF);
12279 ✗ if (!sd)
12280 ✗ continue;
12281 ✗ dovi = (const AVDOVIDecoderConfigurationRecord *)sd->data;
12282
12283 /* EL track of a dual-track stream: rpu_present_flag = 1,
12284 * el_present_flag = 1, bl_present_flag = 0, dv_profile = 7. */
12285 ✗ if (dovi->dv_profile != 7 || !dovi->rpu_present_flag ||
12286 ✗ !dovi->el_present_flag || dovi->bl_present_flag)
12287 ✗ continue;
12288
12289 ✗ st_base = mov_find_reference_track(s, st, tag->id, tag->nb_id, 0);
12290 ✗ if (!st_base) {
12291 ✗ int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
12292 ✗ av_log(s, loglevel, "Failed to find base layer for Dolby Vision EL stream\n");
12293 ✗ if (s->error_recognition & AV_EF_EXPLODE)
12294 ✗ return AVERROR_INVALIDDATA;
12295 ✗ continue;
12296 }
12297
12298 ✗ stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_DOLBY_VISION, NULL);
12299 ✗ if (!stg)
12300 ✗ return AVERROR(ENOMEM);
12301
12302 ✗ stg->id = st->id;
12303
12304 ✗ err = avformat_stream_group_add_stream(stg, st_base);
12305 ✗ if (err < 0)
12306 ✗ return err;
12307
12308 ✗ err = avformat_stream_group_add_stream(stg, st);
12309 ✗ if (err < 0)
12310 ✗ return err;
12311
12312 ✗ stg->params.layered_video->el_index = stg->nb_entries - 1;
12313 ✗ stg->params.layered_video->width = st_base->codecpar->width;
12314 ✗ stg->params.layered_video->height = st_base->codecpar->height;
12315 }
12316
12317 132 return 0;
12318 }
12319
12320 665 static void fix_stream_ids(AVFormatContext *s)
12321 {
12322 665 int highest_id = 0, lowest_iamf_id = INT_MAX;
12323
12324
2/2
✓ Branch 0 taken 1055 times.
✓ Branch 1 taken 665 times.
1720 for (int i = 0; i < s->nb_streams; i++) {
12325 1055 const AVStream *st = s->streams[i];
12326 1055 const MOVStreamContext *sc = st->priv_data;
12327
2/2
✓ Branch 0 taken 987 times.
✓ Branch 1 taken 68 times.
1055 if (!sc->iamf)
12328 987 highest_id = FFMAX(highest_id, st->id);
12329 }
12330
12331
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 665 times.
755 for (int i = 0; i < s->nb_stream_groups; i++) {
12332 90 AVStreamGroup *stg = s->stream_groups[i];
12333
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 16 times.
90 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
12334 74 continue;
12335
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 16 times.
84 for (int j = 0; j < stg->nb_entries; j++) {
12336 68 AVStream *st = stg->entries[j]->stream;
12337 68 lowest_iamf_id = FFMIN(lowest_iamf_id, st->id);
12338 }
12339 }
12340
12341
2/2
✓ Branch 0 taken 655 times.
✓ Branch 1 taken 10 times.
665 if (highest_id < lowest_iamf_id)
12342 655 return;
12343
12344 10 highest_id += !lowest_iamf_id;
12345
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
14 for (int i = 0; highest_id > 1 && i < s->nb_stream_groups; i++) {
12346 4 AVStreamGroup *stg = s->stream_groups[i];
12347
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
12348 2 continue;
12349
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_entries; j++) {
12350 14 AVStream *st = stg->entries[j]->stream;
12351 14 MOVStreamContext *sc = st->priv_data;
12352 14 st->id += highest_id;
12353 14 sc->iamf_stream_offset = highest_id;
12354 }
12355 }
12356 }
12357
12358 668 static int mov_read_header(AVFormatContext *s)
12359 {
12360 668 MOVContext *mov = s->priv_data;
12361 668 AVIOContext *pb = s->pb;
12362 int j, err;
12363 668 MOVAtom atom = { AV_RL32("root") };
12364 int i;
12365
12366 668 mov->fc = s;
12367 668 mov->trak_index = -1;
12368 668 mov->primary_item_id = -1;
12369 668 mov->cur_item_id = -1;
12370 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
12371
2/2
✓ Branch 0 taken 666 times.
✓ Branch 1 taken 2 times.
668 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
12372 666 atom.size = avio_size(pb);
12373 else
12374 2 atom.size = INT64_MAX;
12375
12376 /* check MOV header */
12377 do {
12378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 668 times.
668 if (mov->moov_retry)
12379 ✗ avio_seek(pb, 0, SEEK_SET);
12380
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 665 times.
668 if ((err = mov_read_default(mov, pb, atom)) < 0) {
12381 3 av_log(s, AV_LOG_ERROR, "error reading header\n");
12382 3 return err;
12383 }
12384 1328 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
12385
6/10
✓ Branch 0 taken 663 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 639 times.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 24 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
665 !mov->found_moov && (!mov->found_iloc || !mov->found_iinf) && !mov->moov_retry++);
12386
3/6
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 641 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
665 if (!mov->found_moov && !mov->found_iloc && !mov->found_iinf) {
12387 ✗ av_log(s, AV_LOG_ERROR, "moov atom not found\n");
12388 ✗ return AVERROR_INVALIDDATA;
12389 }
12390 665 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
12391
12392
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 641 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
665 if (mov->found_iloc && mov->found_iinf) {
12393 24 err = mov_parse_heif_items(s);
12394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (err < 0)
12395 ✗ return err;
12396 }
12397 // prevent iloc and iinf boxes from being parsed while reading packets.
12398 // this is needed because an iinf box may have been parsed but ignored
12399 // for having old infe boxes which create no streams.
12400 665 mov->found_iloc = mov->found_iinf = 1;
12401
12402
2/2
✓ Branch 0 taken 663 times.
✓ Branch 1 taken 2 times.
665 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
12403
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 661 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
663 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
12404 2 mov_read_chapters(s);
12405
2/2
✓ Branch 0 taken 954 times.
✓ Branch 1 taken 663 times.
1617 for (i = 0; i < s->nb_streams; i++)
12406
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 926 times.
954 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
12407 28 mov_read_timecode_track(s, s->streams[i]);
12408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 926 times.
926 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
12409 ✗ mov_read_rtmd_track(s, s->streams[i]);
12410 }
12411 }
12412
12413 /* Create metadata stream groups. */
12414 665 err = mov_parse_cdsc_and_rndr_streams(s);
12415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (err < 0)
12416 ✗ return err;
12417
12418 /* copy timecode metadata from tmcd tracks to the related video streams */
12419 665 err = mov_parse_tmcd_streams(s);
12420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (err < 0)
12421 ✗ return err;
12422
12423 /* Create LCEVC stream groups. */
12424 665 err = mov_parse_lcevc_streams(s);
12425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (err < 0)
12426 ✗ return err;
12427
12428 /* Create Dolby Vision Profile 7 stream groups. */
12429 665 err = mov_parse_dovi_streams(s);
12430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (err < 0)
12431 ✗ return err;
12432
12433
2/2
✓ Branch 0 taken 1055 times.
✓ Branch 1 taken 665 times.
1720 for (i = 0; i < s->nb_streams; i++) {
12434 1055 AVStream *st = s->streams[i];
12435 1055 FFStream *const sti = ffstream(st);
12436 1055 MOVStreamContext *sc = st->priv_data;
12437 1055 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
12438 1055 fix_timescale(mov, sc);
12439
12440 /* Set the primary extradata based on the first Sample if it doesn't reference the first stsd entry. */
12441
6/6
✓ Branch 0 taken 904 times.
✓ Branch 1 taken 151 times.
✓ Branch 2 taken 798 times.
✓ Branch 3 taken 106 times.
✓ Branch 4 taken 730 times.
✓ Branch 5 taken 68 times.
1055 if (sc->stsc_count && sc->extradata_size && !sc->iamf &&
12442
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 727 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
730 sc->stsc_data[0].id > 1 && sc->stsc_data[0].id <= sc->stsd_count) {
12443 3 sc->last_stsd_index = sc->stsc_data[0].id - 1;
12444 3 av_freep(&st->codecpar->extradata);
12445 3 st->codecpar->extradata_size = sc->extradata_size[sc->last_stsd_index];
12446
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (sc->extradata_size[sc->last_stsd_index]) {
12447 3 st->codecpar->extradata = av_mallocz(sc->extradata_size[sc->last_stsd_index] + AV_INPUT_BUFFER_PADDING_SIZE);
12448
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata)
12449 ✗ return AVERROR(ENOMEM);
12450 3 memcpy(st->codecpar->extradata, sc->extradata[sc->last_stsd_index], sc->extradata_size[sc->last_stsd_index]);
12451 }
12452 }
12453
12454
2/2
✓ Branch 0 taken 483 times.
✓ Branch 1 taken 572 times.
1055 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
12455
2/2
✓ Branch 0 taken 183 times.
✓ Branch 1 taken 300 times.
483 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
12456 183 sti->skip_samples = st->codecpar->initial_padding;
12457 }
12458
5/6
✓ Branch 0 taken 506 times.
✓ Branch 1 taken 549 times.
✓ Branch 2 taken 384 times.
✓ Branch 3 taken 122 times.
✓ Branch 4 taken 384 times.
✗ Branch 5 not taken.
1055 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
12459 384 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
12460 384 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
12461
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1043 times.
1055 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
12462
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) {
12463 8 st->codecpar->width = sc->width;
12464 8 st->codecpar->height = sc->height;
12465 }
12466
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
12467 ✗ st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
12468
12469 ✗ for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
12470 ✗ dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
12471
12472 ✗ err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
12473 ✗ if (err < 0)
12474 ✗ return err;
12475
12476 ✗ av_freep(&st->codecpar->extradata);
12477 ✗ st->codecpar->extradata_size = 0;
12478
12479 ✗ err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
12480 st->codecpar);
12481 ✗ if (err < 0)
12482 ✗ return err;
12483 }
12484 }
12485
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1054 times.
1055 if (mov->handbrake_version &&
12486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
12487 ✗ st->codecpar->codec_id == AV_CODEC_ID_MP3) {
12488 ✗ av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
12489 ✗ sti->need_parsing = AVSTREAM_PARSE_FULL;
12490 }
12491 }
12492
12493
3/4
✓ Branch 0 taken 639 times.
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 639 times.
665 if (mov->trex_data || mov->use_mfra_for > 0) {
12494
2/2
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 26 times.
160 for (i = 0; i < s->nb_streams; i++) {
12495 134 AVStream *st = s->streams[i];
12496 134 MOVStreamContext *sc = st->priv_data;
12497
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 4 times.
134 if (sc->duration_for_fps > 0) {
12498 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
12499 130 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
12500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 130 times.
130 if (st->codecpar->bit_rate == INT64_MIN) {
12501 ✗ av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
12502 sc->data_size, sc->time_scale);
12503 ✗ st->codecpar->bit_rate = 0;
12504 ✗ if (s->error_recognition & AV_EF_EXPLODE)
12505 ✗ return AVERROR_INVALIDDATA;
12506 }
12507 }
12508 }
12509 }
12510
12511
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
665 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
12512 ✗ if (mov->bitrates[i]) {
12513 ✗ s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
12514 }
12515 }
12516
12517 665 ff_rfps_calculate(s);
12518
12519
2/2
✓ Branch 0 taken 1055 times.
✓ Branch 1 taken 665 times.
1720 for (i = 0; i < s->nb_streams; i++) {
12520 1055 AVStream *st = s->streams[i];
12521 1055 MOVStreamContext *sc = st->priv_data;
12522
12523
3/3
✓ Branch 0 taken 483 times.
✓ Branch 1 taken 506 times.
✓ Branch 2 taken 66 times.
1055 switch (st->codecpar->codec_type) {
12524 483 case AVMEDIA_TYPE_AUDIO:
12525 483 err = ff_replaygain_export(st, s->metadata);
12526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
483 if (err < 0)
12527 ✗ return err;
12528 483 break;
12529 506 case AVMEDIA_TYPE_VIDEO:
12530
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 494 times.
506 if (sc->display_matrix) {
12531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
12532 AV_PKT_DATA_DISPLAYMATRIX,
12533 12 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
12534 ✗ return AVERROR(ENOMEM);
12535
12536 12 sc->display_matrix = NULL;
12537 }
12538
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 500 times.
506 if (sc->stereo3d) {
12539
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,
12540 AV_PKT_DATA_STEREO3D,
12541 6 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
12542 ✗ return AVERROR(ENOMEM);
12543
12544 6 sc->stereo3d = NULL;
12545 }
12546
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 502 times.
506 if (sc->spherical) {
12547
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,
12548 AV_PKT_DATA_SPHERICAL,
12549 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
12550 ✗ return AVERROR(ENOMEM);
12551
12552 4 sc->spherical = NULL;
12553 }
12554
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 506 times.
506 if (sc->mastering) {
12555 ✗ if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
12556 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
12557 ✗ (uint8_t *)sc->mastering, sc->mastering_size, 0))
12558 ✗ return AVERROR(ENOMEM);
12559
12560 ✗ sc->mastering = NULL;
12561 }
12562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 506 times.
506 if (sc->coll) {
12563 ✗ if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
12564 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
12565 ✗ (uint8_t *)sc->coll, sc->coll_size, 0))
12566 ✗ return AVERROR(ENOMEM);
12567
12568 ✗ sc->coll = NULL;
12569 }
12570
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 502 times.
506 if (sc->ambient) {
12571
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,
12572 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
12573 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
12574 ✗ return AVERROR(ENOMEM);
12575
12576 4 sc->ambient = NULL;
12577 }
12578 506 break;
12579 }
12580 }
12581
12582 665 fix_stream_ids(s);
12583
12584 665 ff_configure_buffers_for_index(s, AV_TIME_BASE);
12585
12586
2/2
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 665 times.
1151 for (i = 0; i < mov->frag_index.nb_items; i++)
12587
2/2
✓ Branch 0 taken 476 times.
✓ Branch 1 taken 10 times.
486 if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset)
12588 476 mov->frag_index.item[i].headers_read = 1;
12589
12590 665 return 0;
12591 }
12592
12593 122690 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
12594 {
12595 122690 AVIndexEntry *sample = NULL;
12596 122690 int64_t best_dts = INT64_MAX;
12597 int i;
12598 122690 MOVContext *mov = s->priv_data;
12599
3/4
✓ Branch 0 taken 122690 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2847 times.
✓ Branch 3 taken 119843 times.
122690 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
12600
2/2
✓ Branch 0 taken 435935 times.
✓ Branch 1 taken 122690 times.
558625 for (i = 0; i < s->nb_streams; i++) {
12601 435935 AVStream *avst = s->streams[i];
12602 435935 FFStream *const avsti = ffstream(avst);
12603 435935 MOVStreamContext *msc = avst->priv_data;
12604
4/4
✓ Branch 0 taken 426418 times.
✓ Branch 1 taken 9517 times.
✓ Branch 2 taken 283371 times.
✓ Branch 3 taken 143047 times.
435935 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
12605 283371 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
12606 283371 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
12607
2/2
✓ Branch 0 taken 257324 times.
✓ Branch 1 taken 26047 times.
283371 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
12608 283371 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
12609
5/6
✓ Branch 0 taken 161291 times.
✓ Branch 1 taken 122080 times.
✓ Branch 2 taken 138600 times.
✓ Branch 3 taken 22691 times.
✓ Branch 4 taken 138600 times.
✗ Branch 5 not taken.
283371 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
12610
2/2
✓ Branch 0 taken 22691 times.
✓ Branch 1 taken 138600 times.
161291 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
12611
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 22691 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 22691 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 22691 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 20469 times.
✓ Branch 9 taken 2222 times.
22691 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
12612
4/4
✓ Branch 0 taken 12217 times.
✓ Branch 1 taken 8252 times.
✓ Branch 2 taken 2222 times.
✓ Branch 3 taken 12217 times.
22691 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
12613
3/4
✓ Branch 0 taken 796 times.
✓ Branch 1 taken 1426 times.
✓ Branch 2 taken 796 times.
✗ Branch 3 not taken.
2222 (dtsdiff > AV_TIME_BASE && dts < best_dts && mov->interleaved_read)))))) {
12614 131128 sample = current_sample;
12615 131128 best_dts = dts;
12616 131128 *st = avst;
12617 }
12618 }
12619 }
12620 122690 return sample;
12621 }
12622
12623 11 static int should_retry(AVIOContext *pb, int error_code) {
12624
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))
12625 11 return 0;
12626
12627 ✗ return 1;
12628 }
12629
12630 51 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
12631 {
12632 int ret;
12633 51 MOVContext *mov = s->priv_data;
12634
12635
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)
12636 1 target = mov->frag_index.item[index].moof_offset;
12637
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) {
12638 ✗ av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
12639 ✗ return AVERROR_INVALIDDATA;
12640 }
12641
12642 51 mov->next_root_atom = 0;
12643
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)
12644 50 index = search_frag_moof_offset(&mov->frag_index, target);
12645
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 &&
12646
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 mov->frag_index.item[index].moof_offset == target) {
12647
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 4 times.
42 if (index + 1 < mov->frag_index.nb_items)
12648 38 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
12649
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 6 times.
42 if (mov->frag_index.item[index].headers_read)
12650 36 return 0;
12651 6 mov->frag_index.item[index].headers_read = 1;
12652 }
12653
12654 15 mov->found_mdat = 0;
12655 15 mov->pssh_side_data = NULL;
12656
12657 15 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
12658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (ret < 0)
12659 ✗ return ret;
12660
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 7 times.
15 if (avio_feof(s->pb))
12661 8 return AVERROR_EOF;
12662 7 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
12663
12664 7 return 1;
12665 }
12666
12667 17 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
12668 {
12669 17 MOVStreamContext *sc = st->priv_data;
12670 uint8_t *side, *extradata;
12671 int extradata_size;
12672
12673 /* Save the current index. */
12674 17 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
12675
12676 /* Notify the decoder that extradata changed. */
12677 17 extradata_size = sc->extradata_size[sc->last_stsd_index];
12678 17 extradata = sc->extradata[sc->last_stsd_index];
12679
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) {
12680 14 side = av_packet_new_side_data(pkt,
12681 AV_PKT_DATA_NEW_EXTRADATA,
12682 extradata_size);
12683
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!side)
12684 ✗ return AVERROR(ENOMEM);
12685 14 memcpy(side, extradata, extradata_size);
12686 }
12687
12688 17 return 0;
12689 }
12690
12691 ✗ static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
12692 {
12693 /* We can't make assumptions about the structure of the payload,
12694 because it may include multiple cdat and cdt2 samples. */
12695 ✗ const uint32_t cdat = AV_RB32("cdat");
12696 ✗ const uint32_t cdt2 = AV_RB32("cdt2");
12697 ✗ int ret, out_size = 0;
12698
12699 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
12700 ✗ if (src_size < 10)
12701 ✗ return AVERROR_INVALIDDATA;
12702
12703 /* avoid an int overflow: */
12704 ✗ if ((src_size - 8) / 2 >= INT_MAX / 3)
12705 ✗ return AVERROR_INVALIDDATA;
12706
12707 ✗ ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
12708 ✗ if (ret < 0)
12709 ✗ return ret;
12710
12711 /* parse and re-format the c608 payload in one pass. */
12712 ✗ while (src_size >= 10) {
12713 ✗ const uint32_t atom_size = avio_rb32(pb);
12714 ✗ const uint32_t atom_type = avio_rb32(pb);
12715 ✗ const uint32_t data_size = atom_size - 8;
12716 ✗ const uint8_t cc_field =
12717 atom_type == cdat ? 1 :
12718 atom_type == cdt2 ? 2 :
12719 0;
12720
12721 /* account for bytes consumed for atom size and type. */
12722 ✗ src_size -= 8;
12723
12724 /* make sure the data size stays within the buffer boundaries. */
12725 ✗ if (data_size < 2 || data_size > src_size) {
12726 ✗ ret = AVERROR_INVALIDDATA;
12727 ✗ break;
12728 }
12729
12730 /* make sure the data size is consistent with N byte pairs. */
12731 ✗ if (data_size % 2 != 0) {
12732 ✗ ret = AVERROR_INVALIDDATA;
12733 ✗ break;
12734 }
12735
12736 ✗ if (!cc_field) {
12737 /* neither cdat or cdt2 ... skip it */
12738 ✗ avio_skip(pb, data_size);
12739 ✗ src_size -= data_size;
12740 ✗ continue;
12741 }
12742
12743 ✗ for (uint32_t i = 0; i < data_size; i += 2) {
12744 ✗ pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
12745 ✗ pkt->data[out_size + 1] = avio_r8(pb);
12746 ✗ pkt->data[out_size + 2] = avio_r8(pb);
12747 ✗ out_size += 3;
12748 ✗ src_size -= 2;
12749 }
12750 }
12751
12752 ✗ if (src_size > 0)
12753 /* skip any remaining unread portion of the input payload */
12754 ✗ avio_skip(pb, src_size);
12755
12756 ✗ av_shrink_packet(pkt, out_size);
12757 ✗ return ret;
12758 }
12759
12760 122033 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
12761 int64_t current_index, AVPacket *pkt)
12762 {
12763 122033 MOVContext *mov = s->priv_data;
12764 122033 MOVStreamContext *sc = st->priv_data;
12765
12766 122033 pkt->stream_index = sc->ffindex;
12767 122033 pkt->dts = sample->timestamp;
12768
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 121713 times.
122033 if (sample->flags & AVINDEX_DISCARD_FRAME) {
12769 320 pkt->flags |= AV_PKT_FLAG_DISCARD;
12770 }
12771
4/4
✓ Branch 0 taken 102177 times.
✓ Branch 1 taken 19856 times.
✓ Branch 2 taken 102165 times.
✓ Branch 3 taken 12 times.
122033 if (sc->stts_count && sc->tts_index < sc->tts_count)
12772 102165 pkt->duration = sc->tts_data[sc->tts_index].duration;
12773
3/4
✓ Branch 0 taken 4729 times.
✓ Branch 1 taken 117304 times.
✓ Branch 2 taken 4729 times.
✗ Branch 3 not taken.
122033 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
12774 4729 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
12775 } else {
12776
2/2
✓ Branch 0 taken 15865 times.
✓ Branch 1 taken 101439 times.
117304 if (pkt->duration == 0) {
12777 15865 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
12778
2/2
✓ Branch 0 taken 15707 times.
✓ Branch 1 taken 158 times.
15865 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
12779
2/2
✓ Branch 0 taken 15756 times.
✓ Branch 1 taken 109 times.
15865 if (next_dts >= pkt->dts)
12780 15756 pkt->duration = next_dts - pkt->dts;
12781 }
12782 117304 pkt->pts = pkt->dts;
12783 }
12784
12785
4/4
✓ Branch 0 taken 103090 times.
✓ Branch 1 taken 18943 times.
✓ Branch 2 taken 100202 times.
✓ Branch 3 taken 2888 times.
122033 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && !mov->fragment.found_tfhd &&
12786
2/2
✓ Branch 1 taken 240 times.
✓ Branch 2 taken 99962 times.
100202 sc->current_sample >= ffstream(st)->nb_index_entries) {
12787 240 int64_t pts = av_rescale_q(pkt->pts, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12788 240 int64_t total = av_rescale_q(st->duration, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12789 240 int64_t duration = pkt->duration;
12790
12791
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 238 times.
240 if (st->duration < pkt->pts) {
12792 2 duration = 0;
12793 } else
12794 238 duration = FFMIN(duration, (uint64_t)st->duration - pkt->pts);
12795
12796 240 duration = av_rescale_q(duration, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12797
12798
2/2
✓ Branch 1 taken 197 times.
✓ Branch 2 taken 43 times.
240 if (!ffstream(st)->first_discard_sample)
12799 197 ffstream(st)->first_discard_sample = av_sat_add64(pts, duration);
12800
2/2
✓ Branch 1 taken 197 times.
✓ Branch 2 taken 43 times.
240 if (!ffstream(st)->last_discard_sample)
12801 197 ffstream(st)->last_discard_sample = total;
12802 }
12803
12804
4/4
✓ Branch 0 taken 102177 times.
✓ Branch 1 taken 19856 times.
✓ Branch 2 taken 102165 times.
✓ Branch 3 taken 12 times.
122033 if (sc->tts_data && sc->tts_index < sc->tts_count) {
12805 /* update tts context */
12806 102165 sc->tts_sample++;
12807
1/2
✓ Branch 0 taken 102165 times.
✗ Branch 1 not taken.
102165 if (sc->tts_index < sc->tts_count &&
12808
1/2
✓ Branch 0 taken 102165 times.
✗ Branch 1 not taken.
102165 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
12809 102165 sc->tts_index++;
12810 102165 sc->tts_sample = 0;
12811 }
12812 }
12813
12814
4/4
✓ Branch 0 taken 1122 times.
✓ Branch 1 taken 120911 times.
✓ Branch 2 taken 990 times.
✓ Branch 3 taken 132 times.
122033 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
12815 990 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
12816 990 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
12817
2/2
✓ Branch 0 taken 329 times.
✓ Branch 1 taken 661 times.
990 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
12818 }
12819 122033 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
12820 122033 pkt->pos = sample->pos;
12821
12822 /* Multiple stsd handling. */
12823
2/2
✓ Branch 0 taken 115833 times.
✓ Branch 1 taken 6200 times.
122033 if (sc->stsc_data) {
12824
1/2
✓ Branch 0 taken 115833 times.
✗ Branch 1 not taken.
115833 if (sc->stsc_data[sc->stsc_index].id > 0 &&
12825
2/2
✓ Branch 0 taken 115727 times.
✓ Branch 1 taken 106 times.
115833 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
12826
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 115710 times.
115727 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
12827 17 int ret = mov_change_extradata(st, pkt);
12828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (ret < 0)
12829 ✗ return ret;
12830 }
12831
12832 /* Update the stsc index for the next sample */
12833 115833 sc->stsc_sample++;
12834
2/2
✓ Branch 1 taken 57569 times.
✓ Branch 2 taken 58264 times.
115833 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
12835
2/2
✓ Branch 1 taken 1225 times.
✓ Branch 2 taken 56344 times.
57569 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
12836 1225 sc->stsc_index++;
12837 1225 sc->stsc_sample = 0;
12838 }
12839 }
12840
12841 122033 return 0;
12842 }
12843
12844 113349 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
12845 {
12846 113349 MOVContext *mov = s->priv_data;
12847 MOVStreamContext *sc;
12848 AVIndexEntry *sample;
12849 113349 AVStream *st = NULL;
12850 113349 FFStream *avsti = NULL;
12851 int64_t current_index;
12852 int ret;
12853 int i;
12854 113349 mov->fc = s;
12855 9341 retry:
12856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 122690 times.
122690 if (s->pb->pos == 0) {
12857
12858 // Discard current fragment index
12859 ✗ if (mov->frag_index.allocated_size > 0) {
12860 ✗ for(int i = 0; i < mov->frag_index.nb_items; i++) {
12861 ✗ av_freep(&mov->frag_index.item[i].stream_info);
12862 }
12863 ✗ av_freep(&mov->frag_index.item);
12864 ✗ mov->frag_index.nb_items = 0;
12865 ✗ mov->frag_index.allocated_size = 0;
12866 ✗ mov->frag_index.current = -1;
12867 ✗ mov->frag_index.complete = 0;
12868 }
12869
12870 ✗ for (i = 0; i < s->nb_streams; i++) {
12871 ✗ AVStream *avst = s->streams[i];
12872 ✗ MOVStreamContext *msc = avst->priv_data;
12873
12874 // Clear current sample
12875 ✗ mov_current_sample_set(msc, 0);
12876 ✗ msc->tts_index = 0;
12877
12878 // Discard current index entries
12879 ✗ avsti = ffstream(avst);
12880 ✗ if (avsti->index_entries_allocated_size > 0) {
12881 ✗ av_freep(&avsti->index_entries);
12882 ✗ avsti->index_entries_allocated_size = 0;
12883 ✗ avsti->nb_index_entries = 0;
12884 }
12885 }
12886
12887 ✗ if ((ret = mov_switch_root(s, -1, -1)) < 0)
12888 ✗ return ret;
12889 }
12890 122690 sample = mov_find_next_sample(s, &st);
12891
6/6
✓ Branch 0 taken 122080 times.
✓ Branch 1 taken 610 times.
✓ Branch 2 taken 3448 times.
✓ Branch 3 taken 118632 times.
✓ Branch 4 taken 36 times.
✓ Branch 5 taken 3412 times.
122690 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
12892
2/2
✓ Branch 0 taken 596 times.
✓ Branch 1 taken 50 times.
646 if (!mov->next_root_atom)
12893 596 return AVERROR_EOF;
12894
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)
12895 8 return ret;
12896 42 goto retry;
12897 }
12898 122044 sc = st->priv_data;
12899 /* must be done just before reading, to avoid infinite loop on sample */
12900 122044 current_index = sc->current_index;
12901 122044 mov_current_sample_inc(sc);
12902
12903
2/2
✓ Branch 0 taken 3412 times.
✓ Branch 1 taken 118632 times.
122044 if (mov->next_root_atom) {
12904 3412 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
12905 3412 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
12906 }
12907
12908
4/4
✓ Branch 0 taken 9309 times.
✓ Branch 1 taken 112735 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 9299 times.
122044 if (st->discard != AVDISCARD_ALL || sc->iamf) {
12909 112745 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
12910
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 112738 times.
112745 if (ret64 != sample->pos) {
12911 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
12912 sc->ffindex, sample->pos);
12913
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
12914 ✗ mov_current_sample_dec(sc);
12915
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
12916 7 return (int)ret64;
12917 }
12918 ✗ return AVERROR_INVALIDDATA;
12919 }
12920
12921
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 112738 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
112738 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
12922 ✗ av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
12923 ✗ goto retry;
12924 }
12925
12926
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 112738 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
112738 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
12927 ✗ ret = get_eia608_packet(sc->pb, pkt, sample->size);
12928 #if CONFIG_IAMFDEC
12929
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 112644 times.
112738 else if (sc->iamf) {
12930 int64_t pts, dts, pos, duration;
12931 94 int flags, size = sample->size;
12932 94 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
12933 94 pts = pkt->pts; dts = pkt->dts;
12934 94 pos = pkt->pos; flags = pkt->flags;
12935 94 duration = pkt->duration;
12936
3/4
✓ Branch 0 taken 572 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
✓ Branch 3 taken 94 times.
572 while (!ret && size > 0) {
12937 478 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
12938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
478 if (ret < 0) {
12939 ✗ if (should_retry(sc->pb, ret))
12940 ✗ mov_current_sample_dec(sc);
12941 ✗ return ret;
12942 }
12943 478 size -= ret;
12944
12945
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 358 times.
478 if (pkt->flags & AV_PKT_FLAG_DISCARD) {
12946 120 av_packet_unref(pkt);
12947 120 ret = 0;
12948 120 continue;
12949 }
12950 358 pkt->pts = pts; pkt->dts = dts;
12951 358 pkt->pos = pos; pkt->flags |= flags;
12952 358 pkt->duration = duration;
12953 358 ret = ff_buffer_packet(s, pkt);
12954 }
12955
1/2
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
94 if (!ret)
12956 94 return FFERROR_REDO;
12957 }
12958 #endif
12959
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 112641 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
112647 else if (st->codecpar->codec_id == AV_CODEC_ID_APV && sample->size > 4) {
12960 3 uint32_t au_size = avio_rb32(sc->pb);
12961 3 int explode = !!(mov->fc->error_recognition & AV_EF_EXPLODE);
12962
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (au_size > sample->size - 4) {
12963 ✗ av_log(s, explode ? AV_LOG_ERROR : AV_LOG_WARNING,
12964 "APV au_size %u exceeds sample body %d\n",
12965 ✗ au_size, sample->size - 4);
12966 ✗ if (explode)
12967 ✗ return AVERROR_INVALIDDATA;
12968 ✗ au_size = sample->size - 4;
12969 }
12970 3 ret = av_get_packet(sc->pb, pkt, au_size);
12971 } else
12972 112641 ret = av_get_packet(sc->pb, pkt, sample->size);
12973
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 112640 times.
112644 if (ret < 0) {
12974
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (should_retry(sc->pb, ret)) {
12975 ✗ mov_current_sample_dec(sc);
12976 }
12977 4 return ret;
12978 }
12979 #if CONFIG_DV_DEMUXER
12980
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 112640 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
112640 if (mov->dv_demux && sc->dv_audio_container) {
12981 ✗ ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
12982 ✗ av_packet_unref(pkt);
12983 ✗ if (ret < 0)
12984 ✗ return ret;
12985 ✗ ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
12986 ✗ if (ret < 0)
12987 ✗ return ret;
12988 }
12989 #endif
12990
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 112622 times.
112640 if (sc->has_palette) {
12991 uint8_t *pal;
12992
12993 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
12994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
12995 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
12996 } else {
12997 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
12998 18 sc->has_palette = 0;
12999 }
13000 }
13001
4/6
✓ Branch 0 taken 3129 times.
✓ Branch 1 taken 109511 times.
✓ Branch 3 taken 3129 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3129 times.
✗ Branch 6 not taken.
112640 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
13002
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3129 times.
3129 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
13003 ✗ ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
13004 }
13005 }
13006
13007 121939 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
13008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 121939 times.
121939 if (ret < 0)
13009 ✗ return ret;
13010
13011
2/2
✓ Branch 0 taken 9299 times.
✓ Branch 1 taken 112640 times.
121939 if (st->discard == AVDISCARD_ALL)
13012 9299 goto retry;
13013
13014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112640 times.
112640 if (mov->aax_mode)
13015 ✗ aax_filter(pkt->data, pkt->size, mov);
13016
13017 112640 ret = cenc_filter(mov, st, sc, pkt, current_index);
13018
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112640 times.
112640 if (ret < 0) {
13019 ✗ return ret;
13020 }
13021
13022 112640 return 0;
13023 }
13024
13025 537 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
13026 {
13027 537 MOVContext *mov = s->priv_data;
13028 int index;
13029
13030
2/2
✓ Branch 0 taken 509 times.
✓ Branch 1 taken 28 times.
537 if (!mov->frag_index.complete)
13031 509 return 0;
13032
13033 28 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
13034
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 24 times.
28 if (index < 0)
13035 4 index = 0;
13036
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (!mov->frag_index.item[index].headers_read)
13037 1 return mov_switch_root(s, -1, index);
13038
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (index + 1 < mov->frag_index.nb_items)
13039 27 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
13040
13041 27 return 0;
13042 }
13043
13044 ✗ static int is_open_key_sample(const MOVStreamContext *sc, int sample)
13045 {
13046 // TODO: a bisect search would scale much better
13047 ✗ for (int i = 0; i < sc->open_key_samples_count; i++) {
13048 ✗ const int oks = sc->open_key_samples[i];
13049 ✗ if (oks == sample)
13050 ✗ return 1;
13051 ✗ if (oks > sample) /* list is monotically increasing so we can stop early */
13052 ✗ break;
13053 }
13054 ✗ return 0;
13055 }
13056
13057 /*
13058 * Some key sample may be key frames but not IDR frames, so a random access to
13059 * them may not be allowed.
13060 */
13061 335 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
13062 {
13063 335 MOVStreamContext *sc = st->priv_data;
13064 335 FFStream *const sti = ffstream(st);
13065 int64_t key_sample_dts, key_sample_pts;
13066
13067
1/2
✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
335 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
13068 335 return 1;
13069
13070 ✗ if (sample >= sc->sample_offsets_count)
13071 ✗ return 1;
13072
13073 ✗ av_assert0(sample >= 0);
13074 ✗ key_sample_dts = sti->index_entries[sample].timestamp;
13075 ✗ key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
13076
13077 /*
13078 * If the sample needs to be presented before an open key sample, they may
13079 * not be decodable properly, even though they come after in decoding
13080 * order.
13081 */
13082 ✗ if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
13083 ✗ return 0;
13084
13085 ✗ return 1;
13086 }
13087
13088 537 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
13089 {
13090 537 MOVStreamContext *sc = st->priv_data;
13091 537 FFStream *const sti = ffstream(st);
13092 int sample, time_sample, ret, requested_sample;
13093 int64_t next_ts;
13094 unsigned int i;
13095
13096 // Here we consider timestamp to be PTS, hence try to offset it so that we
13097 // can search over the DTS timeline.
13098 537 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
13099
13100 537 ret = mov_seek_fragment(s, st, timestamp);
13101
1/2
✓ Branch 0 taken 537 times.
✗ Branch 1 not taken.
537 if (ret < 0)
13102 ✗ return ret;
13103
13104 for (;;) {
13105 537 sample = av_index_search_timestamp(st, timestamp, flags);
13106 537 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
13107
5/6
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 435 times.
✓ Branch 2 taken 102 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 76 times.
✓ Branch 5 taken 26 times.
537 if (sample < 0 && sti->nb_index_entries && timestamp < sti->index_entries[0].timestamp)
13108 76 sample = 0;
13109
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 511 times.
537 if (sample < 0) /* not sure what to do */
13110 26 return AVERROR_INVALIDDATA;
13111
13112
3/4
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 176 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 335 times.
511 if (!sample || can_seek_to_key_sample(st, sample, timestamp))
13113 break;
13114
13115 ✗ next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
13116 ✗ requested_sample = av_index_search_timestamp(st, next_ts, flags);
13117 ✗ if (requested_sample < 0)
13118 ✗ return AVERROR_INVALIDDATA;
13119
13120 // If we've reached a different sample trying to find a good pts to
13121 // seek to, give up searching because we'll end up seeking back to
13122 // sample 0 on every seek.
13123 ✗ if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
13124 ✗ break;
13125
13126 ✗ timestamp = next_ts;
13127 }
13128
13129 511 mov_current_sample_set(sc, sample);
13130 511 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
13131 /* adjust time to sample index */
13132
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 125 times.
511 if (sc->tts_data) {
13133 386 time_sample = 0;
13134
1/2
✓ Branch 0 taken 65225 times.
✗ Branch 1 not taken.
65225 for (i = 0; i < sc->tts_count; i++) {
13135 65225 int next = time_sample + sc->tts_data[i].count;
13136
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 64839 times.
65225 if (next > sc->current_sample) {
13137 386 sc->tts_index = i;
13138 386 sc->tts_sample = sc->current_sample - time_sample;
13139 386 break;
13140 }
13141 64839 time_sample = next;
13142 }
13143 }
13144
13145 /* adjust stsd index */
13146
2/2
✓ Branch 0 taken 483 times.
✓ Branch 1 taken 28 times.
511 if (sc->chunk_count) {
13147 483 time_sample = 0;
13148
1/2
✓ Branch 0 taken 563 times.
✗ Branch 1 not taken.
563 for (i = 0; i < sc->stsc_count; i++) {
13149 563 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
13150
2/2
✓ Branch 0 taken 483 times.
✓ Branch 1 taken 80 times.
563 if (next > sc->current_sample) {
13151 483 sc->stsc_index = i;
13152 483 sc->stsc_sample = sc->current_sample - time_sample;
13153 483 break;
13154 }
13155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 av_assert0(next == (int)next);
13156 80 time_sample = next;
13157 }
13158 }
13159
13160 511 return sample;
13161 }
13162
13163 511 static int64_t mov_get_skip_samples(AVStream *st, int sample)
13164 {
13165 511 FFStream *const sti = ffstream(st);
13166 511 int64_t first_ts = sti->index_entries[0].timestamp;
13167 511 int64_t ts = sti->index_entries[sample].timestamp;
13168 int64_t off;
13169
13170
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 297 times.
511 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
13171 214 return 0;
13172
13173 /* compute skip samples according to stream initial_padding, seek ts and first ts */
13174 297 off = av_rescale_q(ts - first_ts, st->time_base,
13175 297 (AVRational){1, st->codecpar->sample_rate});
13176 297 return FFMAX(st->codecpar->initial_padding - off, 0);
13177 }
13178
13179 461 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
13180 {
13181 461 MOVContext *mc = s->priv_data;
13182 AVStream *st;
13183 FFStream *sti;
13184 int sample;
13185 int i;
13186
13187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 461 times.
461 if (stream_index >= s->nb_streams)
13188 ✗ return AVERROR_INVALIDDATA;
13189
13190 461 st = s->streams[stream_index];
13191 461 sti = ffstream(st);
13192 461 sample = mov_seek_stream(s, st, sample_time, flags);
13193
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 435 times.
461 if (sample < 0)
13194 26 return sample;
13195
13196
1/2
✓ Branch 0 taken 435 times.
✗ Branch 1 not taken.
435 if (mc->seek_individually) {
13197 /* adjust seek timestamp to found sample timestamp */
13198 435 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
13199 435 sti->skip_samples = mov_get_skip_samples(st, sample);
13200
13201
2/2
✓ Branch 0 taken 511 times.
✓ Branch 1 taken 435 times.
946 for (i = 0; i < s->nb_streams; i++) {
13202 511 AVStream *const st = s->streams[i];
13203 511 FFStream *const sti = ffstream(st);
13204 int64_t timestamp;
13205
13206
2/2
✓ Branch 0 taken 435 times.
✓ Branch 1 taken 76 times.
511 if (stream_index == i)
13207 435 continue;
13208
13209 76 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
13210 76 sample = mov_seek_stream(s, st, timestamp, flags);
13211
1/2
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
76 if (sample >= 0)
13212 76 sti->skip_samples = mov_get_skip_samples(st, sample);
13213 }
13214 } else {
13215 ✗ for (i = 0; i < s->nb_streams; i++) {
13216 MOVStreamContext *sc;
13217 ✗ st = s->streams[i];
13218 ✗ sc = st->priv_data;
13219 ✗ mov_current_sample_set(sc, 0);
13220 }
13221 ✗ while (1) {
13222 MOVStreamContext *sc;
13223 ✗ AVIndexEntry *entry = mov_find_next_sample(s, &st);
13224 ✗ if (!entry)
13225 ✗ return AVERROR_INVALIDDATA;
13226 ✗ sc = st->priv_data;
13227 ✗ if (sc->ffindex == stream_index && sc->current_sample == sample)
13228 ✗ break;
13229 ✗ mov_current_sample_inc(sc);
13230 }
13231 }
13232 435 return 0;
13233 }
13234
13235 #define OFFSET(x) offsetof(MOVContext, x)
13236 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
13237 static const AVOption mov_options[] = {
13238 {"use_absolute_path",
13239 "allow using absolute path when opening alias, this is a possible security issue",
13240 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
13241 0, 1, FLAGS},
13242 {"seek_streams_individually",
13243 "Seek each stream individually to the closest point",
13244 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
13245 0, 1, FLAGS},
13246 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
13247 0, 1, FLAGS},
13248 {"advanced_editlist",
13249 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
13250 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
13251 0, 1, FLAGS},
13252 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
13253 0, 1, FLAGS},
13254 {"use_mfra_for",
13255 "use mfra for fragment timestamps",
13256 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
13257 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
13258 .unit = "use_mfra_for"},
13259 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
13260 FLAGS, .unit = "use_mfra_for" },
13261 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
13262 FLAGS, .unit = "use_mfra_for" },
13263 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
13264 FLAGS, .unit = "use_mfra_for" },
13265 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
13266 0, 1, FLAGS},
13267 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
13268 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
13269 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
13270 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
13271 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
13272 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
13273 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
13274 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
13275 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
13276 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
13277 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
13278 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
13279 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
13280 .flags = AV_OPT_FLAG_DECODING_PARAM },
13281 { "decryption_key", "The default media decryption key (hex)", OFFSET(decryption_default_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
13282 { "decryption_keys", "The media decryption keys by KID (hex)", OFFSET(decryption_keys), AV_OPT_TYPE_DICT, .flags = AV_OPT_FLAG_DECODING_PARAM },
13283 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
13284 {.i64 = 0}, 0, 1, FLAGS },
13285 { "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 },
13286 { "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 },
13287
13288 { NULL },
13289 };
13290
13291 static const AVClass mov_class = {
13292 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
13293 .item_name = av_default_item_name,
13294 .option = mov_options,
13295 .version = LIBAVUTIL_VERSION_INT,
13296 };
13297
13298 const FFInputFormat ff_mov_demuxer = {
13299 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
13300 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
13301 .p.priv_class = &mov_class,
13302 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4v,m4b,ism,ismv,isma,f4v,avif,heic,heif",
13303 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
13304 .priv_data_size = sizeof(MOVContext),
13305 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
13306 .read_probe = mov_probe,
13307 .read_header = mov_read_header,
13308 .read_packet = mov_read_packet,
13309 .read_close = mov_read_close,
13310 .read_seek = mov_read_seek,
13311 };
13312