FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2025-03-08 20:38:41
Exec Total Coverage
Lines: 4279 6778 63.1%
Functions: 173 212 81.6%
Branches: 2407 4552 52.9%

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/dict_internal.h"
36 #include "libavutil/internal.h"
37 #include "libavutil/intreadwrite.h"
38 #include "libavutil/intfloat.h"
39 #include "libavutil/mathematics.h"
40 #include "libavutil/avassert.h"
41 #include "libavutil/avstring.h"
42 #include "libavutil/dict.h"
43 #include "libavutil/display.h"
44 #include "libavutil/mem.h"
45 #include "libavutil/opt.h"
46 #include "libavutil/aes.h"
47 #include "libavutil/aes_ctr.h"
48 #include "libavutil/pixdesc.h"
49 #include "libavutil/sha.h"
50 #include "libavutil/spherical.h"
51 #include "libavutil/stereo3d.h"
52 #include "libavutil/timecode.h"
53 #include "libavutil/uuid.h"
54 #include "libavcodec/ac3tab.h"
55 #include "libavcodec/flac.h"
56 #include "libavcodec/hevc/hevc.h"
57 #include "libavcodec/mpegaudiodecheader.h"
58 #include "libavcodec/mlp_parse.h"
59 #include "avformat.h"
60 #include "internal.h"
61 #include "avio_internal.h"
62 #include "demux.h"
63 #include "dvdclut.h"
64 #include "iamf_parse.h"
65 #include "iamf_reader.h"
66 #include "dovi_isom.h"
67 #include "riff.h"
68 #include "isom.h"
69 #include "libavcodec/get_bits.h"
70 #include "id3v1.h"
71 #include "mov_chan.h"
72 #include "replaygain.h"
73
74 #if CONFIG_ZLIB
75 #include <zlib.h>
76 #endif
77
78 #include "qtpalette.h"
79
80 /* those functions parse an atom */
81 /* links atom IDs to parse functions */
82 typedef struct MOVParseTableEntry {
83 uint32_t type;
84 int (*parse)(MOVContext *ctx, AVIOContext *pb, MOVAtom atom);
85 } MOVParseTableEntry;
86
87 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom);
88 static int mov_read_mfra(MOVContext *c, AVIOContext *f);
89 static void mov_free_stream_context(AVFormatContext *s, AVStream *st);
90
91 24 static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
92 unsigned len, const char *key)
93 {
94 char buf[16];
95
96 24 short current, total = 0;
97 24 avio_rb16(pb); // unknown
98 24 current = avio_rb16(pb);
99
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (len >= 6)
100 24 total = avio_rb16(pb);
101
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19 times.
24 if (!total)
102 5 snprintf(buf, sizeof(buf), "%d", current);
103 else
104 19 snprintf(buf, sizeof(buf), "%d/%d", current, total);
105 24 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
106 24 av_dict_set(&c->fc->metadata, key, buf, 0);
107
108 24 return 0;
109 }
110
111 static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
112 unsigned len, const char *key)
113 {
114 /* bypass padding bytes */
115 avio_r8(pb);
116 avio_r8(pb);
117 avio_r8(pb);
118
119 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
120 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
121
122 return 0;
123 }
124
125 26 static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
126 unsigned len, const char *key)
127 {
128 26 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
129 26 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
130
131 26 return 0;
132 }
133
134 10 static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
135 unsigned len, const char *key)
136 {
137 short genre;
138
139 10 avio_r8(pb); // unknown
140
141 10 genre = avio_r8(pb);
142
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)
143 return 0;
144 10 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
145 10 av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
146
147 10 return 0;
148 }
149
150 static const uint32_t mac_to_unicode[128] = {
151 0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
152 0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
153 0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,
154 0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,
155 0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,
156 0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,
157 0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,
158 0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,
159 0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,
160 0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,
161 0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,
162 0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,
163 0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,
164 0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,
165 0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,
166 0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7,
167 };
168
169 326 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
170 char *dst, int dstlen)
171 {
172 326 char *p = dst;
173 326 char *end = dst+dstlen-1;
174 int i;
175
176
2/2
✓ Branch 0 taken 2889 times.
✓ Branch 1 taken 326 times.
3215 for (i = 0; i < len; i++) {
177 2889 uint8_t t, c = avio_r8(pb);
178
179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2889 times.
2889 if (p >= end)
180 continue;
181
182
2/2
✓ Branch 0 taken 2886 times.
✓ Branch 1 taken 3 times.
2889 if (c < 0x80)
183 2886 *p++ = c;
184
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 else if (p < end)
185
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 3 times.
6 PUT_UTF8(mac_to_unicode[c-0x80], t, if (p < end) *p++ = t;);
186 }
187 326 *p = 0;
188 326 return p - dst;
189 }
190
191 /**
192 * Get the current item in the parsing process.
193 */
194 82 static HEIFItem *heif_cur_item(MOVContext *c)
195 {
196 82 HEIFItem *item = NULL;
197
198
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 12 times.
138 for (int i = 0; i < c->nb_heif_item; i++) {
199
3/4
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✓ Branch 3 taken 70 times.
126 if (!c->heif_item[i] || c->heif_item[i]->item_id != c->cur_item_id)
200 56 continue;
201
202 70 item = c->heif_item[i];
203 70 break;
204 }
205
206 82 return item;
207 }
208
209 /**
210 * Get the current stream in the parsing process. This can either be the
211 * latest stream added to the context, or the stream referenced by an item.
212 */
213 198 static AVStream *get_curr_st(MOVContext *c)
214 {
215 198 AVStream *st = NULL;
216 HEIFItem *item;
217
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 if (c->fc->nb_streams < 1)
219 return NULL;
220
221
2/2
✓ Branch 0 taken 169 times.
✓ Branch 1 taken 29 times.
198 if (c->cur_item_id == -1)
222 169 return c->fc->streams[c->fc->nb_streams-1];
223
224 29 item = heif_cur_item(c);
225
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (item)
226 29 st = item->st;
227
228 29 return st;
229 }
230
231 14 static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
232 {
233 AVStream *st;
234 MOVStreamContext *sc;
235 enum AVCodecID id;
236 int ret;
237
238
2/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
14 switch (type) {
239 7 case 0xd: id = AV_CODEC_ID_MJPEG; break;
240 7 case 0xe: id = AV_CODEC_ID_PNG; break;
241 case 0x1b: id = AV_CODEC_ID_BMP; break;
242 default:
243 av_log(c->fc, AV_LOG_WARNING, "Unknown cover type: 0x%x.\n", type);
244 avio_skip(pb, len);
245 return 0;
246 }
247
248 14 sc = av_mallocz(sizeof(*sc));
249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!sc)
250 return AVERROR(ENOMEM);
251 14 ret = ff_add_attached_pic(c->fc, NULL, pb, NULL, len);
252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0) {
253 av_free(sc);
254 return ret;
255 }
256 14 st = c->fc->streams[c->fc->nb_streams - 1];
257 14 st->priv_data = sc;
258 14 sc->id = st->id;
259 14 sc->refcount = 1;
260
261
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) {
262
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
263 7 id = AV_CODEC_ID_PNG;
264 } else {
265 7 id = AV_CODEC_ID_MJPEG;
266 }
267 }
268 14 st->codecpar->codec_id = id;
269
270 14 return 0;
271 }
272
273 // 3GPP TS 26.244
274 static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
275 {
276 char language[4] = { 0 };
277 char buf[200], place[100];
278 uint16_t langcode = 0;
279 double longitude, latitude, altitude;
280 const char *key = "location";
281
282 if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) {
283 av_log(c->fc, AV_LOG_ERROR, "loci too short\n");
284 return AVERROR_INVALIDDATA;
285 }
286
287 avio_skip(pb, 4); // version+flags
288 langcode = avio_rb16(pb);
289 ff_mov_lang_to_iso639(langcode, language);
290 len -= 6;
291
292 len -= avio_get_str(pb, len, place, sizeof(place));
293 if (len < 1) {
294 av_log(c->fc, AV_LOG_ERROR, "place name too long\n");
295 return AVERROR_INVALIDDATA;
296 }
297 avio_skip(pb, 1); // role
298 len -= 1;
299
300 if (len < 12) {
301 av_log(c->fc, AV_LOG_ERROR,
302 "loci too short (%u bytes left, need at least %d)\n", len, 12);
303 return AVERROR_INVALIDDATA;
304 }
305 longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
306 latitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
307 altitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
308
309 // Try to output in the same format as the ?xyz field
310 snprintf(buf, sizeof(buf), "%+08.4f%+09.4f", latitude, longitude);
311 if (altitude)
312 av_strlcatf(buf, sizeof(buf), "%+f", altitude);
313 av_strlcatf(buf, sizeof(buf), "/%s", place);
314
315 if (*language && strcmp(language, "und")) {
316 char key2[16];
317 snprintf(key2, sizeof(key2), "%s-%s", key, language);
318 av_dict_set(&c->fc->metadata, key2, buf, 0);
319 }
320 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
321 return av_dict_set(&c->fc->metadata, key, buf, 0);
322 }
323
324 static int mov_metadata_hmmt(MOVContext *c, AVIOContext *pb, unsigned len)
325 {
326 int i, n_hmmt;
327
328 if (len < 2)
329 return 0;
330 if (c->ignore_chapters)
331 return 0;
332
333 n_hmmt = avio_rb32(pb);
334 if (n_hmmt > len / 4)
335 return AVERROR_INVALIDDATA;
336 for (i = 0; i < n_hmmt && !pb->eof_reached; i++) {
337 int moment_time = avio_rb32(pb);
338 avpriv_new_chapter(c->fc, i, av_make_q(1, 1000), moment_time, AV_NOPTS_VALUE, NULL);
339 }
340 if (avio_feof(pb))
341 return AVERROR_INVALIDDATA;
342 return 0;
343 }
344
345 472 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
346 {
347 472 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
348 472 char key2[32], language[4] = {0};
349 472 char *str = NULL;
350 472 const char *key = NULL;
351 472 uint16_t langcode = 0;
352 472 uint32_t data_type = 0, str_size_alloc;
353 uint64_t str_size;
354 472 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
355 472 int raw = 0;
356 472 int num = 0;
357 AVDictionary **metadata;
358
359
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 443 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
472 if (c->trak_index >= 0 && c->trak_index < c->fc->nb_streams)
360 29 metadata = &c->fc->streams[c->trak_index]->metadata;
361 else
362 443 metadata = &c->fc->metadata;
363
364
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 41 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 58 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.
472 switch (atom.type) {
365 3 case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break;
366 3 case MKTAG( '@','P','R','Q'): key = "quicktime_version"; raw = 1; break;
367 2 case MKTAG( 'X','M','P','_'):
368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->export_xmp) { key = "xmp"; raw = 1; } break;
369 12 case MKTAG( 'a','A','R','T'): key = "album_artist"; break;
370 case MKTAG( 'a','k','I','D'): key = "account_type";
371 parse = mov_metadata_int8_no_padding; break;
372 case MKTAG( 'a','p','I','D'): key = "account_id"; break;
373 case MKTAG( 'c','a','t','g'): key = "category"; break;
374 13 case MKTAG( 'c','p','i','l'): key = "compilation";
375 13 parse = mov_metadata_int8_no_padding; break;
376 case MKTAG( 'c','p','r','t'): key = "copyright"; break;
377 case MKTAG( 'd','e','s','c'): key = "description"; break;
378 12 case MKTAG( 'd','i','s','k'): key = "disc";
379 12 parse = mov_metadata_track_or_disc_number; break;
380 case MKTAG( 'e','g','i','d'): key = "episode_uid";
381 parse = mov_metadata_int8_no_padding; break;
382 case MKTAG( 'F','I','R','M'): key = "firmware"; raw = 1; break;
383 10 case MKTAG( 'g','n','r','e'): key = "genre";
384 10 parse = mov_metadata_gnre; break;
385 case MKTAG( 'h','d','v','d'): key = "hd_video";
386 parse = mov_metadata_int8_no_padding; break;
387 case MKTAG( 'H','M','M','T'):
388 return mov_metadata_hmmt(c, pb, atom.size);
389 case MKTAG( 'k','e','y','w'): key = "keywords"; break;
390 case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
391 case MKTAG( 'l','o','c','i'):
392 return mov_metadata_loci(c, pb, atom.size);
393 case MKTAG( 'm','a','n','u'): key = "make"; break;
394 case MKTAG( 'm','o','d','l'): key = "model"; break;
395 case MKTAG( 'p','c','s','t'): key = "podcast";
396 parse = mov_metadata_int8_no_padding; break;
397 13 case MKTAG( 'p','g','a','p'): key = "gapless_playback";
398 13 parse = mov_metadata_int8_no_padding; break;
399 case MKTAG( 'p','u','r','d'): key = "purchase_date"; break;
400 case MKTAG( 'r','t','n','g'): key = "rating";
401 parse = mov_metadata_int8_no_padding; break;
402 case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break;
403 case MKTAG( 's','o','a','l'): key = "sort_album"; break;
404 case MKTAG( 's','o','a','r'): key = "sort_artist"; break;
405 case MKTAG( 's','o','c','o'): key = "sort_composer"; break;
406 case MKTAG( 's','o','n','m'): key = "sort_name"; break;
407 case MKTAG( 's','o','s','n'): key = "sort_show"; break;
408 case MKTAG( 's','t','i','k'): key = "media_type";
409 parse = mov_metadata_int8_no_padding; break;
410 12 case MKTAG( 't','r','k','n'): key = "track";
411 12 parse = mov_metadata_track_or_disc_number; break;
412 case MKTAG( 't','v','e','n'): key = "episode_id"; break;
413 case MKTAG( 't','v','e','s'): key = "episode_sort";
414 parse = mov_metadata_int8_bypass_padding; break;
415 case MKTAG( 't','v','n','n'): key = "network"; break;
416 case MKTAG( 't','v','s','h'): key = "show"; break;
417 case MKTAG( 't','v','s','n'): key = "season_number";
418 parse = mov_metadata_int8_bypass_padding; break;
419 17 case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
420 case MKTAG(0xa9,'P','R','D'): key = "producer"; break;
421 16 case MKTAG(0xa9,'a','l','b'): key = "album"; break;
422 3 case MKTAG(0xa9,'a','u','t'): key = "artist"; break;
423 case MKTAG(0xa9,'c','h','p'): key = "chapter"; break;
424 8 case MKTAG(0xa9,'c','m','t'): key = "comment"; break;
425 case MKTAG(0xa9,'c','o','m'): key = "composer"; break;
426 4 case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
427 16 case MKTAG(0xa9,'d','a','y'): key = "date"; break;
428 case MKTAG(0xa9,'d','i','r'): key = "director"; break;
429 case MKTAG(0xa9,'d','i','s'): key = "disclaimer"; break;
430 case MKTAG(0xa9,'e','d','1'): key = "edit_date"; break;
431 2 case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
432 case MKTAG(0xa9,'f','m','t'): key = "original_format"; break;
433 3 case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
434 case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
435 case MKTAG(0xa9,'h','s','t'): key = "host_computer"; break;
436 case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
437 case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
438 5 case MKTAG(0xa9,'m','a','k'): key = "make"; break;
439 5 case MKTAG(0xa9,'m','o','d'): key = "model"; break;
440 41 case MKTAG(0xa9,'n','a','m'): key = "title"; break;
441 case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break;
442 case MKTAG(0xa9,'p','r','d'): key = "producer"; break;
443 case MKTAG(0xa9,'p','r','f'): key = "performers"; break;
444 case MKTAG(0xa9,'r','e','q'): key = "playback_requirements"; break;
445 case MKTAG(0xa9,'s','r','c'): key = "original_source"; break;
446 case MKTAG(0xa9,'s','t','3'): key = "subtitle"; break;
447 58 case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
448 50 case MKTAG(0xa9,'t','o','o'): key = "encoder"; break;
449 case MKTAG(0xa9,'t','r','k'): key = "track"; break;
450 case MKTAG(0xa9,'u','r','l'): key = "URL"; break;
451 case MKTAG(0xa9,'w','r','n'): key = "warning"; break;
452 1 case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
453 5 case MKTAG(0xa9,'x','y','z'): key = "location"; break;
454 }
455 2 retry:
456
3/4
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 174 times.
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
760 if (c->itunes_metadata && atom.size > 8) {
457 300 int data_size = avio_rb32(pb);
458 300 int tag = avio_rl32(pb);
459
3/6
✓ Branch 0 taken 300 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 300 times.
✗ Branch 5 not taken.
300 if (tag == MKTAG('d','a','t','a') && data_size <= atom.size && data_size >= 16) {
460 300 data_type = avio_rb32(pb); // type
461 300 avio_rb32(pb); // unknown
462 300 str_size = data_size - 16;
463 300 atom.size -= 16;
464
465
5/6
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 207 times.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 34 times.
✓ Branch 4 taken 59 times.
✗ Branch 5 not taken.
300 if (!key && c->found_hdlr_mdta && c->meta_keys) {
466 59 uint32_t index = av_bswap32(atom.type); // BE number has been read as LE
467
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) {
468 59 key = c->meta_keys[index];
469 } else if (atom.type != MKTAG('c', 'o', 'v', 'r')) {
470 av_log(c->fc, AV_LOG_WARNING,
471 "The index of 'data' is out of range: %"PRId32" < 1 or >= %d.\n",
472 index, c->meta_keys_count);
473 }
474 }
475
4/4
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 266 times.
✓ Branch 3 taken 20 times.
300 if (atom.type == MKTAG('c', 'o', 'v', 'r') ||
476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 266 times.
266 (key && !strcmp(key, "com.apple.quicktime.artwork"))) {
477 14 int ret = mov_read_covr(c, pb, data_type, str_size);
478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0) {
479 av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
480 return ret;
481 }
482 14 atom.size -= str_size;
483
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (atom.size > 8)
484 2 goto retry;
485 12 return ret;
486 }
487 } else return 0;
488
7/8
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 105 times.
✓ Branch 3 taken 51 times.
✓ Branch 4 taken 105 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 99 times.
✓ Branch 7 taken 6 times.
174 } else if (atom.size > 4 && key && !c->itunes_metadata && !raw) {
489 99 str_size = avio_rb16(pb); // string length
490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (str_size > atom.size) {
491 raw = 1;
492 avio_seek(pb, -2, SEEK_CUR);
493 av_log(c->fc, AV_LOG_WARNING, "UDTA parsing failed retrying raw\n");
494 goto retry;
495 }
496 99 langcode = avio_rb16(pb);
497 99 ff_mov_lang_to_iso639(langcode, language);
498 99 atom.size -= 4;
499 } else
500 75 str_size = atom.size;
501
502
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 460 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
460 if (c->export_all && !key) {
503 key = av_fourcc_make_string(tmp_key, atom.type);
504 }
505
506
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 371 times.
460 if (!key)
507 89 return 0;
508
2/4
✓ Branch 0 taken 371 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 371 times.
371 if (atom.size < 0 || str_size >= INT_MAX/2)
509 return AVERROR_INVALIDDATA;
510
511 // Allocates enough space if data_type is a int32 or float32 number, otherwise
512 // worst-case requirement for output string in case of utf8 coded input
513
3/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 330 times.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
371 num = (data_type >= 21 && data_type <= 23);
514
4/4
✓ Branch 0 taken 330 times.
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 324 times.
✓ Branch 3 taken 6 times.
371 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
515 371 str = av_mallocz(str_size_alloc);
516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 371 times.
371 if (!str)
517 return AVERROR(ENOMEM);
518
519
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 311 times.
371 if (parse)
520 60 parse(c, pb, str_size, key);
521 else {
522
8/10
✓ Branch 0 taken 305 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 305 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 100 times.
✓ Branch 5 taken 205 times.
✓ Branch 6 taken 86 times.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 86 times.
311 if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
523 14 mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
524
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 295 times.
297 } else if (data_type == 21) { // BE signed integer, variable size
525 2 int val = 0;
526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (str_size == 1)
527 val = (int8_t)avio_r8(pb);
528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 2)
529 val = (int16_t)avio_rb16(pb);
530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 3)
531 val = ((int32_t)(avio_rb24(pb)<<8))>>8;
532
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (str_size == 4)
533 2 val = (int32_t)avio_rb32(pb);
534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
535 av_log(c->fc, AV_LOG_ERROR,
536 "Failed to store the number (%d) in string.\n", val);
537 av_free(str);
538 return AVERROR_INVALIDDATA;
539 }
540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 295 times.
295 } else if (data_type == 22) { // BE unsigned integer, variable size
541 unsigned int val = 0;
542 if (str_size == 1)
543 val = avio_r8(pb);
544 else if (str_size == 2)
545 val = avio_rb16(pb);
546 else if (str_size == 3)
547 val = avio_rb24(pb);
548 else if (str_size == 4)
549 val = avio_rb32(pb);
550 if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
551 av_log(c->fc, AV_LOG_ERROR,
552 "Failed to store the number (%u) in string.\n", val);
553 av_free(str);
554 return AVERROR_INVALIDDATA;
555 }
556
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 282 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
308 } else if (data_type == 23 && str_size >= 4) { // BE float32
557 13 float val = av_int2float(avio_rb32(pb));
558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
559 av_log(c->fc, AV_LOG_ERROR,
560 "Failed to store the float32 number (%f) in string.\n", val);
561 av_free(str);
562 return AVERROR_INVALIDDATA;
563 }
564
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
282 } else if (data_type > 1 && data_type != 4) {
565 // data_type can be 0 if not set at all above. data_type 1 means
566 // UTF8 and 4 means "UTF8 sort". For any other type (UTF16 or e.g.
567 // a picture), don't return it blindly in a string that is supposed
568 // to be UTF8 text.
569 av_log(c->fc, AV_LOG_WARNING, "Skipping unhandled metadata %s of type %d\n", key, data_type);
570 av_free(str);
571 return 0;
572 } else {
573 282 int ret = ffio_read_size(pb, str, str_size);
574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 282 times.
282 if (ret < 0) {
575 av_free(str);
576 return ret;
577 }
578 282 str[str_size] = 0;
579 }
580 311 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
581 311 av_dict_set(metadata, key, str, 0);
582
4/4
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 212 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 62 times.
311 if (*language && strcmp(language, "und")) {
583 37 snprintf(key2, sizeof(key2), "%s-%s", key, language);
584 37 av_dict_set(metadata, key2, str, 0);
585 }
586
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 201 times.
311 if (!strcmp(key, "encoder")) {
587 int major, minor, micro;
588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
110 if (sscanf(str, "HandBrake %d.%d.%d", &major, &minor, &micro) == 3) {
589 c->handbrake_version = 1000000*major + 1000*minor + micro;
590 }
591 }
592 }
593
594 371 av_freep(&str);
595 371 return 0;
596 }
597
598 12 static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
599 {
600 int64_t start;
601 int i, nb_chapters, str_len, version;
602 char str[256+1];
603 int ret;
604
605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->ignore_chapters)
606 return 0;
607
608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if ((atom.size -= 5) < 0)
609 return 0;
610
611 12 version = avio_r8(pb);
612 12 avio_rb24(pb);
613
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (version)
614 12 avio_rb32(pb); // ???
615 12 nb_chapters = avio_r8(pb);
616
617
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
30 for (i = 0; i < nb_chapters; i++) {
618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size < 9)
619 return 0;
620
621 18 start = avio_rb64(pb);
622 18 str_len = avio_r8(pb);
623
624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if ((atom.size -= 9+str_len) < 0)
625 return 0;
626
627 18 ret = ffio_read_size(pb, str, str_len);
628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (ret < 0)
629 return ret;
630 18 str[str_len] = 0;
631 18 avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
632 }
633 12 return 0;
634 }
635
636 #define MIN_DATA_ENTRY_BOX_SIZE 12
637 594 static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
638 {
639 AVStream *st;
640 MOVStreamContext *sc;
641 int entries, i, j;
642
643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
644 return 0;
645 594 st = c->fc->streams[c->fc->nb_streams-1];
646 594 sc = st->priv_data;
647
648 594 avio_rb32(pb); // version + flags
649 594 entries = avio_rb32(pb);
650
1/2
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
594 if (!entries ||
651
1/2
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
594 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 entries >= UINT_MAX / sizeof(*sc->drefs))
653 return AVERROR_INVALIDDATA;
654
655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 for (i = 0; i < sc->drefs_count; i++) {
656 MOVDref *dref = &sc->drefs[i];
657 av_freep(&dref->path);
658 av_freep(&dref->dir);
659 }
660 594 av_free(sc->drefs);
661 594 sc->drefs_count = 0;
662 594 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (!sc->drefs)
664 return AVERROR(ENOMEM);
665 594 sc->drefs_count = entries;
666
667
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 594 times.
1188 for (i = 0; i < entries; i++) {
668 594 MOVDref *dref = &sc->drefs[i];
669 594 uint32_t size = avio_rb32(pb);
670 594 int64_t next = avio_tell(pb);
671
672
3/6
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 594 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 594 times.
594 if (size < 12 || next < 0 || next > INT64_MAX - size)
673 return AVERROR_INVALIDDATA;
674
675 594 next += size - 4;
676
677 594 dref->type = avio_rl32(pb);
678 594 avio_rb32(pb); // version + flags
679
680
3/4
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 476 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 118 times.
594 if (dref->type == MKTAG('a','l','i','s') && size > 150) {
681 /* macintosh alias record */
682 uint16_t volume_len, len;
683 int16_t type;
684 int ret;
685
686 avio_skip(pb, 10);
687
688 volume_len = avio_r8(pb);
689 volume_len = FFMIN(volume_len, 27);
690 ret = ffio_read_size(pb, dref->volume, 27);
691 if (ret < 0)
692 return ret;
693 dref->volume[volume_len] = 0;
694 av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
695
696 avio_skip(pb, 12);
697
698 len = avio_r8(pb);
699 len = FFMIN(len, 63);
700 ret = ffio_read_size(pb, dref->filename, 63);
701 if (ret < 0)
702 return ret;
703 dref->filename[len] = 0;
704 av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
705
706 avio_skip(pb, 16);
707
708 /* read next level up_from_alias/down_to_target */
709 dref->nlvl_from = avio_rb16(pb);
710 dref->nlvl_to = avio_rb16(pb);
711 av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
712 dref->nlvl_from, dref->nlvl_to);
713
714 avio_skip(pb, 16);
715
716 for (type = 0; type != -1 && avio_tell(pb) < next; ) {
717 if (avio_feof(pb))
718 return AVERROR_EOF;
719 type = avio_rb16(pb);
720 len = avio_rb16(pb);
721 av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
722 if (len&1)
723 len += 1;
724 if (type == 2) { // absolute path
725 av_free(dref->path);
726 dref->path = av_mallocz(len+1);
727 if (!dref->path)
728 return AVERROR(ENOMEM);
729
730 ret = ffio_read_size(pb, dref->path, len);
731 if (ret < 0) {
732 av_freep(&dref->path);
733 return ret;
734 }
735 if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
736 len -= volume_len;
737 memmove(dref->path, dref->path+volume_len, len);
738 dref->path[len] = 0;
739 }
740 // trim string of any ending zeros
741 for (j = len - 1; j >= 0; j--) {
742 if (dref->path[j] == 0)
743 len--;
744 else
745 break;
746 }
747 for (j = 0; j < len; j++)
748 if (dref->path[j] == ':' || dref->path[j] == 0)
749 dref->path[j] = '/';
750 av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
751 } else if (type == 0) { // directory name
752 av_free(dref->dir);
753 dref->dir = av_malloc(len+1);
754 if (!dref->dir)
755 return AVERROR(ENOMEM);
756
757 ret = ffio_read_size(pb, dref->dir, len);
758 if (ret < 0) {
759 av_freep(&dref->dir);
760 return ret;
761 }
762 dref->dir[len] = 0;
763 for (j = 0; j < len; j++)
764 if (dref->dir[j] == ':')
765 dref->dir[j] = '/';
766 av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
767 } else
768 avio_skip(pb, len);
769 }
770 } else {
771 594 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
772 dref->type, size);
773 594 entries--;
774 594 i--;
775 }
776 594 avio_seek(pb, next, SEEK_SET);
777 }
778 594 return 0;
779 }
780
781 1087 static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
782 {
783 AVStream *st;
784 uint32_t type;
785 uint32_t ctype;
786 int64_t title_size;
787 char *title_str;
788 int ret;
789
790 1087 avio_r8(pb); /* version */
791 1087 avio_rb24(pb); /* flags */
792
793 /* component type */
794 1087 ctype = avio_rl32(pb);
795 1087 type = avio_rl32(pb); /* component subtype */
796
797 1087 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
798 1087 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
799
800
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 951 times.
1087 if (c->trak_index < 0) { // meta not inside a trak
801
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 125 times.
136 if (type == MKTAG('m','d','t','a')) {
802 11 c->found_hdlr_mdta = 1;
803 }
804 136 return 0;
805 }
806
807 951 st = c->fc->streams[c->fc->nb_streams-1];
808
809
2/2
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 649 times.
951 if (type == MKTAG('v','i','d','e'))
810 302 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
811
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 408 times.
649 else if (type == MKTAG('s','o','u','n'))
812 241 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
813
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 408 times.
408 else if (type == MKTAG('m','1','a',' '))
814 st->codecpar->codec_id = AV_CODEC_ID_MP2;
815
2/4
✓ Branch 0 taken 408 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 408 times.
408 else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
816 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
817
818 951 avio_rb32(pb); /* component manufacture */
819 951 avio_rb32(pb); /* component flags */
820 951 avio_rb32(pb); /* component flags mask */
821
822 951 title_size = atom.size - 24;
823
2/2
✓ Branch 0 taken 948 times.
✓ Branch 1 taken 3 times.
951 if (title_size > 0) {
824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 948 times.
948 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
825 return AVERROR_INVALIDDATA;
826 948 title_str = av_malloc(title_size + 1); /* Add null terminator */
827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 948 times.
948 if (!title_str)
828 return AVERROR(ENOMEM);
829
830 948 ret = ffio_read_size(pb, title_str, title_size);
831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 948 times.
948 if (ret < 0) {
832 av_freep(&title_str);
833 return ret;
834 }
835 948 title_str[title_size] = 0;
836
2/2
✓ Branch 0 taken 897 times.
✓ Branch 1 taken 51 times.
948 if (title_str[0]) {
837
4/4
✓ Branch 0 taken 690 times.
✓ Branch 1 taken 207 times.
✓ Branch 2 taken 688 times.
✓ Branch 3 taken 2 times.
897 int off = (!c->isom && title_str[0] == title_size - 1);
838 // flag added so as to not set stream handler name if already set from mdia->hdlr
839 897 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
840 }
841 948 av_freep(&title_str);
842 }
843
844 951 return 0;
845 }
846
847 150 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
848 {
849 150 return ff_mov_read_esds(c->fc, pb);
850 }
851
852 7 static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
853 {
854 AVStream *st;
855 AVPacketSideData *sd;
856 enum AVAudioServiceType *ast;
857 int ac3info, acmod, lfeon, bsmod;
858 uint64_t mask;
859
860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (c->fc->nb_streams < 1)
861 return 0;
862 7 st = c->fc->streams[c->fc->nb_streams-1];
863
864 7 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
865 7 &st->codecpar->nb_coded_side_data,
866 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
867 sizeof(*ast), 0);
868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sd)
869 return AVERROR(ENOMEM);
870
871 7 ast = (enum AVAudioServiceType*)sd->data;
872 7 ac3info = avio_rb24(pb);
873 7 bsmod = (ac3info >> 14) & 0x7;
874 7 acmod = (ac3info >> 11) & 0x7;
875 7 lfeon = (ac3info >> 10) & 0x1;
876
877 7 mask = ff_ac3_channel_layout_tab[acmod];
878
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (lfeon)
879 1 mask |= AV_CH_LOW_FREQUENCY;
880 7 av_channel_layout_uninit(&st->codecpar->ch_layout);
881 7 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
882
883 7 *ast = bsmod;
884
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)
885 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
886
887 7 return 0;
888 }
889
890 #if CONFIG_IAMFDEC
891 10 static int mov_read_iacb(MOVContext *c, AVIOContext *pb, MOVAtom atom)
892 {
893 AVStream *st;
894 MOVStreamContext *sc;
895 FFIOContext b;
896 AVIOContext *descriptor_pb;
897 AVDictionary *metadata;
898 IAMFContext *iamf;
899 int64_t start_time, duration;
900 unsigned descriptors_size;
901 int nb_frames, disposition;
902 int version, ret;
903
904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (atom.size < 5)
905 return AVERROR_INVALIDDATA;
906
907
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (c->fc->nb_streams < 1)
908 return 0;
909
910 10 version = avio_r8(pb);
911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (version != 1) {
912 av_log(c->fc, AV_LOG_ERROR, "%s configurationVersion %d",
913 version < 1 ? "invalid" : "unsupported", version);
914 return AVERROR_INVALIDDATA;
915 }
916
917 10 descriptors_size = ffio_read_leb(pb);
918
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)
919 return AVERROR_INVALIDDATA;
920
921 10 st = c->fc->streams[c->fc->nb_streams - 1];
922 10 sc = st->priv_data;
923
924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (st->codecpar->extradata) {
925 av_log(c->fc, AV_LOG_WARNING, "ignoring iacb\n");
926 return 0;
927 }
928
929 10 sc->iamf = av_mallocz(sizeof(*sc->iamf));
930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!sc->iamf)
931 return AVERROR(ENOMEM);
932 10 iamf = &sc->iamf->iamf;
933
934 10 st->codecpar->extradata = av_malloc(descriptors_size);
935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!st->codecpar->extradata)
936 return AVERROR(ENOMEM);
937 10 st->codecpar->extradata_size = descriptors_size;
938
939 10 ret = avio_read(pb, st->codecpar->extradata, descriptors_size);
940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret != descriptors_size)
941 return ret < 0 ? ret : AVERROR_INVALIDDATA;
942
943 10 ffio_init_read_context(&b, st->codecpar->extradata, descriptors_size);
944 10 descriptor_pb = &b.pub;
945
946 10 ret = ff_iamfdec_read_descriptors(iamf, descriptor_pb, descriptors_size, c->fc);
947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
948 return ret;
949
950 10 metadata = st->metadata;
951 10 st->metadata = NULL;
952 10 start_time = st->start_time;
953 10 nb_frames = st->nb_frames;
954 10 duration = st->duration;
955 10 disposition = st->disposition;
956
957
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_audio_elements; i++) {
958 10 IAMFAudioElement *audio_element = iamf->audio_elements[i];
959 const AVIAMFAudioElement *element;
960 AVStreamGroup *stg =
961 10 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, NULL);
962
963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!stg) {
964 ret = AVERROR(ENOMEM);
965 goto fail;
966 }
967
968 10 av_iamf_audio_element_free(&stg->params.iamf_audio_element);
969 10 stg->id = audio_element->audio_element_id;
970 /* Transfer ownership */
971 10 element = stg->params.iamf_audio_element = audio_element->element;
972 10 audio_element->element = NULL;
973
974
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int j = 0; j < audio_element->nb_substreams; j++) {
975 50 IAMFSubStream *substream = &audio_element->substreams[j];
976 AVStream *stream;
977
978
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) {
979
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (audio_element->layers[0].substream_count != 1)
980 2 disposition &= ~AV_DISPOSITION_DEFAULT;
981 10 stream = st;
982 } else
983 40 stream = avformat_new_stream(c->fc, NULL);
984
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (!stream) {
985 ret = AVERROR(ENOMEM);
986 goto fail;
987 }
988
989 50 stream->start_time = start_time;
990 50 stream->nb_frames = nb_frames;
991 50 stream->duration = duration;
992 50 stream->disposition = disposition;
993
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 10 times.
50 if (stream != st) {
994 40 stream->priv_data = sc;
995 40 sc->refcount++;
996 }
997
998
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 42 times.
50 if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
999 8 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1000
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) {
1001 40 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1002
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 6 times.
40 if (audio_element->layers[0].substream_count == 1)
1003 34 stream->disposition &= ~AV_DISPOSITION_DEFAULT;
1004 }
1005
1006 50 ret = avcodec_parameters_copy(stream->codecpar, substream->codecpar);
1007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (ret < 0)
1008 goto fail;
1009
1010 50 stream->id = substream->audio_substream_id;
1011
1012 50 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
1013
1014 50 ret = avformat_stream_group_add_stream(stg, stream);
1015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (ret < 0)
1016 goto fail;
1017 }
1018
1019 10 ret = av_dict_copy(&stg->metadata, metadata, 0);
1020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
1021 goto fail;
1022 }
1023
1024
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1025 10 IAMFMixPresentation *mix_presentation = iamf->mix_presentations[i];
1026 10 const AVIAMFMixPresentation *mix = mix_presentation->cmix;
1027 AVStreamGroup *stg =
1028 10 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, NULL);
1029
1030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!stg) {
1031 ret = AVERROR(ENOMEM);
1032 goto fail;
1033 }
1034
1035 10 av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
1036 10 stg->id = mix_presentation->mix_presentation_id;
1037 /* Transfer ownership */
1038 10 stg->params.iamf_mix_presentation = mix_presentation->mix;
1039 10 mix_presentation->mix = NULL;
1040
1041
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 10 times.
22 for (int j = 0; j < mix->nb_submixes; j++) {
1042 12 const AVIAMFSubmix *submix = mix->submixes[j];
1043
1044
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int k = 0; k < submix->nb_elements; k++) {
1045 12 const AVIAMFSubmixElement *submix_element = submix->elements[k];
1046 12 const AVStreamGroup *audio_element = NULL;
1047
1048
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 for (int l = 0; l < c->fc->nb_stream_groups; l++)
1049
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 &&
1050
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 c->fc->stream_groups[l]->id == submix_element->audio_element_id) {
1051 12 audio_element = c->fc->stream_groups[l];
1052 12 break;
1053 }
1054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 av_assert0(audio_element);
1055
1056
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 12 times.
64 for (int l = 0; l < audio_element->nb_streams; l++) {
1057 52 ret = avformat_stream_group_add_stream(stg, audio_element->streams[l]);
1058
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))
1059 goto fail;
1060 }
1061 }
1062 }
1063
1064 10 ret = av_dict_copy(&stg->metadata, metadata, 0);
1065
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
1066 goto fail;
1067 }
1068
1069 10 ret = 0;
1070 10 fail:
1071 10 av_dict_free(&metadata);
1072
1073 10 return ret;
1074 }
1075 #endif
1076
1077 1 static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1078 {
1079 AVStream *st;
1080 AVPacketSideData *sd;
1081 enum AVAudioServiceType *ast;
1082 int eac3info, acmod, lfeon, bsmod;
1083 uint64_t mask;
1084
1085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
1086 return 0;
1087 1 st = c->fc->streams[c->fc->nb_streams-1];
1088
1089 1 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1090 1 &st->codecpar->nb_coded_side_data,
1091 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
1092 sizeof(*ast), 0);
1093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sd)
1094 return AVERROR(ENOMEM);
1095
1096 1 ast = (enum AVAudioServiceType*)sd->data;
1097
1098 /* No need to parse fields for additional independent substreams and its
1099 * associated dependent substreams since libavcodec's E-AC-3 decoder
1100 * does not support them yet. */
1101 1 avio_rb16(pb); /* data_rate and num_ind_sub */
1102 1 eac3info = avio_rb24(pb);
1103 1 bsmod = (eac3info >> 12) & 0x1f;
1104 1 acmod = (eac3info >> 9) & 0x7;
1105 1 lfeon = (eac3info >> 8) & 0x1;
1106
1107 1 mask = ff_ac3_channel_layout_tab[acmod];
1108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (lfeon)
1109 mask |= AV_CH_LOW_FREQUENCY;
1110 1 av_channel_layout_uninit(&st->codecpar->ch_layout);
1111 1 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
1112
1113 1 *ast = bsmod;
1114
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)
1115 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
1116
1117 1 return 0;
1118 }
1119
1120 static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1121 {
1122 #define DDTS_SIZE 20
1123 uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
1124 AVStream *st = NULL;
1125 uint32_t frame_duration_code = 0;
1126 uint32_t channel_layout_code = 0;
1127 GetBitContext gb;
1128 int ret;
1129
1130 if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
1131 return ret;
1132
1133 init_get_bits(&gb, buf, 8 * DDTS_SIZE);
1134
1135 if (c->fc->nb_streams < 1) {
1136 return 0;
1137 }
1138 st = c->fc->streams[c->fc->nb_streams-1];
1139
1140 st->codecpar->sample_rate = get_bits_long(&gb, 32);
1141 if (st->codecpar->sample_rate <= 0) {
1142 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
1143 return AVERROR_INVALIDDATA;
1144 }
1145 skip_bits_long(&gb, 32); /* max bitrate */
1146 st->codecpar->bit_rate = get_bits_long(&gb, 32);
1147 st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
1148 frame_duration_code = get_bits(&gb, 2);
1149 skip_bits(&gb, 30); /* various fields */
1150 channel_layout_code = get_bits(&gb, 16);
1151
1152 st->codecpar->frame_size =
1153 (frame_duration_code == 0) ? 512 :
1154 (frame_duration_code == 1) ? 1024 :
1155 (frame_duration_code == 2) ? 2048 :
1156 (frame_duration_code == 3) ? 4096 : 0;
1157
1158 if (channel_layout_code > 0xff) {
1159 av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout\n");
1160 }
1161 av_channel_layout_uninit(&st->codecpar->ch_layout);
1162 av_channel_layout_from_mask(&st->codecpar->ch_layout,
1163 ((channel_layout_code & 0x1) ? AV_CH_FRONT_CENTER : 0) |
1164 ((channel_layout_code & 0x2) ? AV_CH_FRONT_LEFT : 0) |
1165 ((channel_layout_code & 0x2) ? AV_CH_FRONT_RIGHT : 0) |
1166 ((channel_layout_code & 0x4) ? AV_CH_SIDE_LEFT : 0) |
1167 ((channel_layout_code & 0x4) ? AV_CH_SIDE_RIGHT : 0) |
1168 ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0));
1169
1170 return 0;
1171 }
1172
1173 51 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1174 {
1175 AVStream *st;
1176
1177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (c->fc->nb_streams < 1)
1178 return 0;
1179 51 st = c->fc->streams[c->fc->nb_streams-1];
1180
1181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (atom.size < 16)
1182 return 0;
1183
1184 /* skip version and flags */
1185 51 avio_skip(pb, 4);
1186
1187 51 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
1188
1189 51 return 0;
1190 }
1191
1192 5 static int mov_read_chnl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1193 {
1194 5 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
1195 int version, flags;
1196 int ret;
1197 AVStream *st;
1198
1199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
1200 return 0;
1201 5 st = c->fc->streams[c->fc->nb_streams-1];
1202
1203 5 version = avio_r8(pb);
1204 5 flags = avio_rb24(pb);
1205
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) {
1206 av_log(c->fc, AV_LOG_ERROR,
1207 "Unsupported 'chnl' box with version %d, flags: %#x",
1208 version, flags);
1209 return AVERROR_INVALIDDATA;
1210 }
1211
1212 5 ret = ff_mov_read_chnl(c->fc, pb, st);
1213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
1214 return ret;
1215
1216
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_tell(pb) != end) {
1217 av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data inside chnl\n",
1218 end - avio_tell(pb));
1219 avio_seek(pb, end, SEEK_SET);
1220 }
1221 5 return ret;
1222 }
1223
1224 2 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1225 {
1226 AVStream *st;
1227 int ret;
1228
1229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
1230 return 0;
1231 2 st = c->fc->streams[c->fc->nb_streams-1];
1232
1233
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)
1234 av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
1235
1236 2 return ret;
1237 }
1238
1239 16 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1240 {
1241 AVStream *st;
1242 HEIFItem *item;
1243 AVPacketSideData *sd;
1244 16 int width, height, err = 0;
1245 AVRational aperture_width, aperture_height, horiz_off, vert_off;
1246 AVRational pc_x, pc_y;
1247 uint64_t top, bottom, left, right;
1248
1249 16 item = heif_cur_item(c);
1250 16 st = get_curr_st(c);
1251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!st)
1252 return 0;
1253
1254 16 width = st->codecpar->width;
1255 16 height = st->codecpar->height;
1256
4/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
16 if ((!width || !height) && item) {
1257 4 width = item->width;
1258 4 height = item->height;
1259 }
1260
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
16 if (!width || !height) {
1261 err = AVERROR_INVALIDDATA;
1262 goto fail;
1263 }
1264
1265 16 aperture_width.num = avio_rb32(pb);
1266 16 aperture_width.den = avio_rb32(pb);
1267 16 aperture_height.num = avio_rb32(pb);
1268 16 aperture_height.den = avio_rb32(pb);
1269
1270 16 horiz_off.num = avio_rb32(pb);
1271 16 horiz_off.den = avio_rb32(pb);
1272 16 vert_off.num = avio_rb32(pb);
1273 16 vert_off.den = avio_rb32(pb);
1274
1275
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 if (aperture_width.num < 0 || aperture_width.den < 0 ||
1276
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 aperture_height.num < 0 || aperture_height.den < 0 ||
1277
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
16 horiz_off.den < 0 || vert_off.den < 0) {
1278 err = AVERROR_INVALIDDATA;
1279 goto fail;
1280 }
1281 16 av_log(c->fc, AV_LOG_TRACE, "clap: apertureWidth %d/%d, apertureHeight %d/%d "
1282 "horizOff %d/%d vertOff %d/%d\n",
1283 aperture_width.num, aperture_width.den, aperture_height.num, aperture_height.den,
1284 horiz_off.num, horiz_off.den, vert_off.num, vert_off.den);
1285
1286 16 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1287 16 pc_x = av_add_q(pc_x, horiz_off);
1288 16 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1289 16 pc_y = av_add_q(pc_y, vert_off);
1290
1291 16 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1292 16 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1293 16 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1294 16 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1295
1296 16 left = av_q2d(av_sub_q(pc_x, aperture_width));
1297 16 right = av_q2d(av_add_q(pc_x, aperture_width));
1298 16 top = av_q2d(av_sub_q(pc_y, aperture_height));
1299 16 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1300
1301
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 if (bottom > (height - 1) ||
1302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 right > (width - 1)) {
1303 2 err = AVERROR_INVALIDDATA;
1304 2 goto fail;
1305 }
1306
1307 14 bottom = height - 1 - bottom;
1308 14 right = width - 1 - right;
1309
1310
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
14 if (!(left | right | top | bottom))
1311 6 return 0;
1312
1313
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if ((left + right) >= width ||
1314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 (top + bottom) >= height) {
1315 err = AVERROR_INVALIDDATA;
1316 goto fail;
1317 }
1318
1319 8 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1320 8 &st->codecpar->nb_coded_side_data,
1321 AV_PKT_DATA_FRAME_CROPPING,
1322 sizeof(uint32_t) * 4, 0);
1323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!sd)
1324 return AVERROR(ENOMEM);
1325
1326 8 AV_WL32A(sd->data, top);
1327 8 AV_WL32A(sd->data + 4, bottom);
1328 8 AV_WL32A(sd->data + 8, left);
1329 8 AV_WL32A(sd->data + 12, right);
1330
1331 10 fail:
1332
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (err < 0) {
1333 2 int explode = !!(c->fc->error_recognition & AV_EF_EXPLODE);
1334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_log(c->fc, explode ? AV_LOG_ERROR : AV_LOG_WARNING, "Invalid clap box\n");
1335
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!explode)
1336 2 err = 0;
1337 }
1338
1339 10 return err;
1340 }
1341
1342 /* This atom overrides any previously set aspect ratio */
1343 66 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1344 {
1345 66 const int num = avio_rb32(pb);
1346 66 const int den = avio_rb32(pb);
1347 AVStream *st;
1348 MOVStreamContext *sc;
1349
1350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (c->fc->nb_streams < 1)
1351 return 0;
1352 66 st = c->fc->streams[c->fc->nb_streams-1];
1353 66 sc = st->priv_data;
1354
1355 66 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1356
1357
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 2 times.
66 if (den != 0) {
1358 64 sc->h_spacing = num;
1359 64 sc->v_spacing = den;
1360 }
1361 66 return 0;
1362 }
1363
1364 /* this atom contains actual media data */
1365 873 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1366 {
1367
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 873 times.
873 if (atom.size == 0) /* wrong one (MP4) */
1368 return 0;
1369 873 c->found_mdat=1;
1370 873 return 0; /* now go for moov */
1371 }
1372
1373 #define DRM_BLOB_SIZE 56
1374
1375 static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1376 {
1377 uint8_t intermediate_key[20];
1378 uint8_t intermediate_iv[20];
1379 uint8_t input[64];
1380 uint8_t output[64];
1381 uint8_t file_checksum[20];
1382 uint8_t calculated_checksum[20];
1383 char checksum_string[2 * sizeof(file_checksum) + 1];
1384 struct AVSHA *sha;
1385 int i;
1386 int ret = 0;
1387 uint8_t *activation_bytes = c->activation_bytes;
1388 uint8_t *fixed_key = c->audible_fixed_key;
1389
1390 c->aax_mode = 1;
1391
1392 sha = av_sha_alloc();
1393 if (!sha)
1394 return AVERROR(ENOMEM);
1395 av_free(c->aes_decrypt);
1396 c->aes_decrypt = av_aes_alloc();
1397 if (!c->aes_decrypt) {
1398 ret = AVERROR(ENOMEM);
1399 goto fail;
1400 }
1401
1402 /* drm blob processing */
1403 avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1404 avio_read(pb, input, DRM_BLOB_SIZE);
1405 avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1406 avio_read(pb, file_checksum, 20);
1407
1408 // required by external tools
1409 ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1);
1410 av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string);
1411
1412 /* verify activation data */
1413 if (!activation_bytes) {
1414 av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1415 ret = 0; /* allow ffprobe to continue working on .aax files */
1416 goto fail;
1417 }
1418 if (c->activation_bytes_size != 4) {
1419 av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1420 ret = AVERROR(EINVAL);
1421 goto fail;
1422 }
1423
1424 /* verify fixed key */
1425 if (c->audible_fixed_key_size != 16) {
1426 av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1427 ret = AVERROR(EINVAL);
1428 goto fail;
1429 }
1430
1431 /* AAX (and AAX+) key derivation */
1432 av_sha_init(sha, 160);
1433 av_sha_update(sha, fixed_key, 16);
1434 av_sha_update(sha, activation_bytes, 4);
1435 av_sha_final(sha, intermediate_key);
1436 av_sha_init(sha, 160);
1437 av_sha_update(sha, fixed_key, 16);
1438 av_sha_update(sha, intermediate_key, 20);
1439 av_sha_update(sha, activation_bytes, 4);
1440 av_sha_final(sha, intermediate_iv);
1441 av_sha_init(sha, 160);
1442 av_sha_update(sha, intermediate_key, 16);
1443 av_sha_update(sha, intermediate_iv, 16);
1444 av_sha_final(sha, calculated_checksum);
1445 if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1446 av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1447 ret = AVERROR_INVALIDDATA;
1448 goto fail;
1449 }
1450 av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1451 av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1452 for (i = 0; i < 4; i++) {
1453 // file data (in output) is stored in big-endian mode
1454 if (activation_bytes[i] != output[3 - i]) { // critical error
1455 av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1456 ret = AVERROR_INVALIDDATA;
1457 goto fail;
1458 }
1459 }
1460 memcpy(c->file_key, output + 8, 16);
1461 memcpy(input, output + 26, 16);
1462 av_sha_init(sha, 160);
1463 av_sha_update(sha, input, 16);
1464 av_sha_update(sha, c->file_key, 16);
1465 av_sha_update(sha, fixed_key, 16);
1466 av_sha_final(sha, c->file_iv);
1467
1468 fail:
1469 av_free(sha);
1470
1471 return ret;
1472 }
1473
1474 static int mov_aaxc_crypto(MOVContext *c)
1475 {
1476 if (c->audible_key_size != 16) {
1477 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n");
1478 return AVERROR(EINVAL);
1479 }
1480
1481 if (c->audible_iv_size != 16) {
1482 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n");
1483 return AVERROR(EINVAL);
1484 }
1485
1486 c->aes_decrypt = av_aes_alloc();
1487 if (!c->aes_decrypt) {
1488 return AVERROR(ENOMEM);
1489 }
1490
1491 memcpy(c->file_key, c->audible_key, 16);
1492 memcpy(c->file_iv, c->audible_iv, 16);
1493 c->aax_mode = 1;
1494
1495 return 0;
1496 }
1497
1498 // Audible AAX (and AAX+) bytestream decryption
1499 static int aax_filter(uint8_t *input, int size, MOVContext *c)
1500 {
1501 int blocks = 0;
1502 unsigned char iv[16];
1503
1504 memcpy(iv, c->file_iv, 16); // iv is overwritten
1505 blocks = size >> 4; // trailing bytes are not encrypted!
1506 av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1507 av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1508
1509 return 0;
1510 }
1511
1512 /* read major brand, minor version and compatible brands and store them as metadata */
1513 452 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1514 {
1515 uint32_t minor_ver;
1516 int comp_brand_size;
1517 char* comp_brands_str;
1518 452 uint8_t type[5] = {0};
1519 452 int ret = ffio_read_size(pb, type, 4);
1520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 452 times.
452 if (ret < 0)
1521 return ret;
1522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 452 times.
452 if (c->fc->nb_streams) {
1523 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1524 return AVERROR_INVALIDDATA;
1525 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate FTYP\n");
1526 return 0;
1527 }
1528
1529
2/2
✓ Branch 0 taken 220 times.
✓ Branch 1 taken 232 times.
452 if (strcmp(type, "qt "))
1530 220 c->isom = 1;
1531 452 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1532 452 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1533 452 minor_ver = avio_rb32(pb); /* minor version */
1534 452 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1535
1536 452 comp_brand_size = atom.size - 8;
1537
2/4
✓ Branch 0 taken 452 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 452 times.
452 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1538 return AVERROR_INVALIDDATA;
1539 452 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 452 times.
452 if (!comp_brands_str)
1541 return AVERROR(ENOMEM);
1542
1543 452 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 452 times.
452 if (ret < 0) {
1545 av_freep(&comp_brands_str);
1546 return ret;
1547 }
1548 452 comp_brands_str[comp_brand_size] = 0;
1549 452 av_dict_set(&c->fc->metadata, "compatible_brands",
1550 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1551
1552 // Logic for handling Audible's .aaxc files
1553
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 452 times.
452 if (!strcmp(type, "aaxc")) {
1554 mov_aaxc_crypto(c);
1555 }
1556
1557 452 return 0;
1558 }
1559
1560 /* this atom should contain all header atoms */
1561 484 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1562 {
1563 int ret;
1564
1565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
484 if (c->found_moov) {
1566 av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1567 avio_skip(pb, atom.size);
1568 return 0;
1569 }
1570
1571
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 484 times.
484 if ((ret = mov_read_default(c, pb, atom)) < 0)
1572 return ret;
1573 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1574 /* so we don't parse the whole file if over a network */
1575 484 c->found_moov=1;
1576 484 return 0; /* now go for mdat */
1577 }
1578
1579 2869 static MOVFragmentStreamInfo * get_frag_stream_info(
1580 MOVFragmentIndex *frag_index,
1581 int index,
1582 int id)
1583 {
1584 int i;
1585 MOVFragmentIndexItem * item;
1586
1587
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)
1588 return NULL;
1589 2869 item = &frag_index->item[index];
1590
1/2
✓ Branch 0 taken 2993 times.
✗ Branch 1 not taken.
2993 for (i = 0; i < item->nb_stream_info; i++)
1591
2/2
✓ Branch 0 taken 2869 times.
✓ Branch 1 taken 124 times.
2993 if (item->stream_info[i].id == id)
1592 2869 return &item->stream_info[i];
1593
1594 // This shouldn't happen
1595 return NULL;
1596 }
1597
1598 388 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1599 {
1600 int i;
1601 MOVFragmentIndexItem * item;
1602
1603
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_index->current < 0 ||
1604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 frag_index->current >= frag_index->nb_items)
1605 return;
1606
1607 388 item = &frag_index->item[frag_index->current];
1608
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < item->nb_stream_info; i++)
1609
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (item->stream_info[i].id == id) {
1610 388 item->current = i;
1611 388 return;
1612 }
1613
1614 // id not found. This shouldn't happen.
1615 item->current = -1;
1616 }
1617
1618 1149 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1619 MOVFragmentIndex *frag_index)
1620 {
1621 MOVFragmentIndexItem *item;
1622
1/2
✓ Branch 0 taken 1149 times.
✗ Branch 1 not taken.
1149 if (frag_index->current < 0 ||
1623
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1146 times.
1149 frag_index->current >= frag_index->nb_items)
1624 3 return NULL;
1625
1626 1146 item = &frag_index->item[frag_index->current];
1627
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)
1628 1146 return &item->stream_info[item->current];
1629
1630 // This shouldn't happen
1631 return NULL;
1632 }
1633
1634 798 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1635 {
1636 int a, b, m;
1637 int64_t moof_offset;
1638
1639 // Optimize for appending new entries
1640
2/2
✓ Branch 0 taken 788 times.
✓ Branch 1 taken 10 times.
798 if (!frag_index->nb_items ||
1641
2/2
✓ Branch 0 taken 383 times.
✓ Branch 1 taken 405 times.
788 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1642 393 return frag_index->nb_items;
1643
1644 405 a = -1;
1645 405 b = frag_index->nb_items;
1646
1647
2/2
✓ Branch 0 taken 2655 times.
✓ Branch 1 taken 405 times.
3060 while (b - a > 1) {
1648 2655 m = (a + b) >> 1;
1649 2655 moof_offset = frag_index->item[m].moof_offset;
1650
2/2
✓ Branch 0 taken 732 times.
✓ Branch 1 taken 1923 times.
2655 if (moof_offset >= offset)
1651 732 b = m;
1652
2/2
✓ Branch 0 taken 2328 times.
✓ Branch 1 taken 327 times.
2655 if (moof_offset <= offset)
1653 2328 a = m;
1654 }
1655 405 return b;
1656 }
1657
1658 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1659 {
1660 av_assert0(frag_stream_info);
1661 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1662 return frag_stream_info->sidx_pts;
1663 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1664 return frag_stream_info->first_tfra_pts;
1665 return frag_stream_info->tfdt_dts;
1666 }
1667
1668 219 static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1669 MOVFragmentIndex *frag_index, int index)
1670 {
1671 MOVFragmentStreamInfo * frag_stream_info;
1672 219 MOVStreamContext *sc = dst_st->priv_data;
1673 int64_t timestamp;
1674 int i, j;
1675
1676 // If the stream is referenced by any sidx, limit the search
1677 // to fragments that referenced this stream in the sidx
1678
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (sc->has_sidx) {
1679 219 frag_stream_info = get_frag_stream_info(frag_index, index, sc->id);
1680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!frag_stream_info)
1681 return AV_NOPTS_VALUE;
1682
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1683 219 return frag_stream_info->sidx_pts;
1684 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1685 return frag_stream_info->first_tfra_pts;
1686 return frag_stream_info->sidx_pts;
1687 }
1688
1689 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
1690 AVStream *frag_stream = NULL;
1691 frag_stream_info = &frag_index->item[index].stream_info[i];
1692 for (j = 0; j < s->nb_streams; j++) {
1693 MOVStreamContext *sc2 = s->streams[j]->priv_data;
1694 if (sc2->id == frag_stream_info->id)
1695 frag_stream = s->streams[j];
1696 }
1697 if (!frag_stream) {
1698 av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1699 continue;
1700 }
1701 timestamp = get_stream_info_time(frag_stream_info);
1702 if (timestamp != AV_NOPTS_VALUE)
1703 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1704 }
1705 return AV_NOPTS_VALUE;
1706 }
1707
1708 26 static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1709 AVStream *st, int64_t timestamp)
1710 {
1711 int a, b, m, m0;
1712 int64_t frag_time;
1713
1714 26 a = -1;
1715 26 b = frag_index->nb_items;
1716
1717
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 26 times.
245 while (b - a > 1) {
1718 219 m0 = m = (a + b) >> 1;
1719
1720
2/4
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 219 times.
438 while (m < b &&
1721 219 (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
1722 m++;
1723
1724
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)
1725 93 a = m;
1726 else
1727 126 b = m0;
1728 }
1729
1730 26 return a;
1731 }
1732
1733 756 static int update_frag_index(MOVContext *c, int64_t offset)
1734 {
1735 int index, i;
1736 MOVFragmentIndexItem * item;
1737 MOVFragmentStreamInfo * frag_stream_info;
1738
1739 // If moof_offset already exists in frag_index, return index to it
1740 756 index = search_frag_moof_offset(&c->frag_index, offset);
1741
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 389 times.
756 if (index < c->frag_index.nb_items &&
1742
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 c->frag_index.item[index].moof_offset == offset)
1743 367 return index;
1744
1745 // offset is not yet in frag index.
1746 // Insert new item at index (sorted by moof offset)
1747 389 item = av_fast_realloc(c->frag_index.item,
1748 389 &c->frag_index.allocated_size,
1749 389 (c->frag_index.nb_items + 1) *
1750 sizeof(*c->frag_index.item));
1751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (!item)
1752 return -1;
1753 389 c->frag_index.item = item;
1754
1755 389 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1756 sizeof(*item->stream_info));
1757
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (!frag_stream_info)
1758 return -1;
1759
1760
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 389 times.
796 for (i = 0; i < c->fc->nb_streams; i++) {
1761 // Avoid building frag index if streams lack track id.
1762 407 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 407 times.
407 if (sc->id < 0) {
1764 av_free(frag_stream_info);
1765 return AVERROR_INVALIDDATA;
1766 }
1767
1768 407 frag_stream_info[i].id = sc->id;
1769 407 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1770 407 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1771 407 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1772 407 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1773 407 frag_stream_info[i].index_base = -1;
1774 407 frag_stream_info[i].index_entry = -1;
1775 407 frag_stream_info[i].encryption_index = NULL;
1776 407 frag_stream_info[i].stsd_id = -1;
1777 }
1778
1779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (index < c->frag_index.nb_items)
1780 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1781 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1782
1783 389 item = &c->frag_index.item[index];
1784 389 item->headers_read = 0;
1785 389 item->current = 0;
1786 389 item->nb_stream_info = c->fc->nb_streams;
1787 389 item->moof_offset = offset;
1788 389 item->stream_info = frag_stream_info;
1789 389 c->frag_index.nb_items++;
1790
1791 389 return index;
1792 }
1793
1794 388 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1795 int id, int entries)
1796 {
1797 int i;
1798 MOVFragmentStreamInfo * frag_stream_info;
1799
1800
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (index < 0)
1801 388 return;
1802 for (i = index; i < frag_index->nb_items; i++) {
1803 frag_stream_info = get_frag_stream_info(frag_index, i, id);
1804 if (frag_stream_info && frag_stream_info->index_entry >= 0)
1805 frag_stream_info->index_entry += entries;
1806 }
1807 }
1808
1809 388 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1810 {
1811 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1812 388 c->fragment.found_tfhd = 0;
1813
1814
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) {
1815 c->has_looked_for_mfra = 1;
1816 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1817 int ret;
1818 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1819 "for a mfra\n");
1820 if ((ret = mov_read_mfra(c, pb)) < 0) {
1821 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1822 "read the mfra (may be a live ismv)\n");
1823 }
1824 } else {
1825 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1826 "seekable, can not look for mfra\n");
1827 }
1828 }
1829 388 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1830 388 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1831 388 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1832 388 return mov_read_default(c, pb, atom);
1833 }
1834
1835 1075 static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version)
1836 {
1837 int64_t time;
1838
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1064 times.
1075 if (version == 1) {
1839 11 time = avio_rb64(pb);
1840 11 avio_rb64(pb);
1841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (time < 0) {
1842 av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n");
1843 return;
1844 }
1845 } else {
1846 1064 time = avio_rb32(pb);
1847 1064 avio_rb32(pb); /* modification time */
1848
4/4
✓ Branch 0 taken 519 times.
✓ Branch 1 taken 545 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 471 times.
1064 if (time > 0 && time < 2082844800) {
1849 48 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1850 48 time += 2082844800;
1851 }
1852 }
1853
2/2
✓ Branch 0 taken 525 times.
✓ Branch 1 taken 550 times.
1075 if (time) {
1854 525 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1855
1856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 525 times.
525 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1857 av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n");
1858 return;
1859 }
1860
1861 525 avpriv_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1862 }
1863 }
1864
1865 594 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1866 {
1867 AVStream *st;
1868 MOVStreamContext *sc;
1869 int version;
1870 594 char language[4] = {0};
1871 unsigned lang;
1872
1873
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
1874 return 0;
1875 594 st = c->fc->streams[c->fc->nb_streams-1];
1876 594 sc = st->priv_data;
1877
1878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (sc->time_scale) {
1879 av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
1880 return AVERROR_INVALIDDATA;
1881 }
1882
1883 594 version = avio_r8(pb);
1884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (version > 1) {
1885 avpriv_request_sample(c->fc, "Version %d", version);
1886 return AVERROR_PATCHWELCOME;
1887 }
1888 594 avio_rb24(pb); /* flags */
1889 594 mov_metadata_creation_time(c, pb, &st->metadata, version);
1890
1891 594 sc->time_scale = avio_rb32(pb);
1892
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (sc->time_scale <= 0) {
1893 av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
1894 sc->time_scale = 1;
1895 }
1896
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 585 times.
594 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1897
1898
6/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 585 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 585 times.
✓ Branch 5 taken 4 times.
594 if ((version == 1 && st->duration == UINT64_MAX) ||
1899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 585 times.
585 (version != 1 && st->duration == UINT32_MAX)) {
1900 5 st->duration = 0;
1901 }
1902
1903 594 lang = avio_rb16(pb); /* language */
1904
2/2
✓ Branch 1 taken 422 times.
✓ Branch 2 taken 172 times.
594 if (ff_mov_lang_to_iso639(lang, language))
1905 422 av_dict_set(&st->metadata, "language", language, 0);
1906 594 avio_rb16(pb); /* quality */
1907
1908 594 return 0;
1909 }
1910
1911 481 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1912 {
1913 int i;
1914 481 int version = avio_r8(pb); /* version */
1915 481 avio_rb24(pb); /* flags */
1916
1917 481 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
1918 481 c->time_scale = avio_rb32(pb); /* time scale */
1919
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 481 times.
481 if (c->time_scale <= 0) {
1920 av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
1921 c->time_scale = 1;
1922 }
1923 481 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
1924
1925
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 479 times.
481 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1926 481 avio_rb32(pb); /* preferred scale */
1927
1928 481 avio_rb16(pb); /* preferred volume */
1929
1930 481 avio_skip(pb, 10); /* reserved */
1931
1932 /* movie display matrix, store it in main context and use it later on */
1933
2/2
✓ Branch 0 taken 1443 times.
✓ Branch 1 taken 481 times.
1924 for (i = 0; i < 3; i++) {
1934 1443 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
1935 1443 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
1936 1443 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
1937 }
1938
1939 481 avio_rb32(pb); /* preview time */
1940 481 avio_rb32(pb); /* preview duration */
1941 481 avio_rb32(pb); /* poster time */
1942 481 avio_rb32(pb); /* selection time */
1943 481 avio_rb32(pb); /* selection duration */
1944 481 avio_rb32(pb); /* current time */
1945 481 avio_rb32(pb); /* next track ID */
1946
1947 481 return 0;
1948 }
1949
1950 7 static void set_last_stream_little_endian(AVFormatContext *fc)
1951 {
1952 AVStream *st;
1953
1954
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (fc->nb_streams < 1)
1955 return;
1956 7 st = fc->streams[fc->nb_streams-1];
1957
1958
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) {
1959 5 case AV_CODEC_ID_PCM_S16BE:
1960 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
1961 5 break;
1962 1 case AV_CODEC_ID_PCM_S24BE:
1963 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
1964 1 break;
1965 case AV_CODEC_ID_PCM_S32BE:
1966 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
1967 break;
1968 1 case AV_CODEC_ID_PCM_F32BE:
1969 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
1970 1 break;
1971 case AV_CODEC_ID_PCM_F64BE:
1972 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
1973 break;
1974 default:
1975 break;
1976 }
1977 }
1978
1979 5 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1980 {
1981 5 int little_endian = avio_rb16(pb) & 0xFF;
1982 5 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
1983
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (little_endian == 1)
1984 1 set_last_stream_little_endian(c->fc);
1985 5 return 0;
1986 }
1987
1988 6 static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1989 {
1990 int format_flags;
1991 int version, flags;
1992 int pcm_sample_size;
1993 6 AVFormatContext *fc = c->fc;
1994 AVStream *st;
1995 MOVStreamContext *sc;
1996
1997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 6) {
1998 av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n");
1999 return AVERROR_INVALIDDATA;
2000 }
2001
2002 6 version = avio_r8(pb);
2003 6 flags = avio_rb24(pb);
2004
2005
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) {
2006 av_log(c->fc, AV_LOG_ERROR,
2007 "Unsupported 'pcmC' box with version %d, flags: %x",
2008 version, flags);
2009 return AVERROR_INVALIDDATA;
2010 }
2011
2012 6 format_flags = avio_r8(pb);
2013 6 pcm_sample_size = avio_r8(pb);
2014
2015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fc->nb_streams < 1)
2016 return AVERROR_INVALIDDATA;
2017
2018 6 st = fc->streams[fc->nb_streams - 1];
2019 6 sc = st->priv_data;
2020
2021
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (sc->format == MOV_MP4_FPCM_TAG) {
2022
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (pcm_sample_size) {
2023 1 case 32:
2024 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE;
2025 1 break;
2026 case 64:
2027 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE;
2028 break;
2029 default:
2030 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2031 pcm_sample_size,
2032 av_fourcc2str(sc->format));
2033 return AVERROR_INVALIDDATA;
2034 }
2035
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (sc->format == MOV_MP4_IPCM_TAG) {
2036
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 switch (pcm_sample_size) {
2037 5 case 16:
2038 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2039 5 break;
2040 case 24:
2041 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
2042 break;
2043 case 32:
2044 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
2045 break;
2046 default:
2047 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2048 pcm_sample_size,
2049 av_fourcc2str(sc->format));
2050 return AVERROR_INVALIDDATA;
2051 }
2052 } else {
2053 av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n",
2054 av_fourcc2str(sc->format));
2055 return AVERROR_INVALIDDATA;
2056 }
2057
2058
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
2059 6 set_last_stream_little_endian(c->fc);
2060 6 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2061
2062 6 return 0;
2063 }
2064
2065 43 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2066 {
2067 AVStream *st;
2068 43 HEIFItem *item = NULL;
2069 43 char color_parameter_type[5] = { 0 };
2070 uint16_t color_primaries, color_trc, color_matrix;
2071 int ret;
2072
2073 43 st = get_curr_st(c);
2074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st) {
2075 item = heif_cur_item(c);
2076 if (!item)
2077 return 0;
2078 }
2079
2080 43 ret = ffio_read_size(pb, color_parameter_type, 4);
2081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
2082 return ret;
2083
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 10 times.
43 if (strncmp(color_parameter_type, "nclx", 4) &&
2084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 strncmp(color_parameter_type, "nclc", 4) &&
2085 strncmp(color_parameter_type, "prof", 4)) {
2086 av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
2087 color_parameter_type);
2088 return 0;
2089 }
2090
2091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!strncmp(color_parameter_type, "prof", 4)) {
2092 AVPacketSideData *sd;
2093 uint8_t *icc_profile;
2094 if (st) {
2095 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
2096 &st->codecpar->nb_coded_side_data,
2097 AV_PKT_DATA_ICC_PROFILE,
2098 atom.size - 4, 0);
2099 if (!sd)
2100 return AVERROR(ENOMEM);
2101 icc_profile = sd->data;
2102 } else {
2103 av_freep(&item->icc_profile);
2104 icc_profile = item->icc_profile = av_malloc(atom.size - 4);
2105 if (!icc_profile) {
2106 item->icc_profile_size = 0;
2107 return AVERROR(ENOMEM);
2108 }
2109 item->icc_profile_size = atom.size - 4;
2110 }
2111 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
2112 if (ret < 0)
2113 return ret;
2114
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 } else if (st) {
2115 43 color_primaries = avio_rb16(pb);
2116 43 color_trc = avio_rb16(pb);
2117 43 color_matrix = avio_rb16(pb);
2118
2119 43 av_log(c->fc, AV_LOG_TRACE,
2120 "%s: pri %d trc %d matrix %d",
2121 color_parameter_type, color_primaries, color_trc, color_matrix);
2122
2123
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 33 times.
43 if (!strncmp(color_parameter_type, "nclx", 4)) {
2124 10 uint8_t color_range = avio_r8(pb) >> 7;
2125 10 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (color_range)
2127 st->codecpar->color_range = AVCOL_RANGE_JPEG;
2128 else
2129 10 st->codecpar->color_range = AVCOL_RANGE_MPEG;
2130 }
2131
2132
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_primaries_name(color_primaries))
2133 color_primaries = AVCOL_PRI_UNSPECIFIED;
2134
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_transfer_name(color_trc))
2135 color_trc = AVCOL_TRC_UNSPECIFIED;
2136
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_space_name(color_matrix))
2137 color_matrix = AVCOL_SPC_UNSPECIFIED;
2138
2139 43 st->codecpar->color_primaries = color_primaries;
2140 43 st->codecpar->color_trc = color_trc;
2141 43 st->codecpar->color_space = color_matrix;
2142 43 av_log(c->fc, AV_LOG_TRACE, "\n");
2143 }
2144 43 return 0;
2145 }
2146
2147 112 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2148 {
2149 AVStream *st;
2150 unsigned mov_field_order;
2151 112 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2152
2153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (c->fc->nb_streams < 1) // will happen with jp2 files
2154 return 0;
2155 112 st = c->fc->streams[c->fc->nb_streams-1];
2156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (atom.size < 2)
2157 return AVERROR_INVALIDDATA;
2158 112 mov_field_order = avio_rb16(pb);
2159
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 20 times.
112 if ((mov_field_order & 0xFF00) == 0x0100)
2160 92 decoded_field_order = AV_FIELD_PROGRESSIVE;
2161
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 else if ((mov_field_order & 0xFF00) == 0x0200) {
2162
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) {
2163 1 case 0x01: decoded_field_order = AV_FIELD_TT;
2164 1 break;
2165 case 0x06: decoded_field_order = AV_FIELD_BB;
2166 break;
2167 1 case 0x09: decoded_field_order = AV_FIELD_TB;
2168 1 break;
2169 18 case 0x0E: decoded_field_order = AV_FIELD_BT;
2170 18 break;
2171 }
2172 }
2173
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) {
2174 av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
2175 }
2176 112 st->codecpar->field_order = decoded_field_order;
2177
2178 112 return 0;
2179 }
2180
2181 68 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
2182 {
2183 68 int err = 0;
2184 68 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
2185
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)
2186 return AVERROR_INVALIDDATA;
2187
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
68 if ((err = av_reallocp(&par->extradata, size)) < 0) {
2188 par->extradata_size = 0;
2189 return err;
2190 }
2191 68 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
2192 68 return 0;
2193 }
2194
2195 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
2196 65 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2197 AVCodecParameters *par, uint8_t *buf)
2198 {
2199 65 int64_t result = atom.size;
2200 int err;
2201
2202 65 AV_WB32(buf , atom.size + 8);
2203 65 AV_WL32(buf + 4, atom.type);
2204 65 err = ffio_read_size(pb, buf + 8, atom.size);
2205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (err < 0) {
2206 par->extradata_size -= atom.size;
2207 return err;
2208
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 } else if (err < atom.size) {
2209 av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
2210 par->extradata_size -= atom.size - err;
2211 result = err;
2212 }
2213 65 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2214 65 return result;
2215 }
2216
2217 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
2218 58 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2219 enum AVCodecID codec_id)
2220 {
2221 AVStream *st;
2222 uint64_t original_size;
2223 int err;
2224
2225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (c->fc->nb_streams < 1) // will happen with jp2 files
2226 return 0;
2227 58 st = c->fc->streams[c->fc->nb_streams-1];
2228
2229
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
58 if (st->codecpar->codec_id != codec_id)
2230 19 return 0; /* unexpected codec_id - don't mess with extradata */
2231
2232 39 original_size = st->codecpar->extradata_size;
2233 39 err = mov_realloc_extradata(st->codecpar, atom);
2234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err)
2235 return err;
2236
2237 39 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
2238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err < 0)
2239 return err;
2240 39 return 0; // Note: this is the original behavior to ignore truncation.
2241 }
2242
2243 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
2244 16 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2245 {
2246 16 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
2247 }
2248
2249 static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2250 {
2251 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS);
2252 }
2253
2254 static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2255 {
2256 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
2257 }
2258
2259 static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2260 {
2261 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
2262 }
2263
2264 19 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2265 {
2266 19 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
2267
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!ret)
2268 19 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
2269 19 return ret;
2270 }
2271
2272 static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2273 {
2274 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
2275
2276 if (!ret && c->fc->nb_streams >= 1) {
2277 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2278 if (par->extradata_size >= 40) {
2279 par->height = AV_RB16(&par->extradata[36]);
2280 par->width = AV_RB16(&par->extradata[38]);
2281 }
2282 }
2283 return ret;
2284 }
2285
2286 16 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2287 {
2288
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (c->fc->nb_streams >= 1) {
2289 16 AVStream *const st = c->fc->streams[c->fc->nb_streams - 1];
2290 16 FFStream *const sti = ffstream(st);
2291 16 AVCodecParameters *par = st->codecpar;
2292
2293
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
2294 par->codec_id == AV_CODEC_ID_H264 &&
2295 atom.size > 11) {
2296 int cid;
2297 avio_skip(pb, 10);
2298 cid = avio_rb16(pb);
2299 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
2300 if (cid == 0xd4d || cid == 0xd4e)
2301 par->width = 1440;
2302 return 0;
2303
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
2304
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
2305
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
2306
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 atom.size >= 24) {
2307 int num, den;
2308 13 avio_skip(pb, 12);
2309 13 num = avio_rb32(pb);
2310 13 den = avio_rb32(pb);
2311
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)
2312 return 0;
2313
2/3
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
13 switch (avio_rb32(pb)) {
2314 12 case 2:
2315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (den >= INT_MAX / 2)
2316 return 0;
2317 12 den *= 2;
2318 13 case 1:
2319 13 sti->display_aspect_ratio = (AVRational){ num, den };
2320 13 default:
2321 13 return 0;
2322 }
2323 }
2324 }
2325
2326 3 return mov_read_avid(c, pb, atom);
2327 }
2328
2329 26 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2330 {
2331 26 int ret = 0;
2332 26 int length = 0;
2333 uint64_t original_size;
2334
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (c->fc->nb_streams >= 1) {
2335 26 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (par->codec_id == AV_CODEC_ID_H264)
2337 return 0;
2338
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (atom.size == 16) {
2339 26 original_size = par->extradata_size;
2340 26 ret = mov_realloc_extradata(par, atom);
2341
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!ret) {
2342 26 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
2343
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (length == atom.size) {
2344 26 const uint8_t range_value = par->extradata[original_size + 19];
2345
1/3
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
26 switch (range_value) {
2346 26 case 1:
2347 26 par->color_range = AVCOL_RANGE_MPEG;
2348 26 break;
2349 case 2:
2350 par->color_range = AVCOL_RANGE_JPEG;
2351 break;
2352 default:
2353 av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
2354 break;
2355 }
2356 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
2357 } else {
2358 /* For some reason the whole atom was not added to the extradata */
2359 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
2360 }
2361 } else {
2362 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
2363 }
2364 } else {
2365 av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
2366 }
2367 }
2368
2369 26 return ret;
2370 }
2371
2372 4 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2373 {
2374 4 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
2375 }
2376
2377 34 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2378 {
2379 AVStream *st;
2380 int ret;
2381
2382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (c->fc->nb_streams < 1)
2383 return 0;
2384 34 st = c->fc->streams[c->fc->nb_streams-1];
2385
2386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if ((uint64_t)atom.size > (1<<30))
2387 return AVERROR_INVALIDDATA;
2388
2389
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2 times.
34 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2390
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
2392 // pass all frma atom to codec, needed at least for QDMC and QDM2
2393 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2395 return ret;
2396
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 } else if (atom.size > 8) { /* to read frma, esds atoms */
2397
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) {
2398 uint64_t buffer;
2399 10 ret = ffio_ensure_seekback(pb, 8);
2400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2401 return ret;
2402 10 buffer = avio_rb64(pb);
2403 10 atom.size -= 8;
2404
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
2405
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 <= atom.size
2406
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 >= 8) {
2407 10 avio_skip(pb, -8);
2408 10 atom.size += 8;
2409 } else if (!st->codecpar->extradata_size) {
2410 #define ALAC_EXTRADATA_SIZE 36
2411 st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
2412 if (!st->codecpar->extradata)
2413 return AVERROR(ENOMEM);
2414 st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
2415 AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
2416 AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
2417 AV_WB64(st->codecpar->extradata + 12, buffer);
2418 avio_read(pb, st->codecpar->extradata + 20, 16);
2419 avio_skip(pb, atom.size - 24);
2420 return 0;
2421 }
2422 }
2423
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if ((ret = mov_read_default(c, pb, atom)) < 0)
2424 return ret;
2425 } else
2426 avio_skip(pb, atom.size);
2427 34 return 0;
2428 }
2429
2430 /**
2431 * This function reads atom content and puts data in extradata without tag
2432 * nor size unlike mov_read_extradata.
2433 */
2434 139 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2435 {
2436 AVStream *st;
2437 int ret;
2438
2439 139 st = get_curr_st(c);
2440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if (!st)
2441 return 0;
2442
2443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if ((uint64_t)atom.size > (1<<30))
2444 return AVERROR_INVALIDDATA;
2445
2446
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 138 times.
139 if (atom.type == MKTAG('v','v','c','C')) {
2447 1 avio_skip(pb, 4);
2448 1 atom.size -= 4;
2449 }
2450
2451
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 4 times.
139 if (atom.size >= 10) {
2452 // Broken files created by legacy versions of libavformat will
2453 // wrap a whole fiel atom inside of a glbl atom.
2454 135 unsigned size = avio_rb32(pb);
2455 135 unsigned type = avio_rl32(pb);
2456
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 135 times.
135 if (avio_feof(pb))
2457 return AVERROR_INVALIDDATA;
2458 135 avio_seek(pb, -8, SEEK_CUR);
2459
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 127 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
135 if (type == MKTAG('f','i','e','l') && size == atom.size)
2460 8 return mov_read_default(c, pb, atom);
2461 }
2462
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 131 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
131 if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
2463 av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
2464 return 0;
2465 }
2466 131 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 131 times.
131 if (ret < 0)
2468 return ret;
2469
3/4
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 39 times.
131 if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
2470 /* HEVC-based Dolby Vision derived from hvc1.
2471 Happens to match with an identifier
2472 previously utilized for DV. Thus, if we have
2473 the hvcC extradata box available as specified,
2474 set codec to HEVC */
2475 st->codecpar->codec_id = AV_CODEC_ID_HEVC;
2476
2477 131 return 0;
2478 }
2479
2480 2 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2481 {
2482 AVStream *st;
2483 uint8_t profile_level;
2484 int ret;
2485
2486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
2487 return 0;
2488 2 st = c->fc->streams[c->fc->nb_streams-1];
2489
2490
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)
2491 return AVERROR_INVALIDDATA;
2492
2493 2 profile_level = avio_r8(pb);
2494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((profile_level & 0xf0) != 0xc0)
2495 return 0;
2496
2497 2 avio_seek(pb, 6, SEEK_CUR);
2498 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
2499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2500 return ret;
2501
2502 2 return 0;
2503 }
2504
2505 static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2506 {
2507 AVStream* st;
2508 MOVStreamContext* sc;
2509
2510 if (c->fc->nb_streams < 1)
2511 return 0;
2512
2513 /* For SBAS this should be fine - though beware if someone implements a
2514 * tref atom processor that doesn't drop down to default then this may
2515 * be lost. */
2516 if (atom.size > 4) {
2517 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2518 return AVERROR_PATCHWELCOME;
2519 }
2520
2521 st = c->fc->streams[c->fc->nb_streams - 1];
2522 sc = st->priv_data;
2523 sc->tref_id = avio_rb32(pb);
2524 sc->tref_flags |= MOV_TREF_FLAG_ENHANCEMENT;
2525
2526 return 0;
2527 }
2528
2529 /**
2530 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2531 * but can have extradata appended at the end after the 40 bytes belonging
2532 * to the struct.
2533 */
2534 static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2535 {
2536 AVStream *st;
2537 int ret;
2538
2539 if (c->fc->nb_streams < 1)
2540 return 0;
2541 if (atom.size <= 40)
2542 return 0;
2543 st = c->fc->streams[c->fc->nb_streams-1];
2544
2545 if ((uint64_t)atom.size > (1<<30))
2546 return AVERROR_INVALIDDATA;
2547
2548 avio_skip(pb, 40);
2549 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
2550 if (ret < 0)
2551 return ret;
2552
2553 return 0;
2554 }
2555
2556 594 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2557 {
2558 AVStream *st;
2559 MOVStreamContext *sc;
2560 unsigned int i, entries;
2561
2562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->trak_index < 0) {
2563 av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
2564 return 0;
2565 }
2566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
2567 return 0;
2568 594 st = c->fc->streams[c->fc->nb_streams-1];
2569 594 sc = st->priv_data;
2570
2571 594 avio_r8(pb); /* version */
2572 594 avio_rb24(pb); /* flags */
2573
2574 // Clamp allocation size for `chunk_offsets` -- don't throw an error for an
2575 // invalid count since the EOF path doesn't throw either.
2576 594 entries = avio_rb32(pb);
2577 594 entries =
2578
2/2
✓ Branch 0 taken 589 times.
✓ Branch 1 taken 5 times.
594 FFMIN(entries,
2579 FFMAX(0, (atom.size - 8) /
2580 (atom.type == MKTAG('s', 't', 'c', 'o') ? 4 : 8)));
2581
2582
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 578 times.
594 if (!entries)
2583 16 return 0;
2584
2585
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (sc->chunk_offsets) {
2586 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2587 return 0;
2588 }
2589
2590 578 av_free(sc->chunk_offsets);
2591 578 sc->chunk_count = 0;
2592 578 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (!sc->chunk_offsets)
2594 return AVERROR(ENOMEM);
2595 578 sc->chunk_count = entries;
2596
2597
2/2
✓ Branch 0 taken 574 times.
✓ Branch 1 taken 4 times.
578 if (atom.type == MKTAG('s','t','c','o'))
2598
3/4
✓ Branch 0 taken 42907 times.
✓ Branch 1 taken 574 times.
✓ Branch 2 taken 42907 times.
✗ Branch 3 not taken.
43481 for (i = 0; i < entries && !pb->eof_reached; i++)
2599 42907 sc->chunk_offsets[i] = avio_rb32(pb);
2600
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (atom.type == MKTAG('c','o','6','4'))
2601
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++) {
2602 136336 sc->chunk_offsets[i] = avio_rb64(pb);
2603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136336 times.
136336 if (sc->chunk_offsets[i] < 0) {
2604 av_log(c->fc, AV_LOG_WARNING, "Impossible chunk_offset\n");
2605 sc->chunk_offsets[i] = 0;
2606 }
2607 }
2608 else
2609 return AVERROR_INVALIDDATA;
2610
2611 578 sc->chunk_count = i;
2612
2613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (pb->eof_reached) {
2614 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2615 return AVERROR_EOF;
2616 }
2617
2618 578 return 0;
2619 }
2620
2621 631 static int mov_codec_id(AVStream *st, uint32_t format)
2622 {
2623 631 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2624
2625
2/2
✓ Branch 0 taken 411 times.
✓ Branch 1 taken 220 times.
631 if (id <= 0 &&
2626
2/2
✓ Branch 0 taken 408 times.
✓ Branch 1 taken 3 times.
411 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 408 times.
408 (format & 0xFFFF) == 'T' + ('S' << 8)))
2628 3 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2629
2630
4/4
✓ Branch 0 taken 293 times.
✓ Branch 1 taken 338 times.
✓ Branch 2 taken 223 times.
✓ Branch 3 taken 70 times.
631 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2631 223 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2632
3/4
✓ Branch 0 taken 390 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 390 times.
✗ Branch 3 not taken.
408 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2633 /* skip old ASF MPEG-4 tag */
2634
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 4 times.
390 format && format != MKTAG('m','p','4','s')) {
2635 386 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2636
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 331 times.
386 if (id <= 0)
2637 55 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2638
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 51 times.
386 if (id > 0)
2639 335 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2640
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 47 times.
51 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2641
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2643 47 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2644
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6 times.
47 if (id <= 0) {
2645
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 2 times.
80 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2646
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 2 times.
80 AV_CODEC_ID_TTML : id;
2647 }
2648
2649
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 37 times.
47 if (id > 0)
2650 10 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2651 else
2652 37 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2653 }
2654 }
2655
2656 631 st->codecpar->codec_tag = format;
2657
2658 631 return id;
2659 }
2660
2661 312 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2662 AVStream *st, MOVStreamContext *sc)
2663 {
2664 312 uint8_t codec_name[32] = { 0 };
2665 int64_t stsd_start;
2666 unsigned int len;
2667 312 uint32_t id = 0;
2668
2669 /* The first 16 bytes of the video sample description are already
2670 * read in ff_mov_read_stsd_entries() */
2671 312 stsd_start = avio_tell(pb) - 16;
2672
2673 312 avio_rb16(pb); /* version */
2674 312 avio_rb16(pb); /* revision level */
2675 312 id = avio_rl32(pb); /* vendor */
2676 312 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2677 312 avio_rb32(pb); /* temporal quality */
2678 312 avio_rb32(pb); /* spatial quality */
2679
2680 312 st->codecpar->width = avio_rb16(pb); /* width */
2681 312 st->codecpar->height = avio_rb16(pb); /* height */
2682
2683 312 avio_rb32(pb); /* horiz resolution */
2684 312 avio_rb32(pb); /* vert resolution */
2685 312 avio_rb32(pb); /* data size, always 0 */
2686 312 avio_rb16(pb); /* frames per samples */
2687
2688 312 len = avio_r8(pb); /* codec name, pascal string */
2689
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 311 times.
312 if (len > 31)
2690 1 len = 31;
2691 312 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2692
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 3 times.
312 if (len < 31)
2693 309 avio_skip(pb, 31 - len);
2694
2695
2/2
✓ Branch 0 taken 250 times.
✓ Branch 1 taken 62 times.
312 if (codec_name[0])
2696 250 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2697
2698 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 312 times.
312 if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2700 st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2701 st->codecpar->width &= ~1;
2702 st->codecpar->height &= ~1;
2703 }
2704 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 312 times.
312 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2706 !strncmp(codec_name, "Sorenson H263", 13))
2707 st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2708
2709 312 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2710
2711 312 avio_seek(pb, stsd_start, SEEK_SET);
2712
2713
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 294 times.
312 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2714 18 st->codecpar->bits_per_coded_sample &= 0x1F;
2715 18 sc->has_palette = 1;
2716 }
2717 312 }
2718
2719 241 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2720 AVStream *st, MOVStreamContext *sc)
2721 {
2722 int bits_per_sample, flags;
2723 241 uint16_t version = avio_rb16(pb);
2724 241 uint32_t id = 0;
2725 241 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2726 int channel_count;
2727
2728 241 avio_rb16(pb); /* revision level */
2729 241 id = avio_rl32(pb); /* vendor */
2730 241 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2731
2732 241 channel_count = avio_rb16(pb);
2733
2734 241 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2735 241 st->codecpar->ch_layout.nb_channels = channel_count;
2736 241 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
2737 241 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
2738
2739 241 sc->audio_cid = avio_rb16(pb);
2740 241 avio_rb16(pb); /* packet size = 0 */
2741
2742 241 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
2743
2744 // Read QT version 1 fields. In version 0 these do not exist.
2745 241 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
2746
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 ||
2747
1/2
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
155 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
2748
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)) {
2749
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 40 times.
90 if (version == 1) {
2750 50 sc->samples_per_frame = avio_rb32(pb);
2751 50 avio_rb32(pb); /* bytes per packet */
2752 50 sc->bytes_per_frame = avio_rb32(pb);
2753 50 avio_rb32(pb); /* bytes per sample */
2754
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
40 } else if (version == 2) {
2755 4 avio_rb32(pb); /* sizeof struct only */
2756 4 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
2757 4 channel_count = avio_rb32(pb);
2758 4 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2759 4 st->codecpar->ch_layout.nb_channels = channel_count;
2760 4 avio_rb32(pb); /* always 0x7F000000 */
2761 4 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
2762
2763 4 flags = avio_rb32(pb); /* lpcm format specific flag */
2764 4 sc->bytes_per_frame = avio_rb32(pb);
2765 4 sc->samples_per_frame = avio_rb32(pb);
2766
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
2767 st->codecpar->codec_id =
2768 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
2769 flags);
2770 }
2771
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)) {
2772 /* can't correctly handle variable sized packet as audio unit */
2773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 switch (st->codecpar->codec_id) {
2774 case AV_CODEC_ID_MP2:
2775 case AV_CODEC_ID_MP3:
2776 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
2777 break;
2778 }
2779 }
2780 }
2781
2782
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (sc->format == 0) {
2783 if (st->codecpar->bits_per_coded_sample == 8)
2784 st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
2785 else if (st->codecpar->bits_per_coded_sample == 16)
2786 st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
2787 }
2788
2789
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) {
2790 7 case AV_CODEC_ID_PCM_S8:
2791 case AV_CODEC_ID_PCM_U8:
2792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
2793 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2794 7 break;
2795 19 case AV_CODEC_ID_PCM_S16LE:
2796 case AV_CODEC_ID_PCM_S16BE:
2797
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
19 if (st->codecpar->bits_per_coded_sample == 8)
2798 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
2799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 24)
2800 st->codecpar->codec_id =
2801 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2802 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
2803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 32)
2804 st->codecpar->codec_id =
2805 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2806 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
2807 19 break;
2808 /* set values for old format before stsd version 1 appeared */
2809 2 case AV_CODEC_ID_MACE3:
2810 2 sc->samples_per_frame = 6;
2811 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
2812 2 break;
2813 8 case AV_CODEC_ID_MACE6:
2814 8 sc->samples_per_frame = 6;
2815 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
2816 8 break;
2817 5 case AV_CODEC_ID_ADPCM_IMA_QT:
2818 5 sc->samples_per_frame = 64;
2819 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
2820 5 break;
2821 1 case AV_CODEC_ID_GSM:
2822 1 sc->samples_per_frame = 160;
2823 1 sc->bytes_per_frame = 33;
2824 1 break;
2825 199 default:
2826 199 break;
2827 }
2828
2829 241 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2830
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) {
2831 48 st->codecpar->bits_per_coded_sample = bits_per_sample;
2832 48 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
2833 }
2834 241 }
2835
2836 11 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
2837 AVStream *st, MOVStreamContext *sc,
2838 int64_t size)
2839 {
2840 // ttxt stsd contains display flags, justification, background
2841 // color, fonts, and default styles, so fake an atom to read it
2842 11 MOVAtom fake_atom = { .size = size };
2843 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
2844 // in extradata unlike stpp MP4 TTML.
2845
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
2846
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
2847 9 mov_read_glbl(c, pb, fake_atom);
2848 11 st->codecpar->width = sc->width;
2849 11 st->codecpar->height = sc->height;
2850 11 }
2851
2852 41 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
2853 AVStream *st, MOVStreamContext *sc,
2854 int64_t size)
2855 {
2856 int ret;
2857
2858
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 22 times.
41 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
2859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if ((int)size != size)
2860 return AVERROR(ENOMEM);
2861
2862 19 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
2863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
2864 return ret;
2865
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (size > 16) {
2866 19 MOVStreamContext *tmcd_ctx = st->priv_data;
2867 int val;
2868 19 val = AV_RB32(st->codecpar->extradata + 4);
2869 19 tmcd_ctx->tmcd_flags = val;
2870 19 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
2871 19 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
2872 19 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
2873
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (size > 30) {
2874 4 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
2875 4 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
2876
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) {
2877 4 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
2878
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 &&
2879
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 st->codecpar->extradata[30] /* Don't add empty string */) {
2880 4 char *reel_name = av_malloc(str_size + 1);
2881
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!reel_name)
2882 return AVERROR(ENOMEM);
2883 4 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
2884 4 reel_name[str_size] = 0; /* Add null terminator */
2885 4 av_dict_set(&st->metadata, "reel_name", reel_name,
2886 AV_DICT_DONT_STRDUP_VAL);
2887 }
2888 }
2889 }
2890 }
2891 } else {
2892 /* other codec type, just skip (rtp, mp4s ...) */
2893 22 avio_skip(pb, size);
2894 }
2895 41 return 0;
2896 }
2897
2898 594 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
2899 AVStream *st, MOVStreamContext *sc)
2900 {
2901 594 FFStream *const sti = ffstream(st);
2902
2903
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 353 times.
594 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
2904
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)
2905 st->codecpar->sample_rate = sc->time_scale;
2906
2907 /* special codec parameters handling */
2908
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 66 times.
✓ Branch 9 taken 475 times.
594 switch (st->codecpar->codec_id) {
2909 #if CONFIG_DV_DEMUXER
2910 case AV_CODEC_ID_DVAUDIO:
2911 if (c->dv_fctx) {
2912 avpriv_request_sample(c->fc, "multiple DV audio streams");
2913 return AVERROR(ENOSYS);
2914 }
2915
2916 c->dv_fctx = avformat_alloc_context();
2917 if (!c->dv_fctx) {
2918 av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
2919 return AVERROR(ENOMEM);
2920 }
2921 c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
2922 if (!c->dv_demux) {
2923 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
2924 return AVERROR(ENOMEM);
2925 }
2926 sc->dv_audio_container = 1;
2927 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2928 break;
2929 #endif
2930 /* no ifdef since parameters are always those */
2931 case AV_CODEC_ID_QCELP:
2932 av_channel_layout_uninit(&st->codecpar->ch_layout);
2933 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2934 // force sample rate for qcelp when not stored in mov
2935 if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
2936 st->codecpar->sample_rate = 8000;
2937 // FIXME: Why is the following needed for some files?
2938 sc->samples_per_frame = 160;
2939 if (!sc->bytes_per_frame)
2940 sc->bytes_per_frame = 35;
2941 break;
2942 case AV_CODEC_ID_AMR_NB:
2943 av_channel_layout_uninit(&st->codecpar->ch_layout);
2944 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2945 /* force sample rate for amr, stsd in 3gp does not store sample rate */
2946 st->codecpar->sample_rate = 8000;
2947 break;
2948 11 case AV_CODEC_ID_AMR_WB:
2949 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
2950 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2951 11 st->codecpar->sample_rate = 16000;
2952 11 break;
2953 1 case AV_CODEC_ID_MP2:
2954 case AV_CODEC_ID_MP3:
2955 /* force type after stsd for m1a hdlr */
2956 1 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2957 1 break;
2958 15 case AV_CODEC_ID_GSM:
2959 case AV_CODEC_ID_ADPCM_MS:
2960 case AV_CODEC_ID_ADPCM_IMA_WAV:
2961 case AV_CODEC_ID_ILBC:
2962 case AV_CODEC_ID_MACE3:
2963 case AV_CODEC_ID_MACE6:
2964 case AV_CODEC_ID_QDM2:
2965 15 st->codecpar->block_align = sc->bytes_per_frame;
2966 15 break;
2967 16 case AV_CODEC_ID_ALAC:
2968
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
2969 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
2970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
2971 av_channel_layout_uninit(&st->codecpar->ch_layout);
2972 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2973 st->codecpar->ch_layout.nb_channels = channel_count;
2974 }
2975 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
2976 }
2977 16 break;
2978 10 case AV_CODEC_ID_AC3:
2979 case AV_CODEC_ID_EAC3:
2980 case AV_CODEC_ID_MPEG1VIDEO:
2981 case AV_CODEC_ID_VC1:
2982 case AV_CODEC_ID_VP8:
2983 case AV_CODEC_ID_VP9:
2984 10 sti->need_parsing = AVSTREAM_PARSE_FULL;
2985 10 break;
2986 66 case AV_CODEC_ID_EVC:
2987 case AV_CODEC_ID_AV1:
2988 /* field_order detection of H264 requires parsing */
2989 case AV_CODEC_ID_H264:
2990 66 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
2991 66 break;
2992 475 default:
2993 475 break;
2994 }
2995 594 return 0;
2996 }
2997
2998 605 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
2999 int codec_tag, int format,
3000 int64_t size)
3001 {
3002
3/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 594 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
605 if (codec_tag &&
3003 (codec_tag != format &&
3004 // AVID 1:1 samples with differing data format and codec tag exist
3005 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
3006 // prores is allowed to have differing data format and codec tag
3007 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
3008 // so is dv (sigh)
3009 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
3010 (c->fc->video_codec_id ? ff_codec_get_id(ff_codec_movvideo_tags, format) != c->fc->video_codec_id
3011 : codec_tag != MKTAG('j','p','e','g')))) {
3012 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3013 * export it as a separate AVStream but this needs a few changes
3014 * in the MOV demuxer, patch welcome. */
3015
3016 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3017 avio_skip(pb, size);
3018 return 1;
3019 }
3020
3021 605 return 0;
3022 }
3023
3024 594 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3025 {
3026 AVStream *st;
3027 MOVStreamContext *sc;
3028 int pseudo_stream_id;
3029
3030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 av_assert0 (c->fc->nb_streams >= 1);
3031 594 st = c->fc->streams[c->fc->nb_streams-1];
3032 594 sc = st->priv_data;
3033
3034 594 for (pseudo_stream_id = 0;
3035
3/4
✓ Branch 0 taken 605 times.
✓ Branch 1 taken 594 times.
✓ Branch 2 taken 605 times.
✗ Branch 3 not taken.
1199 pseudo_stream_id < entries && !pb->eof_reached;
3036 605 pseudo_stream_id++) {
3037 //Parsing Sample description table
3038 enum AVCodecID id;
3039 605 int ret, dref_id = 1;
3040 605 MOVAtom a = { AV_RL32("stsd") };
3041 605 int64_t start_pos = avio_tell(pb);
3042 605 int64_t size = avio_rb32(pb); /* size */
3043 605 uint32_t format = avio_rl32(pb); /* data format */
3044
3045
1/2
✓ Branch 0 taken 605 times.
✗ Branch 1 not taken.
605 if (size >= 16) {
3046 605 avio_rb32(pb); /* reserved */
3047 605 avio_rb16(pb); /* reserved */
3048 605 dref_id = avio_rb16(pb);
3049 } else if (size <= 7) {
3050 av_log(c->fc, AV_LOG_ERROR,
3051 "invalid size %"PRId64" in stsd\n", size);
3052 return AVERROR_INVALIDDATA;
3053 }
3054
3055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 605 times.
605 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3056 605 size - (avio_tell(pb) - start_pos))) {
3057 sc->stsd_count++;
3058 continue;
3059 }
3060
3061
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 11 times.
605 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
3062 605 sc->dref_id= dref_id;
3063 605 sc->format = format;
3064
3065 605 id = mov_codec_id(st, format);
3066
3067 605 av_log(c->fc, AV_LOG_TRACE,
3068 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3069 605 av_fourcc2str(format), st->codecpar->codec_type);
3070
3071 605 st->codecpar->codec_id = id;
3072
2/2
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 293 times.
605 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3073 312 mov_parse_stsd_video(c, pb, st, sc);
3074
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 52 times.
293 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3075 241 mov_parse_stsd_audio(c, pb, st, sc);
3076
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (st->codecpar->sample_rate < 0) {
3077 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3078 return AVERROR_INVALIDDATA;
3079 }
3080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (st->codecpar->ch_layout.nb_channels < 0) {
3081 av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3082 return AVERROR_INVALIDDATA;
3083 }
3084
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 41 times.
52 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3085 11 mov_parse_stsd_subtitle(c, pb, st, sc,
3086 11 size - (avio_tell(pb) - start_pos));
3087 } else {
3088 41 ret = mov_parse_stsd_data(c, pb, st, sc,
3089 41 size - (avio_tell(pb) - start_pos));
3090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ret < 0)
3091 return ret;
3092 }
3093 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3094 605 a.size = size - (avio_tell(pb) - start_pos);
3095
2/2
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 128 times.
605 if (a.size > 8) {
3096
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 477 times.
477 if ((ret = mov_read_default(c, pb, a)) < 0)
3097 return ret;
3098
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 127 times.
128 } else if (a.size > 0)
3099 1 avio_skip(pb, a.size);
3100
3101
3/4
✓ Branch 0 taken 605 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 341 times.
✓ Branch 3 taken 264 times.
605 if (sc->extradata && st->codecpar->extradata) {
3102 341 int extra_size = st->codecpar->extradata_size;
3103
3104 /* Move the current stream extradata to the stream context one. */
3105 341 sc->extradata_size[pseudo_stream_id] = extra_size;
3106 341 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3107 341 st->codecpar->extradata = NULL;
3108 341 st->codecpar->extradata_size = 0;
3109 }
3110 605 sc->stsd_count++;
3111 }
3112
3113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (pb->eof_reached) {
3114 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3115 return AVERROR_EOF;
3116 }
3117
3118 594 return 0;
3119 }
3120
3121 594 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3122 {
3123 AVStream *st;
3124 MOVStreamContext *sc;
3125 int ret, entries;
3126
3127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
3128 return 0;
3129 594 st = c->fc->streams[c->fc->nb_streams - 1];
3130 594 sc = st->priv_data;
3131
3132 594 sc->stsd_version = avio_r8(pb);
3133 594 avio_rb24(pb); /* flags */
3134 594 entries = avio_rb32(pb);
3135
3136 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3137
3/6
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 594 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 594 times.
594 if (entries <= 0 || entries > atom.size / 8 || entries > 1024) {
3138 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3139 return AVERROR_INVALIDDATA;
3140 }
3141
3142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (sc->extradata) {
3143 av_log(c->fc, AV_LOG_ERROR,
3144 "Duplicate stsd found in this track.\n");
3145 return AVERROR_INVALIDDATA;
3146 }
3147
3148 /* Prepare space for hosting multiple extradata. */
3149 594 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (!sc->extradata)
3151 return AVERROR(ENOMEM);
3152
3153 594 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (!sc->extradata_size) {
3155 ret = AVERROR(ENOMEM);
3156 goto fail;
3157 }
3158
3159 594 ret = ff_mov_read_stsd_entries(c, pb, entries);
3160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (ret < 0)
3161 goto fail;
3162
3163 /* Restore back the primary extradata. */
3164 594 av_freep(&st->codecpar->extradata);
3165 594 st->codecpar->extradata_size = sc->extradata_size[0];
3166
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 263 times.
594 if (sc->extradata_size[0]) {
3167 331 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 331 times.
331 if (!st->codecpar->extradata)
3169 return AVERROR(ENOMEM);
3170 331 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3171 }
3172
3173 594 return mov_finalize_stsd_codec(c, pb, st, sc);
3174 fail:
3175 if (sc->extradata) {
3176 int j;
3177 for (j = 0; j < sc->stsd_count; j++)
3178 av_freep(&sc->extradata[j]);
3179 }
3180
3181 av_freep(&sc->extradata);
3182 av_freep(&sc->extradata_size);
3183 return ret;
3184 }
3185
3186 594 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3187 {
3188 AVStream *st;
3189 MOVStreamContext *sc;
3190 unsigned int i, entries;
3191
3192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->trak_index < 0) {
3193 av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3194 return 0;
3195 }
3196
3197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
3198 return 0;
3199 594 st = c->fc->streams[c->fc->nb_streams-1];
3200 594 sc = st->priv_data;
3201
3202 594 avio_r8(pb); /* version */
3203 594 avio_rb24(pb); /* flags */
3204
3205 594 entries = avio_rb32(pb);
3206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if ((uint64_t)entries * 12 + 4 > atom.size)
3207 return AVERROR_INVALIDDATA;
3208
3209 594 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3210
3211
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 579 times.
594 if (!entries)
3212 15 return 0;
3213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 579 times.
579 if (sc->stsc_data) {
3214 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3215 return 0;
3216 }
3217 579 av_free(sc->stsc_data);
3218 579 sc->stsc_count = 0;
3219 579 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 579 times.
579 if (!sc->stsc_data)
3221 return AVERROR(ENOMEM);
3222
3223
3/4
✓ Branch 0 taken 3779 times.
✓ Branch 1 taken 579 times.
✓ Branch 2 taken 3779 times.
✗ Branch 3 not taken.
4358 for (i = 0; i < entries && !pb->eof_reached; i++) {
3224 3779 sc->stsc_data[i].first = avio_rb32(pb);
3225 3779 sc->stsc_data[i].count = avio_rb32(pb);
3226 3779 sc->stsc_data[i].id = avio_rb32(pb);
3227 }
3228
3229 579 sc->stsc_count = i;
3230
2/2
✓ Branch 0 taken 3779 times.
✓ Branch 1 taken 579 times.
4358 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3231 3779 int64_t first_min = i + 1;
3232
5/6
✓ Branch 0 taken 3200 times.
✓ Branch 1 taken 579 times.
✓ Branch 2 taken 3200 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3200 times.
✓ Branch 5 taken 579 times.
3779 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
3233
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) ||
3234
1/2
✓ Branch 0 taken 3779 times.
✗ Branch 1 not taken.
3779 sc->stsc_data[i].first < first_min ||
3235
1/2
✓ Branch 0 taken 3779 times.
✗ Branch 1 not taken.
3779 sc->stsc_data[i].count < 1 ||
3236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3779 times.
3779 sc->stsc_data[i].id < 1) {
3237 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);
3238 if (i+1 >= sc->stsc_count) {
3239 if (sc->stsc_data[i].count == 0 && i > 0) {
3240 sc->stsc_count --;
3241 continue;
3242 }
3243 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3244 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3245 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3246 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3247 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3248 continue;
3249 }
3250 av_assert0(sc->stsc_data[i+1].first >= 2);
3251 // We replace this entry by the next valid
3252 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3253 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3254 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3255 }
3256 }
3257
3258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 579 times.
579 if (pb->eof_reached) {
3259 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3260 return AVERROR_EOF;
3261 }
3262
3263 579 return 0;
3264 }
3265
3266 340661 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3267 {
3268 340661 return index < count - 1;
3269 }
3270
3271 /* Compute the samples value for the stsc entry at the given index. */
3272 55529 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3273 {
3274 int chunk_count;
3275
3276
2/2
✓ Branch 1 taken 55333 times.
✓ Branch 2 taken 196 times.
55529 if (mov_stsc_index_valid(index, sc->stsc_count))
3277 55333 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3278 else {
3279 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3281 196 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3282 }
3283
3284 55529 return sc->stsc_data[index].count * (int64_t)chunk_count;
3285 }
3286
3287 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3288 {
3289 AVStream *st;
3290 MOVStreamContext *sc;
3291 unsigned i, entries;
3292
3293 if (c->trak_index < 0) {
3294 av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3295 return 0;
3296 }
3297
3298 if (c->fc->nb_streams < 1)
3299 return 0;
3300 st = c->fc->streams[c->fc->nb_streams-1];
3301 sc = st->priv_data;
3302
3303 avio_rb32(pb); // version + flags
3304
3305 entries = avio_rb32(pb);
3306 if (sc->stps_data)
3307 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3308 av_free(sc->stps_data);
3309 sc->stps_count = 0;
3310 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3311 if (!sc->stps_data)
3312 return AVERROR(ENOMEM);
3313
3314 for (i = 0; i < entries && !pb->eof_reached; i++) {
3315 sc->stps_data[i] = avio_rb32(pb);
3316 }
3317
3318 sc->stps_count = i;
3319
3320 if (pb->eof_reached) {
3321 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3322 return AVERROR_EOF;
3323 }
3324
3325 return 0;
3326 }
3327
3328 144 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3329 {
3330 AVStream *st;
3331 FFStream *sti;
3332 MOVStreamContext *sc;
3333 unsigned int i, entries;
3334
3335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (c->trak_index < 0) {
3336 av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3337 return 0;
3338 }
3339
3340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (c->fc->nb_streams < 1)
3341 return 0;
3342 144 st = c->fc->streams[c->fc->nb_streams-1];
3343 144 sti = ffstream(st);
3344 144 sc = st->priv_data;
3345
3346 144 avio_r8(pb); /* version */
3347 144 avio_rb24(pb); /* flags */
3348
3349 144 entries = avio_rb32(pb);
3350
3351 144 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3352
3353
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 138 times.
144 if (!entries) {
3354 6 sc->keyframe_absent = 1;
3355
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)
3356 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3357 6 return 0;
3358 }
3359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (sc->keyframes)
3360 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (entries >= UINT_MAX / sizeof(int))
3362 return AVERROR_INVALIDDATA;
3363 138 av_freep(&sc->keyframes);
3364 138 sc->keyframe_count = 0;
3365 138 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (!sc->keyframes)
3367 return AVERROR(ENOMEM);
3368
3369
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++) {
3370 5706 sc->keyframes[i] = avio_rb32(pb);
3371 }
3372
3373 138 sc->keyframe_count = i;
3374
3375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (pb->eof_reached) {
3376 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3377 return AVERROR_EOF;
3378 }
3379
3380 138 return 0;
3381 }
3382
3383 594 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3384 {
3385 AVStream *st;
3386 MOVStreamContext *sc;
3387 unsigned int i, entries, sample_size, field_size, num_bytes;
3388 GetBitContext gb;
3389 unsigned char* buf;
3390 int ret;
3391
3392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->trak_index < 0) {
3393 av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3394 return 0;
3395 }
3396
3397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
3398 return 0;
3399 594 st = c->fc->streams[c->fc->nb_streams-1];
3400 594 sc = st->priv_data;
3401
3402 594 avio_r8(pb); /* version */
3403 594 avio_rb24(pb); /* flags */
3404
3405
1/2
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
594 if (atom.type == MKTAG('s','t','s','z')) {
3406 594 sample_size = avio_rb32(pb);
3407
2/2
✓ Branch 0 taken 553 times.
✓ Branch 1 taken 41 times.
594 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3408 553 sc->sample_size = sample_size;
3409 594 sc->stsz_sample_size = sample_size;
3410 594 field_size = 32;
3411 } else {
3412 sample_size = 0;
3413 avio_rb24(pb); /* reserved */
3414 field_size = avio_r8(pb);
3415 }
3416 594 entries = avio_rb32(pb);
3417
3418 594 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3419
3420 594 sc->sample_count = entries;
3421
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 396 times.
594 if (sample_size)
3422 198 return 0;
3423
3424
4/8
✓ Branch 0 taken 396 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 396 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 396 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 396 times.
396 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
3425 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3426 return AVERROR_INVALIDDATA;
3427 }
3428
3429
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 380 times.
396 if (!entries)
3430 16 return 0;
3431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (entries >= (INT_MAX - 4 - 8 * AV_INPUT_BUFFER_PADDING_SIZE) / field_size)
3432 return AVERROR_INVALIDDATA;
3433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (sc->sample_sizes)
3434 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3435 380 av_free(sc->sample_sizes);
3436 380 sc->sample_count = 0;
3437 380 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (!sc->sample_sizes)
3439 return AVERROR(ENOMEM);
3440
3441 380 num_bytes = (entries*field_size+4)>>3;
3442
3443 380 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (!buf) {
3445 av_freep(&sc->sample_sizes);
3446 return AVERROR(ENOMEM);
3447 }
3448
3449 380 ret = ffio_read_size(pb, buf, num_bytes);
3450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (ret < 0) {
3451 av_freep(&sc->sample_sizes);
3452 av_free(buf);
3453 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3454 return 0;
3455 }
3456
3457 380 init_get_bits(&gb, buf, 8*num_bytes);
3458
3459
2/2
✓ Branch 0 taken 226883 times.
✓ Branch 1 taken 380 times.
227263 for (i = 0; i < entries; i++) {
3460 226883 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 226883 times.
226883 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3462 av_free(buf);
3463 av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3464 return AVERROR_INVALIDDATA;
3465 }
3466 226883 sc->data_size += sc->sample_sizes[i];
3467 }
3468
3469 380 sc->sample_count = i;
3470
3471 380 av_free(buf);
3472
3473 380 return 0;
3474 }
3475
3476 594 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3477 {
3478 AVStream *st;
3479 MOVStreamContext *sc;
3480 unsigned int i, entries;
3481 594 int64_t duration = 0;
3482 594 int64_t total_sample_count = 0;
3483 594 int64_t current_dts = 0;
3484 594 int64_t corrected_dts = 0;
3485
3486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->trak_index < 0) {
3487 av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3488 return 0;
3489 }
3490
3491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
3492 return 0;
3493 594 st = c->fc->streams[c->fc->nb_streams-1];
3494 594 sc = st->priv_data;
3495
3496 594 avio_r8(pb); /* version */
3497 594 avio_rb24(pb); /* flags */
3498 594 entries = avio_rb32(pb);
3499
3500 594 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3501 594 c->fc->nb_streams-1, entries);
3502
3503
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (sc->stts_data)
3504 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3505 594 av_freep(&sc->stts_data);
3506 594 sc->stts_count = 0;
3507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3508 return AVERROR(ENOMEM);
3509
3510
3/4
✓ Branch 0 taken 2941 times.
✓ Branch 1 taken 594 times.
✓ Branch 2 taken 2941 times.
✗ Branch 3 not taken.
3535 for (i = 0; i < entries && !pb->eof_reached; i++) {
3511 unsigned int sample_duration;
3512 unsigned int sample_count;
3513 2941 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3514 2941 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3515 min_entries * sizeof(*sc->stts_data));
3516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2941 times.
2941 if (!stts_data) {
3517 av_freep(&sc->stts_data);
3518 sc->stts_count = 0;
3519 return AVERROR(ENOMEM);
3520 }
3521 2941 sc->stts_count = min_entries;
3522 2941 sc->stts_data = stts_data;
3523
3524 2941 sample_count = avio_rb32(pb);
3525 2941 sample_duration = avio_rb32(pb);
3526
3527 2941 sc->stts_data[i].count= sample_count;
3528 2941 sc->stts_data[i].duration= sample_duration;
3529
3530 2941 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3531 sample_count, sample_duration);
3532
3533 /* STTS sample offsets are uint32 but some files store it as int32
3534 * with negative values used to correct DTS delays.
3535 There may be abnormally large values as well. */
3536
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2940 times.
2941 if (sample_duration > c->max_stts_delta) {
3537 // assume high delta is a correction if negative when cast as int32
3538 1 int32_t delta_magnitude = (int32_t)sample_duration;
3539 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",
3540 sample_duration, i, sample_count, st->index);
3541 1 sc->stts_data[i].duration = 1;
3542
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);
3543 } else {
3544 2940 corrected_dts += sample_duration * (uint64_t)sample_count;
3545 }
3546
3547 2941 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3548
3549
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2919 times.
2941 if (current_dts > corrected_dts) {
3550 22 int64_t drift = av_sat_sub64(current_dts, corrected_dts) / FFMAX(sample_count, 1);
3551
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;
3552 22 current_dts -= correction * (uint64_t)sample_count;
3553 22 sc->stts_data[i].duration -= correction;
3554 }
3555
3556 2941 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3557 2941 total_sample_count+=sc->stts_data[i].count;
3558 }
3559
3560 594 sc->stts_count = i;
3561
3562
2/2
✓ Branch 0 taken 578 times.
✓ Branch 1 taken 16 times.
594 if (duration > 0 &&
3563
1/2
✓ Branch 0 taken 578 times.
✗ Branch 1 not taken.
578 duration <= INT64_MAX - sc->duration_for_fps &&
3564
1/2
✓ Branch 0 taken 578 times.
✗ Branch 1 not taken.
578 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3565 578 sc->duration_for_fps += duration;
3566 578 sc->nb_frames_for_fps += total_sample_count;
3567 }
3568
3569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (pb->eof_reached) {
3570 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3571 return AVERROR_EOF;
3572 }
3573
3574 594 st->nb_frames= total_sample_count;
3575
2/2
✓ Branch 0 taken 578 times.
✓ Branch 1 taken 16 times.
594 if (duration)
3576 578 st->duration= FFMIN(st->duration, duration);
3577
3578 // All samples have zero duration. They have higher chance be chose by
3579 // mov_find_next_sample, which leads to seek again and again.
3580 //
3581 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3582 // So only mark data stream as discarded for safety.
3583
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 578 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
594 if (!duration && sc->stts_count &&
3584 st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3585 av_log(c->fc, AV_LOG_WARNING,
3586 "All samples in data stream index:id [%d:%d] have zero "
3587 "duration, stream set to be discarded by default. Override "
3588 "using AVStream->discard or -discard for ffmpeg command.\n",
3589 st->index, sc->id);
3590 st->discard = AVDISCARD_ALL;
3591 }
3592 594 sc->track_end = duration;
3593 594 return 0;
3594 }
3595
3596 44 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3597 {
3598 AVStream *st;
3599 MOVStreamContext *sc;
3600 int64_t i, entries;
3601
3602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (c->fc->nb_streams < 1)
3603 return 0;
3604 44 st = c->fc->streams[c->fc->nb_streams - 1];
3605 44 sc = st->priv_data;
3606
3607 44 avio_r8(pb); /* version */
3608 44 avio_rb24(pb); /* flags */
3609 44 entries = atom.size - 4;
3610
3611 44 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3612 44 c->fc->nb_streams - 1, entries);
3613
3614
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 36 times.
44 if (sc->sdtp_data)
3615 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3616 44 av_freep(&sc->sdtp_data);
3617 44 sc->sdtp_count = 0;
3618
3619 44 sc->sdtp_data = av_malloc(entries);
3620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (!sc->sdtp_data)
3621 return AVERROR(ENOMEM);
3622
3623
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++)
3624 3807 sc->sdtp_data[i] = avio_r8(pb);
3625 44 sc->sdtp_count = i;
3626
3627 44 return 0;
3628 }
3629
3630 10827 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3631 {
3632
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 9691 times.
10827 if (duration < 0) {
3633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3634 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3635 duration++;
3636 }
3637 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3638 }
3639 10827 }
3640
3641 63 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3642 {
3643 AVStream *st;
3644 MOVStreamContext *sc;
3645 63 unsigned int i, entries, ctts_count = 0;
3646
3647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->trak_index < 0) {
3648 av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
3649 return 0;
3650 }
3651
3652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->fc->nb_streams < 1)
3653 return 0;
3654 63 st = c->fc->streams[c->fc->nb_streams-1];
3655 63 sc = st->priv_data;
3656
3657 63 avio_r8(pb); /* version */
3658 63 avio_rb24(pb); /* flags */
3659 63 entries = avio_rb32(pb);
3660
3661 63 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3662
3663
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 59 times.
63 if (!entries)
3664 4 return 0;
3665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
3666 return AVERROR_INVALIDDATA;
3667 59 av_freep(&sc->ctts_data);
3668 59 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
3669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->ctts_data)
3670 return AVERROR(ENOMEM);
3671
3672
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++) {
3673 MOVCtts *ctts_data;
3674 4874 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
3675 4874 const size_t requested_size =
3676 4874 min_size_needed > sc->ctts_allocated_size ?
3677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
3678 min_size_needed;
3679 4874 int count = avio_rb32(pb);
3680 4874 int duration = avio_rb32(pb);
3681
3682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (count <= 0) {
3683 av_log(c->fc, AV_LOG_TRACE,
3684 "ignoring CTTS entry with count=%d duration=%d\n",
3685 count, duration);
3686 continue;
3687 }
3688
3689
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
3690 return AVERROR(ENOMEM);
3691
3692 4874 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
3693
3694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (!ctts_data)
3695 return AVERROR(ENOMEM);
3696
3697 4874 sc->ctts_data = ctts_data;
3698
3699 4874 ctts_data[ctts_count].count = count;
3700 4874 ctts_data[ctts_count].offset = duration;
3701 4874 ctts_count++;
3702
3703 4874 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
3704 count, duration);
3705
3706
2/2
✓ Branch 0 taken 4761 times.
✓ Branch 1 taken 113 times.
4874 if (i+2<entries)
3707 4761 mov_update_dts_shift(sc, duration, c->fc);
3708 }
3709
3710 59 sc->ctts_count = ctts_count;
3711
3712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (pb->eof_reached) {
3713 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
3714 return AVERROR_EOF;
3715 }
3716
3717 59 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
3718
3719 59 return 0;
3720 }
3721
3722 28 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3723 {
3724 AVStream *st;
3725 MOVStreamContext *sc;
3726 uint8_t version;
3727 uint32_t grouping_type;
3728 uint32_t default_length;
3729 av_unused uint32_t default_group_description_index;
3730 uint32_t entry_count;
3731
3732
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (c->fc->nb_streams < 1)
3733 return 0;
3734 28 st = c->fc->streams[c->fc->nb_streams - 1];
3735 28 sc = st->priv_data;
3736
3737 28 version = avio_r8(pb); /* version */
3738 28 avio_rb24(pb); /* flags */
3739 28 grouping_type = avio_rl32(pb);
3740
3741 /*
3742 * This function only supports "sync" boxes, but the code is able to parse
3743 * other boxes (such as "tscl", "tsas" and "stsa")
3744 */
3745
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 5 times.
28 if (grouping_type != MKTAG('s','y','n','c'))
3746 23 return 0;
3747
3748
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
3749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
3750 5 entry_count = avio_rb32(pb);
3751
3752 5 av_freep(&sc->sgpd_sync);
3753 5 sc->sgpd_sync_count = entry_count;
3754 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
3755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
3756 return AVERROR(ENOMEM);
3757
3758
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++) {
3759 8 uint32_t description_length = default_length;
3760
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)
3761 description_length = avio_rb32(pb);
3762
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
3763 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
3764 8 sc->sgpd_sync[i] = nal_unit_type;
3765 8 description_length -= 1;
3766 }
3767 8 avio_skip(pb, description_length);
3768 }
3769
3770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
3771 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
3772 return AVERROR_EOF;
3773 }
3774
3775 5 return 0;
3776 }
3777
3778 25 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3779 {
3780 AVStream *st;
3781 MOVStreamContext *sc;
3782 unsigned int i, entries;
3783 uint8_t version;
3784 uint32_t grouping_type;
3785 MOVSbgp *table, **tablep;
3786 int *table_count;
3787
3788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (c->fc->nb_streams < 1)
3789 return 0;
3790 25 st = c->fc->streams[c->fc->nb_streams-1];
3791 25 sc = st->priv_data;
3792
3793 25 version = avio_r8(pb); /* version */
3794 25 avio_rb24(pb); /* flags */
3795 25 grouping_type = avio_rl32(pb);
3796
3797
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 24 times.
25 if (grouping_type == MKTAG('r','a','p',' ')) {
3798 1 tablep = &sc->rap_group;
3799 1 table_count = &sc->rap_group_count;
3800
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19 times.
24 } else if (grouping_type == MKTAG('s','y','n','c')) {
3801 5 tablep = &sc->sync_group;
3802 5 table_count = &sc->sync_group_count;
3803 } else {
3804 19 return 0;
3805 }
3806
3807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
3808 avio_rb32(pb); /* grouping_type_parameter */
3809
3810 6 entries = avio_rb32(pb);
3811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
3812 return 0;
3813
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
3814 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
3815 6 av_freep(tablep);
3816 6 table = av_malloc_array(entries, sizeof(*table));
3817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
3818 return AVERROR(ENOMEM);
3819 6 *tablep = table;
3820
3821
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++) {
3822 32 table[i].count = avio_rb32(pb); /* sample_count */
3823 32 table[i].index = avio_rb32(pb); /* group_description_index */
3824 }
3825
3826 6 *table_count = i;
3827
3828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
3829 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
3830 return AVERROR_EOF;
3831 }
3832
3833 6 return 0;
3834 }
3835
3836 /**
3837 * Get ith edit list entry (media time, duration).
3838 */
3839 901 static int get_edit_list_entry(MOVContext *mov,
3840 const MOVStreamContext *msc,
3841 unsigned int edit_list_index,
3842 int64_t *edit_list_media_time,
3843 int64_t *edit_list_duration,
3844 int64_t global_timescale)
3845 {
3846
2/2
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 464 times.
901 if (edit_list_index == msc->elst_count) {
3847 437 return 0;
3848 }
3849 464 *edit_list_media_time = msc->elst_data[edit_list_index].time;
3850 464 *edit_list_duration = msc->elst_data[edit_list_index].duration;
3851
3852 /* duration is in global timescale units;convert to msc timescale */
3853
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 464 times.
464 if (global_timescale == 0) {
3854 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
3855 return 0;
3856 }
3857 464 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
3858 global_timescale);
3859
3860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 464 times.
464 if (*edit_list_duration + (uint64_t)*edit_list_media_time > INT64_MAX)
3861 *edit_list_duration = 0;
3862
3863 464 return 1;
3864 }
3865
3866 /**
3867 * Find the closest previous frame to the timestamp_pts, in e_old index
3868 * entries. Searching for just any frame / just key frames can be controlled by
3869 * last argument 'flag'.
3870 * Note that if ctts_data is not NULL, we will always search for a key frame
3871 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
3872 * return the first frame of the video.
3873 *
3874 * Here the timestamp_pts is considered to be a presentation timestamp and
3875 * the timestamp of index entries are considered to be decoding timestamps.
3876 *
3877 * Returns 0 if successful in finding a frame, else returns -1.
3878 * Places the found index corresponding output arg.
3879 *
3880 * If ctts_old is not NULL, then refines the searched entry by searching
3881 * backwards from the found timestamp, to find the frame with correct PTS.
3882 *
3883 * Places the found ctts_index and ctts_sample in corresponding output args.
3884 */
3885 463 static int find_prev_closest_index(AVStream *st,
3886 AVIndexEntry *e_old,
3887 int nb_old,
3888 MOVTimeToSample *tts_data,
3889 int64_t tts_count,
3890 int64_t timestamp_pts,
3891 int flag,
3892 int64_t* index,
3893 int64_t* tts_index,
3894 int64_t* tts_sample)
3895 {
3896 463 MOVStreamContext *msc = st->priv_data;
3897 463 FFStream *const sti = ffstream(st);
3898 463 AVIndexEntry *e_keep = sti->index_entries;
3899 463 int nb_keep = sti->nb_index_entries;
3900 463 int64_t i = 0;
3901
3902
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 463 times.
463 av_assert0(index);
3903
3904 // If dts_shift > 0, then all the index timestamps will have to be offset by
3905 // at least dts_shift amount to obtain PTS.
3906 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
3907
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 454 times.
463 if (msc->dts_shift > 0) {
3908 9 timestamp_pts -= msc->dts_shift;
3909 }
3910
3911 463 sti->index_entries = e_old;
3912 463 sti->nb_index_entries = nb_old;
3913 463 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
3914
3915 // Keep going backwards in the index entries until the timestamp is the same.
3916
2/2
✓ Branch 0 taken 462 times.
✓ Branch 1 taken 1 times.
463 if (*index >= 0) {
3917
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 438 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
462 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
3918 i--) {
3919 if ((flag & AVSEEK_FLAG_ANY) ||
3920 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
3921 *index = i - 1;
3922 }
3923 }
3924 }
3925
3926 // If we have CTTS then refine the search, by searching backwards over PTS
3927 // computed by adding corresponding CTTS durations to index timestamps.
3928
4/4
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 399 times.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 1 times.
463 if (msc->ctts_count && *index >= 0) {
3929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(tts_index);
3930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(tts_sample);
3931 // Find out the ctts_index for the found frame.
3932 63 *tts_index = 0;
3933 63 *tts_sample = 0;
3934
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++) {
3935
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (*tts_index < tts_count) {
3936 175 (*tts_sample)++;
3937
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (tts_data[*tts_index].count == *tts_sample) {
3938 175 (*tts_index)++;
3939 175 *tts_sample = 0;
3940 }
3941 }
3942 }
3943
3944
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) {
3945 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
3946 // No need to add dts_shift to the timestamp here becase timestamp_pts has already been
3947 // compensated by dts_shift above.
3948
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 &&
3949
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 4 times.
62 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
3950 58 break;
3951 }
3952
3953 12 (*index)--;
3954
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (*tts_sample == 0) {
3955 12 (*tts_index)--;
3956
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 if (*tts_index >= 0)
3957 7 *tts_sample = tts_data[*tts_index].count - 1;
3958 } else {
3959 (*tts_sample)--;
3960 }
3961 }
3962 }
3963
3964 /* restore AVStream state*/
3965 463 sti->index_entries = e_keep;
3966 463 sti->nb_index_entries = nb_keep;
3967
2/2
✓ Branch 0 taken 457 times.
✓ Branch 1 taken 6 times.
463 return *index >= 0 ? 0 : -1;
3968 }
3969
3970 /**
3971 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
3972 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
3973 *
3974 * This function is similar to ff_add_index_entry in libavformat/utils.c
3975 * except that here we are always unconditionally adding an index entry to
3976 * the end, instead of searching the entries list and skipping the add if
3977 * there is an existing entry with the same timestamp.
3978 * This is needed because the mov_fix_index calls this func with the same
3979 * unincremented timestamp for successive discarded frames.
3980 */
3981 348547 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
3982 int size, int distance, int flags)
3983 {
3984 348547 FFStream *const sti = ffstream(st);
3985 AVIndexEntry *entries, *ie;
3986 348547 int64_t index = -1;
3987 348547 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
3988
3989 // Double the allocation each time, to lower memory fragmentation.
3990 // Another difference from ff_add_index_entry function.
3991 348547 const size_t requested_size =
3992 348547 min_size_needed > sti->index_entries_allocated_size ?
3993
2/2
✓ Branch 0 taken 1973 times.
✓ Branch 1 taken 346574 times.
348547 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
3994 min_size_needed;
3995
3996
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348547 times.
348547 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
3997 return -1;
3998
3999 348547 entries = av_fast_realloc(sti->index_entries,
4000 &sti->index_entries_allocated_size,
4001 requested_size);
4002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348547 times.
348547 if (!entries)
4003 return -1;
4004
4005 348547 sti->index_entries = entries;
4006
4007 348547 index = sti->nb_index_entries++;
4008 348547 ie= &entries[index];
4009
4010 348547 ie->pos = pos;
4011 348547 ie->timestamp = timestamp;
4012 348547 ie->min_distance= distance;
4013 348547 ie->size= size;
4014 348547 ie->flags = flags;
4015 348547 return index;
4016 }
4017
4018 /**
4019 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4020 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4021 */
4022 27 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4023 int64_t* frame_duration_buffer,
4024 int frame_duration_buffer_size) {
4025 27 FFStream *const sti = ffstream(st);
4026 27 int i = 0;
4027
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);
4028
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 27 times.
164 for (i = 0; i < frame_duration_buffer_size; i++) {
4029 137 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4030 137 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4031 }
4032 27 }
4033
4034 186048 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4035 int count, int offset, unsigned int duration)
4036 {
4037 MOVTimeToSample *tts_buf_new;
4038 186048 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4039 186048 const size_t requested_size =
4040 186048 min_size_needed > *allocated_size ?
4041
2/2
✓ Branch 0 taken 1341 times.
✓ Branch 1 taken 184707 times.
186048 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4042 min_size_needed;
4043
4044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186048 times.
186048 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4045 return -1;
4046
4047 186048 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4048
4049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186048 times.
186048 if (!tts_buf_new)
4050 return -1;
4051
4052 186048 *tts_data = tts_buf_new;
4053
4054 186048 tts_buf_new[*tts_count].count = count;
4055 186048 tts_buf_new[*tts_count].offset = offset;
4056 186048 tts_buf_new[*tts_count].duration = duration;
4057
4058 186048 *tts_count = (*tts_count) + 1;
4059 186048 return 0;
4060 }
4061
4062 #define MAX_REORDER_DELAY 16
4063 601 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4064 {
4065 601 MOVStreamContext *msc = st->priv_data;
4066 601 FFStream *const sti = ffstream(st);
4067 601 int ctts_ind = 0;
4068 601 int ctts_sample = 0;
4069 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4070 601 int buf_start = 0;
4071 int j, r, num_swaps;
4072
4073
2/2
✓ Branch 0 taken 10217 times.
✓ Branch 1 taken 601 times.
10818 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4074 10217 pts_buf[j] = INT64_MIN;
4075
4076
3/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 542 times.
601 if (st->codecpar->video_delay <= 0 && msc->ctts_count &&
4077
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 16 times.
59 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4078 43 st->codecpar->video_delay = 0;
4079
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) {
4080 // Point j to the last elem of the buffer and insert the current pts there.
4081 138279 j = buf_start;
4082 138279 buf_start = (buf_start + 1);
4083
2/2
✓ Branch 0 taken 8111 times.
✓ Branch 1 taken 130168 times.
138279 if (buf_start == MAX_REORDER_DELAY + 1)
4084 8111 buf_start = 0;
4085
4086 138279 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4087
4088 // The timestamps that are already in the sorted buffer, and are greater than the
4089 // current pts, are exactly the timestamps that need to be buffered to output PTS
4090 // in correct sorted order.
4091 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4092 // can be computed as the maximum no. of swaps any particular timestamp needs to
4093 // go through, to keep this buffer in sorted order.
4094 138279 num_swaps = 0;
4095
2/2
✓ Branch 0 taken 142294 times.
✓ Branch 1 taken 4 times.
142298 while (j != buf_start) {
4096 142294 r = j - 1;
4097
2/2
✓ Branch 0 taken 8389 times.
✓ Branch 1 taken 133905 times.
142294 if (r < 0) r = MAX_REORDER_DELAY;
4098
2/2
✓ Branch 0 taken 4019 times.
✓ Branch 1 taken 138275 times.
142294 if (pts_buf[j] < pts_buf[r]) {
4099 4019 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4100 4019 ++num_swaps;
4101 } else {
4102 138275 break;
4103 }
4104 4019 j = r;
4105 }
4106 138279 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4107
4108 138279 ctts_sample++;
4109
1/2
✓ Branch 0 taken 138279 times.
✗ Branch 1 not taken.
138279 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4110 138279 ctts_ind++;
4111 138279 ctts_sample = 0;
4112 }
4113 }
4114 43 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4115 43 st->codecpar->video_delay, st->index);
4116 }
4117 601 }
4118
4119 103400 static void mov_current_sample_inc(MOVStreamContext *sc)
4120 {
4121 103400 sc->current_sample++;
4122 103400 sc->current_index++;
4123
2/2
✓ Branch 0 taken 61402 times.
✓ Branch 1 taken 41998 times.
103400 if (sc->index_ranges &&
4124
2/2
✓ Branch 0 taken 422 times.
✓ Branch 1 taken 60980 times.
61402 sc->current_index >= sc->current_index_range->end &&
4125
1/2
✓ Branch 0 taken 422 times.
✗ Branch 1 not taken.
422 sc->current_index_range->end) {
4126 422 sc->current_index_range++;
4127 422 sc->current_index = sc->current_index_range->start;
4128 }
4129 103400 }
4130
4131 static void mov_current_sample_dec(MOVStreamContext *sc)
4132 {
4133 sc->current_sample--;
4134 sc->current_index--;
4135 if (sc->index_ranges &&
4136 sc->current_index < sc->current_index_range->start &&
4137 sc->current_index_range > sc->index_ranges) {
4138 sc->current_index_range--;
4139 sc->current_index = sc->current_index_range->end - 1;
4140 }
4141 }
4142
4143 335 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4144 {
4145 int64_t range_size;
4146
4147 335 sc->current_sample = current_sample;
4148 335 sc->current_index = current_sample;
4149
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 309 times.
335 if (!sc->index_ranges) {
4150 26 return;
4151 }
4152
4153 309 for (sc->current_index_range = sc->index_ranges;
4154
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 sc->current_index_range->end;
4155 sc->current_index_range++) {
4156 309 range_size = sc->current_index_range->end - sc->current_index_range->start;
4157
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 if (range_size > current_sample) {
4158 309 sc->current_index = sc->current_index_range->start + current_sample;
4159 309 break;
4160 }
4161 current_sample -= range_size;
4162 }
4163 }
4164
4165 /**
4166 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4167 * which are needed to decode them) that fall in the edit list time ranges.
4168 * Also fixes the timestamps of the index entries to match the timeline
4169 * specified the edit lists.
4170 */
4171 601 static void mov_fix_index(MOVContext *mov, AVStream *st)
4172 {
4173 601 MOVStreamContext *msc = st->priv_data;
4174 601 FFStream *const sti = ffstream(st);
4175 601 AVIndexEntry *e_old = sti->index_entries;
4176 601 int nb_old = sti->nb_index_entries;
4177 601 const AVIndexEntry *e_old_end = e_old + nb_old;
4178 601 const AVIndexEntry *current = NULL;
4179 601 MOVTimeToSample *tts_data_old = msc->tts_data;
4180 601 int64_t tts_index_old = 0;
4181 601 int64_t tts_sample_old = 0;
4182 601 int64_t tts_count_old = msc->tts_count;
4183 601 int64_t edit_list_media_time = 0;
4184 601 int64_t edit_list_duration = 0;
4185 601 int64_t frame_duration = 0;
4186 601 int64_t edit_list_dts_counter = 0;
4187 601 int64_t edit_list_dts_entry_end = 0;
4188 601 int64_t edit_list_start_tts_sample = 0;
4189 int64_t curr_cts;
4190 601 int64_t curr_ctts = 0;
4191 601 int64_t empty_edits_sum_duration = 0;
4192 601 int64_t edit_list_index = 0;
4193 int64_t index;
4194 int flags;
4195 601 int64_t start_dts = 0;
4196 601 int64_t edit_list_start_encountered = 0;
4197 601 int64_t search_timestamp = 0;
4198 601 int64_t* frame_duration_buffer = NULL;
4199 601 int num_discarded_begin = 0;
4200 601 int first_non_zero_audio_edit = -1;
4201 601 int packet_skip_samples = 0;
4202 601 MOVIndexRange *current_index_range = NULL;
4203 601 int found_keyframe_after_edit = 0;
4204 601 int found_non_empty_edit = 0;
4205
4206
4/6
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 164 times.
✓ Branch 2 taken 437 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 437 times.
601 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
4207 164 return;
4208 }
4209
4210 // allocate the index ranges array
4211 437 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4212 sizeof(msc->index_ranges[0]));
4213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 437 times.
437 if (!msc->index_ranges) {
4214 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4215 return;
4216 }
4217 437 msc->current_index_range = msc->index_ranges;
4218
4219 // Clean AVStream from traces of old index
4220 437 sti->index_entries = NULL;
4221 437 sti->index_entries_allocated_size = 0;
4222 437 sti->nb_index_entries = 0;
4223
4224 // Clean time to sample fields of MOVStreamContext
4225 437 msc->tts_data = NULL;
4226 437 msc->tts_count = 0;
4227 437 msc->tts_index = 0;
4228 437 msc->tts_sample = 0;
4229 437 msc->tts_allocated_size = 0;
4230
4231 // Reinitialize min_corrected_pts so that it can be computed again.
4232 437 msc->min_corrected_pts = -1;
4233
4234 // If the dts_shift is positive (in case of negative ctts values in mov),
4235 // then negate the DTS by dts_shift
4236
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 428 times.
437 if (msc->dts_shift > 0) {
4237 9 edit_list_dts_entry_end -= msc->dts_shift;
4238 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4239 }
4240
4241 437 start_dts = edit_list_dts_entry_end;
4242
4243
2/2
✓ Branch 0 taken 464 times.
✓ Branch 1 taken 437 times.
1338 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
4244 901 &edit_list_duration, mov->time_scale)) {
4245 464 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4246 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4247 464 edit_list_index++;
4248 464 edit_list_dts_counter = edit_list_dts_entry_end;
4249 464 edit_list_dts_entry_end += edit_list_duration;
4250 464 num_discarded_begin = 0;
4251
4/4
✓ Branch 0 taken 441 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 437 times.
464 if (!found_non_empty_edit && edit_list_media_time == -1) {
4252 4 empty_edits_sum_duration += edit_list_duration;
4253 4 continue;
4254 }
4255 460 found_non_empty_edit = 1;
4256
4257 // If we encounter a non-negative edit list reset the skip_samples/start_pad fields and set them
4258 // according to the edit list below.
4259
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 333 times.
460 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4260
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit < 0) {
4261 127 first_non_zero_audio_edit = 1;
4262 } else {
4263 first_non_zero_audio_edit = 0;
4264 }
4265
4266
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit > 0)
4267 127 sti->skip_samples = msc->start_pad = 0;
4268 }
4269
4270 // While reordering frame index according to edit list we must handle properly
4271 // the scenario when edit list entry starts from none key frame.
4272 // We find closest previous key frame and preserve it and consequent frames in index.
4273 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4274 460 search_timestamp = edit_list_media_time;
4275
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 333 times.
460 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4276 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4277 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4278 // edit_list_media_time to cover the decoder delay.
4279 127 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
4280 }
4281
4282
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 457 times.
460 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, 0,
4283 &index, &tts_index_old, &tts_sample_old) < 0) {
4284 3 av_log(mov->fc, AV_LOG_WARNING,
4285 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4286 st->index, edit_list_index, search_timestamp);
4287
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,
4288 &index, &tts_index_old, &tts_sample_old) < 0) {
4289 3 av_log(mov->fc, AV_LOG_WARNING,
4290 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4291 st->index, edit_list_index, search_timestamp);
4292 3 index = 0;
4293 3 tts_index_old = 0;
4294 3 tts_sample_old = 0;
4295 }
4296 }
4297 460 current = e_old + index;
4298 460 edit_list_start_tts_sample = tts_sample_old;
4299
4300 // Iterate over index and arrange it according to edit list
4301 460 edit_list_start_encountered = 0;
4302 460 found_keyframe_after_edit = 0;
4303
2/2
✓ Branch 0 taken 348547 times.
✓ Branch 1 taken 112 times.
348659 for (; current < e_old_end; current++, index++) {
4304 // check if frame outside edit list mark it for discard
4305 697094 frame_duration = (current + 1 < e_old_end) ?
4306
2/2
✓ Branch 0 taken 348114 times.
✓ Branch 1 taken 433 times.
348547 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4307
4308 348547 flags = current->flags;
4309
4310 // frames (pts) before or after edit list
4311 348547 curr_cts = current->timestamp + msc->dts_shift;
4312 348547 curr_ctts = 0;
4313
4314
4/4
✓ Branch 0 taken 186060 times.
✓ Branch 1 taken 162487 times.
✓ Branch 2 taken 186048 times.
✓ Branch 3 taken 12 times.
348547 if (tts_data_old && tts_index_old < tts_count_old) {
4315 186048 curr_ctts = tts_data_old[tts_index_old].offset;
4316 186048 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4317 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4318 186048 curr_cts += curr_ctts;
4319 186048 tts_sample_old++;
4320
1/2
✓ Branch 0 taken 186048 times.
✗ Branch 1 not taken.
186048 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186048 times.
186048 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4322 &msc->tts_allocated_size,
4323 186048 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4324 186048 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4325 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4326 tts_index_old,
4327 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4328 tts_data_old[tts_index_old].offset);
4329 break;
4330 }
4331 186048 tts_index_old++;
4332 186048 tts_sample_old = 0;
4333 186048 edit_list_start_tts_sample = 0;
4334 }
4335 }
4336
4337
4/4
✓ Branch 0 taken 348395 times.
✓ Branch 1 taken 152 times.
✓ Branch 2 taken 130 times.
✓ Branch 3 taken 348265 times.
348547 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
4338
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 &&
4339
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 &&
4340 first_non_zero_audio_edit > 0) {
4341 11 packet_skip_samples = edit_list_media_time - curr_cts;
4342 11 sti->skip_samples += packet_skip_samples;
4343
4344 // Shift the index entry timestamp by packet_skip_samples to be correct.
4345 11 edit_list_dts_counter -= packet_skip_samples;
4346
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (edit_list_start_encountered == 0) {
4347 11 edit_list_start_encountered = 1;
4348 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4349 // discarded packets.
4350
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 if (frame_duration_buffer) {
4351 6 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4352 frame_duration_buffer, num_discarded_begin);
4353 6 av_freep(&frame_duration_buffer);
4354 }
4355 }
4356
4357 11 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4358 } else {
4359 271 flags |= AVINDEX_DISCARD_FRAME;
4360 271 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4361
4362
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 132 times.
271 if (edit_list_start_encountered == 0) {
4363 139 num_discarded_begin++;
4364 139 frame_duration_buffer = av_realloc(frame_duration_buffer,
4365 num_discarded_begin * sizeof(int64_t));
4366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if (!frame_duration_buffer) {
4367 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4368 break;
4369 }
4370 139 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4371
4372 // Increment skip_samples for the first non-zero audio edit list
4373
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 &&
4374
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) {
4375 20 sti->skip_samples += frame_duration;
4376 }
4377 }
4378 }
4379 } else {
4380
2/2
✓ Branch 0 taken 436 times.
✓ Branch 1 taken 347829 times.
348265 if (msc->min_corrected_pts < 0) {
4381 436 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4382 } else {
4383 347829 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4384 }
4385
2/2
✓ Branch 0 taken 447 times.
✓ Branch 1 taken 347818 times.
348265 if (edit_list_start_encountered == 0) {
4386 447 edit_list_start_encountered = 1;
4387 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4388 // discarded packets.
4389
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 426 times.
447 if (frame_duration_buffer) {
4390 21 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4391 frame_duration_buffer, num_discarded_begin);
4392 21 av_freep(&frame_duration_buffer);
4393 }
4394 }
4395 }
4396
4397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348547 times.
348547 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
4398 348547 current->min_distance, flags) == -1) {
4399 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4400 break;
4401 }
4402
4403 // Update the index ranges array
4404
4/4
✓ Branch 0 taken 348110 times.
✓ Branch 1 taken 437 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 348089 times.
348547 if (!current_index_range || index != current_index_range->end) {
4405 458 current_index_range = current_index_range ? current_index_range + 1
4406
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 437 times.
458 : msc->index_ranges;
4407 458 current_index_range->start = index;
4408 }
4409 348547 current_index_range->end = index + 1;
4410
4411 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4412
2/2
✓ Branch 0 taken 348408 times.
✓ Branch 1 taken 139 times.
348547 if (edit_list_start_encountered > 0) {
4413 348408 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4414 }
4415
4416 // Break when found first key frame after edit entry completion
4417
2/2
✓ Branch 0 taken 616 times.
✓ Branch 1 taken 347931 times.
348547 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
4418
3/4
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 256 times.
616 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
4419
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 339 times.
360 if (msc->ctts_count) {
4420 // If we have CTTS and this is the first keyframe after edit elist,
4421 // wait for one more, because there might be trailing B-frames after this I-frame
4422 // that do belong to the edit.
4423
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) {
4424 12 found_keyframe_after_edit = 1;
4425 12 continue;
4426 }
4427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (tts_sample_old != 0) {
4428 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4429 &msc->tts_allocated_size,
4430 tts_sample_old - edit_list_start_tts_sample,
4431 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4432 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4433 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4434 tts_data_old[tts_index_old].offset);
4435 break;
4436 }
4437 }
4438 }
4439 348 break;
4440 }
4441 }
4442 }
4443 // If there are empty edits, then msc->min_corrected_pts might be positive
4444 // intentionally. So we subtract the sum duration of emtpy edits here.
4445 437 msc->min_corrected_pts -= empty_edits_sum_duration;
4446
4447 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4448 // dts by that amount to make the first pts zero.
4449
2/2
✓ Branch 0 taken 268 times.
✓ Branch 1 taken 169 times.
437 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4450
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 227 times.
268 if (msc->min_corrected_pts > 0) {
4451 41 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4452
2/2
✓ Branch 0 taken 2829 times.
✓ Branch 1 taken 41 times.
2870 for (int i = 0; i < sti->nb_index_entries; ++i)
4453 2829 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4454 }
4455 }
4456 // Start time should be equal to zero or the duration of any empty edits.
4457 437 st->start_time = empty_edits_sum_duration;
4458
4459 // Update av stream length, if it ends up shorter than the track's media duration
4460 437 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4461 437 msc->start_pad = sti->skip_samples;
4462
4463 // Free the old index and the old CTTS structures
4464 437 av_free(e_old);
4465 437 av_free(tts_data_old);
4466 437 av_freep(&frame_duration_buffer);
4467
4468 // Null terminate the index ranges array
4469 437 current_index_range = current_index_range ? current_index_range + 1
4470
1/2
✓ Branch 0 taken 437 times.
✗ Branch 1 not taken.
437 : msc->index_ranges;
4471 437 current_index_range->start = 0;
4472 437 current_index_range->end = 0;
4473 437 msc->current_index = msc->index_ranges[0].start;
4474 }
4475
4476 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4477 {
4478
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4479
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == HEVC_NAL_CRA_NUT)
4480 5 return i + 1;
4481 return 0;
4482 }
4483
4484 617 static int build_open_gop_key_points(AVStream *st)
4485 {
4486 int k;
4487 617 int sample_id = 0;
4488 uint32_t cra_index;
4489 617 MOVStreamContext *sc = st->priv_data;
4490
4491
4/4
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 580 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 5 times.
617 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count)
4492 612 return 0;
4493
4494 /* Build an unrolled index of the samples */
4495 5 sc->sample_offsets_count = 0;
4496
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4498 return AVERROR(ENOMEM);
4499 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4500 }
4501 5 av_freep(&sc->sample_offsets);
4502 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4503
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4504 return AVERROR(ENOMEM);
4505 5 k = 0;
4506
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4507
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4508 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4509
4510 /* The following HEVC NAL type reveal the use of open GOP sync points
4511 * (TODO: BLA types may also be concerned) */
4512 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4514 return 0;
4515
4516 /* Build a list of open-GOP key samples */
4517 5 sc->open_key_samples_count = 0;
4518
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4519
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4520
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)
4521 return AVERROR(ENOMEM);
4522 11 sc->open_key_samples_count += sc->sync_group[i].count;
4523 }
4524 5 av_freep(&sc->open_key_samples);
4525 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4527 return AVERROR(ENOMEM);
4528 5 k = 0;
4529
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4530 28 const MOVSbgp *sg = &sc->sync_group[i];
4531
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4532
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4533 11 sc->open_key_samples[k++] = sample_id;
4534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4535 return AVERROR_PATCHWELCOME;
4536 28 sample_id += sg->count;
4537 }
4538
4539 /* Identify the minimal time step between samples */
4540 5 sc->min_sample_duration = UINT_MAX;
4541
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4542 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4543
4544 5 return 0;
4545 }
4546
4547 #define MOV_MERGE_CTTS 1
4548 #define MOV_MERGE_STTS 2
4549 /*
4550 * Merge stts and ctts arrays into a new combined array.
4551 * stts_count and ctts_count may be left untouched as they will be
4552 * used to check for the presence of either of them.
4553 */
4554 601 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4555 {
4556 601 MOVStreamContext *sc = st->priv_data;
4557
3/4
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 542 times.
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
601 int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS);
4558
3/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 535 times.
✓ Branch 3 taken 66 times.
601 int stts = sc->stts_data && (flags & MOV_MERGE_STTS);
4559 601 int idx = 0;
4560
4561
3/4
✓ Branch 0 taken 542 times.
✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 542 times.
601 if (!sc->ctts_data && !sc->stts_data)
4562 return 0;
4563 // Expand time to sample entries such that we have a 1-1 mapping with samples
4564
2/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 601 times.
601 if (!sc->sample_count || sc->sample_count >= UINT_MAX / sizeof(*sc->tts_data))
4565 return -1;
4566
4567
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 542 times.
601 if (ctts) {
4568 118 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4569 59 sc->sample_count * sizeof(*sc->tts_data));
4570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->tts_data)
4571 return -1;
4572
4573 59 memset(sc->tts_data, 0, sc->tts_allocated_size);
4574
4575
2/2
✓ Branch 0 taken 4874 times.
✓ Branch 1 taken 59 times.
4933 for (int i = 0; i < sc->ctts_count &&
4576
1/2
✓ Branch 0 taken 4874 times.
✗ Branch 1 not taken.
9748 idx < sc->sample_count; i++)
4577
2/2
✓ Branch 0 taken 139017 times.
✓ Branch 1 taken 4874 times.
143891 for (int j = 0; j < sc->ctts_data[i].count &&
4578
1/2
✓ Branch 0 taken 139017 times.
✗ Branch 1 not taken.
139017 idx < sc->sample_count; j++) {
4579 139017 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4580 139017 sc->tts_data[idx++].count = 1;
4581 }
4582
4583 59 sc->tts_count = idx;
4584 } else
4585 542 sc->ctts_count = 0;
4586 601 av_freep(&sc->ctts_data);
4587 601 sc->ctts_allocated_size = 0;
4588
4589 601 idx = 0;
4590
2/2
✓ Branch 0 taken 535 times.
✓ Branch 1 taken 66 times.
601 if (stts) {
4591 535 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4592 535 sc->sample_count * sizeof(*sc->tts_data));
4593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
535 if (!tts_data)
4594 return -1;
4595
4596
2/2
✓ Branch 0 taken 476 times.
✓ Branch 1 taken 59 times.
535 if (!sc->tts_data)
4597 476 memset(tts_data, 0, sc->tts_allocated_size);
4598 535 sc->tts_data = tts_data;
4599
4600
2/2
✓ Branch 0 taken 2898 times.
✓ Branch 1 taken 535 times.
3433 for (int i = 0; i < sc->stts_count &&
4601
1/2
✓ Branch 0 taken 2898 times.
✗ Branch 1 not taken.
5796 idx < sc->sample_count; i++)
4602
2/2
✓ Branch 0 taken 235892 times.
✓ Branch 1 taken 2898 times.
238790 for (int j = 0; j < sc->stts_data[i].count &&
4603
1/2
✓ Branch 0 taken 235892 times.
✗ Branch 1 not taken.
235892 idx < sc->sample_count; j++) {
4604 235892 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4605 235892 sc->tts_data[idx++].count = 1;
4606 }
4607
4608 535 sc->tts_count = FFMAX(sc->tts_count, idx);
4609 } else
4610 66 sc->stts_count = 0;
4611 601 av_freep(&sc->stts_data);
4612 601 sc->stts_allocated_size = 0;
4613
4614 601 return 0;
4615 }
4616
4617 617 static void mov_build_index(MOVContext *mov, AVStream *st)
4618 {
4619 617 MOVStreamContext *sc = st->priv_data;
4620 617 FFStream *const sti = ffstream(st);
4621 int64_t current_offset;
4622 617 int64_t current_dts = 0;
4623 617 unsigned int stts_index = 0;
4624 617 unsigned int stsc_index = 0;
4625 617 unsigned int stss_index = 0;
4626 617 unsigned int stps_index = 0;
4627 unsigned int i, j;
4628 617 uint64_t stream_size = 0;
4629
4630 617 int ret = build_open_gop_key_points(st);
4631
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 617 times.
617 if (ret < 0)
4632 return;
4633
4634
2/2
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 178 times.
617 if (sc->elst_count) {
4635 439 int i, edit_start_index = 0, multiple_edits = 0;
4636 439 int64_t empty_duration = 0; // empty duration of the first edit list entry
4637 439 int64_t start_time = 0; // start time of the media
4638
4639
2/2
✓ Branch 0 taken 466 times.
✓ Branch 1 taken 439 times.
905 for (i = 0; i < sc->elst_count; i++) {
4640 466 const MOVElst *e = &sc->elst_data[i];
4641
4/4
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 435 times.
466 if (i == 0 && e->time == -1) {
4642 /* if empty, the first entry is the start time of the stream
4643 * relative to the presentation itself */
4644 4 empty_duration = e->duration;
4645 4 edit_start_index = 1;
4646
3/4
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 439 times.
✗ Branch 3 not taken.
462 } else if (i == edit_start_index && e->time >= 0) {
4647 439 start_time = e->time;
4648 } else {
4649 23 multiple_edits = 1;
4650 }
4651 }
4652
4653
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 433 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
439 if (multiple_edits && !mov->advanced_editlist) {
4654 if (mov->advanced_editlist_autodisabled)
4655 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4656 "not supported in fragmented MP4 files\n");
4657 else
4658 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4659 "Use -advanced_editlist to correctly decode otherwise "
4660 "a/v desync might occur\n");
4661 }
4662
4663 /* adjust first dts according to edit list */
4664
5/6
✓ Branch 0 taken 435 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 366 times.
✓ Branch 4 taken 73 times.
✗ Branch 5 not taken.
439 if ((empty_duration || start_time) && mov->time_scale > 0) {
4665
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 69 times.
73 if (empty_duration)
4666 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
4667
4668
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)
4669 av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
4670
4671 73 sc->time_offset = start_time - (uint64_t)empty_duration;
4672 73 sc->min_corrected_pts = start_time;
4673
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 72 times.
73 if (!mov->advanced_editlist)
4674 1 current_dts = -sc->time_offset;
4675 }
4676
4677
4/4
✓ Branch 0 taken 433 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 431 times.
439 if (!multiple_edits && !mov->advanced_editlist &&
4678
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)
4679 sc->start_pad = start_time;
4680 }
4681
4682 /* only use old uncompressed audio chunk demuxing when stts specifies it */
4683
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 376 times.
617 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4684
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.
776 sc->stts_count == 1 && sc->stts_data && sc->stts_data[0].duration == 1)) {
4685 551 unsigned int current_sample = 0;
4686 551 unsigned int stts_sample = 0;
4687 unsigned int sample_size;
4688 551 unsigned int distance = 0;
4689 551 unsigned int rap_group_index = 0;
4690 551 unsigned int rap_group_sample = 0;
4691
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 550 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
551 int rap_group_present = sc->rap_group_count && sc->rap_group;
4692
4/8
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 413 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 138 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 413 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
551 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
4693
4694 551 current_dts -= sc->dts_shift;
4695
4696
4/6
✓ Branch 0 taken 535 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 535 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 535 times.
551 if (!sc->sample_count || sti->nb_index_entries || sc->tts_count)
4697 16 return;
4698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
535 if (sc->sample_count >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4699 return;
4700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
535 if (av_reallocp_array(&sti->index_entries,
4701 535 sti->nb_index_entries + sc->sample_count,
4702 sizeof(*sti->index_entries)) < 0) {
4703 sti->nb_index_entries = 0;
4704 return;
4705 }
4706 535 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
4707
4708 535 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
4709
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
535 if (ret < 0)
4710 return;
4711
4712
2/2
✓ Branch 0 taken 173838 times.
✓ Branch 1 taken 535 times.
174373 for (i = 0; i < sc->chunk_count; i++) {
4713
2/2
✓ Branch 0 taken 173303 times.
✓ Branch 1 taken 535 times.
173838 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
4714 173838 current_offset = sc->chunk_offsets[i];
4715
2/2
✓ Branch 1 taken 8859 times.
✓ Branch 2 taken 167522 times.
176381 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4716
2/2
✓ Branch 0 taken 2543 times.
✓ Branch 1 taken 6316 times.
8859 i + 1 == sc->stsc_data[stsc_index + 1].first)
4717 2543 stsc_index++;
4718
4719
4/6
✓ Branch 0 taken 173838 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7346 times.
✓ Branch 3 taken 166492 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7346 times.
173838 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
4720 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
4721 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
4722 sc->stsz_sample_size = sc->sample_size;
4723 }
4724
3/4
✓ Branch 0 taken 7346 times.
✓ Branch 1 taken 166492 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7346 times.
173838 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
4725 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
4726 sc->stsz_sample_size = sc->sample_size;
4727 }
4728
4729
2/2
✓ Branch 0 taken 235892 times.
✓ Branch 1 taken 173838 times.
409730 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
4730 235892 int keyframe = 0;
4731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235892 times.
235892 if (current_sample >= sc->sample_count) {
4732 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
4733 return;
4734 }
4735
4736
6/6
✓ Branch 0 taken 231136 times.
✓ Branch 1 taken 4756 times.
✓ Branch 2 taken 152644 times.
✓ Branch 3 taken 78492 times.
✓ Branch 4 taken 5706 times.
✓ Branch 5 taken 146938 times.
235892 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
4737 84198 keyframe = 1;
4738
2/2
✓ Branch 0 taken 5568 times.
✓ Branch 1 taken 78630 times.
84198 if (stss_index + 1 < sc->keyframe_count)
4739 5568 stss_index++;
4740
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]) {
4741 keyframe = 1;
4742 if (stps_index + 1 < sc->stps_count)
4743 stps_index++;
4744 }
4745
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 235704 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
235892 if (rap_group_present && rap_group_index < sc->rap_group_count) {
4746
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
4747 2 keyframe = 1;
4748
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
4749 4 rap_group_sample = 0;
4750 4 rap_group_index++;
4751 }
4752 }
4753
2/2
✓ Branch 0 taken 4756 times.
✓ Branch 1 taken 231136 times.
235892 if (sc->keyframe_absent
4754
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !sc->stps_count
4755
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !rap_group_present
4756
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)))
4757 3884 keyframe = 1;
4758
2/2
✓ Branch 0 taken 88082 times.
✓ Branch 1 taken 147810 times.
235892 if (keyframe)
4759 88082 distance = 0;
4760
2/2
✓ Branch 0 taken 8986 times.
✓ Branch 1 taken 226906 times.
235892 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
4761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235892 times.
235892 if (current_offset > INT64_MAX - sample_size) {
4762 av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
4763 current_offset,
4764 sample_size);
4765 return;
4766 }
4767
4768
2/2
✓ Branch 0 taken 235811 times.
✓ Branch 1 taken 81 times.
235892 if (sc->pseudo_stream_id == -1 ||
4769
1/2
✓ Branch 0 taken 235811 times.
✗ Branch 1 not taken.
235811 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
4770 AVIndexEntry *e;
4771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235892 times.
235892 if (sample_size > 0x3FFFFFFF) {
4772 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
4773 return;
4774 }
4775 235892 e = &sti->index_entries[sti->nb_index_entries++];
4776 235892 e->pos = current_offset;
4777 235892 e->timestamp = current_dts;
4778 235892 e->size = sample_size;
4779 235892 e->min_distance = distance;
4780 235892 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
4781 235892 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
4782 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
4783 current_offset, current_dts, sample_size, distance, keyframe);
4784
4/4
✓ Branch 0 taken 154992 times.
✓ Branch 1 taken 80900 times.
✓ Branch 2 taken 10359 times.
✓ Branch 3 taken 144633 times.
235892 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries < 100)
4785 10359 ff_rfps_add_frame(mov->fc, st, current_dts);
4786 }
4787
4788 235892 current_offset += sample_size;
4789 235892 stream_size += sample_size;
4790
4791 235892 current_dts += sc->tts_data[stts_index].duration;
4792
4793 235892 distance++;
4794 235892 stts_sample++;
4795 235892 current_sample++;
4796
3/4
✓ Branch 0 taken 235357 times.
✓ Branch 1 taken 535 times.
✓ Branch 2 taken 235357 times.
✗ Branch 3 not taken.
235892 if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) {
4797 235357 stts_sample = 0;
4798 235357 stts_index++;
4799 }
4800 }
4801 }
4802
2/2
✓ Branch 0 taken 512 times.
✓ Branch 1 taken 23 times.
535 if (st->duration > 0)
4803 512 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
4804 } else {
4805 66 unsigned chunk_samples, total = 0;
4806
4807
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)
4808 return;
4809
4810 66 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
4811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
4812 return;
4813
4814 // compute total chunk count
4815
2/2
✓ Branch 0 taken 723 times.
✓ Branch 1 taken 66 times.
789 for (i = 0; i < sc->stsc_count; i++) {
4816 unsigned count, chunk_count;
4817
4818 723 chunk_samples = sc->stsc_data[i].count;
4819
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 66 times.
723 if (i != sc->stsc_count - 1 &&
4820
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) {
4821 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
4822 return;
4823 }
4824
4825
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 648 times.
723 if (sc->samples_per_frame >= 160) { // gsm
4826 75 count = chunk_samples / sc->samples_per_frame;
4827
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 117 times.
648 } else if (sc->samples_per_frame > 1) {
4828 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
4829 531 count = (chunk_samples+samples-1) / samples;
4830 } else {
4831 117 count = (chunk_samples+1023) / 1024;
4832 }
4833
4834
2/2
✓ Branch 1 taken 657 times.
✓ Branch 2 taken 66 times.
723 if (mov_stsc_index_valid(i, sc->stsc_count))
4835 657 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
4836 else
4837 66 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
4838 723 total += chunk_count * count;
4839 }
4840
4841 66 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
4842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4843 return;
4844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (av_reallocp_array(&sti->index_entries,
4845 66 sti->nb_index_entries + total,
4846 sizeof(*sti->index_entries)) < 0) {
4847 sti->nb_index_entries = 0;
4848 return;
4849 }
4850 66 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
4851
4852 // populate index
4853
2/2
✓ Branch 0 taken 5428 times.
✓ Branch 1 taken 66 times.
5494 for (i = 0; i < sc->chunk_count; i++) {
4854 5428 current_offset = sc->chunk_offsets[i];
4855
2/2
✓ Branch 1 taken 5287 times.
✓ Branch 2 taken 141 times.
5428 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4856
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 4630 times.
5287 i + 1 == sc->stsc_data[stsc_index + 1].first)
4857 657 stsc_index++;
4858 5428 chunk_samples = sc->stsc_data[stsc_index].count;
4859
4860
2/2
✓ Branch 0 taken 162532 times.
✓ Branch 1 taken 5428 times.
167960 while (chunk_samples > 0) {
4861 AVIndexEntry *e;
4862 unsigned size, samples;
4863
4864
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) {
4865 avpriv_request_sample(mov->fc,
4866 "Zero bytes per frame, but %d samples per frame",
4867 sc->samples_per_frame);
4868 return;
4869 }
4870
4871
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 148174 times.
162532 if (sc->samples_per_frame >= 160) { // gsm
4872 14358 samples = sc->samples_per_frame;
4873 14358 size = sc->bytes_per_frame;
4874 } else {
4875
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 138611 times.
148174 if (sc->samples_per_frame > 1) {
4876 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
4877 sc->samples_per_frame, chunk_samples);
4878 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
4879 } else {
4880 138611 samples = FFMIN(1024, chunk_samples);
4881 138611 size = samples * sc->sample_size;
4882 }
4883 }
4884
4885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (sti->nb_index_entries >= total) {
4886 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
4887 return;
4888 }
4889
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (size > 0x3FFFFFFF) {
4890 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
4891 return;
4892 }
4893 162532 e = &sti->index_entries[sti->nb_index_entries++];
4894 162532 e->pos = current_offset;
4895 162532 e->timestamp = current_dts;
4896 162532 e->size = size;
4897 162532 e->min_distance = 0;
4898 162532 e->flags = AVINDEX_KEYFRAME;
4899 162532 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
4900 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
4901 size, samples);
4902
4903 162532 current_offset += size;
4904 162532 current_dts += samples;
4905 162532 chunk_samples -= samples;
4906 }
4907 }
4908 }
4909
4910
2/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
601 if (!mov->ignore_editlist && mov->advanced_editlist) {
4911 // Fix index according to edit lists.
4912 601 mov_fix_index(mov, st);
4913 }
4914
4915 // Update start time of the stream.
4916
5/6
✓ Branch 0 taken 164 times.
✓ Branch 1 taken 437 times.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 117 times.
✓ Branch 4 taken 47 times.
✗ Branch 5 not taken.
601 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) {
4917 47 st->start_time = sti->index_entries[0].timestamp + sc->dts_shift;
4918
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 if (sc->tts_data) {
4919 47 st->start_time += sc->tts_data[0].offset;
4920 }
4921 }
4922
4923 601 mov_estimate_video_delay(mov, st);
4924 }
4925
4926 static int test_same_origin(const char *src, const char *ref) {
4927 char src_proto[64];
4928 char ref_proto[64];
4929 char src_auth[256];
4930 char ref_auth[256];
4931 char src_host[256];
4932 char ref_host[256];
4933 int src_port=-1;
4934 int ref_port=-1;
4935
4936 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
4937 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
4938
4939 if (strlen(src) == 0) {
4940 return -1;
4941 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
4942 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
4943 strlen(src_host) + 1 >= sizeof(src_host) ||
4944 strlen(ref_host) + 1 >= sizeof(ref_host)) {
4945 return 0;
4946 } else if (strcmp(src_proto, ref_proto) ||
4947 strcmp(src_auth, ref_auth) ||
4948 strcmp(src_host, ref_host) ||
4949 src_port != ref_port) {
4950 return 0;
4951 } else
4952 return 1;
4953 }
4954
4955 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
4956 {
4957 /* try relative path, we do not try the absolute because it can leak information about our
4958 system to an attacker */
4959 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
4960 char filename[1025];
4961 const char *src_path;
4962 int i, l;
4963
4964 /* find a source dir */
4965 src_path = strrchr(src, '/');
4966 if (src_path)
4967 src_path++;
4968 else
4969 src_path = src;
4970
4971 /* find a next level down to target */
4972 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
4973 if (ref->path[l] == '/') {
4974 if (i == ref->nlvl_to - 1)
4975 break;
4976 else
4977 i++;
4978 }
4979
4980 /* compose filename if next level down to target was found */
4981 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
4982 memcpy(filename, src, src_path - src);
4983 filename[src_path - src] = 0;
4984
4985 for (i = 1; i < ref->nlvl_from; i++)
4986 av_strlcat(filename, "../", sizeof(filename));
4987
4988 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
4989 if (!c->use_absolute_path) {
4990 int same_origin = test_same_origin(src, filename);
4991
4992 if (!same_origin) {
4993 av_log(c->fc, AV_LOG_ERROR,
4994 "Reference with mismatching origin, %s not tried for security reasons, "
4995 "set demuxer option use_absolute_path to allow it anyway\n",
4996 ref->path);
4997 return AVERROR(ENOENT);
4998 }
4999
5000 if (strstr(ref->path + l + 1, "..") ||
5001 strstr(ref->path + l + 1, ":") ||
5002 (ref->nlvl_from > 1 && same_origin < 0) ||
5003 (filename[0] == '/' && src_path == src))
5004 return AVERROR(ENOENT);
5005 }
5006
5007 if (strlen(filename) + 1 == sizeof(filename))
5008 return AVERROR(ENOENT);
5009 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5010 return 0;
5011 }
5012 } else if (c->use_absolute_path) {
5013 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5014 "this is a possible security issue\n");
5015 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5016 return 0;
5017 } else {
5018 av_log(c->fc, AV_LOG_ERROR,
5019 "Absolute path %s not tried for security reasons, "
5020 "set demuxer option use_absolute_path to allow absolute paths\n",
5021 ref->path);
5022 }
5023
5024 return AVERROR(ENOENT);
5025 }
5026
5027 1265 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5028 {
5029
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1251 times.
1265 if (sc->time_scale <= 0) {
5030 14 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5031 14 sc->time_scale = c->time_scale;
5032
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (sc->time_scale <= 0)
5033 sc->time_scale = 1;
5034 }
5035 1265 }
5036
5037 #if CONFIG_IAMFDEC
5038 10 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5039 {
5040 10 const MOVStreamContext *sc = st->priv_data;
5041 10 const IAMFContext *iamf = &sc->iamf->iamf;
5042
5043
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5044 10 const AVStreamGroup *stg = NULL;
5045
5046
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5047
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)
5048 10 stg = c->fc->stream_groups[j];
5049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 av_assert0(stg);
5050
5051
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int j = 0; j < stg->nb_streams; j++) {
5052 50 const FFStream *sti = cffstream(st);
5053 50 AVStream *out = stg->streams[j];
5054 50 FFStream *out_sti = ffstream(stg->streams[j]);
5055
5056 50 out->codecpar->bit_rate = 0;
5057
5058
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 40 times.
50 if (out == st)
5059 10 continue;
5060
5061 40 out->time_base = st->time_base;
5062 40 out->start_time = st->start_time;
5063 40 out->duration = st->duration;
5064 40 out->nb_frames = st->nb_frames;
5065 40 out->discard = st->discard;
5066
5067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 av_assert0(!out_sti->index_entries);
5068 40 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (!out_sti->index_entries)
5070 return AVERROR(ENOMEM);
5071
5072 40 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5073 40 out_sti->nb_index_entries = sti->nb_index_entries;
5074 40 out_sti->skip_samples = sti->skip_samples;
5075 40 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5076 }
5077 }
5078
5079 10 return 0;
5080 }
5081 #endif
5082
5083 617 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5084 {
5085
4/6
✓ Branch 0 taken 601 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 601 times.
✗ Branch 5 not taken.
617 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5086
3/4
✓ Branch 0 taken 403 times.
✓ Branch 1 taken 198 times.
✓ Branch 2 taken 403 times.
✗ Branch 3 not taken.
601 (!sc->sample_size && !sc->sample_count))) ||
5087
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 601 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
617 (!sc->chunk_count && sc->sample_count)) {
5088 av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5089 index);
5090 return 1;
5091 }
5092
5093
3/4
✓ Branch 0 taken 601 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 601 times.
617 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
5094 av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5095 index);
5096 return 2;
5097 }
5098 617 return 0;
5099 }
5100
5101 594 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5102 {
5103 AVStream *st;
5104 MOVStreamContext *sc;
5105 int ret;
5106
5107 594 st = avformat_new_stream(c->fc, NULL);
5108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (!st) return AVERROR(ENOMEM);
5109 594 st->id = -1;
5110 594 sc = av_mallocz(sizeof(MOVStreamContext));
5111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (!sc) return AVERROR(ENOMEM);
5112
5113 594 st->priv_data = sc;
5114 594 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5115 594 sc->ffindex = st->index;
5116 594 c->trak_index = st->index;
5117 594 sc->tref_flags = 0;
5118 594 sc->tref_id = -1;
5119 594 sc->refcount = 1;
5120
5121
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 594 times.
594 if ((ret = mov_read_default(c, pb, atom)) < 0)
5122 return ret;
5123
5124 594 c->trak_index = -1;
5125
5126 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5127 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5128
5/6
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 578 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 15 times.
594 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
5129 1 sc->stsc_count = 0;
5130 1 av_freep(&sc->stsc_data);
5131 }
5132
5133 594 ret = sanity_checks(c->fc, sc, st->index);
5134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (ret)
5135 return ret > 1 ? AVERROR_INVALIDDATA : 0;
5136
5137 594 fix_timescale(c, sc);
5138
5139 594 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5140
5141 /*
5142 * Advanced edit list support does not work with fragemented MP4s, which
5143 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5144 * In these files, trun atoms may be streamed in.
5145 */
5146
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 578 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 4 times.
594 if (!sc->stts_count && c->advanced_editlist) {
5147
5148 12 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5149 "MP4. disabling.\n");
5150 12 c->advanced_editlist = 0;
5151 12 c->advanced_editlist_autodisabled = 1;
5152 }
5153
5154 594 mov_build_index(c, st);
5155
5156 #if CONFIG_IAMFDEC
5157
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 584 times.
594 if (sc->iamf) {
5158 10 ret = mov_update_iamf_streams(c, st);
5159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
5160 return ret;
5161 }
5162 #endif
5163
5164
3/4
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 593 times.
594 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
5165 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5166 if (c->enable_drefs) {
5167 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5168 av_log(c->fc, AV_LOG_ERROR,
5169 "stream %d, error opening alias: path='%s', dir='%s', "
5170 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5171 st->index, dref->path, dref->dir, dref->filename,
5172 dref->volume, dref->nlvl_from, dref->nlvl_to);
5173 } else {
5174 av_log(c->fc, AV_LOG_WARNING,
5175 "Skipped opening external track: "
5176 "stream %d, alias: path='%s', dir='%s', "
5177 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5178 "Set enable_drefs to allow this.\n",
5179 st->index, dref->path, dref->dir, dref->filename,
5180 dref->volume, dref->nlvl_from, dref->nlvl_to);
5181 }
5182 } else {
5183 594 sc->pb = c->fc->pb;
5184 594 sc->pb_is_copied = 1;
5185 }
5186
5187
2/2
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 292 times.
594 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5188
3/4
✓ Branch 0 taken 292 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 292 times.
✗ Branch 3 not taken.
302 int stts_constant = sc->stts_count && sc->tts_count;
5189
3/4
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 244 times.
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
302 if (sc->h_spacing && sc->v_spacing)
5190 58 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5191 58 sc->h_spacing, sc->v_spacing, INT_MAX);
5192
4/6
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 61 times.
✓ Branch 2 taken 241 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 241 times.
✗ Branch 5 not taken.
302 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
5193
2/4
✓ Branch 0 taken 241 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241 times.
✗ Branch 3 not taken.
241 sc->height && sc->width &&
5194
2/4
✓ Branch 0 taken 241 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 241 times.
241 (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
5195 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5196 (int64_t)st->codecpar->height * sc->width,
5197 (int64_t)st->codecpar->width * sc->height, INT_MAX);
5198 }
5199
5200 #if FF_API_R_FRAME_RATE
5201
4/4
✓ Branch 0 taken 154827 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 154535 times.
✓ Branch 3 taken 292 times.
154837 for (unsigned int i = 1; sc->stts_count && i + 1 < sc->tts_count; i++) {
5202
2/2
✓ Branch 0 taken 152108 times.
✓ Branch 1 taken 2427 times.
154535 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5203 152108 continue;
5204 2427 stts_constant = 0;
5205 }
5206
2/2
✓ Branch 0 taken 278 times.
✓ Branch 1 taken 24 times.
302 if (stts_constant)
5207 278 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5208 278 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5209 #endif
5210 }
5211
5212 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
5213
3/4
✓ Branch 0 taken 263 times.
✓ Branch 1 taken 331 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 263 times.
594 if (!st->codecpar->extradata_size && st->codecpar->codec_id == AV_CODEC_ID_H264 &&
5214 TAG_IS_AVCI(st->codecpar->codec_tag)) {
5215 ret = ff_generate_avci_extradata(st);
5216 if (ret < 0)
5217 return ret;
5218 }
5219
5220
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 570 times.
594 switch (st->codecpar->codec_id) {
5221 #if CONFIG_H261_DECODER
5222 24 case AV_CODEC_ID_H261:
5223 #endif
5224 #if CONFIG_H263_DECODER
5225 case AV_CODEC_ID_H263:
5226 #endif
5227 #if CONFIG_MPEG4_DECODER
5228 case AV_CODEC_ID_MPEG4:
5229 #endif
5230 24 st->codecpar->width = 0; /* let decoder init width/height */
5231 24 st->codecpar->height= 0;
5232 24 break;
5233 }
5234
5235 // If the duration of the mp3 packets is not constant, then they could need a parser
5236
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 593 times.
594 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5237
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 && sc->time_scale == st->codecpar->sample_rate) {
5238 1 int stts_constant = 1;
5239
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++) {
5240
1/2
✓ Branch 0 taken 287 times.
✗ Branch 1 not taken.
287 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5241 287 continue;
5242 stts_constant = 0;
5243 }
5244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!stts_constant)
5245 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5246 }
5247 /* Do not need those anymore. */
5248 594 av_freep(&sc->chunk_offsets);
5249 594 av_freep(&sc->sample_sizes);
5250 594 av_freep(&sc->keyframes);
5251 594 av_freep(&sc->stps_data);
5252 594 av_freep(&sc->elst_data);
5253 594 av_freep(&sc->rap_group);
5254 594 av_freep(&sc->sync_group);
5255 594 av_freep(&sc->sgpd_sync);
5256
5257 594 return 0;
5258 }
5259
5260 125 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5261 {
5262 int ret;
5263 125 c->itunes_metadata = 1;
5264 125 ret = mov_read_default(c, pb, atom);
5265 125 c->itunes_metadata = 0;
5266 125 return ret;
5267 }
5268
5269 11 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5270 {
5271 uint32_t count;
5272 uint32_t i;
5273
5274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
5275 return 0;
5276
5277 11 avio_skip(pb, 4);
5278 11 count = avio_rb32(pb);
5279 11 atom.size -= 8;
5280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (count >= UINT_MAX / sizeof(*c->meta_keys)) {
5281 av_log(c->fc, AV_LOG_ERROR,
5282 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5283 return AVERROR_INVALIDDATA;
5284 }
5285
5286 11 c->meta_keys_count = count + 1;
5287 11 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
5288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!c->meta_keys)
5289 return AVERROR(ENOMEM);
5290
5291
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i <= count; ++i) {
5292 58 uint32_t key_size = avio_rb32(pb);
5293 58 uint32_t type = avio_rl32(pb);
5294
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) {
5295 av_log(c->fc, AV_LOG_ERROR,
5296 "The key# %"PRIu32" in meta has invalid size:"
5297 "%"PRIu32"\n", i, key_size);
5298 return AVERROR_INVALIDDATA;
5299 }
5300 58 atom.size -= key_size;
5301 58 key_size -= 8;
5302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (type != MKTAG('m','d','t','a')) {
5303 avio_skip(pb, key_size);
5304 continue;
5305 }
5306 58 c->meta_keys[i] = av_mallocz(key_size + 1);
5307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!c->meta_keys[i])
5308 return AVERROR(ENOMEM);
5309 58 avio_read(pb, c->meta_keys[i], key_size);
5310 }
5311
5312 11 return 0;
5313 }
5314
5315 65 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5316 {
5317 65 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5318 65 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5319 int i;
5320 65 int ret = 0;
5321 AVStream *st;
5322 MOVStreamContext *sc;
5323
5324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (c->fc->nb_streams < 1)
5325 return 0;
5326 65 st = c->fc->streams[c->fc->nb_streams-1];
5327 65 sc = st->priv_data;
5328
5329
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 65 times.
260 for (i = 0; i < 3; i++) {
5330 uint8_t **p;
5331 uint32_t len, tag;
5332
5333
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 195 times.
195 if (end - avio_tell(pb) <= 12)
5334 break;
5335
5336 195 len = avio_rb32(pb);
5337 195 tag = avio_rl32(pb);
5338 195 avio_skip(pb, 4); // flags
5339
5340
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))
5341 break;
5342 195 len -= 12;
5343
5344
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 130 times.
195 if (tag == MKTAG('m', 'e', 'a', 'n'))
5345 65 p = &mean;
5346
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 65 times.
130 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5347 65 p = &key;
5348
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) {
5349 65 avio_skip(pb, 4);
5350 65 len -= 4;
5351 65 p = &val;
5352 } else
5353 break;
5354
5355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (*p)
5356 break;
5357
5358 195 *p = av_malloc(len + 1);
5359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*p) {
5360 ret = AVERROR(ENOMEM);
5361 break;
5362 }
5363 195 ret = ffio_read_size(pb, *p, len);
5364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (ret < 0) {
5365 av_freep(p);
5366 break;
5367 }
5368 195 (*p)[len] = 0;
5369 }
5370
5371
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) {
5372
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 32 times.
65 if (strcmp(key, "iTunSMPB") == 0) {
5373 int priming, remainder, samples;
5374
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
5375
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)
5376 33 sc->start_pad = priming;
5377 }
5378 }
5379
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 10 times.
120 if (strcmp(key, "cdec") != 0) {
5380 55 av_dict_set(&c->fc->metadata, key, val,
5381 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5382 55 key = val = NULL;
5383 }
5384 } else {
5385 av_log(c->fc, AV_LOG_VERBOSE,
5386 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5387 }
5388
5389 65 avio_seek(pb, end, SEEK_SET);
5390 65 av_freep(&key);
5391 65 av_freep(&val);
5392 65 av_freep(&mean);
5393 65 return ret;
5394 }
5395
5396 23 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5397 {
5398 MOVStreamContext *sc;
5399 AVStream *st;
5400
5401 23 st = avformat_new_stream(c->fc, NULL);
5402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!st)
5403 return AVERROR(ENOMEM);
5404 23 sc = av_mallocz(sizeof(MOVStreamContext));
5405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc)
5406 return AVERROR(ENOMEM);
5407
5408 23 item->st = st;
5409 23 st->id = item->item_id;
5410 23 st->priv_data = sc;
5411 23 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5412 23 st->codecpar->codec_id = mov_codec_id(st, item->type);
5413 23 sc->id = st->id;
5414 23 sc->ffindex = st->index;
5415 23 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5416 23 st->time_base.num = st->time_base.den = 1;
5417 23 st->nb_frames = 1;
5418 23 sc->time_scale = 1;
5419 23 sc->pb = c->fc->pb;
5420 23 sc->pb_is_copied = 1;
5421 23 sc->refcount = 1;
5422
5423
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 if (item->name)
5424 23 av_dict_set(&st->metadata, "title", item->name, 0);
5425
5426 // Populate the necessary fields used by mov_build_index.
5427 23 sc->stsc_count = 1;
5428 23 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc->stsc_data)
5430 return AVERROR(ENOMEM);
5431 23 sc->stsc_data[0].first = 1;
5432 23 sc->stsc_data[0].count = 1;
5433 23 sc->stsc_data[0].id = 1;
5434 23 sc->chunk_count = 1;
5435 23 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc->chunk_offsets)
5437 return AVERROR(ENOMEM);
5438 23 sc->sample_count = 1;
5439 23 sc->sample_sizes = av_malloc_array(1, sizeof(*sc->sample_sizes));
5440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc->sample_sizes)
5441 return AVERROR(ENOMEM);
5442 23 sc->stts_count = 1;
5443 23 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc->stts_data)
5445 return AVERROR(ENOMEM);
5446 23 sc->stts_data[0].count = 1;
5447 // Not used for still images. But needed by mov_build_index.
5448 23 sc->stts_data[0].duration = 0;
5449
5450 23 return 0;
5451 }
5452
5453 139 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5454 {
5455
1/2
✓ Branch 0 taken 403 times.
✗ Branch 1 not taken.
403 while (atom.size > 8) {
5456 uint32_t tag;
5457
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 403 times.
403 if (avio_feof(pb))
5458 return AVERROR_EOF;
5459 403 tag = avio_rl32(pb);
5460 403 atom.size -= 4;
5461
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 264 times.
403 if (tag == MKTAG('h','d','l','r')) {
5462 139 avio_seek(pb, -8, SEEK_CUR);
5463 139 atom.size += 8;
5464 139 return mov_read_default(c, pb, atom);
5465 }
5466 }
5467 return 0;
5468 }
5469
5470 // return 1 when matrix is identity, 0 otherwise
5471 #define IS_MATRIX_IDENT(matrix) \
5472 ( (matrix)[0][0] == (1 << 16) && \
5473 (matrix)[1][1] == (1 << 16) && \
5474 (matrix)[2][2] == (1 << 30) && \
5475 !(matrix)[0][1] && !(matrix)[0][2] && \
5476 !(matrix)[1][0] && !(matrix)[1][2] && \
5477 !(matrix)[2][0] && !(matrix)[2][1])
5478
5479 594 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5480 {
5481 int i, j, e;
5482 int width;
5483 int height;
5484 int display_matrix[3][3];
5485 594 int res_display_matrix[3][3] = { { 0 } };
5486 AVStream *st;
5487 MOVStreamContext *sc;
5488 int version;
5489 int flags;
5490
5491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
5492 return 0;
5493 594 st = c->fc->streams[c->fc->nb_streams-1];
5494 594 sc = st->priv_data;
5495
5496 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5497 // avoids corrupting AVStreams mapped to an earlier tkhd.
5498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (st->id != -1)
5499 return AVERROR_INVALIDDATA;
5500
5501 594 version = avio_r8(pb);
5502 594 flags = avio_rb24(pb);
5503 594 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5504
5505
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 585 times.
594 if (version == 1) {
5506 9 avio_rb64(pb);
5507 9 avio_rb64(pb);
5508 } else {
5509 585 avio_rb32(pb); /* creation time */
5510 585 avio_rb32(pb); /* modification time */
5511 }
5512 594 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5513 594 sc->id = st->id;
5514 594 avio_rb32(pb); /* reserved */
5515
5516 /* highlevel (considering edits) duration in movie timebase */
5517
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 585 times.
594 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5518 594 avio_rb32(pb); /* reserved */
5519 594 avio_rb32(pb); /* reserved */
5520
5521 594 avio_rb16(pb); /* layer */
5522 594 avio_rb16(pb); /* alternate group */
5523 594 avio_rb16(pb); /* volume */
5524 594 avio_rb16(pb); /* reserved */
5525
5526 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
5527 // they're kept in fixed point format through all calculations
5528 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
5529 // side data, but the scale factor is not needed to calculate aspect ratio
5530
2/2
✓ Branch 0 taken 1782 times.
✓ Branch 1 taken 594 times.
2376 for (i = 0; i < 3; i++) {
5531 1782 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
5532 1782 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
5533 1782 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
5534 }
5535
5536 594 width = avio_rb32(pb); // 16.16 fixed point track width
5537 594 height = avio_rb32(pb); // 16.16 fixed point track height
5538 594 sc->width = width >> 16;
5539 594 sc->height = height >> 16;
5540
5541 // apply the moov display matrix (after the tkhd one)
5542
2/2
✓ Branch 0 taken 1782 times.
✓ Branch 1 taken 594 times.
2376 for (i = 0; i < 3; i++) {
5543 1782 const int sh[3] = { 16, 16, 30 };
5544
2/2
✓ Branch 0 taken 5346 times.
✓ Branch 1 taken 1782 times.
7128 for (j = 0; j < 3; j++) {
5545
2/2
✓ Branch 0 taken 16038 times.
✓ Branch 1 taken 5346 times.
21384 for (e = 0; e < 3; e++) {
5546 16038 res_display_matrix[i][j] +=
5547 16038 ((int64_t) display_matrix[i][e] *
5548 16038 c->movie_display_matrix[e][j]) >> sh[e];
5549 }
5550 }
5551 }
5552
5553 // save the matrix when it is not the default identity
5554
10/18
✓ Branch 0 taken 585 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 585 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 585 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 585 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 585 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 585 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 585 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 585 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 585 times.
594 if (!IS_MATRIX_IDENT(res_display_matrix)) {
5555 9 av_freep(&sc->display_matrix);
5556 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
5557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
5558 return AVERROR(ENOMEM);
5559
5560
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
5561
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
5562 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
5563 }
5564
5565 // transform the display width/height according to the matrix
5566 // to keep the same scale, use [width height 1<<16]
5567
5/6
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 282 times.
✓ Branch 2 taken 312 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 304 times.
594 if (width && height && sc->display_matrix) {
5568 double disp_transform[2];
5569
5570
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
5571 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
5572 16 sc->display_matrix[3 + i]);
5573
5574
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 &&
5575
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) &&
5576
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
5577 3 st->sample_aspect_ratio = av_d2q(
5578 3 disp_transform[0] / disp_transform[1],
5579 INT_MAX);
5580 }
5581 594 return 0;
5582 }
5583
5584 388 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5585 {
5586 388 MOVFragment *frag = &c->fragment;
5587 388 MOVTrackExt *trex = NULL;
5588 int flags, track_id, i;
5589 MOVFragmentStreamInfo * frag_stream_info;
5590
5591 388 avio_r8(pb); /* version */
5592 388 flags = avio_rb24(pb);
5593
5594 388 track_id = avio_rb32(pb);
5595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!track_id)
5596 return AVERROR_INVALIDDATA;
5597
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < c->trex_count; i++)
5598
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (c->trex_data[i].track_id == track_id) {
5599 388 trex = &c->trex_data[i];
5600 388 break;
5601 }
5602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!trex) {
5603 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
5604 return 0;
5605 }
5606 388 c->fragment.found_tfhd = 1;
5607 388 frag->track_id = track_id;
5608 388 set_frag_stream(&c->frag_index, track_id);
5609
5610 776 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
5611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
776 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
5612
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 21 times.
388 frag->moof_offset : frag->implicit_offset;
5613
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;
5614
5615 776 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
5616
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 383 times.
388 avio_rb32(pb) : trex->duration;
5617 776 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
5618
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 382 times.
388 avio_rb32(pb) : trex->size;
5619 776 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
5620
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 365 times.
388 avio_rb32(pb) : trex->flags;
5621 388 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
5622
5623 388 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5624
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5625 388 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
5626 388 frag_stream_info->stsd_id = frag->stsd_id;
5627 }
5628 388 return 0;
5629 }
5630
5631 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5632 {
5633 unsigned i, num;
5634 void *new_tracks;
5635
5636 2 num = atom.size / 4;
5637
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
5638 return AVERROR(ENOMEM);
5639
5640 2 av_free(c->chapter_tracks);
5641 2 c->chapter_tracks = new_tracks;
5642 2 c->nb_chapter_tracks = num;
5643
5644
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++)
5645 2 c->chapter_tracks[i] = avio_rb32(pb);
5646
5647 2 c->nb_chapter_tracks = i;
5648
5649 2 return 0;
5650 }
5651
5652 17 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5653 {
5654 MOVTrackExt *trex;
5655 int err;
5656
5657
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))
5658 return AVERROR_INVALIDDATA;
5659
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
5660 sizeof(*c->trex_data))) < 0) {
5661 c->trex_count = 0;
5662 return err;
5663 }
5664
5665 17 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
5666
5667 17 trex = &c->trex_data[c->trex_count++];
5668 17 avio_r8(pb); /* version */
5669 17 avio_rb24(pb); /* flags */
5670 17 trex->track_id = avio_rb32(pb);
5671 17 trex->stsd_id = avio_rb32(pb);
5672 17 trex->duration = avio_rb32(pb);
5673 17 trex->size = avio_rb32(pb);
5674 17 trex->flags = avio_rb32(pb);
5675 17 return 0;
5676 }
5677
5678 367 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5679 {
5680 367 MOVFragment *frag = &c->fragment;
5681 367 AVStream *st = NULL;
5682 MOVStreamContext *sc;
5683 int version, i;
5684 MOVFragmentStreamInfo * frag_stream_info;
5685 int64_t base_media_decode_time;
5686
5687
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 for (i = 0; i < c->fc->nb_streams; i++) {
5688 367 sc = c->fc->streams[i]->priv_data;
5689
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 if (sc->id == frag->track_id) {
5690 367 st = c->fc->streams[i];
5691 367 break;
5692 }
5693 }
5694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367 times.
367 if (!st) {
5695 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5696 return 0;
5697 }
5698 367 sc = st->priv_data;
5699
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)
5700 return 0;
5701 367 version = avio_r8(pb);
5702 367 avio_rb24(pb); /* flags */
5703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367 times.
367 if (version) {
5704 base_media_decode_time = avio_rb64(pb);
5705 } else {
5706 367 base_media_decode_time = avio_rb32(pb);
5707 }
5708
5709 367 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5710
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 if (frag_stream_info)
5711 367 frag_stream_info->tfdt_dts = base_media_decode_time;
5712 367 sc->track_end = base_media_decode_time;
5713
5714 367 return 0;
5715 }
5716
5717 388 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5718 {
5719 388 MOVFragment *frag = &c->fragment;
5720 388 AVStream *st = NULL;
5721 388 FFStream *sti = NULL;
5722 MOVStreamContext *sc;
5723 MOVTimeToSample *tts_data;
5724 uint64_t offset;
5725 388 int64_t dts, pts = AV_NOPTS_VALUE;
5726 388 int data_offset = 0;
5727 388 unsigned entries, first_sample_flags = frag->flags;
5728 int flags, distance, i;
5729 388 int64_t prev_dts = AV_NOPTS_VALUE;
5730 388 int next_frag_index = -1, index_entry_pos;
5731 size_t requested_size;
5732 size_t old_allocated_size;
5733 AVIndexEntry *new_entries;
5734 MOVFragmentStreamInfo * frag_stream_info;
5735
5736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!frag->found_tfhd) {
5737 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
5738 return AVERROR_INVALIDDATA;
5739 }
5740
5741
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < c->fc->nb_streams; i++) {
5742 394 sc = c->fc->streams[i]->priv_data;
5743
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (sc->id == frag->track_id) {
5744 388 st = c->fc->streams[i];
5745 388 sti = ffstream(st);
5746 388 break;
5747 }
5748 }
5749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!st) {
5750 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5751 return 0;
5752 }
5753 388 sc = st->priv_data;
5754
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)
5755 return 0;
5756
5757 // Find the next frag_index index that has a valid index_entry for
5758 // the current track_id.
5759 //
5760 // A valid index_entry means the trun for the fragment was read
5761 // and it's samples are in index_entries at the given position.
5762 // New index entries will be inserted before the index_entry found.
5763 388 index_entry_pos = sti->nb_index_entries;
5764
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++) {
5765 1621 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
5766
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) {
5767 next_frag_index = i;
5768 index_entry_pos = frag_stream_info->index_entry;
5769 break;
5770 }
5771 }
5772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 av_assert0(index_entry_pos <= sti->nb_index_entries);
5773
5774 388 avio_r8(pb); /* version */
5775 388 flags = avio_rb24(pb);
5776 388 entries = avio_rb32(pb);
5777 388 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
5778
5779
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))
5780 return AVERROR_INVALIDDATA;
5781
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
5782
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);
5783
5784 388 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5785
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
5787 dts = frag_stream_info->next_trun_dts - sc->time_offset;
5788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5789 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
5790 pts = frag_stream_info->first_tfra_pts;
5791 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5792 ", using it for pts\n", pts);
5793
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5794 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
5795 dts = frag_stream_info->first_tfra_pts;
5796 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5797 ", using it for dts\n", pts);
5798 } else {
5799 388 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
5800 388 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
5801
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;
5802
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;
5803
5804
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (fallback_sidx) {
5805 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
5806 }
5807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (fallback_tfdt) {
5808 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
5809 }
5810
5811
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) {
5812 367 dts = frag_stream_info->tfdt_dts - sc->time_offset;
5813 367 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
5814 ", using it for dts\n", dts);
5815
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) {
5816 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
5817 // pts = frag_stream_info->sidx_pts;
5818 dts = frag_stream_info->sidx_pts - sc->time_offset;
5819 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
5820 ", using it for dts\n", frag_stream_info->sidx_pts);
5821 } else {
5822 21 dts = sc->track_end - sc->time_offset;
5823 21 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5824 ", using it for dts\n", dts);
5825 }
5826 }
5827 } else {
5828 dts = sc->track_end - sc->time_offset;
5829 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5830 ", using it for dts\n", dts);
5831 }
5832 388 offset = frag->base_data_offset + data_offset;
5833 388 distance = 0;
5834 388 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
5835
5836 // realloc space for new index entries
5837
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
5838 entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
5839 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
5840 }
5841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (entries == 0)
5842 return 0;
5843
5844 388 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
5845 388 new_entries = av_fast_realloc(sti->index_entries,
5846 &sti->index_entries_allocated_size,
5847 requested_size);
5848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!new_entries)
5849 return AVERROR(ENOMEM);
5850 388 sti->index_entries= new_entries;
5851
5852 388 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
5853 388 old_allocated_size = sc->tts_allocated_size;
5854 388 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
5855 requested_size);
5856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!tts_data)
5857 return AVERROR(ENOMEM);
5858 388 sc->tts_data = tts_data;
5859
5860 // In case there were samples without time to sample entries, ensure they get
5861 // zero valued entries. This ensures clips which mix boxes with and
5862 // without time to sample entries don't pickup uninitialized data.
5863 388 memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0,
5864 388 sc->tts_allocated_size - old_allocated_size);
5865
5866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (index_entry_pos < sti->nb_index_entries) {
5867 // Make hole in index_entries and tts_data for new samples
5868 memmove(sti->index_entries + index_entry_pos + entries,
5869 sti->index_entries + index_entry_pos,
5870 sizeof(*sti->index_entries) *
5871 (sti->nb_index_entries - index_entry_pos));
5872 memmove(sc->tts_data + index_entry_pos + entries,
5873 sc->tts_data + index_entry_pos,
5874 sizeof(*sc->tts_data) * (sc->tts_count - index_entry_pos));
5875 if (index_entry_pos < sc->current_sample) {
5876 sc->current_sample += entries;
5877 }
5878 }
5879
5880 388 sti->nb_index_entries += entries;
5881 388 sc->tts_count = sti->nb_index_entries;
5882 388 sc->stts_count = sti->nb_index_entries;
5883
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 28 times.
388 if (flags & MOV_TRUN_SAMPLE_CTS)
5884 360 sc->ctts_count = sti->nb_index_entries;
5885
5886 // Record the index_entry position in frag_index of this fragment
5887
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5888 388 frag_stream_info->index_entry = index_entry_pos;
5889
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info->index_base < 0)
5890 388 frag_stream_info->index_base = index_entry_pos;
5891 }
5892
5893
2/2
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 14 times.
388 if (index_entry_pos > 0)
5894 374 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
5895
5896
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++) {
5897 6066 unsigned sample_size = frag->size;
5898
2/2
✓ Branch 0 taken 5678 times.
✓ Branch 1 taken 388 times.
6066 int sample_flags = i ? frag->flags : first_sample_flags;
5899 6066 unsigned sample_duration = frag->duration;
5900 6066 unsigned ctts_duration = 0;
5901 6066 int keyframe = 0;
5902 6066 int index_entry_flags = 0;
5903
5904
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 5594 times.
6066 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
5905
2/2
✓ Branch 0 taken 6034 times.
✓ Branch 1 taken 32 times.
6066 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
5906
2/2
✓ Branch 0 taken 933 times.
✓ Branch 1 taken 5133 times.
6066 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
5907
2/2
✓ Branch 0 taken 5400 times.
✓ Branch 1 taken 666 times.
6066 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
5908
5909 6066 mov_update_dts_shift(sc, ctts_duration, c->fc);
5910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6066 times.
6066 if (pts != AV_NOPTS_VALUE) {
5911 dts = pts - sc->dts_shift;
5912 if (flags & MOV_TRUN_SAMPLE_CTS) {
5913 dts -= ctts_duration;
5914 } else {
5915 dts -= sc->time_offset;
5916 }
5917 av_log(c->fc, AV_LOG_DEBUG,
5918 "pts %"PRId64" calculated dts %"PRId64
5919 " sc->dts_shift %d ctts.duration %d"
5920 " sc->time_offset %"PRId64
5921 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
5922 pts, dts,
5923 sc->dts_shift, ctts_duration,
5924 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
5925 pts = AV_NOPTS_VALUE;
5926 }
5927
5928 6066 keyframe =
5929 6066 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
5930 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
5931
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 5666 times.
6066 if (keyframe) {
5932 400 distance = 0;
5933 400 index_entry_flags |= AVINDEX_KEYFRAME;
5934 }
5935 // Fragments can overlap in time. Discard overlapping frames after
5936 // decoding.
5937
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6042 times.
6066 if (prev_dts >= dts)
5938 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
5939
5940 6066 sti->index_entries[index_entry_pos].pos = offset;
5941 6066 sti->index_entries[index_entry_pos].timestamp = dts;
5942 6066 sti->index_entries[index_entry_pos].size = sample_size;
5943 6066 sti->index_entries[index_entry_pos].min_distance = distance;
5944 6066 sti->index_entries[index_entry_pos].flags = index_entry_flags;
5945
5946 6066 sc->tts_data[index_entry_pos].count = 1;
5947 6066 sc->tts_data[index_entry_pos].offset = ctts_duration;
5948 6066 sc->tts_data[index_entry_pos].duration = sample_duration;
5949 6066 index_entry_pos++;
5950
5951 6066 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
5952 "size %u, distance %d, keyframe %d\n", st->index,
5953 index_entry_pos, offset, dts, sample_size, distance, keyframe);
5954 6066 distance++;
5955
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6066 times.
6066 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
5956 return AVERROR_INVALIDDATA;
5957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6066 times.
6066 if (!sample_size)
5958 return AVERROR_INVALIDDATA;
5959 6066 dts += sample_duration;
5960 6066 offset += sample_size;
5961 6066 sc->data_size += sample_size;
5962
5963
1/2
✓ Branch 0 taken 6066 times.
✗ Branch 1 not taken.
6066 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
5964
1/2
✓ Branch 0 taken 6066 times.
✗ Branch 1 not taken.
6066 1 <= INT_MAX - sc->nb_frames_for_fps
5965 ) {
5966 6066 sc->duration_for_fps += sample_duration;
5967 6066 sc->nb_frames_for_fps ++;
5968 }
5969 }
5970
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info)
5971 388 frag_stream_info->next_trun_dts = dts + sc->time_offset;
5972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (i < entries) {
5973 // EOF found before reading all entries. Fix the hole this would
5974 // leave in index_entries and tts_data
5975 int gap = entries - i;
5976 memmove(sti->index_entries + index_entry_pos,
5977 sti->index_entries + index_entry_pos + gap,
5978 sizeof(*sti->index_entries) *
5979 (sti->nb_index_entries - (index_entry_pos + gap)));
5980 memmove(sc->tts_data + index_entry_pos,
5981 sc->tts_data + index_entry_pos + gap,
5982 sizeof(*sc->tts_data) *
5983 (sc->tts_count - (index_entry_pos + gap)));
5984
5985 sti->nb_index_entries -= gap;
5986 sc->tts_count -= gap;
5987 if (index_entry_pos < sc->current_sample) {
5988 sc->current_sample -= gap;
5989 }
5990 entries = i;
5991 }
5992
5993 // The end of this new fragment may overlap in time with the start
5994 // of the next fragment in index_entries. Mark the samples in the next
5995 // fragment that overlap with AVINDEX_DISCARD_FRAME
5996 388 prev_dts = AV_NOPTS_VALUE;
5997
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (index_entry_pos > 0)
5998 388 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
5999
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
6000 if (prev_dts < sti->index_entries[i].timestamp)
6001 break;
6002 sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6003 }
6004
6005 // If a hole was created to insert the new index_entries into,
6006 // the index_entry recorded for all subsequent moof must
6007 // be incremented by the number of entries inserted.
6008 388 fix_frag_index_entries(&c->frag_index, next_frag_index,
6009 388 frag->track_id, entries);
6010
6011
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (pb->eof_reached) {
6012 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6013 return AVERROR_EOF;
6014 }
6015
6016 388 frag->implicit_offset = offset;
6017
6018 388 sc->track_end = dts + sc->time_offset;
6019
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 379 times.
388 if (st->duration < sc->track_end)
6020 9 st->duration = sc->track_end;
6021
6022 388 return 0;
6023 }
6024
6025 43 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6026 {
6027 43 int64_t stream_size = avio_size(pb);
6028 43 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6029 uint8_t version, is_complete;
6030 int64_t offadd;
6031 unsigned i, j, track_id, item_count;
6032 43 AVStream *st = NULL;
6033 43 AVStream *ref_st = NULL;
6034 43 MOVStreamContext *sc, *ref_sc = NULL;
6035 AVRational timescale;
6036
6037 43 version = avio_r8(pb);
6038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (version > 1) {
6039 avpriv_request_sample(c->fc, "sidx version %u", version);
6040 return 0;
6041 }
6042
6043 43 avio_rb24(pb); // flags
6044
6045 43 track_id = avio_rb32(pb); // Reference ID
6046
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 for (i = 0; i < c->fc->nb_streams; i++) {
6047 43 sc = c->fc->streams[i]->priv_data;
6048
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (sc->id == track_id) {
6049 43 st = c->fc->streams[i];
6050 43 break;
6051 }
6052 }
6053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st) {
6054 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6055 return 0;
6056 }
6057
6058 43 sc = st->priv_data;
6059
6060 43 timescale = av_make_q(1, avio_rb32(pb));
6061
6062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (timescale.den <= 0) {
6063 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6064 return AVERROR_INVALIDDATA;
6065 }
6066
6067
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (version == 0) {
6068 43 pts = avio_rb32(pb);
6069 43 offadd= avio_rb32(pb);
6070 } else {
6071 pts = avio_rb64(pb);
6072 offadd= avio_rb64(pb);
6073 }
6074
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6075 return AVERROR_INVALIDDATA;
6076
6077 43 offset += (uint64_t)offadd;
6078
6079 43 avio_rb16(pb); // reserved
6080
6081 43 item_count = avio_rb16(pb);
6082
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (item_count == 0)
6083 return AVERROR_INVALIDDATA;
6084
6085
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 43 times.
411 for (i = 0; i < item_count; i++) {
6086 int index;
6087 MOVFragmentStreamInfo * frag_stream_info;
6088 368 uint32_t size = avio_rb32(pb);
6089 368 uint32_t duration = avio_rb32(pb);
6090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 368 times.
368 if (size & 0x80000000) {
6091 avpriv_request_sample(c->fc, "sidx reference_type 1");
6092 return AVERROR_PATCHWELCOME;
6093 }
6094 368 avio_rb32(pb); // sap_flags
6095 368 timestamp = av_rescale_q(pts, timescale, st->time_base);
6096
6097 368 index = update_frag_index(c, offset);
6098 368 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6099
1/2
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
368 if (frag_stream_info)
6100 368 frag_stream_info->sidx_pts = timestamp;
6101
6102
1/2
✓ Branch 1 taken 368 times.
✗ Branch 2 not taken.
368 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6103
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 368 times.
368 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6104 )
6105 return AVERROR_INVALIDDATA;
6106 368 offset += size;
6107 368 pts += duration;
6108 }
6109
6110 43 st->duration = sc->track_end = pts;
6111
6112 43 sc->has_sidx = 1;
6113
6114 // See if the remaining bytes are just an mfra which we can ignore.
6115 43 is_complete = offset == stream_size;
6116
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 ) {
6117 int64_t ret;
6118 38 int64_t original_pos = avio_tell(pb);
6119
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
38 if (!c->have_read_mfra_size) {
6120
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6121 return ret;
6122 3 c->mfra_size = avio_rb32(pb);
6123 3 c->have_read_mfra_size = 1;
6124
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6125 return ret;
6126 }
6127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (offset == stream_size - c->mfra_size)
6128 is_complete = 1;
6129 }
6130
6131
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 38 times.
43 if (is_complete) {
6132 // Find first entry in fragment index that came from an sidx.
6133 // This will pretty much always be the first entry.
6134
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 5 times.
373 for (i = 0; i < c->frag_index.nb_items; i++) {
6135 368 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6136
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++) {
6137 MOVFragmentStreamInfo * si;
6138 5 si = &item->stream_info[j];
6139
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (si->sidx_pts != AV_NOPTS_VALUE) {
6140 5 ref_st = c->fc->streams[j];
6141 5 ref_sc = ref_st->priv_data;
6142 5 break;
6143 }
6144 }
6145 }
6146
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++) {
6147 5 st = c->fc->streams[i];
6148 5 sc = st->priv_data;
6149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->has_sidx) {
6150 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6151 }
6152 }
6153
6154 5 c->frag_index.complete = 1;
6155 }
6156
6157 43 return 0;
6158 }
6159
6160 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6161 /* like the files created with Adobe Premiere 5.0, for samples see */
6162 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6163 267 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6164 {
6165 int err;
6166
6167
1/2
✓ Branch 0 taken 267 times.
✗ Branch 1 not taken.
267 if (atom.size < 8)
6168 267 return 0; /* continue */
6169 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6170 avio_skip(pb, atom.size - 4);
6171 return 0;
6172 }
6173 atom.type = avio_rl32(pb);
6174 atom.size -= 8;
6175 if (atom.type != MKTAG('m','d','a','t')) {
6176 avio_skip(pb, atom.size);
6177 return 0;
6178 }
6179 err = mov_read_mdat(c, pb, atom);
6180 return err;
6181 }
6182
6183 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6184 {
6185 #if CONFIG_ZLIB
6186 FFIOContext ctx;
6187 uint8_t *cmov_data;
6188 uint8_t *moov_data; /* uncompressed data */
6189 long cmov_len, moov_len;
6190 3 int ret = -1;
6191
6192 3 avio_rb32(pb); /* dcom atom */
6193
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6194 return AVERROR_INVALIDDATA;
6195
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6196 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6197 return AVERROR_INVALIDDATA;
6198 }
6199 3 avio_rb32(pb); /* cmvd atom */
6200
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6201 return AVERROR_INVALIDDATA;
6202 3 moov_len = avio_rb32(pb); /* uncompressed size */
6203 3 cmov_len = atom.size - 6 * 4;
6204
6205 3 cmov_data = av_malloc(cmov_len);
6206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6207 return AVERROR(ENOMEM);
6208 3 moov_data = av_malloc(moov_len);
6209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6210 av_free(cmov_data);
6211 return AVERROR(ENOMEM);
6212 }
6213 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6215 goto free_and_return;
6216
6217 3 ret = AVERROR_INVALIDDATA;
6218
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)
6219 goto free_and_return;
6220 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6221 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6222 3 atom.type = MKTAG('m','o','o','v');
6223 3 atom.size = moov_len;
6224 3 ret = mov_read_default(c, &ctx.pub, atom);
6225 3 free_and_return:
6226 3 av_free(moov_data);
6227 3 av_free(cmov_data);
6228 3 return ret;
6229 #else
6230 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6231 return AVERROR(ENOSYS);
6232 #endif
6233 }
6234
6235 /* edit list atom */
6236 439 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6237 {
6238 MOVStreamContext *sc;
6239 int i, edit_count, version;
6240 int64_t elst_entry_size;
6241
6242
2/4
✓ Branch 0 taken 439 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 439 times.
439 if (c->fc->nb_streams < 1 || c->ignore_editlist)
6243 return 0;
6244 439 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6245
6246 439 version = avio_r8(pb); /* version */
6247 439 avio_rb24(pb); /* flags */
6248 439 edit_count = avio_rb32(pb); /* entries */
6249 439 atom.size -= 8;
6250
6251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
439 elst_entry_size = version == 1 ? 20 : 12;
6252
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 438 times.
439 if (atom.size != edit_count * elst_entry_size) {
6253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6254 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6255 edit_count, atom.size + 8);
6256 return AVERROR_INVALIDDATA;
6257 } else {
6258 1 edit_count = atom.size / elst_entry_size;
6259
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6260 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6261 }
6262 }
6263 }
6264
6265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
439 if (!edit_count)
6266 return 0;
6267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
439 if (sc->elst_data)
6268 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6269 439 av_free(sc->elst_data);
6270 439 sc->elst_count = 0;
6271 439 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
439 if (!sc->elst_data)
6273 return AVERROR(ENOMEM);
6274
6275 439 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6276
4/6
✓ Branch 0 taken 466 times.
✓ Branch 1 taken 439 times.
✓ Branch 2 taken 466 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 466 times.
✗ Branch 5 not taken.
905 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
6277 466 MOVElst *e = &sc->elst_data[i];
6278
6279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 466 times.
466 if (version == 1) {
6280 e->duration = avio_rb64(pb);
6281 e->time = avio_rb64(pb);
6282 atom.size -= 16;
6283 } else {
6284 466 e->duration = avio_rb32(pb); /* segment duration */
6285 466 e->time = (int32_t)avio_rb32(pb); /* media time */
6286 466 atom.size -= 8;
6287 }
6288 466 e->rate = avio_rb32(pb) / 65536.0;
6289 466 atom.size -= 4;
6290 466 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6291 466 e->duration, e->time, e->rate);
6292
6293
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 462 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
466 if (e->time < 0 && e->time != -1 &&
6294 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6295 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6296 c->fc->nb_streams-1, i, e->time);
6297 return AVERROR_INVALIDDATA;
6298 }
6299 }
6300 439 sc->elst_count = i;
6301
6302 439 return 0;
6303 }
6304
6305 18 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6306 {
6307 MOVStreamContext *sc;
6308
6309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->fc->nb_streams < 1)
6310 return AVERROR_INVALIDDATA;
6311 18 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6312 18 sc->timecode_track = avio_rb32(pb);
6313 18 return 0;
6314 }
6315
6316 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6317 {
6318 AVStream *st;
6319 int version, color_range, color_primaries, color_trc, color_space;
6320
6321 if (c->fc->nb_streams < 1)
6322 return 0;
6323 st = c->fc->streams[c->fc->nb_streams - 1];
6324
6325 if (atom.size < 5) {
6326 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6327 return AVERROR_INVALIDDATA;
6328 }
6329
6330 version = avio_r8(pb);
6331 if (version != 1) {
6332 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6333 return 0;
6334 }
6335 avio_skip(pb, 3); /* flags */
6336
6337 avio_skip(pb, 2); /* profile + level */
6338 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6339 color_primaries = avio_r8(pb);
6340 color_trc = avio_r8(pb);
6341 color_space = avio_r8(pb);
6342 if (avio_rb16(pb)) /* codecIntializationDataSize */
6343 return AVERROR_INVALIDDATA;
6344
6345 if (!av_color_primaries_name(color_primaries))
6346 color_primaries = AVCOL_PRI_UNSPECIFIED;
6347 if (!av_color_transfer_name(color_trc))
6348 color_trc = AVCOL_TRC_UNSPECIFIED;
6349 if (!av_color_space_name(color_space))
6350 color_space = AVCOL_SPC_UNSPECIFIED;
6351
6352 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6353 st->codecpar->color_primaries = color_primaries;
6354 st->codecpar->color_trc = color_trc;
6355 st->codecpar->color_space = color_space;
6356
6357 return 0;
6358 }
6359
6360 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6361 {
6362 MOVStreamContext *sc;
6363 int i, version;
6364
6365 if (c->fc->nb_streams < 1)
6366 return AVERROR_INVALIDDATA;
6367
6368 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6369
6370 if (atom.size < 5) {
6371 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6372 return AVERROR_INVALIDDATA;
6373 }
6374
6375 version = avio_r8(pb);
6376 if (version) {
6377 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6378 return 0;
6379 }
6380 if (sc->mastering) {
6381 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6382 return 0;
6383 }
6384
6385 avio_skip(pb, 3); /* flags */
6386
6387 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6388 if (!sc->mastering)
6389 return AVERROR(ENOMEM);
6390
6391 for (i = 0; i < 3; i++) {
6392 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6393 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6394 }
6395 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6396 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6397
6398 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6399 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6400
6401 sc->mastering->has_primaries = 1;
6402 sc->mastering->has_luminance = 1;
6403
6404 return 0;
6405 }
6406
6407 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6408 {
6409 MOVStreamContext *sc;
6410 const int mapping[3] = {1, 2, 0};
6411 const int chroma_den = 50000;
6412 const int luma_den = 10000;
6413 int i;
6414
6415 if (c->fc->nb_streams < 1)
6416 return AVERROR_INVALIDDATA;
6417
6418 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6419
6420 if (atom.size < 24) {
6421 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6422 return AVERROR_INVALIDDATA;
6423 }
6424
6425 if (sc->mastering) {
6426 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6427 return 0;
6428 }
6429
6430 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6431 if (!sc->mastering)
6432 return AVERROR(ENOMEM);
6433
6434 for (i = 0; i < 3; i++) {
6435 const int j = mapping[i];
6436 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6437 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6438 }
6439 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6440 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6441
6442 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6443 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6444
6445 sc->mastering->has_luminance = 1;
6446 sc->mastering->has_primaries = 1;
6447
6448 return 0;
6449 }
6450
6451 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6452 {
6453 MOVStreamContext *sc;
6454 int version;
6455
6456 if (c->fc->nb_streams < 1)
6457 return AVERROR_INVALIDDATA;
6458
6459 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6460
6461 if (atom.size < 5) {
6462 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
6463 return AVERROR_INVALIDDATA;
6464 }
6465
6466 version = avio_r8(pb);
6467 if (version) {
6468 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
6469 return 0;
6470 }
6471 avio_skip(pb, 3); /* flags */
6472
6473 if (sc->coll){
6474 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
6475 return 0;
6476 }
6477
6478 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6479 if (!sc->coll)
6480 return AVERROR(ENOMEM);
6481
6482 sc->coll->MaxCLL = avio_rb16(pb);
6483 sc->coll->MaxFALL = avio_rb16(pb);
6484
6485 return 0;
6486 }
6487
6488 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6489 {
6490 MOVStreamContext *sc;
6491
6492 if (c->fc->nb_streams < 1)
6493 return AVERROR_INVALIDDATA;
6494
6495 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6496
6497 if (atom.size < 4) {
6498 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
6499 return AVERROR_INVALIDDATA;
6500 }
6501
6502 if (sc->coll){
6503 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
6504 return 0;
6505 }
6506
6507 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6508 if (!sc->coll)
6509 return AVERROR(ENOMEM);
6510
6511 sc->coll->MaxCLL = avio_rb16(pb);
6512 sc->coll->MaxFALL = avio_rb16(pb);
6513
6514 return 0;
6515 }
6516
6517 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6518 {
6519 MOVStreamContext *sc;
6520 4 const int illuminance_den = 10000;
6521 4 const int ambient_den = 50000;
6522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
6523 return AVERROR_INVALIDDATA;
6524 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
6526 av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
6527 return AVERROR_INVALIDDATA;
6528 }
6529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
6530 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
6531 return 0;
6532 }
6533 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
6534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
6535 return AVERROR(ENOMEM);
6536 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
6537 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
6538 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
6539 4 return 0;
6540 }
6541
6542 1 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6543 {
6544 AVStream *st;
6545 MOVStreamContext *sc;
6546 enum AVStereo3DType type;
6547 int mode;
6548
6549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6550 return 0;
6551
6552 1 st = c->fc->streams[c->fc->nb_streams - 1];
6553 1 sc = st->priv_data;
6554
6555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 5) {
6556 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
6557 return AVERROR_INVALIDDATA;
6558 }
6559
6560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sc->stereo3d)
6561 return AVERROR_INVALIDDATA;
6562
6563 1 avio_skip(pb, 4); /* version + flags */
6564
6565 1 mode = avio_r8(pb);
6566
1/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 switch (mode) {
6567 1 case 0:
6568 1 type = AV_STEREO3D_2D;
6569 1 break;
6570 case 1:
6571 type = AV_STEREO3D_TOPBOTTOM;
6572 break;
6573 case 2:
6574 type = AV_STEREO3D_SIDEBYSIDE;
6575 break;
6576 default:
6577 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
6578 return 0;
6579 }
6580
6581 1 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->stereo3d)
6583 return AVERROR(ENOMEM);
6584
6585 1 sc->stereo3d->type = type;
6586 1 return 0;
6587 }
6588
6589 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6590 {
6591 AVStream *st;
6592 MOVStreamContext *sc;
6593 int size, version, layout;
6594 int32_t yaw, pitch, roll;
6595 1 uint32_t l = 0, t = 0, r = 0, b = 0;
6596 1 uint32_t tag, padding = 0;
6597 enum AVSphericalProjection projection;
6598
6599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6600 return 0;
6601
6602 1 st = c->fc->streams[c->fc->nb_streams - 1];
6603 1 sc = st->priv_data;
6604
6605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
6606 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
6607 return AVERROR_INVALIDDATA;
6608 }
6609
6610 1 size = avio_rb32(pb);
6611
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)
6612 return AVERROR_INVALIDDATA;
6613
6614 1 tag = avio_rl32(pb);
6615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
6616 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
6617 return 0;
6618 }
6619 1 version = avio_r8(pb);
6620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6621 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6622 version);
6623 return 0;
6624 }
6625 1 avio_skip(pb, 3); /* flags */
6626 1 avio_skip(pb, size - 12); /* metadata_source */
6627
6628 1 size = avio_rb32(pb);
6629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6630 return AVERROR_INVALIDDATA;
6631
6632 1 tag = avio_rl32(pb);
6633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
6634 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
6635 return 0;
6636 }
6637
6638 1 size = avio_rb32(pb);
6639
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6640 return AVERROR_INVALIDDATA;
6641
6642 1 tag = avio_rl32(pb);
6643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
6644 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
6645 return 0;
6646 }
6647 1 version = avio_r8(pb);
6648
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6649 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6650 version);
6651 return 0;
6652 }
6653 1 avio_skip(pb, 3); /* flags */
6654
6655 /* 16.16 fixed point */
6656 1 yaw = avio_rb32(pb);
6657 1 pitch = avio_rb32(pb);
6658 1 roll = avio_rb32(pb);
6659
6660 1 size = avio_rb32(pb);
6661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6662 return AVERROR_INVALIDDATA;
6663
6664 1 tag = avio_rl32(pb);
6665 1 version = avio_r8(pb);
6666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6667 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6668 version);
6669 return 0;
6670 }
6671 1 avio_skip(pb, 3); /* flags */
6672
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
6673 case MKTAG('c','b','m','p'):
6674 layout = avio_rb32(pb);
6675 if (layout) {
6676 av_log(c->fc, AV_LOG_WARNING,
6677 "Unsupported cubemap layout %d\n", layout);
6678 return 0;
6679 }
6680 projection = AV_SPHERICAL_CUBEMAP;
6681 padding = avio_rb32(pb);
6682 break;
6683 1 case MKTAG('e','q','u','i'):
6684 1 t = avio_rb32(pb);
6685 1 b = avio_rb32(pb);
6686 1 l = avio_rb32(pb);
6687 1 r = avio_rb32(pb);
6688
6689
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) {
6690 av_log(c->fc, AV_LOG_ERROR,
6691 "Invalid bounding rectangle coordinates "
6692 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
6693 return AVERROR_INVALIDDATA;
6694 }
6695
6696
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)
6697 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
6698 else
6699 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6700 1 break;
6701 default:
6702 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
6703 return 0;
6704 }
6705
6706 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
6708 return AVERROR(ENOMEM);
6709
6710 1 sc->spherical->projection = projection;
6711
6712 1 sc->spherical->yaw = yaw;
6713 1 sc->spherical->pitch = pitch;
6714 1 sc->spherical->roll = roll;
6715
6716 1 sc->spherical->padding = padding;
6717
6718 1 sc->spherical->bound_left = l;
6719 1 sc->spherical->bound_top = t;
6720 1 sc->spherical->bound_right = r;
6721 1 sc->spherical->bound_bottom = b;
6722
6723 1 return 0;
6724 }
6725
6726 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6727 {
6728 AVStream *st;
6729 MOVStreamContext *sc;
6730 int size;
6731 uint32_t tag;
6732 enum AVSphericalProjection projection;
6733
6734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6735 return 0;
6736
6737 3 st = c->fc->streams[c->fc->nb_streams - 1];
6738 3 sc = st->priv_data;
6739
6740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 16) {
6741 av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
6742 return AVERROR_INVALIDDATA;
6743 }
6744
6745 3 size = avio_rb32(pb);
6746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 16) {
6747 av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
6748 return AVERROR_INVALIDDATA;
6749 }
6750
6751 3 tag = avio_rl32(pb);
6752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
6753 av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: 0x%08X\n", tag);
6754 return AVERROR_INVALIDDATA;
6755 }
6756
6757 3 avio_skip(pb, 1); // version
6758 3 avio_skip(pb, 3); // flags
6759
6760 3 tag = avio_rl32(pb);
6761
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) {
6762 3 case MKTAG('r','e','c','t'):
6763 3 projection = AV_SPHERICAL_RECTILINEAR;
6764 3 break;
6765 case MKTAG('e','q','u','i'):
6766 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6767 break;
6768 case MKTAG('h','e','q','u'):
6769 projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
6770 break;
6771 case MKTAG('f','i','s','h'):
6772 projection = AV_SPHERICAL_FISHEYE;
6773 break;
6774 default:
6775 av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: 0x%08X\n", tag);
6776 return AVERROR_INVALIDDATA;
6777 }
6778
6779 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
6781 return AVERROR(ENOMEM);
6782
6783 3 sc->spherical->projection = projection;
6784
6785 3 return 0;
6786 }
6787
6788 3 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6789 {
6790 AVStream *st;
6791 MOVStreamContext *sc;
6792 3 int size, flags = 0;
6793 int64_t remaining;
6794 3 uint32_t tag, baseline = 0;
6795 3 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
6796 3 enum AVStereo3DType type = AV_STEREO3D_2D;
6797 3 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
6798 3 AVRational horizontal_disparity_adjustment = { 0, 1 };
6799
6800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6801 return 0;
6802
6803 3 st = c->fc->streams[c->fc->nb_streams - 1];
6804 3 sc = st->priv_data;
6805
6806 3 remaining = atom.size;
6807
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 while (remaining > 0) {
6808 9 size = avio_rb32(pb);
6809
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 ) {
6810 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
6811 return AVERROR_INVALIDDATA;
6812 }
6813
6814 9 tag = avio_rl32(pb);
6815
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) {
6816 3 case MKTAG('s','t','r','i'): {
6817 int has_right, has_left;
6818 uint8_t tmp;
6819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 13) {
6820 av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
6821 return AVERROR_INVALIDDATA;
6822 }
6823 3 avio_skip(pb, 1); // version
6824 3 avio_skip(pb, 3); // flags
6825
6826 3 tmp = avio_r8(pb);
6827
6828 // eye_views_reversed
6829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tmp & 8) {
6830 flags |= AV_STEREO3D_FLAG_INVERT;
6831 }
6832 // has_additional_views
6833 3 if (tmp & 4) {
6834 // skip...
6835 }
6836
6837 3 has_right = tmp & 2; // has_right_eye_view
6838 3 has_left = tmp & 1; // has_left_eye_view
6839
6840
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)
6841 3 view = AV_STEREO3D_VIEW_PACKED;
6842 else if (has_left)
6843 view = AV_STEREO3D_VIEW_LEFT;
6844 else if (has_right)
6845 view = AV_STEREO3D_VIEW_RIGHT;
6846
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)
6847 3 type = AV_STEREO3D_UNSPEC;
6848
6849 3 break;
6850 }
6851 case MKTAG('h','e','r','o'): {
6852 int tmp;
6853 if (size != 13) {
6854 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
6855 return AVERROR_INVALIDDATA;
6856 }
6857 avio_skip(pb, 1); // version
6858 avio_skip(pb, 3); // flags
6859
6860 tmp = avio_r8(pb);
6861 if (tmp == 0)
6862 primary_eye = AV_PRIMARY_EYE_NONE;
6863 else if (tmp == 1)
6864 primary_eye = AV_PRIMARY_EYE_LEFT;
6865 else if (tmp == 2)
6866 primary_eye = AV_PRIMARY_EYE_RIGHT;
6867 else
6868 av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
6869
6870 break;
6871 }
6872 3 case MKTAG('c','a','m','s'): {
6873 uint32_t subtag;
6874 int subsize;
6875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
6876 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
6877 return AVERROR_INVALIDDATA;
6878 }
6879
6880 3 subsize = avio_rb32(pb);
6881
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
6882 av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
6883 return AVERROR_INVALIDDATA;
6884 }
6885
6886 3 subtag = avio_rl32(pb);
6887
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
6888 av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got 0x%08X\n", subtag);
6889 return AVERROR_INVALIDDATA;
6890 }
6891
6892 3 avio_skip(pb, 1); // version
6893 3 avio_skip(pb, 3); // flags
6894
6895 3 baseline = avio_rb32(pb);
6896
6897 3 break;
6898 }
6899 3 case MKTAG('c','m','f','y'): {
6900 uint32_t subtag;
6901 int subsize;
6902 int32_t adjustment;
6903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
6904 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
6905 return AVERROR_INVALIDDATA;
6906 }
6907
6908 3 subsize = avio_rb32(pb);
6909
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
6910 av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
6911 return AVERROR_INVALIDDATA;
6912 }
6913
6914 3 subtag = avio_rl32(pb);
6915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
6916 av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got 0x%08X\n", subtag);
6917 return AVERROR_INVALIDDATA;
6918 }
6919
6920 3 avio_skip(pb, 1); // version
6921 3 avio_skip(pb, 3); // flags
6922
6923 3 adjustment = (int32_t) avio_rb32(pb);
6924
6925 3 horizontal_disparity_adjustment.num = (int) adjustment;
6926 3 horizontal_disparity_adjustment.den = 10000;
6927
6928 3 break;
6929 }
6930 default:
6931 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: 0x%08X\n", tag);
6932 avio_skip(pb, size - 8);
6933 break;
6934 }
6935 9 remaining -= size;
6936 }
6937
6938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
6939 av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
6940 return AVERROR_INVALIDDATA;
6941 }
6942
6943
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (type == AV_STEREO3D_2D)
6944 return 0;
6945
6946
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->stereo3d) {
6947 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6948
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
6949 return AVERROR(ENOMEM);
6950 }
6951
6952 3 sc->stereo3d->flags = flags;
6953 3 sc->stereo3d->type = type;
6954 3 sc->stereo3d->view = view;
6955 3 sc->stereo3d->primary_eye = primary_eye;
6956 3 sc->stereo3d->baseline = baseline;
6957 3 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
6958
6959 3 return 0;
6960 }
6961
6962 3 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6963 {
6964 int size;
6965 int64_t remaining;
6966 uint32_t tag;
6967
6968
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6969 return 0;
6970
6971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8) {
6972 av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
6973 return AVERROR_INVALIDDATA;
6974 }
6975
6976 3 remaining = atom.size;
6977
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 while (remaining > 0) {
6978 6 size = avio_rb32(pb);
6979
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 ) {
6980 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
6981 return AVERROR_INVALIDDATA;
6982 }
6983
6984 6 tag = avio_rl32(pb);
6985
2/3
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 switch (tag) {
6986 3 case MKTAG('p','r','o','j'): {
6987 3 MOVAtom proj = { tag, size - 8 };
6988 3 int ret = mov_read_vexu_proj(c, pb, proj);
6989
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6990 return ret;
6991 3 break;
6992 }
6993 3 case MKTAG('e','y','e','s'): {
6994 3 MOVAtom eyes = { tag, size - 8 };
6995 3 int ret = mov_read_eyes(c, pb, eyes);
6996
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6997 return ret;
6998 3 break;
6999 }
7000 default:
7001 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: 0x%08X\n", tag);
7002 avio_skip(pb, size - 8);
7003 break;
7004 }
7005 6 remaining -= size;
7006 }
7007
7008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7009 av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7010 return AVERROR_INVALIDDATA;
7011 }
7012
7013 3 return 0;
7014 }
7015
7016 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7017 {
7018 AVStream *st;
7019 MOVStreamContext *sc;
7020
7021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7022 return 0;
7023
7024 3 st = c->fc->streams[c->fc->nb_streams - 1];
7025 3 sc = st->priv_data;
7026
7027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7028 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7029 return AVERROR_INVALIDDATA;
7030 }
7031
7032
7033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7034 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7035 if (!sc->stereo3d)
7036 return AVERROR(ENOMEM);
7037 }
7038
7039 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7040 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7041
7042 3 return 0;
7043 }
7044
7045 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7046 {
7047 int ret = 0;
7048 uint8_t *buffer = av_malloc(len + 1);
7049 const char *val;
7050
7051 if (!buffer)
7052 return AVERROR(ENOMEM);
7053 buffer[len] = '\0';
7054
7055 ret = ffio_read_size(pb, buffer, len);
7056 if (ret < 0)
7057 goto out;
7058
7059 /* Check for mandatory keys and values, try to support XML as best-effort */
7060 if (!sc->spherical &&
7061 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7062 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7063 av_stristr(val, "true") &&
7064 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7065 av_stristr(val, "true") &&
7066 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7067 av_stristr(val, "equirectangular")) {
7068 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7069 if (!sc->spherical)
7070 goto out;
7071
7072 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7073
7074 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7075 enum AVStereo3DType mode;
7076
7077 if (av_stristr(buffer, "left-right"))
7078 mode = AV_STEREO3D_SIDEBYSIDE;
7079 else if (av_stristr(buffer, "top-bottom"))
7080 mode = AV_STEREO3D_TOPBOTTOM;
7081 else
7082 mode = AV_STEREO3D_2D;
7083
7084 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7085 if (!sc->stereo3d)
7086 goto out;
7087
7088 sc->stereo3d->type = mode;
7089 }
7090
7091 /* orientation */
7092 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7093 if (val)
7094 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7095 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7096 if (val)
7097 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7098 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7099 if (val)
7100 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7101 }
7102
7103 out:
7104 av_free(buffer);
7105 return ret;
7106 }
7107
7108 15 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7109 {
7110 AVStream *st;
7111 MOVStreamContext *sc;
7112 int64_t ret;
7113 AVUUID uuid;
7114 static const AVUUID uuid_isml_manifest = {
7115 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7116 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7117 };
7118 static const AVUUID uuid_xmp = {
7119 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7120 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7121 };
7122 static const AVUUID uuid_spherical = {
7123 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7124 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7125 };
7126
7127
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 if (atom.size < AV_UUID_LEN || atom.size >= FFMIN(INT_MAX, SIZE_MAX))
7128 return AVERROR_INVALIDDATA;
7129
7130
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 14 times.
15 if (c->fc->nb_streams < 1)
7131 1 return 0;
7132 14 st = c->fc->streams[c->fc->nb_streams - 1];
7133 14 sc = st->priv_data;
7134
7135 14 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0)
7137 return ret;
7138
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7139 uint8_t *buffer, *ptr;
7140 char *endptr;
7141 size_t len = atom.size - AV_UUID_LEN;
7142
7143 if (len < 4) {
7144 return AVERROR_INVALIDDATA;
7145 }
7146 ret = avio_skip(pb, 4); // zeroes
7147 len -= 4;
7148
7149 buffer = av_mallocz(len + 1);
7150 if (!buffer) {
7151 return AVERROR(ENOMEM);
7152 }
7153 ret = ffio_read_size(pb, buffer, len);
7154 if (ret < 0) {
7155 av_free(buffer);
7156 return ret;
7157 }
7158
7159 ptr = buffer;
7160 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7161 ptr += sizeof("systemBitrate=\"") - 1;
7162 c->bitrates_count++;
7163 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7164 if (!c->bitrates) {
7165 c->bitrates_count = 0;
7166 av_free(buffer);
7167 return AVERROR(ENOMEM);
7168 }
7169 errno = 0;
7170 ret = strtol(ptr, &endptr, 10);
7171 if (ret < 0 || errno || *endptr != '"') {
7172 c->bitrates[c->bitrates_count - 1] = 0;
7173 } else {
7174 c->bitrates[c->bitrates_count - 1] = ret;
7175 }
7176 }
7177
7178 av_free(buffer);
7179
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7180 uint8_t *buffer;
7181 size_t len = atom.size - AV_UUID_LEN;
7182 if (c->export_xmp) {
7183 buffer = av_mallocz(len + 1);
7184 if (!buffer) {
7185 return AVERROR(ENOMEM);
7186 }
7187 ret = ffio_read_size(pb, buffer, len);
7188 if (ret < 0) {
7189 av_free(buffer);
7190 return ret;
7191 }
7192 buffer[len] = '\0';
7193 av_dict_set(&c->fc->metadata, "xmp",
7194 buffer, AV_DICT_DONT_STRDUP_VAL);
7195 } else {
7196 // skip all uuid atom, which makes it fast for long uuid-xmp file
7197 ret = avio_skip(pb, len);
7198 if (ret < 0)
7199 return ret;
7200 }
7201
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7202 size_t len = atom.size - AV_UUID_LEN;
7203 ret = mov_parse_uuid_spherical(sc, pb, len);
7204 if (ret < 0)
7205 return ret;
7206 if (!sc->spherical)
7207 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7208 }
7209
7210 14 return 0;
7211 }
7212
7213 188 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7214 {
7215 int ret;
7216 uint8_t content[16];
7217
7218
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 96 times.
188 if (atom.size < 8)
7219 92 return 0;
7220
7221 96 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (ret < 0)
7223 return ret;
7224
7225
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 55 times.
96 if ( !c->found_moov
7226
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 23 times.
41 && !c->found_mdat
7227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 && !memcmp(content, "Anevia\x1A\x1A", 8)
7228 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7229 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7230 }
7231
7232 96 return 0;
7233 }
7234
7235 35 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7236 {
7237 35 uint32_t format = avio_rl32(pb);
7238 MOVStreamContext *sc;
7239 enum AVCodecID id;
7240 AVStream *st;
7241
7242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (c->fc->nb_streams < 1)
7243 return 0;
7244 35 st = c->fc->streams[c->fc->nb_streams - 1];
7245 35 sc = st->priv_data;
7246
7247
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 32 times.
35 switch (sc->format)
7248 {
7249 3 case MKTAG('e','n','c','v'): // encrypted video
7250 case MKTAG('e','n','c','a'): // encrypted audio
7251 3 id = mov_codec_id(st, format);
7252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7253 st->codecpar->codec_id != id) {
7254 av_log(c->fc, AV_LOG_WARNING,
7255 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7256 (char*)&format, st->codecpar->codec_id);
7257 break;
7258 }
7259
7260 3 st->codecpar->codec_id = id;
7261 3 sc->format = format;
7262 3 break;
7263
7264 32 default:
7265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (format != sc->format) {
7266 av_log(c->fc, AV_LOG_WARNING,
7267 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7268 (char*)&format, (char*)&sc->format);
7269 }
7270 32 break;
7271 }
7272
7273 35 return 0;
7274 }
7275
7276 /**
7277 * Gets the current encryption info and associated current stream context. If
7278 * we are parsing a track fragment, this will return the specific encryption
7279 * info for this fragment; otherwise this will return the global encryption
7280 * info for the current stream.
7281 */
7282 6 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7283 {
7284 MOVFragmentStreamInfo *frag_stream_info;
7285 AVStream *st;
7286 int i;
7287
7288 6 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7289
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (frag_stream_info) {
7290
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 for (i = 0; i < c->fc->nb_streams; i++) {
7291 3 *sc = c->fc->streams[i]->priv_data;
7292
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if ((*sc)->id == frag_stream_info->id) {
7293 3 st = c->fc->streams[i];
7294 3 break;
7295 }
7296 }
7297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (i == c->fc->nb_streams)
7298 return 0;
7299 3 *sc = st->priv_data;
7300
7301
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!frag_stream_info->encryption_index) {
7302 // If this stream isn't encrypted, don't create the index.
7303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!(*sc)->cenc.default_encrypted_sample)
7304 return 0;
7305 1 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!frag_stream_info->encryption_index)
7307 return AVERROR(ENOMEM);
7308 }
7309 3 *encryption_index = frag_stream_info->encryption_index;
7310 3 return 1;
7311 } else {
7312 // No current track fragment, using stream level encryption info.
7313
7314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7315 return 0;
7316 3 st = c->fc->streams[c->fc->nb_streams - 1];
7317 3 *sc = st->priv_data;
7318
7319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!(*sc)->cenc.encryption_index) {
7320 // If this stream isn't encrypted, don't create the index.
7321 if (!(*sc)->cenc.default_encrypted_sample)
7322 return 0;
7323 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7324 if (!(*sc)->cenc.encryption_index)
7325 return AVERROR(ENOMEM);
7326 }
7327
7328 3 *encryption_index = (*sc)->cenc.encryption_index;
7329 3 return 1;
7330 }
7331 }
7332
7333 72 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7334 {
7335 int i, ret;
7336 unsigned int subsample_count;
7337 AVSubsampleEncryptionInfo *subsamples;
7338
7339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!sc->cenc.default_encrypted_sample) {
7340 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7341 return AVERROR_INVALIDDATA;
7342 }
7343
7344
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) {
7345 72 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!*sample)
7347 return AVERROR(ENOMEM);
7348 } else
7349 *sample = NULL;
7350
7351
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (sc->cenc.per_sample_iv_size != 0) {
7352
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) {
7353 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
7354 av_encryption_info_free(*sample);
7355 *sample = NULL;
7356 return ret;
7357 }
7358 }
7359
7360
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (use_subsamples) {
7361 72 subsample_count = avio_rb16(pb);
7362 72 av_free((*sample)->subsamples);
7363 72 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
7364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!(*sample)->subsamples) {
7365 av_encryption_info_free(*sample);
7366 *sample = NULL;
7367 return AVERROR(ENOMEM);
7368 }
7369
7370
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++) {
7371 72 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
7372 72 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
7373 }
7374
7375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (pb->eof_reached) {
7376 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
7377 av_encryption_info_free(*sample);
7378 *sample = NULL;
7379 return AVERROR_INVALIDDATA;
7380 }
7381 72 (*sample)->subsample_count = subsample_count;
7382 }
7383
7384 72 return 0;
7385 }
7386
7387 2 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7388 {
7389 AVEncryptionInfo **encrypted_samples;
7390 MOVEncryptionIndex *encryption_index;
7391 MOVStreamContext *sc;
7392 int use_subsamples, ret;
7393 2 unsigned int sample_count, i, alloc_size = 0;
7394
7395 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7397 return ret;
7398
7399
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7400 // This can happen if we have both saio/saiz and senc atoms.
7401 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
7402 1 return 0;
7403 }
7404
7405 1 avio_r8(pb); /* version */
7406 1 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
7407
7408 1 sample_count = avio_rb32(pb);
7409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7410 return AVERROR(ENOMEM);
7411
7412
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1 times.
49 for (i = 0; i < sample_count; i++) {
7413 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7414 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7415 min_samples * sizeof(*encrypted_samples));
7416
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (encrypted_samples) {
7417 48 encryption_index->encrypted_samples = encrypted_samples;
7418
7419 48 ret = mov_read_sample_encryption_info(
7420 48 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
7421 } else {
7422 ret = AVERROR(ENOMEM);
7423 }
7424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (pb->eof_reached) {
7425 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
7426 if (ret >= 0)
7427 av_encryption_info_free(encryption_index->encrypted_samples[i]);
7428 ret = AVERROR_INVALIDDATA;
7429 }
7430
7431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0) {
7432 for (; i > 0; i--)
7433 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7434 av_freep(&encryption_index->encrypted_samples);
7435 return ret;
7436 }
7437 }
7438 1 encryption_index->nb_encrypted_samples = sample_count;
7439
7440 1 return 0;
7441 }
7442
7443 1 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
7444 {
7445 AVEncryptionInfo **sample, **encrypted_samples;
7446 int64_t prev_pos;
7447 size_t sample_count, sample_info_size, i;
7448 1 int ret = 0;
7449 1 unsigned int alloc_size = 0;
7450
7451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->nb_encrypted_samples)
7452 return 0;
7453 1 sample_count = encryption_index->auxiliary_info_sample_count;
7454
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count != 1) {
7455 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
7456 return AVERROR_PATCHWELCOME;
7457 }
7458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7459 return AVERROR(ENOMEM);
7460
7461 1 prev_pos = avio_tell(pb);
7462
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
7463
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]) {
7464 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
7465 goto finish;
7466 }
7467
7468
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++) {
7469 24 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7470 24 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7471 min_samples * sizeof(*encrypted_samples));
7472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!encrypted_samples) {
7473 ret = AVERROR(ENOMEM);
7474 goto finish;
7475 }
7476 24 encryption_index->encrypted_samples = encrypted_samples;
7477
7478 24 sample = &encryption_index->encrypted_samples[i];
7479 48 sample_info_size = encryption_index->auxiliary_info_default_size
7480 24 ? encryption_index->auxiliary_info_default_size
7481
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 : encryption_index->auxiliary_info_sizes[i];
7482
7483 24 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
7484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (ret < 0)
7485 goto finish;
7486 }
7487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7488 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
7489 ret = AVERROR_INVALIDDATA;
7490 } else {
7491 1 encryption_index->nb_encrypted_samples = sample_count;
7492 }
7493
7494 1 finish:
7495 1 avio_seek(pb, prev_pos, SEEK_SET);
7496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
7497 for (; i > 0; i--) {
7498 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7499 }
7500 av_freep(&encryption_index->encrypted_samples);
7501 }
7502 1 return ret;
7503 }
7504
7505 2 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7506 {
7507 MOVEncryptionIndex *encryption_index;
7508 MOVStreamContext *sc;
7509 int ret;
7510 unsigned int sample_count, aux_info_type, aux_info_param;
7511
7512 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7514 return ret;
7515
7516
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7517 // This can happen if we have both saio/saiz and senc atoms.
7518 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
7519 1 return 0;
7520 }
7521
7522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_sample_count) {
7523 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
7524 return AVERROR_INVALIDDATA;
7525 }
7526
7527 1 avio_r8(pb); /* version */
7528
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7529 aux_info_type = avio_rb32(pb);
7530 aux_info_param = avio_rb32(pb);
7531 if (sc->cenc.default_encrypted_sample) {
7532 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7533 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
7534 return 0;
7535 }
7536 if (aux_info_param != 0) {
7537 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
7538 return 0;
7539 }
7540 } else {
7541 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7542 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7543 aux_info_type == MKBETAG('c','e','n','s') ||
7544 aux_info_type == MKBETAG('c','b','c','1') ||
7545 aux_info_type == MKBETAG('c','b','c','s')) &&
7546 aux_info_param == 0) {
7547 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
7548 return AVERROR_INVALIDDATA;
7549 } else {
7550 return 0;
7551 }
7552 }
7553
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7554 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7555 return 0;
7556 }
7557
7558 1 encryption_index->auxiliary_info_default_size = avio_r8(pb);
7559 1 sample_count = avio_rb32(pb);
7560
7561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_default_size == 0) {
7562 if (sample_count == 0)
7563 return AVERROR_INVALIDDATA;
7564
7565 encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
7566 if (!encryption_index->auxiliary_info_sizes)
7567 return AVERROR(ENOMEM);
7568
7569 ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
7570 if (ret != sample_count) {
7571 av_freep(&encryption_index->auxiliary_info_sizes);
7572
7573 if (ret >= 0)
7574 ret = AVERROR_INVALIDDATA;
7575 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
7576 av_err2str(ret));
7577 return ret;
7578 }
7579 }
7580 1 encryption_index->auxiliary_info_sample_count = sample_count;
7581
7582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7583 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7584 }
7585
7586 1 return 0;
7587 }
7588
7589 2 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7590 {
7591 uint64_t *auxiliary_offsets;
7592 MOVEncryptionIndex *encryption_index;
7593 MOVStreamContext *sc;
7594 int i, ret;
7595 unsigned int version, entry_count, aux_info_type, aux_info_param;
7596 2 unsigned int alloc_size = 0;
7597
7598 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7600 return ret;
7601
7602
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7603 // This can happen if we have both saio/saiz and senc atoms.
7604 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
7605 1 return 0;
7606 }
7607
7608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7609 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
7610 return AVERROR_INVALIDDATA;
7611 }
7612
7613 1 version = avio_r8(pb); /* version */
7614
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7615 aux_info_type = avio_rb32(pb);
7616 aux_info_param = avio_rb32(pb);
7617 if (sc->cenc.default_encrypted_sample) {
7618 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7619 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
7620 return 0;
7621 }
7622 if (aux_info_param != 0) {
7623 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
7624 return 0;
7625 }
7626 } else {
7627 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7628 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7629 aux_info_type == MKBETAG('c','e','n','s') ||
7630 aux_info_type == MKBETAG('c','b','c','1') ||
7631 aux_info_type == MKBETAG('c','b','c','s')) &&
7632 aux_info_param == 0) {
7633 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
7634 return AVERROR_INVALIDDATA;
7635 } else {
7636 return 0;
7637 }
7638 }
7639
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7640 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7641 return 0;
7642 }
7643
7644 1 entry_count = avio_rb32(pb);
7645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
7646 return AVERROR(ENOMEM);
7647
7648
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++) {
7649
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);
7650 1 auxiliary_offsets = av_fast_realloc(
7651 1 encryption_index->auxiliary_offsets, &alloc_size,
7652 min_offsets * sizeof(*auxiliary_offsets));
7653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!auxiliary_offsets) {
7654 av_freep(&encryption_index->auxiliary_offsets);
7655 return AVERROR(ENOMEM);
7656 }
7657 1 encryption_index->auxiliary_offsets = auxiliary_offsets;
7658
7659
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (version == 0) {
7660 1 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
7661 } else {
7662 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
7663 }
7664
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (c->frag_index.current >= 0) {
7665 1 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
7666 }
7667 }
7668
7669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7670 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
7671 av_freep(&encryption_index->auxiliary_offsets);
7672 return AVERROR_INVALIDDATA;
7673 }
7674
7675 1 encryption_index->auxiliary_offsets_count = entry_count;
7676
7677
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (encryption_index->auxiliary_info_sample_count) {
7678 1 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7679 }
7680
7681 return 0;
7682 }
7683
7684 2 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7685 {
7686 AVEncryptionInitInfo *info, *old_init_info;
7687 uint8_t **key_ids;
7688 AVStream *st;
7689 const AVPacketSideData *old_side_data;
7690 uint8_t *side_data, *extra_data;
7691 size_t side_data_size;
7692 2 int ret = 0;
7693 2 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
7694
7695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
7696 return 0;
7697 2 st = c->fc->streams[c->fc->nb_streams-1];
7698
7699 2 version = avio_r8(pb); /* version */
7700 2 avio_rb24(pb); /* flags */
7701
7702 2 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
7703 /* key_id_size */ 16, /* data_size */ 0);
7704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info)
7705 return AVERROR(ENOMEM);
7706
7707
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
7708 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
7709 goto finish;
7710 }
7711
7712
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version > 0) {
7713 2 kid_count = avio_rb32(pb);
7714
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
7715 ret = AVERROR(ENOMEM);
7716 goto finish;
7717 }
7718
7719
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++) {
7720 2 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
7721 2 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
7722 min_kid_count * sizeof(*key_ids));
7723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!key_ids) {
7724 ret = AVERROR(ENOMEM);
7725 goto finish;
7726 }
7727 2 info->key_ids = key_ids;
7728
7729 2 info->key_ids[i] = av_mallocz(16);
7730
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info->key_ids[i]) {
7731 ret = AVERROR(ENOMEM);
7732 goto finish;
7733 }
7734 2 info->num_key_ids = i + 1;
7735
7736
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
7737 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
7738 goto finish;
7739 }
7740 }
7741
7742
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
7743 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
7744 ret = AVERROR_INVALIDDATA;
7745 goto finish;
7746 }
7747 }
7748
7749 2 extra_data_size = avio_rb32(pb);
7750 2 extra_data = av_malloc(extra_data_size);
7751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!extra_data) {
7752 ret = AVERROR(ENOMEM);
7753 goto finish;
7754 }
7755 2 ret = avio_read(pb, extra_data, extra_data_size);
7756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != extra_data_size) {
7757 av_free(extra_data);
7758
7759 if (ret >= 0)
7760 ret = AVERROR_INVALIDDATA;
7761 goto finish;
7762 }
7763
7764 2 av_freep(&info->data); // malloc(0) may still allocate something.
7765 2 info->data = extra_data;
7766 2 info->data_size = extra_data_size;
7767
7768 // If there is existing initialization data, append to the list.
7769 2 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
7770 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
7771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (old_side_data) {
7772 old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
7773 if (old_init_info) {
7774 // Append to the end of the list.
7775 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
7776 if (!cur->next) {
7777 cur->next = info;
7778 break;
7779 }
7780 }
7781 info = old_init_info;
7782 } else {
7783 // Assume existing side-data will be valid, so the only error we could get is OOM.
7784 ret = AVERROR(ENOMEM);
7785 goto finish;
7786 }
7787 }
7788
7789 2 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
7790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!side_data) {
7791 ret = AVERROR(ENOMEM);
7792 goto finish;
7793 }
7794
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
7795 2 &st->codecpar->nb_coded_side_data,
7796 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
7797 side_data, side_data_size, 0))
7798 av_free(side_data);
7799
7800 2 finish:
7801 2 av_encryption_init_info_free(info);
7802 2 return ret;
7803 }
7804
7805 3 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7806 {
7807 AVStream *st;
7808 MOVStreamContext *sc;
7809
7810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7811 return 0;
7812 3 st = c->fc->streams[c->fc->nb_streams-1];
7813 3 sc = st->priv_data;
7814
7815
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7816 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
7817 return AVERROR_PATCHWELCOME;
7818 }
7819
7820
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8)
7821 return AVERROR_INVALIDDATA;
7822
7823 3 avio_rb32(pb); /* version and flags */
7824
7825
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->cenc.default_encrypted_sample) {
7826 3 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7828 return AVERROR(ENOMEM);
7829 }
7830 }
7831
7832 3 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
7833 3 return 0;
7834 }
7835
7836 3 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7837 {
7838 AVStream *st;
7839 MOVStreamContext *sc;
7840 unsigned int version, pattern, is_protected, iv_size;
7841
7842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7843 return 0;
7844 3 st = c->fc->streams[c->fc->nb_streams-1];
7845 3 sc = st->priv_data;
7846
7847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7848 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
7849 return AVERROR_PATCHWELCOME;
7850 }
7851
7852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7853 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7854 if (!sc->cenc.default_encrypted_sample) {
7855 return AVERROR(ENOMEM);
7856 }
7857 }
7858
7859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 20)
7860 return AVERROR_INVALIDDATA;
7861
7862 3 version = avio_r8(pb); /* version */
7863 3 avio_rb24(pb); /* flags */
7864
7865 3 avio_r8(pb); /* reserved */
7866 3 pattern = avio_r8(pb);
7867
7868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (version > 0) {
7869 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
7870 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
7871 }
7872
7873 3 is_protected = avio_r8(pb);
7874
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) {
7875 // The whole stream should be by-default encrypted.
7876 3 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
7877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.encryption_index)
7878 return AVERROR(ENOMEM);
7879 }
7880 3 sc->cenc.per_sample_iv_size = avio_r8(pb);
7881
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 &&
7882 sc->cenc.per_sample_iv_size != 16) {
7883 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
7884 return AVERROR_INVALIDDATA;
7885 }
7886
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) {
7887 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
7888 return AVERROR_INVALIDDATA;
7889 }
7890
7891
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) {
7892 1 iv_size = avio_r8(pb);
7893
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) {
7894 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
7895 return AVERROR_INVALIDDATA;
7896 }
7897
7898
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) {
7899 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
7900 return AVERROR_INVALIDDATA;
7901 }
7902 }
7903
7904 3 return 0;
7905 }
7906
7907 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7908 {
7909 AVStream *st;
7910 int last, type, size, ret;
7911 uint8_t buf[4];
7912
7913 if (c->fc->nb_streams < 1)
7914 return 0;
7915 st = c->fc->streams[c->fc->nb_streams-1];
7916
7917 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
7918 return AVERROR_INVALIDDATA;
7919
7920 /* Check FlacSpecificBox version. */
7921 if (avio_r8(pb) != 0)
7922 return AVERROR_INVALIDDATA;
7923
7924 avio_rb24(pb); /* Flags */
7925
7926 if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
7927 av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
7928 return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
7929 }
7930 flac_parse_block_header(buf, &last, &type, &size);
7931
7932 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
7933 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
7934 return AVERROR_INVALIDDATA;
7935 }
7936
7937 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
7938 if (ret < 0)
7939 return ret;
7940
7941 if (!last)
7942 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
7943
7944 return 0;
7945 }
7946
7947 146 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
7948 {
7949 int i, ret;
7950 int bytes_of_protected_data;
7951
7952
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 143 times.
146 if (!sc->cenc.aes_ctr) {
7953 /* initialize the cipher */
7954 3 sc->cenc.aes_ctr = av_aes_ctr_alloc();
7955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.aes_ctr) {
7956 return AVERROR(ENOMEM);
7957 }
7958
7959 3 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
7960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
7961 return ret;
7962 }
7963 }
7964
7965 146 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
7966
7967
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!sample->subsample_count) {
7968 /* decrypt the whole packet */
7969 48 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
7970 48 return 0;
7971 }
7972
7973
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 98 times.
196 for (i = 0; i < sample->subsample_count; i++) {
7974
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) {
7975 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
7976 return AVERROR_INVALIDDATA;
7977 }
7978
7979 /* skip the clear bytes */
7980 98 input += sample->subsamples[i].bytes_of_clear_data;
7981 98 size -= sample->subsamples[i].bytes_of_clear_data;
7982
7983 /* decrypt the encrypted bytes */
7984
7985 98 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
7986 98 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
7987
7988 98 input += bytes_of_protected_data;
7989 98 size -= bytes_of_protected_data;
7990 }
7991
7992
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (size > 0) {
7993 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
7994 return AVERROR_INVALIDDATA;
7995 }
7996
7997 98 return 0;
7998 }
7999
8000 static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8001 {
8002 int i, ret;
8003 int num_of_encrypted_blocks;
8004 uint8_t iv[16];
8005
8006 if (!sc->cenc.aes_ctx) {
8007 /* initialize the cipher */
8008 sc->cenc.aes_ctx = av_aes_alloc();
8009 if (!sc->cenc.aes_ctx) {
8010 return AVERROR(ENOMEM);
8011 }
8012
8013 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8014 if (ret < 0) {
8015 return ret;
8016 }
8017 }
8018
8019 memcpy(iv, sample->iv, 16);
8020
8021 /* whole-block full sample encryption */
8022 if (!sample->subsample_count) {
8023 /* decrypt the whole packet */
8024 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8025 return 0;
8026 }
8027
8028 for (i = 0; i < sample->subsample_count; i++) {
8029 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8030 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8031 return AVERROR_INVALIDDATA;
8032 }
8033
8034 if (sample->subsamples[i].bytes_of_protected_data % 16) {
8035 av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8036 return AVERROR_INVALIDDATA;
8037 }
8038
8039 /* skip the clear bytes */
8040 input += sample->subsamples[i].bytes_of_clear_data;
8041 size -= sample->subsamples[i].bytes_of_clear_data;
8042
8043 /* decrypt the encrypted bytes */
8044 num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8045 if (num_of_encrypted_blocks > 0) {
8046 av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8047 }
8048 input += sample->subsamples[i].bytes_of_protected_data;
8049 size -= sample->subsamples[i].bytes_of_protected_data;
8050 }
8051
8052 if (size > 0) {
8053 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8054 return AVERROR_INVALIDDATA;
8055 }
8056
8057 return 0;
8058 }
8059
8060 static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8061 {
8062 int i, ret, rem_bytes;
8063 uint8_t *data;
8064
8065 if (!sc->cenc.aes_ctr) {
8066 /* initialize the cipher */
8067 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8068 if (!sc->cenc.aes_ctr) {
8069 return AVERROR(ENOMEM);
8070 }
8071
8072 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
8073 if (ret < 0) {
8074 return ret;
8075 }
8076 }
8077
8078 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8079
8080 /* whole-block full sample encryption */
8081 if (!sample->subsample_count) {
8082 /* decrypt the whole packet */
8083 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8084 return 0;
8085 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8086 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8087 return AVERROR_INVALIDDATA;
8088 }
8089
8090 for (i = 0; i < sample->subsample_count; i++) {
8091 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8092 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8093 return AVERROR_INVALIDDATA;
8094 }
8095
8096 /* skip the clear bytes */
8097 input += sample->subsamples[i].bytes_of_clear_data;
8098 size -= sample->subsamples[i].bytes_of_clear_data;
8099
8100 /* decrypt the encrypted bytes */
8101 data = input;
8102 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8103 while (rem_bytes > 0) {
8104 if (rem_bytes < 16*sample->crypt_byte_block) {
8105 break;
8106 }
8107 av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8108 data += 16*sample->crypt_byte_block;
8109 rem_bytes -= 16*sample->crypt_byte_block;
8110 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8111 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8112 }
8113 input += sample->subsamples[i].bytes_of_protected_data;
8114 size -= sample->subsamples[i].bytes_of_protected_data;
8115 }
8116
8117 if (size > 0) {
8118 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8119 return AVERROR_INVALIDDATA;
8120 }
8121
8122 return 0;
8123 }
8124
8125 static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8126 {
8127 int i, ret, rem_bytes;
8128 uint8_t iv[16];
8129 uint8_t *data;
8130
8131 if (!sc->cenc.aes_ctx) {
8132 /* initialize the cipher */
8133 sc->cenc.aes_ctx = av_aes_alloc();
8134 if (!sc->cenc.aes_ctx) {
8135 return AVERROR(ENOMEM);
8136 }
8137
8138 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8139 if (ret < 0) {
8140 return ret;
8141 }
8142 }
8143
8144 /* whole-block full sample encryption */
8145 if (!sample->subsample_count) {
8146 /* decrypt the whole packet */
8147 memcpy(iv, sample->iv, 16);
8148 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8149 return 0;
8150 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8151 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8152 return AVERROR_INVALIDDATA;
8153 }
8154
8155 for (i = 0; i < sample->subsample_count; i++) {
8156 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8157 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8158 return AVERROR_INVALIDDATA;
8159 }
8160
8161 /* skip the clear bytes */
8162 input += sample->subsamples[i].bytes_of_clear_data;
8163 size -= sample->subsamples[i].bytes_of_clear_data;
8164
8165 /* decrypt the encrypted bytes */
8166 memcpy(iv, sample->iv, 16);
8167 data = input;
8168 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8169 while (rem_bytes > 0) {
8170 if (rem_bytes < 16*sample->crypt_byte_block) {
8171 break;
8172 }
8173 av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8174 data += 16*sample->crypt_byte_block;
8175 rem_bytes -= 16*sample->crypt_byte_block;
8176 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8177 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8178 }
8179 input += sample->subsamples[i].bytes_of_protected_data;
8180 size -= sample->subsamples[i].bytes_of_protected_data;
8181 }
8182
8183 if (size > 0) {
8184 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8185 return AVERROR_INVALIDDATA;
8186 }
8187
8188 return 0;
8189 }
8190
8191 146 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8192 {
8193
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) {
8194 146 return cenc_scheme_decrypt(c, sc, sample, input, size);
8195 } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8196 return cbc1_scheme_decrypt(c, sc, sample, input, size);
8197 } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8198 return cens_scheme_decrypt(c, sc, sample, input, size);
8199 } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8200 return cbcs_scheme_decrypt(c, sc, sample, input, size);
8201 } else {
8202 av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8203 return AVERROR_INVALIDDATA;
8204 }
8205 }
8206
8207 96514 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8208 {
8209 96514 int current = frag_index->current;
8210
8211
2/2
✓ Branch 0 taken 95853 times.
✓ Branch 1 taken 661 times.
96514 if (!frag_index->nb_items)
8212 95853 return NULL;
8213
8214 // Check frag_index->current is the right one for pkt. It can out of sync.
8215
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) {
8216
2/2
✓ Branch 0 taken 639 times.
✓ Branch 1 taken 22 times.
661 if (frag_index->item[current].moof_offset < pkt->pos &&
8217
2/2
✓ Branch 0 taken 413 times.
✓ Branch 1 taken 226 times.
639 (current + 1 == frag_index->nb_items ||
8218
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 25 times.
413 frag_index->item[current + 1].moof_offset > pkt->pos))
8219 614 return get_frag_stream_info(frag_index, current, id);
8220 }
8221
8222
8223
2/2
✓ Branch 0 taken 3955 times.
✓ Branch 1 taken 4 times.
3959 for (int i = 0; i < frag_index->nb_items; i++) {
8224
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 3912 times.
3955 if (frag_index->item[i].moof_offset > pkt->pos)
8225 43 break;
8226 3912 current = i;
8227 }
8228 47 frag_index->current = current;
8229 47 return get_frag_stream_info(frag_index, current, id);
8230 }
8231
8232 96514 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8233 {
8234 MOVFragmentStreamInfo *frag_stream_info;
8235 MOVEncryptionIndex *encryption_index;
8236 AVEncryptionInfo *encrypted_sample;
8237 int encrypted_index, ret;
8238
8239 96514 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8240 96514 encrypted_index = current_index;
8241 96514 encryption_index = NULL;
8242
2/2
✓ Branch 0 taken 661 times.
✓ Branch 1 taken 95853 times.
96514 if (frag_stream_info) {
8243 // Note this only supports encryption info in the first sample descriptor.
8244
2/2
✓ Branch 0 taken 637 times.
✓ Branch 1 taken 24 times.
661 if (frag_stream_info->stsd_id == 1) {
8245
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 613 times.
637 if (frag_stream_info->encryption_index) {
8246 24 encrypted_index = current_index - frag_stream_info->index_base;
8247 24 encryption_index = frag_stream_info->encryption_index;
8248 } else {
8249 613 encryption_index = sc->cenc.encryption_index;
8250 }
8251 }
8252 } else {
8253 95853 encryption_index = sc->cenc.encryption_index;
8254 }
8255
8256
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 96368 times.
96514 if (encryption_index) {
8257
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_info_sample_count &&
8258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8259 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8260 return AVERROR_INVALIDDATA;
8261 }
8262
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_offsets_count &&
8263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8264 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8265 return AVERROR_INVALIDDATA;
8266 }
8267
8268 146 encrypted_sample = NULL;
8269
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!encryption_index->nb_encrypted_samples) {
8270 // Full-sample encryption with default settings.
8271 48 encrypted_sample = sc->cenc.default_encrypted_sample;
8272
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) {
8273 // Per-sample setting override.
8274 98 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (!encrypted_sample) {
8276 encrypted_sample = sc->cenc.default_encrypted_sample;
8277 }
8278 }
8279
8280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (!encrypted_sample) {
8281 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8282 return AVERROR_INVALIDDATA;
8283 }
8284
8285
1/2
✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
146 if (mov->decryption_key) {
8286 146 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
8287 } else {
8288 size_t size;
8289 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
8290 if (!side_data)
8291 return AVERROR(ENOMEM);
8292 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
8293 if (ret < 0)
8294 av_free(side_data);
8295 return ret;
8296 }
8297 }
8298
8299 96368 return 0;
8300 }
8301
8302 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8303 {
8304 const int OPUS_SEEK_PREROLL_MS = 80;
8305 int ret;
8306 AVStream *st;
8307 size_t size;
8308 uint16_t pre_skip;
8309
8310 if (c->fc->nb_streams < 1)
8311 return 0;
8312 st = c->fc->streams[c->fc->nb_streams-1];
8313
8314 if ((uint64_t)atom.size > (1<<30) || atom.size < 11)
8315 return AVERROR_INVALIDDATA;
8316
8317 /* Check OpusSpecificBox version. */
8318 if (avio_r8(pb) != 0) {
8319 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
8320 return AVERROR_INVALIDDATA;
8321 }
8322
8323 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
8324 size = atom.size + 8;
8325
8326 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
8327 return ret;
8328
8329 AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
8330 AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
8331 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
8332 avio_read(pb, st->codecpar->extradata + 9, size - 9);
8333
8334 /* OpusSpecificBox is stored in big-endian, but OpusHead is
8335 little-endian; aside from the preceeding magic and version they're
8336 otherwise currently identical. Data after output gain at offset 16
8337 doesn't need to be bytewapped. */
8338 pre_skip = AV_RB16A(st->codecpar->extradata + 10);
8339 AV_WL16A(st->codecpar->extradata + 10, pre_skip);
8340 AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
8341 AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
8342
8343 st->codecpar->initial_padding = pre_skip;
8344 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
8345 (AVRational){1, 1000},
8346 (AVRational){1, 48000});
8347
8348 return 0;
8349 }
8350
8351 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8352 {
8353 AVStream *st;
8354 unsigned format_info;
8355 int channel_assignment, channel_assignment1, channel_assignment2;
8356 int ratebits;
8357 uint64_t chmask;
8358
8359 if (c->fc->nb_streams < 1)
8360 return 0;
8361 st = c->fc->streams[c->fc->nb_streams-1];
8362
8363 if (atom.size < 10)
8364 return AVERROR_INVALIDDATA;
8365
8366 format_info = avio_rb32(pb);
8367
8368 ratebits = (format_info >> 28) & 0xF;
8369 channel_assignment1 = (format_info >> 15) & 0x1F;
8370 channel_assignment2 = format_info & 0x1FFF;
8371 if (channel_assignment2)
8372 channel_assignment = channel_assignment2;
8373 else
8374 channel_assignment = channel_assignment1;
8375
8376 st->codecpar->frame_size = 40 << (ratebits & 0x7);
8377 st->codecpar->sample_rate = mlp_samplerate(ratebits);
8378
8379 av_channel_layout_uninit(&st->codecpar->ch_layout);
8380 chmask = truehd_layout(channel_assignment);
8381 av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
8382
8383 return 0;
8384 }
8385
8386 4 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8387 {
8388 AVStream *st;
8389 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
8390 int ret;
8391 4 int64_t read_size = atom.size;
8392
8393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8394 return 0;
8395 4 st = c->fc->streams[c->fc->nb_streams-1];
8396
8397 // At most 24 bytes
8398 4 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
8399
8400
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
8401 return ret;
8402
8403 4 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
8404 }
8405
8406 3 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8407 {
8408 AVStream *st;
8409 uint8_t *buf;
8410 int ret, old_size, num_arrays;
8411
8412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
8413 return 0;
8414 3 st = c->fc->streams[c->fc->nb_streams-1];
8415
8416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata_size)
8417 // TODO: handle lhvC when present before hvcC
8418 return 0;
8419
8420
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)
8421 return AVERROR_INVALIDDATA;
8422
8423 3 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
8424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!buf)
8425 return AVERROR(ENOMEM);
8426 3 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8427
8428 3 ret = ffio_read_size(pb, buf, atom.size);
8429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8430 av_free(buf);
8431 av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
8432 return 0;
8433 }
8434
8435 3 num_arrays = buf[5];
8436 3 old_size = st->codecpar->extradata_size;
8437 3 atom.size -= 8 /* account for mov_realloc_extradata offseting */
8438 + 6 /* lhvC bytes before the arrays*/;
8439
8440 3 ret = mov_realloc_extradata(st->codecpar, atom);
8441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8442 av_free(buf);
8443 return ret;
8444 }
8445
8446 3 st->codecpar->extradata[22] += num_arrays;
8447 3 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
8448
8449 3 st->disposition |= AV_DISPOSITION_MULTILAYER;
8450
8451 3 av_free(buf);
8452 3 return 0;
8453 }
8454
8455 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8456 {
8457 4 AVFormatContext *ctx = c->fc;
8458 4 AVStream *st = NULL;
8459 AVBPrint scheme_buf, value_buf;
8460 4 int64_t scheme_str_len = 0, value_str_len = 0;
8461 4 int version, flags, ret = AVERROR_BUG;
8462 4 int64_t size = atom.size;
8463
8464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
8465 // 4 bytes for version + flags, 2x 1 byte for null
8466 return AVERROR_INVALIDDATA;
8467
8468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8469 return 0;
8470 4 st = c->fc->streams[c->fc->nb_streams-1];
8471
8472 4 version = avio_r8(pb);
8473 4 flags = avio_rb24(pb);
8474 4 size -= 4;
8475
8476
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) {
8477 av_log(ctx, AV_LOG_ERROR,
8478 "Unsupported 'kind' box with version %d, flags: %x",
8479 version, flags);
8480 return AVERROR_INVALIDDATA;
8481 }
8482
8483 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8484 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8485
8486
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,
8487 size)) < 0) {
8488 ret = scheme_str_len;
8489 goto cleanup;
8490 }
8491
8492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
8493 // we need to have another string, even if nullptr.
8494 // we check with + 1 since we expect that if size was not hit,
8495 // an additional null was read.
8496 ret = AVERROR_INVALIDDATA;
8497 goto cleanup;
8498 }
8499
8500 4 size -= scheme_str_len + 1;
8501
8502
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,
8503 size)) < 0) {
8504 ret = value_str_len;
8505 goto cleanup;
8506 }
8507
8508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
8509 // in case of no trailing null, box is not valid.
8510 ret = AVERROR_INVALIDDATA;
8511 goto cleanup;
8512 }
8513
8514 4 av_log(ctx, AV_LOG_TRACE,
8515 "%s stream %d KindBox(scheme: %s, value: %s)\n",
8516 4 av_get_media_type_string(st->codecpar->codec_type),
8517 st->index,
8518 scheme_buf.str, value_buf.str);
8519
8520
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++) {
8521 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
8522
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
8523 continue;
8524
8525
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
8526 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
8527
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
8528 16 continue;
8529
8530 4 st->disposition |= value_map.disposition;
8531 }
8532 }
8533
8534 4 ret = 0;
8535
8536 4 cleanup:
8537
8538 4 av_bprint_finalize(&scheme_buf, NULL);
8539 4 av_bprint_finalize(&value_buf, NULL);
8540
8541 4 return ret;
8542 }
8543
8544 static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8545 {
8546 AVStream *st;
8547 AVChannelLayout ch_layout = { 0 };
8548 int ret, i, version, type;
8549 int ambisonic_order, channel_order, normalization, channel_count;
8550 int ambi_channels, non_diegetic_channels;
8551
8552 if (c->fc->nb_streams < 1)
8553 return 0;
8554
8555 st = c->fc->streams[c->fc->nb_streams - 1];
8556
8557 if (atom.size < 16) {
8558 av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
8559 return AVERROR_INVALIDDATA;
8560 }
8561
8562 version = avio_r8(pb);
8563 if (version) {
8564 av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
8565 return 0;
8566 }
8567
8568 type = avio_r8(pb);
8569 if (type & 0x7f) {
8570 av_log(c->fc, AV_LOG_WARNING,
8571 "Unsupported ambisonic type %d\n", type & 0x7f);
8572 return 0;
8573 }
8574 non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
8575
8576 ambisonic_order = avio_rb32(pb);
8577
8578 channel_order = avio_r8(pb);
8579 if (channel_order) {
8580 av_log(c->fc, AV_LOG_WARNING,
8581 "Unsupported channel_order %d\n", channel_order);
8582 return 0;
8583 }
8584
8585 normalization = avio_r8(pb);
8586 if (normalization) {
8587 av_log(c->fc, AV_LOG_WARNING,
8588 "Unsupported normalization %d\n", normalization);
8589 return 0;
8590 }
8591
8592 channel_count = avio_rb32(pb);
8593 if (ambisonic_order < 0 || ambisonic_order > 31 ||
8594 channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
8595 non_diegetic_channels)) {
8596 av_log(c->fc, AV_LOG_ERROR,
8597 "Invalid number of channels (%d / %d)\n",
8598 channel_count, ambisonic_order);
8599 return 0;
8600 }
8601 ambi_channels = channel_count - non_diegetic_channels;
8602
8603 ret = av_channel_layout_custom_init(&ch_layout, channel_count);
8604 if (ret < 0)
8605 return 0;
8606
8607 for (i = 0; i < channel_count; i++) {
8608 unsigned channel = avio_rb32(pb);
8609
8610 if (channel >= channel_count) {
8611 av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
8612 channel, ambisonic_order);
8613 av_channel_layout_uninit(&ch_layout);
8614 return 0;
8615 }
8616 if (channel >= ambi_channels)
8617 ch_layout.u.map[i].id = channel - ambi_channels;
8618 else
8619 ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
8620 }
8621
8622 ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
8623 if (ret < 0) {
8624 av_channel_layout_uninit(&ch_layout);
8625 return 0;
8626 }
8627
8628 av_channel_layout_uninit(&st->codecpar->ch_layout);
8629 st->codecpar->ch_layout = ch_layout;
8630
8631 return 0;
8632 }
8633
8634 static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8635 {
8636 AVStream *st;
8637 int version;
8638
8639 if (c->fc->nb_streams < 1)
8640 return 0;
8641
8642 st = c->fc->streams[c->fc->nb_streams - 1];
8643
8644 if (atom.size < 5) {
8645 av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
8646 return AVERROR_INVALIDDATA;
8647 }
8648
8649 version = avio_r8(pb);
8650 if (version) {
8651 av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
8652 return 0;
8653 }
8654
8655 st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
8656
8657 return 0;
8658 }
8659
8660 90 static int rb_size(AVIOContext *pb, int64_t *value, int size)
8661 {
8662
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 89 times.
90 if (size == 0)
8663 1 *value = 0;
8664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
89 else if (size == 1)
8665 *value = avio_r8(pb);
8666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
89 else if (size == 2)
8667 *value = avio_rb16(pb);
8668
1/2
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
89 else if (size == 4)
8669 89 *value = avio_rb32(pb);
8670 else if (size == 8) {
8671 *value = avio_rb64(pb);
8672 if (*value < 0)
8673 return -1;
8674 } else
8675 return -1;
8676 90 return size;
8677 }
8678
8679 12 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8680 {
8681 12 avio_rb32(pb); // version & flags.
8682 12 c->primary_item_id = avio_rb16(pb);
8683 12 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
8684 12 return atom.size;
8685 }
8686
8687 6 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8688 {
8689 6 c->idat_offset = avio_tell(pb);
8690 6 return 0;
8691 }
8692
8693 12 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8694 {
8695 HEIFItem **heif_item;
8696 int version, offset_size, length_size, base_offset_size, index_size;
8697 int item_count, extent_count;
8698 int64_t base_offset, extent_offset, extent_length;
8699 uint8_t value;
8700
8701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->found_iloc) {
8702 av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
8703 return 0;
8704 }
8705
8706 12 version = avio_r8(pb);
8707 12 avio_rb24(pb); // flags.
8708
8709 12 value = avio_r8(pb);
8710 12 offset_size = (value >> 4) & 0xF;
8711 12 length_size = value & 0xF;
8712 12 value = avio_r8(pb);
8713 12 base_offset_size = (value >> 4) & 0xF;
8714
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 index_size = !version ? 0 : (value & 0xF);
8715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (index_size) {
8716 avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
8717 return AVERROR_PATCHWELCOME;
8718 }
8719
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8720
8721 12 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
8722
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!heif_item)
8723 return AVERROR(ENOMEM);
8724 12 c->heif_item = heif_item;
8725
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (item_count > c->nb_heif_item)
8726 12 memset(&c->heif_item[c->nb_heif_item], 0,
8727 12 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
8728 12 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
8729
8730 12 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
8731
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 for (int i = 0; i < item_count; i++) {
8732 30 HEIFItem *item = c->heif_item[i];
8733
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8734
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
8735
8736
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (avio_feof(pb))
8737 return AVERROR_INVALIDDATA;
8738
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (offset_type > 1) {
8739 avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
8740 return AVERROR_PATCHWELCOME;
8741 }
8742
8743 30 avio_rb16(pb); // data_reference_index.
8744
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (rb_size(pb, &base_offset, base_offset_size) < 0)
8745 return AVERROR_INVALIDDATA;
8746 30 extent_count = avio_rb16(pb);
8747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (extent_count > 1) {
8748 // For still AVIF images, we only support one extent item.
8749 avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
8750 return AVERROR_PATCHWELCOME;
8751 }
8752
8753
2/4
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
✗ Branch 4 not taken.
60 if (rb_size(pb, &extent_offset, offset_size) < 0 ||
8754 30 rb_size(pb, &extent_length, length_size) < 0 ||
8755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 base_offset > INT64_MAX - extent_offset)
8756 return AVERROR_INVALIDDATA;
8757
8758
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if (!item)
8759 30 item = c->heif_item[i] = av_mallocz(sizeof(*item));
8760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!item)
8761 return AVERROR(ENOMEM);
8762
8763 30 item->item_id = item_id;
8764
8765
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 24 times.
30 if (offset_type == 1)
8766 6 item->is_idat_relative = 1;
8767 30 item->extent_length = extent_length;
8768 30 item->extent_offset = base_offset + extent_offset;
8769 30 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, offset_type %d, "
8770 "extent_offset %"PRId64", extent_length %"PRId64"\n",
8771 i, offset_type, item->extent_offset, item->extent_length);
8772 }
8773
8774 12 c->found_iloc = 1;
8775 12 return atom.size;
8776 }
8777
8778 30 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom, int idx)
8779 {
8780 HEIFItem *item;
8781 AVBPrint item_name;
8782 30 int64_t size = atom.size;
8783 uint32_t item_type;
8784 int item_id;
8785 int version, ret;
8786
8787 30 version = avio_r8(pb);
8788 30 avio_rb24(pb); // flags.
8789 30 size -= 4;
8790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (size < 0)
8791 return AVERROR_INVALIDDATA;
8792
8793
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (version < 2) {
8794 avpriv_report_missing_feature(c->fc, "infe version < 2");
8795 avio_skip(pb, size);
8796 return 1;
8797 }
8798
8799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
8800 30 avio_rb16(pb); // item_protection_index
8801 30 item_type = avio_rl32(pb);
8802 30 size -= 8;
8803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (size < 1)
8804 return AVERROR_INVALIDDATA;
8805
8806 30 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
8807 30 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
8808
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (ret < 0) {
8809 av_bprint_finalize(&item_name, NULL);
8810 return ret;
8811 }
8812
8813 30 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
8814 30 item_id, av_fourcc2str(item_type), item_name.str);
8815
8816 30 size -= ret + 1;
8817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (size > 0)
8818 avio_skip(pb, size);
8819
8820 30 item = c->heif_item[idx];
8821
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!item)
8822 item = c->heif_item[idx] = av_mallocz(sizeof(*item));
8823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!item)
8824 return AVERROR(ENOMEM);
8825
8826
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 1 times.
30 if (ret)
8827 29 av_bprint_finalize(&item_name, &c->heif_item[idx]->name);
8828 30 c->heif_item[idx]->item_id = item_id;
8829 30 c->heif_item[idx]->type = item_type;
8830
8831
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 7 times.
30 switch (item_type) {
8832 23 case MKTAG('a','v','0','1'):
8833 case MKTAG('h','v','c','1'):
8834 23 ret = heif_add_stream(c, c->heif_item[idx]);
8835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (ret < 0)
8836 return ret;
8837 23 break;
8838 }
8839
8840 30 return 0;
8841 }
8842
8843 12 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8844 {
8845 HEIFItem **heif_item;
8846 int entry_count;
8847 12 int version, got_stream = 0, ret, i;
8848
8849
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->found_iinf) {
8850 av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
8851 return 0;
8852 }
8853
8854 12 version = avio_r8(pb);
8855 12 avio_rb24(pb); // flags.
8856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
8857
8858 12 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
8859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!heif_item)
8860 return AVERROR(ENOMEM);
8861 12 c->heif_item = heif_item;
8862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (entry_count > c->nb_heif_item)
8863 memset(&c->heif_item[c->nb_heif_item], 0,
8864 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
8865 12 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
8866
8867
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 for (i = 0; i < entry_count; i++) {
8868 MOVAtom infe;
8869
8870 30 infe.size = avio_rb32(pb) - 8;
8871 30 infe.type = avio_rl32(pb);
8872
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (avio_feof(pb)) {
8873 ret = AVERROR_INVALIDDATA;
8874 goto fail;
8875 }
8876 30 ret = mov_read_infe(c, pb, infe, i);
8877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (ret < 0)
8878 goto fail;
8879
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if (!ret)
8880 30 got_stream = 1;
8881 }
8882
8883 12 c->found_iinf = got_stream;
8884 12 return 0;
8885 fail:
8886 for (; i >= 0; i--) {
8887 HEIFItem *item = c->heif_item[i];
8888
8889 if (!item)
8890 continue;
8891
8892 av_freep(&item->name);
8893 if (!item->st)
8894 continue;
8895
8896 mov_free_stream_context(c->fc, item->st);
8897 ff_remove_stream(c->fc, item->st);
8898 item->st = NULL;
8899 }
8900 return ret;
8901 }
8902
8903 6 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
8904 {
8905 6 HEIFItem *item = NULL;
8906 HEIFGrid *grid;
8907 int entries, i;
8908
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8909
8910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 for (int i = 0; i < c->nb_heif_grid; i++) {
8911 if (c->heif_grid[i].item->item_id == from_item_id) {
8912 av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
8913 "referencing the same Derived Image item\n");
8914 return AVERROR_INVALIDDATA;
8915 }
8916 }
8917
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 for (int i = 0; i < c->nb_heif_item; i++) {
8918
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)
8919 14 continue;
8920 6 item = c->heif_item[i];
8921
8922
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 switch (item->type) {
8923 6 case MKTAG('g','r','i','d'):
8924 case MKTAG('i','o','v','l'):
8925 6 break;
8926 default:
8927 avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
8928 av_fourcc2str(item->type));
8929 return 0;
8930 }
8931 6 break;
8932 }
8933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!item) {
8934 av_log(c->fc, AV_LOG_ERROR, "Missing grid information\n");
8935 return AVERROR_INVALIDDATA;
8936 }
8937
8938 6 grid = av_realloc_array(c->heif_grid, c->nb_heif_grid + 1U,
8939 sizeof(*c->heif_grid));
8940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!grid)
8941 return AVERROR(ENOMEM);
8942 6 c->heif_grid = grid;
8943 6 grid = &grid[c->nb_heif_grid++];
8944
8945 6 entries = avio_rb16(pb);
8946 6 grid->tile_id_list = av_malloc_array(entries, sizeof(*grid->tile_id_list));
8947 6 grid->tile_idx_list = av_calloc(entries, sizeof(*grid->tile_idx_list));
8948 6 grid->tile_item_list = av_calloc(entries, sizeof(*grid->tile_item_list));
8949
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)
8950 return AVERROR(ENOMEM);
8951 /* 'to' item ids */
8952
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (i = 0; i < entries; i++)
8953
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 grid->tile_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
8954 6 grid->nb_tiles = entries;
8955 6 grid->item = item;
8956
8957 6 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
8958 from_item_id, entries);
8959
8960 6 return 0;
8961 }
8962
8963 2 static int mov_read_iref_thmb(MOVContext *c, AVIOContext *pb, int version)
8964 {
8965 int entries;
8966
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 int to_item_id, from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8967
8968 2 entries = avio_rb16(pb);
8969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (entries > 1) {
8970 avpriv_request_sample(c->fc, "thmb in iref referencing several items");
8971 return AVERROR_PATCHWELCOME;
8972 }
8973 /* 'to' item ids */
8974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 to_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8975
8976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (to_item_id != c->primary_item_id)
8977 return 0;
8978
8979 2 c->thmb_item_id = from_item_id;
8980
8981 2 av_log(c->fc, AV_LOG_TRACE, "thmb: from_item_id %d, entries %d\n",
8982 from_item_id, entries);
8983
8984 2 return 0;
8985 }
8986
8987 8 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8988 {
8989 8 int version = avio_r8(pb);
8990 8 avio_rb24(pb); // flags
8991 8 atom.size -= 4;
8992
8993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (version > 1) {
8994 av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
8995 return 0;
8996 }
8997
8998
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 while (atom.size) {
8999 8 uint32_t type, size = avio_rb32(pb);
9000 8 int64_t next = avio_tell(pb);
9001
9002
3/6
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
8 if (size < 14 || next < 0 || next > INT64_MAX - size)
9003 return AVERROR_INVALIDDATA;
9004
9005 8 next += size - 4;
9006 8 type = avio_rl32(pb);
9007
2/3
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
8 switch (type) {
9008 6 case MKTAG('d','i','m','g'):
9009 6 mov_read_iref_dimg(c, pb, version);
9010 8 break;
9011 2 case MKTAG('t','h','m','b'):
9012 2 mov_read_iref_thmb(c, pb, version);
9013 2 break;
9014 default:
9015 av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
9016 av_fourcc2str(type), size);
9017 }
9018
9019 8 atom.size -= size;
9020 8 avio_seek(pb, next, SEEK_SET);
9021 }
9022 8 return 0;
9023 }
9024
9025 29 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9026 {
9027 HEIFItem *item;
9028 uint32_t width, height;
9029
9030 29 avio_r8(pb); /* version */
9031 29 avio_rb24(pb); /* flags */
9032 29 width = avio_rb32(pb);
9033 29 height = avio_rb32(pb);
9034
9035 29 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %u, height %u\n",
9036 c->cur_item_id, width, height);
9037
9038 29 item = heif_cur_item(c);
9039
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (item) {
9040 29 item->width = width;
9041 29 item->height = height;
9042 }
9043
9044 29 return 0;
9045 }
9046
9047 4 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9048 {
9049 HEIFItem *item;
9050 int angle;
9051
9052 4 angle = avio_r8(pb) & 0x3;
9053
9054 4 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
9055 c->cur_item_id, angle);
9056
9057 4 item = heif_cur_item(c);
9058
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item) {
9059 // angle * 90 specifies the angle (in anti-clockwise direction)
9060 // in units of degrees.
9061 4 item->rotation = angle * 90;
9062 }
9063
9064 4 return 0;
9065 }
9066
9067 4 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9068 {
9069 HEIFItem *item;
9070 int axis;
9071
9072 4 axis = avio_r8(pb) & 0x1;
9073
9074 4 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
9075 c->cur_item_id, axis);
9076
9077 4 item = heif_cur_item(c);
9078
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item) {
9079 4 item->hflip = axis;
9080 4 item->vflip = !axis;
9081 }
9082
9083 4 return 0;
9084 }
9085
9086 12 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9087 {
9088 typedef struct MOVAtoms {
9089 FFIOContext b;
9090 uint32_t type;
9091 int64_t size;
9092 uint8_t *data;
9093 } MOVAtoms;
9094 12 MOVAtoms *atoms = NULL;
9095 MOVAtom a;
9096 unsigned count;
9097 12 int nb_atoms = 0;
9098 int version, flags;
9099 int ret;
9100
9101 12 a.size = avio_rb32(pb);
9102 12 a.type = avio_rl32(pb);
9103
9104
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (a.size < 8 || a.type != MKTAG('i','p','c','o'))
9105 return AVERROR_INVALIDDATA;
9106
9107 12 a.size -= 8;
9108
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 12 times.
61 while (a.size >= 8) {
9109 49 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
9110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if (!ref) {
9111 ret = AVERROR(ENOMEM);
9112 goto fail;
9113 }
9114 49 ref->data = NULL;
9115 49 ref->size = avio_rb32(pb);
9116 49 ref->type = avio_rl32(pb);
9117
2/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
49 if (ref->size > a.size || ref->size < 8)
9118 break;
9119 49 ref->data = av_malloc(ref->size);
9120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if (!ref->data) {
9121 ret = AVERROR_INVALIDDATA;
9122 goto fail;
9123 }
9124 49 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
9125 49 avio_seek(pb, -8, SEEK_CUR);
9126
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
49 if (avio_read(pb, ref->data, ref->size) != ref->size) {
9127 ret = AVERROR_INVALIDDATA;
9128 goto fail;
9129 }
9130 49 ffio_init_read_context(&ref->b, ref->data, ref->size);
9131 49 a.size -= ref->size;
9132 }
9133
9134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (a.size) {
9135 ret = AVERROR_INVALIDDATA;
9136 goto fail;
9137 }
9138
9139 12 a.size = avio_rb32(pb);
9140 12 a.type = avio_rl32(pb);
9141
9142
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (a.size < 8 || a.type != MKTAG('i','p','m','a')) {
9143 ret = AVERROR_INVALIDDATA;
9144 goto fail;
9145 }
9146
9147 12 version = avio_r8(pb);
9148 12 flags = avio_rb24(pb);
9149 12 count = avio_rb32(pb);
9150
9151
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 12 times.
41 for (int i = 0; i < count; i++) {
9152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9153 29 int assoc_count = avio_r8(pb);
9154
9155
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 if (avio_feof(pb)) {
9156 ret = AVERROR_INVALIDDATA;
9157 goto fail;
9158 }
9159
9160
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 29 times.
101 for (int j = 0; j < assoc_count; j++) {
9161 MOVAtoms *ref;
9162 72 int index = avio_r8(pb) & 0x7f;
9163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (flags & 1) {
9164 index <<= 8;
9165 index |= avio_r8(pb);
9166 }
9167
2/4
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 72 times.
72 if (index > nb_atoms || index <= 0) {
9168 ret = AVERROR_INVALIDDATA;
9169 goto fail;
9170 }
9171 72 ref = &atoms[--index];
9172
9173 72 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
9174 72 index + 1, item_id, av_fourcc2str(ref->type));
9175
9176 72 c->cur_item_id = item_id;
9177
9178 72 ret = mov_read_default(c, &ref->b.pub,
9179 72 (MOVAtom) { .size = ref->size,
9180 .type = MKTAG('i','p','c','o') });
9181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (ret < 0)
9182 goto fail;
9183 72 ffio_init_read_context(&ref->b, ref->data, ref->size);
9184 }
9185 }
9186
9187 12 ret = 0;
9188 12 fail:
9189 12 c->cur_item_id = -1;
9190
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 12 times.
61 for (int i = 0; i < nb_atoms; i++)
9191 49 av_free(atoms[i].data);
9192 12 av_free(atoms);
9193
9194 12 return ret;
9195 }
9196
9197 static const MOVParseTableEntry mov_default_parse_table[] = {
9198 { MKTAG('A','C','L','R'), mov_read_aclr },
9199 { MKTAG('A','P','R','G'), mov_read_avid },
9200 { MKTAG('A','A','L','P'), mov_read_avid },
9201 { MKTAG('A','R','E','S'), mov_read_ares },
9202 { MKTAG('a','v','s','s'), mov_read_avss },
9203 { MKTAG('a','v','1','C'), mov_read_glbl },
9204 { MKTAG('c','h','p','l'), mov_read_chpl },
9205 { MKTAG('c','o','6','4'), mov_read_stco },
9206 { MKTAG('c','o','l','r'), mov_read_colr },
9207 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
9208 { MKTAG('d','i','n','f'), mov_read_default },
9209 { MKTAG('D','p','x','E'), mov_read_dpxe },
9210 { MKTAG('d','r','e','f'), mov_read_dref },
9211 { MKTAG('e','d','t','s'), mov_read_default },
9212 { MKTAG('e','l','s','t'), mov_read_elst },
9213 { MKTAG('e','n','d','a'), mov_read_enda },
9214 { MKTAG('f','i','e','l'), mov_read_fiel },
9215 { MKTAG('a','d','r','m'), mov_read_adrm },
9216 { MKTAG('f','t','y','p'), mov_read_ftyp },
9217 { MKTAG('g','l','b','l'), mov_read_glbl },
9218 { MKTAG('h','d','l','r'), mov_read_hdlr },
9219 { MKTAG('i','l','s','t'), mov_read_ilst },
9220 { MKTAG('j','p','2','h'), mov_read_jp2h },
9221 { MKTAG('m','d','a','t'), mov_read_mdat },
9222 { MKTAG('m','d','h','d'), mov_read_mdhd },
9223 { MKTAG('m','d','i','a'), mov_read_default },
9224 { MKTAG('m','e','t','a'), mov_read_meta },
9225 { MKTAG('m','i','n','f'), mov_read_default },
9226 { MKTAG('m','o','o','f'), mov_read_moof },
9227 { MKTAG('m','o','o','v'), mov_read_moov },
9228 { MKTAG('m','v','e','x'), mov_read_default },
9229 { MKTAG('m','v','h','d'), mov_read_mvhd },
9230 { MKTAG('S','M','I',' '), mov_read_svq3 },
9231 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
9232 { MKTAG('a','v','c','C'), mov_read_glbl },
9233 { MKTAG('p','a','s','p'), mov_read_pasp },
9234 { MKTAG('c','l','a','p'), mov_read_clap },
9235 { MKTAG('s','b','a','s'), mov_read_sbas },
9236 { MKTAG('s','i','d','x'), mov_read_sidx },
9237 { MKTAG('s','t','b','l'), mov_read_default },
9238 { MKTAG('s','t','c','o'), mov_read_stco },
9239 { MKTAG('s','t','p','s'), mov_read_stps },
9240 { MKTAG('s','t','r','f'), mov_read_strf },
9241 { MKTAG('s','t','s','c'), mov_read_stsc },
9242 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
9243 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
9244 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
9245 { MKTAG('s','t','t','s'), mov_read_stts },
9246 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
9247 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
9248 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
9249 { MKTAG('t','f','d','t'), mov_read_tfdt },
9250 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
9251 { MKTAG('t','r','a','k'), mov_read_trak },
9252 { MKTAG('t','r','a','f'), mov_read_default },
9253 { MKTAG('t','r','e','f'), mov_read_default },
9254 { MKTAG('t','m','c','d'), mov_read_tmcd },
9255 { MKTAG('c','h','a','p'), mov_read_chap },
9256 { MKTAG('t','r','e','x'), mov_read_trex },
9257 { MKTAG('t','r','u','n'), mov_read_trun },
9258 { MKTAG('u','d','t','a'), mov_read_default },
9259 { MKTAG('w','a','v','e'), mov_read_wave },
9260 { MKTAG('e','s','d','s'), mov_read_esds },
9261 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
9262 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
9263 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
9264 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
9265 { MKTAG('w','f','e','x'), mov_read_wfex },
9266 { MKTAG('c','m','o','v'), mov_read_cmov },
9267 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
9268 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
9269 { MKTAG('d','v','c','1'), mov_read_dvc1 },
9270 { MKTAG('s','g','p','d'), mov_read_sgpd },
9271 { MKTAG('s','b','g','p'), mov_read_sbgp },
9272 { MKTAG('h','v','c','C'), mov_read_glbl },
9273 { MKTAG('v','v','c','C'), mov_read_glbl },
9274 { MKTAG('u','u','i','d'), mov_read_uuid },
9275 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
9276 { MKTAG('f','r','e','e'), mov_read_free },
9277 { MKTAG('-','-','-','-'), mov_read_custom },
9278 { MKTAG('s','i','n','f'), mov_read_default },
9279 { MKTAG('f','r','m','a'), mov_read_frma },
9280 { MKTAG('s','e','n','c'), mov_read_senc },
9281 { MKTAG('s','a','i','z'), mov_read_saiz },
9282 { MKTAG('s','a','i','o'), mov_read_saio },
9283 { MKTAG('p','s','s','h'), mov_read_pssh },
9284 { MKTAG('s','c','h','m'), mov_read_schm },
9285 { MKTAG('s','c','h','i'), mov_read_default },
9286 { MKTAG('t','e','n','c'), mov_read_tenc },
9287 { MKTAG('d','f','L','a'), mov_read_dfla },
9288 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
9289 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
9290 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
9291 { MKTAG('h','f','o','v'), mov_read_hfov },
9292 { MKTAG('d','O','p','s'), mov_read_dops },
9293 { MKTAG('d','m','l','p'), mov_read_dmlp },
9294 { MKTAG('S','m','D','m'), mov_read_smdm },
9295 { MKTAG('C','o','L','L'), mov_read_coll },
9296 { MKTAG('v','p','c','C'), mov_read_vpcc },
9297 { MKTAG('m','d','c','v'), mov_read_mdcv },
9298 { MKTAG('c','l','l','i'), mov_read_clli },
9299 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
9300 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
9301 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
9302 { MKTAG('k','i','n','d'), mov_read_kind },
9303 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
9304 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
9305 { MKTAG('i','l','o','c'), mov_read_iloc },
9306 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
9307 { MKTAG('p','i','t','m'), mov_read_pitm },
9308 { MKTAG('e','v','c','C'), mov_read_glbl },
9309 { MKTAG('i','d','a','t'), mov_read_idat },
9310 { MKTAG('i','m','i','r'), mov_read_imir },
9311 { MKTAG('i','r','e','f'), mov_read_iref },
9312 { MKTAG('i','s','p','e'), mov_read_ispe },
9313 { MKTAG('i','r','o','t'), mov_read_irot },
9314 { MKTAG('i','p','r','p'), mov_read_iprp },
9315 { MKTAG('i','i','n','f'), mov_read_iinf },
9316 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
9317 { MKTAG('l','h','v','C'), mov_read_lhvc },
9318 { MKTAG('l','v','c','C'), mov_read_glbl },
9319 #if CONFIG_IAMFDEC
9320 { MKTAG('i','a','c','b'), mov_read_iacb },
9321 #endif
9322 { 0, NULL }
9323 };
9324
9325 6320 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9326 {
9327 6320 int64_t total_size = 0;
9328 MOVAtom a;
9329 int i;
9330
9331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6320 times.
6320 if (c->atom_depth > 10) {
9332 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
9333 return AVERROR_INVALIDDATA;
9334 }
9335 6320 c->atom_depth ++;
9336
9337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6320 times.
6320 if (atom.size < 0)
9338 atom.size = INT64_MAX;
9339
2/2
✓ Branch 0 taken 18123 times.
✓ Branch 1 taken 5839 times.
23962 while (total_size <= atom.size - 8) {
9340 18123 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
9341 18123 a.size = avio_rb32(pb);
9342 18123 a.type = avio_rl32(pb);
9343
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 18119 times.
18123 if (avio_feof(pb))
9344 4 break;
9345
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 17931 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
18119 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
9346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18119 times.
18119 a.type == MKTAG('h','o','o','v')) &&
9347 a.size >= 8 &&
9348 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
9349 uint32_t type;
9350 avio_skip(pb, 4);
9351 type = avio_rl32(pb);
9352 if (avio_feof(pb))
9353 break;
9354 avio_seek(pb, -8, SEEK_CUR);
9355 if (type == MKTAG('m','v','h','d') ||
9356 type == MKTAG('c','m','o','v')) {
9357 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
9358 a.type = MKTAG('m','o','o','v');
9359 }
9360 }
9361
2/2
✓ Branch 0 taken 15429 times.
✓ Branch 1 taken 2690 times.
18119 if (atom.type != MKTAG('r','o','o','t') &&
9362
2/2
✓ Branch 0 taken 14029 times.
✓ Branch 1 taken 1400 times.
15429 atom.type != MKTAG('m','o','o','v')) {
9363
1/2
✓ Branch 0 taken 14029 times.
✗ Branch 1 not taken.
14029 if (a.type == MKTAG('t','r','a','k') ||
9364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14029 times.
14029 a.type == MKTAG('m','d','a','t')) {
9365 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
9366 avio_skip(pb, -8);
9367 c->atom_depth --;
9368 477 return 0;
9369 }
9370 }
9371 18119 total_size += 8;
9372
3/4
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 18096 times.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
18119 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
9373 23 a.size = avio_rb64(pb) - 8;
9374 23 total_size += 8;
9375 }
9376 18119 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
9377 18119 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
9378
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 18114 times.
18119 if (a.size == 0) {
9379 5 a.size = atom.size - total_size + 8;
9380 }
9381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18119 times.
18119 if (a.size < 0)
9382 break;
9383 18119 a.size -= 8;
9384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18119 times.
18119 if (a.size < 0)
9385 break;
9386 18119 a.size = FFMIN(a.size, atom.size - total_size);
9387
9388
2/2
✓ Branch 0 taken 824548 times.
✓ Branch 1 taken 1841 times.
826389 for (i = 0; mov_default_parse_table[i].type; i++)
9389
2/2
✓ Branch 0 taken 16278 times.
✓ Branch 1 taken 808270 times.
824548 if (mov_default_parse_table[i].type == a.type) {
9390 16278 parse = mov_default_parse_table[i].parse;
9391 16278 break;
9392 }
9393
9394 // container is user data
9395
4/4
✓ Branch 0 taken 1841 times.
✓ Branch 1 taken 16278 times.
✓ Branch 2 taken 1667 times.
✓ Branch 3 taken 174 times.
18119 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
9396
2/2
✓ Branch 0 taken 298 times.
✓ Branch 1 taken 1369 times.
1667 atom.type == MKTAG('i','l','s','t')))
9397 472 parse = mov_read_udta_string;
9398
9399 // Supports parsing the QuickTime Metadata Keys.
9400 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
9401
4/4
✓ Branch 0 taken 1369 times.
✓ Branch 1 taken 16750 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 1358 times.
18119 if (!parse && c->found_hdlr_mdta &&
9402
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 atom.type == MKTAG('m','e','t','a') &&
9403
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 a.type == MKTAG('k','e','y','s') &&
9404
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 c->meta_keys_count == 0) {
9405 11 parse = mov_read_keys;
9406 }
9407
9408
2/2
✓ Branch 0 taken 1358 times.
✓ Branch 1 taken 16761 times.
18119 if (!parse) { /* skip leaf atoms data */
9409 1358 avio_skip(pb, a.size);
9410 } else {
9411 16761 int64_t start_pos = avio_tell(pb);
9412 int64_t left;
9413 16761 int err = parse(c, pb, a);
9414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16761 times.
16761 if (err < 0) {
9415 c->atom_depth --;
9416 return err;
9417 }
9418
5/6
✓ Branch 0 taken 3079 times.
✓ Branch 1 taken 13682 times.
✓ Branch 2 taken 2781 times.
✓ Branch 3 taken 298 times.
✓ Branch 4 taken 2781 times.
✗ Branch 5 not taken.
16761 if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos &&
9419
6/8
✓ Branch 0 taken 2781 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2781 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2773 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 469 times.
✓ Branch 7 taken 2304 times.
5554 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
9420 2773 start_pos + a.size == avio_size(pb))) {
9421
4/6
✓ Branch 0 taken 477 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 477 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 469 times.
477 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
9422 8 c->next_root_atom = start_pos + a.size;
9423 477 c->atom_depth --;
9424 477 return 0;
9425 }
9426 16284 left = a.size - avio_tell(pb) + start_pos;
9427
2/2
✓ Branch 0 taken 1304 times.
✓ Branch 1 taken 14980 times.
16284 if (left > 0) /* skip garbage at atom end */
9428 1304 avio_skip(pb, left);
9429
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14978 times.
14980 else if (left < 0) {
9430 2 av_log(c->fc, AV_LOG_WARNING,
9431 "overread end of atom '%s' by %"PRId64" bytes\n",
9432 2 av_fourcc2str(a.type), -left);
9433 2 avio_seek(pb, left, SEEK_CUR);
9434 }
9435 }
9436
9437 17642 total_size += a.size;
9438 }
9439
9440
4/4
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 5737 times.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 4 times.
5843 if (total_size < atom.size && atom.size < 0x7ffff)
9441 102 avio_skip(pb, atom.size - total_size);
9442
9443 5843 c->atom_depth --;
9444 5843 return 0;
9445 }
9446
9447 7204 static int mov_probe(const AVProbeData *p)
9448 {
9449 int64_t offset;
9450 uint32_t tag;
9451 7204 int score = 0;
9452 7204 int moov_offset = -1;
9453
9454 /* check file header */
9455 7204 offset = 0;
9456 8875 for (;;) {
9457 int64_t size;
9458 16079 int minsize = 8;
9459 /* ignore invalid offset */
9460
2/2
✓ Branch 0 taken 7204 times.
✓ Branch 1 taken 8875 times.
16079 if ((offset + 8ULL) > (unsigned int)p->buf_size)
9461 7204 break;
9462 8875 size = AV_RB32(p->buf + offset);
9463
3/4
✓ Branch 0 taken 518 times.
✓ Branch 1 taken 8357 times.
✓ Branch 2 taken 518 times.
✗ Branch 3 not taken.
8875 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
9464 518 size = AV_RB64(p->buf+offset + 8);
9465 518 minsize = 16;
9466
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 8302 times.
8357 } else if (size == 0) {
9467 55 size = p->buf_size - offset;
9468 }
9469
2/2
✓ Branch 0 taken 397 times.
✓ Branch 1 taken 8478 times.
8875 if (size < minsize) {
9470 397 offset += 4;
9471 397 continue;
9472 }
9473 8478 tag = AV_RL32(p->buf + offset + 4);
9474
5/6
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 830 times.
✓ Branch 2 taken 353 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7171 times.
8478 switch(tag) {
9475 /* check for obvious tags */
9476 123 case MKTAG('m','o','o','v'):
9477 123 moov_offset = offset + 4;
9478 953 case MKTAG('m','d','a','t'):
9479 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
9480 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
9481 case MKTAG('f','t','y','p'):
9482
2/2
✓ Branch 0 taken 433 times.
✓ Branch 1 taken 520 times.
953 if (tag == MKTAG('f','t','y','p') &&
9483
1/2
✓ Branch 0 taken 433 times.
✗ Branch 1 not taken.
433 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
9484
1/2
✓ Branch 0 taken 433 times.
✗ Branch 1 not taken.
433 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
9485
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 427 times.
433 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
9486 )) {
9487 6 score = FFMAX(score, 5);
9488 } else {
9489 947 score = AVPROBE_SCORE_MAX;
9490 }
9491 953 break;
9492 /* those are more common words, so rate then a bit less */
9493 353 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
9494 case MKTAG('w','i','d','e'):
9495 case MKTAG('f','r','e','e'):
9496 case MKTAG('j','u','n','k'):
9497 case MKTAG('p','i','c','t'):
9498 353 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
9499 353 break;
9500 case MKTAG(0x82,0x82,0x7f,0x7d):
9501 score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
9502 break;
9503 1 case MKTAG('s','k','i','p'):
9504 case MKTAG('u','u','i','d'):
9505 case MKTAG('p','r','f','l'):
9506 /* if we only find those cause probedata is too small at least rate them */
9507 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
9508 1 break;
9509 }
9510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8478 times.
8478 if (size > INT64_MAX - offset)
9511 break;
9512 8478 offset += size;
9513 }
9514
4/4
✓ Branch 0 taken 464 times.
✓ Branch 1 taken 6740 times.
✓ Branch 2 taken 123 times.
✓ Branch 3 taken 341 times.
7204 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
9515 /* moov atom in the header - we should make sure that this is not a
9516 * MOV-packed MPEG-PS */
9517 123 offset = moov_offset;
9518
9519
2/2
✓ Branch 0 taken 120608 times.
✓ Branch 1 taken 123 times.
120731 while (offset < (p->buf_size - 16)) { /* Sufficient space */
9520 /* We found an actual hdlr atom */
9521
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 120476 times.
120608 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
9522
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 111 times.
132 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
9523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
9524 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
9525 /* We found a media handler reference atom describing an
9526 * MPEG-PS-in-MOV, return a
9527 * low score to force expanding the probe window until
9528 * mpegps_probe finds what it needs */
9529 return 5;
9530 } else {
9531 /* Keep looking */
9532 120608 offset += 2;
9533 }
9534 }
9535 }
9536
9537 7204 return score;
9538 }
9539
9540 // must be done after parsing all trak because there's no order requirement
9541 2 static void mov_read_chapters(AVFormatContext *s)
9542 {
9543 2 MOVContext *mov = s->priv_data;
9544 MOVStreamContext *sc;
9545 int64_t cur_pos;
9546 int i, j;
9547 int chapter_track;
9548
9549
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
9550 2 AVStream *st = NULL;
9551 2 FFStream *sti = NULL;
9552 2 chapter_track = mov->chapter_tracks[j];
9553
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
9554 4 sc = mov->fc->streams[i]->priv_data;
9555
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
9556 2 st = s->streams[i];
9557 2 break;
9558 }
9559 }
9560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
9561 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
9562 continue;
9563 }
9564 2 sti = ffstream(st);
9565
9566 2 sc = st->priv_data;
9567 2 cur_pos = avio_tell(sc->pb);
9568
9569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
9570 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
9571 if (!st->attached_pic.data && sti->nb_index_entries) {
9572 // Retrieve the first frame, if possible
9573 AVIndexEntry *sample = &sti->index_entries[0];
9574 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9575 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
9576 goto finish;
9577 }
9578
9579 if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
9580 goto finish;
9581 }
9582 } else {
9583 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
9584 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
9585 2 st->discard = AVDISCARD_ALL;
9586
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
9587 8 AVIndexEntry *sample = &sti->index_entries[i];
9588
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;
9589 uint8_t *title;
9590 uint16_t ch;
9591 int len, title_len;
9592
9593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
9594 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
9595 end = AV_NOPTS_VALUE;
9596 }
9597
9598
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9599 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
9600 goto finish;
9601 }
9602
9603 // the first two bytes are the length of the title
9604 8 len = avio_rb16(sc->pb);
9605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
9606 continue;
9607 8 title_len = 2*len + 1;
9608
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
9609 goto finish;
9610
9611 // The samples could theoretically be in any encoding if there's an encd
9612 // atom following, but in practice are only utf-8 or utf-16, distinguished
9613 // instead by the presence of a BOM
9614
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
9615 title[0] = 0;
9616 } else {
9617 8 ch = avio_rb16(sc->pb);
9618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
9619 avio_get_str16be(sc->pb, len, title, title_len);
9620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
9621 avio_get_str16le(sc->pb, len, title, title_len);
9622 else {
9623 8 AV_WB16(title, ch);
9624
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)
9625 title[len] = 0;
9626 else
9627 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
9628 }
9629 }
9630
9631 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
9632 8 av_freep(&title);
9633 }
9634 }
9635 2 finish:
9636 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
9637 }
9638 2 }
9639
9640 19 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
9641 int64_t value, int flags)
9642 {
9643 AVTimecode tc;
9644 char buf[AV_TIMECODE_STR_SIZE];
9645 19 AVRational rate = st->avg_frame_rate;
9646 19 int ret = av_timecode_init(&tc, rate, flags, 0, s);
9647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
9648 return ret;
9649 19 av_dict_set(&st->metadata, "timecode",
9650 19 av_timecode_make_string(&tc, buf, value), 0);
9651 19 return 0;
9652 }
9653
9654 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
9655 {
9656 MOVStreamContext *sc = st->priv_data;
9657 FFStream *const sti = ffstream(st);
9658 char buf[AV_TIMECODE_STR_SIZE];
9659 int64_t cur_pos = avio_tell(sc->pb);
9660 int hh, mm, ss, ff, drop;
9661
9662 if (!sti->nb_index_entries)
9663 return -1;
9664
9665 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9666 avio_skip(s->pb, 13);
9667 hh = avio_r8(s->pb);
9668 mm = avio_r8(s->pb);
9669 ss = avio_r8(s->pb);
9670 drop = avio_r8(s->pb);
9671 ff = avio_r8(s->pb);
9672 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
9673 hh, mm, ss, drop ? ';' : ':', ff);
9674 av_dict_set(&st->metadata, "timecode", buf, 0);
9675
9676 avio_seek(sc->pb, cur_pos, SEEK_SET);
9677 return 0;
9678 }
9679
9680 19 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
9681 {
9682 19 MOVStreamContext *sc = st->priv_data;
9683 19 FFStream *const sti = ffstream(st);
9684 19 int flags = 0;
9685 19 int64_t cur_pos = avio_tell(sc->pb);
9686 int64_t value;
9687 19 AVRational tc_rate = st->avg_frame_rate;
9688 19 int tmcd_nb_frames = sc->tmcd_nb_frames;
9689 int rounded_tc_rate;
9690
9691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!sti->nb_index_entries)
9692 return -1;
9693
9694
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)
9695 return -1;
9696
9697 19 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9698 19 value = avio_rb32(s->pb);
9699
9700
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13 times.
19 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
9701
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
9702
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
9703
9704 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
9705 * not the case) and thus assume "frame number format" instead of QT one.
9706 * No sample with tmcd track can be found with a QT timecode at the moment,
9707 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
9708 * format). */
9709
9710 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
9711 * we multiply the frame number with the quotient.
9712 * See tickets #9492, #9710. */
9713 19 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
9714 /* Work around files where tmcd_nb_frames is rounded down from frame rate
9715 * instead of up. See ticket #5978. */
9716
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
9717
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
9718 10 tmcd_nb_frames = rounded_tc_rate;
9719 19 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
9720
9721 19 parse_timecode_in_framenum_format(s, st, value, flags);
9722
9723 19 avio_seek(sc->pb, cur_pos, SEEK_SET);
9724 19 return 0;
9725 }
9726
9727 1038 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
9728 int i;
9729
3/4
✓ Branch 0 taken 1038 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1034 times.
✓ Branch 3 taken 4 times.
1038 if (!index || !*index) return;
9730
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 4 times.
76 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
9731 72 av_encryption_info_free((*index)->encrypted_samples[i]);
9732 }
9733 4 av_freep(&(*index)->encrypted_samples);
9734 4 av_freep(&(*index)->auxiliary_info_sizes);
9735 4 av_freep(&(*index)->auxiliary_offsets);
9736 4 av_freep(index);
9737 }
9738
9739 671 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
9740 {
9741 671 MOVStreamContext *sc = st->priv_data;
9742
9743
3/4
✓ Branch 0 taken 671 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 631 times.
671 if (!sc || --sc->refcount) {
9744 40 st->priv_data = NULL;
9745 40 return;
9746 }
9747
9748 631 av_freep(&sc->tts_data);
9749
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 631 times.
1225 for (int i = 0; i < sc->drefs_count; i++) {
9750 594 av_freep(&sc->drefs[i].path);
9751 594 av_freep(&sc->drefs[i].dir);
9752 }
9753 631 av_freep(&sc->drefs);
9754
9755 631 sc->drefs_count = 0;
9756
9757
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 617 times.
631 if (!sc->pb_is_copied)
9758 14 ff_format_io_close(s, &sc->pb);
9759
9760 631 sc->pb = NULL;
9761 631 av_freep(&sc->chunk_offsets);
9762 631 av_freep(&sc->stsc_data);
9763 631 av_freep(&sc->sample_sizes);
9764 631 av_freep(&sc->keyframes);
9765 631 av_freep(&sc->ctts_data);
9766 631 av_freep(&sc->stts_data);
9767 631 av_freep(&sc->sdtp_data);
9768 631 av_freep(&sc->stps_data);
9769 631 av_freep(&sc->elst_data);
9770 631 av_freep(&sc->rap_group);
9771 631 av_freep(&sc->sync_group);
9772 631 av_freep(&sc->sgpd_sync);
9773 631 av_freep(&sc->sample_offsets);
9774 631 av_freep(&sc->open_key_samples);
9775 631 av_freep(&sc->display_matrix);
9776 631 av_freep(&sc->index_ranges);
9777
9778
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 37 times.
631 if (sc->extradata)
9779
2/2
✓ Branch 0 taken 605 times.
✓ Branch 1 taken 594 times.
1199 for (int i = 0; i < sc->stsd_count; i++)
9780 605 av_free(sc->extradata[i]);
9781 631 av_freep(&sc->extradata);
9782 631 av_freep(&sc->extradata_size);
9783
9784 631 mov_free_encryption_index(&sc->cenc.encryption_index);
9785 631 av_encryption_info_free(sc->cenc.default_encrypted_sample);
9786 631 av_aes_ctr_free(sc->cenc.aes_ctr);
9787
9788 631 av_freep(&sc->stereo3d);
9789 631 av_freep(&sc->spherical);
9790 631 av_freep(&sc->mastering);
9791 631 av_freep(&sc->coll);
9792 631 av_freep(&sc->ambient);
9793
9794 #if CONFIG_IAMFDEC
9795
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 621 times.
631 if (sc->iamf)
9796 10 ff_iamf_read_deinit(sc->iamf);
9797 #endif
9798 631 av_freep(&sc->iamf);
9799 }
9800
9801 493 static int mov_read_close(AVFormatContext *s)
9802 {
9803 493 MOVContext *mov = s->priv_data;
9804 int i, j;
9805
9806
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 493 times.
1164 for (i = 0; i < s->nb_streams; i++) {
9807 671 AVStream *st = s->streams[i];
9808
9809 671 mov_free_stream_context(s, st);
9810 }
9811
9812 493 av_freep(&mov->dv_demux);
9813 493 avformat_free_context(mov->dv_fctx);
9814 493 mov->dv_fctx = NULL;
9815
9816
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 482 times.
493 if (mov->meta_keys) {
9817
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i < mov->meta_keys_count; i++) {
9818 58 av_freep(&mov->meta_keys[i]);
9819 }
9820 11 av_freep(&mov->meta_keys);
9821 }
9822
9823 493 av_freep(&mov->trex_data);
9824 493 av_freep(&mov->bitrates);
9825
9826
2/2
✓ Branch 0 taken 389 times.
✓ Branch 1 taken 493 times.
882 for (i = 0; i < mov->frag_index.nb_items; i++) {
9827 389 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
9828
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++) {
9829 407 mov_free_encryption_index(&frag[j].encryption_index);
9830 }
9831 389 av_freep(&mov->frag_index.item[i].stream_info);
9832 }
9833 493 av_freep(&mov->frag_index.item);
9834
9835 493 av_freep(&mov->aes_decrypt);
9836 493 av_freep(&mov->chapter_tracks);
9837
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 493 times.
523 for (i = 0; i < mov->nb_heif_item; i++) {
9838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!mov->heif_item[i])
9839 continue;
9840 30 av_freep(&mov->heif_item[i]->name);
9841 30 av_freep(&mov->heif_item[i]->icc_profile);
9842 30 av_freep(&mov->heif_item[i]);
9843 }
9844 493 av_freep(&mov->heif_item);
9845
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 493 times.
499 for (i = 0; i < mov->nb_heif_grid; i++) {
9846 6 av_freep(&mov->heif_grid[i].tile_id_list);
9847 6 av_freep(&mov->heif_grid[i].tile_idx_list);
9848 6 av_freep(&mov->heif_grid[i].tile_item_list);
9849 }
9850 493 av_freep(&mov->heif_grid);
9851
9852 493 return 0;
9853 }
9854
9855 16 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
9856 {
9857 int i;
9858
9859
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 for (i = 0; i < s->nb_streams; i++) {
9860 24 AVStream *st = s->streams[i];
9861 24 MOVStreamContext *sc = st->priv_data;
9862
9863
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
9864
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 sc->timecode_track == tmcd_id)
9865 14 return 1;
9866 }
9867 2 return 0;
9868 }
9869
9870 /* look for a tmcd track not referenced by any video track, and export it globally */
9871 493 static void export_orphan_timecode(AVFormatContext *s)
9872 {
9873 int i;
9874
9875
2/2
✓ Branch 0 taken 668 times.
✓ Branch 1 taken 491 times.
1159 for (i = 0; i < s->nb_streams; i++) {
9876 668 AVStream *st = s->streams[i];
9877
9878
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 652 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 14 times.
684 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
9879 16 !tmcd_is_referenced(s, i + 1)) {
9880 2 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
9881
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (tcr) {
9882 2 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
9883 2 break;
9884 }
9885 }
9886 }
9887 493 }
9888
9889 static int read_tfra(MOVContext *mov, AVIOContext *f)
9890 {
9891 int version, fieldlength, i, j;
9892 int64_t pos = avio_tell(f);
9893 uint32_t size = avio_rb32(f);
9894 unsigned track_id, item_count;
9895
9896 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
9897 return 1;
9898 }
9899 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
9900
9901 version = avio_r8(f);
9902 avio_rb24(f);
9903 track_id = avio_rb32(f);
9904 fieldlength = avio_rb32(f);
9905 item_count = avio_rb32(f);
9906 for (i = 0; i < item_count; i++) {
9907 int64_t time, offset;
9908 int index;
9909 MOVFragmentStreamInfo * frag_stream_info;
9910
9911 if (avio_feof(f)) {
9912 return AVERROR_INVALIDDATA;
9913 }
9914
9915 if (version == 1) {
9916 time = avio_rb64(f);
9917 offset = avio_rb64(f);
9918 } else {
9919 time = avio_rb32(f);
9920 offset = avio_rb32(f);
9921 }
9922
9923 // The first sample of each stream in a fragment is always a random
9924 // access sample. So it's entry in the tfra can be used as the
9925 // initial PTS of the fragment.
9926 index = update_frag_index(mov, offset);
9927 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
9928 if (frag_stream_info &&
9929 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
9930 frag_stream_info->first_tfra_pts = time;
9931
9932 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
9933 avio_r8(f);
9934 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
9935 avio_r8(f);
9936 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
9937 avio_r8(f);
9938 }
9939
9940 avio_seek(f, pos + size, SEEK_SET);
9941 return 0;
9942 }
9943
9944 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
9945 {
9946 int64_t stream_size = avio_size(f);
9947 int64_t original_pos = avio_tell(f);
9948 int64_t seek_ret;
9949 int ret = -1;
9950 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
9951 ret = seek_ret;
9952 goto fail;
9953 }
9954 c->mfra_size = avio_rb32(f);
9955 c->have_read_mfra_size = 1;
9956 if (!c->mfra_size || c->mfra_size > stream_size) {
9957 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
9958 goto fail;
9959 }
9960 if ((seek_ret = avio_seek(f, -((int64_t) c->mfra_size), SEEK_CUR)) < 0) {
9961 ret = seek_ret;
9962 goto fail;
9963 }
9964 if (avio_rb32(f) != c->mfra_size) {
9965 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
9966 goto fail;
9967 }
9968 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
9969 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
9970 goto fail;
9971 }
9972 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
9973 do {
9974 ret = read_tfra(c, f);
9975 if (ret < 0)
9976 goto fail;
9977 } while (!ret);
9978 ret = 0;
9979 c->frag_index.complete = 1;
9980 fail:
9981 seek_ret = avio_seek(f, original_pos, SEEK_SET);
9982 if (seek_ret < 0) {
9983 av_log(c->fc, AV_LOG_ERROR,
9984 "failed to seek back after looking for mfra\n");
9985 ret = seek_ret;
9986 }
9987 return ret;
9988 }
9989
9990 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
9991 const HEIFItem *item)
9992 {
9993 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
9994 AV_PKT_DATA_ICC_PROFILE,
9995 item->icc_profile_size, 0);
9996 if (!sd)
9997 return AVERROR(ENOMEM);
9998
9999 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
10000
10001 return 0;
10002 }
10003
10004 4 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10005 const HEIFItem *item)
10006 {
10007 int32_t *matrix;
10008 4 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data,
10009 nb_coded_side_data,
10010 AV_PKT_DATA_DISPLAYMATRIX,
10011 9 * sizeof(*matrix), 0);
10012
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sd)
10013 return AVERROR(ENOMEM);
10014
10015 4 matrix = (int32_t*)sd->data;
10016 /* rotation is in the counter-clockwise direction whereas
10017 * av_display_rotation_set() expects its argument to be
10018 * oriented clockwise, so we need to negate it. */
10019 4 av_display_rotation_set(matrix, -item->rotation);
10020 4 av_display_matrix_flip(matrix, item->hflip, item->vflip);
10021
10022 4 return 0;
10023 }
10024
10025 2 static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid,
10026 AVStreamGroupTileGrid *tile_grid)
10027 {
10028 2 MOVContext *c = s->priv_data;
10029 2 const HEIFItem *item = grid->item;
10030 2 int64_t offset = 0, pos = avio_tell(s->pb);
10031 2 int x = 0, y = 0, i = 0;
10032 int tile_rows, tile_cols;
10033 int flags, size;
10034
10035
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10036 av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
10037 return AVERROR_PATCHWELCOME;
10038 }
10039
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (item->is_idat_relative) {
10040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!c->idat_offset) {
10041 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
10042 return AVERROR_INVALIDDATA;
10043 }
10044 2 offset = c->idat_offset;
10045 }
10046
10047 2 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10048
10049 2 avio_r8(s->pb); /* version */
10050 2 flags = avio_r8(s->pb);
10051
10052 2 tile_rows = avio_r8(s->pb) + 1;
10053 2 tile_cols = avio_r8(s->pb) + 1;
10054 /* actual width and height of output image */
10055
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);
10056
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);
10057
10058 /* ICC profile */
10059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (item->icc_profile_size) {
10060 int ret = set_icc_profile_from_item(&tile_grid->coded_side_data,
10061 &tile_grid->nb_coded_side_data, item);
10062 if (ret < 0)
10063 return ret;
10064 }
10065 /* rotation */
10066
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) {
10067 int ret = set_display_matrix_from_item(&tile_grid->coded_side_data,
10068 &tile_grid->nb_coded_side_data, item);
10069 if (ret < 0)
10070 return ret;
10071 }
10072
10073 2 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
10074 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
10075
10076 2 avio_seek(s->pb, pos, SEEK_SET);
10077
10078 2 size = tile_rows * tile_cols;
10079 2 tile_grid->nb_tiles = grid->nb_tiles;
10080
10081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tile_grid->nb_tiles != size)
10082 return AVERROR_INVALIDDATA;
10083
10084
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < tile_cols; i++)
10085 4 tile_grid->coded_width += grid->tile_item_list[i]->width;
10086
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < size; i += tile_cols)
10087 4 tile_grid->coded_height += grid->tile_item_list[i]->height;
10088
10089 2 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!tile_grid->offsets)
10091 return AVERROR(ENOMEM);
10092
10093
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 while (y < tile_grid->coded_height) {
10094 4 int left_col = i;
10095
10096
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 while (x < tile_grid->coded_width) {
10097
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (i == tile_grid->nb_tiles)
10098 return AVERROR_INVALIDDATA;
10099
10100 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10101 8 tile_grid->offsets[i].horizontal = x;
10102 8 tile_grid->offsets[i].vertical = y;
10103
10104 8 x += grid->tile_item_list[i++]->width;
10105 }
10106
10107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (x > tile_grid->coded_width) {
10108 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10109 return AVERROR_INVALIDDATA;
10110 }
10111
10112 4 x = 0;
10113 4 y += grid->tile_item_list[left_col]->height;
10114 }
10115
10116
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) {
10117 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10118 return AVERROR_INVALIDDATA;
10119 }
10120
10121 2 return 0;
10122 }
10123
10124 4 static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid,
10125 AVStreamGroupTileGrid *tile_grid)
10126 {
10127 4 MOVContext *c = s->priv_data;
10128 4 const HEIFItem *item = grid->item;
10129 uint16_t canvas_fill_value[4];
10130 4 int64_t offset = 0, pos = avio_tell(s->pb);
10131 4 int ret = 0, flags;
10132
10133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10134 av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
10135 return AVERROR_PATCHWELCOME;
10136 }
10137
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
10138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
10139 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
10140 return AVERROR_INVALIDDATA;
10141 }
10142 4 offset = c->idat_offset;
10143 }
10144
10145 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10146
10147 4 avio_r8(s->pb); /* version */
10148 4 flags = avio_r8(s->pb);
10149
10150
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10151 16 canvas_fill_value[i] = avio_rb16(s->pb);
10152 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
10153 4 canvas_fill_value[0], canvas_fill_value[1],
10154 4 canvas_fill_value[2], canvas_fill_value[3]);
10155
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10156 16 tile_grid->background[i] = canvas_fill_value[i];
10157
10158 /* actual width and height of output image */
10159 4 tile_grid->width =
10160
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);
10161 4 tile_grid->height =
10162
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);
10163
10164 /* rotation */
10165
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) {
10166 int ret = set_display_matrix_from_item(&tile_grid->coded_side_data,
10167 &tile_grid->nb_coded_side_data, item);
10168 if (ret < 0)
10169 return ret;
10170 }
10171
10172 /* ICC profile */
10173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (item->icc_profile_size) {
10174 int ret = set_icc_profile_from_item(&tile_grid->coded_side_data,
10175 &tile_grid->nb_coded_side_data, item);
10176 if (ret < 0)
10177 return ret;
10178 }
10179
10180 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
10181 tile_grid->width, tile_grid->height);
10182
10183 4 tile_grid->nb_tiles = grid->nb_tiles;
10184 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
10186 ret = AVERROR(ENOMEM);
10187 goto fail;
10188 }
10189
10190
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
10191 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10192
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);
10193
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);
10194 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
10195 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
10196 8 i, tile_grid->offsets[i].idx,
10197 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
10198 }
10199
10200 4 fail:
10201 4 avio_seek(s->pb, pos, SEEK_SET);
10202
10203 4 return ret;
10204 }
10205
10206 6 static int mov_parse_tiles(AVFormatContext *s)
10207 {
10208 6 MOVContext *mov = s->priv_data;
10209
10210
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (int i = 0; i < mov->nb_heif_grid; i++) {
10211 6 AVStreamGroup *stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
10212 AVStreamGroupTileGrid *tile_grid;
10213 6 const HEIFGrid *grid = &mov->heif_grid[i];
10214 6 int err, loop = 1;
10215
10216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!stg)
10217 return AVERROR(ENOMEM);
10218
10219 6 stg->id = grid->item->item_id;
10220 6 tile_grid = stg->params.tile_grid;
10221
10222
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (int j = 0; j < grid->nb_tiles; j++) {
10223 16 int tile_id = grid->tile_id_list[j];
10224 int k;
10225
10226
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 for (k = 0; k < mov->nb_heif_item; k++) {
10227 30 HEIFItem *item = mov->heif_item[k];
10228 AVStream *st;
10229
10230
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)
10231 14 continue;
10232 16 st = item->st;
10233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!st) {
10234 av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
10235 "reference a stream\n",
10236 tile_id, grid->item->item_id);
10237 ff_remove_stream_group(s, stg);
10238 loop = 0;
10239 break;
10240 }
10241
10242 16 grid->tile_item_list[j] = item;
10243 16 grid->tile_idx_list[j] = stg->nb_streams;
10244
10245 16 err = avformat_stream_group_add_stream(stg, st);
10246
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (err < 0) {
10247 int l;
10248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
10249 return err;
10250
10251
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_streams; l++)
10252
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->streams[l]->index == st->index)
10253 2 break;
10254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_streams);
10255 2 grid->tile_idx_list[j] = l;
10256 }
10257
10258
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
16 if (item->item_id != mov->primary_item_id)
10259 10 st->disposition |= AV_DISPOSITION_DEPENDENT;
10260 16 break;
10261 }
10262
10263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (k == mov->nb_heif_item) {
10264 av_assert0(loop);
10265 av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
10266 "exist\n",
10267 tile_id, grid->item->item_id);
10268 ff_remove_stream_group(s, stg);
10269 loop = 0;
10270 }
10271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!loop)
10272 break;
10273 }
10274
10275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!loop)
10276 continue;
10277
10278
2/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
6 switch (grid->item->type) {
10279 2 case MKTAG('g','r','i','d'):
10280 2 err = read_image_grid(s, grid, tile_grid);
10281 2 break;
10282 4 case MKTAG('i','o','v','l'):
10283 4 err = read_image_iovl(s, grid, tile_grid);
10284 4 break;
10285 default:
10286 av_assert0(0);
10287 }
10288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10289 return err;
10290
10291
10292
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (grid->item->name)
10293 6 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
10294
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (grid->item->item_id == mov->primary_item_id)
10295 2 stg->disposition |= AV_DISPOSITION_DEFAULT;
10296 }
10297
10298 6 return 0;
10299 }
10300
10301 12 static int mov_parse_heif_items(AVFormatContext *s)
10302 {
10303 12 MOVContext *mov = s->priv_data;
10304 int err;
10305
10306
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 for (int i = 0; i < mov->nb_heif_item; i++) {
10307 30 HEIFItem *item = mov->heif_item[i];
10308 MOVStreamContext *sc;
10309 AVStream *st;
10310 30 int64_t offset = 0;
10311
10312
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!item)
10313 continue;
10314
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 23 times.
30 if (!item->st) {
10315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (item->item_id == mov->thmb_item_id) {
10316 av_log(s, AV_LOG_ERROR, "HEIF thumbnail doesn't reference a stream\n");
10317 return AVERROR_INVALIDDATA;
10318 }
10319 7 continue;
10320 }
10321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (item->is_idat_relative) {
10322 if (!mov->idat_offset) {
10323 av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
10324 return AVERROR_INVALIDDATA;
10325 }
10326 offset = mov->idat_offset;
10327 }
10328
10329 23 st = item->st;
10330 23 sc = st->priv_data;
10331 23 st->codecpar->width = item->width;
10332 23 st->codecpar->height = item->height;
10333
10334 23 err = sanity_checks(s, sc, item->item_id);
10335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (err)
10336 return AVERROR_INVALIDDATA;
10337
10338 23 sc->sample_sizes[0] = item->extent_length;
10339 23 sc->chunk_offsets[0] = item->extent_offset + offset;
10340
10341
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 13 times.
23 if (item->item_id == mov->primary_item_id)
10342 10 st->disposition |= AV_DISPOSITION_DEFAULT;
10343
10344
4/6
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 19 times.
23 if (item->rotation || item->hflip || item->vflip) {
10345 4 err = set_display_matrix_from_item(&st->codecpar->coded_side_data,
10346 4 &st->codecpar->nb_coded_side_data, item);
10347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
10348 return err;
10349 }
10350
10351 23 mov_build_index(mov, st);
10352 }
10353
10354
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (mov->nb_heif_grid) {
10355 6 err = mov_parse_tiles(s);
10356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10357 return err;
10358 }
10359
10360 12 return 0;
10361 }
10362
10363 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
10364 int first_index)
10365 {
10366 MOVStreamContext *sc = st->priv_data;
10367
10368 if (sc->tref_id < 0)
10369 return NULL;
10370
10371 for (int i = first_index; i < s->nb_streams; i++)
10372 if (s->streams[i]->id == sc->tref_id)
10373 return s->streams[i];
10374
10375 return NULL;
10376 }
10377
10378 493 static int mov_parse_lcevc_streams(AVFormatContext *s)
10379 {
10380 int err;
10381
10382
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 493 times.
1164 for (int i = 0; i < s->nb_streams; i++) {
10383 AVStreamGroup *stg;
10384 671 AVStream *st = s->streams[i];
10385 AVStream *st_base;
10386 671 MOVStreamContext *sc = st->priv_data;
10387 671 int j = 0;
10388
10389 /* Find an enhancement stream. */
10390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 671 times.
671 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC ||
10391 !(sc->tref_flags & MOV_TREF_FLAG_ENHANCEMENT))
10392 671 continue;
10393
10394 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10395
10396 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
10397 if (!stg)
10398 return AVERROR(ENOMEM);
10399
10400 stg->id = st->id;
10401 stg->params.lcevc->width = st->codecpar->width;
10402 stg->params.lcevc->height = st->codecpar->height;
10403 st->codecpar->width = 0;
10404 st->codecpar->height = 0;
10405
10406 while (st_base = mov_find_reference_track(s, st, j)) {
10407 err = avformat_stream_group_add_stream(stg, st_base);
10408 if (err < 0)
10409 return err;
10410
10411 j = st_base->index + 1;
10412 }
10413 if (!j) {
10414 av_log(s, AV_LOG_ERROR, "Failed to find base stream for enhancement stream\n");
10415 return AVERROR_INVALIDDATA;
10416 }
10417
10418 err = avformat_stream_group_add_stream(stg, st);
10419 if (err < 0)
10420 return err;
10421
10422 stg->params.lcevc->lcevc_index = stg->nb_streams - 1;
10423 }
10424
10425 493 return 0;
10426 }
10427
10428 493 static void fix_stream_ids(AVFormatContext *s)
10429 {
10430 493 int highest_id = 0;
10431
10432
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 493 times.
1164 for (int i = 0; i < s->nb_streams; i++) {
10433 671 const AVStream *st = s->streams[i];
10434 671 const MOVStreamContext *sc = st->priv_data;
10435
2/2
✓ Branch 0 taken 621 times.
✓ Branch 1 taken 50 times.
671 if (!sc->iamf)
10436 621 highest_id = FFMAX(highest_id, st->id);
10437 }
10438 493 highest_id += !highest_id;
10439
4/4
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 409 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 84 times.
503 for (int i = 0; highest_id > 1 && i < s->nb_stream_groups; i++) {
10440 10 AVStreamGroup *stg = s->stream_groups[i];
10441
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
10442 8 continue;
10443
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_streams; j++) {
10444 14 AVStream *st = stg->streams[j];
10445 14 MOVStreamContext *sc = st->priv_data;
10446 14 st->id += highest_id;
10447 14 sc->iamf_stream_offset = highest_id;
10448 }
10449 }
10450 493 }
10451
10452 493 static int mov_read_header(AVFormatContext *s)
10453 {
10454 493 MOVContext *mov = s->priv_data;
10455 493 AVIOContext *pb = s->pb;
10456 int j, err;
10457 493 MOVAtom atom = { AV_RL32("root") };
10458 int i;
10459
10460
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 490 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
493 if (mov->decryption_key_len != 0 && mov->decryption_key_len != AES_CTR_KEY_SIZE) {
10461 av_log(s, AV_LOG_ERROR, "Invalid decryption key len %d expected %d\n",
10462 mov->decryption_key_len, AES_CTR_KEY_SIZE);
10463 return AVERROR(EINVAL);
10464 }
10465
10466 493 mov->fc = s;
10467 493 mov->trak_index = -1;
10468 493 mov->thmb_item_id = -1;
10469 493 mov->primary_item_id = -1;
10470 493 mov->cur_item_id = -1;
10471 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
10472
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
10473 493 atom.size = avio_size(pb);
10474 else
10475 atom.size = INT64_MAX;
10476
10477 /* check MOV header */
10478 do {
10479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (mov->moov_retry)
10480 avio_seek(pb, 0, SEEK_SET);
10481
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 493 times.
493 if ((err = mov_read_default(mov, pb, atom)) < 0) {
10482 av_log(s, AV_LOG_ERROR, "error reading header\n");
10483 return err;
10484 }
10485 986 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10486
5/10
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 481 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
493 !mov->found_moov && (!mov->found_iloc || !mov->found_iinf) && !mov->moov_retry++);
10487
3/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 481 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
493 if (!mov->found_moov && !mov->found_iloc && !mov->found_iinf) {
10488 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
10489 return AVERROR_INVALIDDATA;
10490 }
10491 493 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
10492
10493
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 481 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
493 if (mov->found_iloc && mov->found_iinf) {
10494 12 err = mov_parse_heif_items(s);
10495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (err < 0)
10496 return err;
10497 }
10498 // prevent iloc and iinf boxes from being parsed while reading packets.
10499 // this is needed because an iinf box may have been parsed but ignored
10500 // for having old infe boxes which create no streams.
10501 493 mov->found_iloc = mov->found_iinf = 1;
10502
10503
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
10504
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 491 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
493 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
10505 2 mov_read_chapters(s);
10506
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 493 times.
1164 for (i = 0; i < s->nb_streams; i++)
10507
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 652 times.
671 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
10508 19 mov_read_timecode_track(s, s->streams[i]);
10509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 652 times.
652 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
10510 mov_read_rtmd_track(s, s->streams[i]);
10511 }
10512 }
10513
10514 /* copy timecode metadata from tmcd tracks to the related video streams */
10515
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 493 times.
1164 for (i = 0; i < s->nb_streams; i++) {
10516 671 AVStream *st = s->streams[i];
10517 671 MOVStreamContext *sc = st->priv_data;
10518
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 653 times.
671 if (sc->timecode_track > 0) {
10519 AVDictionaryEntry *tcr;
10520 18 int tmcd_st_id = -1;
10521
10522
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 18 times.
66 for (j = 0; j < s->nb_streams; j++) {
10523 48 MOVStreamContext *sc2 = s->streams[j]->priv_data;
10524
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 30 times.
48 if (sc2->id == sc->timecode_track)
10525 18 tmcd_st_id = j;
10526 }
10527
10528
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)
10529 continue;
10530 18 tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
10531
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 if (tcr)
10532 16 av_dict_set(&st->metadata, "timecode", tcr->value, 0);
10533 }
10534 }
10535 493 export_orphan_timecode(s);
10536
10537 /* Create LCEVC stream groups. */
10538 493 err = mov_parse_lcevc_streams(s);
10539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (err < 0)
10540 return err;
10541
10542
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 493 times.
1164 for (i = 0; i < s->nb_streams; i++) {
10543 671 AVStream *st = s->streams[i];
10544 671 FFStream *const sti = ffstream(st);
10545 671 MOVStreamContext *sc = st->priv_data;
10546 671 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
10547 671 fix_timescale(mov, sc);
10548
2/2
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 390 times.
671 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
10549
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 165 times.
281 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
10550 116 sti->skip_samples = sc->start_pad;
10551 }
10552
5/6
✓ Branch 0 taken 339 times.
✓ Branch 1 taken 332 times.
✓ Branch 2 taken 302 times.
✓ Branch 3 taken 37 times.
✓ Branch 4 taken 302 times.
✗ Branch 5 not taken.
671 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
10553 302 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
10554 302 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
10555
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 663 times.
671 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
10556
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) {
10557 4 st->codecpar->width = sc->width;
10558 4 st->codecpar->height = sc->height;
10559 }
10560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
10561 st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
10562
10563 for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
10564 dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
10565
10566 err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
10567 if (err < 0)
10568 return err;
10569
10570 av_freep(&st->codecpar->extradata);
10571 st->codecpar->extradata_size = 0;
10572
10573 err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
10574 st->codecpar);
10575 if (err < 0)
10576 return err;
10577 }
10578 }
10579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 671 times.
671 if (mov->handbrake_version &&
10580 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
10581 st->codecpar->codec_id == AV_CODEC_ID_MP3) {
10582 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
10583 sti->need_parsing = AVSTREAM_PARSE_FULL;
10584 }
10585 }
10586
10587
3/4
✓ Branch 0 taken 481 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 481 times.
493 if (mov->trex_data || mov->use_mfra_for > 0) {
10588
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 12 times.
29 for (i = 0; i < s->nb_streams; i++) {
10589 17 AVStream *st = s->streams[i];
10590 17 MOVStreamContext *sc = st->priv_data;
10591
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 3 times.
17 if (sc->duration_for_fps > 0) {
10592 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
10593 14 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
10594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (st->codecpar->bit_rate == INT64_MIN) {
10595 av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
10596 sc->data_size, sc->time_scale);
10597 st->codecpar->bit_rate = 0;
10598 if (s->error_recognition & AV_EF_EXPLODE)
10599 return AVERROR_INVALIDDATA;
10600 }
10601 }
10602 }
10603 }
10604
10605
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
493 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
10606 if (mov->bitrates[i]) {
10607 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
10608 }
10609 }
10610
10611 493 ff_rfps_calculate(s);
10612
10613
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 493 times.
1164 for (i = 0; i < s->nb_streams; i++) {
10614 671 AVStream *st = s->streams[i];
10615 671 MOVStreamContext *sc = st->priv_data;
10616
10617
3/3
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 339 times.
✓ Branch 2 taken 51 times.
671 switch (st->codecpar->codec_type) {
10618 281 case AVMEDIA_TYPE_AUDIO:
10619 281 err = ff_replaygain_export(st, s->metadata);
10620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 281 times.
281 if (err < 0)
10621 return err;
10622 281 break;
10623 339 case AVMEDIA_TYPE_VIDEO:
10624
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 331 times.
339 if (sc->display_matrix) {
10625
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,
10626 AV_PKT_DATA_DISPLAYMATRIX,
10627 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
10628 return AVERROR(ENOMEM);
10629
10630 8 sc->display_matrix = NULL;
10631 }
10632
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 335 times.
339 if (sc->stereo3d) {
10633
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,
10634 AV_PKT_DATA_STEREO3D,
10635 4 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
10636 return AVERROR(ENOMEM);
10637
10638 4 sc->stereo3d = NULL;
10639 }
10640
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 335 times.
339 if (sc->spherical) {
10641
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,
10642 AV_PKT_DATA_SPHERICAL,
10643 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
10644 return AVERROR(ENOMEM);
10645
10646 4 sc->spherical = NULL;
10647 }
10648
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 339 times.
339 if (sc->mastering) {
10649 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10650 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
10651 (uint8_t *)sc->mastering, sc->mastering_size, 0))
10652 return AVERROR(ENOMEM);
10653
10654 sc->mastering = NULL;
10655 }
10656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 339 times.
339 if (sc->coll) {
10657 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10658 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
10659 (uint8_t *)sc->coll, sc->coll_size, 0))
10660 return AVERROR(ENOMEM);
10661
10662 sc->coll = NULL;
10663 }
10664
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 335 times.
339 if (sc->ambient) {
10665
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,
10666 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
10667 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
10668 return AVERROR(ENOMEM);
10669
10670 4 sc->ambient = NULL;
10671 }
10672 339 break;
10673 }
10674 }
10675
10676 493 fix_stream_ids(s);
10677
10678 493 ff_configure_buffers_for_index(s, AV_TIME_BASE);
10679
10680
2/2
✓ Branch 0 taken 389 times.
✓ Branch 1 taken 493 times.
882 for (i = 0; i < mov->frag_index.nb_items; i++)
10681
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)
10682 385 mov->frag_index.item[i].headers_read = 1;
10683
10684 493 return 0;
10685 }
10686
10687 103923 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
10688 {
10689 103923 AVIndexEntry *sample = NULL;
10690 103923 int64_t best_dts = INT64_MAX;
10691 int i;
10692 103923 MOVContext *mov = s->priv_data;
10693
2/4
✓ Branch 0 taken 103923 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 103923 times.
103923 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
10694
2/2
✓ Branch 0 taken 133785 times.
✓ Branch 1 taken 103923 times.
237708 for (i = 0; i < s->nb_streams; i++) {
10695 133785 AVStream *avst = s->streams[i];
10696 133785 FFStream *const avsti = ffstream(avst);
10697 133785 MOVStreamContext *msc = avst->priv_data;
10698
4/4
✓ Branch 0 taken 125547 times.
✓ Branch 1 taken 8238 times.
✓ Branch 2 taken 122269 times.
✓ Branch 3 taken 3278 times.
133785 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
10699 122269 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
10700 122269 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
10701
2/2
✓ Branch 0 taken 108577 times.
✓ Branch 1 taken 13692 times.
122269 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
10702 122269 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
10703
3/6
✓ Branch 0 taken 18834 times.
✓ Branch 1 taken 103435 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18834 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
122269 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
10704
1/2
✓ Branch 0 taken 18834 times.
✗ Branch 1 not taken.
18834 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10705
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 18834 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 18834 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18834 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 16725 times.
✓ Branch 9 taken 2109 times.
18834 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
10706
4/4
✓ Branch 0 taken 8610 times.
✓ Branch 1 taken 8115 times.
✓ Branch 2 taken 2109 times.
✓ Branch 3 taken 8610 times.
18834 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
10707
2/2
✓ Branch 0 taken 714 times.
✓ Branch 1 taken 1395 times.
2109 (dtsdiff > AV_TIME_BASE && dts < best_dts)))))) {
10708 112264 sample = current_sample;
10709 112264 best_dts = dts;
10710 112264 *st = avst;
10711 }
10712 }
10713 }
10714 103923 return sample;
10715 }
10716
10717 9 static int should_retry(AVIOContext *pb, int error_code) {
10718
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))
10719 9 return 0;
10720
10721 return 1;
10722 }
10723
10724 42 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
10725 {
10726 int ret;
10727 42 MOVContext *mov = s->priv_data;
10728
10729
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)
10730 target = mov->frag_index.item[index].moof_offset;
10731
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) {
10732 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
10733 return AVERROR_INVALIDDATA;
10734 }
10735
10736 42 mov->next_root_atom = 0;
10737
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)
10738 42 index = search_frag_moof_offset(&mov->frag_index, target);
10739
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 &&
10740
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 mov->frag_index.item[index].moof_offset == target) {
10741
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (index + 1 < mov->frag_index.nb_items)
10742 35 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
10743
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (mov->frag_index.item[index].headers_read)
10744 35 return 0;
10745 3 mov->frag_index.item[index].headers_read = 1;
10746 }
10747
10748 7 mov->found_mdat = 0;
10749
10750 7 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
10751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
10752 return ret;
10753
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 3 times.
7 if (avio_feof(s->pb))
10754 4 return AVERROR_EOF;
10755 3 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
10756
10757 3 return 1;
10758 }
10759
10760 16 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
10761 {
10762 16 MOVStreamContext *sc = st->priv_data;
10763 uint8_t *side, *extradata;
10764 int extradata_size;
10765
10766 /* Save the current index. */
10767 16 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
10768
10769 /* Notify the decoder that extradata changed. */
10770 16 extradata_size = sc->extradata_size[sc->last_stsd_index];
10771 16 extradata = sc->extradata[sc->last_stsd_index];
10772
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) {
10773 13 side = av_packet_new_side_data(pkt,
10774 AV_PKT_DATA_NEW_EXTRADATA,
10775 extradata_size);
10776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!side)
10777 return AVERROR(ENOMEM);
10778 13 memcpy(side, extradata, extradata_size);
10779 }
10780
10781 16 return 0;
10782 }
10783
10784 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
10785 {
10786 /* We can't make assumptions about the structure of the payload,
10787 because it may include multiple cdat and cdt2 samples. */
10788 const uint32_t cdat = AV_RB32("cdat");
10789 const uint32_t cdt2 = AV_RB32("cdt2");
10790 int ret, out_size = 0;
10791
10792 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
10793 if (src_size < 10)
10794 return AVERROR_INVALIDDATA;
10795
10796 /* avoid an int overflow: */
10797 if ((src_size - 8) / 2 >= INT_MAX / 3)
10798 return AVERROR_INVALIDDATA;
10799
10800 ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
10801 if (ret < 0)
10802 return ret;
10803
10804 /* parse and re-format the c608 payload in one pass. */
10805 while (src_size >= 10) {
10806 const uint32_t atom_size = avio_rb32(pb);
10807 const uint32_t atom_type = avio_rb32(pb);
10808 const uint32_t data_size = atom_size - 8;
10809 const uint8_t cc_field =
10810 atom_type == cdat ? 1 :
10811 atom_type == cdt2 ? 2 :
10812 0;
10813
10814 /* account for bytes consumed for atom size and type. */
10815 src_size -= 8;
10816
10817 /* make sure the data size stays within the buffer boundaries. */
10818 if (data_size < 2 || data_size > src_size) {
10819 ret = AVERROR_INVALIDDATA;
10820 break;
10821 }
10822
10823 /* make sure the data size is consistent with N byte pairs. */
10824 if (data_size % 2 != 0) {
10825 ret = AVERROR_INVALIDDATA;
10826 break;
10827 }
10828
10829 if (!cc_field) {
10830 /* neither cdat or cdt2 ... skip it */
10831 avio_skip(pb, data_size);
10832 src_size -= data_size;
10833 continue;
10834 }
10835
10836 for (uint32_t i = 0; i < data_size; i += 2) {
10837 pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
10838 pkt->data[out_size + 1] = avio_r8(pb);
10839 pkt->data[out_size + 2] = avio_r8(pb);
10840 out_size += 3;
10841 src_size -= 2;
10842 }
10843 }
10844
10845 if (src_size > 0)
10846 /* skip any remaining unread portion of the input payload */
10847 avio_skip(pb, src_size);
10848
10849 av_shrink_packet(pkt, out_size);
10850 return ret;
10851 }
10852
10853 103391 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
10854 int64_t current_index, AVPacket *pkt)
10855 {
10856 103391 MOVStreamContext *sc = st->priv_data;
10857
10858 103391 pkt->stream_index = sc->ffindex;
10859 103391 pkt->dts = sample->timestamp;
10860
2/2
✓ Branch 0 taken 237 times.
✓ Branch 1 taken 103154 times.
103391 if (sample->flags & AVINDEX_DISCARD_FRAME) {
10861 237 pkt->flags |= AV_PKT_FLAG_DISCARD;
10862 }
10863
4/4
✓ Branch 0 taken 83535 times.
✓ Branch 1 taken 19856 times.
✓ Branch 2 taken 83523 times.
✓ Branch 3 taken 12 times.
103391 if (sc->stts_count && sc->tts_index < sc->tts_count)
10864 83523 pkt->duration = sc->tts_data[sc->tts_index].duration;
10865
3/4
✓ Branch 0 taken 3017 times.
✓ Branch 1 taken 100374 times.
✓ Branch 2 taken 3017 times.
✗ Branch 3 not taken.
103391 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
10866 3017 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
10867 } else {
10868
2/2
✓ Branch 0 taken 15773 times.
✓ Branch 1 taken 84601 times.
100374 if (pkt->duration == 0) {
10869 15773 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
10870
2/2
✓ Branch 0 taken 15700 times.
✓ Branch 1 taken 73 times.
15773 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
10871
2/2
✓ Branch 0 taken 15747 times.
✓ Branch 1 taken 26 times.
15773 if (next_dts >= pkt->dts)
10872 15747 pkt->duration = next_dts - pkt->dts;
10873 }
10874 100374 pkt->pts = pkt->dts;
10875 }
10876
10877
4/4
✓ Branch 0 taken 83535 times.
✓ Branch 1 taken 19856 times.
✓ Branch 2 taken 83523 times.
✓ Branch 3 taken 12 times.
103391 if (sc->tts_data && sc->tts_index < sc->tts_count) {
10878 /* update tts context */
10879 83523 sc->tts_sample++;
10880
1/2
✓ Branch 0 taken 83523 times.
✗ Branch 1 not taken.
83523 if (sc->tts_index < sc->tts_count &&
10881
1/2
✓ Branch 0 taken 83523 times.
✗ Branch 1 not taken.
83523 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
10882 83523 sc->tts_index++;
10883 83523 sc->tts_sample = 0;
10884 }
10885 }
10886
10887
4/4
✓ Branch 0 taken 1037 times.
✓ Branch 1 taken 102354 times.
✓ Branch 2 taken 905 times.
✓ Branch 3 taken 132 times.
103391 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
10888 905 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
10889 905 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
10890
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 591 times.
905 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
10891 }
10892 103391 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
10893 103391 pkt->pos = sample->pos;
10894
10895 /* Multiple stsd handling. */
10896
2/2
✓ Branch 0 taken 102600 times.
✓ Branch 1 taken 791 times.
103391 if (sc->stsc_data) {
10897
1/2
✓ Branch 0 taken 102600 times.
✗ Branch 1 not taken.
102600 if (sc->stsc_data[sc->stsc_index].id > 0 &&
10898
2/2
✓ Branch 0 taken 102577 times.
✓ Branch 1 taken 23 times.
102600 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
10899
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 102561 times.
102577 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
10900 16 int ret = mov_change_extradata(st, pkt);
10901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0)
10902 return ret;
10903 }
10904
10905 /* Update the stsc index for the next sample */
10906 102600 sc->stsc_sample++;
10907
2/2
✓ Branch 1 taken 55148 times.
✓ Branch 2 taken 47452 times.
102600 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
10908
2/2
✓ Branch 1 taken 1189 times.
✓ Branch 2 taken 53959 times.
55148 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
10909 1189 sc->stsc_index++;
10910 1189 sc->stsc_sample = 0;
10911 }
10912 }
10913
10914 103391 return 0;
10915 }
10916
10917 97063 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
10918 {
10919 97063 MOVContext *mov = s->priv_data;
10920 MOVStreamContext *sc;
10921 AVIndexEntry *sample;
10922 97063 AVStream *st = NULL;
10923 97063 FFStream *avsti = NULL;
10924 int64_t current_index;
10925 int ret;
10926 int i;
10927 97063 mov->fc = s;
10928 6860 retry:
10929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103923 times.
103923 if (s->pb->pos == 0) {
10930
10931 // Discard current fragment index
10932 if (mov->frag_index.allocated_size > 0) {
10933 for(int i = 0; i < mov->frag_index.nb_items; i++) {
10934 av_freep(&mov->frag_index.item[i].stream_info);
10935 }
10936 av_freep(&mov->frag_index.item);
10937 mov->frag_index.nb_items = 0;
10938 mov->frag_index.allocated_size = 0;
10939 mov->frag_index.current = -1;
10940 mov->frag_index.complete = 0;
10941 }
10942
10943 for (i = 0; i < s->nb_streams; i++) {
10944 AVStream *avst = s->streams[i];
10945 MOVStreamContext *msc = avst->priv_data;
10946
10947 // Clear current sample
10948 mov_current_sample_set(msc, 0);
10949 msc->tts_index = 0;
10950
10951 // Discard current index entries
10952 avsti = ffstream(avst);
10953 if (avsti->index_entries_allocated_size > 0) {
10954 av_freep(&avsti->index_entries);
10955 avsti->index_entries_allocated_size = 0;
10956 avsti->nb_index_entries = 0;
10957 }
10958 }
10959
10960 if ((ret = mov_switch_root(s, -1, -1)) < 0)
10961 return ret;
10962 }
10963 103923 sample = mov_find_next_sample(s, &st);
10964
6/6
✓ Branch 0 taken 103435 times.
✓ Branch 1 taken 488 times.
✓ Branch 2 taken 472 times.
✓ Branch 3 taken 102963 times.
✓ Branch 4 taken 35 times.
✓ Branch 5 taken 437 times.
103923 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
10965
2/2
✓ Branch 0 taken 481 times.
✓ Branch 1 taken 42 times.
523 if (!mov->next_root_atom)
10966 481 return AVERROR_EOF;
10967
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)
10968 4 return ret;
10969 38 goto retry;
10970 }
10971 103400 sc = st->priv_data;
10972 /* must be done just before reading, to avoid infinite loop on sample */
10973 103400 current_index = sc->current_index;
10974 103400 mov_current_sample_inc(sc);
10975
10976
2/2
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 102963 times.
103400 if (mov->next_root_atom) {
10977 437 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
10978 437 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
10979 }
10980
10981
2/2
✓ Branch 0 taken 96578 times.
✓ Branch 1 taken 6822 times.
103400 if (st->discard != AVDISCARD_ALL) {
10982 96578 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
10983
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 96571 times.
96578 if (ret64 != sample->pos) {
10984 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
10985 sc->ffindex, sample->pos);
10986
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
10987 mov_current_sample_dec(sc);
10988
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
10989 7 return (int)ret64;
10990 }
10991 return AVERROR_INVALIDDATA;
10992 }
10993
10994
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96571 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96571 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
10995 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
10996 goto retry;
10997 }
10998
10999
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96571 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96571 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
11000 ret = get_eia608_packet(sc->pb, pkt, sample->size);
11001 #if CONFIG_IAMFDEC
11002
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 96516 times.
96571 else if (sc->iamf) {
11003 int64_t pts, dts, pos, duration;
11004 55 int flags, size = sample->size;
11005 55 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11006 55 pts = pkt->pts; dts = pkt->dts;
11007 55 pos = pkt->pos; flags = pkt->flags;
11008 55 duration = pkt->duration;
11009
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) {
11010 275 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
11011
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
275 if (ret < 0) {
11012 if (should_retry(sc->pb, ret))
11013 mov_current_sample_dec(sc);
11014 return ret;
11015 }
11016 275 size -= ret;
11017 275 pkt->pts = pts; pkt->dts = dts;
11018 275 pkt->pos = pos; pkt->flags |= flags;
11019 275 pkt->duration = duration;
11020 275 ret = ff_buffer_packet(s, pkt);
11021 }
11022
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 if (!ret)
11023 55 return FFERROR_REDO;
11024 }
11025 #endif
11026 else
11027 96516 ret = av_get_packet(sc->pb, pkt, sample->size);
11028
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 96514 times.
96516 if (ret < 0) {
11029
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (should_retry(sc->pb, ret)) {
11030 mov_current_sample_dec(sc);
11031 }
11032 2 return ret;
11033 }
11034 #if CONFIG_DV_DEMUXER
11035
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96514 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96514 if (mov->dv_demux && sc->dv_audio_container) {
11036 ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
11037 av_packet_unref(pkt);
11038 if (ret < 0)
11039 return ret;
11040 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
11041 if (ret < 0)
11042 return ret;
11043 }
11044 #endif
11045
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 96496 times.
96514 if (sc->has_palette) {
11046 uint8_t *pal;
11047
11048 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
11049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
11050 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
11051 } else {
11052 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
11053 18 sc->has_palette = 0;
11054 }
11055 }
11056
4/6
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 96226 times.
✓ Branch 3 taken 288 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 288 times.
✗ Branch 6 not taken.
96514 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
11057
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 288 times.
288 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
11058 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
11059 }
11060 }
11061
11062 103336 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103336 times.
103336 if (ret < 0)
11064 return ret;
11065
11066
2/2
✓ Branch 0 taken 6822 times.
✓ Branch 1 taken 96514 times.
103336 if (st->discard == AVDISCARD_ALL)
11067 6822 goto retry;
11068
11069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96514 times.
96514 if (mov->aax_mode)
11070 aax_filter(pkt->data, pkt->size, mov);
11071
11072 96514 ret = cenc_filter(mov, st, sc, pkt, current_index);
11073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96514 times.
96514 if (ret < 0) {
11074 return ret;
11075 }
11076
11077 96514 return 0;
11078 }
11079
11080 361 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
11081 {
11082 361 MOVContext *mov = s->priv_data;
11083 int index;
11084
11085
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 26 times.
361 if (!mov->frag_index.complete)
11086 335 return 0;
11087
11088 26 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
11089
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 22 times.
26 if (index < 0)
11090 4 index = 0;
11091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (!mov->frag_index.item[index].headers_read)
11092 return mov_switch_root(s, -1, index);
11093
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (index + 1 < mov->frag_index.nb_items)
11094 26 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11095
11096 26 return 0;
11097 }
11098
11099 static int is_open_key_sample(const MOVStreamContext *sc, int sample)
11100 {
11101 // TODO: a bisect search would scale much better
11102 for (int i = 0; i < sc->open_key_samples_count; i++) {
11103 const int oks = sc->open_key_samples[i];
11104 if (oks == sample)
11105 return 1;
11106 if (oks > sample) /* list is monotically increasing so we can stop early */
11107 break;
11108 }
11109 return 0;
11110 }
11111
11112 /*
11113 * Some key sample may be key frames but not IDR frames, so a random access to
11114 * them may not be allowed.
11115 */
11116 229 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
11117 {
11118 229 MOVStreamContext *sc = st->priv_data;
11119 229 FFStream *const sti = ffstream(st);
11120 int64_t key_sample_dts, key_sample_pts;
11121
11122
1/2
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
229 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
11123 229 return 1;
11124
11125 if (sample >= sc->sample_offsets_count)
11126 return 1;
11127
11128 key_sample_dts = sti->index_entries[sample].timestamp;
11129 key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
11130
11131 /*
11132 * If the sample needs to be presented before an open key sample, they may
11133 * not be decodable properly, even though they come after in decoding
11134 * order.
11135 */
11136 if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
11137 return 0;
11138
11139 return 1;
11140 }
11141
11142 361 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
11143 {
11144 361 MOVStreamContext *sc = st->priv_data;
11145 361 FFStream *const sti = ffstream(st);
11146 int sample, time_sample, ret, next_ts, requested_sample;
11147 unsigned int i;
11148
11149 // Here we consider timestamp to be PTS, hence try to offset it so that we
11150 // can search over the DTS timeline.
11151 361 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
11152
11153 361 ret = mov_seek_fragment(s, st, timestamp);
11154
1/2
✓ Branch 0 taken 361 times.
✗ Branch 1 not taken.
361 if (ret < 0)
11155 return ret;
11156
11157 for (;;) {
11158 361 sample = av_index_search_timestamp(st, timestamp, flags);
11159 361 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
11160
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)
11161 43 sample = 0;
11162
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 335 times.
361 if (sample < 0) /* not sure what to do */
11163 26 return AVERROR_INVALIDDATA;
11164
11165
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))
11166 break;
11167
11168 next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
11169 requested_sample = av_index_search_timestamp(st, next_ts, flags);
11170
11171 // If we've reached a different sample trying to find a good pts to
11172 // seek to, give up searching because we'll end up seeking back to
11173 // sample 0 on every seek.
11174 if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
11175 break;
11176
11177 timestamp = next_ts;
11178 }
11179
11180 335 mov_current_sample_set(sc, sample);
11181 335 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
11182 /* adjust time to sample index */
11183
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 125 times.
335 if (sc->tts_data) {
11184 210 time_sample = 0;
11185
1/2
✓ Branch 0 taken 60235 times.
✗ Branch 1 not taken.
60235 for (i = 0; i < sc->tts_count; i++) {
11186 60235 int next = time_sample + sc->tts_data[i].count;
11187
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 60025 times.
60235 if (next > sc->current_sample) {
11188 210 sc->tts_index = i;
11189 210 sc->tts_sample = sc->current_sample - time_sample;
11190 210 break;
11191 }
11192 60025 time_sample = next;
11193 }
11194 }
11195
11196 /* adjust stsd index */
11197
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 26 times.
335 if (sc->chunk_count) {
11198 309 time_sample = 0;
11199
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
381 for (i = 0; i < sc->stsc_count; i++) {
11200 381 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
11201
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 72 times.
381 if (next > sc->current_sample) {
11202 309 sc->stsc_index = i;
11203 309 sc->stsc_sample = sc->current_sample - time_sample;
11204 309 break;
11205 }
11206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
11207 72 time_sample = next;
11208 }
11209 }
11210
11211 335 return sample;
11212 }
11213
11214 335 static int64_t mov_get_skip_samples(AVStream *st, int sample)
11215 {
11216 335 MOVStreamContext *sc = st->priv_data;
11217 335 FFStream *const sti = ffstream(st);
11218 335 int64_t first_ts = sti->index_entries[0].timestamp;
11219 335 int64_t ts = sti->index_entries[sample].timestamp;
11220 int64_t off;
11221
11222
2/2
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 151 times.
335 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
11223 184 return 0;
11224
11225 /* compute skip samples according to stream start_pad, seek ts and first ts */
11226 151 off = av_rescale_q(ts - first_ts, st->time_base,
11227 151 (AVRational){1, st->codecpar->sample_rate});
11228 151 return FFMAX(sc->start_pad - off, 0);
11229 }
11230
11231 340 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
11232 {
11233 340 MOVContext *mc = s->priv_data;
11234 AVStream *st;
11235 FFStream *sti;
11236 int sample;
11237 int i;
11238
11239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 340 times.
340 if (stream_index >= s->nb_streams)
11240 return AVERROR_INVALIDDATA;
11241
11242 340 st = s->streams[stream_index];
11243 340 sti = ffstream(st);
11244 340 sample = mov_seek_stream(s, st, sample_time, flags);
11245
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 314 times.
340 if (sample < 0)
11246 26 return sample;
11247
11248
1/2
✓ Branch 0 taken 314 times.
✗ Branch 1 not taken.
314 if (mc->seek_individually) {
11249 /* adjust seek timestamp to found sample timestamp */
11250 314 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
11251 314 sti->skip_samples = mov_get_skip_samples(st, sample);
11252
11253
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 314 times.
649 for (i = 0; i < s->nb_streams; i++) {
11254 335 AVStream *const st = s->streams[i];
11255 335 FFStream *const sti = ffstream(st);
11256 int64_t timestamp;
11257
11258
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 21 times.
335 if (stream_index == i)
11259 314 continue;
11260
11261 21 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
11262 21 sample = mov_seek_stream(s, st, timestamp, flags);
11263
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (sample >= 0)
11264 21 sti->skip_samples = mov_get_skip_samples(st, sample);
11265 }
11266 } else {
11267 for (i = 0; i < s->nb_streams; i++) {
11268 MOVStreamContext *sc;
11269 st = s->streams[i];
11270 sc = st->priv_data;
11271 mov_current_sample_set(sc, 0);
11272 }
11273 while (1) {
11274 MOVStreamContext *sc;
11275 AVIndexEntry *entry = mov_find_next_sample(s, &st);
11276 if (!entry)
11277 return AVERROR_INVALIDDATA;
11278 sc = st->priv_data;
11279 if (sc->ffindex == stream_index && sc->current_sample == sample)
11280 break;
11281 mov_current_sample_inc(sc);
11282 }
11283 }
11284 314 return 0;
11285 }
11286
11287 #define OFFSET(x) offsetof(MOVContext, x)
11288 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
11289 static const AVOption mov_options[] = {
11290 {"use_absolute_path",
11291 "allow using absolute path when opening alias, this is a possible security issue",
11292 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
11293 0, 1, FLAGS},
11294 {"seek_streams_individually",
11295 "Seek each stream individually to the closest point",
11296 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
11297 0, 1, FLAGS},
11298 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
11299 0, 1, FLAGS},
11300 {"advanced_editlist",
11301 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
11302 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
11303 0, 1, FLAGS},
11304 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
11305 0, 1, FLAGS},
11306 {"use_mfra_for",
11307 "use mfra for fragment timestamps",
11308 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
11309 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
11310 .unit = "use_mfra_for"},
11311 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
11312 FLAGS, .unit = "use_mfra_for" },
11313 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
11314 FLAGS, .unit = "use_mfra_for" },
11315 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
11316 FLAGS, .unit = "use_mfra_for" },
11317 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
11318 0, 1, FLAGS},
11319 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
11320 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11321 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
11322 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11323 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
11324 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11325 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
11326 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11327 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
11328 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11329 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
11330 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
11331 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
11332 .flags = AV_OPT_FLAG_DECODING_PARAM },
11333 { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11334 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
11335 {.i64 = 0}, 0, 1, FLAGS },
11336 { "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 },
11337 { "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 },
11338
11339 { NULL },
11340 };
11341
11342 static const AVClass mov_class = {
11343 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
11344 .item_name = av_default_item_name,
11345 .option = mov_options,
11346 .version = LIBAVUTIL_VERSION_INT,
11347 };
11348
11349 const FFInputFormat ff_mov_demuxer = {
11350 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
11351 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
11352 .p.priv_class = &mov_class,
11353 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v,avif,heic,heif",
11354 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
11355 .priv_data_size = sizeof(MOVContext),
11356 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
11357 .read_probe = mov_probe,
11358 .read_header = mov_read_header,
11359 .read_packet = mov_read_packet,
11360 .read_close = mov_read_close,
11361 .read_seek = mov_read_seek,
11362 };
11363