FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2025-07-28 20:30:09
Exec Total Coverage
Lines: 4303 6805 63.2%
Functions: 173 212 81.6%
Branches: 2428 4582 53.0%

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
32 #include "libavutil/attributes.h"
33 #include "libavutil/bprint.h"
34 #include "libavutil/channel_layout.h"
35 #include "libavutil/internal.h"
36 #include "libavutil/intreadwrite.h"
37 #include "libavutil/intfloat.h"
38 #include "libavutil/mathematics.h"
39 #include "libavutil/avassert.h"
40 #include "libavutil/avstring.h"
41 #include "libavutil/dict.h"
42 #include "libavutil/display.h"
43 #include "libavutil/mem.h"
44 #include "libavutil/opt.h"
45 #include "libavutil/aes.h"
46 #include "libavutil/aes_ctr.h"
47 #include "libavutil/pixdesc.h"
48 #include "libavutil/sha.h"
49 #include "libavutil/spherical.h"
50 #include "libavutil/stereo3d.h"
51 #include "libavutil/timecode.h"
52 #include "libavutil/uuid.h"
53 #include "libavcodec/ac3tab.h"
54 #include "libavcodec/flac.h"
55 #include "libavcodec/hevc/hevc.h"
56 #include "libavcodec/mpegaudiodecheader.h"
57 #include "libavcodec/mlp_parse.h"
58 #include "avformat.h"
59 #include "internal.h"
60 #include "avio_internal.h"
61 #include "demux.h"
62 #include "dvdclut.h"
63 #include "iamf_parse.h"
64 #include "iamf_reader.h"
65 #include "dovi_isom.h"
66 #include "riff.h"
67 #include "isom.h"
68 #include "libavcodec/get_bits.h"
69 #include "id3v1.h"
70 #include "mov_chan.h"
71 #include "replaygain.h"
72
73 #if CONFIG_ZLIB
74 #include <zlib.h>
75 #endif
76
77 #include "qtpalette.h"
78
79 /* those functions parse an atom */
80 /* links atom IDs to parse functions */
81 typedef struct MOVParseTableEntry {
82 uint32_t type;
83 int (*parse)(MOVContext *ctx, AVIOContext *pb, MOVAtom atom);
84 } MOVParseTableEntry;
85
86 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom);
87 static int mov_read_mfra(MOVContext *c, AVIOContext *f);
88 static void mov_free_stream_context(AVFormatContext *s, AVStream *st);
89
90 24 static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
91 unsigned len, const char *key)
92 {
93 char buf[16];
94
95 24 short current, total = 0;
96 24 avio_rb16(pb); // unknown
97 24 current = avio_rb16(pb);
98
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (len >= 6)
99 24 total = avio_rb16(pb);
100
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19 times.
24 if (!total)
101 5 snprintf(buf, sizeof(buf), "%d", current);
102 else
103 19 snprintf(buf, sizeof(buf), "%d/%d", current, total);
104 24 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
105 24 av_dict_set(&c->fc->metadata, key, buf, 0);
106
107 24 return 0;
108 }
109
110 static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
111 unsigned len, const char *key)
112 {
113 /* bypass padding bytes */
114 avio_r8(pb);
115 avio_r8(pb);
116 avio_r8(pb);
117
118 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
119 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
120
121 return 0;
122 }
123
124 26 static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
125 unsigned len, const char *key)
126 {
127 26 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
128 26 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
129
130 26 return 0;
131 }
132
133 10 static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
134 unsigned len, const char *key)
135 {
136 short genre;
137
138 10 avio_r8(pb); // unknown
139
140 10 genre = avio_r8(pb);
141
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (genre < 1 || genre > ID3v1_GENRE_MAX)
142 return 0;
143 10 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
144 10 av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
145
146 10 return 0;
147 }
148
149 static const uint32_t mac_to_unicode[128] = {
150 0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
151 0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
152 0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,
153 0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,
154 0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,
155 0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,
156 0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,
157 0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,
158 0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,
159 0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,
160 0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,
161 0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,
162 0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,
163 0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,
164 0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,
165 0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7,
166 };
167
168 330 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
169 char *dst, int dstlen)
170 {
171 330 char *p = dst;
172 330 char *end = dst+dstlen-1;
173 int i;
174
175
2/2
✓ Branch 0 taken 2945 times.
✓ Branch 1 taken 330 times.
3275 for (i = 0; i < len; i++) {
176 2945 uint8_t t, c = avio_r8(pb);
177
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2945 times.
2945 if (p >= end)
179 continue;
180
181
2/2
✓ Branch 0 taken 2937 times.
✓ Branch 1 taken 8 times.
2945 if (c < 0x80)
182 2937 *p++ = c;
183
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 else if (p < end)
184
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;);
185 }
186 330 *p = 0;
187 330 return p - dst;
188 }
189
190 /**
191 * Get the current item in the parsing process.
192 */
193 106 static HEIFItem *heif_cur_item(MOVContext *c)
194 {
195 106 HEIFItem *item = NULL;
196
197
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 12 times.
210 for (int i = 0; i < c->nb_heif_item; i++) {
198
3/4
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104 times.
✓ Branch 3 taken 94 times.
198 if (!c->heif_item[i] || c->heif_item[i]->item_id != c->cur_item_id)
199 104 continue;
200
201 94 item = c->heif_item[i];
202 94 break;
203 }
204
205 106 return item;
206 }
207
208 /**
209 * Get the current stream in the parsing process. This can either be the
210 * latest stream added to the context, or the stream referenced by an item.
211 */
212 208 static AVStream *get_curr_st(MOVContext *c)
213 {
214 208 AVStream *st = NULL;
215 HEIFItem *item;
216
217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 208 times.
208 if (c->fc->nb_streams < 1)
218 return NULL;
219
220
2/2
✓ Branch 0 taken 171 times.
✓ Branch 1 taken 37 times.
208 if (c->cur_item_id == -1)
221 171 return c->fc->streams[c->fc->nb_streams-1];
222
223 37 item = heif_cur_item(c);
224
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if (item)
225 37 st = item->st;
226
227 37 return st;
228 }
229
230 14 static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
231 {
232 AVStream *st;
233 MOVStreamContext *sc;
234 enum AVCodecID id;
235 int ret;
236
237
2/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
14 switch (type) {
238 7 case 0xd: id = AV_CODEC_ID_MJPEG; break;
239 7 case 0xe: id = AV_CODEC_ID_PNG; break;
240 case 0x1b: id = AV_CODEC_ID_BMP; break;
241 default:
242 av_log(c->fc, AV_LOG_WARNING, "Unknown cover type: 0x%x.\n", type);
243 avio_skip(pb, len);
244 return 0;
245 }
246
247 14 sc = av_mallocz(sizeof(*sc));
248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!sc)
249 return AVERROR(ENOMEM);
250 14 ret = ff_add_attached_pic(c->fc, NULL, pb, NULL, len);
251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0) {
252 av_free(sc);
253 return ret;
254 }
255 14 st = c->fc->streams[c->fc->nb_streams - 1];
256 14 st->priv_data = sc;
257 14 sc->id = st->id;
258 14 sc->refcount = 1;
259
260
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 if (st->attached_pic.size >= 8 && id != AV_CODEC_ID_BMP) {
261
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
262 7 id = AV_CODEC_ID_PNG;
263 } else {
264 7 id = AV_CODEC_ID_MJPEG;
265 }
266 }
267 14 st->codecpar->codec_id = id;
268
269 14 return 0;
270 }
271
272 // 3GPP TS 26.244
273 static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
274 {
275 char language[4] = { 0 };
276 char buf[200], place[100];
277 uint16_t langcode = 0;
278 double longitude, latitude, altitude;
279 const char *key = "location";
280
281 if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) {
282 av_log(c->fc, AV_LOG_ERROR, "loci too short\n");
283 return AVERROR_INVALIDDATA;
284 }
285
286 avio_skip(pb, 4); // version+flags
287 langcode = avio_rb16(pb);
288 ff_mov_lang_to_iso639(langcode, language);
289 len -= 6;
290
291 len -= avio_get_str(pb, len, place, sizeof(place));
292 if (len < 1) {
293 av_log(c->fc, AV_LOG_ERROR, "place name too long\n");
294 return AVERROR_INVALIDDATA;
295 }
296 avio_skip(pb, 1); // role
297 len -= 1;
298
299 if (len < 12) {
300 av_log(c->fc, AV_LOG_ERROR,
301 "loci too short (%u bytes left, need at least %d)\n", len, 12);
302 return AVERROR_INVALIDDATA;
303 }
304 longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
305 latitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
306 altitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
307
308 // Try to output in the same format as the ?xyz field
309 snprintf(buf, sizeof(buf), "%+08.4f%+09.4f", latitude, longitude);
310 if (altitude)
311 av_strlcatf(buf, sizeof(buf), "%+f", altitude);
312 av_strlcatf(buf, sizeof(buf), "/%s", place);
313
314 if (*language && strcmp(language, "und")) {
315 char key2[16];
316 snprintf(key2, sizeof(key2), "%s-%s", key, language);
317 av_dict_set(&c->fc->metadata, key2, buf, 0);
318 }
319 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
320 return av_dict_set(&c->fc->metadata, key, buf, 0);
321 }
322
323 static int mov_metadata_hmmt(MOVContext *c, AVIOContext *pb, unsigned len)
324 {
325 int i, n_hmmt;
326
327 if (len < 2)
328 return 0;
329 if (c->ignore_chapters)
330 return 0;
331
332 n_hmmt = avio_rb32(pb);
333 if (n_hmmt > len / 4)
334 return AVERROR_INVALIDDATA;
335 for (i = 0; i < n_hmmt && !pb->eof_reached; i++) {
336 int moment_time = avio_rb32(pb);
337 avpriv_new_chapter(c->fc, i, av_make_q(1, 1000), moment_time, AV_NOPTS_VALUE, NULL);
338 }
339 if (avio_feof(pb))
340 return AVERROR_INVALIDDATA;
341 return 0;
342 }
343
344 474 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
345 {
346 474 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
347 474 char key2[32], language[4] = {0};
348 474 char *str = NULL;
349 474 const char *key = NULL;
350 474 uint16_t langcode = 0;
351 474 uint32_t data_type = 0, str_size_alloc;
352 uint64_t str_size;
353 474 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
354 474 int raw = 0;
355 474 int num = 0;
356 AVDictionary **metadata;
357
358
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 445 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
474 if (c->trak_index >= 0 && c->trak_index < c->fc->nb_streams)
359 29 metadata = &c->fc->streams[c->trak_index]->metadata;
360 else
361 445 metadata = &c->fc->metadata;
362
363
25/74
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 158 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 13 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 12 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 10 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 not taken.
✓ Branch 23 taken 13 times.
✗ Branch 24 not taken.
✗ 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 taken 12 times.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✓ Branch 39 taken 17 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 16 times.
✓ Branch 42 taken 3 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 8 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 4 times.
✓ Branch 47 taken 16 times.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✓ Branch 51 taken 2 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 3 times.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✓ Branch 58 taken 5 times.
✓ Branch 59 taken 5 times.
✓ Branch 60 taken 42 times.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✓ Branch 67 taken 59 times.
✓ Branch 68 taken 50 times.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✓ Branch 72 taken 1 times.
✓ Branch 73 taken 5 times.
474 switch (atom.type) {
364 3 case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break;
365 3 case MKTAG( '@','P','R','Q'): key = "quicktime_version"; raw = 1; break;
366 2 case MKTAG( 'X','M','P','_'):
367
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->export_xmp) { key = "xmp"; raw = 1; } break;
368 12 case MKTAG( 'a','A','R','T'): key = "album_artist"; break;
369 case MKTAG( 'a','k','I','D'): key = "account_type";
370 parse = mov_metadata_int8_no_padding; break;
371 case MKTAG( 'a','p','I','D'): key = "account_id"; break;
372 case MKTAG( 'c','a','t','g'): key = "category"; break;
373 13 case MKTAG( 'c','p','i','l'): key = "compilation";
374 13 parse = mov_metadata_int8_no_padding; break;
375 case MKTAG( 'c','p','r','t'): key = "copyright"; break;
376 case MKTAG( 'd','e','s','c'): key = "description"; break;
377 12 case MKTAG( 'd','i','s','k'): key = "disc";
378 12 parse = mov_metadata_track_or_disc_number; break;
379 case MKTAG( 'e','g','i','d'): key = "episode_uid";
380 parse = mov_metadata_int8_no_padding; break;
381 case MKTAG( 'F','I','R','M'): key = "firmware"; raw = 1; break;
382 10 case MKTAG( 'g','n','r','e'): key = "genre";
383 10 parse = mov_metadata_gnre; break;
384 case MKTAG( 'h','d','v','d'): key = "hd_video";
385 parse = mov_metadata_int8_no_padding; break;
386 case MKTAG( 'H','M','M','T'):
387 return mov_metadata_hmmt(c, pb, atom.size);
388 case MKTAG( 'k','e','y','w'): key = "keywords"; break;
389 case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
390 case MKTAG( 'l','o','c','i'):
391 return mov_metadata_loci(c, pb, atom.size);
392 case MKTAG( 'm','a','n','u'): key = "make"; break;
393 case MKTAG( 'm','o','d','l'): key = "model"; break;
394 case MKTAG( 'p','c','s','t'): key = "podcast";
395 parse = mov_metadata_int8_no_padding; break;
396 13 case MKTAG( 'p','g','a','p'): key = "gapless_playback";
397 13 parse = mov_metadata_int8_no_padding; break;
398 case MKTAG( 'p','u','r','d'): key = "purchase_date"; break;
399 case MKTAG( 'r','t','n','g'): key = "rating";
400 parse = mov_metadata_int8_no_padding; break;
401 case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break;
402 case MKTAG( 's','o','a','l'): key = "sort_album"; break;
403 case MKTAG( 's','o','a','r'): key = "sort_artist"; break;
404 case MKTAG( 's','o','c','o'): key = "sort_composer"; break;
405 case MKTAG( 's','o','n','m'): key = "sort_name"; break;
406 case MKTAG( 's','o','s','n'): key = "sort_show"; break;
407 case MKTAG( 's','t','i','k'): key = "media_type";
408 parse = mov_metadata_int8_no_padding; break;
409 12 case MKTAG( 't','r','k','n'): key = "track";
410 12 parse = mov_metadata_track_or_disc_number; break;
411 case MKTAG( 't','v','e','n'): key = "episode_id"; break;
412 case MKTAG( 't','v','e','s'): key = "episode_sort";
413 parse = mov_metadata_int8_bypass_padding; break;
414 case MKTAG( 't','v','n','n'): key = "network"; break;
415 case MKTAG( 't','v','s','h'): key = "show"; break;
416 case MKTAG( 't','v','s','n'): key = "season_number";
417 parse = mov_metadata_int8_bypass_padding; break;
418 17 case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
419 case MKTAG(0xa9,'P','R','D'): key = "producer"; break;
420 16 case MKTAG(0xa9,'a','l','b'): key = "album"; break;
421 3 case MKTAG(0xa9,'a','u','t'): key = "artist"; break;
422 case MKTAG(0xa9,'c','h','p'): key = "chapter"; break;
423 8 case MKTAG(0xa9,'c','m','t'): key = "comment"; break;
424 case MKTAG(0xa9,'c','o','m'): key = "composer"; break;
425 4 case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
426 16 case MKTAG(0xa9,'d','a','y'): key = "date"; break;
427 case MKTAG(0xa9,'d','i','r'): key = "director"; break;
428 case MKTAG(0xa9,'d','i','s'): key = "disclaimer"; break;
429 case MKTAG(0xa9,'e','d','1'): key = "edit_date"; break;
430 2 case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
431 case MKTAG(0xa9,'f','m','t'): key = "original_format"; break;
432 3 case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
433 case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
434 case MKTAG(0xa9,'h','s','t'): key = "host_computer"; break;
435 case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
436 case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
437 5 case MKTAG(0xa9,'m','a','k'): key = "make"; break;
438 5 case MKTAG(0xa9,'m','o','d'): key = "model"; break;
439 42 case MKTAG(0xa9,'n','a','m'): key = "title"; break;
440 case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break;
441 case MKTAG(0xa9,'p','r','d'): key = "producer"; break;
442 case MKTAG(0xa9,'p','r','f'): key = "performers"; break;
443 case MKTAG(0xa9,'r','e','q'): key = "playback_requirements"; break;
444 case MKTAG(0xa9,'s','r','c'): key = "original_source"; break;
445 case MKTAG(0xa9,'s','t','3'): key = "subtitle"; break;
446 59 case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
447 50 case MKTAG(0xa9,'t','o','o'): key = "encoder"; break;
448 case MKTAG(0xa9,'t','r','k'): key = "track"; break;
449 case MKTAG(0xa9,'u','r','l'): key = "URL"; break;
450 case MKTAG(0xa9,'w','r','n'): key = "warning"; break;
451 1 case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
452 5 case MKTAG(0xa9,'x','y','z'): key = "location"; break;
453 }
454 2 retry:
455
3/4
✓ Branch 0 taken 301 times.
✓ Branch 1 taken 175 times.
✓ Branch 2 taken 301 times.
✗ Branch 3 not taken.
763 if (c->itunes_metadata && atom.size > 8) {
456 301 int data_size = avio_rb32(pb);
457 301 int tag = avio_rl32(pb);
458
3/6
✓ Branch 0 taken 301 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 301 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 301 times.
✗ Branch 5 not taken.
301 if (tag == MKTAG('d','a','t','a') && data_size <= atom.size && data_size >= 16) {
459 301 data_type = avio_rb32(pb); // type
460 301 avio_rb32(pb); // unknown
461 301 str_size = data_size - 16;
462 301 atom.size -= 16;
463
464
5/6
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 208 times.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 34 times.
✓ Branch 4 taken 59 times.
✗ Branch 5 not taken.
301 if (!key && c->found_hdlr_mdta && c->meta_keys) {
465 59 uint32_t index = av_bswap32(atom.type); // BE number has been read as LE
466
2/4
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
59 if (index < c->meta_keys_count && index > 0) {
467 59 key = c->meta_keys[index];
468 } else if (atom.type != MKTAG('c', 'o', 'v', 'r')) {
469 av_log(c->fc, AV_LOG_WARNING,
470 "The index of 'data' is out of range: %"PRId32" < 1 or >= %d.\n",
471 index, c->meta_keys_count);
472 }
473 }
474
4/4
✓ Branch 0 taken 287 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 267 times.
✓ Branch 3 taken 20 times.
301 if (atom.type == MKTAG('c', 'o', 'v', 'r') ||
475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 267 times.
267 (key && !strcmp(key, "com.apple.quicktime.artwork"))) {
476 14 int ret = mov_read_covr(c, pb, data_type, str_size);
477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0) {
478 av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
479 return ret;
480 }
481 14 atom.size -= str_size;
482
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (atom.size > 8)
483 2 goto retry;
484 12 return ret;
485 }
486 } else return 0;
487
8/10
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 106 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 51 times.
✓ Branch 6 taken 106 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 100 times.
✓ Branch 9 taken 6 times.
175 } else if (atom.size > 4 && (key || c->export_all) && !c->itunes_metadata && !raw) {
488 100 str_size = avio_rb16(pb); // string length
489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (str_size > atom.size) {
490 raw = 1;
491 avio_seek(pb, -2, SEEK_CUR);
492 av_log(c->fc, AV_LOG_WARNING, "UDTA parsing failed retrying raw\n");
493 goto retry;
494 }
495 100 langcode = avio_rb16(pb);
496 100 ff_mov_lang_to_iso639(langcode, language);
497 100 atom.size -= 4;
498 } else
499 75 str_size = atom.size;
500
501
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 462 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
462 if (c->export_all && !key) {
502 key = av_fourcc_make_string(tmp_key, atom.type);
503 }
504
505
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 373 times.
462 if (!key)
506 89 return 0;
507
2/4
✓ Branch 0 taken 373 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 373 times.
373 if (atom.size < 0 || str_size >= INT_MAX/2)
508 return AVERROR_INVALIDDATA;
509
510 // Allocates enough space if data_type is a int32 or float32 number, otherwise
511 // worst-case requirement for output string in case of utf8 coded input
512
3/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 332 times.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
373 num = (data_type >= 21 && data_type <= 23);
513
4/4
✓ Branch 0 taken 332 times.
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 326 times.
✓ Branch 3 taken 6 times.
373 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
514 373 str = av_mallocz(str_size_alloc);
515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 373 times.
373 if (!str)
516 return AVERROR(ENOMEM);
517
518
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 313 times.
373 if (parse)
519 60 parse(c, pb, str_size, key);
520 else {
521
8/10
✓ Branch 0 taken 307 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 307 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 101 times.
✓ Branch 5 taken 206 times.
✓ Branch 6 taken 87 times.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 87 times.
313 if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
522 14 mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
523
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 297 times.
299 } else if (data_type == 21) { // BE signed integer, variable size
524 2 int val = 0;
525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (str_size == 1)
526 val = (int8_t)avio_r8(pb);
527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 2)
528 val = (int16_t)avio_rb16(pb);
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 3)
530 val = ((int32_t)(avio_rb24(pb)<<8))>>8;
531
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (str_size == 4)
532 2 val = (int32_t)avio_rb32(pb);
533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
534 av_log(c->fc, AV_LOG_ERROR,
535 "Failed to store the number (%d) in string.\n", val);
536 av_free(str);
537 return AVERROR_INVALIDDATA;
538 }
539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 297 times.
297 } else if (data_type == 22) { // BE unsigned integer, variable size
540 unsigned int val = 0;
541 if (str_size == 1)
542 val = avio_r8(pb);
543 else if (str_size == 2)
544 val = avio_rb16(pb);
545 else if (str_size == 3)
546 val = avio_rb24(pb);
547 else if (str_size == 4)
548 val = avio_rb32(pb);
549 if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
550 av_log(c->fc, AV_LOG_ERROR,
551 "Failed to store the number (%u) in string.\n", val);
552 av_free(str);
553 return AVERROR_INVALIDDATA;
554 }
555
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 284 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
310 } else if (data_type == 23 && str_size >= 4) { // BE float32
556 13 float val = av_int2float(avio_rb32(pb));
557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
558 av_log(c->fc, AV_LOG_ERROR,
559 "Failed to store the float32 number (%f) in string.\n", val);
560 av_free(str);
561 return AVERROR_INVALIDDATA;
562 }
563
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 284 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
284 } else if (data_type > 1 && data_type != 4) {
564 // data_type can be 0 if not set at all above. data_type 1 means
565 // UTF8 and 4 means "UTF8 sort". For any other type (UTF16 or e.g.
566 // a picture), don't return it blindly in a string that is supposed
567 // to be UTF8 text.
568 av_log(c->fc, AV_LOG_WARNING, "Skipping unhandled metadata %s of type %d\n", key, data_type);
569 av_free(str);
570 return 0;
571 } else {
572 284 int ret = ffio_read_size(pb, str, str_size);
573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 284 times.
284 if (ret < 0) {
574 av_free(str);
575 return ret;
576 }
577 284 str[str_size] = 0;
578 }
579 313 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
580 313 av_dict_set(metadata, key, str, 0);
581
4/4
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 213 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 63 times.
313 if (*language && strcmp(language, "und")) {
582 37 snprintf(key2, sizeof(key2), "%s-%s", key, language);
583 37 av_dict_set(metadata, key2, str, 0);
584 }
585
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 202 times.
313 if (!strcmp(key, "encoder")) {
586 int major, minor, micro;
587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111 times.
111 if (sscanf(str, "HandBrake %d.%d.%d", &major, &minor, &micro) == 3) {
588 c->handbrake_version = 1000000*major + 1000*minor + micro;
589 }
590 }
591 }
592
593 373 av_freep(&str);
594 373 return 0;
595 }
596
597 12 static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
598 {
599 int64_t start;
600 int i, nb_chapters, str_len, version;
601 char str[256+1];
602 int ret;
603
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->ignore_chapters)
605 return 0;
606
607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if ((atom.size -= 5) < 0)
608 return 0;
609
610 12 version = avio_r8(pb);
611 12 avio_rb24(pb);
612
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (version)
613 12 avio_rb32(pb); // ???
614 12 nb_chapters = avio_r8(pb);
615
616
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
30 for (i = 0; i < nb_chapters; i++) {
617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size < 9)
618 return 0;
619
620 18 start = avio_rb64(pb);
621 18 str_len = avio_r8(pb);
622
623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if ((atom.size -= 9+str_len) < 0)
624 return 0;
625
626 18 ret = ffio_read_size(pb, str, str_len);
627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (ret < 0)
628 return ret;
629 18 str[str_len] = 0;
630 18 avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
631 }
632 12 return 0;
633 }
634
635 #define MIN_DATA_ENTRY_BOX_SIZE 12
636 598 static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
637 {
638 AVStream *st;
639 MOVStreamContext *sc;
640 int entries, i, j;
641
642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (c->fc->nb_streams < 1)
643 return 0;
644 598 st = c->fc->streams[c->fc->nb_streams-1];
645 598 sc = st->priv_data;
646
647 598 avio_rb32(pb); // version + flags
648 598 entries = avio_rb32(pb);
649
1/2
✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
598 if (!entries ||
650
1/2
✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
598 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 entries >= UINT_MAX / sizeof(*sc->drefs))
652 return AVERROR_INVALIDDATA;
653
654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 for (i = 0; i < sc->drefs_count; i++) {
655 MOVDref *dref = &sc->drefs[i];
656 av_freep(&dref->path);
657 av_freep(&dref->dir);
658 }
659 598 av_free(sc->drefs);
660 598 sc->drefs_count = 0;
661 598 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (!sc->drefs)
663 return AVERROR(ENOMEM);
664 598 sc->drefs_count = entries;
665
666
2/2
✓ Branch 0 taken 598 times.
✓ Branch 1 taken 598 times.
1196 for (i = 0; i < entries; i++) {
667 598 MOVDref *dref = &sc->drefs[i];
668 598 uint32_t size = avio_rb32(pb);
669 598 int64_t next = avio_tell(pb);
670
671
3/6
✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 598 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 598 times.
598 if (size < 12 || next < 0 || next > INT64_MAX - size)
672 return AVERROR_INVALIDDATA;
673
674 598 next += size - 4;
675
676 598 dref->type = avio_rl32(pb);
677 598 avio_rb32(pb); // version + flags
678
679
3/4
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 480 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 118 times.
598 if (dref->type == MKTAG('a','l','i','s') && size > 150) {
680 /* macintosh alias record */
681 uint16_t volume_len, len;
682 int16_t type;
683 int ret;
684
685 avio_skip(pb, 10);
686
687 volume_len = avio_r8(pb);
688 volume_len = FFMIN(volume_len, 27);
689 ret = ffio_read_size(pb, dref->volume, 27);
690 if (ret < 0)
691 return ret;
692 dref->volume[volume_len] = 0;
693 av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
694
695 avio_skip(pb, 12);
696
697 len = avio_r8(pb);
698 len = FFMIN(len, 63);
699 ret = ffio_read_size(pb, dref->filename, 63);
700 if (ret < 0)
701 return ret;
702 dref->filename[len] = 0;
703 av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
704
705 avio_skip(pb, 16);
706
707 /* read next level up_from_alias/down_to_target */
708 dref->nlvl_from = avio_rb16(pb);
709 dref->nlvl_to = avio_rb16(pb);
710 av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
711 dref->nlvl_from, dref->nlvl_to);
712
713 avio_skip(pb, 16);
714
715 for (type = 0; type != -1 && avio_tell(pb) < next; ) {
716 if (avio_feof(pb))
717 return AVERROR_EOF;
718 type = avio_rb16(pb);
719 len = avio_rb16(pb);
720 av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
721 if (len&1)
722 len += 1;
723 if (type == 2) { // absolute path
724 av_free(dref->path);
725 dref->path = av_mallocz(len+1);
726 if (!dref->path)
727 return AVERROR(ENOMEM);
728
729 ret = ffio_read_size(pb, dref->path, len);
730 if (ret < 0) {
731 av_freep(&dref->path);
732 return ret;
733 }
734 if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
735 len -= volume_len;
736 memmove(dref->path, dref->path+volume_len, len);
737 dref->path[len] = 0;
738 }
739 // trim string of any ending zeros
740 for (j = len - 1; j >= 0; j--) {
741 if (dref->path[j] == 0)
742 len--;
743 else
744 break;
745 }
746 for (j = 0; j < len; j++)
747 if (dref->path[j] == ':' || dref->path[j] == 0)
748 dref->path[j] = '/';
749 av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
750 } else if (type == 0) { // directory name
751 av_free(dref->dir);
752 dref->dir = av_malloc(len+1);
753 if (!dref->dir)
754 return AVERROR(ENOMEM);
755
756 ret = ffio_read_size(pb, dref->dir, len);
757 if (ret < 0) {
758 av_freep(&dref->dir);
759 return ret;
760 }
761 dref->dir[len] = 0;
762 for (j = 0; j < len; j++)
763 if (dref->dir[j] == ':')
764 dref->dir[j] = '/';
765 av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
766 } else
767 avio_skip(pb, len);
768 }
769 } else {
770 598 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
771 dref->type, size);
772 598 entries--;
773 598 i--;
774 }
775 598 avio_seek(pb, next, SEEK_SET);
776 }
777 598 return 0;
778 }
779
780 1098 static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
781 {
782 AVStream *st;
783 uint32_t type;
784 uint32_t ctype;
785 int64_t title_size;
786 char *title_str;
787 int ret;
788
789 1098 avio_r8(pb); /* version */
790 1098 avio_rb24(pb); /* flags */
791
792 /* component type */
793 1098 ctype = avio_rl32(pb);
794 1098 type = avio_rl32(pb); /* component subtype */
795
796 1098 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
797 1098 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
798
799
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 958 times.
1098 if (c->trak_index < 0) { // meta not inside a trak
800
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 129 times.
140 if (type == MKTAG('m','d','t','a')) {
801 11 c->found_hdlr_mdta = 1;
802 }
803 140 return 0;
804 }
805
806 958 st = c->fc->streams[c->fc->nb_streams-1];
807
808
2/2
✓ Branch 0 taken 306 times.
✓ Branch 1 taken 652 times.
958 if (type == MKTAG('v','i','d','e'))
809 306 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
810
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 411 times.
652 else if (type == MKTAG('s','o','u','n'))
811 241 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 411 times.
411 else if (type == MKTAG('m','1','a',' '))
813 st->codecpar->codec_id = AV_CODEC_ID_MP2;
814
2/4
✓ Branch 0 taken 411 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 411 times.
411 else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
815 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
816
817 958 avio_rb32(pb); /* component manufacture */
818 958 avio_rb32(pb); /* component flags */
819 958 avio_rb32(pb); /* component flags mask */
820
821 958 title_size = atom.size - 24;
822
2/2
✓ Branch 0 taken 955 times.
✓ Branch 1 taken 3 times.
958 if (title_size > 0) {
823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 955 times.
955 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
824 return AVERROR_INVALIDDATA;
825 955 title_str = av_malloc(title_size + 1); /* Add null terminator */
826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 955 times.
955 if (!title_str)
827 return AVERROR(ENOMEM);
828
829 955 ret = ffio_read_size(pb, title_str, title_size);
830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 955 times.
955 if (ret < 0) {
831 av_freep(&title_str);
832 return ret;
833 }
834 955 title_str[title_size] = 0;
835
2/2
✓ Branch 0 taken 904 times.
✓ Branch 1 taken 51 times.
955 if (title_str[0]) {
836
4/4
✓ Branch 0 taken 696 times.
✓ Branch 1 taken 208 times.
✓ Branch 2 taken 694 times.
✓ Branch 3 taken 2 times.
904 int off = (!c->isom && title_str[0] == title_size - 1);
837 // flag added so as to not set stream handler name if already set from mdia->hdlr
838 904 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
839 }
840 955 av_freep(&title_str);
841 }
842
843 958 return 0;
844 }
845
846 150 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
847 {
848 150 return ff_mov_read_esds(c->fc, pb);
849 }
850
851 7 static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
852 {
853 AVStream *st;
854 AVPacketSideData *sd;
855 enum AVAudioServiceType *ast;
856 int ac3info, acmod, lfeon, bsmod;
857 uint64_t mask;
858
859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (c->fc->nb_streams < 1)
860 return 0;
861 7 st = c->fc->streams[c->fc->nb_streams-1];
862
863 7 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
864 7 &st->codecpar->nb_coded_side_data,
865 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
866 sizeof(*ast), 0);
867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sd)
868 return AVERROR(ENOMEM);
869
870 7 ast = (enum AVAudioServiceType*)sd->data;
871 7 ac3info = avio_rb24(pb);
872 7 bsmod = (ac3info >> 14) & 0x7;
873 7 acmod = (ac3info >> 11) & 0x7;
874 7 lfeon = (ac3info >> 10) & 0x1;
875
876 7 mask = ff_ac3_channel_layout_tab[acmod];
877
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (lfeon)
878 1 mask |= AV_CH_LOW_FREQUENCY;
879 7 av_channel_layout_uninit(&st->codecpar->ch_layout);
880 7 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
881
882 7 *ast = bsmod;
883
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
7 if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7)
884 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
885
886 7 return 0;
887 }
888
889 #if CONFIG_IAMFDEC
890 10 static int mov_read_iacb(MOVContext *c, AVIOContext *pb, MOVAtom atom)
891 {
892 AVStream *st;
893 MOVStreamContext *sc;
894 FFIOContext b;
895 AVIOContext *descriptor_pb;
896 AVDictionary *metadata;
897 IAMFContext *iamf;
898 int64_t start_time, duration;
899 unsigned descriptors_size;
900 int nb_frames, disposition;
901 int version, ret;
902
903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (atom.size < 5)
904 return AVERROR_INVALIDDATA;
905
906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (c->fc->nb_streams < 1)
907 return 0;
908
909 10 version = avio_r8(pb);
910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (version != 1) {
911 av_log(c->fc, AV_LOG_ERROR, "%s configurationVersion %d",
912 version < 1 ? "invalid" : "unsupported", version);
913 return AVERROR_INVALIDDATA;
914 }
915
916 10 descriptors_size = ffio_read_leb(pb);
917
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (!descriptors_size || descriptors_size > INT_MAX)
918 return AVERROR_INVALIDDATA;
919
920 10 st = c->fc->streams[c->fc->nb_streams - 1];
921 10 sc = st->priv_data;
922
923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (st->codecpar->extradata) {
924 av_log(c->fc, AV_LOG_WARNING, "ignoring iacb\n");
925 return 0;
926 }
927
928 10 sc->iamf = av_mallocz(sizeof(*sc->iamf));
929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!sc->iamf)
930 return AVERROR(ENOMEM);
931 10 iamf = &sc->iamf->iamf;
932
933 10 st->codecpar->extradata = av_malloc(descriptors_size);
934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!st->codecpar->extradata)
935 return AVERROR(ENOMEM);
936 10 st->codecpar->extradata_size = descriptors_size;
937
938 10 ret = avio_read(pb, st->codecpar->extradata, descriptors_size);
939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret != descriptors_size)
940 return ret < 0 ? ret : AVERROR_INVALIDDATA;
941
942 10 ffio_init_read_context(&b, st->codecpar->extradata, descriptors_size);
943 10 descriptor_pb = &b.pub;
944
945 10 ret = ff_iamfdec_read_descriptors(iamf, descriptor_pb, descriptors_size, c->fc);
946
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
947 return ret;
948
949 10 metadata = st->metadata;
950 10 st->metadata = NULL;
951 10 start_time = st->start_time;
952 10 nb_frames = st->nb_frames;
953 10 duration = st->duration;
954 10 disposition = st->disposition;
955
956
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_audio_elements; i++) {
957 10 IAMFAudioElement *audio_element = iamf->audio_elements[i];
958 const AVIAMFAudioElement *element;
959 AVStreamGroup *stg =
960 10 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, NULL);
961
962
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!stg) {
963 ret = AVERROR(ENOMEM);
964 goto fail;
965 }
966
967 10 av_iamf_audio_element_free(&stg->params.iamf_audio_element);
968 10 stg->id = audio_element->audio_element_id;
969 /* Transfer ownership */
970 10 element = stg->params.iamf_audio_element = audio_element->element;
971 10 audio_element->element = NULL;
972
973
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int j = 0; j < audio_element->nb_substreams; j++) {
974 50 IAMFSubStream *substream = &audio_element->substreams[j];
975 AVStream *stream;
976
977
3/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 40 times.
50 if (!i && !j) {
978
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (audio_element->layers[0].substream_count != 1)
979 2 disposition &= ~AV_DISPOSITION_DEFAULT;
980 10 stream = st;
981 } else
982 40 stream = avformat_new_stream(c->fc, NULL);
983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (!stream) {
984 ret = AVERROR(ENOMEM);
985 goto fail;
986 }
987
988 50 stream->start_time = start_time;
989 50 stream->nb_frames = nb_frames;
990 50 stream->duration = duration;
991 50 stream->disposition = disposition;
992
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 10 times.
50 if (stream != st) {
993 40 stream->priv_data = sc;
994 40 sc->refcount++;
995 }
996
997
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 42 times.
50 if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
998 8 stream->disposition |= AV_DISPOSITION_DEPENDENT;
999
3/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 10 times.
50 if (i || j) {
1000 40 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1001
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 6 times.
40 if (audio_element->layers[0].substream_count == 1)
1002 34 stream->disposition &= ~AV_DISPOSITION_DEFAULT;
1003 }
1004
1005 50 ret = avcodec_parameters_copy(stream->codecpar, substream->codecpar);
1006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (ret < 0)
1007 goto fail;
1008
1009 50 stream->id = substream->audio_substream_id;
1010
1011 50 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
1012
1013 50 ret = avformat_stream_group_add_stream(stg, stream);
1014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (ret < 0)
1015 goto fail;
1016 }
1017
1018 10 ret = av_dict_copy(&stg->metadata, metadata, 0);
1019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
1020 goto fail;
1021 }
1022
1023
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1024 10 IAMFMixPresentation *mix_presentation = iamf->mix_presentations[i];
1025 10 const AVIAMFMixPresentation *mix = mix_presentation->cmix;
1026 AVStreamGroup *stg =
1027 10 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, NULL);
1028
1029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!stg) {
1030 ret = AVERROR(ENOMEM);
1031 goto fail;
1032 }
1033
1034 10 av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
1035 10 stg->id = mix_presentation->mix_presentation_id;
1036 /* Transfer ownership */
1037 10 stg->params.iamf_mix_presentation = mix_presentation->mix;
1038 10 mix_presentation->mix = NULL;
1039
1040
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 10 times.
22 for (int j = 0; j < mix->nb_submixes; j++) {
1041 12 const AVIAMFSubmix *submix = mix->submixes[j];
1042
1043
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int k = 0; k < submix->nb_elements; k++) {
1044 12 const AVIAMFSubmixElement *submix_element = submix->elements[k];
1045 12 const AVStreamGroup *audio_element = NULL;
1046
1047
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 for (int l = 0; l < c->fc->nb_stream_groups; l++)
1048
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (c->fc->stream_groups[l]->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT &&
1049
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 c->fc->stream_groups[l]->id == submix_element->audio_element_id) {
1050 12 audio_element = c->fc->stream_groups[l];
1051 12 break;
1052 }
1053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 av_assert0(audio_element);
1054
1055
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 12 times.
64 for (int l = 0; l < audio_element->nb_streams; l++) {
1056 52 ret = avformat_stream_group_add_stream(stg, audio_element->streams[l]);
1057
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
52 if (ret < 0 && ret != AVERROR(EEXIST))
1058 goto fail;
1059 }
1060 }
1061 }
1062
1063 10 ret = av_dict_copy(&stg->metadata, metadata, 0);
1064
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
1065 goto fail;
1066 }
1067
1068 10 ret = 0;
1069 10 fail:
1070 10 av_dict_free(&metadata);
1071
1072 10 return ret;
1073 }
1074 #endif
1075
1076 1 static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1077 {
1078 AVStream *st;
1079 AVPacketSideData *sd;
1080 enum AVAudioServiceType *ast;
1081 int eac3info, acmod, lfeon, bsmod;
1082 uint64_t mask;
1083
1084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
1085 return 0;
1086 1 st = c->fc->streams[c->fc->nb_streams-1];
1087
1088 1 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1089 1 &st->codecpar->nb_coded_side_data,
1090 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
1091 sizeof(*ast), 0);
1092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sd)
1093 return AVERROR(ENOMEM);
1094
1095 1 ast = (enum AVAudioServiceType*)sd->data;
1096
1097 /* No need to parse fields for additional independent substreams and its
1098 * associated dependent substreams since libavcodec's E-AC-3 decoder
1099 * does not support them yet. */
1100 1 avio_rb16(pb); /* data_rate and num_ind_sub */
1101 1 eac3info = avio_rb24(pb);
1102 1 bsmod = (eac3info >> 12) & 0x1f;
1103 1 acmod = (eac3info >> 9) & 0x7;
1104 1 lfeon = (eac3info >> 8) & 0x1;
1105
1106 1 mask = ff_ac3_channel_layout_tab[acmod];
1107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (lfeon)
1108 mask |= AV_CH_LOW_FREQUENCY;
1109 1 av_channel_layout_uninit(&st->codecpar->ch_layout);
1110 1 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
1111
1112 1 *ast = bsmod;
1113
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7)
1114 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
1115
1116 1 return 0;
1117 }
1118
1119 static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1120 {
1121 #define DDTS_SIZE 20
1122 uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
1123 AVStream *st = NULL;
1124 uint32_t frame_duration_code = 0;
1125 uint32_t channel_layout_code = 0;
1126 GetBitContext gb;
1127 int ret;
1128
1129 if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
1130 return ret;
1131
1132 init_get_bits(&gb, buf, 8 * DDTS_SIZE);
1133
1134 if (c->fc->nb_streams < 1) {
1135 return 0;
1136 }
1137 st = c->fc->streams[c->fc->nb_streams-1];
1138
1139 st->codecpar->sample_rate = get_bits_long(&gb, 32);
1140 if (st->codecpar->sample_rate <= 0) {
1141 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
1142 return AVERROR_INVALIDDATA;
1143 }
1144 skip_bits_long(&gb, 32); /* max bitrate */
1145 st->codecpar->bit_rate = get_bits_long(&gb, 32);
1146 st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
1147 frame_duration_code = get_bits(&gb, 2);
1148 skip_bits(&gb, 30); /* various fields */
1149 channel_layout_code = get_bits(&gb, 16);
1150
1151 st->codecpar->frame_size =
1152 (frame_duration_code == 0) ? 512 :
1153 (frame_duration_code == 1) ? 1024 :
1154 (frame_duration_code == 2) ? 2048 :
1155 (frame_duration_code == 3) ? 4096 : 0;
1156
1157 if (channel_layout_code > 0xff) {
1158 av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout\n");
1159 }
1160 av_channel_layout_uninit(&st->codecpar->ch_layout);
1161 av_channel_layout_from_mask(&st->codecpar->ch_layout,
1162 ((channel_layout_code & 0x1) ? AV_CH_FRONT_CENTER : 0) |
1163 ((channel_layout_code & 0x2) ? AV_CH_FRONT_LEFT : 0) |
1164 ((channel_layout_code & 0x2) ? AV_CH_FRONT_RIGHT : 0) |
1165 ((channel_layout_code & 0x4) ? AV_CH_SIDE_LEFT : 0) |
1166 ((channel_layout_code & 0x4) ? AV_CH_SIDE_RIGHT : 0) |
1167 ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0));
1168
1169 return 0;
1170 }
1171
1172 51 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1173 {
1174 AVStream *st;
1175
1176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (c->fc->nb_streams < 1)
1177 return 0;
1178 51 st = c->fc->streams[c->fc->nb_streams-1];
1179
1180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (atom.size < 16)
1181 return 0;
1182
1183 /* skip version and flags */
1184 51 avio_skip(pb, 4);
1185
1186 51 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
1187
1188 51 return 0;
1189 }
1190
1191 5 static int mov_read_chnl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1192 {
1193 5 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
1194 int version, flags;
1195 int ret;
1196 AVStream *st;
1197
1198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
1199 return 0;
1200 5 st = c->fc->streams[c->fc->nb_streams-1];
1201
1202 5 version = avio_r8(pb);
1203 5 flags = avio_rb24(pb);
1204
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (version != 0 || flags != 0) {
1205 av_log(c->fc, AV_LOG_ERROR,
1206 "Unsupported 'chnl' box with version %d, flags: %#x",
1207 version, flags);
1208 return AVERROR_INVALIDDATA;
1209 }
1210
1211 5 ret = ff_mov_read_chnl(c->fc, pb, st);
1212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
1213 return ret;
1214
1215
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_tell(pb) != end) {
1216 av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data inside chnl\n",
1217 end - avio_tell(pb));
1218 avio_seek(pb, end, SEEK_SET);
1219 }
1220 5 return ret;
1221 }
1222
1223 2 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1224 {
1225 AVStream *st;
1226 int ret;
1227
1228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
1229 return 0;
1230 2 st = c->fc->streams[c->fc->nb_streams-1];
1231
1232
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)
1233 av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
1234
1235 2 return ret;
1236 }
1237
1238 18 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1239 {
1240 AVStream *st;
1241 HEIFItem *item;
1242 AVPacketSideData *sd;
1243 18 int width, height, err = 0;
1244 AVRational aperture_width, aperture_height, horiz_off, vert_off;
1245 AVRational pc_x, pc_y;
1246 uint64_t top, bottom, left, right;
1247
1248 18 item = heif_cur_item(c);
1249 18 st = get_curr_st(c);
1250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!st)
1251 return 0;
1252
1253 18 width = st->codecpar->width;
1254 18 height = st->codecpar->height;
1255
4/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
18 if ((!width || !height) && item) {
1256 6 width = item->width;
1257 6 height = item->height;
1258 }
1259
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (!width || !height) {
1260 err = AVERROR_INVALIDDATA;
1261 goto fail;
1262 }
1263
1264 18 aperture_width.num = avio_rb32(pb);
1265 18 aperture_width.den = avio_rb32(pb);
1266 18 aperture_height.num = avio_rb32(pb);
1267 18 aperture_height.den = avio_rb32(pb);
1268
1269 18 horiz_off.num = avio_rb32(pb);
1270 18 horiz_off.den = avio_rb32(pb);
1271 18 vert_off.num = avio_rb32(pb);
1272 18 vert_off.den = avio_rb32(pb);
1273
1274
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 if (aperture_width.num < 0 || aperture_width.den < 0 ||
1275
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 aperture_height.num < 0 || aperture_height.den < 0 ||
1276
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 horiz_off.den < 0 || vert_off.den < 0) {
1277 err = AVERROR_INVALIDDATA;
1278 goto fail;
1279 }
1280
3/4
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
33 if ((av_cmp_q((AVRational) { width, 1 }, aperture_width) < 0) ||
1281 15 (av_cmp_q((AVRational) { height, 1 }, aperture_height) < 0)) {
1282 3 err = AVERROR_INVALIDDATA;
1283 3 goto fail;
1284 }
1285 15 av_log(c->fc, AV_LOG_TRACE, "clap: apertureWidth %d/%d, apertureHeight %d/%d "
1286 "horizOff %d/%d vertOff %d/%d\n",
1287 aperture_width.num, aperture_width.den, aperture_height.num, aperture_height.den,
1288 horiz_off.num, horiz_off.den, vert_off.num, vert_off.den);
1289
1290 15 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1291 15 pc_x = av_add_q(pc_x, horiz_off);
1292 15 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1293 15 pc_y = av_add_q(pc_y, vert_off);
1294
1295 15 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1296 15 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1297 15 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1298 15 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1299
1300 15 left = av_q2d(av_sub_q(pc_x, aperture_width));
1301 15 right = av_q2d(av_add_q(pc_x, aperture_width));
1302 15 top = av_q2d(av_sub_q(pc_y, aperture_height));
1303 15 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1304
1305
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (bottom > (height - 1) ||
1306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 right > (width - 1)) {
1307 err = AVERROR_INVALIDDATA;
1308 goto fail;
1309 }
1310
1311 15 bottom = height - 1 - bottom;
1312 15 right = width - 1 - right;
1313
1314
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
15 if (!(left | right | top | bottom))
1315 6 return 0;
1316
1317
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if ((left + right) >= width ||
1318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 (top + bottom) >= height) {
1319 err = AVERROR_INVALIDDATA;
1320 goto fail;
1321 }
1322
1323 9 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1324 9 &st->codecpar->nb_coded_side_data,
1325 AV_PKT_DATA_FRAME_CROPPING,
1326 sizeof(uint32_t) * 4, 0);
1327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sd)
1328 return AVERROR(ENOMEM);
1329
1330 9 AV_WL32A(sd->data, top);
1331 9 AV_WL32A(sd->data + 4, bottom);
1332 9 AV_WL32A(sd->data + 8, left);
1333 9 AV_WL32A(sd->data + 12, right);
1334
1335 12 fail:
1336
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 if (err < 0) {
1337 3 int explode = !!(c->fc->error_recognition & AV_EF_EXPLODE);
1338
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");
1339
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!explode)
1340 3 err = 0;
1341 }
1342
1343 12 return err;
1344 }
1345
1346 /* This atom overrides any previously set aspect ratio */
1347 67 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1348 {
1349 67 const int num = avio_rb32(pb);
1350 67 const int den = avio_rb32(pb);
1351 AVStream *st;
1352 MOVStreamContext *sc;
1353
1354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
67 if (c->fc->nb_streams < 1)
1355 return 0;
1356 67 st = c->fc->streams[c->fc->nb_streams-1];
1357 67 sc = st->priv_data;
1358
1359 67 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1360
1361
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 2 times.
67 if (den != 0) {
1362 65 sc->h_spacing = num;
1363 65 sc->v_spacing = den;
1364 }
1365 67 return 0;
1366 }
1367
1368 /* this atom contains actual media data */
1369 879 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1370 {
1371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 879 times.
879 if (atom.size == 0) /* wrong one (MP4) */
1372 return 0;
1373 879 c->found_mdat=1;
1374 879 return 0; /* now go for moov */
1375 }
1376
1377 #define DRM_BLOB_SIZE 56
1378
1379 static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1380 {
1381 uint8_t intermediate_key[20];
1382 uint8_t intermediate_iv[20];
1383 uint8_t input[64];
1384 uint8_t output[64];
1385 uint8_t file_checksum[20];
1386 uint8_t calculated_checksum[20];
1387 char checksum_string[2 * sizeof(file_checksum) + 1];
1388 struct AVSHA *sha;
1389 int i;
1390 int ret = 0;
1391 uint8_t *activation_bytes = c->activation_bytes;
1392 uint8_t *fixed_key = c->audible_fixed_key;
1393
1394 c->aax_mode = 1;
1395
1396 sha = av_sha_alloc();
1397 if (!sha)
1398 return AVERROR(ENOMEM);
1399 av_free(c->aes_decrypt);
1400 c->aes_decrypt = av_aes_alloc();
1401 if (!c->aes_decrypt) {
1402 ret = AVERROR(ENOMEM);
1403 goto fail;
1404 }
1405
1406 /* drm blob processing */
1407 avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1408 avio_read(pb, input, DRM_BLOB_SIZE);
1409 avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1410 ret = ffio_read_size(pb, file_checksum, 20);
1411 if (ret < 0)
1412 goto fail;
1413
1414 // required by external tools
1415 ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1);
1416 av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string);
1417
1418 /* verify activation data */
1419 if (!activation_bytes) {
1420 av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1421 ret = 0; /* allow ffprobe to continue working on .aax files */
1422 goto fail;
1423 }
1424 if (c->activation_bytes_size != 4) {
1425 av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1426 ret = AVERROR(EINVAL);
1427 goto fail;
1428 }
1429
1430 /* verify fixed key */
1431 if (c->audible_fixed_key_size != 16) {
1432 av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1433 ret = AVERROR(EINVAL);
1434 goto fail;
1435 }
1436
1437 /* AAX (and AAX+) key derivation */
1438 av_sha_init(sha, 160);
1439 av_sha_update(sha, fixed_key, 16);
1440 av_sha_update(sha, activation_bytes, 4);
1441 av_sha_final(sha, intermediate_key);
1442 av_sha_init(sha, 160);
1443 av_sha_update(sha, fixed_key, 16);
1444 av_sha_update(sha, intermediate_key, 20);
1445 av_sha_update(sha, activation_bytes, 4);
1446 av_sha_final(sha, intermediate_iv);
1447 av_sha_init(sha, 160);
1448 av_sha_update(sha, intermediate_key, 16);
1449 av_sha_update(sha, intermediate_iv, 16);
1450 av_sha_final(sha, calculated_checksum);
1451 if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1452 av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1453 ret = AVERROR_INVALIDDATA;
1454 goto fail;
1455 }
1456 av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1457 av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1458 for (i = 0; i < 4; i++) {
1459 // file data (in output) is stored in big-endian mode
1460 if (activation_bytes[i] != output[3 - i]) { // critical error
1461 av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1462 ret = AVERROR_INVALIDDATA;
1463 goto fail;
1464 }
1465 }
1466 memcpy(c->file_key, output + 8, 16);
1467 memcpy(input, output + 26, 16);
1468 av_sha_init(sha, 160);
1469 av_sha_update(sha, input, 16);
1470 av_sha_update(sha, c->file_key, 16);
1471 av_sha_update(sha, fixed_key, 16);
1472 av_sha_final(sha, c->file_iv);
1473
1474 fail:
1475 av_free(sha);
1476
1477 return ret;
1478 }
1479
1480 static int mov_aaxc_crypto(MOVContext *c)
1481 {
1482 if (c->audible_key_size != 16) {
1483 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n");
1484 return AVERROR(EINVAL);
1485 }
1486
1487 if (c->audible_iv_size != 16) {
1488 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n");
1489 return AVERROR(EINVAL);
1490 }
1491
1492 c->aes_decrypt = av_aes_alloc();
1493 if (!c->aes_decrypt) {
1494 return AVERROR(ENOMEM);
1495 }
1496
1497 memcpy(c->file_key, c->audible_key, 16);
1498 memcpy(c->file_iv, c->audible_iv, 16);
1499 c->aax_mode = 1;
1500
1501 return 0;
1502 }
1503
1504 // Audible AAX (and AAX+) bytestream decryption
1505 static int aax_filter(uint8_t *input, int size, MOVContext *c)
1506 {
1507 int blocks = 0;
1508 unsigned char iv[16];
1509
1510 memcpy(iv, c->file_iv, 16); // iv is overwritten
1511 blocks = size >> 4; // trailing bytes are not encrypted!
1512 av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1513 av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1514
1515 return 0;
1516 }
1517
1518 /* read major brand, minor version and compatible brands and store them as metadata */
1519 458 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1520 {
1521 uint32_t minor_ver;
1522 int comp_brand_size;
1523 char* comp_brands_str;
1524 458 uint8_t type[5] = {0};
1525 458 int ret = ffio_read_size(pb, type, 4);
1526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 458 times.
458 if (ret < 0)
1527 return ret;
1528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 458 times.
458 if (c->fc->nb_streams) {
1529 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1530 return AVERROR_INVALIDDATA;
1531 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate FTYP\n");
1532 return 0;
1533 }
1534
1535
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 234 times.
458 if (strcmp(type, "qt "))
1536 224 c->isom = 1;
1537 458 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1538 458 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1539 458 minor_ver = avio_rb32(pb); /* minor version */
1540 458 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1541
1542 458 comp_brand_size = atom.size - 8;
1543
2/4
✓ Branch 0 taken 458 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 458 times.
458 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1544 return AVERROR_INVALIDDATA;
1545 458 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 458 times.
458 if (!comp_brands_str)
1547 return AVERROR(ENOMEM);
1548
1549 458 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1550
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 458 times.
458 if (ret < 0) {
1551 av_freep(&comp_brands_str);
1552 return ret;
1553 }
1554 458 comp_brands_str[comp_brand_size] = 0;
1555 458 av_dict_set(&c->fc->metadata, "compatible_brands",
1556 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1557
1558 // Logic for handling Audible's .aaxc files
1559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 458 times.
458 if (!strcmp(type, "aaxc")) {
1560 mov_aaxc_crypto(c);
1561 }
1562
1563 458 return 0;
1564 }
1565
1566 /* this atom should contain all header atoms */
1567 487 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1568 {
1569 int ret;
1570
1571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 487 times.
487 if (c->found_moov) {
1572 av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1573 avio_skip(pb, atom.size);
1574 return 0;
1575 }
1576
1577
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 487 times.
487 if ((ret = mov_read_default(c, pb, atom)) < 0)
1578 return ret;
1579 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1580 /* so we don't parse the whole file if over a network */
1581 487 c->found_moov=1;
1582 487 return 0; /* now go for mdat */
1583 }
1584
1585 2869 static MOVFragmentStreamInfo * get_frag_stream_info(
1586 MOVFragmentIndex *frag_index,
1587 int index,
1588 int id)
1589 {
1590 int i;
1591 MOVFragmentIndexItem * item;
1592
1593
2/4
✓ Branch 0 taken 2869 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2869 times.
2869 if (index < 0 || index >= frag_index->nb_items)
1594 return NULL;
1595 2869 item = &frag_index->item[index];
1596
1/2
✓ Branch 0 taken 2993 times.
✗ Branch 1 not taken.
2993 for (i = 0; i < item->nb_stream_info; i++)
1597
2/2
✓ Branch 0 taken 2869 times.
✓ Branch 1 taken 124 times.
2993 if (item->stream_info[i].id == id)
1598 2869 return &item->stream_info[i];
1599
1600 // This shouldn't happen
1601 return NULL;
1602 }
1603
1604 388 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1605 {
1606 int i;
1607 MOVFragmentIndexItem * item;
1608
1609
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_index->current < 0 ||
1610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 frag_index->current >= frag_index->nb_items)
1611 return;
1612
1613 388 item = &frag_index->item[frag_index->current];
1614
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < item->nb_stream_info; i++)
1615
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (item->stream_info[i].id == id) {
1616 388 item->current = i;
1617 388 return;
1618 }
1619
1620 // id not found. This shouldn't happen.
1621 item->current = -1;
1622 }
1623
1624 1149 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1625 MOVFragmentIndex *frag_index)
1626 {
1627 MOVFragmentIndexItem *item;
1628
1/2
✓ Branch 0 taken 1149 times.
✗ Branch 1 not taken.
1149 if (frag_index->current < 0 ||
1629
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1146 times.
1149 frag_index->current >= frag_index->nb_items)
1630 3 return NULL;
1631
1632 1146 item = &frag_index->item[frag_index->current];
1633
2/4
✓ Branch 0 taken 1146 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1146 times.
✗ Branch 3 not taken.
1146 if (item->current >= 0 && item->current < item->nb_stream_info)
1634 1146 return &item->stream_info[item->current];
1635
1636 // This shouldn't happen
1637 return NULL;
1638 }
1639
1640 798 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1641 {
1642 int a, b, m;
1643 int64_t moof_offset;
1644
1645 // Optimize for appending new entries
1646
2/2
✓ Branch 0 taken 788 times.
✓ Branch 1 taken 10 times.
798 if (!frag_index->nb_items ||
1647
2/2
✓ Branch 0 taken 383 times.
✓ Branch 1 taken 405 times.
788 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1648 393 return frag_index->nb_items;
1649
1650 405 a = -1;
1651 405 b = frag_index->nb_items;
1652
1653
2/2
✓ Branch 0 taken 2655 times.
✓ Branch 1 taken 405 times.
3060 while (b - a > 1) {
1654 2655 m = (a + b) >> 1;
1655 2655 moof_offset = frag_index->item[m].moof_offset;
1656
2/2
✓ Branch 0 taken 732 times.
✓ Branch 1 taken 1923 times.
2655 if (moof_offset >= offset)
1657 732 b = m;
1658
2/2
✓ Branch 0 taken 2328 times.
✓ Branch 1 taken 327 times.
2655 if (moof_offset <= offset)
1659 2328 a = m;
1660 }
1661 405 return b;
1662 }
1663
1664 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1665 {
1666 av_assert0(frag_stream_info);
1667 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1668 return frag_stream_info->sidx_pts;
1669 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1670 return frag_stream_info->first_tfra_pts;
1671 return frag_stream_info->tfdt_dts;
1672 }
1673
1674 219 static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1675 MOVFragmentIndex *frag_index, int index)
1676 {
1677 MOVFragmentStreamInfo * frag_stream_info;
1678 219 MOVStreamContext *sc = dst_st->priv_data;
1679 int64_t timestamp;
1680 int i, j;
1681
1682 // If the stream is referenced by any sidx, limit the search
1683 // to fragments that referenced this stream in the sidx
1684
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (sc->has_sidx) {
1685 219 frag_stream_info = get_frag_stream_info(frag_index, index, sc->id);
1686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!frag_stream_info)
1687 return AV_NOPTS_VALUE;
1688
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1689 219 return frag_stream_info->sidx_pts;
1690 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1691 return frag_stream_info->first_tfra_pts;
1692 return frag_stream_info->sidx_pts;
1693 }
1694
1695 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
1696 AVStream *frag_stream = NULL;
1697 frag_stream_info = &frag_index->item[index].stream_info[i];
1698 for (j = 0; j < s->nb_streams; j++) {
1699 MOVStreamContext *sc2 = s->streams[j]->priv_data;
1700 if (sc2->id == frag_stream_info->id)
1701 frag_stream = s->streams[j];
1702 }
1703 if (!frag_stream) {
1704 av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1705 continue;
1706 }
1707 timestamp = get_stream_info_time(frag_stream_info);
1708 if (timestamp != AV_NOPTS_VALUE)
1709 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1710 }
1711 return AV_NOPTS_VALUE;
1712 }
1713
1714 26 static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1715 AVStream *st, int64_t timestamp)
1716 {
1717 int a, b, m, m0;
1718 int64_t frag_time;
1719
1720 26 a = -1;
1721 26 b = frag_index->nb_items;
1722
1723
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 26 times.
245 while (b - a > 1) {
1724 219 m0 = m = (a + b) >> 1;
1725
1726
2/4
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 219 times.
438 while (m < b &&
1727 219 (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
1728 m++;
1729
1730
3/4
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 93 times.
✓ Branch 3 taken 126 times.
219 if (m < b && frag_time <= timestamp)
1731 93 a = m;
1732 else
1733 126 b = m0;
1734 }
1735
1736 26 return a;
1737 }
1738
1739 756 static int update_frag_index(MOVContext *c, int64_t offset)
1740 {
1741 int index, i;
1742 MOVFragmentIndexItem * item;
1743 MOVFragmentStreamInfo * frag_stream_info;
1744
1745 // If moof_offset already exists in frag_index, return index to it
1746 756 index = search_frag_moof_offset(&c->frag_index, offset);
1747
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 389 times.
756 if (index < c->frag_index.nb_items &&
1748
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 c->frag_index.item[index].moof_offset == offset)
1749 367 return index;
1750
1751 // offset is not yet in frag index.
1752 // Insert new item at index (sorted by moof offset)
1753 389 item = av_fast_realloc(c->frag_index.item,
1754 389 &c->frag_index.allocated_size,
1755 389 (c->frag_index.nb_items + 1) *
1756 sizeof(*c->frag_index.item));
1757
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (!item)
1758 return -1;
1759 389 c->frag_index.item = item;
1760
1761 389 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1762 sizeof(*item->stream_info));
1763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (!frag_stream_info)
1764 return -1;
1765
1766
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 389 times.
796 for (i = 0; i < c->fc->nb_streams; i++) {
1767 // Avoid building frag index if streams lack track id.
1768 407 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 407 times.
407 if (sc->id < 0) {
1770 av_free(frag_stream_info);
1771 return AVERROR_INVALIDDATA;
1772 }
1773
1774 407 frag_stream_info[i].id = sc->id;
1775 407 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1776 407 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1777 407 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1778 407 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1779 407 frag_stream_info[i].index_base = -1;
1780 407 frag_stream_info[i].index_entry = -1;
1781 407 frag_stream_info[i].encryption_index = NULL;
1782 407 frag_stream_info[i].stsd_id = -1;
1783 }
1784
1785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (index < c->frag_index.nb_items)
1786 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1787 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1788
1789 389 item = &c->frag_index.item[index];
1790 389 item->headers_read = 0;
1791 389 item->current = 0;
1792 389 item->nb_stream_info = c->fc->nb_streams;
1793 389 item->moof_offset = offset;
1794 389 item->stream_info = frag_stream_info;
1795 389 c->frag_index.nb_items++;
1796
1797 389 return index;
1798 }
1799
1800 388 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1801 int id, int entries)
1802 {
1803 int i;
1804 MOVFragmentStreamInfo * frag_stream_info;
1805
1806
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (index < 0)
1807 388 return;
1808 for (i = index; i < frag_index->nb_items; i++) {
1809 frag_stream_info = get_frag_stream_info(frag_index, i, id);
1810 if (frag_stream_info && frag_stream_info->index_entry >= 0)
1811 frag_stream_info->index_entry += entries;
1812 }
1813 }
1814
1815 388 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1816 {
1817 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1818 388 c->fragment.found_tfhd = 0;
1819
1820
2/4
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 388 times.
388 if (!c->has_looked_for_mfra && c->use_mfra_for > 0) {
1821 c->has_looked_for_mfra = 1;
1822 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1823 int ret;
1824 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1825 "for a mfra\n");
1826 if ((ret = mov_read_mfra(c, pb)) < 0) {
1827 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1828 "read the mfra (may be a live ismv)\n");
1829 }
1830 } else {
1831 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1832 "seekable, can not look for mfra\n");
1833 }
1834 }
1835 388 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1836 388 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1837 388 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1838 388 return mov_read_default(c, pb, atom);
1839 }
1840
1841 1082 static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version)
1842 {
1843 int64_t time;
1844
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1071 times.
1082 if (version == 1) {
1845 11 time = avio_rb64(pb);
1846 11 avio_rb64(pb);
1847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (time < 0) {
1848 av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n");
1849 return;
1850 }
1851 } else {
1852 1071 time = avio_rb32(pb);
1853 1071 avio_rb32(pb); /* modification time */
1854
4/4
✓ Branch 0 taken 519 times.
✓ Branch 1 taken 552 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 471 times.
1071 if (time > 0 && time < 2082844800) {
1855 48 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1856 48 time += 2082844800;
1857 }
1858 }
1859
2/2
✓ Branch 0 taken 525 times.
✓ Branch 1 taken 557 times.
1082 if (time) {
1860 525 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1861
1862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 525 times.
525 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1863 av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n");
1864 return;
1865 }
1866
1867 525 ff_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1868 }
1869 }
1870
1871 598 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1872 {
1873 AVStream *st;
1874 MOVStreamContext *sc;
1875 int version;
1876 598 char language[4] = {0};
1877 unsigned lang;
1878
1879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (c->fc->nb_streams < 1)
1880 return 0;
1881 598 st = c->fc->streams[c->fc->nb_streams-1];
1882 598 sc = st->priv_data;
1883
1884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (sc->time_scale) {
1885 av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
1886 return AVERROR_INVALIDDATA;
1887 }
1888
1889 598 version = avio_r8(pb);
1890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (version > 1) {
1891 avpriv_request_sample(c->fc, "Version %d", version);
1892 return AVERROR_PATCHWELCOME;
1893 }
1894 598 avio_rb24(pb); /* flags */
1895 598 mov_metadata_creation_time(c, pb, &st->metadata, version);
1896
1897 598 sc->time_scale = avio_rb32(pb);
1898
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (sc->time_scale <= 0) {
1899 av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
1900 sc->time_scale = 1;
1901 }
1902
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 589 times.
598 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1903
1904
6/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 589 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 589 times.
✓ Branch 5 taken 4 times.
598 if ((version == 1 && st->duration == UINT64_MAX) ||
1905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 589 times.
589 (version != 1 && st->duration == UINT32_MAX)) {
1906 5 st->duration = 0;
1907 }
1908
1909 598 lang = avio_rb16(pb); /* language */
1910
2/2
✓ Branch 1 taken 426 times.
✓ Branch 2 taken 172 times.
598 if (ff_mov_lang_to_iso639(lang, language))
1911 426 av_dict_set(&st->metadata, "language", language, 0);
1912 598 avio_rb16(pb); /* quality */
1913
1914 598 return 0;
1915 }
1916
1917 484 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1918 {
1919 int i;
1920 484 int version = avio_r8(pb); /* version */
1921 484 avio_rb24(pb); /* flags */
1922
1923 484 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
1924 484 c->time_scale = avio_rb32(pb); /* time scale */
1925
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
484 if (c->time_scale <= 0) {
1926 av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
1927 c->time_scale = 1;
1928 }
1929 484 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
1930
1931
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 482 times.
484 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1932 484 avio_rb32(pb); /* preferred scale */
1933
1934 484 avio_rb16(pb); /* preferred volume */
1935
1936 484 avio_skip(pb, 10); /* reserved */
1937
1938 /* movie display matrix, store it in main context and use it later on */
1939
2/2
✓ Branch 0 taken 1452 times.
✓ Branch 1 taken 484 times.
1936 for (i = 0; i < 3; i++) {
1940 1452 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
1941 1452 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
1942 1452 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
1943 }
1944
1945 484 avio_rb32(pb); /* preview time */
1946 484 avio_rb32(pb); /* preview duration */
1947 484 avio_rb32(pb); /* poster time */
1948 484 avio_rb32(pb); /* selection time */
1949 484 avio_rb32(pb); /* selection duration */
1950 484 avio_rb32(pb); /* current time */
1951 484 avio_rb32(pb); /* next track ID */
1952
1953 484 return 0;
1954 }
1955
1956 7 static void set_last_stream_little_endian(AVFormatContext *fc)
1957 {
1958 AVStream *st;
1959
1960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (fc->nb_streams < 1)
1961 return;
1962 7 st = fc->streams[fc->nb_streams-1];
1963
1964
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) {
1965 5 case AV_CODEC_ID_PCM_S16BE:
1966 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
1967 5 break;
1968 1 case AV_CODEC_ID_PCM_S24BE:
1969 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
1970 1 break;
1971 case AV_CODEC_ID_PCM_S32BE:
1972 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
1973 break;
1974 1 case AV_CODEC_ID_PCM_F32BE:
1975 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
1976 1 break;
1977 case AV_CODEC_ID_PCM_F64BE:
1978 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
1979 break;
1980 default:
1981 break;
1982 }
1983 }
1984
1985 5 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1986 {
1987 5 int little_endian = avio_rb16(pb) & 0xFF;
1988 5 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
1989
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (little_endian == 1)
1990 1 set_last_stream_little_endian(c->fc);
1991 5 return 0;
1992 }
1993
1994 6 static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1995 {
1996 int format_flags;
1997 int version, flags;
1998 int pcm_sample_size;
1999 6 AVFormatContext *fc = c->fc;
2000 AVStream *st;
2001 MOVStreamContext *sc;
2002
2003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 6) {
2004 av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n");
2005 return AVERROR_INVALIDDATA;
2006 }
2007
2008 6 version = avio_r8(pb);
2009 6 flags = avio_rb24(pb);
2010
2011
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) {
2012 av_log(c->fc, AV_LOG_ERROR,
2013 "Unsupported 'pcmC' box with version %d, flags: %x",
2014 version, flags);
2015 return AVERROR_INVALIDDATA;
2016 }
2017
2018 6 format_flags = avio_r8(pb);
2019 6 pcm_sample_size = avio_r8(pb);
2020
2021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fc->nb_streams < 1)
2022 return AVERROR_INVALIDDATA;
2023
2024 6 st = fc->streams[fc->nb_streams - 1];
2025 6 sc = st->priv_data;
2026
2027
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (sc->format == MOV_MP4_FPCM_TAG) {
2028
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (pcm_sample_size) {
2029 1 case 32:
2030 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE;
2031 1 break;
2032 case 64:
2033 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE;
2034 break;
2035 default:
2036 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2037 pcm_sample_size,
2038 av_fourcc2str(sc->format));
2039 return AVERROR_INVALIDDATA;
2040 }
2041
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (sc->format == MOV_MP4_IPCM_TAG) {
2042
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 switch (pcm_sample_size) {
2043 5 case 16:
2044 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2045 5 break;
2046 case 24:
2047 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
2048 break;
2049 case 32:
2050 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
2051 break;
2052 default:
2053 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2054 pcm_sample_size,
2055 av_fourcc2str(sc->format));
2056 return AVERROR_INVALIDDATA;
2057 }
2058 } else {
2059 av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n",
2060 av_fourcc2str(sc->format));
2061 return AVERROR_INVALIDDATA;
2062 }
2063
2064
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
2065 6 set_last_stream_little_endian(c->fc);
2066 6 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2067
2068 6 return 0;
2069 }
2070
2071 46 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2072 {
2073 AVStream *st;
2074 46 HEIFItem *item = NULL;
2075 46 char color_parameter_type[5] = { 0 };
2076 uint16_t color_primaries, color_trc, color_matrix;
2077 int ret;
2078
2079 46 st = get_curr_st(c);
2080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!st) {
2081 item = heif_cur_item(c);
2082 if (!item)
2083 return 0;
2084 }
2085
2086 46 ret = ffio_read_size(pb, color_parameter_type, 4);
2087
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (ret < 0)
2088 return ret;
2089
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 13 times.
46 if (strncmp(color_parameter_type, "nclx", 4) &&
2090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 strncmp(color_parameter_type, "nclc", 4) &&
2091 strncmp(color_parameter_type, "prof", 4)) {
2092 av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
2093 color_parameter_type);
2094 return 0;
2095 }
2096
2097
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!strncmp(color_parameter_type, "prof", 4)) {
2098 AVPacketSideData *sd;
2099 uint8_t *icc_profile;
2100 if (st) {
2101 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
2102 &st->codecpar->nb_coded_side_data,
2103 AV_PKT_DATA_ICC_PROFILE,
2104 atom.size - 4, 0);
2105 if (!sd)
2106 return AVERROR(ENOMEM);
2107 icc_profile = sd->data;
2108 } else {
2109 av_freep(&item->icc_profile);
2110 icc_profile = item->icc_profile = av_malloc(atom.size - 4);
2111 if (!icc_profile) {
2112 item->icc_profile_size = 0;
2113 return AVERROR(ENOMEM);
2114 }
2115 item->icc_profile_size = atom.size - 4;
2116 }
2117 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
2118 if (ret < 0)
2119 return ret;
2120
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 } else if (st) {
2121 46 color_primaries = avio_rb16(pb);
2122 46 color_trc = avio_rb16(pb);
2123 46 color_matrix = avio_rb16(pb);
2124
2125 46 av_log(c->fc, AV_LOG_TRACE,
2126 "%s: pri %d trc %d matrix %d",
2127 color_parameter_type, color_primaries, color_trc, color_matrix);
2128
2129
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 33 times.
46 if (!strncmp(color_parameter_type, "nclx", 4)) {
2130 13 uint8_t color_range = avio_r8(pb) >> 7;
2131 13 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2132
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
13 if (color_range)
2133 2 st->codecpar->color_range = AVCOL_RANGE_JPEG;
2134 else
2135 11 st->codecpar->color_range = AVCOL_RANGE_MPEG;
2136 }
2137
2138
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if (!av_color_primaries_name(color_primaries))
2139 color_primaries = AVCOL_PRI_UNSPECIFIED;
2140
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if (!av_color_transfer_name(color_trc))
2141 color_trc = AVCOL_TRC_UNSPECIFIED;
2142
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if (!av_color_space_name(color_matrix))
2143 color_matrix = AVCOL_SPC_UNSPECIFIED;
2144
2145 46 st->codecpar->color_primaries = color_primaries;
2146 46 st->codecpar->color_trc = color_trc;
2147 46 st->codecpar->color_space = color_matrix;
2148 46 av_log(c->fc, AV_LOG_TRACE, "\n");
2149 }
2150 46 return 0;
2151 }
2152
2153 112 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2154 {
2155 AVStream *st;
2156 unsigned mov_field_order;
2157 112 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2158
2159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (c->fc->nb_streams < 1) // will happen with jp2 files
2160 return 0;
2161 112 st = c->fc->streams[c->fc->nb_streams-1];
2162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (atom.size < 2)
2163 return AVERROR_INVALIDDATA;
2164 112 mov_field_order = avio_rb16(pb);
2165
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 20 times.
112 if ((mov_field_order & 0xFF00) == 0x0100)
2166 92 decoded_field_order = AV_FIELD_PROGRESSIVE;
2167
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 else if ((mov_field_order & 0xFF00) == 0x0200) {
2168
3/5
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
20 switch (mov_field_order & 0xFF) {
2169 1 case 0x01: decoded_field_order = AV_FIELD_TT;
2170 1 break;
2171 case 0x06: decoded_field_order = AV_FIELD_BB;
2172 break;
2173 1 case 0x09: decoded_field_order = AV_FIELD_TB;
2174 1 break;
2175 18 case 0x0E: decoded_field_order = AV_FIELD_BT;
2176 18 break;
2177 }
2178 }
2179
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
112 if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) {
2180 av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
2181 }
2182 112 st->codecpar->field_order = decoded_field_order;
2183
2184 112 return 0;
2185 }
2186
2187 68 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
2188 {
2189 68 int err = 0;
2190 68 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
2191
2/4
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 68 times.
68 if (size > INT_MAX || (uint64_t)atom.size > INT_MAX)
2192 return AVERROR_INVALIDDATA;
2193
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
68 if ((err = av_reallocp(&par->extradata, size)) < 0) {
2194 par->extradata_size = 0;
2195 return err;
2196 }
2197 68 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
2198 68 return 0;
2199 }
2200
2201 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
2202 65 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2203 AVCodecParameters *par, uint8_t *buf)
2204 {
2205 65 int64_t result = atom.size;
2206 int err;
2207
2208 65 AV_WB32(buf , atom.size + 8);
2209 65 AV_WL32(buf + 4, atom.type);
2210 65 err = ffio_read_size(pb, buf + 8, atom.size);
2211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (err < 0) {
2212 par->extradata_size -= atom.size;
2213 return err;
2214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 } else if (err < atom.size) {
2215 av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
2216 par->extradata_size -= atom.size - err;
2217 result = err;
2218 }
2219 65 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2220 65 return result;
2221 }
2222
2223 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
2224 58 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2225 enum AVCodecID codec_id)
2226 {
2227 AVStream *st;
2228 uint64_t original_size;
2229 int err;
2230
2231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (c->fc->nb_streams < 1) // will happen with jp2 files
2232 return 0;
2233 58 st = c->fc->streams[c->fc->nb_streams-1];
2234
2235
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
58 if (st->codecpar->codec_id != codec_id)
2236 19 return 0; /* unexpected codec_id - don't mess with extradata */
2237
2238 39 original_size = st->codecpar->extradata_size;
2239 39 err = mov_realloc_extradata(st->codecpar, atom);
2240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err)
2241 return err;
2242
2243 39 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
2244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err < 0)
2245 return err;
2246 39 return 0; // Note: this is the original behavior to ignore truncation.
2247 }
2248
2249 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
2250 16 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2251 {
2252 16 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
2253 }
2254
2255 static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2256 {
2257 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS);
2258 }
2259
2260 static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2261 {
2262 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
2263 }
2264
2265 static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2266 {
2267 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
2268 }
2269
2270 19 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2271 {
2272 19 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
2273
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!ret)
2274 19 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
2275 19 return ret;
2276 }
2277
2278 static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2279 {
2280 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
2281
2282 if (!ret && c->fc->nb_streams >= 1) {
2283 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2284 if (par->extradata_size >= 40) {
2285 par->height = AV_RB16(&par->extradata[36]);
2286 par->width = AV_RB16(&par->extradata[38]);
2287 }
2288 }
2289 return ret;
2290 }
2291
2292 16 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2293 {
2294
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (c->fc->nb_streams >= 1) {
2295 16 AVStream *const st = c->fc->streams[c->fc->nb_streams - 1];
2296 16 FFStream *const sti = ffstream(st);
2297 16 AVCodecParameters *par = st->codecpar;
2298
2299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
2300 par->codec_id == AV_CODEC_ID_H264 &&
2301 atom.size > 11) {
2302 int cid;
2303 avio_skip(pb, 10);
2304 cid = avio_rb16(pb);
2305 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
2306 if (cid == 0xd4d || cid == 0xd4e)
2307 par->width = 1440;
2308 return 0;
2309
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
2310
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
2311
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
2312
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 atom.size >= 24) {
2313 int num, den;
2314 13 avio_skip(pb, 12);
2315 13 num = avio_rb32(pb);
2316 13 den = avio_rb32(pb);
2317
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)
2318 return 0;
2319
2/3
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
13 switch (avio_rb32(pb)) {
2320 12 case 2:
2321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (den >= INT_MAX / 2)
2322 return 0;
2323 12 den *= 2;
2324 13 case 1:
2325 13 sti->display_aspect_ratio = (AVRational){ num, den };
2326 13 default:
2327 13 return 0;
2328 }
2329 }
2330 }
2331
2332 3 return mov_read_avid(c, pb, atom);
2333 }
2334
2335 26 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2336 {
2337 26 int ret = 0;
2338 26 int length = 0;
2339 uint64_t original_size;
2340
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (c->fc->nb_streams >= 1) {
2341 26 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (par->codec_id == AV_CODEC_ID_H264)
2343 return 0;
2344
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (atom.size == 16) {
2345 26 original_size = par->extradata_size;
2346 26 ret = mov_realloc_extradata(par, atom);
2347
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!ret) {
2348 26 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
2349
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (length == atom.size) {
2350 26 const uint8_t range_value = par->extradata[original_size + 19];
2351
1/3
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
26 switch (range_value) {
2352 26 case 1:
2353 26 par->color_range = AVCOL_RANGE_MPEG;
2354 26 break;
2355 case 2:
2356 par->color_range = AVCOL_RANGE_JPEG;
2357 break;
2358 default:
2359 av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
2360 break;
2361 }
2362 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
2363 } else {
2364 /* For some reason the whole atom was not added to the extradata */
2365 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
2366 }
2367 } else {
2368 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
2369 }
2370 } else {
2371 av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
2372 }
2373 }
2374
2375 26 return ret;
2376 }
2377
2378 4 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2379 {
2380 4 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
2381 }
2382
2383 34 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2384 {
2385 AVStream *st;
2386 int ret;
2387
2388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (c->fc->nb_streams < 1)
2389 return 0;
2390 34 st = c->fc->streams[c->fc->nb_streams-1];
2391
2392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if ((uint64_t)atom.size > (1<<30))
2393 return AVERROR_INVALIDDATA;
2394
2395
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2 times.
34 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2396
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
2398 // pass all frma atom to codec, needed at least for QDMC and QDM2
2399 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2401 return ret;
2402
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 } else if (atom.size > 8) { /* to read frma, esds atoms */
2403
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
32 if (st->codecpar->codec_id == AV_CODEC_ID_ALAC && atom.size >= 24) {
2404 uint64_t buffer;
2405 10 ret = ffio_ensure_seekback(pb, 8);
2406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2407 return ret;
2408 10 buffer = avio_rb64(pb);
2409 10 atom.size -= 8;
2410
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
2411
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 <= atom.size
2412
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 >= 8) {
2413 10 avio_skip(pb, -8);
2414 10 atom.size += 8;
2415 } else if (!st->codecpar->extradata_size) {
2416 #define ALAC_EXTRADATA_SIZE 36
2417 st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
2418 if (!st->codecpar->extradata)
2419 return AVERROR(ENOMEM);
2420 st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
2421 AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
2422 AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
2423 AV_WB64(st->codecpar->extradata + 12, buffer);
2424 avio_read(pb, st->codecpar->extradata + 20, 16);
2425 avio_skip(pb, atom.size - 24);
2426 return 0;
2427 }
2428 }
2429
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if ((ret = mov_read_default(c, pb, atom)) < 0)
2430 return ret;
2431 } else
2432 avio_skip(pb, atom.size);
2433 34 return 0;
2434 }
2435
2436 /**
2437 * This function reads atom content and puts data in extradata without tag
2438 * nor size unlike mov_read_extradata.
2439 */
2440 144 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2441 {
2442 AVStream *st;
2443 int ret;
2444
2445 144 st = get_curr_st(c);
2446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (!st)
2447 return 0;
2448
2449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if ((uint64_t)atom.size > (1<<30))
2450 return AVERROR_INVALIDDATA;
2451
2452
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 143 times.
144 if (atom.type == MKTAG('v','v','c','C')) {
2453 1 avio_skip(pb, 4);
2454 1 atom.size -= 4;
2455 }
2456
2457
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 4 times.
144 if (atom.size >= 10) {
2458 // Broken files created by legacy versions of libavformat will
2459 // wrap a whole fiel atom inside of a glbl atom.
2460 140 unsigned size = avio_rb32(pb);
2461 140 unsigned type = avio_rl32(pb);
2462
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 140 times.
140 if (avio_feof(pb))
2463 return AVERROR_INVALIDDATA;
2464 140 avio_seek(pb, -8, SEEK_CUR);
2465
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 132 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
140 if (type == MKTAG('f','i','e','l') && size == atom.size)
2466 8 return mov_read_default(c, pb, atom);
2467 }
2468
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
136 if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
2469 av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
2470 return 0;
2471 }
2472 136 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2473
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (ret < 0)
2474 return ret;
2475
3/4
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 93 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 43 times.
136 if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
2476 /* HEVC-based Dolby Vision derived from hvc1.
2477 Happens to match with an identifier
2478 previously utilized for DV. Thus, if we have
2479 the hvcC extradata box available as specified,
2480 set codec to HEVC */
2481 st->codecpar->codec_id = AV_CODEC_ID_HEVC;
2482
2483 136 return 0;
2484 }
2485
2486 2 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2487 {
2488 AVStream *st;
2489 uint8_t profile_level;
2490 int ret;
2491
2492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
2493 return 0;
2494 2 st = c->fc->streams[c->fc->nb_streams-1];
2495
2496
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)
2497 return AVERROR_INVALIDDATA;
2498
2499 2 profile_level = avio_r8(pb);
2500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((profile_level & 0xf0) != 0xc0)
2501 return 0;
2502
2503 2 avio_seek(pb, 6, SEEK_CUR);
2504 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
2505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2506 return ret;
2507
2508 2 return 0;
2509 }
2510
2511 static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2512 {
2513 AVStream* st;
2514 MOVStreamContext* sc;
2515
2516 if (c->fc->nb_streams < 1)
2517 return 0;
2518
2519 /* For SBAS this should be fine - though beware if someone implements a
2520 * tref atom processor that doesn't drop down to default then this may
2521 * be lost. */
2522 if (atom.size > 4) {
2523 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2524 return AVERROR_PATCHWELCOME;
2525 }
2526
2527 st = c->fc->streams[c->fc->nb_streams - 1];
2528 sc = st->priv_data;
2529 sc->tref_id = avio_rb32(pb);
2530 sc->tref_flags |= MOV_TREF_FLAG_ENHANCEMENT;
2531
2532 return 0;
2533 }
2534
2535 /**
2536 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2537 * but can have extradata appended at the end after the 40 bytes belonging
2538 * to the struct.
2539 */
2540 static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2541 {
2542 AVStream *st;
2543 int ret;
2544
2545 if (c->fc->nb_streams < 1)
2546 return 0;
2547 if (atom.size <= 40)
2548 return 0;
2549 st = c->fc->streams[c->fc->nb_streams-1];
2550
2551 if ((uint64_t)atom.size > (1<<30))
2552 return AVERROR_INVALIDDATA;
2553
2554 avio_skip(pb, 40);
2555 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
2556 if (ret < 0)
2557 return ret;
2558
2559 return 0;
2560 }
2561
2562 598 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2563 {
2564 AVStream *st;
2565 MOVStreamContext *sc;
2566 unsigned int i, entries;
2567
2568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (c->trak_index < 0) {
2569 av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
2570 return 0;
2571 }
2572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (c->fc->nb_streams < 1)
2573 return 0;
2574 598 st = c->fc->streams[c->fc->nb_streams-1];
2575 598 sc = st->priv_data;
2576
2577 598 avio_r8(pb); /* version */
2578 598 avio_rb24(pb); /* flags */
2579
2580 // Clamp allocation size for `chunk_offsets` -- don't throw an error for an
2581 // invalid count since the EOF path doesn't throw either.
2582 598 entries = avio_rb32(pb);
2583 598 entries =
2584
2/2
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 5 times.
598 FFMIN(entries,
2585 FFMAX(0, (atom.size - 8) /
2586 (atom.type == MKTAG('s', 't', 'c', 'o') ? 4 : 8)));
2587
2588
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 582 times.
598 if (!entries)
2589 16 return 0;
2590
2591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 582 times.
582 if (sc->chunk_offsets) {
2592 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2593 return 0;
2594 }
2595
2596 582 av_free(sc->chunk_offsets);
2597 582 sc->chunk_count = 0;
2598 582 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 582 times.
582 if (!sc->chunk_offsets)
2600 return AVERROR(ENOMEM);
2601 582 sc->chunk_count = entries;
2602
2603
2/2
✓ Branch 0 taken 578 times.
✓ Branch 1 taken 4 times.
582 if (atom.type == MKTAG('s','t','c','o'))
2604
3/4
✓ Branch 0 taken 42911 times.
✓ Branch 1 taken 578 times.
✓ Branch 2 taken 42911 times.
✗ Branch 3 not taken.
43489 for (i = 0; i < entries && !pb->eof_reached; i++)
2605 42911 sc->chunk_offsets[i] = avio_rb32(pb);
2606
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (atom.type == MKTAG('c','o','6','4'))
2607
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++) {
2608 136336 sc->chunk_offsets[i] = avio_rb64(pb);
2609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136336 times.
136336 if (sc->chunk_offsets[i] < 0) {
2610 av_log(c->fc, AV_LOG_WARNING, "Impossible chunk_offset\n");
2611 sc->chunk_offsets[i] = 0;
2612 }
2613 }
2614 else
2615 return AVERROR_INVALIDDATA;
2616
2617 582 sc->chunk_count = i;
2618
2619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 582 times.
582 if (pb->eof_reached) {
2620 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2621 return AVERROR_EOF;
2622 }
2623
2624 582 return 0;
2625 }
2626
2627 643 static int mov_codec_id(AVStream *st, uint32_t format)
2628 {
2629 643 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2630
2631
2/2
✓ Branch 0 taken 423 times.
✓ Branch 1 taken 220 times.
643 if (id <= 0 &&
2632
2/2
✓ Branch 0 taken 420 times.
✓ Branch 1 taken 3 times.
423 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 420 times.
420 (format & 0xFFFF) == 'T' + ('S' << 8)))
2634 3 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2635
2636
4/4
✓ Branch 0 taken 293 times.
✓ Branch 1 taken 350 times.
✓ Branch 2 taken 223 times.
✓ Branch 3 taken 70 times.
643 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2637 223 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2638
3/4
✓ Branch 0 taken 402 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 402 times.
✗ Branch 3 not taken.
420 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2639 /* skip old ASF MPEG-4 tag */
2640
2/2
✓ Branch 0 taken 398 times.
✓ Branch 1 taken 4 times.
402 format && format != MKTAG('m','p','4','s')) {
2641 398 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2642
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 343 times.
398 if (id <= 0)
2643 55 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2644
2/2
✓ Branch 0 taken 347 times.
✓ Branch 1 taken 51 times.
398 if (id > 0)
2645 347 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2646
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 47 times.
51 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2647
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2648
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2649 47 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2650
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6 times.
47 if (id <= 0) {
2651
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 2 times.
80 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2652
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 2 times.
80 AV_CODEC_ID_TTML : id;
2653 }
2654
2655
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 37 times.
47 if (id > 0)
2656 10 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2657 else
2658 37 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2659 }
2660 }
2661
2662 643 st->codecpar->codec_tag = format;
2663
2664 643 return id;
2665 }
2666
2667 316 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2668 AVStream *st, MOVStreamContext *sc)
2669 {
2670 316 uint8_t codec_name[32] = { 0 };
2671 int64_t stsd_start;
2672 unsigned int len;
2673 316 uint32_t id = 0;
2674
2675 /* The first 16 bytes of the video sample description are already
2676 * read in ff_mov_read_stsd_entries() */
2677 316 stsd_start = avio_tell(pb) - 16;
2678
2679 316 avio_rb16(pb); /* version */
2680 316 avio_rb16(pb); /* revision level */
2681 316 id = avio_rl32(pb); /* vendor */
2682 316 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2683 316 avio_rb32(pb); /* temporal quality */
2684 316 avio_rb32(pb); /* spatial quality */
2685
2686 316 st->codecpar->width = avio_rb16(pb); /* width */
2687 316 st->codecpar->height = avio_rb16(pb); /* height */
2688
2689 316 avio_rb32(pb); /* horiz resolution */
2690 316 avio_rb32(pb); /* vert resolution */
2691 316 avio_rb32(pb); /* data size, always 0 */
2692 316 avio_rb16(pb); /* frames per samples */
2693
2694 316 len = avio_r8(pb); /* codec name, pascal string */
2695
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 315 times.
316 if (len > 31)
2696 1 len = 31;
2697 316 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2698
2/2
✓ Branch 0 taken 313 times.
✓ Branch 1 taken 3 times.
316 if (len < 31)
2699 313 avio_skip(pb, 31 - len);
2700
2701
2/2
✓ Branch 0 taken 253 times.
✓ Branch 1 taken 63 times.
316 if (codec_name[0])
2702 253 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2703
2704 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 316 times.
316 if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2706 st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2707 st->codecpar->width &= ~1;
2708 st->codecpar->height &= ~1;
2709 }
2710 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 316 times.
316 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2712 !strncmp(codec_name, "Sorenson H263", 13))
2713 st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2714
2715 316 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2716
2717 316 avio_seek(pb, stsd_start, SEEK_SET);
2718
2719
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 298 times.
316 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2720 18 st->codecpar->bits_per_coded_sample &= 0x1F;
2721 18 sc->has_palette = 1;
2722 }
2723 316 }
2724
2725 241 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2726 AVStream *st, MOVStreamContext *sc)
2727 {
2728 int bits_per_sample, flags;
2729 241 uint16_t version = avio_rb16(pb);
2730 241 uint32_t id = 0;
2731 241 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2732 int channel_count;
2733
2734 241 avio_rb16(pb); /* revision level */
2735 241 id = avio_rl32(pb); /* vendor */
2736 241 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2737
2738 241 channel_count = avio_rb16(pb);
2739
2740 241 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2741 241 st->codecpar->ch_layout.nb_channels = channel_count;
2742 241 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
2743 241 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
2744
2745 241 sc->audio_cid = avio_rb16(pb);
2746 241 avio_rb16(pb); /* packet size = 0 */
2747
2748 241 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
2749
2750 // Read QT version 1 fields. In version 0 these do not exist.
2751 241 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
2752
3/4
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 86 times.
✓ Branch 2 taken 155 times.
✗ Branch 3 not taken.
241 if (!c->isom ||
2753
1/2
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
155 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
2754
3/4
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 151 times.
155 (sc->stsd_version == 0 && version > 0)) {
2755
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 40 times.
90 if (version == 1) {
2756 50 sc->samples_per_frame = avio_rb32(pb);
2757 50 avio_rb32(pb); /* bytes per packet */
2758 50 sc->bytes_per_frame = avio_rb32(pb);
2759 50 avio_rb32(pb); /* bytes per sample */
2760
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
40 } else if (version == 2) {
2761 4 avio_rb32(pb); /* sizeof struct only */
2762 4 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
2763 4 channel_count = avio_rb32(pb);
2764 4 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2765 4 st->codecpar->ch_layout.nb_channels = channel_count;
2766 4 avio_rb32(pb); /* always 0x7F000000 */
2767 4 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
2768
2769 4 flags = avio_rb32(pb); /* lpcm format specific flag */
2770 4 sc->bytes_per_frame = avio_rb32(pb);
2771 4 sc->samples_per_frame = avio_rb32(pb);
2772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
2773 st->codecpar->codec_id =
2774 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
2775 flags);
2776 }
2777
6/6
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 26 times.
90 if (version == 0 || (version == 1 && sc->audio_cid != -2)) {
2778 /* can't correctly handle variable sized packet as audio unit */
2779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 switch (st->codecpar->codec_id) {
2780 case AV_CODEC_ID_MP2:
2781 case AV_CODEC_ID_MP3:
2782 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
2783 break;
2784 }
2785 }
2786 }
2787
2788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (sc->format == 0) {
2789 if (st->codecpar->bits_per_coded_sample == 8)
2790 st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
2791 else if (st->codecpar->bits_per_coded_sample == 16)
2792 st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
2793 }
2794
2795
7/7
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 199 times.
241 switch (st->codecpar->codec_id) {
2796 7 case AV_CODEC_ID_PCM_S8:
2797 case AV_CODEC_ID_PCM_U8:
2798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
2799 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2800 7 break;
2801 19 case AV_CODEC_ID_PCM_S16LE:
2802 case AV_CODEC_ID_PCM_S16BE:
2803
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
19 if (st->codecpar->bits_per_coded_sample == 8)
2804 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
2805
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 24)
2806 st->codecpar->codec_id =
2807 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2808 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
2809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 32)
2810 st->codecpar->codec_id =
2811 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2812 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
2813 19 break;
2814 /* set values for old format before stsd version 1 appeared */
2815 2 case AV_CODEC_ID_MACE3:
2816 2 sc->samples_per_frame = 6;
2817 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
2818 2 break;
2819 8 case AV_CODEC_ID_MACE6:
2820 8 sc->samples_per_frame = 6;
2821 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
2822 8 break;
2823 5 case AV_CODEC_ID_ADPCM_IMA_QT:
2824 5 sc->samples_per_frame = 64;
2825 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
2826 5 break;
2827 1 case AV_CODEC_ID_GSM:
2828 1 sc->samples_per_frame = 160;
2829 1 sc->bytes_per_frame = 33;
2830 1 break;
2831 199 default:
2832 199 break;
2833 }
2834
2835 241 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2836
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 193 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
241 if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->ch_layout.nb_channels <= INT_MAX) {
2837 48 st->codecpar->bits_per_coded_sample = bits_per_sample;
2838 48 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
2839 }
2840 241 }
2841
2842 11 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
2843 AVStream *st, MOVStreamContext *sc,
2844 int64_t size)
2845 {
2846 // ttxt stsd contains display flags, justification, background
2847 // color, fonts, and default styles, so fake an atom to read it
2848 11 MOVAtom fake_atom = { .size = size };
2849 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
2850 // in extradata unlike stpp MP4 TTML.
2851
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
2852
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
2853 9 mov_read_glbl(c, pb, fake_atom);
2854 11 st->codecpar->width = sc->width;
2855 11 st->codecpar->height = sc->height;
2856 11 }
2857
2858 41 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
2859 AVStream *st, MOVStreamContext *sc,
2860 int64_t size)
2861 {
2862 int ret;
2863
2864
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 22 times.
41 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
2865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if ((int)size != size)
2866 return AVERROR(ENOMEM);
2867
2868 19 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
2869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
2870 return ret;
2871
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (size > 16) {
2872 19 MOVStreamContext *tmcd_ctx = st->priv_data;
2873 int val;
2874 19 val = AV_RB32(st->codecpar->extradata + 4);
2875 19 tmcd_ctx->tmcd_flags = val;
2876 19 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
2877 19 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
2878 19 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
2879
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (size > 30) {
2880 4 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
2881 4 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
2882
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if (format == AV_RB32("name") && (int64_t)size >= (int64_t)len + 18) {
2883 4 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
2884
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if (str_size > 0 && size >= (int)str_size + 30 &&
2885
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 st->codecpar->extradata[30] /* Don't add empty string */) {
2886 4 char *reel_name = av_malloc(str_size + 1);
2887
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!reel_name)
2888 return AVERROR(ENOMEM);
2889 4 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
2890 4 reel_name[str_size] = 0; /* Add null terminator */
2891 4 av_dict_set(&st->metadata, "reel_name", reel_name,
2892 AV_DICT_DONT_STRDUP_VAL);
2893 }
2894 }
2895 }
2896 }
2897 } else {
2898 /* other codec type, just skip (rtp, mp4s ...) */
2899 22 avio_skip(pb, size);
2900 }
2901 41 return 0;
2902 }
2903
2904 598 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
2905 AVStream *st, MOVStreamContext *sc)
2906 {
2907 598 FFStream *const sti = ffstream(st);
2908
2909
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 357 times.
598 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
2910
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
241 !st->codecpar->sample_rate && sc->time_scale > 1)
2911 st->codecpar->sample_rate = sc->time_scale;
2912
2913 /* special codec parameters handling */
2914
7/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 15 times.
✓ Branch 6 taken 16 times.
✓ Branch 7 taken 10 times.
✓ Branch 8 taken 67 times.
✓ Branch 9 taken 478 times.
598 switch (st->codecpar->codec_id) {
2915 #if CONFIG_DV_DEMUXER
2916 case AV_CODEC_ID_DVAUDIO:
2917 if (c->dv_fctx) {
2918 avpriv_request_sample(c->fc, "multiple DV audio streams");
2919 return AVERROR(ENOSYS);
2920 }
2921
2922 c->dv_fctx = avformat_alloc_context();
2923 if (!c->dv_fctx) {
2924 av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
2925 return AVERROR(ENOMEM);
2926 }
2927 c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
2928 if (!c->dv_demux) {
2929 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
2930 return AVERROR(ENOMEM);
2931 }
2932 sc->dv_audio_container = 1;
2933 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2934 break;
2935 #endif
2936 /* no ifdef since parameters are always those */
2937 case AV_CODEC_ID_QCELP:
2938 av_channel_layout_uninit(&st->codecpar->ch_layout);
2939 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2940 // force sample rate for qcelp when not stored in mov
2941 if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
2942 st->codecpar->sample_rate = 8000;
2943 // FIXME: Why is the following needed for some files?
2944 sc->samples_per_frame = 160;
2945 if (!sc->bytes_per_frame)
2946 sc->bytes_per_frame = 35;
2947 break;
2948 case AV_CODEC_ID_AMR_NB:
2949 av_channel_layout_uninit(&st->codecpar->ch_layout);
2950 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2951 /* force sample rate for amr, stsd in 3gp does not store sample rate */
2952 st->codecpar->sample_rate = 8000;
2953 break;
2954 11 case AV_CODEC_ID_AMR_WB:
2955 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
2956 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2957 11 st->codecpar->sample_rate = 16000;
2958 11 break;
2959 1 case AV_CODEC_ID_MP2:
2960 case AV_CODEC_ID_MP3:
2961 /* force type after stsd for m1a hdlr */
2962 1 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2963 1 break;
2964 15 case AV_CODEC_ID_GSM:
2965 case AV_CODEC_ID_ADPCM_MS:
2966 case AV_CODEC_ID_ADPCM_IMA_WAV:
2967 case AV_CODEC_ID_ILBC:
2968 case AV_CODEC_ID_MACE3:
2969 case AV_CODEC_ID_MACE6:
2970 case AV_CODEC_ID_QDM2:
2971 15 st->codecpar->block_align = sc->bytes_per_frame;
2972 15 break;
2973 16 case AV_CODEC_ID_ALAC:
2974
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
2975 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
2976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
2977 av_channel_layout_uninit(&st->codecpar->ch_layout);
2978 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2979 st->codecpar->ch_layout.nb_channels = channel_count;
2980 }
2981 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
2982 }
2983 16 break;
2984 10 case AV_CODEC_ID_AC3:
2985 case AV_CODEC_ID_EAC3:
2986 case AV_CODEC_ID_MPEG1VIDEO:
2987 case AV_CODEC_ID_VC1:
2988 case AV_CODEC_ID_VP8:
2989 case AV_CODEC_ID_VP9:
2990 10 sti->need_parsing = AVSTREAM_PARSE_FULL;
2991 10 break;
2992 67 case AV_CODEC_ID_APV:
2993 case AV_CODEC_ID_EVC:
2994 case AV_CODEC_ID_AV1:
2995 /* field_order detection of H264 requires parsing */
2996 case AV_CODEC_ID_H264:
2997 67 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
2998 67 break;
2999 478 default:
3000 478 break;
3001 }
3002 598 return 0;
3003 }
3004
3005 609 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
3006 int codec_tag, int format,
3007 int64_t size)
3008 {
3009
3/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 598 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
609 if (codec_tag &&
3010 (codec_tag != format &&
3011 // AVID 1:1 samples with differing data format and codec tag exist
3012 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
3013 // prores is allowed to have differing data format and codec tag
3014 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
3015 // so is dv (sigh)
3016 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
3017 (c->fc->video_codec_id ? ff_codec_get_id(ff_codec_movvideo_tags, format) != c->fc->video_codec_id
3018 : codec_tag != MKTAG('j','p','e','g')))) {
3019 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3020 * export it as a separate AVStream but this needs a few changes
3021 * in the MOV demuxer, patch welcome. */
3022
3023 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3024 avio_skip(pb, size);
3025 return 1;
3026 }
3027
3028 609 return 0;
3029 }
3030
3031 598 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3032 {
3033 AVStream *st;
3034 MOVStreamContext *sc;
3035 int pseudo_stream_id;
3036
3037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 av_assert0 (c->fc->nb_streams >= 1);
3038 598 st = c->fc->streams[c->fc->nb_streams-1];
3039 598 sc = st->priv_data;
3040
3041 598 for (pseudo_stream_id = 0;
3042
3/4
✓ Branch 0 taken 609 times.
✓ Branch 1 taken 598 times.
✓ Branch 2 taken 609 times.
✗ Branch 3 not taken.
1207 pseudo_stream_id < entries && !pb->eof_reached;
3043 609 pseudo_stream_id++) {
3044 //Parsing Sample description table
3045 enum AVCodecID id;
3046 609 int ret, dref_id = 1;
3047 609 MOVAtom a = { AV_RL32("stsd") };
3048 609 int64_t start_pos = avio_tell(pb);
3049 609 int64_t size = avio_rb32(pb); /* size */
3050 609 uint32_t format = avio_rl32(pb); /* data format */
3051
3052
1/2
✓ Branch 0 taken 609 times.
✗ Branch 1 not taken.
609 if (size >= 16) {
3053 609 avio_rb32(pb); /* reserved */
3054 609 avio_rb16(pb); /* reserved */
3055 609 dref_id = avio_rb16(pb);
3056 } else if (size <= 7) {
3057 av_log(c->fc, AV_LOG_ERROR,
3058 "invalid size %"PRId64" in stsd\n", size);
3059 return AVERROR_INVALIDDATA;
3060 }
3061
3062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 609 times.
609 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3063 609 size - (avio_tell(pb) - start_pos))) {
3064 sc->stsd_count++;
3065 continue;
3066 }
3067
3068
2/2
✓ Branch 0 taken 598 times.
✓ Branch 1 taken 11 times.
609 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
3069 609 sc->dref_id= dref_id;
3070 609 sc->format = format;
3071
3072 609 id = mov_codec_id(st, format);
3073
3074 609 av_log(c->fc, AV_LOG_TRACE,
3075 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3076 609 av_fourcc2str(format), st->codecpar->codec_type);
3077
3078 609 st->codecpar->codec_id = id;
3079
2/2
✓ Branch 0 taken 316 times.
✓ Branch 1 taken 293 times.
609 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3080 316 mov_parse_stsd_video(c, pb, st, sc);
3081
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 52 times.
293 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3082 241 mov_parse_stsd_audio(c, pb, st, sc);
3083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (st->codecpar->sample_rate < 0) {
3084 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3085 return AVERROR_INVALIDDATA;
3086 }
3087
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (st->codecpar->ch_layout.nb_channels < 0) {
3088 av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3089 return AVERROR_INVALIDDATA;
3090 }
3091
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 41 times.
52 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3092 11 mov_parse_stsd_subtitle(c, pb, st, sc,
3093 11 size - (avio_tell(pb) - start_pos));
3094 } else {
3095 41 ret = mov_parse_stsd_data(c, pb, st, sc,
3096 41 size - (avio_tell(pb) - start_pos));
3097
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ret < 0)
3098 return ret;
3099 }
3100 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3101 609 a.size = size - (avio_tell(pb) - start_pos);
3102
2/2
✓ Branch 0 taken 478 times.
✓ Branch 1 taken 131 times.
609 if (a.size > 8) {
3103
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
478 if ((ret = mov_read_default(c, pb, a)) < 0)
3104 return ret;
3105
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 130 times.
131 } else if (a.size > 0)
3106 1 avio_skip(pb, a.size);
3107
3108
3/4
✓ Branch 0 taken 609 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 342 times.
✓ Branch 3 taken 267 times.
609 if (sc->extradata && st->codecpar->extradata) {
3109 342 int extra_size = st->codecpar->extradata_size;
3110
3111 /* Move the current stream extradata to the stream context one. */
3112 342 sc->extradata_size[pseudo_stream_id] = extra_size;
3113 342 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3114 342 st->codecpar->extradata = NULL;
3115 342 st->codecpar->extradata_size = 0;
3116 }
3117 609 sc->stsd_count++;
3118 }
3119
3120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (pb->eof_reached) {
3121 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3122 return AVERROR_EOF;
3123 }
3124
3125 598 return 0;
3126 }
3127
3128 598 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3129 {
3130 AVStream *st;
3131 MOVStreamContext *sc;
3132 int ret, entries;
3133
3134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (c->fc->nb_streams < 1)
3135 return 0;
3136 598 st = c->fc->streams[c->fc->nb_streams - 1];
3137 598 sc = st->priv_data;
3138
3139 598 sc->stsd_version = avio_r8(pb);
3140 598 avio_rb24(pb); /* flags */
3141 598 entries = avio_rb32(pb);
3142
3143 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3144
3/6
✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 598 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 598 times.
598 if (entries <= 0 || entries > atom.size / 8 || entries > 1024) {
3145 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3146 return AVERROR_INVALIDDATA;
3147 }
3148
3149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (sc->extradata) {
3150 av_log(c->fc, AV_LOG_ERROR,
3151 "Duplicate stsd found in this track.\n");
3152 return AVERROR_INVALIDDATA;
3153 }
3154
3155 /* Prepare space for hosting multiple extradata. */
3156 598 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (!sc->extradata)
3158 return AVERROR(ENOMEM);
3159
3160 598 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (!sc->extradata_size) {
3162 ret = AVERROR(ENOMEM);
3163 goto fail;
3164 }
3165
3166 598 ret = ff_mov_read_stsd_entries(c, pb, entries);
3167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (ret < 0)
3168 goto fail;
3169
3170 /* Restore back the primary extradata. */
3171 598 av_freep(&st->codecpar->extradata);
3172 598 st->codecpar->extradata_size = sc->extradata_size[0];
3173
2/2
✓ Branch 0 taken 332 times.
✓ Branch 1 taken 266 times.
598 if (sc->extradata_size[0]) {
3174 332 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 332 times.
332 if (!st->codecpar->extradata)
3176 return AVERROR(ENOMEM);
3177 332 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3178 }
3179
3180 598 return mov_finalize_stsd_codec(c, pb, st, sc);
3181 fail:
3182 if (sc->extradata) {
3183 int j;
3184 for (j = 0; j < sc->stsd_count; j++)
3185 av_freep(&sc->extradata[j]);
3186 }
3187
3188 av_freep(&sc->extradata);
3189 av_freep(&sc->extradata_size);
3190 return ret;
3191 }
3192
3193 598 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3194 {
3195 AVStream *st;
3196 MOVStreamContext *sc;
3197 unsigned int i, entries;
3198
3199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (c->trak_index < 0) {
3200 av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3201 return 0;
3202 }
3203
3204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (c->fc->nb_streams < 1)
3205 return 0;
3206 598 st = c->fc->streams[c->fc->nb_streams-1];
3207 598 sc = st->priv_data;
3208
3209 598 avio_r8(pb); /* version */
3210 598 avio_rb24(pb); /* flags */
3211
3212 598 entries = avio_rb32(pb);
3213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if ((uint64_t)entries * 12 + 4 > atom.size)
3214 return AVERROR_INVALIDDATA;
3215
3216 598 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3217
3218
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 583 times.
598 if (!entries)
3219 15 return 0;
3220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 583 times.
583 if (sc->stsc_data) {
3221 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3222 return 0;
3223 }
3224 583 av_free(sc->stsc_data);
3225 583 sc->stsc_count = 0;
3226 583 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 583 times.
583 if (!sc->stsc_data)
3228 return AVERROR(ENOMEM);
3229
3230
3/4
✓ Branch 0 taken 3783 times.
✓ Branch 1 taken 583 times.
✓ Branch 2 taken 3783 times.
✗ Branch 3 not taken.
4366 for (i = 0; i < entries && !pb->eof_reached; i++) {
3231 3783 sc->stsc_data[i].first = avio_rb32(pb);
3232 3783 sc->stsc_data[i].count = avio_rb32(pb);
3233 3783 sc->stsc_data[i].id = avio_rb32(pb);
3234 }
3235
3236 583 sc->stsc_count = i;
3237
2/2
✓ Branch 0 taken 3783 times.
✓ Branch 1 taken 583 times.
4366 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3238 3783 int64_t first_min = i + 1;
3239
5/6
✓ Branch 0 taken 3200 times.
✓ Branch 1 taken 583 times.
✓ Branch 2 taken 3200 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3200 times.
✓ Branch 5 taken 583 times.
3783 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
3240
1/2
✓ Branch 0 taken 3200 times.
✗ Branch 1 not taken.
3200 (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) ||
3241
1/2
✓ Branch 0 taken 3783 times.
✗ Branch 1 not taken.
3783 sc->stsc_data[i].first < first_min ||
3242
1/2
✓ Branch 0 taken 3783 times.
✗ Branch 1 not taken.
3783 sc->stsc_data[i].count < 1 ||
3243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3783 times.
3783 sc->stsc_data[i].id < 1) {
3244 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);
3245 if (i+1 >= sc->stsc_count) {
3246 if (sc->stsc_data[i].count == 0 && i > 0) {
3247 sc->stsc_count --;
3248 continue;
3249 }
3250 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3251 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3252 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3253 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3254 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3255 continue;
3256 }
3257 av_assert0(sc->stsc_data[i+1].first >= 2);
3258 // We replace this entry by the next valid
3259 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3260 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3261 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3262 }
3263 }
3264
3265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 583 times.
583 if (pb->eof_reached) {
3266 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3267 return AVERROR_EOF;
3268 }
3269
3270 583 return 0;
3271 }
3272
3273 340696 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3274 {
3275 340696 return index < count - 1;
3276 }
3277
3278 /* Compute the samples value for the stsc entry at the given index. */
3279 55538 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3280 {
3281 int chunk_count;
3282
3283
2/2
✓ Branch 1 taken 55342 times.
✓ Branch 2 taken 196 times.
55538 if (mov_stsc_index_valid(index, sc->stsc_count))
3284 55342 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3285 else {
3286 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3288 196 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3289 }
3290
3291 55538 return sc->stsc_data[index].count * (int64_t)chunk_count;
3292 }
3293
3294 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3295 {
3296 AVStream *st;
3297 MOVStreamContext *sc;
3298 unsigned i, entries;
3299
3300 if (c->trak_index < 0) {
3301 av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3302 return 0;
3303 }
3304
3305 if (c->fc->nb_streams < 1)
3306 return 0;
3307 st = c->fc->streams[c->fc->nb_streams-1];
3308 sc = st->priv_data;
3309
3310 avio_rb32(pb); // version + flags
3311
3312 entries = avio_rb32(pb);
3313 if (sc->stps_data)
3314 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3315 av_free(sc->stps_data);
3316 sc->stps_count = 0;
3317 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3318 if (!sc->stps_data)
3319 return AVERROR(ENOMEM);
3320
3321 for (i = 0; i < entries && !pb->eof_reached; i++) {
3322 sc->stps_data[i] = avio_rb32(pb);
3323 }
3324
3325 sc->stps_count = i;
3326
3327 if (pb->eof_reached) {
3328 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3329 return AVERROR_EOF;
3330 }
3331
3332 return 0;
3333 }
3334
3335 144 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3336 {
3337 AVStream *st;
3338 FFStream *sti;
3339 MOVStreamContext *sc;
3340 unsigned int i, entries;
3341
3342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (c->trak_index < 0) {
3343 av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3344 return 0;
3345 }
3346
3347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (c->fc->nb_streams < 1)
3348 return 0;
3349 144 st = c->fc->streams[c->fc->nb_streams-1];
3350 144 sti = ffstream(st);
3351 144 sc = st->priv_data;
3352
3353 144 avio_r8(pb); /* version */
3354 144 avio_rb24(pb); /* flags */
3355
3356 144 entries = avio_rb32(pb);
3357
3358 144 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3359
3360
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 138 times.
144 if (!entries) {
3361 6 sc->keyframe_absent = 1;
3362
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
6 if (!sti->need_parsing && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
3363 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3364 6 return 0;
3365 }
3366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (sc->keyframes)
3367 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (entries >= UINT_MAX / sizeof(int))
3369 return AVERROR_INVALIDDATA;
3370 138 av_freep(&sc->keyframes);
3371 138 sc->keyframe_count = 0;
3372 138 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3373
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (!sc->keyframes)
3374 return AVERROR(ENOMEM);
3375
3376
3/4
✓ Branch 0 taken 5706 times.
✓ Branch 1 taken 138 times.
✓ Branch 2 taken 5706 times.
✗ Branch 3 not taken.
5844 for (i = 0; i < entries && !pb->eof_reached; i++) {
3377 5706 sc->keyframes[i] = avio_rb32(pb);
3378 }
3379
3380 138 sc->keyframe_count = i;
3381
3382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (pb->eof_reached) {
3383 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3384 return AVERROR_EOF;
3385 }
3386
3387 138 return 0;
3388 }
3389
3390 598 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3391 {
3392 AVStream *st;
3393 MOVStreamContext *sc;
3394 unsigned int i, entries, sample_size, field_size, num_bytes;
3395 GetBitContext gb;
3396 unsigned char* buf;
3397 int ret;
3398
3399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (c->trak_index < 0) {
3400 av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3401 return 0;
3402 }
3403
3404
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (c->fc->nb_streams < 1)
3405 return 0;
3406 598 st = c->fc->streams[c->fc->nb_streams-1];
3407 598 sc = st->priv_data;
3408
3409 598 avio_r8(pb); /* version */
3410 598 avio_rb24(pb); /* flags */
3411
3412
1/2
✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
598 if (atom.type == MKTAG('s','t','s','z')) {
3413 598 sample_size = avio_rb32(pb);
3414
2/2
✓ Branch 0 taken 557 times.
✓ Branch 1 taken 41 times.
598 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3415 557 sc->sample_size = sample_size;
3416 598 sc->stsz_sample_size = sample_size;
3417 598 field_size = 32;
3418 } else {
3419 sample_size = 0;
3420 avio_rb24(pb); /* reserved */
3421 field_size = avio_r8(pb);
3422 }
3423 598 entries = avio_rb32(pb);
3424
3425 598 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3426
3427 598 sc->sample_count = entries;
3428
2/2
✓ Branch 0 taken 201 times.
✓ Branch 1 taken 397 times.
598 if (sample_size)
3429 201 return 0;
3430
3431
4/8
✓ Branch 0 taken 397 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 397 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 397 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 397 times.
397 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
3432 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3433 return AVERROR_INVALIDDATA;
3434 }
3435
3436
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 381 times.
397 if (!entries)
3437 16 return 0;
3438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 381 times.
381 if (entries >= (INT_MAX - 4 - 8 * AV_INPUT_BUFFER_PADDING_SIZE) / field_size)
3439 return AVERROR_INVALIDDATA;
3440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 381 times.
381 if (sc->sample_sizes)
3441 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3442 381 av_free(sc->sample_sizes);
3443 381 sc->sample_count = 0;
3444 381 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 381 times.
381 if (!sc->sample_sizes)
3446 return AVERROR(ENOMEM);
3447
3448 381 num_bytes = (entries*field_size+4)>>3;
3449
3450 381 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 381 times.
381 if (!buf) {
3452 av_freep(&sc->sample_sizes);
3453 return AVERROR(ENOMEM);
3454 }
3455
3456 381 ret = ffio_read_size(pb, buf, num_bytes);
3457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 381 times.
381 if (ret < 0) {
3458 av_freep(&sc->sample_sizes);
3459 av_free(buf);
3460 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3461 return 0;
3462 }
3463
3464 381 init_get_bits(&gb, buf, 8*num_bytes);
3465
3466
2/2
✓ Branch 0 taken 226886 times.
✓ Branch 1 taken 381 times.
227267 for (i = 0; i < entries; i++) {
3467 226886 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 226886 times.
226886 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3469 av_free(buf);
3470 av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3471 return AVERROR_INVALIDDATA;
3472 }
3473 226886 sc->data_size += sc->sample_sizes[i];
3474 }
3475
3476 381 sc->sample_count = i;
3477
3478 381 av_free(buf);
3479
3480 381 return 0;
3481 }
3482
3483 598 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3484 {
3485 AVStream *st;
3486 MOVStreamContext *sc;
3487 unsigned int i, entries;
3488 598 int64_t duration = 0;
3489 598 int64_t total_sample_count = 0;
3490 598 int64_t current_dts = 0;
3491 598 int64_t corrected_dts = 0;
3492
3493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (c->trak_index < 0) {
3494 av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3495 return 0;
3496 }
3497
3498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (c->fc->nb_streams < 1)
3499 return 0;
3500 598 st = c->fc->streams[c->fc->nb_streams-1];
3501 598 sc = st->priv_data;
3502
3503 598 avio_r8(pb); /* version */
3504 598 avio_rb24(pb); /* flags */
3505 598 entries = avio_rb32(pb);
3506
3507 598 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3508 598 c->fc->nb_streams-1, entries);
3509
3510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (sc->stts_data)
3511 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3512 598 av_freep(&sc->stts_data);
3513 598 sc->stts_count = 0;
3514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3515 return AVERROR(ENOMEM);
3516
3517
3/4
✓ Branch 0 taken 2945 times.
✓ Branch 1 taken 598 times.
✓ Branch 2 taken 2945 times.
✗ Branch 3 not taken.
3543 for (i = 0; i < entries && !pb->eof_reached; i++) {
3518 unsigned int sample_duration;
3519 unsigned int sample_count;
3520 2945 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3521 2945 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3522 min_entries * sizeof(*sc->stts_data));
3523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2945 times.
2945 if (!stts_data) {
3524 av_freep(&sc->stts_data);
3525 sc->stts_count = 0;
3526 return AVERROR(ENOMEM);
3527 }
3528 2945 sc->stts_count = min_entries;
3529 2945 sc->stts_data = stts_data;
3530
3531 2945 sample_count = avio_rb32(pb);
3532 2945 sample_duration = avio_rb32(pb);
3533
3534 2945 sc->stts_data[i].count= sample_count;
3535 2945 sc->stts_data[i].duration= sample_duration;
3536
3537 2945 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3538 sample_count, sample_duration);
3539
3540 /* STTS sample offsets are uint32 but some files store it as int32
3541 * with negative values used to correct DTS delays.
3542 There may be abnormally large values as well. */
3543
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2944 times.
2945 if (sample_duration > c->max_stts_delta) {
3544 // assume high delta is a correction if negative when cast as int32
3545 1 int32_t delta_magnitude = (int32_t)sample_duration;
3546 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",
3547 sample_duration, i, sample_count, st->index);
3548 1 sc->stts_data[i].duration = 1;
3549
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);
3550 } else {
3551 2944 corrected_dts += sample_duration * (uint64_t)sample_count;
3552 }
3553
3554 2945 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3555
3556
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2923 times.
2945 if (current_dts > corrected_dts) {
3557 22 int64_t drift = av_sat_sub64(current_dts, corrected_dts) / FFMAX(sample_count, 1);
3558
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;
3559 22 current_dts -= correction * (uint64_t)sample_count;
3560 22 sc->stts_data[i].duration -= correction;
3561 }
3562
3563 2945 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3564 2945 total_sample_count+=sc->stts_data[i].count;
3565 }
3566
3567 598 sc->stts_count = i;
3568
3569
2/2
✓ Branch 0 taken 582 times.
✓ Branch 1 taken 16 times.
598 if (duration > 0 &&
3570
1/2
✓ Branch 0 taken 582 times.
✗ Branch 1 not taken.
582 duration <= INT64_MAX - sc->duration_for_fps &&
3571
1/2
✓ Branch 0 taken 582 times.
✗ Branch 1 not taken.
582 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3572 582 sc->duration_for_fps += duration;
3573 582 sc->nb_frames_for_fps += total_sample_count;
3574 }
3575
3576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (pb->eof_reached) {
3577 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3578 return AVERROR_EOF;
3579 }
3580
3581 598 st->nb_frames= total_sample_count;
3582
2/2
✓ Branch 0 taken 582 times.
✓ Branch 1 taken 16 times.
598 if (duration)
3583 582 st->duration= FFMIN(st->duration, duration);
3584
3585 // All samples have zero duration. They have higher chance be chose by
3586 // mov_find_next_sample, which leads to seek again and again.
3587 //
3588 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3589 // So only mark data stream as discarded for safety.
3590
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 582 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
598 if (!duration && sc->stts_count &&
3591 st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3592 av_log(c->fc, AV_LOG_WARNING,
3593 "All samples in data stream index:id [%d:%d] have zero "
3594 "duration, stream set to be discarded by default. Override "
3595 "using AVStream->discard or -discard for ffmpeg command.\n",
3596 st->index, sc->id);
3597 st->discard = AVDISCARD_ALL;
3598 }
3599 598 sc->track_end = duration;
3600 598 return 0;
3601 }
3602
3603 44 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3604 {
3605 AVStream *st;
3606 MOVStreamContext *sc;
3607 int64_t i, entries;
3608
3609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (c->fc->nb_streams < 1)
3610 return 0;
3611 44 st = c->fc->streams[c->fc->nb_streams - 1];
3612 44 sc = st->priv_data;
3613
3614 44 avio_r8(pb); /* version */
3615 44 avio_rb24(pb); /* flags */
3616 44 entries = atom.size - 4;
3617
3618 44 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3619 44 c->fc->nb_streams - 1, entries);
3620
3621
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 36 times.
44 if (sc->sdtp_data)
3622 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3623 44 av_freep(&sc->sdtp_data);
3624 44 sc->sdtp_count = 0;
3625
3626 44 sc->sdtp_data = av_malloc(entries);
3627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (!sc->sdtp_data)
3628 return AVERROR(ENOMEM);
3629
3630
3/4
✓ Branch 0 taken 3807 times.
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 3807 times.
✗ Branch 3 not taken.
3851 for (i = 0; i < entries && !pb->eof_reached; i++)
3631 3807 sc->sdtp_data[i] = avio_r8(pb);
3632 44 sc->sdtp_count = i;
3633
3634 44 return 0;
3635 }
3636
3637 10827 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3638 {
3639
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 9691 times.
10827 if (duration < 0) {
3640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3641 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3642 duration++;
3643 }
3644 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3645 }
3646 10827 }
3647
3648 63 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3649 {
3650 AVStream *st;
3651 MOVStreamContext *sc;
3652 63 unsigned int i, entries, ctts_count = 0;
3653
3654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->trak_index < 0) {
3655 av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
3656 return 0;
3657 }
3658
3659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->fc->nb_streams < 1)
3660 return 0;
3661 63 st = c->fc->streams[c->fc->nb_streams-1];
3662 63 sc = st->priv_data;
3663
3664 63 avio_r8(pb); /* version */
3665 63 avio_rb24(pb); /* flags */
3666 63 entries = avio_rb32(pb);
3667
3668 63 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3669
3670
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 59 times.
63 if (!entries)
3671 4 return 0;
3672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
3673 return AVERROR_INVALIDDATA;
3674 59 av_freep(&sc->ctts_data);
3675 59 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
3676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->ctts_data)
3677 return AVERROR(ENOMEM);
3678
3679
3/4
✓ Branch 0 taken 4874 times.
✓ Branch 1 taken 59 times.
✓ Branch 2 taken 4874 times.
✗ Branch 3 not taken.
4933 for (i = 0; i < entries && !pb->eof_reached; i++) {
3680 MOVCtts *ctts_data;
3681 4874 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
3682 4874 const size_t requested_size =
3683 4874 min_size_needed > sc->ctts_allocated_size ?
3684
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
3685 min_size_needed;
3686 4874 int count = avio_rb32(pb);
3687 4874 int duration = avio_rb32(pb);
3688
3689
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (count <= 0) {
3690 av_log(c->fc, AV_LOG_TRACE,
3691 "ignoring CTTS entry with count=%d duration=%d\n",
3692 count, duration);
3693 continue;
3694 }
3695
3696
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
3697 return AVERROR(ENOMEM);
3698
3699 4874 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
3700
3701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (!ctts_data)
3702 return AVERROR(ENOMEM);
3703
3704 4874 sc->ctts_data = ctts_data;
3705
3706 4874 ctts_data[ctts_count].count = count;
3707 4874 ctts_data[ctts_count].offset = duration;
3708 4874 ctts_count++;
3709
3710 4874 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
3711 count, duration);
3712
3713
2/2
✓ Branch 0 taken 4761 times.
✓ Branch 1 taken 113 times.
4874 if (i+2<entries)
3714 4761 mov_update_dts_shift(sc, duration, c->fc);
3715 }
3716
3717 59 sc->ctts_count = ctts_count;
3718
3719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (pb->eof_reached) {
3720 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
3721 return AVERROR_EOF;
3722 }
3723
3724 59 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
3725
3726 59 return 0;
3727 }
3728
3729 28 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3730 {
3731 AVStream *st;
3732 MOVStreamContext *sc;
3733 uint8_t version;
3734 uint32_t grouping_type;
3735 uint32_t default_length;
3736 av_unused uint32_t default_group_description_index;
3737 uint32_t entry_count;
3738
3739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (c->fc->nb_streams < 1)
3740 return 0;
3741 28 st = c->fc->streams[c->fc->nb_streams - 1];
3742 28 sc = st->priv_data;
3743
3744 28 version = avio_r8(pb); /* version */
3745 28 avio_rb24(pb); /* flags */
3746 28 grouping_type = avio_rl32(pb);
3747
3748 /*
3749 * This function only supports "sync" boxes, but the code is able to parse
3750 * other boxes (such as "tscl", "tsas" and "stsa")
3751 */
3752
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 5 times.
28 if (grouping_type != MKTAG('s','y','n','c'))
3753 23 return 0;
3754
3755
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
3756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
3757 5 entry_count = avio_rb32(pb);
3758
3759 5 av_freep(&sc->sgpd_sync);
3760 5 sc->sgpd_sync_count = entry_count;
3761 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
3762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
3763 return AVERROR(ENOMEM);
3764
3765
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++) {
3766 8 uint32_t description_length = default_length;
3767
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)
3768 description_length = avio_rb32(pb);
3769
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
3770 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
3771 8 sc->sgpd_sync[i] = nal_unit_type;
3772 8 description_length -= 1;
3773 }
3774 8 avio_skip(pb, description_length);
3775 }
3776
3777
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
3778 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
3779 return AVERROR_EOF;
3780 }
3781
3782 5 return 0;
3783 }
3784
3785 25 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3786 {
3787 AVStream *st;
3788 MOVStreamContext *sc;
3789 unsigned int i, entries;
3790 uint8_t version;
3791 uint32_t grouping_type;
3792 MOVSbgp *table, **tablep;
3793 int *table_count;
3794
3795
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (c->fc->nb_streams < 1)
3796 return 0;
3797 25 st = c->fc->streams[c->fc->nb_streams-1];
3798 25 sc = st->priv_data;
3799
3800 25 version = avio_r8(pb); /* version */
3801 25 avio_rb24(pb); /* flags */
3802 25 grouping_type = avio_rl32(pb);
3803
3804
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 24 times.
25 if (grouping_type == MKTAG('r','a','p',' ')) {
3805 1 tablep = &sc->rap_group;
3806 1 table_count = &sc->rap_group_count;
3807
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19 times.
24 } else if (grouping_type == MKTAG('s','y','n','c')) {
3808 5 tablep = &sc->sync_group;
3809 5 table_count = &sc->sync_group_count;
3810 } else {
3811 19 return 0;
3812 }
3813
3814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
3815 avio_rb32(pb); /* grouping_type_parameter */
3816
3817 6 entries = avio_rb32(pb);
3818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
3819 return 0;
3820
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
3821 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
3822 6 av_freep(tablep);
3823 6 table = av_malloc_array(entries, sizeof(*table));
3824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
3825 return AVERROR(ENOMEM);
3826 6 *tablep = table;
3827
3828
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++) {
3829 32 table[i].count = avio_rb32(pb); /* sample_count */
3830 32 table[i].index = avio_rb32(pb); /* group_description_index */
3831 }
3832
3833 6 *table_count = i;
3834
3835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
3836 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
3837 return AVERROR_EOF;
3838 }
3839
3840 6 return 0;
3841 }
3842
3843 /**
3844 * Get ith edit list entry (media time, duration).
3845 */
3846 909 static int get_edit_list_entry(MOVContext *mov,
3847 const MOVStreamContext *msc,
3848 unsigned int edit_list_index,
3849 int64_t *edit_list_media_time,
3850 int64_t *edit_list_duration,
3851 int64_t global_timescale)
3852 {
3853
2/2
✓ Branch 0 taken 441 times.
✓ Branch 1 taken 468 times.
909 if (edit_list_index == msc->elst_count) {
3854 441 return 0;
3855 }
3856 468 *edit_list_media_time = msc->elst_data[edit_list_index].time;
3857 468 *edit_list_duration = msc->elst_data[edit_list_index].duration;
3858
3859 /* duration is in global timescale units;convert to msc timescale */
3860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
468 if (global_timescale == 0) {
3861 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
3862 return 0;
3863 }
3864 468 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
3865 global_timescale);
3866
3867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
468 if (*edit_list_duration + (uint64_t)*edit_list_media_time > INT64_MAX)
3868 *edit_list_duration = 0;
3869
3870 468 return 1;
3871 }
3872
3873 /**
3874 * Find the closest previous frame to the timestamp_pts, in e_old index
3875 * entries. Searching for just any frame / just key frames can be controlled by
3876 * last argument 'flag'.
3877 * Note that if ctts_data is not NULL, we will always search for a key frame
3878 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
3879 * return the first frame of the video.
3880 *
3881 * Here the timestamp_pts is considered to be a presentation timestamp and
3882 * the timestamp of index entries are considered to be decoding timestamps.
3883 *
3884 * Returns 0 if successful in finding a frame, else returns -1.
3885 * Places the found index corresponding output arg.
3886 *
3887 * If ctts_old is not NULL, then refines the searched entry by searching
3888 * backwards from the found timestamp, to find the frame with correct PTS.
3889 *
3890 * Places the found ctts_index and ctts_sample in corresponding output args.
3891 */
3892 467 static int find_prev_closest_index(AVStream *st,
3893 AVIndexEntry *e_old,
3894 int nb_old,
3895 MOVTimeToSample *tts_data,
3896 int64_t tts_count,
3897 int64_t timestamp_pts,
3898 int flag,
3899 int64_t* index,
3900 int64_t* tts_index,
3901 int64_t* tts_sample)
3902 {
3903 467 MOVStreamContext *msc = st->priv_data;
3904 467 FFStream *const sti = ffstream(st);
3905 467 AVIndexEntry *e_keep = sti->index_entries;
3906 467 int nb_keep = sti->nb_index_entries;
3907 467 int64_t i = 0;
3908
3909
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 467 times.
467 av_assert0(index);
3910
3911 // If dts_shift > 0, then all the index timestamps will have to be offset by
3912 // at least dts_shift amount to obtain PTS.
3913 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
3914
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 458 times.
467 if (msc->dts_shift > 0) {
3915 9 timestamp_pts -= msc->dts_shift;
3916 }
3917
3918 467 sti->index_entries = e_old;
3919 467 sti->nb_index_entries = nb_old;
3920 467 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
3921
3922 // Keep going backwards in the index entries until the timestamp is the same.
3923
2/2
✓ Branch 0 taken 466 times.
✓ Branch 1 taken 1 times.
467 if (*index >= 0) {
3924
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 442 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
466 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
3925 i--) {
3926 if ((flag & AVSEEK_FLAG_ANY) ||
3927 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
3928 *index = i - 1;
3929 }
3930 }
3931 }
3932
3933 // If we have CTTS then refine the search, by searching backwards over PTS
3934 // computed by adding corresponding CTTS durations to index timestamps.
3935
4/4
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 403 times.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 1 times.
467 if (msc->ctts_count && *index >= 0) {
3936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(tts_index);
3937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(tts_sample);
3938 // Find out the ctts_index for the found frame.
3939 63 *tts_index = 0;
3940 63 *tts_sample = 0;
3941
2/2
✓ Branch 0 taken 175 times.
✓ Branch 1 taken 63 times.
238 for (int64_t index_tts_count = 0; index_tts_count < *index; index_tts_count++) {
3942
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (*tts_index < tts_count) {
3943 175 (*tts_sample)++;
3944
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (tts_data[*tts_index].count == *tts_sample) {
3945 175 (*tts_index)++;
3946 175 *tts_sample = 0;
3947 }
3948 }
3949 }
3950
3951
4/6
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 70 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 70 times.
✗ Branch 5 not taken.
75 while (*index >= 0 && (*tts_index) >= 0 && (*tts_index) < tts_count) {
3952 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
3953 // No need to add dts_shift to the timestamp here becase timestamp_pts has already been
3954 // compensated by dts_shift above.
3955
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 8 times.
70 if ((e_old[*index].timestamp + tts_data[*tts_index].offset) <= timestamp_pts &&
3956
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 4 times.
62 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
3957 58 break;
3958 }
3959
3960 12 (*index)--;
3961
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (*tts_sample == 0) {
3962 12 (*tts_index)--;
3963
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 if (*tts_index >= 0)
3964 7 *tts_sample = tts_data[*tts_index].count - 1;
3965 } else {
3966 (*tts_sample)--;
3967 }
3968 }
3969 }
3970
3971 /* restore AVStream state*/
3972 467 sti->index_entries = e_keep;
3973 467 sti->nb_index_entries = nb_keep;
3974
2/2
✓ Branch 0 taken 461 times.
✓ Branch 1 taken 6 times.
467 return *index >= 0 ? 0 : -1;
3975 }
3976
3977 /**
3978 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
3979 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
3980 *
3981 * This function is similar to ff_add_index_entry in libavformat/utils.c
3982 * except that here we are always unconditionally adding an index entry to
3983 * the end, instead of searching the entries list and skipping the add if
3984 * there is an existing entry with the same timestamp.
3985 * This is needed because the mov_fix_index calls this func with the same
3986 * unincremented timestamp for successive discarded frames.
3987 */
3988 348553 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
3989 int size, int distance, int flags)
3990 {
3991 348553 FFStream *const sti = ffstream(st);
3992 AVIndexEntry *entries, *ie;
3993 348553 int64_t index = -1;
3994 348553 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
3995
3996 // Double the allocation each time, to lower memory fragmentation.
3997 // Another difference from ff_add_index_entry function.
3998 348553 const size_t requested_size =
3999 348553 min_size_needed > sti->index_entries_allocated_size ?
4000
2/2
✓ Branch 0 taken 1978 times.
✓ Branch 1 taken 346575 times.
348553 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
4001 min_size_needed;
4002
4003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348553 times.
348553 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
4004 return -1;
4005
4006 348553 entries = av_fast_realloc(sti->index_entries,
4007 &sti->index_entries_allocated_size,
4008 requested_size);
4009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348553 times.
348553 if (!entries)
4010 return -1;
4011
4012 348553 sti->index_entries = entries;
4013
4014 348553 index = sti->nb_index_entries++;
4015 348553 ie= &entries[index];
4016
4017 348553 ie->pos = pos;
4018 348553 ie->timestamp = timestamp;
4019 348553 ie->min_distance= distance;
4020 348553 ie->size= size;
4021 348553 ie->flags = flags;
4022 348553 return index;
4023 }
4024
4025 /**
4026 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4027 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4028 */
4029 27 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4030 int64_t* frame_duration_buffer,
4031 int frame_duration_buffer_size) {
4032 27 FFStream *const sti = ffstream(st);
4033 27 int i = 0;
4034
2/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
27 av_assert0(end_index >= 0 && end_index <= sti->nb_index_entries);
4035
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 27 times.
164 for (i = 0; i < frame_duration_buffer_size; i++) {
4036 137 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4037 137 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4038 }
4039 27 }
4040
4041 186054 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4042 int count, int offset, unsigned int duration)
4043 {
4044 MOVTimeToSample *tts_buf_new;
4045 186054 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4046 186054 const size_t requested_size =
4047 186054 min_size_needed > *allocated_size ?
4048
2/2
✓ Branch 0 taken 1345 times.
✓ Branch 1 taken 184709 times.
186054 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4049 min_size_needed;
4050
4051
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186054 times.
186054 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4052 return -1;
4053
4054 186054 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4055
4056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186054 times.
186054 if (!tts_buf_new)
4057 return -1;
4058
4059 186054 *tts_data = tts_buf_new;
4060
4061 186054 tts_buf_new[*tts_count].count = count;
4062 186054 tts_buf_new[*tts_count].offset = offset;
4063 186054 tts_buf_new[*tts_count].duration = duration;
4064
4065 186054 *tts_count = (*tts_count) + 1;
4066 186054 return 0;
4067 }
4068
4069 #define MAX_REORDER_DELAY 16
4070 613 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4071 {
4072 613 MOVStreamContext *msc = st->priv_data;
4073 613 FFStream *const sti = ffstream(st);
4074 613 int ctts_ind = 0;
4075 613 int ctts_sample = 0;
4076 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4077 613 int buf_start = 0;
4078 int j, r, num_swaps;
4079
4080
2/2
✓ Branch 0 taken 10421 times.
✓ Branch 1 taken 613 times.
11034 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4081 10421 pts_buf[j] = INT64_MIN;
4082
4083
3/4
✓ Branch 0 taken 613 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 554 times.
613 if (st->codecpar->video_delay <= 0 && msc->ctts_count &&
4084
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 16 times.
59 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4085 43 st->codecpar->video_delay = 0;
4086
3/4
✓ Branch 0 taken 138279 times.
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 138279 times.
✗ Branch 3 not taken.
138322 for (int ind = 0; ind < sti->nb_index_entries && ctts_ind < msc->tts_count; ++ind) {
4087 // Point j to the last elem of the buffer and insert the current pts there.
4088 138279 j = buf_start;
4089 138279 buf_start = (buf_start + 1);
4090
2/2
✓ Branch 0 taken 8111 times.
✓ Branch 1 taken 130168 times.
138279 if (buf_start == MAX_REORDER_DELAY + 1)
4091 8111 buf_start = 0;
4092
4093 138279 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4094
4095 // The timestamps that are already in the sorted buffer, and are greater than the
4096 // current pts, are exactly the timestamps that need to be buffered to output PTS
4097 // in correct sorted order.
4098 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4099 // can be computed as the maximum no. of swaps any particular timestamp needs to
4100 // go through, to keep this buffer in sorted order.
4101 138279 num_swaps = 0;
4102
2/2
✓ Branch 0 taken 142294 times.
✓ Branch 1 taken 4 times.
142298 while (j != buf_start) {
4103 142294 r = j - 1;
4104
2/2
✓ Branch 0 taken 8389 times.
✓ Branch 1 taken 133905 times.
142294 if (r < 0) r = MAX_REORDER_DELAY;
4105
2/2
✓ Branch 0 taken 4019 times.
✓ Branch 1 taken 138275 times.
142294 if (pts_buf[j] < pts_buf[r]) {
4106 4019 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4107 4019 ++num_swaps;
4108 } else {
4109 138275 break;
4110 }
4111 4019 j = r;
4112 }
4113 138279 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4114
4115 138279 ctts_sample++;
4116
1/2
✓ Branch 0 taken 138279 times.
✗ Branch 1 not taken.
138279 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4117 138279 ctts_ind++;
4118 138279 ctts_sample = 0;
4119 }
4120 }
4121 43 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4122 43 st->codecpar->video_delay, st->index);
4123 }
4124 613 }
4125
4126 103414 static void mov_current_sample_inc(MOVStreamContext *sc)
4127 {
4128 103414 sc->current_sample++;
4129 103414 sc->current_index++;
4130
2/2
✓ Branch 0 taken 61411 times.
✓ Branch 1 taken 42003 times.
103414 if (sc->index_ranges &&
4131
2/2
✓ Branch 0 taken 425 times.
✓ Branch 1 taken 60986 times.
61411 sc->current_index >= sc->current_index_range->end &&
4132
1/2
✓ Branch 0 taken 425 times.
✗ Branch 1 not taken.
425 sc->current_index_range->end) {
4133 425 sc->current_index_range++;
4134 425 sc->current_index = sc->current_index_range->start;
4135 }
4136 103414 }
4137
4138 static void mov_current_sample_dec(MOVStreamContext *sc)
4139 {
4140 sc->current_sample--;
4141 sc->current_index--;
4142 if (sc->index_ranges &&
4143 sc->current_index < sc->current_index_range->start &&
4144 sc->current_index_range > sc->index_ranges) {
4145 sc->current_index_range--;
4146 sc->current_index = sc->current_index_range->end - 1;
4147 }
4148 }
4149
4150 335 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4151 {
4152 int64_t range_size;
4153
4154 335 sc->current_sample = current_sample;
4155 335 sc->current_index = current_sample;
4156
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 309 times.
335 if (!sc->index_ranges) {
4157 26 return;
4158 }
4159
4160 309 for (sc->current_index_range = sc->index_ranges;
4161
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 sc->current_index_range->end;
4162 sc->current_index_range++) {
4163 309 range_size = sc->current_index_range->end - sc->current_index_range->start;
4164
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 if (range_size > current_sample) {
4165 309 sc->current_index = sc->current_index_range->start + current_sample;
4166 309 break;
4167 }
4168 current_sample -= range_size;
4169 }
4170 }
4171
4172 /**
4173 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4174 * which are needed to decode them) that fall in the edit list time ranges.
4175 * Also fixes the timestamps of the index entries to match the timeline
4176 * specified the edit lists.
4177 */
4178 613 static void mov_fix_index(MOVContext *mov, AVStream *st)
4179 {
4180 613 MOVStreamContext *msc = st->priv_data;
4181 613 FFStream *const sti = ffstream(st);
4182 613 AVIndexEntry *e_old = sti->index_entries;
4183 613 int nb_old = sti->nb_index_entries;
4184 613 const AVIndexEntry *e_old_end = e_old + nb_old;
4185 613 const AVIndexEntry *current = NULL;
4186 613 MOVTimeToSample *tts_data_old = msc->tts_data;
4187 613 int64_t tts_index_old = 0;
4188 613 int64_t tts_sample_old = 0;
4189 613 int64_t tts_count_old = msc->tts_count;
4190 613 int64_t edit_list_media_time = 0;
4191 613 int64_t edit_list_duration = 0;
4192 613 int64_t frame_duration = 0;
4193 613 int64_t edit_list_dts_counter = 0;
4194 613 int64_t edit_list_dts_entry_end = 0;
4195 613 int64_t edit_list_start_tts_sample = 0;
4196 int64_t curr_cts;
4197 613 int64_t curr_ctts = 0;
4198 613 int64_t empty_edits_sum_duration = 0;
4199 613 int64_t edit_list_index = 0;
4200 int64_t index;
4201 int flags;
4202 613 int64_t start_dts = 0;
4203 613 int64_t edit_list_start_encountered = 0;
4204 613 int64_t search_timestamp = 0;
4205 613 int64_t* frame_duration_buffer = NULL;
4206 613 int num_discarded_begin = 0;
4207 613 int first_non_zero_audio_edit = -1;
4208 613 int packet_skip_samples = 0;
4209 613 MOVIndexRange *current_index_range = NULL;
4210 613 int found_keyframe_after_edit = 0;
4211 613 int found_non_empty_edit = 0;
4212
4213
4/6
✓ Branch 0 taken 441 times.
✓ Branch 1 taken 172 times.
✓ Branch 2 taken 441 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 441 times.
613 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
4214 172 return;
4215 }
4216
4217 // allocate the index ranges array
4218 441 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4219 sizeof(msc->index_ranges[0]));
4220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 441 times.
441 if (!msc->index_ranges) {
4221 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4222 return;
4223 }
4224 441 msc->current_index_range = msc->index_ranges;
4225
4226 // Clean AVStream from traces of old index
4227 441 sti->index_entries = NULL;
4228 441 sti->index_entries_allocated_size = 0;
4229 441 sti->nb_index_entries = 0;
4230
4231 // Clean time to sample fields of MOVStreamContext
4232 441 msc->tts_data = NULL;
4233 441 msc->tts_count = 0;
4234 441 msc->tts_index = 0;
4235 441 msc->tts_sample = 0;
4236 441 msc->tts_allocated_size = 0;
4237
4238 // Reinitialize min_corrected_pts so that it can be computed again.
4239 441 msc->min_corrected_pts = -1;
4240
4241 // If the dts_shift is positive (in case of negative ctts values in mov),
4242 // then negate the DTS by dts_shift
4243
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 432 times.
441 if (msc->dts_shift > 0) {
4244 9 edit_list_dts_entry_end -= msc->dts_shift;
4245 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4246 }
4247
4248 441 start_dts = edit_list_dts_entry_end;
4249
4250
2/2
✓ Branch 0 taken 468 times.
✓ Branch 1 taken 441 times.
1350 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
4251 909 &edit_list_duration, mov->time_scale)) {
4252 468 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4253 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4254 468 edit_list_index++;
4255 468 edit_list_dts_counter = edit_list_dts_entry_end;
4256 468 edit_list_dts_entry_end += edit_list_duration;
4257 468 num_discarded_begin = 0;
4258
4/4
✓ Branch 0 taken 445 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 441 times.
468 if (!found_non_empty_edit && edit_list_media_time == -1) {
4259 4 empty_edits_sum_duration += edit_list_duration;
4260 4 continue;
4261 }
4262 464 found_non_empty_edit = 1;
4263
4264 // If we encounter a non-negative edit list reset the skip_samples/start_pad fields and set them
4265 // according to the edit list below.
4266
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 337 times.
464 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4267
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit < 0) {
4268 127 first_non_zero_audio_edit = 1;
4269 } else {
4270 first_non_zero_audio_edit = 0;
4271 }
4272
4273
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit > 0)
4274 127 sti->skip_samples = msc->start_pad = 0;
4275 }
4276
4277 // While reordering frame index according to edit list we must handle properly
4278 // the scenario when edit list entry starts from none key frame.
4279 // We find closest previous key frame and preserve it and consequent frames in index.
4280 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4281 464 search_timestamp = edit_list_media_time;
4282
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 337 times.
464 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4283 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4284 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4285 // edit_list_media_time to cover the decoder delay.
4286 127 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
4287 }
4288
4289
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 461 times.
464 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, 0,
4290 &index, &tts_index_old, &tts_sample_old) < 0) {
4291 3 av_log(mov->fc, AV_LOG_WARNING,
4292 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4293 st->index, edit_list_index, search_timestamp);
4294
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, AVSEEK_FLAG_ANY,
4295 &index, &tts_index_old, &tts_sample_old) < 0) {
4296 3 av_log(mov->fc, AV_LOG_WARNING,
4297 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4298 st->index, edit_list_index, search_timestamp);
4299 3 index = 0;
4300 3 tts_index_old = 0;
4301 3 tts_sample_old = 0;
4302 }
4303 }
4304 464 current = e_old + index;
4305 464 edit_list_start_tts_sample = tts_sample_old;
4306
4307 // Iterate over index and arrange it according to edit list
4308 464 edit_list_start_encountered = 0;
4309 464 found_keyframe_after_edit = 0;
4310
2/2
✓ Branch 0 taken 348553 times.
✓ Branch 1 taken 112 times.
348665 for (; current < e_old_end; current++, index++) {
4311 // check if frame outside edit list mark it for discard
4312 697106 frame_duration = (current + 1 < e_old_end) ?
4313
2/2
✓ Branch 0 taken 348116 times.
✓ Branch 1 taken 437 times.
348553 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4314
4315 348553 flags = current->flags;
4316
4317 // frames (pts) before or after edit list
4318 348553 curr_cts = current->timestamp + msc->dts_shift;
4319 348553 curr_ctts = 0;
4320
4321
4/4
✓ Branch 0 taken 186066 times.
✓ Branch 1 taken 162487 times.
✓ Branch 2 taken 186054 times.
✓ Branch 3 taken 12 times.
348553 if (tts_data_old && tts_index_old < tts_count_old) {
4322 186054 curr_ctts = tts_data_old[tts_index_old].offset;
4323 186054 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4324 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4325 186054 curr_cts += curr_ctts;
4326 186054 tts_sample_old++;
4327
1/2
✓ Branch 0 taken 186054 times.
✗ Branch 1 not taken.
186054 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4328
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186054 times.
186054 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4329 &msc->tts_allocated_size,
4330 186054 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4331 186054 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4332 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4333 tts_index_old,
4334 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4335 tts_data_old[tts_index_old].offset);
4336 break;
4337 }
4338 186054 tts_index_old++;
4339 186054 tts_sample_old = 0;
4340 186054 edit_list_start_tts_sample = 0;
4341 }
4342 }
4343
4344
4/4
✓ Branch 0 taken 348401 times.
✓ Branch 1 taken 152 times.
✓ Branch 2 taken 130 times.
✓ Branch 3 taken 348271 times.
348553 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
4345
4/4
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 205 times.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 46 times.
282 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
4346
4/6
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
31 curr_cts < edit_list_media_time && curr_cts + frame_duration > edit_list_media_time &&
4347 first_non_zero_audio_edit > 0) {
4348 11 packet_skip_samples = edit_list_media_time - curr_cts;
4349 11 sti->skip_samples += packet_skip_samples;
4350
4351 // Shift the index entry timestamp by packet_skip_samples to be correct.
4352 11 edit_list_dts_counter -= packet_skip_samples;
4353
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (edit_list_start_encountered == 0) {
4354 11 edit_list_start_encountered = 1;
4355 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4356 // discarded packets.
4357
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 if (frame_duration_buffer) {
4358 6 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4359 frame_duration_buffer, num_discarded_begin);
4360 6 av_freep(&frame_duration_buffer);
4361 }
4362 }
4363
4364 11 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4365 } else {
4366 271 flags |= AVINDEX_DISCARD_FRAME;
4367 271 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4368
4369
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 132 times.
271 if (edit_list_start_encountered == 0) {
4370 139 num_discarded_begin++;
4371 139 frame_duration_buffer = av_realloc(frame_duration_buffer,
4372 num_discarded_begin * sizeof(int64_t));
4373
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if (!frame_duration_buffer) {
4374 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4375 break;
4376 }
4377 139 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4378
4379 // Increment skip_samples for the first non-zero audio edit list
4380
3/4
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 73 times.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
139 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4381
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 46 times.
66 first_non_zero_audio_edit > 0 && st->codecpar->codec_id != AV_CODEC_ID_VORBIS) {
4382 20 sti->skip_samples += frame_duration;
4383 }
4384 }
4385 }
4386 } else {
4387
2/2
✓ Branch 0 taken 440 times.
✓ Branch 1 taken 347831 times.
348271 if (msc->min_corrected_pts < 0) {
4388 440 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4389 } else {
4390 347831 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4391 }
4392
2/2
✓ Branch 0 taken 451 times.
✓ Branch 1 taken 347820 times.
348271 if (edit_list_start_encountered == 0) {
4393 451 edit_list_start_encountered = 1;
4394 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4395 // discarded packets.
4396
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 430 times.
451 if (frame_duration_buffer) {
4397 21 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4398 frame_duration_buffer, num_discarded_begin);
4399 21 av_freep(&frame_duration_buffer);
4400 }
4401 }
4402 }
4403
4404
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348553 times.
348553 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
4405 348553 current->min_distance, flags) == -1) {
4406 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4407 break;
4408 }
4409
4410 // Update the index ranges array
4411
4/4
✓ Branch 0 taken 348112 times.
✓ Branch 1 taken 441 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 348091 times.
348553 if (!current_index_range || index != current_index_range->end) {
4412 462 current_index_range = current_index_range ? current_index_range + 1
4413
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 441 times.
462 : msc->index_ranges;
4414 462 current_index_range->start = index;
4415 }
4416 348553 current_index_range->end = index + 1;
4417
4418 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4419
2/2
✓ Branch 0 taken 348414 times.
✓ Branch 1 taken 139 times.
348553 if (edit_list_start_encountered > 0) {
4420 348414 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4421 }
4422
4423 // Break when found first key frame after edit entry completion
4424
2/2
✓ Branch 0 taken 620 times.
✓ Branch 1 taken 347933 times.
348553 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
4425
3/4
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 364 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 256 times.
620 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
4426
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 343 times.
364 if (msc->ctts_count) {
4427 // If we have CTTS and this is the first keyframe after edit elist,
4428 // wait for one more, because there might be trailing B-frames after this I-frame
4429 // that do belong to the edit.
4430
3/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 9 times.
21 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO && found_keyframe_after_edit == 0) {
4431 12 found_keyframe_after_edit = 1;
4432 12 continue;
4433 }
4434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (tts_sample_old != 0) {
4435 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4436 &msc->tts_allocated_size,
4437 tts_sample_old - edit_list_start_tts_sample,
4438 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4439 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4440 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4441 tts_data_old[tts_index_old].offset);
4442 break;
4443 }
4444 }
4445 }
4446 352 break;
4447 }
4448 }
4449 }
4450 // If there are empty edits, then msc->min_corrected_pts might be positive
4451 // intentionally. So we subtract the sum duration of emtpy edits here.
4452 441 msc->min_corrected_pts -= empty_edits_sum_duration;
4453
4454 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4455 // dts by that amount to make the first pts zero.
4456
2/2
✓ Branch 0 taken 272 times.
✓ Branch 1 taken 169 times.
441 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4457
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 231 times.
272 if (msc->min_corrected_pts > 0) {
4458 41 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4459
2/2
✓ Branch 0 taken 2829 times.
✓ Branch 1 taken 41 times.
2870 for (int i = 0; i < sti->nb_index_entries; ++i)
4460 2829 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4461 }
4462 }
4463 // Start time should be equal to zero or the duration of any empty edits.
4464 441 st->start_time = empty_edits_sum_duration;
4465
4466 // Update av stream length, if it ends up shorter than the track's media duration
4467 441 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4468 441 msc->start_pad = sti->skip_samples;
4469
4470 // Free the old index and the old CTTS structures
4471 441 av_free(e_old);
4472 441 av_free(tts_data_old);
4473 441 av_freep(&frame_duration_buffer);
4474
4475 // Null terminate the index ranges array
4476 441 current_index_range = current_index_range ? current_index_range + 1
4477
1/2
✓ Branch 0 taken 441 times.
✗ Branch 1 not taken.
441 : msc->index_ranges;
4478 441 current_index_range->start = 0;
4479 441 current_index_range->end = 0;
4480 441 msc->current_index = msc->index_ranges[0].start;
4481 }
4482
4483 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4484 {
4485
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4486
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == nal_unit_type)
4487 5 return i + 1;
4488 return 0;
4489 }
4490
4491 629 static int build_open_gop_key_points(AVStream *st)
4492 {
4493 int k;
4494 629 int sample_id = 0;
4495 uint32_t cra_index;
4496 629 MOVStreamContext *sc = st->priv_data;
4497
4498
4/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 588 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 5 times.
629 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count)
4499 624 return 0;
4500
4501 /* Build an unrolled index of the samples */
4502 5 sc->sample_offsets_count = 0;
4503
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4505 return AVERROR(ENOMEM);
4506 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4507 }
4508 5 av_freep(&sc->sample_offsets);
4509 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4511 return AVERROR(ENOMEM);
4512 5 k = 0;
4513
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4514
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4515 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4516
4517 /* The following HEVC NAL type reveal the use of open GOP sync points
4518 * (TODO: BLA types may also be concerned) */
4519 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4521 return 0;
4522
4523 /* Build a list of open-GOP key samples */
4524 5 sc->open_key_samples_count = 0;
4525
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4526
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4527
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)
4528 return AVERROR(ENOMEM);
4529 11 sc->open_key_samples_count += sc->sync_group[i].count;
4530 }
4531 5 av_freep(&sc->open_key_samples);
4532 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4534 return AVERROR(ENOMEM);
4535 5 k = 0;
4536
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4537 28 const MOVSbgp *sg = &sc->sync_group[i];
4538
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4539
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4540 11 sc->open_key_samples[k++] = sample_id;
4541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4542 return AVERROR_PATCHWELCOME;
4543 28 sample_id += sg->count;
4544 }
4545
4546 /* Identify the minimal time step between samples */
4547 5 sc->min_sample_duration = UINT_MAX;
4548
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4549 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4550
4551 5 return 0;
4552 }
4553
4554 #define MOV_MERGE_CTTS 1
4555 #define MOV_MERGE_STTS 2
4556 /*
4557 * Merge stts and ctts arrays into a new combined array.
4558 * stts_count and ctts_count may be left untouched as they will be
4559 * used to check for the presence of either of them.
4560 */
4561 613 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4562 {
4563 613 MOVStreamContext *sc = st->priv_data;
4564
3/4
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 554 times.
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
613 int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS);
4565
3/4
✓ Branch 0 taken 613 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 547 times.
✓ Branch 3 taken 66 times.
613 int stts = sc->stts_data && (flags & MOV_MERGE_STTS);
4566 613 int idx = 0;
4567
4568
3/4
✓ Branch 0 taken 554 times.
✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 554 times.
613 if (!sc->ctts_data && !sc->stts_data)
4569 return 0;
4570 // Expand time to sample entries such that we have a 1-1 mapping with samples
4571
2/4
✓ Branch 0 taken 613 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 613 times.
613 if (!sc->sample_count || sc->sample_count >= UINT_MAX / sizeof(*sc->tts_data))
4572 return -1;
4573
4574
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 554 times.
613 if (ctts) {
4575 118 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4576 59 sc->sample_count * sizeof(*sc->tts_data));
4577
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->tts_data)
4578 return -1;
4579
4580 59 memset(sc->tts_data, 0, sc->tts_allocated_size);
4581
4582
2/2
✓ Branch 0 taken 4874 times.
✓ Branch 1 taken 59 times.
4933 for (int i = 0; i < sc->ctts_count &&
4583
1/2
✓ Branch 0 taken 4874 times.
✗ Branch 1 not taken.
9748 idx < sc->sample_count; i++)
4584
2/2
✓ Branch 0 taken 139017 times.
✓ Branch 1 taken 4874 times.
143891 for (int j = 0; j < sc->ctts_data[i].count &&
4585
1/2
✓ Branch 0 taken 139017 times.
✗ Branch 1 not taken.
139017 idx < sc->sample_count; j++) {
4586 139017 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4587 139017 sc->tts_data[idx++].count = 1;
4588 }
4589
4590 59 sc->tts_count = idx;
4591 } else
4592 554 sc->ctts_count = 0;
4593 613 av_freep(&sc->ctts_data);
4594 613 sc->ctts_allocated_size = 0;
4595
4596 613 idx = 0;
4597
2/2
✓ Branch 0 taken 547 times.
✓ Branch 1 taken 66 times.
613 if (stts) {
4598 547 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4599 547 sc->sample_count * sizeof(*sc->tts_data));
4600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 547 times.
547 if (!tts_data)
4601 return -1;
4602
4603
2/2
✓ Branch 0 taken 488 times.
✓ Branch 1 taken 59 times.
547 if (!sc->tts_data)
4604 488 memset(tts_data, 0, sc->tts_allocated_size);
4605 547 sc->tts_data = tts_data;
4606
4607
2/2
✓ Branch 0 taken 2910 times.
✓ Branch 1 taken 547 times.
3457 for (int i = 0; i < sc->stts_count &&
4608
1/2
✓ Branch 0 taken 2910 times.
✗ Branch 1 not taken.
5820 idx < sc->sample_count; i++)
4609
2/2
✓ Branch 0 taken 235906 times.
✓ Branch 1 taken 2910 times.
238816 for (int j = 0; j < sc->stts_data[i].count &&
4610
1/2
✓ Branch 0 taken 235906 times.
✗ Branch 1 not taken.
235906 idx < sc->sample_count; j++) {
4611 235906 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4612 235906 sc->tts_data[idx++].count = 1;
4613 }
4614
4615 547 sc->tts_count = FFMAX(sc->tts_count, idx);
4616 } else
4617 66 sc->stts_count = 0;
4618 613 av_freep(&sc->stts_data);
4619 613 sc->stts_allocated_size = 0;
4620
4621 613 return 0;
4622 }
4623
4624 629 static void mov_build_index(MOVContext *mov, AVStream *st)
4625 {
4626 629 MOVStreamContext *sc = st->priv_data;
4627 629 FFStream *const sti = ffstream(st);
4628 int64_t current_offset;
4629 629 int64_t current_dts = 0;
4630 629 unsigned int stts_index = 0;
4631 629 unsigned int stsc_index = 0;
4632 629 unsigned int stss_index = 0;
4633 629 unsigned int stps_index = 0;
4634 unsigned int i, j;
4635 629 uint64_t stream_size = 0;
4636
4637 629 int ret = build_open_gop_key_points(st);
4638
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 629 times.
629 if (ret < 0)
4639 return;
4640
4641
2/2
✓ Branch 0 taken 443 times.
✓ Branch 1 taken 186 times.
629 if (sc->elst_count) {
4642 443 int i, edit_start_index = 0, multiple_edits = 0;
4643 443 int64_t empty_duration = 0; // empty duration of the first edit list entry
4644 443 int64_t start_time = 0; // start time of the media
4645
4646
2/2
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 443 times.
913 for (i = 0; i < sc->elst_count; i++) {
4647 470 const MOVElst *e = &sc->elst_data[i];
4648
4/4
✓ Branch 0 taken 443 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 439 times.
470 if (i == 0 && e->time == -1) {
4649 /* if empty, the first entry is the start time of the stream
4650 * relative to the presentation itself */
4651 4 empty_duration = e->duration;
4652 4 edit_start_index = 1;
4653
3/4
✓ Branch 0 taken 443 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 443 times.
✗ Branch 3 not taken.
466 } else if (i == edit_start_index && e->time >= 0) {
4654 443 start_time = e->time;
4655 } else {
4656 23 multiple_edits = 1;
4657 }
4658 }
4659
4660
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 437 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
443 if (multiple_edits && !mov->advanced_editlist) {
4661 if (mov->advanced_editlist_autodisabled)
4662 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4663 "not supported in fragmented MP4 files\n");
4664 else
4665 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4666 "Use -advanced_editlist to correctly decode otherwise "
4667 "a/v desync might occur\n");
4668 }
4669
4670 /* adjust first dts according to edit list */
4671
5/6
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 370 times.
✓ Branch 4 taken 73 times.
✗ Branch 5 not taken.
443 if ((empty_duration || start_time) && mov->time_scale > 0) {
4672
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 69 times.
73 if (empty_duration)
4673 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
4674
4675
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
73 if (av_sat_sub64(start_time, empty_duration) != start_time - (uint64_t)empty_duration)
4676 av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
4677
4678 73 sc->time_offset = start_time - (uint64_t)empty_duration;
4679 73 sc->min_corrected_pts = start_time;
4680
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 72 times.
73 if (!mov->advanced_editlist)
4681 1 current_dts = -sc->time_offset;
4682 }
4683
4684
4/4
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 435 times.
443 if (!multiple_edits && !mov->advanced_editlist &&
4685
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 st->codecpar->codec_id == AV_CODEC_ID_AAC && start_time > 0)
4686 sc->start_pad = start_time;
4687 }
4688
4689 /* only use old uncompressed audio chunk demuxing when stts specifies it */
4690
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 388 times.
629 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4691
5/6
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 187 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 121 times.
✓ Branch 5 taken 66 times.
788 sc->stts_count == 1 && sc->stts_data && sc->stts_data[0].duration == 1)) {
4692 563 unsigned int current_sample = 0;
4693 563 unsigned int stts_sample = 0;
4694 unsigned int sample_size;
4695 563 unsigned int distance = 0;
4696 563 unsigned int rap_group_index = 0;
4697 563 unsigned int rap_group_sample = 0;
4698
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 562 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
563 int rap_group_present = sc->rap_group_count && sc->rap_group;
4699
4/8
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 425 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 138 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 425 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
563 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
4700
4701 563 current_dts -= sc->dts_shift;
4702
4703
4/6
✓ Branch 0 taken 547 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 547 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 547 times.
563 if (!sc->sample_count || sti->nb_index_entries || sc->tts_count)
4704 16 return;
4705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 547 times.
547 if (sc->sample_count >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4706 return;
4707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 547 times.
547 if (av_reallocp_array(&sti->index_entries,
4708 547 sti->nb_index_entries + sc->sample_count,
4709 sizeof(*sti->index_entries)) < 0) {
4710 sti->nb_index_entries = 0;
4711 return;
4712 }
4713 547 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
4714
4715 547 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
4716
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 547 times.
547 if (ret < 0)
4717 return;
4718
4719
2/2
✓ Branch 0 taken 173850 times.
✓ Branch 1 taken 547 times.
174397 for (i = 0; i < sc->chunk_count; i++) {
4720
2/2
✓ Branch 0 taken 173303 times.
✓ Branch 1 taken 547 times.
173850 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
4721 173850 current_offset = sc->chunk_offsets[i];
4722
2/2
✓ Branch 1 taken 8859 times.
✓ Branch 2 taken 167534 times.
176393 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4723
2/2
✓ Branch 0 taken 2543 times.
✓ Branch 1 taken 6316 times.
8859 i + 1 == sc->stsc_data[stsc_index + 1].first)
4724 2543 stsc_index++;
4725
4726
4/6
✓ Branch 0 taken 173850 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7349 times.
✓ Branch 3 taken 166501 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7349 times.
173850 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
4727 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
4728 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
4729 sc->stsz_sample_size = sc->sample_size;
4730 }
4731
3/4
✓ Branch 0 taken 7349 times.
✓ Branch 1 taken 166501 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7349 times.
173850 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
4732 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
4733 sc->stsz_sample_size = sc->sample_size;
4734 }
4735
4736
2/2
✓ Branch 0 taken 235906 times.
✓ Branch 1 taken 173850 times.
409756 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
4737 235906 int keyframe = 0;
4738
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235906 times.
235906 if (current_sample >= sc->sample_count) {
4739 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
4740 return;
4741 }
4742
4743
6/6
✓ Branch 0 taken 231150 times.
✓ Branch 1 taken 4756 times.
✓ Branch 2 taken 152644 times.
✓ Branch 3 taken 78506 times.
✓ Branch 4 taken 5706 times.
✓ Branch 5 taken 146938 times.
235906 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
4744 84212 keyframe = 1;
4745
2/2
✓ Branch 0 taken 5568 times.
✓ Branch 1 taken 78644 times.
84212 if (stss_index + 1 < sc->keyframe_count)
4746 5568 stss_index++;
4747
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 151694 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
151694 } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
4748 keyframe = 1;
4749 if (stps_index + 1 < sc->stps_count)
4750 stps_index++;
4751 }
4752
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 235718 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
235906 if (rap_group_present && rap_group_index < sc->rap_group_count) {
4753
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
4754 2 keyframe = 1;
4755
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
4756 4 rap_group_sample = 0;
4757 4 rap_group_index++;
4758 }
4759 }
4760
2/2
✓ Branch 0 taken 4756 times.
✓ Branch 1 taken 231150 times.
235906 if (sc->keyframe_absent
4761
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !sc->stps_count
4762
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !rap_group_present
4763
6/6
✓ Branch 0 taken 874 times.
✓ Branch 1 taken 3882 times.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 824 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 48 times.
4756 && (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || (i==0 && j==0)))
4764 3884 keyframe = 1;
4765
2/2
✓ Branch 0 taken 88096 times.
✓ Branch 1 taken 147810 times.
235906 if (keyframe)
4766 88096 distance = 0;
4767
2/2
✓ Branch 0 taken 8989 times.
✓ Branch 1 taken 226917 times.
235906 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
4768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235906 times.
235906 if (current_offset > INT64_MAX - sample_size) {
4769 av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
4770 current_offset,
4771 sample_size);
4772 return;
4773 }
4774
4775
2/2
✓ Branch 0 taken 235825 times.
✓ Branch 1 taken 81 times.
235906 if (sc->pseudo_stream_id == -1 ||
4776
1/2
✓ Branch 0 taken 235825 times.
✗ Branch 1 not taken.
235825 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
4777 AVIndexEntry *e;
4778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235906 times.
235906 if (sample_size > 0x3FFFFFFF) {
4779 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
4780 return;
4781 }
4782 235906 e = &sti->index_entries[sti->nb_index_entries++];
4783 235906 e->pos = current_offset;
4784 235906 e->timestamp = current_dts;
4785 235906 e->size = sample_size;
4786 235906 e->min_distance = distance;
4787 235906 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
4788 235906 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
4789 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
4790 current_offset, current_dts, sample_size, distance, keyframe);
4791
4/4
✓ Branch 0 taken 155006 times.
✓ Branch 1 taken 80900 times.
✓ Branch 2 taken 10373 times.
✓ Branch 3 taken 144633 times.
235906 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries < 100)
4792 10373 ff_rfps_add_frame(mov->fc, st, current_dts);
4793 }
4794
4795 235906 current_offset += sample_size;
4796 235906 stream_size += sample_size;
4797
4798 235906 current_dts += sc->tts_data[stts_index].duration;
4799
4800 235906 distance++;
4801 235906 stts_sample++;
4802 235906 current_sample++;
4803
3/4
✓ Branch 0 taken 235359 times.
✓ Branch 1 taken 547 times.
✓ Branch 2 taken 235359 times.
✗ Branch 3 not taken.
235906 if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) {
4804 235359 stts_sample = 0;
4805 235359 stts_index++;
4806 }
4807 }
4808 }
4809
2/2
✓ Branch 0 taken 516 times.
✓ Branch 1 taken 31 times.
547 if (st->duration > 0)
4810 516 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
4811 } else {
4812 66 unsigned chunk_samples, total = 0;
4813
4814
2/4
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 66 times.
66 if (!sc->chunk_count || sc->tts_count)
4815 return;
4816
4817 66 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
4818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
4819 return;
4820
4821 // compute total chunk count
4822
2/2
✓ Branch 0 taken 723 times.
✓ Branch 1 taken 66 times.
789 for (i = 0; i < sc->stsc_count; i++) {
4823 unsigned count, chunk_count;
4824
4825 723 chunk_samples = sc->stsc_data[i].count;
4826
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 66 times.
723 if (i != sc->stsc_count - 1 &&
4827
3/4
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 594 times.
657 sc->samples_per_frame && chunk_samples % sc->samples_per_frame) {
4828 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
4829 return;
4830 }
4831
4832
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 648 times.
723 if (sc->samples_per_frame >= 160) { // gsm
4833 75 count = chunk_samples / sc->samples_per_frame;
4834
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 117 times.
648 } else if (sc->samples_per_frame > 1) {
4835 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
4836 531 count = (chunk_samples+samples-1) / samples;
4837 } else {
4838 117 count = (chunk_samples+1023) / 1024;
4839 }
4840
4841
2/2
✓ Branch 1 taken 657 times.
✓ Branch 2 taken 66 times.
723 if (mov_stsc_index_valid(i, sc->stsc_count))
4842 657 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
4843 else
4844 66 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
4845 723 total += chunk_count * count;
4846 }
4847
4848 66 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
4849
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4850 return;
4851
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (av_reallocp_array(&sti->index_entries,
4852 66 sti->nb_index_entries + total,
4853 sizeof(*sti->index_entries)) < 0) {
4854 sti->nb_index_entries = 0;
4855 return;
4856 }
4857 66 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
4858
4859 // populate index
4860
2/2
✓ Branch 0 taken 5428 times.
✓ Branch 1 taken 66 times.
5494 for (i = 0; i < sc->chunk_count; i++) {
4861 5428 current_offset = sc->chunk_offsets[i];
4862
2/2
✓ Branch 1 taken 5287 times.
✓ Branch 2 taken 141 times.
5428 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4863
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 4630 times.
5287 i + 1 == sc->stsc_data[stsc_index + 1].first)
4864 657 stsc_index++;
4865 5428 chunk_samples = sc->stsc_data[stsc_index].count;
4866
4867
2/2
✓ Branch 0 taken 162532 times.
✓ Branch 1 taken 5428 times.
167960 while (chunk_samples > 0) {
4868 AVIndexEntry *e;
4869 unsigned size, samples;
4870
4871
3/4
✓ Branch 0 taken 23921 times.
✓ Branch 1 taken 138611 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 23921 times.
162532 if (sc->samples_per_frame > 1 && !sc->bytes_per_frame) {
4872 avpriv_request_sample(mov->fc,
4873 "Zero bytes per frame, but %d samples per frame",
4874 sc->samples_per_frame);
4875 return;
4876 }
4877
4878
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 148174 times.
162532 if (sc->samples_per_frame >= 160) { // gsm
4879 14358 samples = sc->samples_per_frame;
4880 14358 size = sc->bytes_per_frame;
4881 } else {
4882
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 138611 times.
148174 if (sc->samples_per_frame > 1) {
4883 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
4884 sc->samples_per_frame, chunk_samples);
4885 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
4886 } else {
4887 138611 samples = FFMIN(1024, chunk_samples);
4888 138611 size = samples * sc->sample_size;
4889 }
4890 }
4891
4892
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (sti->nb_index_entries >= total) {
4893 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
4894 return;
4895 }
4896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (size > 0x3FFFFFFF) {
4897 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
4898 return;
4899 }
4900 162532 e = &sti->index_entries[sti->nb_index_entries++];
4901 162532 e->pos = current_offset;
4902 162532 e->timestamp = current_dts;
4903 162532 e->size = size;
4904 162532 e->min_distance = 0;
4905 162532 e->flags = AVINDEX_KEYFRAME;
4906 162532 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
4907 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
4908 size, samples);
4909
4910 162532 current_offset += size;
4911 162532 current_dts += samples;
4912 162532 chunk_samples -= samples;
4913 }
4914 }
4915 }
4916
4917
2/4
✓ Branch 0 taken 613 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 613 times.
✗ Branch 3 not taken.
613 if (!mov->ignore_editlist && mov->advanced_editlist) {
4918 // Fix index according to edit lists.
4919 613 mov_fix_index(mov, st);
4920 }
4921
4922 // Update start time of the stream.
4923
5/6
✓ Branch 0 taken 172 times.
✓ Branch 1 taken 441 times.
✓ Branch 2 taken 55 times.
✓ Branch 3 taken 117 times.
✓ Branch 4 taken 55 times.
✗ Branch 5 not taken.
613 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) {
4924 55 st->start_time = sti->index_entries[0].timestamp + sc->dts_shift;
4925
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 if (sc->tts_data) {
4926 55 st->start_time += sc->tts_data[0].offset;
4927 }
4928 }
4929
4930 613 mov_estimate_video_delay(mov, st);
4931 }
4932
4933 static int test_same_origin(const char *src, const char *ref) {
4934 char src_proto[64];
4935 char ref_proto[64];
4936 char src_auth[256];
4937 char ref_auth[256];
4938 char src_host[256];
4939 char ref_host[256];
4940 int src_port=-1;
4941 int ref_port=-1;
4942
4943 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
4944 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
4945
4946 if (strlen(src) == 0) {
4947 return -1;
4948 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
4949 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
4950 strlen(src_host) + 1 >= sizeof(src_host) ||
4951 strlen(ref_host) + 1 >= sizeof(ref_host)) {
4952 return 0;
4953 } else if (strcmp(src_proto, ref_proto) ||
4954 strcmp(src_auth, ref_auth) ||
4955 strcmp(src_host, ref_host) ||
4956 src_port != ref_port) {
4957 return 0;
4958 } else
4959 return 1;
4960 }
4961
4962 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
4963 {
4964 /* try relative path, we do not try the absolute because it can leak information about our
4965 system to an attacker */
4966 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
4967 char filename[1025];
4968 const char *src_path;
4969 int i, l;
4970
4971 /* find a source dir */
4972 src_path = strrchr(src, '/');
4973 if (src_path)
4974 src_path++;
4975 else
4976 src_path = src;
4977
4978 /* find a next level down to target */
4979 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
4980 if (ref->path[l] == '/') {
4981 if (i == ref->nlvl_to - 1)
4982 break;
4983 else
4984 i++;
4985 }
4986
4987 /* compose filename if next level down to target was found */
4988 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
4989 memcpy(filename, src, src_path - src);
4990 filename[src_path - src] = 0;
4991
4992 for (i = 1; i < ref->nlvl_from; i++)
4993 av_strlcat(filename, "../", sizeof(filename));
4994
4995 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
4996 if (!c->use_absolute_path) {
4997 int same_origin = test_same_origin(src, filename);
4998
4999 if (!same_origin) {
5000 av_log(c->fc, AV_LOG_ERROR,
5001 "Reference with mismatching origin, %s not tried for security reasons, "
5002 "set demuxer option use_absolute_path to allow it anyway\n",
5003 ref->path);
5004 return AVERROR(ENOENT);
5005 }
5006
5007 if (strstr(ref->path + l + 1, "..") ||
5008 strstr(ref->path + l + 1, ":") ||
5009 (ref->nlvl_from > 1 && same_origin < 0) ||
5010 (filename[0] == '/' && src_path == src))
5011 return AVERROR(ENOENT);
5012 }
5013
5014 if (strlen(filename) + 1 == sizeof(filename))
5015 return AVERROR(ENOENT);
5016 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5017 return 0;
5018 }
5019 } else if (c->use_absolute_path) {
5020 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5021 "this is a possible security issue\n");
5022 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5023 return 0;
5024 } else {
5025 av_log(c->fc, AV_LOG_ERROR,
5026 "Absolute path %s not tried for security reasons, "
5027 "set demuxer option use_absolute_path to allow absolute paths\n",
5028 ref->path);
5029 }
5030
5031 return AVERROR(ENOENT);
5032 }
5033
5034 1281 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5035 {
5036
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1267 times.
1281 if (sc->time_scale <= 0) {
5037 14 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5038 14 sc->time_scale = c->time_scale;
5039
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (sc->time_scale <= 0)
5040 sc->time_scale = 1;
5041 }
5042 1281 }
5043
5044 #if CONFIG_IAMFDEC
5045 10 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5046 {
5047 10 const MOVStreamContext *sc = st->priv_data;
5048 10 const IAMFContext *iamf = &sc->iamf->iamf;
5049
5050
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5051 10 const AVStreamGroup *stg = NULL;
5052
5053
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5054
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (c->fc->stream_groups[j]->id == iamf->audio_elements[i]->audio_element_id)
5055 10 stg = c->fc->stream_groups[j];
5056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 av_assert0(stg);
5057
5058
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int j = 0; j < stg->nb_streams; j++) {
5059 50 const FFStream *sti = cffstream(st);
5060 50 AVStream *out = stg->streams[j];
5061 50 FFStream *out_sti = ffstream(stg->streams[j]);
5062
5063 50 out->codecpar->bit_rate = 0;
5064
5065
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 40 times.
50 if (out == st)
5066 10 continue;
5067
5068 40 out->time_base = st->time_base;
5069 40 out->start_time = st->start_time;
5070 40 out->duration = st->duration;
5071 40 out->nb_frames = st->nb_frames;
5072 40 out->discard = st->discard;
5073
5074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 av_assert0(!out_sti->index_entries);
5075 40 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5076
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (!out_sti->index_entries)
5077 return AVERROR(ENOMEM);
5078
5079 40 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5080 40 out_sti->nb_index_entries = sti->nb_index_entries;
5081 40 out_sti->skip_samples = sti->skip_samples;
5082 40 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5083 }
5084 }
5085
5086 10 return 0;
5087 }
5088 #endif
5089
5090 629 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5091 {
5092
4/6
✓ Branch 0 taken 613 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 613 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 613 times.
✗ Branch 5 not taken.
629 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5093
3/4
✓ Branch 0 taken 412 times.
✓ Branch 1 taken 201 times.
✓ Branch 2 taken 412 times.
✗ Branch 3 not taken.
613 (!sc->sample_size && !sc->sample_count))) ||
5094
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 613 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
629 (!sc->chunk_count && sc->sample_count)) {
5095 av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5096 index);
5097 return 1;
5098 }
5099
5100
3/4
✓ Branch 0 taken 613 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 613 times.
629 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
5101 av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5102 index);
5103 return 2;
5104 }
5105 629 return 0;
5106 }
5107
5108 598 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5109 {
5110 AVStream *st;
5111 MOVStreamContext *sc;
5112 int ret;
5113
5114 598 st = avformat_new_stream(c->fc, NULL);
5115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (!st) return AVERROR(ENOMEM);
5116 598 st->id = -1;
5117 598 sc = av_mallocz(sizeof(MOVStreamContext));
5118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (!sc) return AVERROR(ENOMEM);
5119
5120 598 st->priv_data = sc;
5121 598 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5122 598 sc->ffindex = st->index;
5123 598 c->trak_index = st->index;
5124 598 sc->tref_flags = 0;
5125 598 sc->tref_id = -1;
5126 598 sc->refcount = 1;
5127
5128
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 598 times.
598 if ((ret = mov_read_default(c, pb, atom)) < 0)
5129 return ret;
5130
5131 598 c->trak_index = -1;
5132
5133 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5134 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5135
5/6
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 582 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 15 times.
598 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
5136 1 sc->stsc_count = 0;
5137 1 av_freep(&sc->stsc_data);
5138 }
5139
5140 598 ret = sanity_checks(c->fc, sc, st->index);
5141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (ret)
5142 return ret > 1 ? AVERROR_INVALIDDATA : 0;
5143
5144 598 fix_timescale(c, sc);
5145
5146 598 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5147
5148 /*
5149 * Advanced edit list support does not work with fragemented MP4s, which
5150 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5151 * In these files, trun atoms may be streamed in.
5152 */
5153
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 582 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 4 times.
598 if (!sc->stts_count && c->advanced_editlist) {
5154
5155 12 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5156 "MP4. disabling.\n");
5157 12 c->advanced_editlist = 0;
5158 12 c->advanced_editlist_autodisabled = 1;
5159 }
5160
5161 598 mov_build_index(c, st);
5162
5163 #if CONFIG_IAMFDEC
5164
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 588 times.
598 if (sc->iamf) {
5165 10 ret = mov_update_iamf_streams(c, st);
5166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
5167 return ret;
5168 }
5169 #endif
5170
5171
3/4
✓ Branch 0 taken 597 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 597 times.
598 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
5172 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5173 if (c->enable_drefs) {
5174 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5175 av_log(c->fc, AV_LOG_ERROR,
5176 "stream %d, error opening alias: path='%s', dir='%s', "
5177 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5178 st->index, dref->path, dref->dir, dref->filename,
5179 dref->volume, dref->nlvl_from, dref->nlvl_to);
5180 } else {
5181 av_log(c->fc, AV_LOG_WARNING,
5182 "Skipped opening external track: "
5183 "stream %d, alias: path='%s', dir='%s', "
5184 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5185 "Set enable_drefs to allow this.\n",
5186 st->index, dref->path, dref->dir, dref->filename,
5187 dref->volume, dref->nlvl_from, dref->nlvl_to);
5188 }
5189 } else {
5190 598 sc->pb = c->fc->pb;
5191 598 sc->pb_is_copied = 1;
5192 }
5193
5194
2/2
✓ Branch 0 taken 306 times.
✓ Branch 1 taken 292 times.
598 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5195
3/4
✓ Branch 0 taken 296 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 296 times.
✗ Branch 3 not taken.
306 int stts_constant = sc->stts_count && sc->tts_count;
5196
3/4
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 247 times.
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
306 if (sc->h_spacing && sc->v_spacing)
5197 59 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5198 59 sc->h_spacing, sc->v_spacing, INT_MAX);
5199
4/6
✓ Branch 0 taken 244 times.
✓ Branch 1 taken 62 times.
✓ Branch 2 taken 244 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 244 times.
✗ Branch 5 not taken.
306 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
5200
2/4
✓ Branch 0 taken 244 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 244 times.
✗ Branch 3 not taken.
244 sc->height && sc->width &&
5201
2/4
✓ Branch 0 taken 244 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 244 times.
244 (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
5202 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5203 (int64_t)st->codecpar->height * sc->width,
5204 (int64_t)st->codecpar->width * sc->height, INT_MAX);
5205 }
5206
5207 #if FF_API_R_FRAME_RATE
5208
4/4
✓ Branch 0 taken 154832 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 154536 times.
✓ Branch 3 taken 296 times.
154842 for (unsigned int i = 1; sc->stts_count && i + 1 < sc->tts_count; i++) {
5209
2/2
✓ Branch 0 taken 152109 times.
✓ Branch 1 taken 2427 times.
154536 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5210 152109 continue;
5211 2427 stts_constant = 0;
5212 }
5213
2/2
✓ Branch 0 taken 282 times.
✓ Branch 1 taken 24 times.
306 if (stts_constant)
5214 282 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5215 282 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5216 #endif
5217 }
5218
5219 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
5220
3/4
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 332 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 266 times.
598 if (!st->codecpar->extradata_size && st->codecpar->codec_id == AV_CODEC_ID_H264 &&
5221 TAG_IS_AVCI(st->codecpar->codec_tag)) {
5222 ret = ff_generate_avci_extradata(st);
5223 if (ret < 0)
5224 return ret;
5225 }
5226
5227
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 574 times.
598 switch (st->codecpar->codec_id) {
5228 #if CONFIG_H261_DECODER
5229 24 case AV_CODEC_ID_H261:
5230 #endif
5231 #if CONFIG_H263_DECODER
5232 case AV_CODEC_ID_H263:
5233 #endif
5234 #if CONFIG_MPEG4_DECODER
5235 case AV_CODEC_ID_MPEG4:
5236 #endif
5237 24 st->codecpar->width = 0; /* let decoder init width/height */
5238 24 st->codecpar->height= 0;
5239 24 break;
5240 }
5241
5242 // If the duration of the mp3 packets is not constant, then they could need a parser
5243
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 597 times.
598 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5244
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 && sc->time_scale == st->codecpar->sample_rate) {
5245 1 int stts_constant = 1;
5246
3/4
✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 287 times.
✓ Branch 3 taken 1 times.
288 for (int i = 1; sc->stts_count && i < sc->tts_count; i++) {
5247
1/2
✓ Branch 0 taken 287 times.
✗ Branch 1 not taken.
287 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5248 287 continue;
5249 stts_constant = 0;
5250 }
5251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!stts_constant)
5252 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5253 }
5254 /* Do not need those anymore. */
5255 598 av_freep(&sc->chunk_offsets);
5256 598 av_freep(&sc->sample_sizes);
5257 598 av_freep(&sc->keyframes);
5258 598 av_freep(&sc->stps_data);
5259 598 av_freep(&sc->elst_data);
5260 598 av_freep(&sc->rap_group);
5261 598 av_freep(&sc->sync_group);
5262 598 av_freep(&sc->sgpd_sync);
5263
5264 598 return 0;
5265 }
5266
5267 126 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5268 {
5269 int ret;
5270 126 c->itunes_metadata = 1;
5271 126 ret = mov_read_default(c, pb, atom);
5272 126 c->itunes_metadata = 0;
5273 126 return ret;
5274 }
5275
5276 11 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5277 {
5278 uint32_t count;
5279 uint32_t i;
5280
5281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
5282 return 0;
5283
5284 11 avio_skip(pb, 4);
5285 11 count = avio_rb32(pb);
5286 11 atom.size -= 8;
5287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (count >= UINT_MAX / sizeof(*c->meta_keys)) {
5288 av_log(c->fc, AV_LOG_ERROR,
5289 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5290 return AVERROR_INVALIDDATA;
5291 }
5292
5293 11 c->meta_keys_count = count + 1;
5294 11 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
5295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!c->meta_keys)
5296 return AVERROR(ENOMEM);
5297
5298
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i <= count; ++i) {
5299 58 uint32_t key_size = avio_rb32(pb);
5300 58 uint32_t type = avio_rl32(pb);
5301
2/4
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 58 times.
58 if (key_size < 8 || key_size > atom.size) {
5302 av_log(c->fc, AV_LOG_ERROR,
5303 "The key# %"PRIu32" in meta has invalid size:"
5304 "%"PRIu32"\n", i, key_size);
5305 return AVERROR_INVALIDDATA;
5306 }
5307 58 atom.size -= key_size;
5308 58 key_size -= 8;
5309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (type != MKTAG('m','d','t','a')) {
5310 avio_skip(pb, key_size);
5311 continue;
5312 }
5313 58 c->meta_keys[i] = av_mallocz(key_size + 1);
5314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!c->meta_keys[i])
5315 return AVERROR(ENOMEM);
5316 58 avio_read(pb, c->meta_keys[i], key_size);
5317 }
5318
5319 11 return 0;
5320 }
5321
5322 65 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5323 {
5324 65 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5325 65 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5326 int i;
5327 65 int ret = 0;
5328 AVStream *st;
5329 MOVStreamContext *sc;
5330
5331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (c->fc->nb_streams < 1)
5332 return 0;
5333 65 st = c->fc->streams[c->fc->nb_streams-1];
5334 65 sc = st->priv_data;
5335
5336
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 65 times.
260 for (i = 0; i < 3; i++) {
5337 uint8_t **p;
5338 uint32_t len, tag;
5339
5340
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 195 times.
195 if (end - avio_tell(pb) <= 12)
5341 break;
5342
5343 195 len = avio_rb32(pb);
5344 195 tag = avio_rl32(pb);
5345 195 avio_skip(pb, 4); // flags
5346
5347
2/4
✓ Branch 0 taken 195 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 195 times.
✗ Branch 4 not taken.
195 if (len < 12 || len - 12 > end - avio_tell(pb))
5348 break;
5349 195 len -= 12;
5350
5351
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 130 times.
195 if (tag == MKTAG('m', 'e', 'a', 'n'))
5352 65 p = &mean;
5353
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 65 times.
130 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5354 65 p = &key;
5355
2/4
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
65 else if (tag == MKTAG('d', 'a', 't', 'a') && len > 4) {
5356 65 avio_skip(pb, 4);
5357 65 len -= 4;
5358 65 p = &val;
5359 } else
5360 break;
5361
5362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (*p)
5363 break;
5364
5365 195 *p = av_malloc(len + 1);
5366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*p) {
5367 ret = AVERROR(ENOMEM);
5368 break;
5369 }
5370 195 ret = ffio_read_size(pb, *p, len);
5371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (ret < 0) {
5372 av_freep(p);
5373 break;
5374 }
5375 195 (*p)[len] = 0;
5376 }
5377
5378
3/6
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 65 times.
✗ Branch 5 not taken.
65 if (mean && key && val) {
5379
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 32 times.
65 if (strcmp(key, "iTunSMPB") == 0) {
5380 int priming, remainder, samples;
5381
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
5382
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
33 if(priming>0 && priming<16384)
5383 33 sc->start_pad = priming;
5384 }
5385 }
5386
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 10 times.
120 if (strcmp(key, "cdec") != 0) {
5387 55 av_dict_set(&c->fc->metadata, key, val,
5388 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5389 55 key = val = NULL;
5390 }
5391 } else {
5392 av_log(c->fc, AV_LOG_VERBOSE,
5393 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5394 }
5395
5396 65 avio_seek(pb, end, SEEK_SET);
5397 65 av_freep(&key);
5398 65 av_freep(&val);
5399 65 av_freep(&mean);
5400 65 return ret;
5401 }
5402
5403 31 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5404 {
5405 MOVStreamContext *sc;
5406 AVStream *st;
5407
5408 31 st = avformat_new_stream(c->fc, NULL);
5409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!st)
5410 return AVERROR(ENOMEM);
5411 31 sc = av_mallocz(sizeof(MOVStreamContext));
5412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!sc)
5413 return AVERROR(ENOMEM);
5414
5415 31 item->st = st;
5416 31 st->id = item->item_id;
5417 31 st->priv_data = sc;
5418 31 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5419 31 st->codecpar->codec_id = mov_codec_id(st, item->type);
5420 31 sc->id = st->id;
5421 31 sc->ffindex = st->index;
5422 31 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5423 31 st->time_base.num = st->time_base.den = 1;
5424 31 st->nb_frames = 1;
5425 31 sc->time_scale = 1;
5426 31 sc->pb = c->fc->pb;
5427 31 sc->pb_is_copied = 1;
5428 31 sc->refcount = 1;
5429
5430
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 if (item->name)
5431 31 av_dict_set(&st->metadata, "title", item->name, 0);
5432
5433 // Populate the necessary fields used by mov_build_index.
5434 31 sc->stsc_count = 1;
5435 31 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!sc->stsc_data)
5437 return AVERROR(ENOMEM);
5438 31 sc->stsc_data[0].first = 1;
5439 31 sc->stsc_data[0].count = 1;
5440 31 sc->stsc_data[0].id = 1;
5441 31 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!sc->chunk_offsets)
5443 return AVERROR(ENOMEM);
5444 31 sc->chunk_count = 1;
5445 31 sc->sample_sizes = av_malloc_array(1, sizeof(*sc->sample_sizes));
5446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!sc->sample_sizes)
5447 return AVERROR(ENOMEM);
5448 31 sc->sample_count = 1;
5449 31 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!sc->stts_data)
5451 return AVERROR(ENOMEM);
5452 31 sc->stts_count = 1;
5453 31 sc->stts_data[0].count = 1;
5454 // Not used for still images. But needed by mov_build_index.
5455 31 sc->stts_data[0].duration = 0;
5456
5457 31 return 0;
5458 }
5459
5460 143 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5461 {
5462
1/2
✓ Branch 0 taken 415 times.
✗ Branch 1 not taken.
415 while (atom.size > 8) {
5463 uint32_t tag;
5464
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 415 times.
415 if (avio_feof(pb))
5465 return AVERROR_EOF;
5466 415 tag = avio_rl32(pb);
5467 415 atom.size -= 4;
5468
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 272 times.
415 if (tag == MKTAG('h','d','l','r')) {
5469 143 avio_seek(pb, -8, SEEK_CUR);
5470 143 atom.size += 8;
5471 143 return mov_read_default(c, pb, atom);
5472 }
5473 }
5474 return 0;
5475 }
5476
5477 // return 1 when matrix is identity, 0 otherwise
5478 #define IS_MATRIX_IDENT(matrix) \
5479 ( (matrix)[0][0] == (1 << 16) && \
5480 (matrix)[1][1] == (1 << 16) && \
5481 (matrix)[2][2] == (1 << 30) && \
5482 !(matrix)[0][1] && !(matrix)[0][2] && \
5483 !(matrix)[1][0] && !(matrix)[1][2] && \
5484 !(matrix)[2][0] && !(matrix)[2][1])
5485
5486 598 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5487 {
5488 int i, j, e;
5489 int width;
5490 int height;
5491 int display_matrix[3][3];
5492 598 int res_display_matrix[3][3] = { { 0 } };
5493 AVStream *st;
5494 MOVStreamContext *sc;
5495 int version;
5496 int flags;
5497
5498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (c->fc->nb_streams < 1)
5499 return 0;
5500 598 st = c->fc->streams[c->fc->nb_streams-1];
5501 598 sc = st->priv_data;
5502
5503 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5504 // avoids corrupting AVStreams mapped to an earlier tkhd.
5505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (st->id != -1)
5506 return AVERROR_INVALIDDATA;
5507
5508 598 version = avio_r8(pb);
5509 598 flags = avio_rb24(pb);
5510 598 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5511
5512
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 589 times.
598 if (version == 1) {
5513 9 avio_rb64(pb);
5514 9 avio_rb64(pb);
5515 } else {
5516 589 avio_rb32(pb); /* creation time */
5517 589 avio_rb32(pb); /* modification time */
5518 }
5519 598 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5520 598 sc->id = st->id;
5521 598 avio_rb32(pb); /* reserved */
5522
5523 /* highlevel (considering edits) duration in movie timebase */
5524
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 589 times.
598 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5525 598 avio_rb32(pb); /* reserved */
5526 598 avio_rb32(pb); /* reserved */
5527
5528 598 avio_rb16(pb); /* layer */
5529 598 avio_rb16(pb); /* alternate group */
5530 598 avio_rb16(pb); /* volume */
5531 598 avio_rb16(pb); /* reserved */
5532
5533 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
5534 // they're kept in fixed point format through all calculations
5535 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
5536 // side data, but the scale factor is not needed to calculate aspect ratio
5537
2/2
✓ Branch 0 taken 1794 times.
✓ Branch 1 taken 598 times.
2392 for (i = 0; i < 3; i++) {
5538 1794 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
5539 1794 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
5540 1794 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
5541 }
5542
5543 598 width = avio_rb32(pb); // 16.16 fixed point track width
5544 598 height = avio_rb32(pb); // 16.16 fixed point track height
5545 598 sc->width = width >> 16;
5546 598 sc->height = height >> 16;
5547
5548 // apply the moov display matrix (after the tkhd one)
5549
2/2
✓ Branch 0 taken 1794 times.
✓ Branch 1 taken 598 times.
2392 for (i = 0; i < 3; i++) {
5550 1794 const int sh[3] = { 16, 16, 30 };
5551
2/2
✓ Branch 0 taken 5382 times.
✓ Branch 1 taken 1794 times.
7176 for (j = 0; j < 3; j++) {
5552
2/2
✓ Branch 0 taken 16146 times.
✓ Branch 1 taken 5382 times.
21528 for (e = 0; e < 3; e++) {
5553 16146 res_display_matrix[i][j] +=
5554 16146 ((int64_t) display_matrix[i][e] *
5555 16146 c->movie_display_matrix[e][j]) >> sh[e];
5556 }
5557 }
5558 }
5559
5560 // save the matrix when it is not the default identity
5561
10/18
✓ Branch 0 taken 589 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 589 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 589 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 589 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 589 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 589 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 589 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 589 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 589 times.
598 if (!IS_MATRIX_IDENT(res_display_matrix)) {
5562 9 av_freep(&sc->display_matrix);
5563 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
5564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
5565 return AVERROR(ENOMEM);
5566
5567
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
5568
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
5569 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
5570 }
5571
5572 // transform the display width/height according to the matrix
5573 // to keep the same scale, use [width height 1<<16]
5574
5/6
✓ Branch 0 taken 316 times.
✓ Branch 1 taken 282 times.
✓ Branch 2 taken 316 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 308 times.
598 if (width && height && sc->display_matrix) {
5575 double disp_transform[2];
5576
5577
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
5578 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
5579 16 sc->display_matrix[3 + i]);
5580
5581
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 if (disp_transform[0] > 1 && disp_transform[1] > 1 &&
5582
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 disp_transform[0] < (1<<24) && disp_transform[1] < (1<<24) &&
5583
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
5584 3 st->sample_aspect_ratio = av_d2q(
5585 3 disp_transform[0] / disp_transform[1],
5586 INT_MAX);
5587 }
5588 598 return 0;
5589 }
5590
5591 388 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5592 {
5593 388 MOVFragment *frag = &c->fragment;
5594 388 MOVTrackExt *trex = NULL;
5595 int flags, track_id, i;
5596 MOVFragmentStreamInfo * frag_stream_info;
5597
5598 388 avio_r8(pb); /* version */
5599 388 flags = avio_rb24(pb);
5600
5601 388 track_id = avio_rb32(pb);
5602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!track_id)
5603 return AVERROR_INVALIDDATA;
5604
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < c->trex_count; i++)
5605
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (c->trex_data[i].track_id == track_id) {
5606 388 trex = &c->trex_data[i];
5607 388 break;
5608 }
5609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!trex) {
5610 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
5611 return 0;
5612 }
5613 388 c->fragment.found_tfhd = 1;
5614 388 frag->track_id = track_id;
5615 388 set_frag_stream(&c->frag_index, track_id);
5616
5617 776 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
5618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
776 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
5619
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 21 times.
388 frag->moof_offset : frag->implicit_offset;
5620
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 385 times.
388 frag->stsd_id = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id;
5621
5622 776 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
5623
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 383 times.
388 avio_rb32(pb) : trex->duration;
5624 776 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
5625
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 382 times.
388 avio_rb32(pb) : trex->size;
5626 776 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
5627
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 365 times.
388 avio_rb32(pb) : trex->flags;
5628 388 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
5629
5630 388 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5631
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5632 388 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
5633 388 frag_stream_info->stsd_id = frag->stsd_id;
5634 }
5635 388 return 0;
5636 }
5637
5638 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5639 {
5640 unsigned i, num;
5641 void *new_tracks;
5642
5643 2 num = atom.size / 4;
5644
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
5645 return AVERROR(ENOMEM);
5646
5647 2 av_free(c->chapter_tracks);
5648 2 c->chapter_tracks = new_tracks;
5649 2 c->nb_chapter_tracks = num;
5650
5651
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++)
5652 2 c->chapter_tracks[i] = avio_rb32(pb);
5653
5654 2 c->nb_chapter_tracks = i;
5655
5656 2 return 0;
5657 }
5658
5659 17 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5660 {
5661 MOVTrackExt *trex;
5662 int err;
5663
5664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if ((uint64_t)c->trex_count+1 >= UINT_MAX / sizeof(*c->trex_data))
5665 return AVERROR_INVALIDDATA;
5666
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
5667 sizeof(*c->trex_data))) < 0) {
5668 c->trex_count = 0;
5669 return err;
5670 }
5671
5672 17 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
5673
5674 17 trex = &c->trex_data[c->trex_count++];
5675 17 avio_r8(pb); /* version */
5676 17 avio_rb24(pb); /* flags */
5677 17 trex->track_id = avio_rb32(pb);
5678 17 trex->stsd_id = avio_rb32(pb);
5679 17 trex->duration = avio_rb32(pb);
5680 17 trex->size = avio_rb32(pb);
5681 17 trex->flags = avio_rb32(pb);
5682 17 return 0;
5683 }
5684
5685 367 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5686 {
5687 367 MOVFragment *frag = &c->fragment;
5688 367 AVStream *st = NULL;
5689 MOVStreamContext *sc;
5690 int version, i;
5691 MOVFragmentStreamInfo * frag_stream_info;
5692 int64_t base_media_decode_time;
5693
5694
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 for (i = 0; i < c->fc->nb_streams; i++) {
5695 367 sc = c->fc->streams[i]->priv_data;
5696
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 if (sc->id == frag->track_id) {
5697 367 st = c->fc->streams[i];
5698 367 break;
5699 }
5700 }
5701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367 times.
367 if (!st) {
5702 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5703 return 0;
5704 }
5705 367 sc = st->priv_data;
5706
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 365 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
367 if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1)
5707 return 0;
5708 367 version = avio_r8(pb);
5709 367 avio_rb24(pb); /* flags */
5710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367 times.
367 if (version) {
5711 base_media_decode_time = avio_rb64(pb);
5712 } else {
5713 367 base_media_decode_time = avio_rb32(pb);
5714 }
5715
5716 367 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5717
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 if (frag_stream_info)
5718 367 frag_stream_info->tfdt_dts = base_media_decode_time;
5719 367 sc->track_end = base_media_decode_time;
5720
5721 367 return 0;
5722 }
5723
5724 388 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5725 {
5726 388 MOVFragment *frag = &c->fragment;
5727 388 AVStream *st = NULL;
5728 388 FFStream *sti = NULL;
5729 MOVStreamContext *sc;
5730 MOVTimeToSample *tts_data;
5731 uint64_t offset;
5732 388 int64_t dts, pts = AV_NOPTS_VALUE;
5733 388 int data_offset = 0;
5734 388 unsigned entries, first_sample_flags = frag->flags;
5735 int flags, distance, i;
5736 388 int64_t prev_dts = AV_NOPTS_VALUE;
5737 388 int next_frag_index = -1, index_entry_pos;
5738 size_t requested_size;
5739 size_t old_allocated_size;
5740 AVIndexEntry *new_entries;
5741 MOVFragmentStreamInfo * frag_stream_info;
5742
5743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!frag->found_tfhd) {
5744 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
5745 return AVERROR_INVALIDDATA;
5746 }
5747
5748
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < c->fc->nb_streams; i++) {
5749 394 sc = c->fc->streams[i]->priv_data;
5750
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (sc->id == frag->track_id) {
5751 388 st = c->fc->streams[i];
5752 388 sti = ffstream(st);
5753 388 break;
5754 }
5755 }
5756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!st) {
5757 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5758 return 0;
5759 }
5760 388 sc = st->priv_data;
5761
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 386 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
388 if (sc->pseudo_stream_id+1 != frag->stsd_id && sc->pseudo_stream_id != -1)
5762 return 0;
5763
5764 // Find the next frag_index index that has a valid index_entry for
5765 // the current track_id.
5766 //
5767 // A valid index_entry means the trun for the fragment was read
5768 // and it's samples are in index_entries at the given position.
5769 // New index entries will be inserted before the index_entry found.
5770 388 index_entry_pos = sti->nb_index_entries;
5771
2/2
✓ Branch 0 taken 1621 times.
✓ Branch 1 taken 388 times.
2009 for (i = c->frag_index.current + 1; i < c->frag_index.nb_items; i++) {
5772 1621 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
5773
2/4
✓ Branch 0 taken 1621 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1621 times.
1621 if (frag_stream_info && frag_stream_info->index_entry >= 0) {
5774 next_frag_index = i;
5775 index_entry_pos = frag_stream_info->index_entry;
5776 break;
5777 }
5778 }
5779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 av_assert0(index_entry_pos <= sti->nb_index_entries);
5780
5781 388 avio_r8(pb); /* version */
5782 388 flags = avio_rb24(pb);
5783 388 entries = avio_rb32(pb);
5784 388 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
5785
5786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if ((uint64_t)entries+sc->tts_count >= UINT_MAX/sizeof(*sc->tts_data))
5787 return AVERROR_INVALIDDATA;
5788
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
5789
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 367 times.
388 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb);
5790
5791 388 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5792
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5793
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
5794 dts = frag_stream_info->next_trun_dts - sc->time_offset;
5795
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5796 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
5797 pts = frag_stream_info->first_tfra_pts;
5798 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5799 ", using it for pts\n", pts);
5800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5801 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
5802 dts = frag_stream_info->first_tfra_pts;
5803 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5804 ", using it for dts\n", pts);
5805 } else {
5806 388 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
5807 388 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
5808
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
388 int fallback_tfdt = !c->use_tfdt && !has_sidx && has_tfdt;
5809
4/6
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 367 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
388 int fallback_sidx = c->use_tfdt && !has_tfdt && has_sidx;
5810
5811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (fallback_sidx) {
5812 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
5813 }
5814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (fallback_tfdt) {
5815 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
5816 }
5817
5818
4/6
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 367 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
388 if (has_tfdt && c->use_tfdt || fallback_tfdt) {
5819 367 dts = frag_stream_info->tfdt_dts - sc->time_offset;
5820 367 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
5821 ", using it for dts\n", dts);
5822
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
21 } else if (has_sidx && !c->use_tfdt || fallback_sidx) {
5823 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
5824 // pts = frag_stream_info->sidx_pts;
5825 dts = frag_stream_info->sidx_pts - sc->time_offset;
5826 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
5827 ", using it for dts\n", frag_stream_info->sidx_pts);
5828 } else {
5829 21 dts = sc->track_end - sc->time_offset;
5830 21 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5831 ", using it for dts\n", dts);
5832 }
5833 }
5834 } else {
5835 dts = sc->track_end - sc->time_offset;
5836 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5837 ", using it for dts\n", dts);
5838 }
5839 388 offset = frag->base_data_offset + data_offset;
5840 388 distance = 0;
5841 388 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
5842
5843 // realloc space for new index entries
5844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
5845 entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
5846 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
5847 }
5848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (entries == 0)
5849 return 0;
5850
5851 388 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
5852 388 new_entries = av_fast_realloc(sti->index_entries,
5853 &sti->index_entries_allocated_size,
5854 requested_size);
5855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!new_entries)
5856 return AVERROR(ENOMEM);
5857 388 sti->index_entries= new_entries;
5858
5859 388 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
5860 388 old_allocated_size = sc->tts_allocated_size;
5861 388 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
5862 requested_size);
5863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!tts_data)
5864 return AVERROR(ENOMEM);
5865 388 sc->tts_data = tts_data;
5866
5867 // In case there were samples without time to sample entries, ensure they get
5868 // zero valued entries. This ensures clips which mix boxes with and
5869 // without time to sample entries don't pickup uninitialized data.
5870 388 memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0,
5871 388 sc->tts_allocated_size - old_allocated_size);
5872
5873
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (index_entry_pos < sti->nb_index_entries) {
5874 // Make hole in index_entries and tts_data for new samples
5875 memmove(sti->index_entries + index_entry_pos + entries,
5876 sti->index_entries + index_entry_pos,
5877 sizeof(*sti->index_entries) *
5878 (sti->nb_index_entries - index_entry_pos));
5879 memmove(sc->tts_data + index_entry_pos + entries,
5880 sc->tts_data + index_entry_pos,
5881 sizeof(*sc->tts_data) * (sc->tts_count - index_entry_pos));
5882 if (index_entry_pos < sc->current_sample) {
5883 sc->current_sample += entries;
5884 }
5885 }
5886
5887 388 sti->nb_index_entries += entries;
5888 388 sc->tts_count = sti->nb_index_entries;
5889 388 sc->stts_count = sti->nb_index_entries;
5890
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 28 times.
388 if (flags & MOV_TRUN_SAMPLE_CTS)
5891 360 sc->ctts_count = sti->nb_index_entries;
5892
5893 // Record the index_entry position in frag_index of this fragment
5894
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5895 388 frag_stream_info->index_entry = index_entry_pos;
5896
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info->index_base < 0)
5897 388 frag_stream_info->index_base = index_entry_pos;
5898 }
5899
5900
2/2
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 14 times.
388 if (index_entry_pos > 0)
5901 374 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
5902
5903
3/4
✓ Branch 0 taken 6066 times.
✓ Branch 1 taken 388 times.
✓ Branch 2 taken 6066 times.
✗ Branch 3 not taken.
6454 for (i = 0; i < entries && !pb->eof_reached; i++) {
5904 6066 unsigned sample_size = frag->size;
5905
2/2
✓ Branch 0 taken 5678 times.
✓ Branch 1 taken 388 times.
6066 int sample_flags = i ? frag->flags : first_sample_flags;
5906 6066 unsigned sample_duration = frag->duration;
5907 6066 unsigned ctts_duration = 0;
5908 6066 int keyframe = 0;
5909 6066 int index_entry_flags = 0;
5910
5911
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 5594 times.
6066 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
5912
2/2
✓ Branch 0 taken 6034 times.
✓ Branch 1 taken 32 times.
6066 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
5913
2/2
✓ Branch 0 taken 933 times.
✓ Branch 1 taken 5133 times.
6066 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
5914
2/2
✓ Branch 0 taken 5400 times.
✓ Branch 1 taken 666 times.
6066 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
5915
5916 6066 mov_update_dts_shift(sc, ctts_duration, c->fc);
5917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6066 times.
6066 if (pts != AV_NOPTS_VALUE) {
5918 dts = pts - sc->dts_shift;
5919 if (flags & MOV_TRUN_SAMPLE_CTS) {
5920 dts -= ctts_duration;
5921 } else {
5922 dts -= sc->time_offset;
5923 }
5924 av_log(c->fc, AV_LOG_DEBUG,
5925 "pts %"PRId64" calculated dts %"PRId64
5926 " sc->dts_shift %d ctts.duration %d"
5927 " sc->time_offset %"PRId64
5928 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
5929 pts, dts,
5930 sc->dts_shift, ctts_duration,
5931 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
5932 pts = AV_NOPTS_VALUE;
5933 }
5934
5935 6066 keyframe =
5936 6066 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
5937 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
5938
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 5666 times.
6066 if (keyframe) {
5939 400 distance = 0;
5940 400 index_entry_flags |= AVINDEX_KEYFRAME;
5941 }
5942 // Fragments can overlap in time. Discard overlapping frames after
5943 // decoding.
5944
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6042 times.
6066 if (prev_dts >= dts)
5945 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
5946
5947 6066 sti->index_entries[index_entry_pos].pos = offset;
5948 6066 sti->index_entries[index_entry_pos].timestamp = dts;
5949 6066 sti->index_entries[index_entry_pos].size = sample_size;
5950 6066 sti->index_entries[index_entry_pos].min_distance = distance;
5951 6066 sti->index_entries[index_entry_pos].flags = index_entry_flags;
5952
5953 6066 sc->tts_data[index_entry_pos].count = 1;
5954 6066 sc->tts_data[index_entry_pos].offset = ctts_duration;
5955 6066 sc->tts_data[index_entry_pos].duration = sample_duration;
5956 6066 index_entry_pos++;
5957
5958 6066 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
5959 "size %u, distance %d, keyframe %d\n", st->index,
5960 index_entry_pos, offset, dts, sample_size, distance, keyframe);
5961 6066 distance++;
5962
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6066 times.
6066 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
5963 return AVERROR_INVALIDDATA;
5964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6066 times.
6066 if (!sample_size)
5965 return AVERROR_INVALIDDATA;
5966 6066 dts += sample_duration;
5967 6066 offset += sample_size;
5968 6066 sc->data_size += sample_size;
5969
5970
1/2
✓ Branch 0 taken 6066 times.
✗ Branch 1 not taken.
6066 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
5971
1/2
✓ Branch 0 taken 6066 times.
✗ Branch 1 not taken.
6066 1 <= INT_MAX - sc->nb_frames_for_fps
5972 ) {
5973 6066 sc->duration_for_fps += sample_duration;
5974 6066 sc->nb_frames_for_fps ++;
5975 }
5976 }
5977
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info)
5978 388 frag_stream_info->next_trun_dts = dts + sc->time_offset;
5979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (i < entries) {
5980 // EOF found before reading all entries. Fix the hole this would
5981 // leave in index_entries and tts_data
5982 int gap = entries - i;
5983 memmove(sti->index_entries + index_entry_pos,
5984 sti->index_entries + index_entry_pos + gap,
5985 sizeof(*sti->index_entries) *
5986 (sti->nb_index_entries - (index_entry_pos + gap)));
5987 memmove(sc->tts_data + index_entry_pos,
5988 sc->tts_data + index_entry_pos + gap,
5989 sizeof(*sc->tts_data) *
5990 (sc->tts_count - (index_entry_pos + gap)));
5991
5992 sti->nb_index_entries -= gap;
5993 sc->tts_count -= gap;
5994 if (index_entry_pos < sc->current_sample) {
5995 sc->current_sample -= gap;
5996 }
5997 entries = i;
5998 }
5999
6000 // The end of this new fragment may overlap in time with the start
6001 // of the next fragment in index_entries. Mark the samples in the next
6002 // fragment that overlap with AVINDEX_DISCARD_FRAME
6003 388 prev_dts = AV_NOPTS_VALUE;
6004
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (index_entry_pos > 0)
6005 388 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
6007 if (prev_dts < sti->index_entries[i].timestamp)
6008 break;
6009 sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6010 }
6011
6012 // If a hole was created to insert the new index_entries into,
6013 // the index_entry recorded for all subsequent moof must
6014 // be incremented by the number of entries inserted.
6015 388 fix_frag_index_entries(&c->frag_index, next_frag_index,
6016 388 frag->track_id, entries);
6017
6018
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (pb->eof_reached) {
6019 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6020 return AVERROR_EOF;
6021 }
6022
6023 388 frag->implicit_offset = offset;
6024
6025 388 sc->track_end = dts + sc->time_offset;
6026
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 379 times.
388 if (st->duration < sc->track_end)
6027 9 st->duration = sc->track_end;
6028
6029 388 return 0;
6030 }
6031
6032 43 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6033 {
6034 43 int64_t stream_size = avio_size(pb);
6035 43 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6036 uint8_t version, is_complete;
6037 int64_t offadd;
6038 unsigned i, j, track_id, item_count;
6039 43 AVStream *st = NULL;
6040 43 AVStream *ref_st = NULL;
6041 43 MOVStreamContext *sc, *ref_sc = NULL;
6042 AVRational timescale;
6043
6044 43 version = avio_r8(pb);
6045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (version > 1) {
6046 avpriv_request_sample(c->fc, "sidx version %u", version);
6047 return 0;
6048 }
6049
6050 43 avio_rb24(pb); // flags
6051
6052 43 track_id = avio_rb32(pb); // Reference ID
6053
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 for (i = 0; i < c->fc->nb_streams; i++) {
6054 43 sc = c->fc->streams[i]->priv_data;
6055
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (sc->id == track_id) {
6056 43 st = c->fc->streams[i];
6057 43 break;
6058 }
6059 }
6060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st) {
6061 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6062 return 0;
6063 }
6064
6065 43 sc = st->priv_data;
6066
6067 43 timescale = av_make_q(1, avio_rb32(pb));
6068
6069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (timescale.den <= 0) {
6070 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6071 return AVERROR_INVALIDDATA;
6072 }
6073
6074
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (version == 0) {
6075 43 pts = avio_rb32(pb);
6076 43 offadd= avio_rb32(pb);
6077 } else {
6078 pts = avio_rb64(pb);
6079 offadd= avio_rb64(pb);
6080 }
6081
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6082 return AVERROR_INVALIDDATA;
6083
6084 43 offset += (uint64_t)offadd;
6085
6086 43 avio_rb16(pb); // reserved
6087
6088 43 item_count = avio_rb16(pb);
6089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (item_count == 0)
6090 return AVERROR_INVALIDDATA;
6091
6092
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 43 times.
411 for (i = 0; i < item_count; i++) {
6093 int index;
6094 MOVFragmentStreamInfo * frag_stream_info;
6095 368 uint32_t size = avio_rb32(pb);
6096 368 uint32_t duration = avio_rb32(pb);
6097
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 368 times.
368 if (size & 0x80000000) {
6098 avpriv_request_sample(c->fc, "sidx reference_type 1");
6099 return AVERROR_PATCHWELCOME;
6100 }
6101 368 avio_rb32(pb); // sap_flags
6102 368 timestamp = av_rescale_q(pts, timescale, st->time_base);
6103
6104 368 index = update_frag_index(c, offset);
6105 368 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6106
1/2
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
368 if (frag_stream_info)
6107 368 frag_stream_info->sidx_pts = timestamp;
6108
6109
1/2
✓ Branch 1 taken 368 times.
✗ Branch 2 not taken.
368 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6110
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 368 times.
368 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6111 )
6112 return AVERROR_INVALIDDATA;
6113 368 offset += size;
6114 368 pts += duration;
6115 }
6116
6117 43 st->duration = sc->track_end = pts;
6118
6119 43 sc->has_sidx = 1;
6120
6121 // See if the remaining bytes are just an mfra which we can ignore.
6122 43 is_complete = offset == stream_size;
6123
4/6
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
43 if (!is_complete && (pb->seekable & AVIO_SEEKABLE_NORMAL) && stream_size > 0 ) {
6124 int64_t ret;
6125 38 int64_t original_pos = avio_tell(pb);
6126
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
38 if (!c->have_read_mfra_size) {
6127
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6128 return ret;
6129 3 c->mfra_size = avio_rb32(pb);
6130 3 c->have_read_mfra_size = 1;
6131
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6132 return ret;
6133 }
6134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (offset == stream_size - c->mfra_size)
6135 is_complete = 1;
6136 }
6137
6138
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 38 times.
43 if (is_complete) {
6139 // Find first entry in fragment index that came from an sidx.
6140 // This will pretty much always be the first entry.
6141
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 5 times.
373 for (i = 0; i < c->frag_index.nb_items; i++) {
6142 368 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6143
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 363 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
368 for (j = 0; ref_st == NULL && j < item->nb_stream_info; j++) {
6144 MOVFragmentStreamInfo * si;
6145 5 si = &item->stream_info[j];
6146
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (si->sidx_pts != AV_NOPTS_VALUE) {
6147 5 ref_st = c->fc->streams[j];
6148 5 ref_sc = ref_st->priv_data;
6149 5 break;
6150 }
6151 }
6152 }
6153
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 5 times.
10 if (ref_st) for (i = 0; i < c->fc->nb_streams; i++) {
6154 5 st = c->fc->streams[i];
6155 5 sc = st->priv_data;
6156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->has_sidx) {
6157 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6158 }
6159 }
6160
6161 5 c->frag_index.complete = 1;
6162 }
6163
6164 43 return 0;
6165 }
6166
6167 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6168 /* like the files created with Adobe Premiere 5.0, for samples see */
6169 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6170 269 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6171 {
6172 int err;
6173
6174
1/2
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
269 if (atom.size < 8)
6175 269 return 0; /* continue */
6176 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6177 avio_skip(pb, atom.size - 4);
6178 return 0;
6179 }
6180 atom.type = avio_rl32(pb);
6181 atom.size -= 8;
6182 if (atom.type != MKTAG('m','d','a','t')) {
6183 avio_skip(pb, atom.size);
6184 return 0;
6185 }
6186 err = mov_read_mdat(c, pb, atom);
6187 return err;
6188 }
6189
6190 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6191 {
6192 #if CONFIG_ZLIB
6193 FFIOContext ctx;
6194 uint8_t *cmov_data;
6195 uint8_t *moov_data; /* uncompressed data */
6196 long cmov_len, moov_len;
6197 3 int ret = -1;
6198
6199 3 avio_rb32(pb); /* dcom atom */
6200
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6201 return AVERROR_INVALIDDATA;
6202
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6203 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6204 return AVERROR_INVALIDDATA;
6205 }
6206 3 avio_rb32(pb); /* cmvd atom */
6207
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6208 return AVERROR_INVALIDDATA;
6209 3 moov_len = avio_rb32(pb); /* uncompressed size */
6210 3 cmov_len = atom.size - 6 * 4;
6211
6212 3 cmov_data = av_malloc(cmov_len);
6213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6214 return AVERROR(ENOMEM);
6215 3 moov_data = av_malloc(moov_len);
6216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6217 av_free(cmov_data);
6218 return AVERROR(ENOMEM);
6219 }
6220 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6222 goto free_and_return;
6223
6224 3 ret = AVERROR_INVALIDDATA;
6225
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)
6226 goto free_and_return;
6227 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6228 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6229 3 atom.type = MKTAG('m','o','o','v');
6230 3 atom.size = moov_len;
6231 3 ret = mov_read_default(c, &ctx.pub, atom);
6232 3 free_and_return:
6233 3 av_free(moov_data);
6234 3 av_free(cmov_data);
6235 3 return ret;
6236 #else
6237 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6238 return AVERROR(ENOSYS);
6239 #endif
6240 }
6241
6242 /* edit list atom */
6243 443 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6244 {
6245 MOVStreamContext *sc;
6246 int i, edit_count, version;
6247 int64_t elst_entry_size;
6248
6249
2/4
✓ Branch 0 taken 443 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 443 times.
443 if (c->fc->nb_streams < 1 || c->ignore_editlist)
6250 return 0;
6251 443 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6252
6253 443 version = avio_r8(pb); /* version */
6254 443 avio_rb24(pb); /* flags */
6255 443 edit_count = avio_rb32(pb); /* entries */
6256 443 atom.size -= 8;
6257
6258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 443 times.
443 elst_entry_size = version == 1 ? 20 : 12;
6259
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 442 times.
443 if (atom.size != edit_count * elst_entry_size) {
6260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6261 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6262 edit_count, atom.size + 8);
6263 return AVERROR_INVALIDDATA;
6264 } else {
6265 1 edit_count = atom.size / elst_entry_size;
6266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6267 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6268 }
6269 }
6270 }
6271
6272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 443 times.
443 if (!edit_count)
6273 return 0;
6274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 443 times.
443 if (sc->elst_data)
6275 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6276 443 av_free(sc->elst_data);
6277 443 sc->elst_count = 0;
6278 443 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 443 times.
443 if (!sc->elst_data)
6280 return AVERROR(ENOMEM);
6281
6282 443 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6283
4/6
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 443 times.
✓ Branch 2 taken 470 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 470 times.
✗ Branch 5 not taken.
913 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
6284 470 MOVElst *e = &sc->elst_data[i];
6285
6286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 if (version == 1) {
6287 e->duration = avio_rb64(pb);
6288 e->time = avio_rb64(pb);
6289 atom.size -= 16;
6290 } else {
6291 470 e->duration = avio_rb32(pb); /* segment duration */
6292 470 e->time = (int32_t)avio_rb32(pb); /* media time */
6293 470 atom.size -= 8;
6294 }
6295 470 e->rate = avio_rb32(pb) / 65536.0;
6296 470 atom.size -= 4;
6297 470 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6298 470 e->duration, e->time, e->rate);
6299
6300
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 466 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
470 if (e->time < 0 && e->time != -1 &&
6301 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6302 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6303 c->fc->nb_streams-1, i, e->time);
6304 return AVERROR_INVALIDDATA;
6305 }
6306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 if (e->duration < 0) {
6307 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list duration=%"PRId64"\n",
6308 c->fc->nb_streams-1, i, e->duration);
6309 return AVERROR_INVALIDDATA;
6310 }
6311 }
6312 443 sc->elst_count = i;
6313
6314 443 return 0;
6315 }
6316
6317 18 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6318 {
6319 MOVStreamContext *sc;
6320
6321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->fc->nb_streams < 1)
6322 return AVERROR_INVALIDDATA;
6323 18 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6324 18 sc->timecode_track = avio_rb32(pb);
6325 18 return 0;
6326 }
6327
6328 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6329 {
6330 AVStream *st;
6331 int version, color_range, color_primaries, color_trc, color_space;
6332
6333 if (c->fc->nb_streams < 1)
6334 return 0;
6335 st = c->fc->streams[c->fc->nb_streams - 1];
6336
6337 if (atom.size < 5) {
6338 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6339 return AVERROR_INVALIDDATA;
6340 }
6341
6342 version = avio_r8(pb);
6343 if (version != 1) {
6344 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6345 return 0;
6346 }
6347 avio_skip(pb, 3); /* flags */
6348
6349 avio_skip(pb, 2); /* profile + level */
6350 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6351 color_primaries = avio_r8(pb);
6352 color_trc = avio_r8(pb);
6353 color_space = avio_r8(pb);
6354 if (avio_rb16(pb)) /* codecIntializationDataSize */
6355 return AVERROR_INVALIDDATA;
6356
6357 if (!av_color_primaries_name(color_primaries))
6358 color_primaries = AVCOL_PRI_UNSPECIFIED;
6359 if (!av_color_transfer_name(color_trc))
6360 color_trc = AVCOL_TRC_UNSPECIFIED;
6361 if (!av_color_space_name(color_space))
6362 color_space = AVCOL_SPC_UNSPECIFIED;
6363
6364 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6365 st->codecpar->color_primaries = color_primaries;
6366 st->codecpar->color_trc = color_trc;
6367 st->codecpar->color_space = color_space;
6368
6369 return 0;
6370 }
6371
6372 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6373 {
6374 MOVStreamContext *sc;
6375 int i, version;
6376
6377 if (c->fc->nb_streams < 1)
6378 return AVERROR_INVALIDDATA;
6379
6380 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6381
6382 if (atom.size < 5) {
6383 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6384 return AVERROR_INVALIDDATA;
6385 }
6386
6387 version = avio_r8(pb);
6388 if (version) {
6389 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6390 return 0;
6391 }
6392 if (sc->mastering) {
6393 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6394 return 0;
6395 }
6396
6397 avio_skip(pb, 3); /* flags */
6398
6399 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6400 if (!sc->mastering)
6401 return AVERROR(ENOMEM);
6402
6403 for (i = 0; i < 3; i++) {
6404 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6405 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6406 }
6407 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6408 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6409
6410 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6411 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6412
6413 sc->mastering->has_primaries = 1;
6414 sc->mastering->has_luminance = 1;
6415
6416 return 0;
6417 }
6418
6419 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6420 {
6421 MOVStreamContext *sc;
6422 const int mapping[3] = {1, 2, 0};
6423 const int chroma_den = 50000;
6424 const int luma_den = 10000;
6425 int i;
6426
6427 if (c->fc->nb_streams < 1)
6428 return AVERROR_INVALIDDATA;
6429
6430 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6431
6432 if (atom.size < 24) {
6433 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6434 return AVERROR_INVALIDDATA;
6435 }
6436
6437 if (sc->mastering) {
6438 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6439 return 0;
6440 }
6441
6442 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6443 if (!sc->mastering)
6444 return AVERROR(ENOMEM);
6445
6446 for (i = 0; i < 3; i++) {
6447 const int j = mapping[i];
6448 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6449 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6450 }
6451 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6452 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6453
6454 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6455 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6456
6457 sc->mastering->has_luminance = 1;
6458 sc->mastering->has_primaries = 1;
6459
6460 return 0;
6461 }
6462
6463 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6464 {
6465 MOVStreamContext *sc;
6466 int version;
6467
6468 if (c->fc->nb_streams < 1)
6469 return AVERROR_INVALIDDATA;
6470
6471 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6472
6473 if (atom.size < 5) {
6474 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
6475 return AVERROR_INVALIDDATA;
6476 }
6477
6478 version = avio_r8(pb);
6479 if (version) {
6480 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
6481 return 0;
6482 }
6483 avio_skip(pb, 3); /* flags */
6484
6485 if (sc->coll){
6486 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
6487 return 0;
6488 }
6489
6490 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6491 if (!sc->coll)
6492 return AVERROR(ENOMEM);
6493
6494 sc->coll->MaxCLL = avio_rb16(pb);
6495 sc->coll->MaxFALL = avio_rb16(pb);
6496
6497 return 0;
6498 }
6499
6500 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6501 {
6502 MOVStreamContext *sc;
6503
6504 if (c->fc->nb_streams < 1)
6505 return AVERROR_INVALIDDATA;
6506
6507 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6508
6509 if (atom.size < 4) {
6510 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
6511 return AVERROR_INVALIDDATA;
6512 }
6513
6514 if (sc->coll){
6515 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
6516 return 0;
6517 }
6518
6519 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6520 if (!sc->coll)
6521 return AVERROR(ENOMEM);
6522
6523 sc->coll->MaxCLL = avio_rb16(pb);
6524 sc->coll->MaxFALL = avio_rb16(pb);
6525
6526 return 0;
6527 }
6528
6529 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6530 {
6531 MOVStreamContext *sc;
6532 4 const int illuminance_den = 10000;
6533 4 const int ambient_den = 50000;
6534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
6535 return AVERROR_INVALIDDATA;
6536 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
6538 av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
6539 return AVERROR_INVALIDDATA;
6540 }
6541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
6542 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
6543 return 0;
6544 }
6545 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
6546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
6547 return AVERROR(ENOMEM);
6548 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
6549 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
6550 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
6551 4 return 0;
6552 }
6553
6554 1 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6555 {
6556 AVStream *st;
6557 MOVStreamContext *sc;
6558 enum AVStereo3DType type;
6559 int mode;
6560
6561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6562 return 0;
6563
6564 1 st = c->fc->streams[c->fc->nb_streams - 1];
6565 1 sc = st->priv_data;
6566
6567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 5) {
6568 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
6569 return AVERROR_INVALIDDATA;
6570 }
6571
6572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sc->stereo3d)
6573 return AVERROR_INVALIDDATA;
6574
6575 1 avio_skip(pb, 4); /* version + flags */
6576
6577 1 mode = avio_r8(pb);
6578
1/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 switch (mode) {
6579 1 case 0:
6580 1 type = AV_STEREO3D_2D;
6581 1 break;
6582 case 1:
6583 type = AV_STEREO3D_TOPBOTTOM;
6584 break;
6585 case 2:
6586 type = AV_STEREO3D_SIDEBYSIDE;
6587 break;
6588 default:
6589 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
6590 return 0;
6591 }
6592
6593 1 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->stereo3d)
6595 return AVERROR(ENOMEM);
6596
6597 1 sc->stereo3d->type = type;
6598 1 return 0;
6599 }
6600
6601 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6602 {
6603 AVStream *st;
6604 MOVStreamContext *sc;
6605 int size, version, layout;
6606 int32_t yaw, pitch, roll;
6607 1 uint32_t l = 0, t = 0, r = 0, b = 0;
6608 1 uint32_t tag, padding = 0;
6609 enum AVSphericalProjection projection;
6610
6611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6612 return 0;
6613
6614 1 st = c->fc->streams[c->fc->nb_streams - 1];
6615 1 sc = st->priv_data;
6616
6617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
6618 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
6619 return AVERROR_INVALIDDATA;
6620 }
6621
6622 1 size = avio_rb32(pb);
6623
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)
6624 return AVERROR_INVALIDDATA;
6625
6626 1 tag = avio_rl32(pb);
6627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
6628 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
6629 return 0;
6630 }
6631 1 version = avio_r8(pb);
6632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6633 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6634 version);
6635 return 0;
6636 }
6637 1 avio_skip(pb, 3); /* flags */
6638 1 avio_skip(pb, size - 12); /* metadata_source */
6639
6640 1 size = avio_rb32(pb);
6641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6642 return AVERROR_INVALIDDATA;
6643
6644 1 tag = avio_rl32(pb);
6645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
6646 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
6647 return 0;
6648 }
6649
6650 1 size = avio_rb32(pb);
6651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6652 return AVERROR_INVALIDDATA;
6653
6654 1 tag = avio_rl32(pb);
6655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
6656 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
6657 return 0;
6658 }
6659 1 version = avio_r8(pb);
6660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6661 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6662 version);
6663 return 0;
6664 }
6665 1 avio_skip(pb, 3); /* flags */
6666
6667 /* 16.16 fixed point */
6668 1 yaw = avio_rb32(pb);
6669 1 pitch = avio_rb32(pb);
6670 1 roll = avio_rb32(pb);
6671
6672 1 size = avio_rb32(pb);
6673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6674 return AVERROR_INVALIDDATA;
6675
6676 1 tag = avio_rl32(pb);
6677 1 version = avio_r8(pb);
6678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6679 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6680 version);
6681 return 0;
6682 }
6683 1 avio_skip(pb, 3); /* flags */
6684
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
6685 case MKTAG('c','b','m','p'):
6686 layout = avio_rb32(pb);
6687 if (layout) {
6688 av_log(c->fc, AV_LOG_WARNING,
6689 "Unsupported cubemap layout %d\n", layout);
6690 return 0;
6691 }
6692 projection = AV_SPHERICAL_CUBEMAP;
6693 padding = avio_rb32(pb);
6694 break;
6695 1 case MKTAG('e','q','u','i'):
6696 1 t = avio_rb32(pb);
6697 1 b = avio_rb32(pb);
6698 1 l = avio_rb32(pb);
6699 1 r = avio_rb32(pb);
6700
6701
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) {
6702 av_log(c->fc, AV_LOG_ERROR,
6703 "Invalid bounding rectangle coordinates "
6704 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
6705 return AVERROR_INVALIDDATA;
6706 }
6707
6708
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)
6709 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
6710 else
6711 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6712 1 break;
6713 default:
6714 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
6715 return 0;
6716 }
6717
6718 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
6720 return AVERROR(ENOMEM);
6721
6722 1 sc->spherical->projection = projection;
6723
6724 1 sc->spherical->yaw = yaw;
6725 1 sc->spherical->pitch = pitch;
6726 1 sc->spherical->roll = roll;
6727
6728 1 sc->spherical->padding = padding;
6729
6730 1 sc->spherical->bound_left = l;
6731 1 sc->spherical->bound_top = t;
6732 1 sc->spherical->bound_right = r;
6733 1 sc->spherical->bound_bottom = b;
6734
6735 1 return 0;
6736 }
6737
6738 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6739 {
6740 AVStream *st;
6741 MOVStreamContext *sc;
6742 int size;
6743 uint32_t tag;
6744 enum AVSphericalProjection projection;
6745
6746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6747 return 0;
6748
6749 3 st = c->fc->streams[c->fc->nb_streams - 1];
6750 3 sc = st->priv_data;
6751
6752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 16) {
6753 av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
6754 return AVERROR_INVALIDDATA;
6755 }
6756
6757 3 size = avio_rb32(pb);
6758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 16) {
6759 av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
6760 return AVERROR_INVALIDDATA;
6761 }
6762
6763 3 tag = avio_rl32(pb);
6764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
6765 av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: 0x%08X\n", tag);
6766 return AVERROR_INVALIDDATA;
6767 }
6768
6769 3 avio_skip(pb, 1); // version
6770 3 avio_skip(pb, 3); // flags
6771
6772 3 tag = avio_rl32(pb);
6773
1/5
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
3 switch (tag) {
6774 3 case MKTAG('r','e','c','t'):
6775 3 projection = AV_SPHERICAL_RECTILINEAR;
6776 3 break;
6777 case MKTAG('e','q','u','i'):
6778 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6779 break;
6780 case MKTAG('h','e','q','u'):
6781 projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
6782 break;
6783 case MKTAG('f','i','s','h'):
6784 projection = AV_SPHERICAL_FISHEYE;
6785 break;
6786 default:
6787 av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: 0x%08X\n", tag);
6788 return AVERROR_INVALIDDATA;
6789 }
6790
6791 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
6793 return AVERROR(ENOMEM);
6794
6795 3 sc->spherical->projection = projection;
6796
6797 3 return 0;
6798 }
6799
6800 3 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6801 {
6802 AVStream *st;
6803 MOVStreamContext *sc;
6804 3 int size, flags = 0;
6805 int64_t remaining;
6806 3 uint32_t tag, baseline = 0;
6807 3 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
6808 3 enum AVStereo3DType type = AV_STEREO3D_2D;
6809 3 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
6810 3 AVRational horizontal_disparity_adjustment = { 0, 1 };
6811
6812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6813 return 0;
6814
6815 3 st = c->fc->streams[c->fc->nb_streams - 1];
6816 3 sc = st->priv_data;
6817
6818 3 remaining = atom.size;
6819
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 while (remaining > 0) {
6820 9 size = avio_rb32(pb);
6821
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
9 if (size < 8 || size > remaining ) {
6822 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
6823 return AVERROR_INVALIDDATA;
6824 }
6825
6826 9 tag = avio_rl32(pb);
6827
3/5
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
9 switch (tag) {
6828 3 case MKTAG('s','t','r','i'): {
6829 int has_right, has_left;
6830 uint8_t tmp;
6831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 13) {
6832 av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
6833 return AVERROR_INVALIDDATA;
6834 }
6835 3 avio_skip(pb, 1); // version
6836 3 avio_skip(pb, 3); // flags
6837
6838 3 tmp = avio_r8(pb);
6839
6840 // eye_views_reversed
6841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tmp & 8) {
6842 flags |= AV_STEREO3D_FLAG_INVERT;
6843 }
6844 // has_additional_views
6845 3 if (tmp & 4) {
6846 // skip...
6847 }
6848
6849 3 has_right = tmp & 2; // has_right_eye_view
6850 3 has_left = tmp & 1; // has_left_eye_view
6851
6852
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if (has_left && has_right)
6853 3 view = AV_STEREO3D_VIEW_PACKED;
6854 else if (has_left)
6855 view = AV_STEREO3D_VIEW_LEFT;
6856 else if (has_right)
6857 view = AV_STEREO3D_VIEW_RIGHT;
6858
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if (has_left || has_right)
6859 3 type = AV_STEREO3D_UNSPEC;
6860
6861 3 break;
6862 }
6863 case MKTAG('h','e','r','o'): {
6864 int tmp;
6865 if (size != 13) {
6866 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
6867 return AVERROR_INVALIDDATA;
6868 }
6869 avio_skip(pb, 1); // version
6870 avio_skip(pb, 3); // flags
6871
6872 tmp = avio_r8(pb);
6873 if (tmp == 0)
6874 primary_eye = AV_PRIMARY_EYE_NONE;
6875 else if (tmp == 1)
6876 primary_eye = AV_PRIMARY_EYE_LEFT;
6877 else if (tmp == 2)
6878 primary_eye = AV_PRIMARY_EYE_RIGHT;
6879 else
6880 av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
6881
6882 break;
6883 }
6884 3 case MKTAG('c','a','m','s'): {
6885 uint32_t subtag;
6886 int subsize;
6887
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
6888 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
6889 return AVERROR_INVALIDDATA;
6890 }
6891
6892 3 subsize = avio_rb32(pb);
6893
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
6894 av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
6895 return AVERROR_INVALIDDATA;
6896 }
6897
6898 3 subtag = avio_rl32(pb);
6899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
6900 av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got 0x%08X\n", subtag);
6901 return AVERROR_INVALIDDATA;
6902 }
6903
6904 3 avio_skip(pb, 1); // version
6905 3 avio_skip(pb, 3); // flags
6906
6907 3 baseline = avio_rb32(pb);
6908
6909 3 break;
6910 }
6911 3 case MKTAG('c','m','f','y'): {
6912 uint32_t subtag;
6913 int subsize;
6914 int32_t adjustment;
6915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
6916 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
6917 return AVERROR_INVALIDDATA;
6918 }
6919
6920 3 subsize = avio_rb32(pb);
6921
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
6922 av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
6923 return AVERROR_INVALIDDATA;
6924 }
6925
6926 3 subtag = avio_rl32(pb);
6927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
6928 av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got 0x%08X\n", subtag);
6929 return AVERROR_INVALIDDATA;
6930 }
6931
6932 3 avio_skip(pb, 1); // version
6933 3 avio_skip(pb, 3); // flags
6934
6935 3 adjustment = (int32_t) avio_rb32(pb);
6936
6937 3 horizontal_disparity_adjustment.num = (int) adjustment;
6938 3 horizontal_disparity_adjustment.den = 10000;
6939
6940 3 break;
6941 }
6942 default:
6943 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: 0x%08X\n", tag);
6944 avio_skip(pb, size - 8);
6945 break;
6946 }
6947 9 remaining -= size;
6948 }
6949
6950
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
6951 av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
6952 return AVERROR_INVALIDDATA;
6953 }
6954
6955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (type == AV_STEREO3D_2D)
6956 return 0;
6957
6958
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->stereo3d) {
6959 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
6961 return AVERROR(ENOMEM);
6962 }
6963
6964 3 sc->stereo3d->flags = flags;
6965 3 sc->stereo3d->type = type;
6966 3 sc->stereo3d->view = view;
6967 3 sc->stereo3d->primary_eye = primary_eye;
6968 3 sc->stereo3d->baseline = baseline;
6969 3 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
6970
6971 3 return 0;
6972 }
6973
6974 3 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6975 {
6976 int size;
6977 int64_t remaining;
6978 uint32_t tag;
6979
6980
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6981 return 0;
6982
6983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8) {
6984 av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
6985 return AVERROR_INVALIDDATA;
6986 }
6987
6988 3 remaining = atom.size;
6989
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 while (remaining > 0) {
6990 6 size = avio_rb32(pb);
6991
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (size < 8 || size > remaining ) {
6992 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
6993 return AVERROR_INVALIDDATA;
6994 }
6995
6996 6 tag = avio_rl32(pb);
6997
2/3
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 switch (tag) {
6998 3 case MKTAG('p','r','o','j'): {
6999 3 MOVAtom proj = { tag, size - 8 };
7000 3 int ret = mov_read_vexu_proj(c, pb, proj);
7001
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7002 return ret;
7003 3 break;
7004 }
7005 3 case MKTAG('e','y','e','s'): {
7006 3 MOVAtom eyes = { tag, size - 8 };
7007 3 int ret = mov_read_eyes(c, pb, eyes);
7008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7009 return ret;
7010 3 break;
7011 }
7012 default:
7013 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: 0x%08X\n", tag);
7014 avio_skip(pb, size - 8);
7015 break;
7016 }
7017 6 remaining -= size;
7018 }
7019
7020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7021 av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7022 return AVERROR_INVALIDDATA;
7023 }
7024
7025 3 return 0;
7026 }
7027
7028 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7029 {
7030 AVStream *st;
7031 MOVStreamContext *sc;
7032
7033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7034 return 0;
7035
7036 3 st = c->fc->streams[c->fc->nb_streams - 1];
7037 3 sc = st->priv_data;
7038
7039
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7040 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7041 return AVERROR_INVALIDDATA;
7042 }
7043
7044
7045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7046 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7047 if (!sc->stereo3d)
7048 return AVERROR(ENOMEM);
7049 }
7050
7051 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7052 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7053
7054 3 return 0;
7055 }
7056
7057 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7058 {
7059 int ret = 0;
7060 uint8_t *buffer = av_malloc(len + 1);
7061 const char *val;
7062
7063 if (!buffer)
7064 return AVERROR(ENOMEM);
7065 buffer[len] = '\0';
7066
7067 ret = ffio_read_size(pb, buffer, len);
7068 if (ret < 0)
7069 goto out;
7070
7071 /* Check for mandatory keys and values, try to support XML as best-effort */
7072 if (!sc->spherical &&
7073 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7074 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7075 av_stristr(val, "true") &&
7076 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7077 av_stristr(val, "true") &&
7078 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7079 av_stristr(val, "equirectangular")) {
7080 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7081 if (!sc->spherical)
7082 goto out;
7083
7084 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7085
7086 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7087 enum AVStereo3DType mode;
7088
7089 if (av_stristr(buffer, "left-right"))
7090 mode = AV_STEREO3D_SIDEBYSIDE;
7091 else if (av_stristr(buffer, "top-bottom"))
7092 mode = AV_STEREO3D_TOPBOTTOM;
7093 else
7094 mode = AV_STEREO3D_2D;
7095
7096 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7097 if (!sc->stereo3d)
7098 goto out;
7099
7100 sc->stereo3d->type = mode;
7101 }
7102
7103 /* orientation */
7104 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7105 if (val)
7106 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7107 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7108 if (val)
7109 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7110 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7111 if (val)
7112 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7113 }
7114
7115 out:
7116 av_free(buffer);
7117 return ret;
7118 }
7119
7120 17 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7121 {
7122 AVStream *st;
7123 MOVStreamContext *sc;
7124 int64_t ret;
7125 AVUUID uuid;
7126 static const AVUUID uuid_isml_manifest = {
7127 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7128 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7129 };
7130 static const AVUUID uuid_xmp = {
7131 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7132 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7133 };
7134 static const AVUUID uuid_spherical = {
7135 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7136 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7137 };
7138
7139
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
17 if (atom.size < AV_UUID_LEN || atom.size >= FFMIN(INT_MAX, SIZE_MAX))
7140 return AVERROR_INVALIDDATA;
7141
7142
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 14 times.
17 if (c->fc->nb_streams < 1)
7143 3 return 0;
7144 14 st = c->fc->streams[c->fc->nb_streams - 1];
7145 14 sc = st->priv_data;
7146
7147 14 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0)
7149 return ret;
7150
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7151 uint8_t *buffer, *ptr;
7152 char *endptr;
7153 size_t len = atom.size - AV_UUID_LEN;
7154
7155 if (len < 4) {
7156 return AVERROR_INVALIDDATA;
7157 }
7158 ret = avio_skip(pb, 4); // zeroes
7159 len -= 4;
7160
7161 buffer = av_mallocz(len + 1);
7162 if (!buffer) {
7163 return AVERROR(ENOMEM);
7164 }
7165 ret = ffio_read_size(pb, buffer, len);
7166 if (ret < 0) {
7167 av_free(buffer);
7168 return ret;
7169 }
7170
7171 ptr = buffer;
7172 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7173 ptr += sizeof("systemBitrate=\"") - 1;
7174 c->bitrates_count++;
7175 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7176 if (!c->bitrates) {
7177 c->bitrates_count = 0;
7178 av_free(buffer);
7179 return AVERROR(ENOMEM);
7180 }
7181 errno = 0;
7182 ret = strtol(ptr, &endptr, 10);
7183 if (ret < 0 || errno || *endptr != '"') {
7184 c->bitrates[c->bitrates_count - 1] = 0;
7185 } else {
7186 c->bitrates[c->bitrates_count - 1] = ret;
7187 }
7188 }
7189
7190 av_free(buffer);
7191
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7192 uint8_t *buffer;
7193 size_t len = atom.size - AV_UUID_LEN;
7194 if (c->export_xmp) {
7195 buffer = av_mallocz(len + 1);
7196 if (!buffer) {
7197 return AVERROR(ENOMEM);
7198 }
7199 ret = ffio_read_size(pb, buffer, len);
7200 if (ret < 0) {
7201 av_free(buffer);
7202 return ret;
7203 }
7204 buffer[len] = '\0';
7205 av_dict_set(&c->fc->metadata, "xmp",
7206 buffer, AV_DICT_DONT_STRDUP_VAL);
7207 } else {
7208 // skip all uuid atom, which makes it fast for long uuid-xmp file
7209 ret = avio_skip(pb, len);
7210 if (ret < 0)
7211 return ret;
7212 }
7213
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7214 size_t len = atom.size - AV_UUID_LEN;
7215 ret = mov_parse_uuid_spherical(sc, pb, len);
7216 if (ret < 0)
7217 return ret;
7218 if (!sc->spherical)
7219 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7220 }
7221
7222 14 return 0;
7223 }
7224
7225 191 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7226 {
7227 int ret;
7228 uint8_t content[16];
7229
7230
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 98 times.
191 if (atom.size < 8)
7231 93 return 0;
7232
7233 98 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (ret < 0)
7235 return ret;
7236
7237
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 55 times.
98 if ( !c->found_moov
7238
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 23 times.
43 && !c->found_mdat
7239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 && !memcmp(content, "Anevia\x1A\x1A", 8)
7240 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7241 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7242 }
7243
7244 98 return 0;
7245 }
7246
7247 35 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7248 {
7249 35 uint32_t format = avio_rl32(pb);
7250 MOVStreamContext *sc;
7251 enum AVCodecID id;
7252 AVStream *st;
7253
7254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (c->fc->nb_streams < 1)
7255 return 0;
7256 35 st = c->fc->streams[c->fc->nb_streams - 1];
7257 35 sc = st->priv_data;
7258
7259
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 32 times.
35 switch (sc->format)
7260 {
7261 3 case MKTAG('e','n','c','v'): // encrypted video
7262 case MKTAG('e','n','c','a'): // encrypted audio
7263 3 id = mov_codec_id(st, format);
7264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7265 st->codecpar->codec_id != id) {
7266 av_log(c->fc, AV_LOG_WARNING,
7267 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7268 (char*)&format, st->codecpar->codec_id);
7269 break;
7270 }
7271
7272 3 st->codecpar->codec_id = id;
7273 3 sc->format = format;
7274 3 break;
7275
7276 32 default:
7277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (format != sc->format) {
7278 av_log(c->fc, AV_LOG_WARNING,
7279 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7280 (char*)&format, (char*)&sc->format);
7281 }
7282 32 break;
7283 }
7284
7285 35 return 0;
7286 }
7287
7288 /**
7289 * Gets the current encryption info and associated current stream context. If
7290 * we are parsing a track fragment, this will return the specific encryption
7291 * info for this fragment; otherwise this will return the global encryption
7292 * info for the current stream.
7293 */
7294 6 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7295 {
7296 MOVFragmentStreamInfo *frag_stream_info;
7297 AVStream *st;
7298 int i;
7299
7300 6 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7301
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (frag_stream_info) {
7302
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 for (i = 0; i < c->fc->nb_streams; i++) {
7303 3 *sc = c->fc->streams[i]->priv_data;
7304
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if ((*sc)->id == frag_stream_info->id) {
7305 3 st = c->fc->streams[i];
7306 3 break;
7307 }
7308 }
7309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (i == c->fc->nb_streams)
7310 return 0;
7311 3 *sc = st->priv_data;
7312
7313
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!frag_stream_info->encryption_index) {
7314 // If this stream isn't encrypted, don't create the index.
7315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!(*sc)->cenc.default_encrypted_sample)
7316 return 0;
7317 1 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!frag_stream_info->encryption_index)
7319 return AVERROR(ENOMEM);
7320 }
7321 3 *encryption_index = frag_stream_info->encryption_index;
7322 3 return 1;
7323 } else {
7324 // No current track fragment, using stream level encryption info.
7325
7326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7327 return 0;
7328 3 st = c->fc->streams[c->fc->nb_streams - 1];
7329 3 *sc = st->priv_data;
7330
7331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!(*sc)->cenc.encryption_index) {
7332 // If this stream isn't encrypted, don't create the index.
7333 if (!(*sc)->cenc.default_encrypted_sample)
7334 return 0;
7335 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7336 if (!(*sc)->cenc.encryption_index)
7337 return AVERROR(ENOMEM);
7338 }
7339
7340 3 *encryption_index = (*sc)->cenc.encryption_index;
7341 3 return 1;
7342 }
7343 }
7344
7345 72 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7346 {
7347 int i, ret;
7348 unsigned int subsample_count;
7349 AVSubsampleEncryptionInfo *subsamples;
7350
7351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!sc->cenc.default_encrypted_sample) {
7352 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7353 return AVERROR_INVALIDDATA;
7354 }
7355
7356
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
72 if (sc->cenc.per_sample_iv_size || use_subsamples) {
7357 72 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!*sample)
7359 return AVERROR(ENOMEM);
7360 } else
7361 *sample = NULL;
7362
7363
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (sc->cenc.per_sample_iv_size != 0) {
7364
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
72 if ((ret = ffio_read_size(pb, (*sample)->iv, sc->cenc.per_sample_iv_size)) < 0) {
7365 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
7366 av_encryption_info_free(*sample);
7367 *sample = NULL;
7368 return ret;
7369 }
7370 }
7371
7372
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (use_subsamples) {
7373 72 subsample_count = avio_rb16(pb);
7374 72 av_free((*sample)->subsamples);
7375 72 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
7376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!(*sample)->subsamples) {
7377 av_encryption_info_free(*sample);
7378 *sample = NULL;
7379 return AVERROR(ENOMEM);
7380 }
7381
7382
3/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
144 for (i = 0; i < subsample_count && !pb->eof_reached; i++) {
7383 72 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
7384 72 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
7385 }
7386
7387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (pb->eof_reached) {
7388 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
7389 av_encryption_info_free(*sample);
7390 *sample = NULL;
7391 return AVERROR_INVALIDDATA;
7392 }
7393 72 (*sample)->subsample_count = subsample_count;
7394 }
7395
7396 72 return 0;
7397 }
7398
7399 2 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7400 {
7401 AVEncryptionInfo **encrypted_samples;
7402 MOVEncryptionIndex *encryption_index;
7403 MOVStreamContext *sc;
7404 int use_subsamples, ret;
7405 2 unsigned int sample_count, i, alloc_size = 0;
7406
7407 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7409 return ret;
7410
7411
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7412 // This can happen if we have both saio/saiz and senc atoms.
7413 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
7414 1 return 0;
7415 }
7416
7417 1 avio_r8(pb); /* version */
7418 1 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
7419
7420 1 sample_count = avio_rb32(pb);
7421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7422 return AVERROR(ENOMEM);
7423
7424
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1 times.
49 for (i = 0; i < sample_count; i++) {
7425 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7426 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7427 min_samples * sizeof(*encrypted_samples));
7428
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (encrypted_samples) {
7429 48 encryption_index->encrypted_samples = encrypted_samples;
7430
7431 48 ret = mov_read_sample_encryption_info(
7432 48 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
7433 } else {
7434 ret = AVERROR(ENOMEM);
7435 }
7436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (pb->eof_reached) {
7437 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
7438 if (ret >= 0)
7439 av_encryption_info_free(encryption_index->encrypted_samples[i]);
7440 ret = AVERROR_INVALIDDATA;
7441 }
7442
7443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0) {
7444 for (; i > 0; i--)
7445 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7446 av_freep(&encryption_index->encrypted_samples);
7447 return ret;
7448 }
7449 }
7450 1 encryption_index->nb_encrypted_samples = sample_count;
7451
7452 1 return 0;
7453 }
7454
7455 1 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
7456 {
7457 AVEncryptionInfo **sample, **encrypted_samples;
7458 int64_t prev_pos;
7459 size_t sample_count, sample_info_size, i;
7460 1 int ret = 0;
7461 1 unsigned int alloc_size = 0;
7462
7463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->nb_encrypted_samples)
7464 return 0;
7465 1 sample_count = encryption_index->auxiliary_info_sample_count;
7466
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count != 1) {
7467 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
7468 return AVERROR_PATCHWELCOME;
7469 }
7470
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7471 return AVERROR(ENOMEM);
7472
7473 1 prev_pos = avio_tell(pb);
7474
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
7475
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 avio_seek(pb, encryption_index->auxiliary_offsets[0], SEEK_SET) != encryption_index->auxiliary_offsets[0]) {
7476 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
7477 goto finish;
7478 }
7479
7480
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
25 for (i = 0; i < sample_count && !pb->eof_reached; i++) {
7481 24 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7482 24 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7483 min_samples * sizeof(*encrypted_samples));
7484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!encrypted_samples) {
7485 ret = AVERROR(ENOMEM);
7486 goto finish;
7487 }
7488 24 encryption_index->encrypted_samples = encrypted_samples;
7489
7490 24 sample = &encryption_index->encrypted_samples[i];
7491 48 sample_info_size = encryption_index->auxiliary_info_default_size
7492 24 ? encryption_index->auxiliary_info_default_size
7493
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 : encryption_index->auxiliary_info_sizes[i];
7494
7495 24 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
7496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (ret < 0)
7497 goto finish;
7498 }
7499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7500 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
7501 ret = AVERROR_INVALIDDATA;
7502 } else {
7503 1 encryption_index->nb_encrypted_samples = sample_count;
7504 }
7505
7506 1 finish:
7507 1 avio_seek(pb, prev_pos, SEEK_SET);
7508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
7509 for (; i > 0; i--) {
7510 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7511 }
7512 av_freep(&encryption_index->encrypted_samples);
7513 }
7514 1 return ret;
7515 }
7516
7517 2 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7518 {
7519 MOVEncryptionIndex *encryption_index;
7520 MOVStreamContext *sc;
7521 int ret;
7522 unsigned int sample_count, aux_info_type, aux_info_param;
7523
7524 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7526 return ret;
7527
7528
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7529 // This can happen if we have both saio/saiz and senc atoms.
7530 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
7531 1 return 0;
7532 }
7533
7534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_sample_count) {
7535 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
7536 return AVERROR_INVALIDDATA;
7537 }
7538
7539 1 avio_r8(pb); /* version */
7540
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7541 aux_info_type = avio_rb32(pb);
7542 aux_info_param = avio_rb32(pb);
7543 if (sc->cenc.default_encrypted_sample) {
7544 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7545 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
7546 return 0;
7547 }
7548 if (aux_info_param != 0) {
7549 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
7550 return 0;
7551 }
7552 } else {
7553 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7554 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7555 aux_info_type == MKBETAG('c','e','n','s') ||
7556 aux_info_type == MKBETAG('c','b','c','1') ||
7557 aux_info_type == MKBETAG('c','b','c','s')) &&
7558 aux_info_param == 0) {
7559 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
7560 return AVERROR_INVALIDDATA;
7561 } else {
7562 return 0;
7563 }
7564 }
7565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7566 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7567 return 0;
7568 }
7569
7570 1 encryption_index->auxiliary_info_default_size = avio_r8(pb);
7571 1 sample_count = avio_rb32(pb);
7572
7573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_default_size == 0) {
7574 if (sample_count == 0)
7575 return AVERROR_INVALIDDATA;
7576
7577 encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
7578 if (!encryption_index->auxiliary_info_sizes)
7579 return AVERROR(ENOMEM);
7580
7581 ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
7582 if (ret != sample_count) {
7583 av_freep(&encryption_index->auxiliary_info_sizes);
7584
7585 if (ret >= 0)
7586 ret = AVERROR_INVALIDDATA;
7587 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
7588 av_err2str(ret));
7589 return ret;
7590 }
7591 }
7592 1 encryption_index->auxiliary_info_sample_count = sample_count;
7593
7594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7595 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7596 }
7597
7598 1 return 0;
7599 }
7600
7601 2 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7602 {
7603 uint64_t *auxiliary_offsets;
7604 MOVEncryptionIndex *encryption_index;
7605 MOVStreamContext *sc;
7606 int i, ret;
7607 unsigned int version, entry_count, aux_info_type, aux_info_param;
7608 2 unsigned int alloc_size = 0;
7609
7610 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7612 return ret;
7613
7614
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7615 // This can happen if we have both saio/saiz and senc atoms.
7616 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
7617 1 return 0;
7618 }
7619
7620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7621 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
7622 return AVERROR_INVALIDDATA;
7623 }
7624
7625 1 version = avio_r8(pb); /* version */
7626
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7627 aux_info_type = avio_rb32(pb);
7628 aux_info_param = avio_rb32(pb);
7629 if (sc->cenc.default_encrypted_sample) {
7630 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7631 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
7632 return 0;
7633 }
7634 if (aux_info_param != 0) {
7635 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
7636 return 0;
7637 }
7638 } else {
7639 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7640 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7641 aux_info_type == MKBETAG('c','e','n','s') ||
7642 aux_info_type == MKBETAG('c','b','c','1') ||
7643 aux_info_type == MKBETAG('c','b','c','s')) &&
7644 aux_info_param == 0) {
7645 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
7646 return AVERROR_INVALIDDATA;
7647 } else {
7648 return 0;
7649 }
7650 }
7651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7652 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7653 return 0;
7654 }
7655
7656 1 entry_count = avio_rb32(pb);
7657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
7658 return AVERROR(ENOMEM);
7659
7660
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 for (i = 0; i < entry_count && !pb->eof_reached; i++) {
7661
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 unsigned int min_offsets = FFMIN(FFMAX(i + 1, 1024), entry_count);
7662 1 auxiliary_offsets = av_fast_realloc(
7663 1 encryption_index->auxiliary_offsets, &alloc_size,
7664 min_offsets * sizeof(*auxiliary_offsets));
7665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!auxiliary_offsets) {
7666 av_freep(&encryption_index->auxiliary_offsets);
7667 return AVERROR(ENOMEM);
7668 }
7669 1 encryption_index->auxiliary_offsets = auxiliary_offsets;
7670
7671
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (version == 0) {
7672 1 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
7673 } else {
7674 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
7675 }
7676
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (c->frag_index.current >= 0) {
7677 1 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
7678 }
7679 }
7680
7681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7682 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
7683 av_freep(&encryption_index->auxiliary_offsets);
7684 return AVERROR_INVALIDDATA;
7685 }
7686
7687 1 encryption_index->auxiliary_offsets_count = entry_count;
7688
7689
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (encryption_index->auxiliary_info_sample_count) {
7690 1 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7691 }
7692
7693 return 0;
7694 }
7695
7696 2 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7697 {
7698 AVEncryptionInitInfo *info, *old_init_info;
7699 uint8_t **key_ids;
7700 AVStream *st;
7701 const AVPacketSideData *old_side_data;
7702 uint8_t *side_data, *extra_data;
7703 size_t side_data_size;
7704 2 int ret = 0;
7705 2 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
7706
7707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
7708 return 0;
7709 2 st = c->fc->streams[c->fc->nb_streams-1];
7710
7711 2 version = avio_r8(pb); /* version */
7712 2 avio_rb24(pb); /* flags */
7713
7714 2 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
7715 /* key_id_size */ 16, /* data_size */ 0);
7716
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info)
7717 return AVERROR(ENOMEM);
7718
7719
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
7720 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
7721 goto finish;
7722 }
7723
7724
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version > 0) {
7725 2 kid_count = avio_rb32(pb);
7726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
7727 ret = AVERROR(ENOMEM);
7728 goto finish;
7729 }
7730
7731
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 for (unsigned int i = 0; i < kid_count && !pb->eof_reached; i++) {
7732 2 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
7733 2 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
7734 min_kid_count * sizeof(*key_ids));
7735
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!key_ids) {
7736 ret = AVERROR(ENOMEM);
7737 goto finish;
7738 }
7739 2 info->key_ids = key_ids;
7740
7741 2 info->key_ids[i] = av_mallocz(16);
7742
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info->key_ids[i]) {
7743 ret = AVERROR(ENOMEM);
7744 goto finish;
7745 }
7746 2 info->num_key_ids = i + 1;
7747
7748
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
7749 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
7750 goto finish;
7751 }
7752 }
7753
7754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
7755 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
7756 ret = AVERROR_INVALIDDATA;
7757 goto finish;
7758 }
7759 }
7760
7761 2 extra_data_size = avio_rb32(pb);
7762 2 extra_data = av_malloc(extra_data_size);
7763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!extra_data) {
7764 ret = AVERROR(ENOMEM);
7765 goto finish;
7766 }
7767 2 ret = avio_read(pb, extra_data, extra_data_size);
7768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != extra_data_size) {
7769 av_free(extra_data);
7770
7771 if (ret >= 0)
7772 ret = AVERROR_INVALIDDATA;
7773 goto finish;
7774 }
7775
7776 2 av_freep(&info->data); // malloc(0) may still allocate something.
7777 2 info->data = extra_data;
7778 2 info->data_size = extra_data_size;
7779
7780 // If there is existing initialization data, append to the list.
7781 2 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
7782 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
7783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (old_side_data) {
7784 old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
7785 if (old_init_info) {
7786 // Append to the end of the list.
7787 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
7788 if (!cur->next) {
7789 cur->next = info;
7790 break;
7791 }
7792 }
7793 info = old_init_info;
7794 } else {
7795 // Assume existing side-data will be valid, so the only error we could get is OOM.
7796 ret = AVERROR(ENOMEM);
7797 goto finish;
7798 }
7799 }
7800
7801 2 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
7802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!side_data) {
7803 ret = AVERROR(ENOMEM);
7804 goto finish;
7805 }
7806
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
7807 2 &st->codecpar->nb_coded_side_data,
7808 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
7809 side_data, side_data_size, 0))
7810 av_free(side_data);
7811
7812 2 finish:
7813 2 av_encryption_init_info_free(info);
7814 2 return ret;
7815 }
7816
7817 3 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7818 {
7819 AVStream *st;
7820 MOVStreamContext *sc;
7821
7822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7823 return 0;
7824 3 st = c->fc->streams[c->fc->nb_streams-1];
7825 3 sc = st->priv_data;
7826
7827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7828 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
7829 return AVERROR_PATCHWELCOME;
7830 }
7831
7832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8)
7833 return AVERROR_INVALIDDATA;
7834
7835 3 avio_rb32(pb); /* version and flags */
7836
7837
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->cenc.default_encrypted_sample) {
7838 3 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7840 return AVERROR(ENOMEM);
7841 }
7842 }
7843
7844 3 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
7845 3 return 0;
7846 }
7847
7848 3 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7849 {
7850 AVStream *st;
7851 MOVStreamContext *sc;
7852 unsigned int version, pattern, is_protected, iv_size;
7853
7854
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7855 return 0;
7856 3 st = c->fc->streams[c->fc->nb_streams-1];
7857 3 sc = st->priv_data;
7858
7859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7860 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
7861 return AVERROR_PATCHWELCOME;
7862 }
7863
7864
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7865 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7866 if (!sc->cenc.default_encrypted_sample) {
7867 return AVERROR(ENOMEM);
7868 }
7869 }
7870
7871
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 20)
7872 return AVERROR_INVALIDDATA;
7873
7874 3 version = avio_r8(pb); /* version */
7875 3 avio_rb24(pb); /* flags */
7876
7877 3 avio_r8(pb); /* reserved */
7878 3 pattern = avio_r8(pb);
7879
7880
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (version > 0) {
7881 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
7882 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
7883 }
7884
7885 3 is_protected = avio_r8(pb);
7886
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if (is_protected && !sc->cenc.encryption_index) {
7887 // The whole stream should be by-default encrypted.
7888 3 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
7889
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.encryption_index)
7890 return AVERROR(ENOMEM);
7891 }
7892 3 sc->cenc.per_sample_iv_size = avio_r8(pb);
7893
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
3 if (sc->cenc.per_sample_iv_size != 0 && sc->cenc.per_sample_iv_size != 8 &&
7894 sc->cenc.per_sample_iv_size != 16) {
7895 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
7896 return AVERROR_INVALIDDATA;
7897 }
7898
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_read(pb, sc->cenc.default_encrypted_sample->key_id, 16) != 16) {
7899 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
7900 return AVERROR_INVALIDDATA;
7901 }
7902
7903
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
3 if (is_protected && !sc->cenc.per_sample_iv_size) {
7904 1 iv_size = avio_r8(pb);
7905
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (iv_size != 8 && iv_size != 16) {
7906 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
7907 return AVERROR_INVALIDDATA;
7908 }
7909
7910
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_read(pb, sc->cenc.default_encrypted_sample->iv, iv_size) != iv_size) {
7911 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
7912 return AVERROR_INVALIDDATA;
7913 }
7914 }
7915
7916 3 return 0;
7917 }
7918
7919 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7920 {
7921 AVStream *st;
7922 int last, type, size, ret;
7923 uint8_t buf[4];
7924
7925 if (c->fc->nb_streams < 1)
7926 return 0;
7927 st = c->fc->streams[c->fc->nb_streams-1];
7928
7929 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
7930 return AVERROR_INVALIDDATA;
7931
7932 /* Check FlacSpecificBox version. */
7933 if (avio_r8(pb) != 0)
7934 return AVERROR_INVALIDDATA;
7935
7936 avio_rb24(pb); /* Flags */
7937
7938 if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
7939 av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
7940 return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
7941 }
7942 flac_parse_block_header(buf, &last, &type, &size);
7943
7944 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
7945 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
7946 return AVERROR_INVALIDDATA;
7947 }
7948
7949 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
7950 if (ret < 0)
7951 return ret;
7952
7953 if (!last)
7954 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
7955
7956 return 0;
7957 }
7958
7959 146 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
7960 {
7961 int i, ret;
7962 int bytes_of_protected_data;
7963
7964
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 143 times.
146 if (!sc->cenc.aes_ctr) {
7965 /* initialize the cipher */
7966 3 sc->cenc.aes_ctr = av_aes_ctr_alloc();
7967
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.aes_ctr) {
7968 return AVERROR(ENOMEM);
7969 }
7970
7971 3 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
7972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
7973 return ret;
7974 }
7975 }
7976
7977 146 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
7978
7979
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!sample->subsample_count) {
7980 /* decrypt the whole packet */
7981 48 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
7982 48 return 0;
7983 }
7984
7985
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 98 times.
196 for (i = 0; i < sample->subsample_count; i++) {
7986
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
7987 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
7988 return AVERROR_INVALIDDATA;
7989 }
7990
7991 /* skip the clear bytes */
7992 98 input += sample->subsamples[i].bytes_of_clear_data;
7993 98 size -= sample->subsamples[i].bytes_of_clear_data;
7994
7995 /* decrypt the encrypted bytes */
7996
7997 98 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
7998 98 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
7999
8000 98 input += bytes_of_protected_data;
8001 98 size -= bytes_of_protected_data;
8002 }
8003
8004
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (size > 0) {
8005 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8006 return AVERROR_INVALIDDATA;
8007 }
8008
8009 98 return 0;
8010 }
8011
8012 static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8013 {
8014 int i, ret;
8015 int num_of_encrypted_blocks;
8016 uint8_t iv[16];
8017
8018 if (!sc->cenc.aes_ctx) {
8019 /* initialize the cipher */
8020 sc->cenc.aes_ctx = av_aes_alloc();
8021 if (!sc->cenc.aes_ctx) {
8022 return AVERROR(ENOMEM);
8023 }
8024
8025 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8026 if (ret < 0) {
8027 return ret;
8028 }
8029 }
8030
8031 memcpy(iv, sample->iv, 16);
8032
8033 /* whole-block full sample encryption */
8034 if (!sample->subsample_count) {
8035 /* decrypt the whole packet */
8036 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8037 return 0;
8038 }
8039
8040 for (i = 0; i < sample->subsample_count; i++) {
8041 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8042 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8043 return AVERROR_INVALIDDATA;
8044 }
8045
8046 if (sample->subsamples[i].bytes_of_protected_data % 16) {
8047 av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8048 return AVERROR_INVALIDDATA;
8049 }
8050
8051 /* skip the clear bytes */
8052 input += sample->subsamples[i].bytes_of_clear_data;
8053 size -= sample->subsamples[i].bytes_of_clear_data;
8054
8055 /* decrypt the encrypted bytes */
8056 num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8057 if (num_of_encrypted_blocks > 0) {
8058 av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8059 }
8060 input += sample->subsamples[i].bytes_of_protected_data;
8061 size -= sample->subsamples[i].bytes_of_protected_data;
8062 }
8063
8064 if (size > 0) {
8065 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8066 return AVERROR_INVALIDDATA;
8067 }
8068
8069 return 0;
8070 }
8071
8072 static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8073 {
8074 int i, ret, rem_bytes;
8075 uint8_t *data;
8076
8077 if (!sc->cenc.aes_ctr) {
8078 /* initialize the cipher */
8079 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8080 if (!sc->cenc.aes_ctr) {
8081 return AVERROR(ENOMEM);
8082 }
8083
8084 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
8085 if (ret < 0) {
8086 return ret;
8087 }
8088 }
8089
8090 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8091
8092 /* whole-block full sample encryption */
8093 if (!sample->subsample_count) {
8094 /* decrypt the whole packet */
8095 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8096 return 0;
8097 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8098 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8099 return AVERROR_INVALIDDATA;
8100 }
8101
8102 for (i = 0; i < sample->subsample_count; i++) {
8103 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8104 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8105 return AVERROR_INVALIDDATA;
8106 }
8107
8108 /* skip the clear bytes */
8109 input += sample->subsamples[i].bytes_of_clear_data;
8110 size -= sample->subsamples[i].bytes_of_clear_data;
8111
8112 /* decrypt the encrypted bytes */
8113 data = input;
8114 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8115 while (rem_bytes > 0) {
8116 if (rem_bytes < 16*sample->crypt_byte_block) {
8117 break;
8118 }
8119 av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8120 data += 16*sample->crypt_byte_block;
8121 rem_bytes -= 16*sample->crypt_byte_block;
8122 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8123 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8124 }
8125 input += sample->subsamples[i].bytes_of_protected_data;
8126 size -= sample->subsamples[i].bytes_of_protected_data;
8127 }
8128
8129 if (size > 0) {
8130 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8131 return AVERROR_INVALIDDATA;
8132 }
8133
8134 return 0;
8135 }
8136
8137 static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8138 {
8139 int i, ret, rem_bytes;
8140 uint8_t iv[16];
8141 uint8_t *data;
8142
8143 if (!sc->cenc.aes_ctx) {
8144 /* initialize the cipher */
8145 sc->cenc.aes_ctx = av_aes_alloc();
8146 if (!sc->cenc.aes_ctx) {
8147 return AVERROR(ENOMEM);
8148 }
8149
8150 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8151 if (ret < 0) {
8152 return ret;
8153 }
8154 }
8155
8156 /* whole-block full sample encryption */
8157 if (!sample->subsample_count) {
8158 /* decrypt the whole packet */
8159 memcpy(iv, sample->iv, 16);
8160 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8161 return 0;
8162 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8163 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8164 return AVERROR_INVALIDDATA;
8165 }
8166
8167 for (i = 0; i < sample->subsample_count; i++) {
8168 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8169 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8170 return AVERROR_INVALIDDATA;
8171 }
8172
8173 /* skip the clear bytes */
8174 input += sample->subsamples[i].bytes_of_clear_data;
8175 size -= sample->subsamples[i].bytes_of_clear_data;
8176
8177 /* decrypt the encrypted bytes */
8178 memcpy(iv, sample->iv, 16);
8179 data = input;
8180 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8181 while (rem_bytes > 0) {
8182 if (rem_bytes < 16*sample->crypt_byte_block) {
8183 break;
8184 }
8185 av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8186 data += 16*sample->crypt_byte_block;
8187 rem_bytes -= 16*sample->crypt_byte_block;
8188 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8189 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8190 }
8191 input += sample->subsamples[i].bytes_of_protected_data;
8192 size -= sample->subsamples[i].bytes_of_protected_data;
8193 }
8194
8195 if (size > 0) {
8196 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8197 return AVERROR_INVALIDDATA;
8198 }
8199
8200 return 0;
8201 }
8202
8203 146 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8204 {
8205
3/6
✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 146 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 146 times.
✗ Branch 5 not taken.
146 if (sample->scheme == MKBETAG('c','e','n','c') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8206 146 return cenc_scheme_decrypt(c, sc, sample, input, size);
8207 } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8208 return cbc1_scheme_decrypt(c, sc, sample, input, size);
8209 } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8210 return cens_scheme_decrypt(c, sc, sample, input, size);
8211 } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8212 return cbcs_scheme_decrypt(c, sc, sample, input, size);
8213 } else {
8214 av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8215 return AVERROR_INVALIDDATA;
8216 }
8217 }
8218
8219 96526 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8220 {
8221 96526 int current = frag_index->current;
8222
8223
2/2
✓ Branch 0 taken 95865 times.
✓ Branch 1 taken 661 times.
96526 if (!frag_index->nb_items)
8224 95865 return NULL;
8225
8226 // Check frag_index->current is the right one for pkt. It can out of sync.
8227
2/4
✓ Branch 0 taken 661 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 661 times.
✗ Branch 3 not taken.
661 if (current >= 0 && current < frag_index->nb_items) {
8228
2/2
✓ Branch 0 taken 639 times.
✓ Branch 1 taken 22 times.
661 if (frag_index->item[current].moof_offset < pkt->pos &&
8229
2/2
✓ Branch 0 taken 413 times.
✓ Branch 1 taken 226 times.
639 (current + 1 == frag_index->nb_items ||
8230
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 25 times.
413 frag_index->item[current + 1].moof_offset > pkt->pos))
8231 614 return get_frag_stream_info(frag_index, current, id);
8232 }
8233
8234
8235
2/2
✓ Branch 0 taken 3955 times.
✓ Branch 1 taken 4 times.
3959 for (int i = 0; i < frag_index->nb_items; i++) {
8236
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 3912 times.
3955 if (frag_index->item[i].moof_offset > pkt->pos)
8237 43 break;
8238 3912 current = i;
8239 }
8240 47 frag_index->current = current;
8241 47 return get_frag_stream_info(frag_index, current, id);
8242 }
8243
8244 96526 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8245 {
8246 MOVFragmentStreamInfo *frag_stream_info;
8247 MOVEncryptionIndex *encryption_index;
8248 AVEncryptionInfo *encrypted_sample;
8249 int encrypted_index, ret;
8250
8251 96526 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8252 96526 encrypted_index = current_index;
8253 96526 encryption_index = NULL;
8254
2/2
✓ Branch 0 taken 661 times.
✓ Branch 1 taken 95865 times.
96526 if (frag_stream_info) {
8255 // Note this only supports encryption info in the first sample descriptor.
8256
2/2
✓ Branch 0 taken 637 times.
✓ Branch 1 taken 24 times.
661 if (frag_stream_info->stsd_id == 1) {
8257
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 613 times.
637 if (frag_stream_info->encryption_index) {
8258 24 encrypted_index = current_index - frag_stream_info->index_base;
8259 24 encryption_index = frag_stream_info->encryption_index;
8260 } else {
8261 613 encryption_index = sc->cenc.encryption_index;
8262 }
8263 }
8264 } else {
8265 95865 encryption_index = sc->cenc.encryption_index;
8266 }
8267
8268
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 96380 times.
96526 if (encryption_index) {
8269
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_info_sample_count &&
8270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8271 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8272 return AVERROR_INVALIDDATA;
8273 }
8274
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_offsets_count &&
8275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8276 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8277 return AVERROR_INVALIDDATA;
8278 }
8279
8280 146 encrypted_sample = NULL;
8281
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!encryption_index->nb_encrypted_samples) {
8282 // Full-sample encryption with default settings.
8283 48 encrypted_sample = sc->cenc.default_encrypted_sample;
8284
2/4
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 98 times.
✗ Branch 3 not taken.
98 } else if (encrypted_index >= 0 && encrypted_index < encryption_index->nb_encrypted_samples) {
8285 // Per-sample setting override.
8286 98 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (!encrypted_sample) {
8288 encrypted_sample = sc->cenc.default_encrypted_sample;
8289 }
8290 }
8291
8292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (!encrypted_sample) {
8293 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8294 return AVERROR_INVALIDDATA;
8295 }
8296
8297
1/2
✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
146 if (mov->decryption_key) {
8298 146 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
8299 } else {
8300 size_t size;
8301 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
8302 if (!side_data)
8303 return AVERROR(ENOMEM);
8304 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
8305 if (ret < 0)
8306 av_free(side_data);
8307 return ret;
8308 }
8309 }
8310
8311 96380 return 0;
8312 }
8313
8314 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8315 {
8316 const int OPUS_SEEK_PREROLL_MS = 80;
8317 int ret;
8318 AVStream *st;
8319 size_t size;
8320 uint16_t pre_skip;
8321
8322 if (c->fc->nb_streams < 1)
8323 return 0;
8324 st = c->fc->streams[c->fc->nb_streams-1];
8325
8326 if ((uint64_t)atom.size > (1<<30) || atom.size < 11)
8327 return AVERROR_INVALIDDATA;
8328
8329 /* Check OpusSpecificBox version. */
8330 if (avio_r8(pb) != 0) {
8331 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
8332 return AVERROR_INVALIDDATA;
8333 }
8334
8335 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
8336 size = atom.size + 8;
8337
8338 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
8339 return ret;
8340
8341 AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
8342 AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
8343 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
8344 avio_read(pb, st->codecpar->extradata + 9, size - 9);
8345
8346 /* OpusSpecificBox is stored in big-endian, but OpusHead is
8347 little-endian; aside from the preceeding magic and version they're
8348 otherwise currently identical. Data after output gain at offset 16
8349 doesn't need to be bytewapped. */
8350 pre_skip = AV_RB16A(st->codecpar->extradata + 10);
8351 AV_WL16A(st->codecpar->extradata + 10, pre_skip);
8352 AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
8353 AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
8354
8355 st->codecpar->initial_padding = pre_skip;
8356 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
8357 (AVRational){1, 1000},
8358 (AVRational){1, 48000});
8359
8360 return 0;
8361 }
8362
8363 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8364 {
8365 AVStream *st;
8366 unsigned format_info;
8367 int channel_assignment, channel_assignment1, channel_assignment2;
8368 int ratebits;
8369 uint64_t chmask;
8370
8371 if (c->fc->nb_streams < 1)
8372 return 0;
8373 st = c->fc->streams[c->fc->nb_streams-1];
8374
8375 if (atom.size < 10)
8376 return AVERROR_INVALIDDATA;
8377
8378 format_info = avio_rb32(pb);
8379
8380 ratebits = (format_info >> 28) & 0xF;
8381 channel_assignment1 = (format_info >> 15) & 0x1F;
8382 channel_assignment2 = format_info & 0x1FFF;
8383 if (channel_assignment2)
8384 channel_assignment = channel_assignment2;
8385 else
8386 channel_assignment = channel_assignment1;
8387
8388 st->codecpar->frame_size = 40 << (ratebits & 0x7);
8389 st->codecpar->sample_rate = mlp_samplerate(ratebits);
8390
8391 av_channel_layout_uninit(&st->codecpar->ch_layout);
8392 chmask = truehd_layout(channel_assignment);
8393 av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
8394
8395 return 0;
8396 }
8397
8398 4 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8399 {
8400 AVStream *st;
8401 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
8402 int ret;
8403 4 int64_t read_size = atom.size;
8404
8405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8406 return 0;
8407 4 st = c->fc->streams[c->fc->nb_streams-1];
8408
8409 // At most 24 bytes
8410 4 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
8411
8412
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
8413 return ret;
8414
8415 4 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
8416 }
8417
8418 3 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8419 {
8420 AVStream *st;
8421 uint8_t *buf;
8422 int ret, old_size, num_arrays;
8423
8424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
8425 return 0;
8426 3 st = c->fc->streams[c->fc->nb_streams-1];
8427
8428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata_size)
8429 // TODO: handle lhvC when present before hvcC
8430 return 0;
8431
8432
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (atom.size < 6 || st->codecpar->extradata_size < 23)
8433 return AVERROR_INVALIDDATA;
8434
8435 3 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
8436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!buf)
8437 return AVERROR(ENOMEM);
8438 3 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8439
8440 3 ret = ffio_read_size(pb, buf, atom.size);
8441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8442 av_free(buf);
8443 av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
8444 return 0;
8445 }
8446
8447 3 num_arrays = buf[5];
8448 3 old_size = st->codecpar->extradata_size;
8449 3 atom.size -= 8 /* account for mov_realloc_extradata offseting */
8450 + 6 /* lhvC bytes before the arrays*/;
8451
8452 3 ret = mov_realloc_extradata(st->codecpar, atom);
8453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8454 av_free(buf);
8455 return ret;
8456 }
8457
8458 3 st->codecpar->extradata[22] += num_arrays;
8459 3 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
8460
8461 3 st->disposition |= AV_DISPOSITION_MULTILAYER;
8462
8463 3 av_free(buf);
8464 3 return 0;
8465 }
8466
8467 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8468 {
8469 4 AVFormatContext *ctx = c->fc;
8470 4 AVStream *st = NULL;
8471 AVBPrint scheme_buf, value_buf;
8472 4 int64_t scheme_str_len = 0, value_str_len = 0;
8473 4 int version, flags, ret = AVERROR_BUG;
8474 4 int64_t size = atom.size;
8475
8476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
8477 // 4 bytes for version + flags, 2x 1 byte for null
8478 return AVERROR_INVALIDDATA;
8479
8480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8481 return 0;
8482 4 st = c->fc->streams[c->fc->nb_streams-1];
8483
8484 4 version = avio_r8(pb);
8485 4 flags = avio_rb24(pb);
8486 4 size -= 4;
8487
8488
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) {
8489 av_log(ctx, AV_LOG_ERROR,
8490 "Unsupported 'kind' box with version %d, flags: %x",
8491 version, flags);
8492 return AVERROR_INVALIDDATA;
8493 }
8494
8495 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8496 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8497
8498
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,
8499 size)) < 0) {
8500 ret = scheme_str_len;
8501 goto cleanup;
8502 }
8503
8504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
8505 // we need to have another string, even if nullptr.
8506 // we check with + 1 since we expect that if size was not hit,
8507 // an additional null was read.
8508 ret = AVERROR_INVALIDDATA;
8509 goto cleanup;
8510 }
8511
8512 4 size -= scheme_str_len + 1;
8513
8514
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,
8515 size)) < 0) {
8516 ret = value_str_len;
8517 goto cleanup;
8518 }
8519
8520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
8521 // in case of no trailing null, box is not valid.
8522 ret = AVERROR_INVALIDDATA;
8523 goto cleanup;
8524 }
8525
8526 4 av_log(ctx, AV_LOG_TRACE,
8527 "%s stream %d KindBox(scheme: %s, value: %s)\n",
8528 4 av_get_media_type_string(st->codecpar->codec_type),
8529 st->index,
8530 scheme_buf.str, value_buf.str);
8531
8532
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++) {
8533 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
8534
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
8535 continue;
8536
8537
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
8538 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
8539
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
8540 16 continue;
8541
8542 4 st->disposition |= value_map.disposition;
8543 }
8544 }
8545
8546 4 ret = 0;
8547
8548 4 cleanup:
8549
8550 4 av_bprint_finalize(&scheme_buf, NULL);
8551 4 av_bprint_finalize(&value_buf, NULL);
8552
8553 4 return ret;
8554 }
8555
8556 static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8557 {
8558 AVStream *st;
8559 AVChannelLayout ch_layout = { 0 };
8560 int ret, i, version, type;
8561 int ambisonic_order, channel_order, normalization, channel_count;
8562 int ambi_channels, non_diegetic_channels;
8563
8564 if (c->fc->nb_streams < 1)
8565 return 0;
8566
8567 st = c->fc->streams[c->fc->nb_streams - 1];
8568
8569 if (atom.size < 16) {
8570 av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
8571 return AVERROR_INVALIDDATA;
8572 }
8573
8574 version = avio_r8(pb);
8575 if (version) {
8576 av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
8577 return 0;
8578 }
8579
8580 type = avio_r8(pb);
8581 if (type & 0x7f) {
8582 av_log(c->fc, AV_LOG_WARNING,
8583 "Unsupported ambisonic type %d\n", type & 0x7f);
8584 return 0;
8585 }
8586 non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
8587
8588 ambisonic_order = avio_rb32(pb);
8589
8590 channel_order = avio_r8(pb);
8591 if (channel_order) {
8592 av_log(c->fc, AV_LOG_WARNING,
8593 "Unsupported channel_order %d\n", channel_order);
8594 return 0;
8595 }
8596
8597 normalization = avio_r8(pb);
8598 if (normalization) {
8599 av_log(c->fc, AV_LOG_WARNING,
8600 "Unsupported normalization %d\n", normalization);
8601 return 0;
8602 }
8603
8604 channel_count = avio_rb32(pb);
8605 if (ambisonic_order < 0 || ambisonic_order > 31 ||
8606 channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
8607 non_diegetic_channels)) {
8608 av_log(c->fc, AV_LOG_ERROR,
8609 "Invalid number of channels (%d / %d)\n",
8610 channel_count, ambisonic_order);
8611 return 0;
8612 }
8613 ambi_channels = channel_count - non_diegetic_channels;
8614
8615 ret = av_channel_layout_custom_init(&ch_layout, channel_count);
8616 if (ret < 0)
8617 return 0;
8618
8619 for (i = 0; i < channel_count; i++) {
8620 unsigned channel = avio_rb32(pb);
8621
8622 if (channel >= channel_count) {
8623 av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
8624 channel, ambisonic_order);
8625 av_channel_layout_uninit(&ch_layout);
8626 return 0;
8627 }
8628 if (channel >= ambi_channels)
8629 ch_layout.u.map[i].id = channel - ambi_channels;
8630 else
8631 ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
8632 }
8633
8634 ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
8635 if (ret < 0) {
8636 av_channel_layout_uninit(&ch_layout);
8637 return 0;
8638 }
8639
8640 av_channel_layout_uninit(&st->codecpar->ch_layout);
8641 st->codecpar->ch_layout = ch_layout;
8642
8643 return 0;
8644 }
8645
8646 static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8647 {
8648 AVStream *st;
8649 int version;
8650
8651 if (c->fc->nb_streams < 1)
8652 return 0;
8653
8654 st = c->fc->streams[c->fc->nb_streams - 1];
8655
8656 if (atom.size < 5) {
8657 av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
8658 return AVERROR_INVALIDDATA;
8659 }
8660
8661 version = avio_r8(pb);
8662 if (version) {
8663 av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
8664 return 0;
8665 }
8666
8667 st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
8668
8669 return 0;
8670 }
8671
8672 126 static int rb_size(AVIOContext *pb, int64_t *value, int size)
8673 {
8674
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 115 times.
126 if (size == 0)
8675 11 *value = 0;
8676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 115 times.
115 else if (size == 1)
8677 *value = avio_r8(pb);
8678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 115 times.
115 else if (size == 2)
8679 *value = avio_rb16(pb);
8680
1/2
✓ Branch 0 taken 115 times.
✗ Branch 1 not taken.
115 else if (size == 4)
8681 115 *value = avio_rb32(pb);
8682 else if (size == 8) {
8683 *value = avio_rb64(pb);
8684 if (*value < 0)
8685 return -1;
8686 } else
8687 return -1;
8688 126 return size;
8689 }
8690
8691 15 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8692 {
8693 15 avio_rb32(pb); // version & flags.
8694 15 c->primary_item_id = avio_rb16(pb);
8695 15 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
8696 15 return atom.size;
8697 }
8698
8699 6 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8700 {
8701 6 c->idat_offset = avio_tell(pb);
8702 6 return 0;
8703 }
8704
8705 15 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8706 {
8707 HEIFItem **heif_item;
8708 int version, offset_size, length_size, base_offset_size, index_size;
8709 int item_count, extent_count;
8710 int64_t base_offset, extent_offset, extent_length;
8711 uint8_t value;
8712
8713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (c->found_iloc) {
8714 av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
8715 return 0;
8716 }
8717
8718 15 version = avio_r8(pb);
8719 15 avio_rb24(pb); // flags.
8720
8721 15 value = avio_r8(pb);
8722 15 offset_size = (value >> 4) & 0xF;
8723 15 length_size = value & 0xF;
8724 15 value = avio_r8(pb);
8725 15 base_offset_size = (value >> 4) & 0xF;
8726
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7 times.
15 index_size = !version ? 0 : (value & 0xF);
8727
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (index_size) {
8728 avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
8729 return AVERROR_PATCHWELCOME;
8730 }
8731
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8732
8733 15 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
8734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!heif_item)
8735 return AVERROR(ENOMEM);
8736 15 c->heif_item = heif_item;
8737
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (item_count > c->nb_heif_item)
8738 15 memset(&c->heif_item[c->nb_heif_item], 0,
8739 15 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
8740 15 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
8741
8742 15 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
8743
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 15 times.
57 for (int i = 0; i < item_count; i++) {
8744 42 HEIFItem *item = NULL;
8745
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8746
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
8747
8748
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
42 if (avio_feof(pb))
8749 return AVERROR_INVALIDDATA;
8750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (offset_type > 1) {
8751 avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
8752 return AVERROR_PATCHWELCOME;
8753 }
8754
8755 42 avio_rb16(pb); // data_reference_index.
8756
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
42 if (rb_size(pb, &base_offset, base_offset_size) < 0)
8757 return AVERROR_INVALIDDATA;
8758 42 extent_count = avio_rb16(pb);
8759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (extent_count > 1) {
8760 // For still AVIF images, we only support one extent item.
8761 avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
8762 return AVERROR_PATCHWELCOME;
8763 }
8764
8765
2/4
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 42 times.
✗ Branch 4 not taken.
84 if (rb_size(pb, &extent_offset, offset_size) < 0 ||
8766 42 rb_size(pb, &extent_length, length_size) < 0 ||
8767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 base_offset > INT64_MAX - extent_offset)
8768 return AVERROR_INVALIDDATA;
8769
8770
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 for (int j = 0; j < c->nb_heif_item; j++) {
8771 95 item = c->heif_item[j];
8772
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 53 times.
95 if (!item)
8773 42 item = c->heif_item[j] = av_mallocz(sizeof(*item));
8774
1/2
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
53 else if (item->item_id != item_id)
8775 53 continue;
8776 42 break;
8777 }
8778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!item)
8779 return AVERROR(ENOMEM);
8780
8781 42 item->item_id = item_id;
8782
8783
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 36 times.
42 if (offset_type == 1)
8784 6 item->is_idat_relative = 1;
8785 42 item->extent_length = extent_length;
8786 42 item->extent_offset = base_offset + extent_offset;
8787 42 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, item->item_id %d, offset_type %d, "
8788 "extent_offset %"PRId64", extent_length %"PRId64"\n",
8789 i, item->item_id, offset_type, item->extent_offset, item->extent_length);
8790 }
8791
8792 15 c->found_iloc = 1;
8793 15 return atom.size;
8794 }
8795
8796 42 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8797 {
8798 42 HEIFItem *item = NULL;
8799 AVBPrint item_name;
8800 42 int64_t size = atom.size;
8801 uint32_t item_type;
8802 int item_id;
8803 int version, ret;
8804
8805 42 version = avio_r8(pb);
8806 42 avio_rb24(pb); // flags.
8807 42 size -= 4;
8808
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (size < 0)
8809 return AVERROR_INVALIDDATA;
8810
8811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (version < 2) {
8812 avpriv_report_missing_feature(c->fc, "infe version < 2");
8813 avio_skip(pb, size);
8814 return 1;
8815 }
8816
8817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
8818 42 avio_rb16(pb); // item_protection_index
8819 42 item_type = avio_rl32(pb);
8820 42 size -= 8;
8821
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (size < 1)
8822 return AVERROR_INVALIDDATA;
8823
8824 42 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
8825 42 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
8826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0) {
8827 av_bprint_finalize(&item_name, NULL);
8828 return ret;
8829 }
8830
8831 42 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
8832 42 item_id, av_fourcc2str(item_type), item_name.str);
8833
8834 42 size -= ret + 1;
8835
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 40 times.
42 if (size > 0)
8836 2 avio_skip(pb, size);
8837
8838
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 for (int i = 0; i < c->nb_heif_item; i++) {
8839 95 item = c->heif_item[i];
8840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
95 if (!item)
8841 item = c->heif_item[i] = av_mallocz(sizeof(*item));
8842
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 42 times.
95 else if (item->item_id != item_id)
8843 53 continue;
8844 42 break;
8845 }
8846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!item)
8847 return AVERROR(ENOMEM);
8848
8849
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 1 times.
42 if (ret)
8850 41 av_bprint_finalize(&item_name, &item->name);
8851 42 item->item_id = item_id;
8852 42 item->type = item_type;
8853
8854
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 11 times.
42 switch (item_type) {
8855 31 case MKTAG('a','v','0','1'):
8856 case MKTAG('j','p','e','g'):
8857 case MKTAG('h','v','c','1'):
8858 31 ret = heif_add_stream(c, item);
8859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (ret < 0)
8860 return ret;
8861 31 break;
8862 }
8863
8864 42 return 0;
8865 }
8866
8867 15 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8868 {
8869 HEIFItem **heif_item;
8870 int entry_count;
8871 15 int version, got_stream = 0, ret, i;
8872
8873
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (c->found_iinf) {
8874 av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
8875 return 0;
8876 }
8877
8878 15 version = avio_r8(pb);
8879 15 avio_rb24(pb); // flags.
8880
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
8881
8882 15 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
8883
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!heif_item)
8884 return AVERROR(ENOMEM);
8885 15 c->heif_item = heif_item;
8886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (entry_count > c->nb_heif_item)
8887 memset(&c->heif_item[c->nb_heif_item], 0,
8888 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
8889 15 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
8890
8891
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 15 times.
57 for (i = 0; i < entry_count; i++) {
8892 MOVAtom infe;
8893
8894 42 infe.size = avio_rb32(pb) - 8;
8895 42 infe.type = avio_rl32(pb);
8896
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
42 if (avio_feof(pb)) {
8897 ret = AVERROR_INVALIDDATA;
8898 goto fail;
8899 }
8900 42 ret = mov_read_infe(c, pb, infe);
8901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0)
8902 goto fail;
8903
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 if (!ret)
8904 42 got_stream = 1;
8905 }
8906
8907 15 c->found_iinf = got_stream;
8908 15 return 0;
8909 fail:
8910 for (; i >= 0; i--) {
8911 HEIFItem *item = c->heif_item[i];
8912
8913 if (!item)
8914 continue;
8915
8916 av_freep(&item->name);
8917 if (!item->st)
8918 continue;
8919
8920 mov_free_stream_context(c->fc, item->st);
8921 ff_remove_stream(c->fc, item->st);
8922 item->st = NULL;
8923 }
8924 return ret;
8925 }
8926
8927 6 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
8928 {
8929 6 HEIFItem *item = NULL;
8930 HEIFGrid *grid;
8931 int entries, i;
8932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8933
8934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 for (int i = 0; i < c->nb_heif_grid; i++) {
8935 if (c->heif_grid[i].item->item_id == from_item_id) {
8936 av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
8937 "referencing the same Derived Image item\n");
8938 return AVERROR_INVALIDDATA;
8939 }
8940 }
8941
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 for (int i = 0; i < c->nb_heif_item; i++) {
8942
3/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 6 times.
20 if (!c->heif_item[i] || c->heif_item[i]->item_id != from_item_id)
8943 14 continue;
8944 6 item = c->heif_item[i];
8945
8946
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 switch (item->type) {
8947 6 case MKTAG('g','r','i','d'):
8948 case MKTAG('i','o','v','l'):
8949 6 break;
8950 default:
8951 avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
8952 av_fourcc2str(item->type));
8953 return 0;
8954 }
8955 6 break;
8956 }
8957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!item) {
8958 av_log(c->fc, AV_LOG_ERROR, "Missing grid information\n");
8959 return AVERROR_INVALIDDATA;
8960 }
8961
8962 6 grid = av_realloc_array(c->heif_grid, c->nb_heif_grid + 1U,
8963 sizeof(*c->heif_grid));
8964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!grid)
8965 return AVERROR(ENOMEM);
8966 6 c->heif_grid = grid;
8967 6 grid = &grid[c->nb_heif_grid++];
8968
8969 6 entries = avio_rb16(pb);
8970 6 grid->tile_id_list = av_malloc_array(entries, sizeof(*grid->tile_id_list));
8971 6 grid->tile_idx_list = av_calloc(entries, sizeof(*grid->tile_idx_list));
8972 6 grid->tile_item_list = av_calloc(entries, sizeof(*grid->tile_item_list));
8973
3/6
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
6 if (!grid->tile_id_list || !grid->tile_item_list || !grid->tile_idx_list)
8974 return AVERROR(ENOMEM);
8975 /* 'to' item ids */
8976
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (i = 0; i < entries; i++)
8977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 grid->tile_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
8978 6 grid->nb_tiles = entries;
8979 6 grid->item = item;
8980
8981 6 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
8982 from_item_id, entries);
8983
8984 6 return 0;
8985 }
8986
8987 7 static int mov_read_iref_thmb(MOVContext *c, AVIOContext *pb, int version)
8988 {
8989 int *thmb_item_id;
8990 int entries;
8991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 int to_item_id, from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8992
8993 7 entries = avio_rb16(pb);
8994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (entries > 1) {
8995 avpriv_request_sample(c->fc, "thmb in iref referencing several items");
8996 return AVERROR_PATCHWELCOME;
8997 }
8998 /* 'to' item ids */
8999
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 to_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9000
9001
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (to_item_id != c->primary_item_id)
9002 return 0;
9003
9004 /* Put thumnbail IDs into an array */
9005 7 thmb_item_id = av_dynarray2_add((void **)&c->thmb_item_id, &c->nb_thmb_item,
9006 sizeof(*c->thmb_item_id),
9007 (const void *)&from_item_id);
9008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!thmb_item_id)
9009 return AVERROR(ENOMEM);
9010
9011 7 av_log(c->fc, AV_LOG_TRACE, "thmb: from_item_id %d, entries %d, nb_thmb: %d\n",
9012 from_item_id, entries, c->nb_thmb_item);
9013
9014 7 return 0;
9015 }
9016
9017 11 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9018 {
9019 11 int version = avio_r8(pb);
9020 11 avio_rb24(pb); // flags
9021 11 atom.size -= 4;
9022
9023
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (version > 1) {
9024 av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
9025 return 0;
9026 }
9027
9028
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 11 times.
28 while (atom.size) {
9029 17 uint32_t type, size = avio_rb32(pb);
9030 17 int64_t next = avio_tell(pb);
9031
9032
3/6
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 17 times.
17 if (size < 14 || next < 0 || next > INT64_MAX - size)
9033 return AVERROR_INVALIDDATA;
9034
9035 17 next += size - 4;
9036 17 type = avio_rl32(pb);
9037
3/3
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 4 times.
17 switch (type) {
9038 6 case MKTAG('d','i','m','g'):
9039 6 mov_read_iref_dimg(c, pb, version);
9040 13 break;
9041 7 case MKTAG('t','h','m','b'):
9042 7 mov_read_iref_thmb(c, pb, version);
9043 7 break;
9044 4 default:
9045 4 av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
9046 4 av_fourcc2str(type), size);
9047 }
9048
9049 17 atom.size -= size;
9050 17 avio_seek(pb, next, SEEK_SET);
9051 }
9052 11 return 0;
9053 }
9054
9055 37 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9056 {
9057 HEIFItem *item;
9058 uint32_t width, height;
9059
9060 37 avio_r8(pb); /* version */
9061 37 avio_rb24(pb); /* flags */
9062 37 width = avio_rb32(pb);
9063 37 height = avio_rb32(pb);
9064
9065 37 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %u, height %u\n",
9066 c->cur_item_id, width, height);
9067
9068 37 item = heif_cur_item(c);
9069
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if (item) {
9070 37 item->width = width;
9071 37 item->height = height;
9072 }
9073
9074 37 return 0;
9075 }
9076
9077 8 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9078 {
9079 HEIFItem *item;
9080 int angle;
9081
9082 8 angle = avio_r8(pb) & 0x3;
9083
9084 8 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
9085 c->cur_item_id, angle);
9086
9087 8 item = heif_cur_item(c);
9088
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (item) {
9089 // angle * 90 specifies the angle (in anti-clockwise direction)
9090 // in units of degrees.
9091 8 item->rotation = angle * 90;
9092 }
9093
9094 8 return 0;
9095 }
9096
9097 6 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9098 {
9099 HEIFItem *item;
9100 int axis;
9101
9102 6 axis = avio_r8(pb) & 0x1;
9103
9104 6 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
9105 c->cur_item_id, axis);
9106
9107 6 item = heif_cur_item(c);
9108
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
9109 6 item->hflip = axis;
9110 6 item->vflip = !axis;
9111 }
9112
9113 6 return 0;
9114 }
9115
9116 15 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9117 {
9118 typedef struct MOVAtoms {
9119 FFIOContext b;
9120 uint32_t type;
9121 int64_t size;
9122 uint8_t *data;
9123 } MOVAtoms;
9124 15 MOVAtoms *atoms = NULL;
9125 MOVAtom a;
9126 unsigned count;
9127 15 int nb_atoms = 0;
9128 int version, flags;
9129 int ret;
9130
9131 15 a.size = avio_rb32(pb);
9132 15 a.type = avio_rl32(pb);
9133
9134
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 if (a.size < 8 || a.type != MKTAG('i','p','c','o'))
9135 return AVERROR_INVALIDDATA;
9136
9137 15 a.size -= 8;
9138
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 15 times.
86 while (a.size >= 8) {
9139 71 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
9140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (!ref) {
9141 ret = AVERROR(ENOMEM);
9142 goto fail;
9143 }
9144 71 ref->data = NULL;
9145 71 ref->size = avio_rb32(pb);
9146 71 ref->type = avio_rl32(pb);
9147
2/4
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 71 times.
✗ Branch 3 not taken.
71 if (ref->size > a.size || ref->size < 8)
9148 break;
9149 71 ref->data = av_malloc(ref->size);
9150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (!ref->data) {
9151 ret = AVERROR_INVALIDDATA;
9152 goto fail;
9153 }
9154 71 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
9155 71 avio_seek(pb, -8, SEEK_CUR);
9156
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 71 times.
71 if (avio_read(pb, ref->data, ref->size) != ref->size) {
9157 ret = AVERROR_INVALIDDATA;
9158 goto fail;
9159 }
9160 71 ffio_init_read_context(&ref->b, ref->data, ref->size);
9161 71 a.size -= ref->size;
9162 }
9163
9164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (a.size) {
9165 ret = AVERROR_INVALIDDATA;
9166 goto fail;
9167 }
9168
9169 15 a.size = avio_rb32(pb);
9170 15 a.type = avio_rl32(pb);
9171
9172
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 if (a.size < 8 || a.type != MKTAG('i','p','m','a')) {
9173 ret = AVERROR_INVALIDDATA;
9174 goto fail;
9175 }
9176
9177 15 version = avio_r8(pb);
9178 15 flags = avio_rb24(pb);
9179 15 count = avio_rb32(pb);
9180
9181
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 15 times.
52 for (int i = 0; i < count; i++) {
9182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9183 37 int assoc_count = avio_r8(pb);
9184
9185
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
37 if (avio_feof(pb)) {
9186 ret = AVERROR_INVALIDDATA;
9187 goto fail;
9188 }
9189
9190
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 37 times.
135 for (int j = 0; j < assoc_count; j++) {
9191 MOVAtoms *ref;
9192 98 int index = avio_r8(pb) & 0x7f;
9193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (flags & 1) {
9194 index <<= 8;
9195 index |= avio_r8(pb);
9196 }
9197
2/4
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 98 times.
98 if (index > nb_atoms || index <= 0) {
9198 ret = AVERROR_INVALIDDATA;
9199 goto fail;
9200 }
9201 98 ref = &atoms[--index];
9202
9203 98 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
9204 98 index + 1, item_id, av_fourcc2str(ref->type));
9205
9206 98 c->cur_item_id = item_id;
9207
9208 98 ret = mov_read_default(c, &ref->b.pub,
9209 98 (MOVAtom) { .size = ref->size,
9210 .type = MKTAG('i','p','c','o') });
9211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (ret < 0)
9212 goto fail;
9213 98 ffio_init_read_context(&ref->b, ref->data, ref->size);
9214 }
9215 }
9216
9217 15 ret = 0;
9218 15 fail:
9219 15 c->cur_item_id = -1;
9220
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 15 times.
86 for (int i = 0; i < nb_atoms; i++)
9221 71 av_free(atoms[i].data);
9222 15 av_free(atoms);
9223
9224 15 return ret;
9225 }
9226
9227 static const MOVParseTableEntry mov_default_parse_table[] = {
9228 { MKTAG('A','C','L','R'), mov_read_aclr },
9229 { MKTAG('A','P','R','G'), mov_read_avid },
9230 { MKTAG('A','A','L','P'), mov_read_avid },
9231 { MKTAG('A','R','E','S'), mov_read_ares },
9232 { MKTAG('a','v','s','s'), mov_read_avss },
9233 { MKTAG('a','v','1','C'), mov_read_glbl },
9234 { MKTAG('c','h','p','l'), mov_read_chpl },
9235 { MKTAG('c','o','6','4'), mov_read_stco },
9236 { MKTAG('c','o','l','r'), mov_read_colr },
9237 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
9238 { MKTAG('d','i','n','f'), mov_read_default },
9239 { MKTAG('D','p','x','E'), mov_read_dpxe },
9240 { MKTAG('d','r','e','f'), mov_read_dref },
9241 { MKTAG('e','d','t','s'), mov_read_default },
9242 { MKTAG('e','l','s','t'), mov_read_elst },
9243 { MKTAG('e','n','d','a'), mov_read_enda },
9244 { MKTAG('f','i','e','l'), mov_read_fiel },
9245 { MKTAG('a','d','r','m'), mov_read_adrm },
9246 { MKTAG('f','t','y','p'), mov_read_ftyp },
9247 { MKTAG('g','l','b','l'), mov_read_glbl },
9248 { MKTAG('h','d','l','r'), mov_read_hdlr },
9249 { MKTAG('i','l','s','t'), mov_read_ilst },
9250 { MKTAG('j','p','2','h'), mov_read_jp2h },
9251 { MKTAG('m','d','a','t'), mov_read_mdat },
9252 { MKTAG('m','d','h','d'), mov_read_mdhd },
9253 { MKTAG('m','d','i','a'), mov_read_default },
9254 { MKTAG('m','e','t','a'), mov_read_meta },
9255 { MKTAG('m','i','n','f'), mov_read_default },
9256 { MKTAG('m','o','o','f'), mov_read_moof },
9257 { MKTAG('m','o','o','v'), mov_read_moov },
9258 { MKTAG('m','v','e','x'), mov_read_default },
9259 { MKTAG('m','v','h','d'), mov_read_mvhd },
9260 { MKTAG('S','M','I',' '), mov_read_svq3 },
9261 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
9262 { MKTAG('a','v','c','C'), mov_read_glbl },
9263 { MKTAG('p','a','s','p'), mov_read_pasp },
9264 { MKTAG('c','l','a','p'), mov_read_clap },
9265 { MKTAG('s','b','a','s'), mov_read_sbas },
9266 { MKTAG('s','i','d','x'), mov_read_sidx },
9267 { MKTAG('s','t','b','l'), mov_read_default },
9268 { MKTAG('s','t','c','o'), mov_read_stco },
9269 { MKTAG('s','t','p','s'), mov_read_stps },
9270 { MKTAG('s','t','r','f'), mov_read_strf },
9271 { MKTAG('s','t','s','c'), mov_read_stsc },
9272 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
9273 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
9274 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
9275 { MKTAG('s','t','t','s'), mov_read_stts },
9276 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
9277 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
9278 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
9279 { MKTAG('t','f','d','t'), mov_read_tfdt },
9280 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
9281 { MKTAG('t','r','a','k'), mov_read_trak },
9282 { MKTAG('t','r','a','f'), mov_read_default },
9283 { MKTAG('t','r','e','f'), mov_read_default },
9284 { MKTAG('t','m','c','d'), mov_read_tmcd },
9285 { MKTAG('c','h','a','p'), mov_read_chap },
9286 { MKTAG('t','r','e','x'), mov_read_trex },
9287 { MKTAG('t','r','u','n'), mov_read_trun },
9288 { MKTAG('u','d','t','a'), mov_read_default },
9289 { MKTAG('w','a','v','e'), mov_read_wave },
9290 { MKTAG('e','s','d','s'), mov_read_esds },
9291 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
9292 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
9293 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
9294 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
9295 { MKTAG('w','f','e','x'), mov_read_wfex },
9296 { MKTAG('c','m','o','v'), mov_read_cmov },
9297 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
9298 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
9299 { MKTAG('d','v','c','1'), mov_read_dvc1 },
9300 { MKTAG('s','g','p','d'), mov_read_sgpd },
9301 { MKTAG('s','b','g','p'), mov_read_sbgp },
9302 { MKTAG('h','v','c','C'), mov_read_glbl },
9303 { MKTAG('v','v','c','C'), mov_read_glbl },
9304 { MKTAG('u','u','i','d'), mov_read_uuid },
9305 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
9306 { MKTAG('f','r','e','e'), mov_read_free },
9307 { MKTAG('-','-','-','-'), mov_read_custom },
9308 { MKTAG('s','i','n','f'), mov_read_default },
9309 { MKTAG('f','r','m','a'), mov_read_frma },
9310 { MKTAG('s','e','n','c'), mov_read_senc },
9311 { MKTAG('s','a','i','z'), mov_read_saiz },
9312 { MKTAG('s','a','i','o'), mov_read_saio },
9313 { MKTAG('p','s','s','h'), mov_read_pssh },
9314 { MKTAG('s','c','h','m'), mov_read_schm },
9315 { MKTAG('s','c','h','i'), mov_read_default },
9316 { MKTAG('t','e','n','c'), mov_read_tenc },
9317 { MKTAG('d','f','L','a'), mov_read_dfla },
9318 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
9319 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
9320 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
9321 { MKTAG('h','f','o','v'), mov_read_hfov },
9322 { MKTAG('d','O','p','s'), mov_read_dops },
9323 { MKTAG('d','m','l','p'), mov_read_dmlp },
9324 { MKTAG('S','m','D','m'), mov_read_smdm },
9325 { MKTAG('C','o','L','L'), mov_read_coll },
9326 { MKTAG('v','p','c','C'), mov_read_vpcc },
9327 { MKTAG('m','d','c','v'), mov_read_mdcv },
9328 { MKTAG('c','l','l','i'), mov_read_clli },
9329 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
9330 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
9331 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
9332 { MKTAG('k','i','n','d'), mov_read_kind },
9333 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
9334 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
9335 { MKTAG('i','l','o','c'), mov_read_iloc },
9336 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
9337 { MKTAG('p','i','t','m'), mov_read_pitm },
9338 { MKTAG('e','v','c','C'), mov_read_glbl },
9339 { MKTAG('i','d','a','t'), mov_read_idat },
9340 { MKTAG('i','m','i','r'), mov_read_imir },
9341 { MKTAG('i','r','e','f'), mov_read_iref },
9342 { MKTAG('i','s','p','e'), mov_read_ispe },
9343 { MKTAG('i','r','o','t'), mov_read_irot },
9344 { MKTAG('i','p','r','p'), mov_read_iprp },
9345 { MKTAG('i','i','n','f'), mov_read_iinf },
9346 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
9347 { MKTAG('l','h','v','C'), mov_read_lhvc },
9348 { MKTAG('l','v','c','C'), mov_read_glbl },
9349 { MKTAG('a','p','v','C'), mov_read_glbl },
9350 #if CONFIG_IAMFDEC
9351 { MKTAG('i','a','c','b'), mov_read_iacb },
9352 #endif
9353 { 0, NULL }
9354 };
9355
9356 6387 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9357 {
9358 6387 int64_t total_size = 0;
9359 MOVAtom a;
9360 int i;
9361
9362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6387 times.
6387 if (c->atom_depth > 10) {
9363 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
9364 return AVERROR_INVALIDDATA;
9365 }
9366 6387 c->atom_depth ++;
9367
9368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6387 times.
6387 if (atom.size < 0)
9369 atom.size = INT64_MAX;
9370
2/2
✓ Branch 0 taken 18277 times.
✓ Branch 1 taken 5903 times.
24180 while (total_size <= atom.size - 8) {
9371 18277 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
9372 18277 a.size = avio_rb32(pb);
9373 18277 a.type = avio_rl32(pb);
9374
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 18273 times.
18277 if (avio_feof(pb))
9375 4 break;
9376
3/4
✓ Branch 0 taken 191 times.
✓ Branch 1 taken 18082 times.
✓ Branch 2 taken 191 times.
✗ Branch 3 not taken.
18273 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
9377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18273 times.
18273 a.type == MKTAG('h','o','o','v')) &&
9378 a.size >= 8 &&
9379 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
9380 uint32_t type;
9381 avio_skip(pb, 4);
9382 type = avio_rl32(pb);
9383 if (avio_feof(pb))
9384 break;
9385 avio_seek(pb, -8, SEEK_CUR);
9386 if (type == MKTAG('m','v','h','d') ||
9387 type == MKTAG('c','m','o','v')) {
9388 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
9389 a.type = MKTAG('m','o','o','v');
9390 }
9391 }
9392
2/2
✓ Branch 0 taken 15560 times.
✓ Branch 1 taken 2713 times.
18273 if (atom.type != MKTAG('r','o','o','t') &&
9393
2/2
✓ Branch 0 taken 14151 times.
✓ Branch 1 taken 1409 times.
15560 atom.type != MKTAG('m','o','o','v')) {
9394
1/2
✓ Branch 0 taken 14151 times.
✗ Branch 1 not taken.
14151 if (a.type == MKTAG('t','r','a','k') ||
9395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14151 times.
14151 a.type == MKTAG('m','d','a','t')) {
9396 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
9397 avio_skip(pb, -8);
9398 c->atom_depth --;
9399 480 return 0;
9400 }
9401 }
9402 18273 total_size += 8;
9403
3/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 18247 times.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
18273 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
9404 26 a.size = avio_rb64(pb) - 8;
9405 26 total_size += 8;
9406 }
9407 18273 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
9408 18273 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
9409
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 18268 times.
18273 if (a.size == 0) {
9410 5 a.size = atom.size - total_size + 8;
9411 }
9412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18273 times.
18273 if (a.size < 0)
9413 break;
9414 18273 a.size -= 8;
9415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18273 times.
18273 if (a.size < 0)
9416 break;
9417 18273 a.size = FFMIN(a.size, atom.size - total_size);
9418
9419
2/2
✓ Branch 0 taken 835082 times.
✓ Branch 1 taken 1852 times.
836934 for (i = 0; mov_default_parse_table[i].type; i++)
9420
2/2
✓ Branch 0 taken 16421 times.
✓ Branch 1 taken 818661 times.
835082 if (mov_default_parse_table[i].type == a.type) {
9421 16421 parse = mov_default_parse_table[i].parse;
9422 16421 break;
9423 }
9424
9425 // container is user data
9426
4/4
✓ Branch 0 taken 1852 times.
✓ Branch 1 taken 16421 times.
✓ Branch 2 taken 1677 times.
✓ Branch 3 taken 175 times.
18273 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
9427
2/2
✓ Branch 0 taken 299 times.
✓ Branch 1 taken 1378 times.
1677 atom.type == MKTAG('i','l','s','t')))
9428 474 parse = mov_read_udta_string;
9429
9430 // Supports parsing the QuickTime Metadata Keys.
9431 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
9432
4/4
✓ Branch 0 taken 1378 times.
✓ Branch 1 taken 16895 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 1367 times.
18273 if (!parse && c->found_hdlr_mdta &&
9433
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 atom.type == MKTAG('m','e','t','a') &&
9434
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 a.type == MKTAG('k','e','y','s') &&
9435
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 c->meta_keys_count == 0) {
9436 11 parse = mov_read_keys;
9437 }
9438
9439
2/2
✓ Branch 0 taken 1367 times.
✓ Branch 1 taken 16906 times.
18273 if (!parse) { /* skip leaf atoms data */
9440 1367 avio_skip(pb, a.size);
9441 } else {
9442 16906 int64_t start_pos = avio_tell(pb);
9443 int64_t left;
9444 16906 int err = parse(c, pb, a);
9445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16906 times.
16906 if (err < 0) {
9446 c->atom_depth --;
9447 return err;
9448 }
9449
5/6
✓ Branch 0 taken 3082 times.
✓ Branch 1 taken 13824 times.
✓ Branch 2 taken 2784 times.
✓ Branch 3 taken 298 times.
✓ Branch 4 taken 2784 times.
✗ Branch 5 not taken.
16906 if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos &&
9450
6/8
✓ Branch 0 taken 2784 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2784 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2776 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 472 times.
✓ Branch 7 taken 2304 times.
5560 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
9451 2776 start_pos + a.size == avio_size(pb))) {
9452
4/6
✓ Branch 0 taken 480 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 480 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 472 times.
480 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
9453 8 c->next_root_atom = start_pos + a.size;
9454 480 c->atom_depth --;
9455 480 return 0;
9456 }
9457 16426 left = a.size - avio_tell(pb) + start_pos;
9458
2/2
✓ Branch 0 taken 1317 times.
✓ Branch 1 taken 15109 times.
16426 if (left > 0) /* skip garbage at atom end */
9459 1317 avio_skip(pb, left);
9460
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 15107 times.
15109 else if (left < 0) {
9461 2 av_log(c->fc, AV_LOG_WARNING,
9462 "overread end of atom '%s' by %"PRId64" bytes\n",
9463 2 av_fourcc2str(a.type), -left);
9464 2 avio_seek(pb, left, SEEK_CUR);
9465 }
9466 }
9467
9468 17793 total_size += a.size;
9469 }
9470
9471
4/4
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 5801 times.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 4 times.
5907 if (total_size < atom.size && atom.size < 0x7ffff)
9472 102 avio_skip(pb, atom.size - total_size);
9473
9474 5907 c->atom_depth --;
9475 5907 return 0;
9476 }
9477
9478 7240 static int mov_probe(const AVProbeData *p)
9479 {
9480 int64_t offset;
9481 uint32_t tag;
9482 7240 int score = 0;
9483 7240 int moov_offset = -1;
9484
9485 /* check file header */
9486 7240 offset = 0;
9487 8919 for (;;) {
9488 int64_t size;
9489 16159 int minsize = 8;
9490 /* ignore invalid offset */
9491
2/2
✓ Branch 0 taken 7240 times.
✓ Branch 1 taken 8919 times.
16159 if ((offset + 8ULL) > (unsigned int)p->buf_size)
9492 7240 break;
9493 8919 size = AV_RB32(p->buf + offset);
9494
3/4
✓ Branch 0 taken 521 times.
✓ Branch 1 taken 8398 times.
✓ Branch 2 taken 521 times.
✗ Branch 3 not taken.
8919 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
9495 521 size = AV_RB64(p->buf+offset + 8);
9496 521 minsize = 16;
9497
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 8343 times.
8398 } else if (size == 0) {
9498 55 size = p->buf_size - offset;
9499 }
9500
2/2
✓ Branch 0 taken 399 times.
✓ Branch 1 taken 8520 times.
8919 if (size < minsize) {
9501 399 offset += 4;
9502 399 continue;
9503 }
9504 8520 tag = AV_RL32(p->buf + offset + 4);
9505
5/6
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 835 times.
✓ Branch 2 taken 356 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7205 times.
8520 switch(tag) {
9506 /* check for obvious tags */
9507 123 case MKTAG('m','o','o','v'):
9508 123 moov_offset = offset + 4;
9509 958 case MKTAG('m','d','a','t'):
9510 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
9511 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
9512 case MKTAG('f','t','y','p'):
9513
2/2
✓ Branch 0 taken 436 times.
✓ Branch 1 taken 522 times.
958 if (tag == MKTAG('f','t','y','p') &&
9514
1/2
✓ Branch 0 taken 436 times.
✗ Branch 1 not taken.
436 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
9515
1/2
✓ Branch 0 taken 436 times.
✗ Branch 1 not taken.
436 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
9516
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 430 times.
436 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
9517 )) {
9518 6 score = FFMAX(score, 5);
9519 } else {
9520 952 score = AVPROBE_SCORE_MAX;
9521 }
9522 958 break;
9523 /* those are more common words, so rate then a bit less */
9524 356 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
9525 case MKTAG('w','i','d','e'):
9526 case MKTAG('f','r','e','e'):
9527 case MKTAG('j','u','n','k'):
9528 case MKTAG('p','i','c','t'):
9529 356 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
9530 356 break;
9531 case MKTAG(0x82,0x82,0x7f,0x7d):
9532 score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
9533 break;
9534 1 case MKTAG('s','k','i','p'):
9535 case MKTAG('u','u','i','d'):
9536 case MKTAG('p','r','f','l'):
9537 /* if we only find those cause probedata is too small at least rate them */
9538 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
9539 1 break;
9540 }
9541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8520 times.
8520 if (size > INT64_MAX - offset)
9542 break;
9543 8520 offset += size;
9544 }
9545
4/4
✓ Branch 0 taken 467 times.
✓ Branch 1 taken 6773 times.
✓ Branch 2 taken 123 times.
✓ Branch 3 taken 344 times.
7240 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
9546 /* moov atom in the header - we should make sure that this is not a
9547 * MOV-packed MPEG-PS */
9548 123 offset = moov_offset;
9549
9550
2/2
✓ Branch 0 taken 120608 times.
✓ Branch 1 taken 123 times.
120731 while (offset < (p->buf_size - 16)) { /* Sufficient space */
9551 /* We found an actual hdlr atom */
9552
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 120476 times.
120608 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
9553
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 111 times.
132 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
9554
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
9555 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
9556 /* We found a media handler reference atom describing an
9557 * MPEG-PS-in-MOV, return a
9558 * low score to force expanding the probe window until
9559 * mpegps_probe finds what it needs */
9560 return 5;
9561 } else {
9562 /* Keep looking */
9563 120608 offset += 2;
9564 }
9565 }
9566 }
9567
9568 7240 return score;
9569 }
9570
9571 // must be done after parsing all trak because there's no order requirement
9572 2 static void mov_read_chapters(AVFormatContext *s)
9573 {
9574 2 MOVContext *mov = s->priv_data;
9575 MOVStreamContext *sc;
9576 int64_t cur_pos;
9577 int i, j;
9578 int chapter_track;
9579
9580
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
9581 2 AVStream *st = NULL;
9582 2 FFStream *sti = NULL;
9583 2 chapter_track = mov->chapter_tracks[j];
9584
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
9585 4 sc = mov->fc->streams[i]->priv_data;
9586
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
9587 2 st = s->streams[i];
9588 2 break;
9589 }
9590 }
9591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
9592 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
9593 continue;
9594 }
9595 2 sti = ffstream(st);
9596
9597 2 sc = st->priv_data;
9598 2 cur_pos = avio_tell(sc->pb);
9599
9600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
9601 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
9602 if (!st->attached_pic.data && sti->nb_index_entries) {
9603 // Retrieve the first frame, if possible
9604 AVIndexEntry *sample = &sti->index_entries[0];
9605 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9606 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
9607 goto finish;
9608 }
9609
9610 if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
9611 goto finish;
9612 }
9613 } else {
9614 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
9615 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
9616 2 st->discard = AVDISCARD_ALL;
9617
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
9618 8 AVIndexEntry *sample = &sti->index_entries[i];
9619
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;
9620 uint8_t *title;
9621 uint16_t ch;
9622 int len, title_len;
9623
9624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
9625 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
9626 end = AV_NOPTS_VALUE;
9627 }
9628
9629
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9630 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
9631 goto finish;
9632 }
9633
9634 // the first two bytes are the length of the title
9635 8 len = avio_rb16(sc->pb);
9636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
9637 continue;
9638 8 title_len = 2*len + 1;
9639
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
9640 goto finish;
9641
9642 // The samples could theoretically be in any encoding if there's an encd
9643 // atom following, but in practice are only utf-8 or utf-16, distinguished
9644 // instead by the presence of a BOM
9645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
9646 title[0] = 0;
9647 } else {
9648 8 ch = avio_rb16(sc->pb);
9649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
9650 avio_get_str16be(sc->pb, len, title, title_len);
9651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
9652 avio_get_str16le(sc->pb, len, title, title_len);
9653 else {
9654 8 AV_WB16(title, ch);
9655
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)
9656 title[len] = 0;
9657 else
9658 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
9659 }
9660 }
9661
9662 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
9663 8 av_freep(&title);
9664 }
9665 }
9666 2 finish:
9667 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
9668 }
9669 2 }
9670
9671 19 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
9672 int64_t value, int flags)
9673 {
9674 AVTimecode tc;
9675 char buf[AV_TIMECODE_STR_SIZE];
9676 19 AVRational rate = st->avg_frame_rate;
9677 19 int ret = av_timecode_init(&tc, rate, flags, 0, s);
9678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
9679 return ret;
9680 19 av_dict_set(&st->metadata, "timecode",
9681 19 av_timecode_make_string(&tc, buf, value), 0);
9682 19 return 0;
9683 }
9684
9685 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
9686 {
9687 MOVStreamContext *sc = st->priv_data;
9688 FFStream *const sti = ffstream(st);
9689 char buf[AV_TIMECODE_STR_SIZE];
9690 int64_t cur_pos = avio_tell(sc->pb);
9691 int hh, mm, ss, ff, drop;
9692
9693 if (!sti->nb_index_entries)
9694 return -1;
9695
9696 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9697 avio_skip(s->pb, 13);
9698 hh = avio_r8(s->pb);
9699 mm = avio_r8(s->pb);
9700 ss = avio_r8(s->pb);
9701 drop = avio_r8(s->pb);
9702 ff = avio_r8(s->pb);
9703 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
9704 hh, mm, ss, drop ? ';' : ':', ff);
9705 av_dict_set(&st->metadata, "timecode", buf, 0);
9706
9707 avio_seek(sc->pb, cur_pos, SEEK_SET);
9708 return 0;
9709 }
9710
9711 19 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
9712 {
9713 19 MOVStreamContext *sc = st->priv_data;
9714 19 FFStream *const sti = ffstream(st);
9715 19 int flags = 0;
9716 19 int64_t cur_pos = avio_tell(sc->pb);
9717 int64_t value;
9718 19 AVRational tc_rate = st->avg_frame_rate;
9719 19 int tmcd_nb_frames = sc->tmcd_nb_frames;
9720 int rounded_tc_rate;
9721
9722
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!sti->nb_index_entries)
9723 return -1;
9724
9725
3/6
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 19 times.
19 if (!tc_rate.num || !tc_rate.den || !tmcd_nb_frames)
9726 return -1;
9727
9728 19 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9729 19 value = avio_rb32(s->pb);
9730
9731
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13 times.
19 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
9732
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
9733
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
9734
9735 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
9736 * not the case) and thus assume "frame number format" instead of QT one.
9737 * No sample with tmcd track can be found with a QT timecode at the moment,
9738 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
9739 * format). */
9740
9741 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
9742 * we multiply the frame number with the quotient.
9743 * See tickets #9492, #9710. */
9744 19 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
9745 /* Work around files where tmcd_nb_frames is rounded down from frame rate
9746 * instead of up. See ticket #5978. */
9747
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
9748
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
9749 10 tmcd_nb_frames = rounded_tc_rate;
9750 19 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
9751
9752 19 parse_timecode_in_framenum_format(s, st, value, flags);
9753
9754 19 avio_seek(sc->pb, cur_pos, SEEK_SET);
9755 19 return 0;
9756 }
9757
9758 1050 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
9759 int i;
9760
3/4
✓ Branch 0 taken 1050 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1046 times.
✓ Branch 3 taken 4 times.
1050 if (!index || !*index) return;
9761
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 4 times.
76 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
9762 72 av_encryption_info_free((*index)->encrypted_samples[i]);
9763 }
9764 4 av_freep(&(*index)->encrypted_samples);
9765 4 av_freep(&(*index)->auxiliary_info_sizes);
9766 4 av_freep(&(*index)->auxiliary_offsets);
9767 4 av_freep(index);
9768 }
9769
9770 683 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
9771 {
9772 683 MOVStreamContext *sc = st->priv_data;
9773
9774
3/4
✓ Branch 0 taken 683 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 643 times.
683 if (!sc || --sc->refcount) {
9775 40 st->priv_data = NULL;
9776 40 return;
9777 }
9778
9779 643 av_freep(&sc->tts_data);
9780
2/2
✓ Branch 0 taken 598 times.
✓ Branch 1 taken 643 times.
1241 for (int i = 0; i < sc->drefs_count; i++) {
9781 598 av_freep(&sc->drefs[i].path);
9782 598 av_freep(&sc->drefs[i].dir);
9783 }
9784 643 av_freep(&sc->drefs);
9785
9786 643 sc->drefs_count = 0;
9787
9788
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 629 times.
643 if (!sc->pb_is_copied)
9789 14 ff_format_io_close(s, &sc->pb);
9790
9791 643 sc->pb = NULL;
9792 643 av_freep(&sc->chunk_offsets);
9793 643 av_freep(&sc->stsc_data);
9794 643 av_freep(&sc->sample_sizes);
9795 643 av_freep(&sc->keyframes);
9796 643 av_freep(&sc->ctts_data);
9797 643 av_freep(&sc->stts_data);
9798 643 av_freep(&sc->sdtp_data);
9799 643 av_freep(&sc->stps_data);
9800 643 av_freep(&sc->elst_data);
9801 643 av_freep(&sc->rap_group);
9802 643 av_freep(&sc->sync_group);
9803 643 av_freep(&sc->sgpd_sync);
9804 643 av_freep(&sc->sample_offsets);
9805 643 av_freep(&sc->open_key_samples);
9806 643 av_freep(&sc->display_matrix);
9807 643 av_freep(&sc->index_ranges);
9808
9809
2/2
✓ Branch 0 taken 598 times.
✓ Branch 1 taken 45 times.
643 if (sc->extradata)
9810
2/2
✓ Branch 0 taken 609 times.
✓ Branch 1 taken 598 times.
1207 for (int i = 0; i < sc->stsd_count; i++)
9811 609 av_free(sc->extradata[i]);
9812 643 av_freep(&sc->extradata);
9813 643 av_freep(&sc->extradata_size);
9814
9815 643 mov_free_encryption_index(&sc->cenc.encryption_index);
9816 643 av_encryption_info_free(sc->cenc.default_encrypted_sample);
9817 643 av_aes_ctr_free(sc->cenc.aes_ctr);
9818
9819 643 av_freep(&sc->stereo3d);
9820 643 av_freep(&sc->spherical);
9821 643 av_freep(&sc->mastering);
9822 643 av_freep(&sc->coll);
9823 643 av_freep(&sc->ambient);
9824
9825 #if CONFIG_IAMFDEC
9826
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 633 times.
643 if (sc->iamf)
9827 10 ff_iamf_read_deinit(sc->iamf);
9828 #endif
9829 643 av_freep(&sc->iamf);
9830 }
9831
9832 499 static int mov_read_close(AVFormatContext *s)
9833 {
9834 499 MOVContext *mov = s->priv_data;
9835 int i, j;
9836
9837
2/2
✓ Branch 0 taken 683 times.
✓ Branch 1 taken 499 times.
1182 for (i = 0; i < s->nb_streams; i++) {
9838 683 AVStream *st = s->streams[i];
9839
9840 683 mov_free_stream_context(s, st);
9841 }
9842
9843 499 av_freep(&mov->dv_demux);
9844 499 avformat_free_context(mov->dv_fctx);
9845 499 mov->dv_fctx = NULL;
9846
9847
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 488 times.
499 if (mov->meta_keys) {
9848
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i < mov->meta_keys_count; i++) {
9849 58 av_freep(&mov->meta_keys[i]);
9850 }
9851 11 av_freep(&mov->meta_keys);
9852 }
9853
9854 499 av_freep(&mov->trex_data);
9855 499 av_freep(&mov->bitrates);
9856
9857
2/2
✓ Branch 0 taken 389 times.
✓ Branch 1 taken 499 times.
888 for (i = 0; i < mov->frag_index.nb_items; i++) {
9858 389 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
9859
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 389 times.
796 for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) {
9860 407 mov_free_encryption_index(&frag[j].encryption_index);
9861 }
9862 389 av_freep(&mov->frag_index.item[i].stream_info);
9863 }
9864 499 av_freep(&mov->frag_index.item);
9865
9866 499 av_freep(&mov->aes_decrypt);
9867 499 av_freep(&mov->chapter_tracks);
9868
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 499 times.
541 for (i = 0; i < mov->nb_heif_item; i++) {
9869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!mov->heif_item[i])
9870 continue;
9871 42 av_freep(&mov->heif_item[i]->name);
9872 42 av_freep(&mov->heif_item[i]->icc_profile);
9873 42 av_freep(&mov->heif_item[i]);
9874 }
9875 499 av_freep(&mov->heif_item);
9876
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 499 times.
505 for (i = 0; i < mov->nb_heif_grid; i++) {
9877 6 av_freep(&mov->heif_grid[i].tile_id_list);
9878 6 av_freep(&mov->heif_grid[i].tile_idx_list);
9879 6 av_freep(&mov->heif_grid[i].tile_item_list);
9880 }
9881 499 av_freep(&mov->heif_grid);
9882 499 av_freep(&mov->thmb_item_id);
9883
9884 499 return 0;
9885 }
9886
9887 16 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
9888 {
9889 int i;
9890
9891
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 for (i = 0; i < s->nb_streams; i++) {
9892 24 AVStream *st = s->streams[i];
9893 24 MOVStreamContext *sc = st->priv_data;
9894
9895
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
9896
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 sc->timecode_track == tmcd_id)
9897 14 return 1;
9898 }
9899 2 return 0;
9900 }
9901
9902 /* look for a tmcd track not referenced by any video track, and export it globally */
9903 499 static void export_orphan_timecode(AVFormatContext *s)
9904 {
9905 int i;
9906
9907
2/2
✓ Branch 0 taken 680 times.
✓ Branch 1 taken 497 times.
1177 for (i = 0; i < s->nb_streams; i++) {
9908 680 AVStream *st = s->streams[i];
9909
9910
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 664 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 14 times.
696 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
9911 16 !tmcd_is_referenced(s, i + 1)) {
9912 2 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
9913
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (tcr) {
9914 2 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
9915 2 break;
9916 }
9917 }
9918 }
9919 499 }
9920
9921 static int read_tfra(MOVContext *mov, AVIOContext *f)
9922 {
9923 int version, fieldlength, i, j;
9924 int64_t pos = avio_tell(f);
9925 uint32_t size = avio_rb32(f);
9926 unsigned track_id, item_count;
9927
9928 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
9929 return 1;
9930 }
9931 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
9932
9933 version = avio_r8(f);
9934 avio_rb24(f);
9935 track_id = avio_rb32(f);
9936 fieldlength = avio_rb32(f);
9937 item_count = avio_rb32(f);
9938 for (i = 0; i < item_count; i++) {
9939 int64_t time, offset;
9940 int index;
9941 MOVFragmentStreamInfo * frag_stream_info;
9942
9943 if (avio_feof(f)) {
9944 return AVERROR_INVALIDDATA;
9945 }
9946
9947 if (version == 1) {
9948 time = avio_rb64(f);
9949 offset = avio_rb64(f);
9950 } else {
9951 time = avio_rb32(f);
9952 offset = avio_rb32(f);
9953 }
9954
9955 // The first sample of each stream in a fragment is always a random
9956 // access sample. So it's entry in the tfra can be used as the
9957 // initial PTS of the fragment.
9958 index = update_frag_index(mov, offset);
9959 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
9960 if (frag_stream_info &&
9961 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
9962 frag_stream_info->first_tfra_pts = time;
9963
9964 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
9965 avio_r8(f);
9966 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
9967 avio_r8(f);
9968 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
9969 avio_r8(f);
9970 }
9971
9972 avio_seek(f, pos + size, SEEK_SET);
9973 return 0;
9974 }
9975
9976 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
9977 {
9978 int64_t stream_size = avio_size(f);
9979 int64_t original_pos = avio_tell(f);
9980 int64_t seek_ret;
9981 int ret = -1;
9982 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
9983 ret = seek_ret;
9984 goto fail;
9985 }
9986 c->mfra_size = avio_rb32(f);
9987 c->have_read_mfra_size = 1;
9988 if (!c->mfra_size || c->mfra_size > stream_size) {
9989 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
9990 goto fail;
9991 }
9992 if ((seek_ret = avio_seek(f, -((int64_t) c->mfra_size), SEEK_CUR)) < 0) {
9993 ret = seek_ret;
9994 goto fail;
9995 }
9996 if (avio_rb32(f) != c->mfra_size) {
9997 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
9998 goto fail;
9999 }
10000 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
10001 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
10002 goto fail;
10003 }
10004 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
10005 do {
10006 ret = read_tfra(c, f);
10007 if (ret < 0)
10008 goto fail;
10009 } while (!ret);
10010 ret = 0;
10011 c->frag_index.complete = 1;
10012 fail:
10013 seek_ret = avio_seek(f, original_pos, SEEK_SET);
10014 if (seek_ret < 0) {
10015 av_log(c->fc, AV_LOG_ERROR,
10016 "failed to seek back after looking for mfra\n");
10017 ret = seek_ret;
10018 }
10019 return ret;
10020 }
10021
10022 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10023 const HEIFItem *item)
10024 {
10025 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
10026 AV_PKT_DATA_ICC_PROFILE,
10027 item->icc_profile_size, 0);
10028 if (!sd)
10029 return AVERROR(ENOMEM);
10030
10031 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
10032
10033 return 0;
10034 }
10035
10036 6 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10037 const HEIFItem *item)
10038 {
10039 int32_t *matrix;
10040 6 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data,
10041 nb_coded_side_data,
10042 AV_PKT_DATA_DISPLAYMATRIX,
10043 9 * sizeof(*matrix), 0);
10044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sd)
10045 return AVERROR(ENOMEM);
10046
10047 6 matrix = (int32_t*)sd->data;
10048 /* rotation is in the counter-clockwise direction whereas
10049 * av_display_rotation_set() expects its argument to be
10050 * oriented clockwise, so we need to negate it. */
10051 6 av_display_rotation_set(matrix, -item->rotation);
10052 6 av_display_matrix_flip(matrix, item->hflip, item->vflip);
10053
10054 6 return 0;
10055 }
10056
10057 2 static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid,
10058 AVStreamGroupTileGrid *tile_grid)
10059 {
10060 2 MOVContext *c = s->priv_data;
10061 2 const HEIFItem *item = grid->item;
10062 2 int64_t offset = 0, pos = avio_tell(s->pb);
10063 2 int x = 0, y = 0, i = 0;
10064 int tile_rows, tile_cols;
10065 int flags, size;
10066
10067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10068 av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
10069 return AVERROR_PATCHWELCOME;
10070 }
10071
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (item->is_idat_relative) {
10072
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!c->idat_offset) {
10073 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
10074 return AVERROR_INVALIDDATA;
10075 }
10076 2 offset = c->idat_offset;
10077 }
10078
10079 2 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10080
10081 2 avio_r8(s->pb); /* version */
10082 2 flags = avio_r8(s->pb);
10083
10084 2 tile_rows = avio_r8(s->pb) + 1;
10085 2 tile_cols = avio_r8(s->pb) + 1;
10086 /* actual width and height of output image */
10087
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 tile_grid->width = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
10088
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 tile_grid->height = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
10089
10090 /* ICC profile */
10091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (item->icc_profile_size) {
10092 int ret = set_icc_profile_from_item(&tile_grid->coded_side_data,
10093 &tile_grid->nb_coded_side_data, item);
10094 if (ret < 0)
10095 return ret;
10096 }
10097 /* rotation */
10098
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 if (item->rotation || item->hflip || item->vflip) {
10099 int ret = set_display_matrix_from_item(&tile_grid->coded_side_data,
10100 &tile_grid->nb_coded_side_data, item);
10101 if (ret < 0)
10102 return ret;
10103 }
10104
10105 2 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
10106 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
10107
10108 2 avio_seek(s->pb, pos, SEEK_SET);
10109
10110 2 size = tile_rows * tile_cols;
10111 2 tile_grid->nb_tiles = grid->nb_tiles;
10112
10113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tile_grid->nb_tiles != size)
10114 return AVERROR_INVALIDDATA;
10115
10116
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < tile_cols; i++)
10117 4 tile_grid->coded_width += grid->tile_item_list[i]->width;
10118
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < size; i += tile_cols)
10119 4 tile_grid->coded_height += grid->tile_item_list[i]->height;
10120
10121 2 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!tile_grid->offsets)
10123 return AVERROR(ENOMEM);
10124
10125
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 while (y < tile_grid->coded_height) {
10126 4 int left_col = i;
10127
10128
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 while (x < tile_grid->coded_width) {
10129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (i == tile_grid->nb_tiles)
10130 return AVERROR_INVALIDDATA;
10131
10132 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10133 8 tile_grid->offsets[i].horizontal = x;
10134 8 tile_grid->offsets[i].vertical = y;
10135
10136 8 x += grid->tile_item_list[i++]->width;
10137 }
10138
10139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (x > tile_grid->coded_width) {
10140 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10141 return AVERROR_INVALIDDATA;
10142 }
10143
10144 4 x = 0;
10145 4 y += grid->tile_item_list[left_col]->height;
10146 }
10147
10148
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (y > tile_grid->coded_height || i != tile_grid->nb_tiles) {
10149 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10150 return AVERROR_INVALIDDATA;
10151 }
10152
10153 2 return 0;
10154 }
10155
10156 4 static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid,
10157 AVStreamGroupTileGrid *tile_grid)
10158 {
10159 4 MOVContext *c = s->priv_data;
10160 4 const HEIFItem *item = grid->item;
10161 uint16_t canvas_fill_value[4];
10162 4 int64_t offset = 0, pos = avio_tell(s->pb);
10163 4 int ret = 0, flags;
10164
10165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10166 av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
10167 return AVERROR_PATCHWELCOME;
10168 }
10169
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
10170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
10171 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
10172 return AVERROR_INVALIDDATA;
10173 }
10174 4 offset = c->idat_offset;
10175 }
10176
10177 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10178
10179 4 avio_r8(s->pb); /* version */
10180 4 flags = avio_r8(s->pb);
10181
10182
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10183 16 canvas_fill_value[i] = avio_rb16(s->pb);
10184 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
10185 4 canvas_fill_value[0], canvas_fill_value[1],
10186 4 canvas_fill_value[2], canvas_fill_value[3]);
10187
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10188 16 tile_grid->background[i] = canvas_fill_value[i];
10189
10190 /* actual width and height of output image */
10191 4 tile_grid->width =
10192
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);
10193 4 tile_grid->height =
10194
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);
10195
10196 /* rotation */
10197
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
4 if (item->rotation || item->hflip || item->vflip) {
10198 int ret = set_display_matrix_from_item(&tile_grid->coded_side_data,
10199 &tile_grid->nb_coded_side_data, item);
10200 if (ret < 0)
10201 return ret;
10202 }
10203
10204 /* ICC profile */
10205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (item->icc_profile_size) {
10206 int ret = set_icc_profile_from_item(&tile_grid->coded_side_data,
10207 &tile_grid->nb_coded_side_data, item);
10208 if (ret < 0)
10209 return ret;
10210 }
10211
10212 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
10213 tile_grid->width, tile_grid->height);
10214
10215 4 tile_grid->nb_tiles = grid->nb_tiles;
10216 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
10218 ret = AVERROR(ENOMEM);
10219 goto fail;
10220 }
10221
10222
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
10223 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10224
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);
10225
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);
10226 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
10227 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
10228 8 i, tile_grid->offsets[i].idx,
10229 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
10230 }
10231
10232 4 fail:
10233 4 avio_seek(s->pb, pos, SEEK_SET);
10234
10235 4 return ret;
10236 }
10237
10238 6 static int mov_parse_tiles(AVFormatContext *s)
10239 {
10240 6 MOVContext *mov = s->priv_data;
10241
10242
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (int i = 0; i < mov->nb_heif_grid; i++) {
10243 6 AVStreamGroup *stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
10244 AVStreamGroupTileGrid *tile_grid;
10245 6 const HEIFGrid *grid = &mov->heif_grid[i];
10246 6 int err, loop = 1;
10247
10248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!stg)
10249 return AVERROR(ENOMEM);
10250
10251 6 stg->id = grid->item->item_id;
10252 6 tile_grid = stg->params.tile_grid;
10253
10254
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (int j = 0; j < grid->nb_tiles; j++) {
10255 16 int tile_id = grid->tile_id_list[j];
10256 int k;
10257
10258
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 for (k = 0; k < mov->nb_heif_item; k++) {
10259 30 HEIFItem *item = mov->heif_item[k];
10260 AVStream *st;
10261
10262
3/4
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 16 times.
30 if (!item || item->item_id != tile_id)
10263 14 continue;
10264 16 st = item->st;
10265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!st) {
10266 av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
10267 "reference a stream\n",
10268 tile_id, grid->item->item_id);
10269 ff_remove_stream_group(s, stg);
10270 loop = 0;
10271 break;
10272 }
10273
10274 16 grid->tile_item_list[j] = item;
10275 16 grid->tile_idx_list[j] = stg->nb_streams;
10276
10277 16 err = avformat_stream_group_add_stream(stg, st);
10278
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (err < 0) {
10279 int l;
10280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
10281 return err;
10282
10283
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_streams; l++)
10284
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->streams[l]->index == st->index)
10285 2 break;
10286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_streams);
10287 2 grid->tile_idx_list[j] = l;
10288 }
10289
10290
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
16 if (item->item_id != mov->primary_item_id)
10291 10 st->disposition |= AV_DISPOSITION_DEPENDENT;
10292 16 break;
10293 }
10294
10295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (k == mov->nb_heif_item) {
10296 av_assert0(loop);
10297 av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
10298 "exist\n",
10299 tile_id, grid->item->item_id);
10300 ff_remove_stream_group(s, stg);
10301 loop = 0;
10302 }
10303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!loop)
10304 break;
10305 }
10306
10307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!loop)
10308 continue;
10309
10310
2/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
6 switch (grid->item->type) {
10311 2 case MKTAG('g','r','i','d'):
10312 2 err = read_image_grid(s, grid, tile_grid);
10313 2 break;
10314 4 case MKTAG('i','o','v','l'):
10315 4 err = read_image_iovl(s, grid, tile_grid);
10316 4 break;
10317 default:
10318 av_assert0(0);
10319 }
10320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10321 return err;
10322
10323
10324
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (grid->item->name)
10325 6 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
10326
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (grid->item->item_id == mov->primary_item_id)
10327 2 stg->disposition |= AV_DISPOSITION_DEFAULT;
10328 }
10329
10330 6 return 0;
10331 }
10332
10333 15 static int mov_parse_heif_items(AVFormatContext *s)
10334 {
10335 15 MOVContext *mov = s->priv_data;
10336 int err;
10337
10338
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 15 times.
57 for (int i = 0; i < mov->nb_heif_item; i++) {
10339 42 HEIFItem *item = mov->heif_item[i];
10340 MOVStreamContext *sc;
10341 AVStream *st;
10342 42 int64_t offset = 0;
10343
10344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!item)
10345 continue;
10346
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 31 times.
42 if (!item->st) {
10347
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 11 times.
19 for (int j = 0; j < mov->nb_thmb_item; j++) {
10348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (item->item_id == mov->thmb_item_id[j]) {
10349 av_log(s, AV_LOG_ERROR, "HEIF thumbnail ID %d doesn't reference a stream\n",
10350 item->item_id);
10351 return AVERROR_INVALIDDATA;
10352 }
10353 }
10354 11 continue;
10355 }
10356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (item->is_idat_relative) {
10357 if (!mov->idat_offset) {
10358 av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
10359 return AVERROR_INVALIDDATA;
10360 }
10361 offset = mov->idat_offset;
10362 }
10363
10364 31 st = item->st;
10365 31 sc = st->priv_data;
10366 31 st->codecpar->width = item->width;
10367 31 st->codecpar->height = item->height;
10368
10369 31 err = sanity_checks(s, sc, item->item_id);
10370
2/4
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 31 times.
31 if (err || !sc->sample_count)
10371 return AVERROR_INVALIDDATA;
10372
10373 31 sc->sample_sizes[0] = item->extent_length;
10374 31 sc->chunk_offsets[0] = item->extent_offset + offset;
10375
10376
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 18 times.
31 if (item->item_id == mov->primary_item_id)
10377 13 st->disposition |= AV_DISPOSITION_DEFAULT;
10378
10379
4/6
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 25 times.
31 if (item->rotation || item->hflip || item->vflip) {
10380 6 err = set_display_matrix_from_item(&st->codecpar->coded_side_data,
10381 6 &st->codecpar->nb_coded_side_data, item);
10382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10383 return err;
10384 }
10385
10386 31 mov_build_index(mov, st);
10387 }
10388
10389
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
15 if (mov->nb_heif_grid) {
10390 6 err = mov_parse_tiles(s);
10391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10392 return err;
10393 }
10394
10395 15 return 0;
10396 }
10397
10398 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
10399 int first_index)
10400 {
10401 MOVStreamContext *sc = st->priv_data;
10402
10403 if (sc->tref_id < 0)
10404 return NULL;
10405
10406 for (int i = first_index; i < s->nb_streams; i++)
10407 if (s->streams[i]->id == sc->tref_id)
10408 return s->streams[i];
10409
10410 return NULL;
10411 }
10412
10413 499 static int mov_parse_lcevc_streams(AVFormatContext *s)
10414 {
10415 int err;
10416
10417
2/2
✓ Branch 0 taken 683 times.
✓ Branch 1 taken 499 times.
1182 for (int i = 0; i < s->nb_streams; i++) {
10418 AVStreamGroup *stg;
10419 683 AVStream *st = s->streams[i];
10420 AVStream *st_base;
10421 683 MOVStreamContext *sc = st->priv_data;
10422 683 int j = 0;
10423
10424 /* Find an enhancement stream. */
10425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 683 times.
683 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC ||
10426 !(sc->tref_flags & MOV_TREF_FLAG_ENHANCEMENT))
10427 683 continue;
10428
10429 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10430
10431 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
10432 if (!stg)
10433 return AVERROR(ENOMEM);
10434
10435 stg->id = st->id;
10436 stg->params.lcevc->width = st->codecpar->width;
10437 stg->params.lcevc->height = st->codecpar->height;
10438 st->codecpar->width = 0;
10439 st->codecpar->height = 0;
10440
10441 while (st_base = mov_find_reference_track(s, st, j)) {
10442 err = avformat_stream_group_add_stream(stg, st_base);
10443 if (err < 0)
10444 return err;
10445
10446 j = st_base->index + 1;
10447 }
10448 if (!j) {
10449 av_log(s, AV_LOG_ERROR, "Failed to find base stream for enhancement stream\n");
10450 return AVERROR_INVALIDDATA;
10451 }
10452
10453 err = avformat_stream_group_add_stream(stg, st);
10454 if (err < 0)
10455 return err;
10456
10457 stg->params.lcevc->lcevc_index = stg->nb_streams - 1;
10458 }
10459
10460 499 return 0;
10461 }
10462
10463 499 static void fix_stream_ids(AVFormatContext *s)
10464 {
10465 499 int highest_id = 0;
10466
10467
2/2
✓ Branch 0 taken 683 times.
✓ Branch 1 taken 499 times.
1182 for (int i = 0; i < s->nb_streams; i++) {
10468 683 const AVStream *st = s->streams[i];
10469 683 const MOVStreamContext *sc = st->priv_data;
10470
2/2
✓ Branch 0 taken 633 times.
✓ Branch 1 taken 50 times.
683 if (!sc->iamf)
10471 633 highest_id = FFMAX(highest_id, st->id);
10472 }
10473 499 highest_id += !highest_id;
10474
4/4
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 411 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 88 times.
509 for (int i = 0; highest_id > 1 && i < s->nb_stream_groups; i++) {
10475 10 AVStreamGroup *stg = s->stream_groups[i];
10476
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
10477 8 continue;
10478
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_streams; j++) {
10479 14 AVStream *st = stg->streams[j];
10480 14 MOVStreamContext *sc = st->priv_data;
10481 14 st->id += highest_id;
10482 14 sc->iamf_stream_offset = highest_id;
10483 }
10484 }
10485 499 }
10486
10487 499 static int mov_read_header(AVFormatContext *s)
10488 {
10489 499 MOVContext *mov = s->priv_data;
10490 499 AVIOContext *pb = s->pb;
10491 int j, err;
10492 499 MOVAtom atom = { AV_RL32("root") };
10493 int i;
10494
10495
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 496 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
499 if (mov->decryption_key_len != 0 && mov->decryption_key_len != AES_CTR_KEY_SIZE) {
10496 av_log(s, AV_LOG_ERROR, "Invalid decryption key len %d expected %d\n",
10497 mov->decryption_key_len, AES_CTR_KEY_SIZE);
10498 return AVERROR(EINVAL);
10499 }
10500
10501 499 mov->fc = s;
10502 499 mov->trak_index = -1;
10503 499 mov->thmb_item_id = NULL;
10504 499 mov->primary_item_id = -1;
10505 499 mov->cur_item_id = -1;
10506 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
10507
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
10508 499 atom.size = avio_size(pb);
10509 else
10510 atom.size = INT64_MAX;
10511
10512 /* check MOV header */
10513 do {
10514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (mov->moov_retry)
10515 avio_seek(pb, 0, SEEK_SET);
10516
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 499 times.
499 if ((err = mov_read_default(mov, pb, atom)) < 0) {
10517 av_log(s, AV_LOG_ERROR, "error reading header\n");
10518 return err;
10519 }
10520 998 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10521
5/10
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 484 times.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 15 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
499 !mov->found_moov && (!mov->found_iloc || !mov->found_iinf) && !mov->moov_retry++);
10522
3/6
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 484 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
499 if (!mov->found_moov && !mov->found_iloc && !mov->found_iinf) {
10523 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
10524 return AVERROR_INVALIDDATA;
10525 }
10526 499 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
10527
10528
3/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 484 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
499 if (mov->found_iloc && mov->found_iinf) {
10529 15 err = mov_parse_heif_items(s);
10530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (err < 0)
10531 return err;
10532 }
10533 // prevent iloc and iinf boxes from being parsed while reading packets.
10534 // this is needed because an iinf box may have been parsed but ignored
10535 // for having old infe boxes which create no streams.
10536 499 mov->found_iloc = mov->found_iinf = 1;
10537
10538
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
10539
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 497 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
499 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
10540 2 mov_read_chapters(s);
10541
2/2
✓ Branch 0 taken 683 times.
✓ Branch 1 taken 499 times.
1182 for (i = 0; i < s->nb_streams; i++)
10542
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 664 times.
683 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
10543 19 mov_read_timecode_track(s, s->streams[i]);
10544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 664 times.
664 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
10545 mov_read_rtmd_track(s, s->streams[i]);
10546 }
10547 }
10548
10549 /* copy timecode metadata from tmcd tracks to the related video streams */
10550
2/2
✓ Branch 0 taken 683 times.
✓ Branch 1 taken 499 times.
1182 for (i = 0; i < s->nb_streams; i++) {
10551 683 AVStream *st = s->streams[i];
10552 683 MOVStreamContext *sc = st->priv_data;
10553
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 665 times.
683 if (sc->timecode_track > 0) {
10554 AVDictionaryEntry *tcr;
10555 18 int tmcd_st_id = -1;
10556
10557
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 18 times.
66 for (j = 0; j < s->nb_streams; j++) {
10558 48 MOVStreamContext *sc2 = s->streams[j]->priv_data;
10559
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 30 times.
48 if (sc2->id == sc->timecode_track)
10560 18 tmcd_st_id = j;
10561 }
10562
10563
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (tmcd_st_id < 0 || tmcd_st_id == i)
10564 continue;
10565 18 tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
10566
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 if (tcr)
10567 16 av_dict_set(&st->metadata, "timecode", tcr->value, 0);
10568 }
10569 }
10570 499 export_orphan_timecode(s);
10571
10572 /* Create LCEVC stream groups. */
10573 499 err = mov_parse_lcevc_streams(s);
10574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (err < 0)
10575 return err;
10576
10577
2/2
✓ Branch 0 taken 683 times.
✓ Branch 1 taken 499 times.
1182 for (i = 0; i < s->nb_streams; i++) {
10578 683 AVStream *st = s->streams[i];
10579 683 FFStream *const sti = ffstream(st);
10580 683 MOVStreamContext *sc = st->priv_data;
10581 683 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
10582 683 fix_timescale(mov, sc);
10583
2/2
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 402 times.
683 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
10584
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 165 times.
281 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
10585 116 sti->skip_samples = sc->start_pad;
10586 }
10587
5/6
✓ Branch 0 taken 351 times.
✓ Branch 1 taken 332 times.
✓ Branch 2 taken 306 times.
✓ Branch 3 taken 45 times.
✓ Branch 4 taken 306 times.
✗ Branch 5 not taken.
683 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
10588 306 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
10589 306 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
10590
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 675 times.
683 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
10591
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
8 if (st->codecpar->width <= 0 || st->codecpar->height <= 0) {
10592 4 st->codecpar->width = sc->width;
10593 4 st->codecpar->height = sc->height;
10594 }
10595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
10596 st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
10597
10598 for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
10599 dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
10600
10601 err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
10602 if (err < 0)
10603 return err;
10604
10605 av_freep(&st->codecpar->extradata);
10606 st->codecpar->extradata_size = 0;
10607
10608 err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
10609 st->codecpar);
10610 if (err < 0)
10611 return err;
10612 }
10613 }
10614
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 683 times.
683 if (mov->handbrake_version &&
10615 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
10616 st->codecpar->codec_id == AV_CODEC_ID_MP3) {
10617 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
10618 sti->need_parsing = AVSTREAM_PARSE_FULL;
10619 }
10620 }
10621
10622
3/4
✓ Branch 0 taken 487 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 487 times.
499 if (mov->trex_data || mov->use_mfra_for > 0) {
10623
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 12 times.
29 for (i = 0; i < s->nb_streams; i++) {
10624 17 AVStream *st = s->streams[i];
10625 17 MOVStreamContext *sc = st->priv_data;
10626
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 3 times.
17 if (sc->duration_for_fps > 0) {
10627 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
10628 14 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
10629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (st->codecpar->bit_rate == INT64_MIN) {
10630 av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
10631 sc->data_size, sc->time_scale);
10632 st->codecpar->bit_rate = 0;
10633 if (s->error_recognition & AV_EF_EXPLODE)
10634 return AVERROR_INVALIDDATA;
10635 }
10636 }
10637 }
10638 }
10639
10640
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
499 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
10641 if (mov->bitrates[i]) {
10642 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
10643 }
10644 }
10645
10646 499 ff_rfps_calculate(s);
10647
10648
2/2
✓ Branch 0 taken 683 times.
✓ Branch 1 taken 499 times.
1182 for (i = 0; i < s->nb_streams; i++) {
10649 683 AVStream *st = s->streams[i];
10650 683 MOVStreamContext *sc = st->priv_data;
10651
10652
3/3
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 351 times.
✓ Branch 2 taken 51 times.
683 switch (st->codecpar->codec_type) {
10653 281 case AVMEDIA_TYPE_AUDIO:
10654 281 err = ff_replaygain_export(st, s->metadata);
10655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 281 times.
281 if (err < 0)
10656 return err;
10657 281 break;
10658 351 case AVMEDIA_TYPE_VIDEO:
10659
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 343 times.
351 if (sc->display_matrix) {
10660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10661 AV_PKT_DATA_DISPLAYMATRIX,
10662 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
10663 return AVERROR(ENOMEM);
10664
10665 8 sc->display_matrix = NULL;
10666 }
10667
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 347 times.
351 if (sc->stereo3d) {
10668
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,
10669 AV_PKT_DATA_STEREO3D,
10670 4 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
10671 return AVERROR(ENOMEM);
10672
10673 4 sc->stereo3d = NULL;
10674 }
10675
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 347 times.
351 if (sc->spherical) {
10676
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,
10677 AV_PKT_DATA_SPHERICAL,
10678 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
10679 return AVERROR(ENOMEM);
10680
10681 4 sc->spherical = NULL;
10682 }
10683
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 351 times.
351 if (sc->mastering) {
10684 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10685 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
10686 (uint8_t *)sc->mastering, sc->mastering_size, 0))
10687 return AVERROR(ENOMEM);
10688
10689 sc->mastering = NULL;
10690 }
10691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 351 times.
351 if (sc->coll) {
10692 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10693 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
10694 (uint8_t *)sc->coll, sc->coll_size, 0))
10695 return AVERROR(ENOMEM);
10696
10697 sc->coll = NULL;
10698 }
10699
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 347 times.
351 if (sc->ambient) {
10700
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,
10701 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
10702 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
10703 return AVERROR(ENOMEM);
10704
10705 4 sc->ambient = NULL;
10706 }
10707 351 break;
10708 }
10709 }
10710
10711 499 fix_stream_ids(s);
10712
10713 499 ff_configure_buffers_for_index(s, AV_TIME_BASE);
10714
10715
2/2
✓ Branch 0 taken 389 times.
✓ Branch 1 taken 499 times.
888 for (i = 0; i < mov->frag_index.nb_items; i++)
10716
2/2
✓ Branch 0 taken 385 times.
✓ Branch 1 taken 4 times.
389 if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset)
10717 385 mov->frag_index.item[i].headers_read = 1;
10718
10719 499 return 0;
10720 }
10721
10722 103944 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
10723 {
10724 103944 AVIndexEntry *sample = NULL;
10725 103944 int64_t best_dts = INT64_MAX;
10726 int i;
10727 103944 MOVContext *mov = s->priv_data;
10728
2/4
✓ Branch 0 taken 103944 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 103944 times.
103944 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
10729
2/2
✓ Branch 0 taken 133807 times.
✓ Branch 1 taken 103944 times.
237751 for (i = 0; i < s->nb_streams; i++) {
10730 133807 AVStream *avst = s->streams[i];
10731 133807 FFStream *const avsti = ffstream(avst);
10732 133807 MOVStreamContext *msc = avst->priv_data;
10733
4/4
✓ Branch 0 taken 125569 times.
✓ Branch 1 taken 8238 times.
✓ Branch 2 taken 122267 times.
✓ Branch 3 taken 3302 times.
133807 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
10734 122267 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
10735 122267 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
10736
2/2
✓ Branch 0 taken 108582 times.
✓ Branch 1 taken 13685 times.
122267 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
10737 122267 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
10738
3/6
✓ Branch 0 taken 18818 times.
✓ Branch 1 taken 103449 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18818 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
122267 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
10739
1/2
✓ Branch 0 taken 18818 times.
✗ Branch 1 not taken.
18818 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10740
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 18818 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 18818 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18818 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 16701 times.
✓ Branch 9 taken 2117 times.
18818 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
10741
4/4
✓ Branch 0 taken 8578 times.
✓ Branch 1 taken 8123 times.
✓ Branch 2 taken 2117 times.
✓ Branch 3 taken 8578 times.
18818 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
10742
3/4
✓ Branch 0 taken 714 times.
✓ Branch 1 taken 1403 times.
✓ Branch 2 taken 714 times.
✗ Branch 3 not taken.
2117 (dtsdiff > AV_TIME_BASE && dts < best_dts && mov->interleaved_read)))))) {
10743 112286 sample = current_sample;
10744 112286 best_dts = dts;
10745 112286 *st = avst;
10746 }
10747 }
10748 }
10749 103944 return sample;
10750 }
10751
10752 9 static int should_retry(AVIOContext *pb, int error_code) {
10753
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
9 if (error_code == AVERROR_EOF || avio_feof(pb))
10754 9 return 0;
10755
10756 return 1;
10757 }
10758
10759 42 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
10760 {
10761 int ret;
10762 42 MOVContext *mov = s->priv_data;
10763
10764
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
42 if (index >= 0 && index < mov->frag_index.nb_items)
10765 target = mov->frag_index.item[index].moof_offset;
10766
2/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 42 times.
42 if (target >= 0 && avio_seek(s->pb, target, SEEK_SET) != target) {
10767 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
10768 return AVERROR_INVALIDDATA;
10769 }
10770
10771 42 mov->next_root_atom = 0;
10772
2/6
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 42 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
42 if ((index < 0 && target >= 0) || index >= mov->frag_index.nb_items)
10773 42 index = search_frag_moof_offset(&mov->frag_index, target);
10774
3/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 4 times.
42 if (index >= 0 && index < mov->frag_index.nb_items &&
10775
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 mov->frag_index.item[index].moof_offset == target) {
10776
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (index + 1 < mov->frag_index.nb_items)
10777 35 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
10778
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (mov->frag_index.item[index].headers_read)
10779 35 return 0;
10780 3 mov->frag_index.item[index].headers_read = 1;
10781 }
10782
10783 7 mov->found_mdat = 0;
10784
10785 7 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
10786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
10787 return ret;
10788
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 3 times.
7 if (avio_feof(s->pb))
10789 4 return AVERROR_EOF;
10790 3 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
10791
10792 3 return 1;
10793 }
10794
10795 16 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
10796 {
10797 16 MOVStreamContext *sc = st->priv_data;
10798 uint8_t *side, *extradata;
10799 int extradata_size;
10800
10801 /* Save the current index. */
10802 16 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
10803
10804 /* Notify the decoder that extradata changed. */
10805 16 extradata_size = sc->extradata_size[sc->last_stsd_index];
10806 16 extradata = sc->extradata[sc->last_stsd_index];
10807
4/6
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
16 if (st->discard != AVDISCARD_ALL && extradata_size > 0 && extradata) {
10808 13 side = av_packet_new_side_data(pkt,
10809 AV_PKT_DATA_NEW_EXTRADATA,
10810 extradata_size);
10811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!side)
10812 return AVERROR(ENOMEM);
10813 13 memcpy(side, extradata, extradata_size);
10814 }
10815
10816 16 return 0;
10817 }
10818
10819 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
10820 {
10821 /* We can't make assumptions about the structure of the payload,
10822 because it may include multiple cdat and cdt2 samples. */
10823 const uint32_t cdat = AV_RB32("cdat");
10824 const uint32_t cdt2 = AV_RB32("cdt2");
10825 int ret, out_size = 0;
10826
10827 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
10828 if (src_size < 10)
10829 return AVERROR_INVALIDDATA;
10830
10831 /* avoid an int overflow: */
10832 if ((src_size - 8) / 2 >= INT_MAX / 3)
10833 return AVERROR_INVALIDDATA;
10834
10835 ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
10836 if (ret < 0)
10837 return ret;
10838
10839 /* parse and re-format the c608 payload in one pass. */
10840 while (src_size >= 10) {
10841 const uint32_t atom_size = avio_rb32(pb);
10842 const uint32_t atom_type = avio_rb32(pb);
10843 const uint32_t data_size = atom_size - 8;
10844 const uint8_t cc_field =
10845 atom_type == cdat ? 1 :
10846 atom_type == cdt2 ? 2 :
10847 0;
10848
10849 /* account for bytes consumed for atom size and type. */
10850 src_size -= 8;
10851
10852 /* make sure the data size stays within the buffer boundaries. */
10853 if (data_size < 2 || data_size > src_size) {
10854 ret = AVERROR_INVALIDDATA;
10855 break;
10856 }
10857
10858 /* make sure the data size is consistent with N byte pairs. */
10859 if (data_size % 2 != 0) {
10860 ret = AVERROR_INVALIDDATA;
10861 break;
10862 }
10863
10864 if (!cc_field) {
10865 /* neither cdat or cdt2 ... skip it */
10866 avio_skip(pb, data_size);
10867 src_size -= data_size;
10868 continue;
10869 }
10870
10871 for (uint32_t i = 0; i < data_size; i += 2) {
10872 pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
10873 pkt->data[out_size + 1] = avio_r8(pb);
10874 pkt->data[out_size + 2] = avio_r8(pb);
10875 out_size += 3;
10876 src_size -= 2;
10877 }
10878 }
10879
10880 if (src_size > 0)
10881 /* skip any remaining unread portion of the input payload */
10882 avio_skip(pb, src_size);
10883
10884 av_shrink_packet(pkt, out_size);
10885 return ret;
10886 }
10887
10888 103405 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
10889 int64_t current_index, AVPacket *pkt)
10890 {
10891 103405 MOVStreamContext *sc = st->priv_data;
10892
10893 103405 pkt->stream_index = sc->ffindex;
10894 103405 pkt->dts = sample->timestamp;
10895
2/2
✓ Branch 0 taken 237 times.
✓ Branch 1 taken 103168 times.
103405 if (sample->flags & AVINDEX_DISCARD_FRAME) {
10896 237 pkt->flags |= AV_PKT_FLAG_DISCARD;
10897 }
10898
4/4
✓ Branch 0 taken 83544 times.
✓ Branch 1 taken 19861 times.
✓ Branch 2 taken 83532 times.
✓ Branch 3 taken 12 times.
103405 if (sc->stts_count && sc->tts_index < sc->tts_count)
10899 83532 pkt->duration = sc->tts_data[sc->tts_index].duration;
10900
3/4
✓ Branch 0 taken 3015 times.
✓ Branch 1 taken 100390 times.
✓ Branch 2 taken 3015 times.
✗ Branch 3 not taken.
103405 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
10901 3015 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
10902 } else {
10903
2/2
✓ Branch 0 taken 15786 times.
✓ Branch 1 taken 84604 times.
100390 if (pkt->duration == 0) {
10904 15786 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
10905
2/2
✓ Branch 0 taken 15705 times.
✓ Branch 1 taken 81 times.
15786 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
10906
2/2
✓ Branch 0 taken 15752 times.
✓ Branch 1 taken 34 times.
15786 if (next_dts >= pkt->dts)
10907 15752 pkt->duration = next_dts - pkt->dts;
10908 }
10909 100390 pkt->pts = pkt->dts;
10910 }
10911
10912
4/4
✓ Branch 0 taken 83544 times.
✓ Branch 1 taken 19861 times.
✓ Branch 2 taken 83532 times.
✓ Branch 3 taken 12 times.
103405 if (sc->tts_data && sc->tts_index < sc->tts_count) {
10913 /* update tts context */
10914 83532 sc->tts_sample++;
10915
1/2
✓ Branch 0 taken 83532 times.
✗ Branch 1 not taken.
83532 if (sc->tts_index < sc->tts_count &&
10916
1/2
✓ Branch 0 taken 83532 times.
✗ Branch 1 not taken.
83532 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
10917 83532 sc->tts_index++;
10918 83532 sc->tts_sample = 0;
10919 }
10920 }
10921
10922
4/4
✓ Branch 0 taken 1041 times.
✓ Branch 1 taken 102364 times.
✓ Branch 2 taken 909 times.
✓ Branch 3 taken 132 times.
103405 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
10923 909 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
10924 909 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
10925
2/2
✓ Branch 0 taken 316 times.
✓ Branch 1 taken 593 times.
909 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
10926 }
10927 103405 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
10928 103405 pkt->pos = sample->pos;
10929
10930 /* Multiple stsd handling. */
10931
2/2
✓ Branch 0 taken 102614 times.
✓ Branch 1 taken 791 times.
103405 if (sc->stsc_data) {
10932
1/2
✓ Branch 0 taken 102614 times.
✗ Branch 1 not taken.
102614 if (sc->stsc_data[sc->stsc_index].id > 0 &&
10933
2/2
✓ Branch 0 taken 102583 times.
✓ Branch 1 taken 31 times.
102614 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
10934
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 102567 times.
102583 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
10935 16 int ret = mov_change_extradata(st, pkt);
10936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0)
10937 return ret;
10938 }
10939
10940 /* Update the stsc index for the next sample */
10941 102614 sc->stsc_sample++;
10942
2/2
✓ Branch 1 taken 55157 times.
✓ Branch 2 taken 47457 times.
102614 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
10943
2/2
✓ Branch 1 taken 1191 times.
✓ Branch 2 taken 53966 times.
55157 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
10944 1191 sc->stsc_index++;
10945 1191 sc->stsc_sample = 0;
10946 }
10947 }
10948
10949 103405 return 0;
10950 }
10951
10952 97082 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
10953 {
10954 97082 MOVContext *mov = s->priv_data;
10955 MOVStreamContext *sc;
10956 AVIndexEntry *sample;
10957 97082 AVStream *st = NULL;
10958 97082 FFStream *avsti = NULL;
10959 int64_t current_index;
10960 int ret;
10961 int i;
10962 97082 mov->fc = s;
10963 6862 retry:
10964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103944 times.
103944 if (s->pb->pos == 0) {
10965
10966 // Discard current fragment index
10967 if (mov->frag_index.allocated_size > 0) {
10968 for(int i = 0; i < mov->frag_index.nb_items; i++) {
10969 av_freep(&mov->frag_index.item[i].stream_info);
10970 }
10971 av_freep(&mov->frag_index.item);
10972 mov->frag_index.nb_items = 0;
10973 mov->frag_index.allocated_size = 0;
10974 mov->frag_index.current = -1;
10975 mov->frag_index.complete = 0;
10976 }
10977
10978 for (i = 0; i < s->nb_streams; i++) {
10979 AVStream *avst = s->streams[i];
10980 MOVStreamContext *msc = avst->priv_data;
10981
10982 // Clear current sample
10983 mov_current_sample_set(msc, 0);
10984 msc->tts_index = 0;
10985
10986 // Discard current index entries
10987 avsti = ffstream(avst);
10988 if (avsti->index_entries_allocated_size > 0) {
10989 av_freep(&avsti->index_entries);
10990 avsti->index_entries_allocated_size = 0;
10991 avsti->nb_index_entries = 0;
10992 }
10993 }
10994
10995 if ((ret = mov_switch_root(s, -1, -1)) < 0)
10996 return ret;
10997 }
10998 103944 sample = mov_find_next_sample(s, &st);
10999
6/6
✓ Branch 0 taken 103449 times.
✓ Branch 1 taken 495 times.
✓ Branch 2 taken 472 times.
✓ Branch 3 taken 102977 times.
✓ Branch 4 taken 35 times.
✓ Branch 5 taken 437 times.
103944 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
11000
2/2
✓ Branch 0 taken 488 times.
✓ Branch 1 taken 42 times.
530 if (!mov->next_root_atom)
11001 488 return AVERROR_EOF;
11002
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 38 times.
42 if ((ret = mov_switch_root(s, mov->next_root_atom, -1)) < 0)
11003 4 return ret;
11004 38 goto retry;
11005 }
11006 103414 sc = st->priv_data;
11007 /* must be done just before reading, to avoid infinite loop on sample */
11008 103414 current_index = sc->current_index;
11009 103414 mov_current_sample_inc(sc);
11010
11011
2/2
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 102977 times.
103414 if (mov->next_root_atom) {
11012 437 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
11013 437 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
11014 }
11015
11016
2/2
✓ Branch 0 taken 96590 times.
✓ Branch 1 taken 6824 times.
103414 if (st->discard != AVDISCARD_ALL) {
11017 96590 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
11018
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 96583 times.
96590 if (ret64 != sample->pos) {
11019 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
11020 sc->ffindex, sample->pos);
11021
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
11022 mov_current_sample_dec(sc);
11023
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
11024 7 return (int)ret64;
11025 }
11026 return AVERROR_INVALIDDATA;
11027 }
11028
11029
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96583 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96583 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
11030 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
11031 goto retry;
11032 }
11033
11034
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96583 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96583 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
11035 ret = get_eia608_packet(sc->pb, pkt, sample->size);
11036 #if CONFIG_IAMFDEC
11037
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 96528 times.
96583 else if (sc->iamf) {
11038 int64_t pts, dts, pos, duration;
11039 55 int flags, size = sample->size;
11040 55 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11041 55 pts = pkt->pts; dts = pkt->dts;
11042 55 pos = pkt->pos; flags = pkt->flags;
11043 55 duration = pkt->duration;
11044
3/4
✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 275 times.
✓ Branch 3 taken 55 times.
330 while (!ret && size > 0) {
11045 275 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
11046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
275 if (ret < 0) {
11047 if (should_retry(sc->pb, ret))
11048 mov_current_sample_dec(sc);
11049 return ret;
11050 }
11051 275 size -= ret;
11052 275 pkt->pts = pts; pkt->dts = dts;
11053 275 pkt->pos = pos; pkt->flags |= flags;
11054 275 pkt->duration = duration;
11055 275 ret = ff_buffer_packet(s, pkt);
11056 }
11057
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 if (!ret)
11058 55 return FFERROR_REDO;
11059 }
11060 #endif
11061
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 96525 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
96531 else if (st->codecpar->codec_id == AV_CODEC_ID_APV && sample->size > 4) {
11062 3 const uint32_t au_size = avio_rb32(sc->pb);
11063 3 ret = av_get_packet(sc->pb, pkt, au_size);
11064 } else
11065 96525 ret = av_get_packet(sc->pb, pkt, sample->size);
11066
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 96526 times.
96528 if (ret < 0) {
11067
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (should_retry(sc->pb, ret)) {
11068 mov_current_sample_dec(sc);
11069 }
11070 2 return ret;
11071 }
11072 #if CONFIG_DV_DEMUXER
11073
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96526 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96526 if (mov->dv_demux && sc->dv_audio_container) {
11074 ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
11075 av_packet_unref(pkt);
11076 if (ret < 0)
11077 return ret;
11078 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
11079 if (ret < 0)
11080 return ret;
11081 }
11082 #endif
11083
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 96508 times.
96526 if (sc->has_palette) {
11084 uint8_t *pal;
11085
11086 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
11087
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
11088 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
11089 } else {
11090 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
11091 18 sc->has_palette = 0;
11092 }
11093 }
11094
4/6
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 96238 times.
✓ Branch 3 taken 288 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 288 times.
✗ Branch 6 not taken.
96526 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
11095
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 288 times.
288 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
11096 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
11097 }
11098 }
11099
11100 103350 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103350 times.
103350 if (ret < 0)
11102 return ret;
11103
11104
2/2
✓ Branch 0 taken 6824 times.
✓ Branch 1 taken 96526 times.
103350 if (st->discard == AVDISCARD_ALL)
11105 6824 goto retry;
11106
11107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96526 times.
96526 if (mov->aax_mode)
11108 aax_filter(pkt->data, pkt->size, mov);
11109
11110 96526 ret = cenc_filter(mov, st, sc, pkt, current_index);
11111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96526 times.
96526 if (ret < 0) {
11112 return ret;
11113 }
11114
11115 96526 return 0;
11116 }
11117
11118 361 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
11119 {
11120 361 MOVContext *mov = s->priv_data;
11121 int index;
11122
11123
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 26 times.
361 if (!mov->frag_index.complete)
11124 335 return 0;
11125
11126 26 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
11127
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 22 times.
26 if (index < 0)
11128 4 index = 0;
11129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (!mov->frag_index.item[index].headers_read)
11130 return mov_switch_root(s, -1, index);
11131
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (index + 1 < mov->frag_index.nb_items)
11132 26 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11133
11134 26 return 0;
11135 }
11136
11137 static int is_open_key_sample(const MOVStreamContext *sc, int sample)
11138 {
11139 // TODO: a bisect search would scale much better
11140 for (int i = 0; i < sc->open_key_samples_count; i++) {
11141 const int oks = sc->open_key_samples[i];
11142 if (oks == sample)
11143 return 1;
11144 if (oks > sample) /* list is monotically increasing so we can stop early */
11145 break;
11146 }
11147 return 0;
11148 }
11149
11150 /*
11151 * Some key sample may be key frames but not IDR frames, so a random access to
11152 * them may not be allowed.
11153 */
11154 229 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
11155 {
11156 229 MOVStreamContext *sc = st->priv_data;
11157 229 FFStream *const sti = ffstream(st);
11158 int64_t key_sample_dts, key_sample_pts;
11159
11160
1/2
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
229 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
11161 229 return 1;
11162
11163 if (sample >= sc->sample_offsets_count)
11164 return 1;
11165
11166 key_sample_dts = sti->index_entries[sample].timestamp;
11167 key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
11168
11169 /*
11170 * If the sample needs to be presented before an open key sample, they may
11171 * not be decodable properly, even though they come after in decoding
11172 * order.
11173 */
11174 if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
11175 return 0;
11176
11177 return 1;
11178 }
11179
11180 361 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
11181 {
11182 361 MOVStreamContext *sc = st->priv_data;
11183 361 FFStream *const sti = ffstream(st);
11184 int sample, time_sample, ret, next_ts, requested_sample;
11185 unsigned int i;
11186
11187 // Here we consider timestamp to be PTS, hence try to offset it so that we
11188 // can search over the DTS timeline.
11189 361 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
11190
11191 361 ret = mov_seek_fragment(s, st, timestamp);
11192
1/2
✓ Branch 0 taken 361 times.
✗ Branch 1 not taken.
361 if (ret < 0)
11193 return ret;
11194
11195 for (;;) {
11196 361 sample = av_index_search_timestamp(st, timestamp, flags);
11197 361 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
11198
5/6
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 292 times.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
✓ Branch 5 taken 26 times.
361 if (sample < 0 && sti->nb_index_entries && timestamp < sti->index_entries[0].timestamp)
11199 43 sample = 0;
11200
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 335 times.
361 if (sample < 0) /* not sure what to do */
11201 26 return AVERROR_INVALIDDATA;
11202
11203
3/4
✓ Branch 0 taken 229 times.
✓ Branch 1 taken 106 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 229 times.
335 if (!sample || can_seek_to_key_sample(st, sample, timestamp))
11204 break;
11205
11206 next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
11207 requested_sample = av_index_search_timestamp(st, next_ts, flags);
11208
11209 // If we've reached a different sample trying to find a good pts to
11210 // seek to, give up searching because we'll end up seeking back to
11211 // sample 0 on every seek.
11212 if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
11213 break;
11214
11215 timestamp = next_ts;
11216 }
11217
11218 335 mov_current_sample_set(sc, sample);
11219 335 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
11220 /* adjust time to sample index */
11221
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 125 times.
335 if (sc->tts_data) {
11222 210 time_sample = 0;
11223
1/2
✓ Branch 0 taken 60235 times.
✗ Branch 1 not taken.
60235 for (i = 0; i < sc->tts_count; i++) {
11224 60235 int next = time_sample + sc->tts_data[i].count;
11225
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 60025 times.
60235 if (next > sc->current_sample) {
11226 210 sc->tts_index = i;
11227 210 sc->tts_sample = sc->current_sample - time_sample;
11228 210 break;
11229 }
11230 60025 time_sample = next;
11231 }
11232 }
11233
11234 /* adjust stsd index */
11235
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 26 times.
335 if (sc->chunk_count) {
11236 309 time_sample = 0;
11237
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
381 for (i = 0; i < sc->stsc_count; i++) {
11238 381 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
11239
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 72 times.
381 if (next > sc->current_sample) {
11240 309 sc->stsc_index = i;
11241 309 sc->stsc_sample = sc->current_sample - time_sample;
11242 309 break;
11243 }
11244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
11245 72 time_sample = next;
11246 }
11247 }
11248
11249 335 return sample;
11250 }
11251
11252 335 static int64_t mov_get_skip_samples(AVStream *st, int sample)
11253 {
11254 335 MOVStreamContext *sc = st->priv_data;
11255 335 FFStream *const sti = ffstream(st);
11256 335 int64_t first_ts = sti->index_entries[0].timestamp;
11257 335 int64_t ts = sti->index_entries[sample].timestamp;
11258 int64_t off;
11259
11260
2/2
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 151 times.
335 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
11261 184 return 0;
11262
11263 /* compute skip samples according to stream start_pad, seek ts and first ts */
11264 151 off = av_rescale_q(ts - first_ts, st->time_base,
11265 151 (AVRational){1, st->codecpar->sample_rate});
11266 151 return FFMAX(sc->start_pad - off, 0);
11267 }
11268
11269 340 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
11270 {
11271 340 MOVContext *mc = s->priv_data;
11272 AVStream *st;
11273 FFStream *sti;
11274 int sample;
11275 int i;
11276
11277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 340 times.
340 if (stream_index >= s->nb_streams)
11278 return AVERROR_INVALIDDATA;
11279
11280 340 st = s->streams[stream_index];
11281 340 sti = ffstream(st);
11282 340 sample = mov_seek_stream(s, st, sample_time, flags);
11283
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 314 times.
340 if (sample < 0)
11284 26 return sample;
11285
11286
1/2
✓ Branch 0 taken 314 times.
✗ Branch 1 not taken.
314 if (mc->seek_individually) {
11287 /* adjust seek timestamp to found sample timestamp */
11288 314 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
11289 314 sti->skip_samples = mov_get_skip_samples(st, sample);
11290
11291
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 314 times.
649 for (i = 0; i < s->nb_streams; i++) {
11292 335 AVStream *const st = s->streams[i];
11293 335 FFStream *const sti = ffstream(st);
11294 int64_t timestamp;
11295
11296
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 21 times.
335 if (stream_index == i)
11297 314 continue;
11298
11299 21 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
11300 21 sample = mov_seek_stream(s, st, timestamp, flags);
11301
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (sample >= 0)
11302 21 sti->skip_samples = mov_get_skip_samples(st, sample);
11303 }
11304 } else {
11305 for (i = 0; i < s->nb_streams; i++) {
11306 MOVStreamContext *sc;
11307 st = s->streams[i];
11308 sc = st->priv_data;
11309 mov_current_sample_set(sc, 0);
11310 }
11311 while (1) {
11312 MOVStreamContext *sc;
11313 AVIndexEntry *entry = mov_find_next_sample(s, &st);
11314 if (!entry)
11315 return AVERROR_INVALIDDATA;
11316 sc = st->priv_data;
11317 if (sc->ffindex == stream_index && sc->current_sample == sample)
11318 break;
11319 mov_current_sample_inc(sc);
11320 }
11321 }
11322 314 return 0;
11323 }
11324
11325 #define OFFSET(x) offsetof(MOVContext, x)
11326 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
11327 static const AVOption mov_options[] = {
11328 {"use_absolute_path",
11329 "allow using absolute path when opening alias, this is a possible security issue",
11330 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
11331 0, 1, FLAGS},
11332 {"seek_streams_individually",
11333 "Seek each stream individually to the closest point",
11334 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
11335 0, 1, FLAGS},
11336 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
11337 0, 1, FLAGS},
11338 {"advanced_editlist",
11339 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
11340 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
11341 0, 1, FLAGS},
11342 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
11343 0, 1, FLAGS},
11344 {"use_mfra_for",
11345 "use mfra for fragment timestamps",
11346 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
11347 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
11348 .unit = "use_mfra_for"},
11349 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
11350 FLAGS, .unit = "use_mfra_for" },
11351 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
11352 FLAGS, .unit = "use_mfra_for" },
11353 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
11354 FLAGS, .unit = "use_mfra_for" },
11355 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
11356 0, 1, FLAGS},
11357 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
11358 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11359 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
11360 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11361 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
11362 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11363 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
11364 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11365 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
11366 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11367 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
11368 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
11369 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
11370 .flags = AV_OPT_FLAG_DECODING_PARAM },
11371 { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11372 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
11373 {.i64 = 0}, 0, 1, FLAGS },
11374 { "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 },
11375 { "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 },
11376
11377 { NULL },
11378 };
11379
11380 static const AVClass mov_class = {
11381 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
11382 .item_name = av_default_item_name,
11383 .option = mov_options,
11384 .version = LIBAVUTIL_VERSION_INT,
11385 };
11386
11387 const FFInputFormat ff_mov_demuxer = {
11388 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
11389 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
11390 .p.priv_class = &mov_class,
11391 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v,avif,heic,heif",
11392 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
11393 .priv_data_size = sizeof(MOVContext),
11394 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
11395 .read_probe = mov_probe,
11396 .read_header = mov_read_header,
11397 .read_packet = mov_read_packet,
11398 .read_close = mov_read_close,
11399 .read_seek = mov_read_seek,
11400 };
11401