FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2025-10-12 01:43:37
Exec Total Coverage
Lines: 4366 6956 62.8%
Functions: 175 215 81.4%
Branches: 2461 4650 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/internal.h"
36 #include "libavutil/intreadwrite.h"
37 #include "libavutil/intfloat.h"
38 #include "libavutil/mathematics.h"
39 #include "libavutil/avassert.h"
40 #include "libavutil/avstring.h"
41 #include "libavutil/dict.h"
42 #include "libavutil/display.h"
43 #include "libavutil/mem.h"
44 #include "libavutil/opt.h"
45 #include "libavutil/aes.h"
46 #include "libavutil/aes_ctr.h"
47 #include "libavutil/pixdesc.h"
48 #include "libavutil/sha.h"
49 #include "libavutil/spherical.h"
50 #include "libavutil/stereo3d.h"
51 #include "libavutil/timecode.h"
52 #include "libavutil/uuid.h"
53 #include "libavcodec/ac3tab.h"
54 #include "libavcodec/exif.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 340 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
170 char *dst, int dstlen)
171 {
172 340 char *p = dst;
173 340 char *end = dst+dstlen-1;
174 int i;
175
176
2/2
✓ Branch 0 taken 3015 times.
✓ Branch 1 taken 340 times.
3355 for (i = 0; i < len; i++) {
177 3015 uint8_t t, c = avio_r8(pb);
178
179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3015 times.
3015 if (p >= end)
180 continue;
181
182
2/2
✓ Branch 0 taken 3007 times.
✓ Branch 1 taken 8 times.
3015 if (c < 0x80)
183 3007 *p++ = c;
184
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 else if (p < end)
185
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✓ Branch 9 taken 8 times.
16 PUT_UTF8(mac_to_unicode[c-0x80], t, if (p < end) *p++ = t;);
186 }
187 340 *p = 0;
188 340 return p - dst;
189 }
190
191 /**
192 * Get the requested item.
193 */
194 139 static HEIFItem *get_heif_item(MOVContext *c, unsigned id)
195 {
196 139 HEIFItem *item = NULL;
197
198
2/2
✓ Branch 0 taken 293 times.
✓ Branch 1 taken 12 times.
305 for (int i = 0; i < c->nb_heif_item; i++) {
199
3/4
✓ Branch 0 taken 293 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 166 times.
✓ Branch 3 taken 127 times.
293 if (!c->heif_item[i] || c->heif_item[i]->item_id != id)
200 166 continue;
201
202 127 item = c->heif_item[i];
203 127 break;
204 }
205
206 139 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 216 static AVStream *get_curr_st(MOVContext *c)
214 {
215 216 AVStream *st = NULL;
216 HEIFItem *item;
217
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 216 times.
216 if (c->fc->nb_streams < 1)
219 return NULL;
220
221
2/2
✓ Branch 0 taken 179 times.
✓ Branch 1 taken 37 times.
216 if (c->cur_item_id == -1)
222 179 return c->fc->streams[c->fc->nb_streams-1];
223
224 37 item = get_heif_item(c, c->cur_item_id);
225
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if (item)
226 37 st = item->st;
227
228 37 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 477 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
346 {
347 477 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
348 477 char key2[32], language[4] = {0};
349 477 char *str = NULL;
350 477 const char *key = NULL;
351 477 uint16_t langcode = 0;
352 477 uint32_t data_type = 0, str_size_alloc;
353 uint64_t str_size;
354 477 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
355 477 int raw = 0;
356 477 int num = 0;
357 AVDictionary **metadata;
358
359
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 448 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
477 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 448 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 42 times.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✓ Branch 67 taken 61 times.
✓ Branch 68 taken 51 times.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✓ Branch 72 taken 1 times.
✓ Branch 73 taken 5 times.
477 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 42 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 61 case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
448 51 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 302 times.
✓ Branch 1 taken 177 times.
✓ Branch 2 taken 302 times.
✗ Branch 3 not taken.
767 if (c->itunes_metadata && atom.size > 8) {
457 302 int data_size = avio_rb32(pb);
458 302 int tag = avio_rl32(pb);
459
3/6
✓ Branch 0 taken 302 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 302 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 302 times.
✗ Branch 5 not taken.
302 if (tag == MKTAG('d','a','t','a') && data_size <= atom.size && data_size >= 16) {
460 302 data_type = avio_rb32(pb); // type
461 302 avio_rb32(pb); // unknown
462 302 str_size = data_size - 16;
463 302 atom.size -= 16;
464
465
5/6
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 209 times.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 34 times.
✓ Branch 4 taken 59 times.
✗ Branch 5 not taken.
302 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 288 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 268 times.
✓ Branch 3 taken 20 times.
302 if (atom.type == MKTAG('c', 'o', 'v', 'r') ||
476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 268 times.
268 (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
8/10
✓ Branch 0 taken 159 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 108 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 51 times.
✓ Branch 6 taken 108 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 102 times.
✓ Branch 9 taken 6 times.
177 } else if (atom.size > 4 && (key || c->export_all) && !c->itunes_metadata && !raw) {
489 102 str_size = avio_rb16(pb); // string length
490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102 times.
102 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 102 langcode = avio_rb16(pb);
497 102 ff_mov_lang_to_iso639(langcode, language);
498 102 atom.size -= 4;
499 } else
500 75 str_size = atom.size;
501
502
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 465 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
465 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 376 times.
465 if (!key)
507 89 return 0;
508
2/4
✓ Branch 0 taken 376 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 376 times.
376 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 335 times.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
376 num = (data_type >= 21 && data_type <= 23);
514
4/4
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 329 times.
✓ Branch 3 taken 6 times.
376 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
515 376 str = av_mallocz(str_size_alloc);
516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 376 times.
376 if (!str)
517 return AVERROR(ENOMEM);
518
519
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 316 times.
376 if (parse)
520 60 parse(c, pb, str_size, key);
521 else {
522
8/10
✓ Branch 0 taken 310 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 310 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 103 times.
✓ Branch 5 taken 207 times.
✓ Branch 6 taken 89 times.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 89 times.
316 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 300 times.
302 } 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 300 times.
300 } 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 287 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
313 } 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 287 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
287 } 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 287 int ret = ffio_read_size(pb, str, str_size);
574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 287 times.
287 if (ret < 0) {
575 av_free(str);
576 return ret;
577 }
578 287 str[str_size] = 0;
579 }
580 316 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
581 316 av_dict_set(metadata, key, str, 0);
582
4/4
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 214 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 65 times.
316 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 114 times.
✓ Branch 1 taken 202 times.
316 if (!strcmp(key, "encoder")) {
587 int major, minor, micro;
588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
114 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 376 av_freep(&str);
595 376 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 612 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 612 times.
612 if (c->fc->nb_streams < 1)
644 return 0;
645 612 st = c->fc->streams[c->fc->nb_streams-1];
646 612 sc = st->priv_data;
647
648 612 avio_rb32(pb); // version + flags
649 612 entries = avio_rb32(pb);
650
1/2
✓ Branch 0 taken 612 times.
✗ Branch 1 not taken.
612 if (!entries ||
651
1/2
✓ Branch 0 taken 612 times.
✗ Branch 1 not taken.
612 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 entries >= UINT_MAX / sizeof(*sc->drefs))
653 return AVERROR_INVALIDDATA;
654
655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 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 612 av_free(sc->drefs);
661 612 sc->drefs_count = 0;
662 612 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (!sc->drefs)
664 return AVERROR(ENOMEM);
665 612 sc->drefs_count = entries;
666
667
2/2
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 612 times.
1224 for (i = 0; i < entries; i++) {
668 612 MOVDref *dref = &sc->drefs[i];
669 612 uint32_t size = avio_rb32(pb);
670 612 int64_t next = avio_tell(pb);
671
672
3/6
✓ Branch 0 taken 612 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 612 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 612 times.
612 if (size < 12 || next < 0 || next > INT64_MAX - size)
673 return AVERROR_INVALIDDATA;
674
675 612 next += size - 4;
676
677 612 dref->type = avio_rl32(pb);
678 612 avio_rb32(pb); // version + flags
679
680
3/4
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 494 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 118 times.
612 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 612 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
772 dref->type, size);
773 612 entries--;
774 612 i--;
775 }
776 612 avio_seek(pb, next, SEEK_SET);
777 }
778 612 return 0;
779 }
780
781 1120 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 1120 avio_r8(pb); /* version */
791 1120 avio_rb24(pb); /* flags */
792
793 /* component type */
794 1120 ctype = avio_rl32(pb);
795 1120 type = avio_rl32(pb); /* component subtype */
796
797 1120 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
798 1120 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
799
800
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 974 times.
1120 if (c->trak_index < 0) { // meta not inside a trak
801
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 135 times.
146 if (type == MKTAG('m','d','t','a')) {
802 11 c->found_hdlr_mdta = 1;
803 }
804 146 return 0;
805 }
806
807 974 st = c->fc->streams[c->fc->nb_streams-1];
808
809
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 660 times.
974 if (type == MKTAG('v','i','d','e'))
810 314 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
811
2/2
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 417 times.
660 else if (type == MKTAG('s','o','u','n'))
812 243 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
813
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 417 times.
417 else if (type == MKTAG('m','1','a',' '))
814 st->codecpar->codec_id = AV_CODEC_ID_MP2;
815
2/4
✓ Branch 0 taken 417 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 417 times.
417 else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
816 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
817
818 974 avio_rb32(pb); /* component manufacture */
819 974 avio_rb32(pb); /* component flags */
820 974 avio_rb32(pb); /* component flags mask */
821
822 974 title_size = atom.size - 24;
823
2/2
✓ Branch 0 taken 971 times.
✓ Branch 1 taken 3 times.
974 if (title_size > 0) {
824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 971 times.
971 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
825 return AVERROR_INVALIDDATA;
826 971 title_str = av_malloc(title_size + 1); /* Add null terminator */
827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 971 times.
971 if (!title_str)
828 return AVERROR(ENOMEM);
829
830 971 ret = ffio_read_size(pb, title_str, title_size);
831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 971 times.
971 if (ret < 0) {
832 av_freep(&title_str);
833 return ret;
834 }
835 971 title_str[title_size] = 0;
836
2/2
✓ Branch 0 taken 920 times.
✓ Branch 1 taken 51 times.
971 if (title_str[0]) {
837
4/4
✓ Branch 0 taken 700 times.
✓ Branch 1 taken 220 times.
✓ Branch 2 taken 698 times.
✓ Branch 3 taken 2 times.
920 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 920 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
840 }
841 971 av_freep(&title_str);
842 }
843
844 974 return 0;
845 }
846
847 156 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
848 {
849 156 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 18 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1240 {
1241 AVStream *st;
1242 HEIFItem *item;
1243 AVPacketSideData *sd;
1244 18 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 18 item = get_heif_item(c, c->cur_item_id);
1250 18 st = get_curr_st(c);
1251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!st)
1252 return 0;
1253
1254 18 width = st->codecpar->width;
1255 18 height = st->codecpar->height;
1256
4/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
18 if ((!width || !height) && item) {
1257 6 width = item->width;
1258 6 height = item->height;
1259 }
1260
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (!width || !height) {
1261 err = AVERROR_INVALIDDATA;
1262 goto fail;
1263 }
1264
1265 18 aperture_width.num = avio_rb32(pb);
1266 18 aperture_width.den = avio_rb32(pb);
1267 18 aperture_height.num = avio_rb32(pb);
1268 18 aperture_height.den = avio_rb32(pb);
1269
1270 18 horiz_off.num = avio_rb32(pb);
1271 18 horiz_off.den = avio_rb32(pb);
1272 18 vert_off.num = avio_rb32(pb);
1273 18 vert_off.den = avio_rb32(pb);
1274
1275
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 if (aperture_width.num < 0 || aperture_width.den < 0 ||
1276
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 aperture_height.num < 0 || aperture_height.den < 0 ||
1277
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 horiz_off.den < 0 || vert_off.den < 0) {
1278 err = AVERROR_INVALIDDATA;
1279 goto fail;
1280 }
1281
3/4
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
33 if ((av_cmp_q((AVRational) { width, 1 }, aperture_width) < 0) ||
1282 15 (av_cmp_q((AVRational) { height, 1 }, aperture_height) < 0)) {
1283 3 err = AVERROR_INVALIDDATA;
1284 3 goto fail;
1285 }
1286 15 av_log(c->fc, AV_LOG_TRACE, "clap: apertureWidth %d/%d, apertureHeight %d/%d "
1287 "horizOff %d/%d vertOff %d/%d\n",
1288 aperture_width.num, aperture_width.den, aperture_height.num, aperture_height.den,
1289 horiz_off.num, horiz_off.den, vert_off.num, vert_off.den);
1290
1291 15 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1292 15 pc_x = av_add_q(pc_x, horiz_off);
1293 15 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1294 15 pc_y = av_add_q(pc_y, vert_off);
1295
1296 15 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1297 15 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1298 15 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1299 15 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1300
1301 15 left = av_q2d(av_sub_q(pc_x, aperture_width));
1302 15 right = av_q2d(av_add_q(pc_x, aperture_width));
1303 15 top = av_q2d(av_sub_q(pc_y, aperture_height));
1304 15 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1305
1306
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (bottom > (height - 1) ||
1307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 right > (width - 1)) {
1308 err = AVERROR_INVALIDDATA;
1309 goto fail;
1310 }
1311
1312 15 bottom = height - 1 - bottom;
1313 15 right = width - 1 - right;
1314
1315
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
15 if (!(left | right | top | bottom))
1316 6 return 0;
1317
1318
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if ((left + right) >= width ||
1319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 (top + bottom) >= height) {
1320 err = AVERROR_INVALIDDATA;
1321 goto fail;
1322 }
1323
1324 9 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1325 9 &st->codecpar->nb_coded_side_data,
1326 AV_PKT_DATA_FRAME_CROPPING,
1327 sizeof(uint32_t) * 4, 0);
1328
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sd)
1329 return AVERROR(ENOMEM);
1330
1331 9 AV_WL32A(sd->data, top);
1332 9 AV_WL32A(sd->data + 4, bottom);
1333 9 AV_WL32A(sd->data + 8, left);
1334 9 AV_WL32A(sd->data + 12, right);
1335
1336 12 fail:
1337
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 if (err < 0) {
1338 3 int explode = !!(c->fc->error_recognition & AV_EF_EXPLODE);
1339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 av_log(c->fc, explode ? AV_LOG_ERROR : AV_LOG_WARNING, "Invalid clap box\n");
1340
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!explode)
1341 3 err = 0;
1342 }
1343
1344 12 return err;
1345 }
1346
1347 /* This atom overrides any previously set aspect ratio */
1348 75 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1349 {
1350 75 const int num = avio_rb32(pb);
1351 75 const int den = avio_rb32(pb);
1352 AVStream *st;
1353 MOVStreamContext *sc;
1354
1355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (c->fc->nb_streams < 1)
1356 return 0;
1357 75 st = c->fc->streams[c->fc->nb_streams-1];
1358 75 sc = st->priv_data;
1359
1360 75 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1361
1362
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 2 times.
75 if (den != 0) {
1363 73 sc->h_spacing = num;
1364 73 sc->v_spacing = den;
1365 }
1366 75 return 0;
1367 }
1368
1369 /* this atom contains actual media data */
1370 963 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1371 {
1372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 963 times.
963 if (atom.size == 0) /* wrong one (MP4) */
1373 return 0;
1374 963 c->found_mdat=1;
1375 963 return 0; /* now go for moov */
1376 }
1377
1378 #define DRM_BLOB_SIZE 56
1379
1380 static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1381 {
1382 uint8_t intermediate_key[20];
1383 uint8_t intermediate_iv[20];
1384 uint8_t input[64];
1385 uint8_t output[64];
1386 uint8_t file_checksum[20];
1387 uint8_t calculated_checksum[20];
1388 char checksum_string[2 * sizeof(file_checksum) + 1];
1389 struct AVSHA *sha;
1390 int i;
1391 int ret = 0;
1392 uint8_t *activation_bytes = c->activation_bytes;
1393 uint8_t *fixed_key = c->audible_fixed_key;
1394
1395 c->aax_mode = 1;
1396
1397 sha = av_sha_alloc();
1398 if (!sha)
1399 return AVERROR(ENOMEM);
1400 av_free(c->aes_decrypt);
1401 c->aes_decrypt = av_aes_alloc();
1402 if (!c->aes_decrypt) {
1403 ret = AVERROR(ENOMEM);
1404 goto fail;
1405 }
1406
1407 /* drm blob processing */
1408 avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1409 avio_read(pb, input, DRM_BLOB_SIZE);
1410 avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1411 ret = ffio_read_size(pb, file_checksum, 20);
1412 if (ret < 0)
1413 goto fail;
1414
1415 // required by external tools
1416 ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1);
1417 av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string);
1418
1419 /* verify activation data */
1420 if (!activation_bytes) {
1421 av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1422 ret = 0; /* allow ffprobe to continue working on .aax files */
1423 goto fail;
1424 }
1425 if (c->activation_bytes_size != 4) {
1426 av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1427 ret = AVERROR(EINVAL);
1428 goto fail;
1429 }
1430
1431 /* verify fixed key */
1432 if (c->audible_fixed_key_size != 16) {
1433 av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1434 ret = AVERROR(EINVAL);
1435 goto fail;
1436 }
1437
1438 /* AAX (and AAX+) key derivation */
1439 av_sha_init(sha, 160);
1440 av_sha_update(sha, fixed_key, 16);
1441 av_sha_update(sha, activation_bytes, 4);
1442 av_sha_final(sha, intermediate_key);
1443 av_sha_init(sha, 160);
1444 av_sha_update(sha, fixed_key, 16);
1445 av_sha_update(sha, intermediate_key, 20);
1446 av_sha_update(sha, activation_bytes, 4);
1447 av_sha_final(sha, intermediate_iv);
1448 av_sha_init(sha, 160);
1449 av_sha_update(sha, intermediate_key, 16);
1450 av_sha_update(sha, intermediate_iv, 16);
1451 av_sha_final(sha, calculated_checksum);
1452 if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1453 av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1454 ret = AVERROR_INVALIDDATA;
1455 goto fail;
1456 }
1457 av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1458 av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1459 for (i = 0; i < 4; i++) {
1460 // file data (in output) is stored in big-endian mode
1461 if (activation_bytes[i] != output[3 - i]) { // critical error
1462 av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1463 ret = AVERROR_INVALIDDATA;
1464 goto fail;
1465 }
1466 }
1467 memcpy(c->file_key, output + 8, 16);
1468 memcpy(input, output + 26, 16);
1469 av_sha_init(sha, 160);
1470 av_sha_update(sha, input, 16);
1471 av_sha_update(sha, c->file_key, 16);
1472 av_sha_update(sha, fixed_key, 16);
1473 av_sha_final(sha, c->file_iv);
1474
1475 fail:
1476 av_free(sha);
1477
1478 return ret;
1479 }
1480
1481 static int mov_aaxc_crypto(MOVContext *c)
1482 {
1483 if (c->audible_key_size != 16) {
1484 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n");
1485 return AVERROR(EINVAL);
1486 }
1487
1488 if (c->audible_iv_size != 16) {
1489 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n");
1490 return AVERROR(EINVAL);
1491 }
1492
1493 c->aes_decrypt = av_aes_alloc();
1494 if (!c->aes_decrypt) {
1495 return AVERROR(ENOMEM);
1496 }
1497
1498 memcpy(c->file_key, c->audible_key, 16);
1499 memcpy(c->file_iv, c->audible_iv, 16);
1500 c->aax_mode = 1;
1501
1502 return 0;
1503 }
1504
1505 // Audible AAX (and AAX+) bytestream decryption
1506 static int aax_filter(uint8_t *input, int size, MOVContext *c)
1507 {
1508 int blocks = 0;
1509 unsigned char iv[16];
1510
1511 memcpy(iv, c->file_iv, 16); // iv is overwritten
1512 blocks = size >> 4; // trailing bytes are not encrypted!
1513 av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1514 av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1515
1516 return 0;
1517 }
1518
1519 /* read major brand, minor version and compatible brands and store them as metadata */
1520 468 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1521 {
1522 uint32_t minor_ver;
1523 int comp_brand_size;
1524 char* comp_brands_str;
1525 468 uint8_t type[5] = {0};
1526 468 int ret = ffio_read_size(pb, type, 4);
1527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
468 if (ret < 0)
1528 return ret;
1529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
468 if (c->fc->nb_streams) {
1530 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1531 return AVERROR_INVALIDDATA;
1532 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate FTYP\n");
1533 return 0;
1534 }
1535
1536
2/2
✓ Branch 0 taken 232 times.
✓ Branch 1 taken 236 times.
468 if (strcmp(type, "qt "))
1537 232 c->isom = 1;
1538 468 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1539 468 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1540 468 minor_ver = avio_rb32(pb); /* minor version */
1541 468 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1542
1543 468 comp_brand_size = atom.size - 8;
1544
2/4
✓ Branch 0 taken 468 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 468 times.
468 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1545 return AVERROR_INVALIDDATA;
1546 468 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
468 if (!comp_brands_str)
1548 return AVERROR(ENOMEM);
1549
1550 468 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
468 if (ret < 0) {
1552 av_freep(&comp_brands_str);
1553 return ret;
1554 }
1555 468 comp_brands_str[comp_brand_size] = 0;
1556 468 av_dict_set(&c->fc->metadata, "compatible_brands",
1557 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1558
1559 // Logic for handling Audible's .aaxc files
1560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
468 if (!strcmp(type, "aaxc")) {
1561 mov_aaxc_crypto(c);
1562 }
1563
1564 468 return 0;
1565 }
1566
1567 /* this atom should contain all header atoms */
1568 497 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1569 {
1570 int ret;
1571
1572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 497 times.
497 if (c->found_moov) {
1573 av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1574 avio_skip(pb, atom.size);
1575 return 0;
1576 }
1577
1578
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 497 times.
497 if ((ret = mov_read_default(c, pb, atom)) < 0)
1579 return ret;
1580 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1581 /* so we don't parse the whole file if over a network */
1582 497 c->found_moov=1;
1583 497 return 0; /* now go for mdat */
1584 }
1585
1586 3050 static MOVFragmentStreamInfo * get_frag_stream_info(
1587 MOVFragmentIndex *frag_index,
1588 int index,
1589 int id)
1590 {
1591 int i;
1592 MOVFragmentIndexItem * item;
1593
1594
2/4
✓ Branch 0 taken 3050 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3050 times.
3050 if (index < 0 || index >= frag_index->nb_items)
1595 return NULL;
1596 3050 item = &frag_index->item[index];
1597
1/2
✓ Branch 0 taken 3226 times.
✗ Branch 1 not taken.
3226 for (i = 0; i < item->nb_stream_info; i++)
1598
2/2
✓ Branch 0 taken 3050 times.
✓ Branch 1 taken 176 times.
3226 if (item->stream_info[i].id == id)
1599 3050 return &item->stream_info[i];
1600
1601 // This shouldn't happen
1602 return NULL;
1603 }
1604
1605 493 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1606 {
1607 int i;
1608 MOVFragmentIndexItem * item;
1609
1610
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (frag_index->current < 0 ||
1611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 frag_index->current >= frag_index->nb_items)
1612 return;
1613
1614 493 item = &frag_index->item[frag_index->current];
1615
1/2
✓ Branch 0 taken 551 times.
✗ Branch 1 not taken.
551 for (i = 0; i < item->nb_stream_info; i++)
1616
2/2
✓ Branch 0 taken 493 times.
✓ Branch 1 taken 58 times.
551 if (item->stream_info[i].id == id) {
1617 493 item->current = i;
1618 493 return;
1619 }
1620
1621 // id not found. This shouldn't happen.
1622 item->current = -1;
1623 }
1624
1625 1412 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1626 MOVFragmentIndex *frag_index)
1627 {
1628 MOVFragmentIndexItem *item;
1629
1/2
✓ Branch 0 taken 1412 times.
✗ Branch 1 not taken.
1412 if (frag_index->current < 0 ||
1630
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1409 times.
1412 frag_index->current >= frag_index->nb_items)
1631 3 return NULL;
1632
1633 1409 item = &frag_index->item[frag_index->current];
1634
2/4
✓ Branch 0 taken 1409 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1409 times.
✗ Branch 3 not taken.
1409 if (item->current >= 0 && item->current < item->nb_stream_info)
1635 1409 return &item->stream_info[item->current];
1636
1637 // This shouldn't happen
1638 return NULL;
1639 }
1640
1641 879 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1642 {
1643 int a, b, m;
1644 int64_t moof_offset;
1645
1646 // Optimize for appending new entries
1647
2/2
✓ Branch 0 taken 864 times.
✓ Branch 1 taken 15 times.
879 if (!frag_index->nb_items ||
1648
2/2
✓ Branch 0 taken 458 times.
✓ Branch 1 taken 406 times.
864 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1649 473 return frag_index->nb_items;
1650
1651 406 a = -1;
1652 406 b = frag_index->nb_items;
1653
1654
2/2
✓ Branch 0 taken 2656 times.
✓ Branch 1 taken 406 times.
3062 while (b - a > 1) {
1655 2656 m = (a + b) >> 1;
1656 2656 moof_offset = frag_index->item[m].moof_offset;
1657
2/2
✓ Branch 0 taken 733 times.
✓ Branch 1 taken 1923 times.
2656 if (moof_offset >= offset)
1658 733 b = m;
1659
2/2
✓ Branch 0 taken 2329 times.
✓ Branch 1 taken 327 times.
2656 if (moof_offset <= offset)
1660 2329 a = m;
1661 }
1662 406 return b;
1663 }
1664
1665 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1666 {
1667 av_assert0(frag_stream_info);
1668 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1669 return frag_stream_info->sidx_pts;
1670 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1671 return frag_stream_info->first_tfra_pts;
1672 return frag_stream_info->tfdt_dts;
1673 }
1674
1675 219 static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1676 MOVFragmentIndex *frag_index, int index)
1677 {
1678 MOVFragmentStreamInfo * frag_stream_info;
1679 219 MOVStreamContext *sc = dst_st->priv_data;
1680 int64_t timestamp;
1681 int i, j;
1682
1683 // If the stream is referenced by any sidx, limit the search
1684 // to fragments that referenced this stream in the sidx
1685
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (sc->has_sidx) {
1686 219 frag_stream_info = get_frag_stream_info(frag_index, index, sc->id);
1687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!frag_stream_info)
1688 return AV_NOPTS_VALUE;
1689
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1690 219 return frag_stream_info->sidx_pts;
1691 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1692 return frag_stream_info->first_tfra_pts;
1693 return frag_stream_info->sidx_pts;
1694 }
1695
1696 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
1697 AVStream *frag_stream = NULL;
1698 frag_stream_info = &frag_index->item[index].stream_info[i];
1699 for (j = 0; j < s->nb_streams; j++) {
1700 MOVStreamContext *sc2 = s->streams[j]->priv_data;
1701 if (sc2->id == frag_stream_info->id)
1702 frag_stream = s->streams[j];
1703 }
1704 if (!frag_stream) {
1705 av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1706 continue;
1707 }
1708 timestamp = get_stream_info_time(frag_stream_info);
1709 if (timestamp != AV_NOPTS_VALUE)
1710 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1711 }
1712 return AV_NOPTS_VALUE;
1713 }
1714
1715 26 static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1716 AVStream *st, int64_t timestamp)
1717 {
1718 int a, b, m, m0;
1719 int64_t frag_time;
1720
1721 26 a = -1;
1722 26 b = frag_index->nb_items;
1723
1724
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 26 times.
245 while (b - a > 1) {
1725 219 m0 = m = (a + b) >> 1;
1726
1727
2/4
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 219 times.
438 while (m < b &&
1728 219 (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
1729 m++;
1730
1731
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)
1732 93 a = m;
1733 else
1734 126 b = m0;
1735 }
1736
1737 26 return a;
1738 }
1739
1740 836 static int update_frag_index(MOVContext *c, int64_t offset)
1741 {
1742 int index, i;
1743 MOVFragmentIndexItem * item;
1744 MOVFragmentStreamInfo * frag_stream_info;
1745
1746 // If moof_offset already exists in frag_index, return index to it
1747 836 index = search_frag_moof_offset(&c->frag_index, offset);
1748
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 468 times.
836 if (index < c->frag_index.nb_items &&
1749
1/2
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
368 c->frag_index.item[index].moof_offset == offset)
1750 368 return index;
1751
1752 // offset is not yet in frag index.
1753 // Insert new item at index (sorted by moof offset)
1754 468 item = av_fast_realloc(c->frag_index.item,
1755 468 &c->frag_index.allocated_size,
1756 468 (c->frag_index.nb_items + 1) *
1757 sizeof(*c->frag_index.item));
1758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
468 if (!item)
1759 return -1;
1760 468 c->frag_index.item = item;
1761
1762 468 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1763 sizeof(*item->stream_info));
1764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
468 if (!frag_stream_info)
1765 return -1;
1766
1767
2/2
✓ Branch 0 taken 564 times.
✓ Branch 1 taken 468 times.
1032 for (i = 0; i < c->fc->nb_streams; i++) {
1768 // Avoid building frag index if streams lack track id.
1769 564 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 564 times.
564 if (sc->id < 0) {
1771 av_free(frag_stream_info);
1772 return AVERROR_INVALIDDATA;
1773 }
1774
1775 564 frag_stream_info[i].id = sc->id;
1776 564 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1777 564 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1778 564 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1779 564 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1780 564 frag_stream_info[i].index_base = -1;
1781 564 frag_stream_info[i].index_entry = -1;
1782 564 frag_stream_info[i].encryption_index = NULL;
1783 564 frag_stream_info[i].stsd_id = -1;
1784 }
1785
1786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
468 if (index < c->frag_index.nb_items)
1787 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1788 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1789
1790 468 item = &c->frag_index.item[index];
1791 468 item->headers_read = 0;
1792 468 item->current = 0;
1793 468 item->nb_stream_info = c->fc->nb_streams;
1794 468 item->moof_offset = offset;
1795 468 item->stream_info = frag_stream_info;
1796 468 c->frag_index.nb_items++;
1797
1798 468 return index;
1799 }
1800
1801 493 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1802 int id, int entries)
1803 {
1804 int i;
1805 MOVFragmentStreamInfo * frag_stream_info;
1806
1807
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (index < 0)
1808 493 return;
1809 for (i = index; i < frag_index->nb_items; i++) {
1810 frag_stream_info = get_frag_stream_info(frag_index, i, id);
1811 if (frag_stream_info && frag_stream_info->index_entry >= 0)
1812 frag_stream_info->index_entry += entries;
1813 }
1814 }
1815
1816 467 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1817 {
1818 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1819 467 c->fragment.found_tfhd = 0;
1820
1821
2/4
✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 467 times.
467 if (!c->has_looked_for_mfra && c->use_mfra_for > 0) {
1822 c->has_looked_for_mfra = 1;
1823 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1824 int ret;
1825 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1826 "for a mfra\n");
1827 if ((ret = mov_read_mfra(c, pb)) < 0) {
1828 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1829 "read the mfra (may be a live ismv)\n");
1830 }
1831 } else {
1832 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1833 "seekable, can not look for mfra\n");
1834 }
1835 }
1836 467 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1837 467 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1838 467 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1839 467 return mov_read_default(c, pb, atom);
1840 }
1841
1842 1106 static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version)
1843 {
1844 int64_t time;
1845
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1091 times.
1106 if (version == 1) {
1846 15 time = avio_rb64(pb);
1847 15 avio_rb64(pb);
1848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (time < 0) {
1849 av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n");
1850 return;
1851 }
1852 } else {
1853 1091 time = avio_rb32(pb);
1854 1091 avio_rb32(pb); /* modification time */
1855
4/4
✓ Branch 0 taken 527 times.
✓ Branch 1 taken 564 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 479 times.
1091 if (time > 0 && time < 2082844800) {
1856 48 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1857 48 time += 2082844800;
1858 }
1859 }
1860
2/2
✓ Branch 0 taken 533 times.
✓ Branch 1 taken 573 times.
1106 if (time) {
1861 533 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1862
1863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 533 times.
533 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1864 av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n");
1865 return;
1866 }
1867
1868 533 ff_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1869 }
1870 }
1871
1872 612 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1873 {
1874 AVStream *st;
1875 MOVStreamContext *sc;
1876 int version;
1877 612 char language[4] = {0};
1878 unsigned lang;
1879
1880
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->fc->nb_streams < 1)
1881 return 0;
1882 612 st = c->fc->streams[c->fc->nb_streams-1];
1883 612 sc = st->priv_data;
1884
1885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (sc->time_scale) {
1886 av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
1887 return AVERROR_INVALIDDATA;
1888 }
1889
1890 612 version = avio_r8(pb);
1891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (version > 1) {
1892 avpriv_request_sample(c->fc, "Version %d", version);
1893 return AVERROR_PATCHWELCOME;
1894 }
1895 612 avio_rb24(pb); /* flags */
1896 612 mov_metadata_creation_time(c, pb, &st->metadata, version);
1897
1898 612 sc->time_scale = avio_rb32(pb);
1899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (sc->time_scale <= 0) {
1900 av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
1901 sc->time_scale = 1;
1902 }
1903
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 599 times.
612 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1904
1905
6/6
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 599 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 599 times.
✓ Branch 5 taken 4 times.
612 if ((version == 1 && st->duration == UINT64_MAX) ||
1906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 599 times.
599 (version != 1 && st->duration == UINT32_MAX)) {
1907 9 st->duration = 0;
1908 }
1909
1910 612 lang = avio_rb16(pb); /* language */
1911
2/2
✓ Branch 1 taken 440 times.
✓ Branch 2 taken 172 times.
612 if (ff_mov_lang_to_iso639(lang, language))
1912 440 av_dict_set(&st->metadata, "language", language, 0);
1913 612 avio_rb16(pb); /* quality */
1914
1915 612 return 0;
1916 }
1917
1918 494 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1919 {
1920 int i;
1921 494 int version = avio_r8(pb); /* version */
1922 494 avio_rb24(pb); /* flags */
1923
1924 494 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
1925 494 c->time_scale = avio_rb32(pb); /* time scale */
1926
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 494 times.
494 if (c->time_scale <= 0) {
1927 av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
1928 c->time_scale = 1;
1929 }
1930 494 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
1931
1932
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 492 times.
494 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1933 494 avio_rb32(pb); /* preferred scale */
1934
1935 494 avio_rb16(pb); /* preferred volume */
1936
1937 494 avio_skip(pb, 10); /* reserved */
1938
1939 /* movie display matrix, store it in main context and use it later on */
1940
2/2
✓ Branch 0 taken 1482 times.
✓ Branch 1 taken 494 times.
1976 for (i = 0; i < 3; i++) {
1941 1482 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
1942 1482 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
1943 1482 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
1944 }
1945
1946 494 avio_rb32(pb); /* preview time */
1947 494 avio_rb32(pb); /* preview duration */
1948 494 avio_rb32(pb); /* poster time */
1949 494 avio_rb32(pb); /* selection time */
1950 494 avio_rb32(pb); /* selection duration */
1951 494 avio_rb32(pb); /* current time */
1952 494 avio_rb32(pb); /* next track ID */
1953
1954 494 return 0;
1955 }
1956
1957 7 static void set_last_stream_little_endian(AVFormatContext *fc)
1958 {
1959 AVStream *st;
1960
1961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (fc->nb_streams < 1)
1962 return;
1963 7 st = fc->streams[fc->nb_streams-1];
1964
1965
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) {
1966 5 case AV_CODEC_ID_PCM_S16BE:
1967 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
1968 5 break;
1969 1 case AV_CODEC_ID_PCM_S24BE:
1970 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
1971 1 break;
1972 case AV_CODEC_ID_PCM_S32BE:
1973 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
1974 break;
1975 1 case AV_CODEC_ID_PCM_F32BE:
1976 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
1977 1 break;
1978 case AV_CODEC_ID_PCM_F64BE:
1979 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
1980 break;
1981 default:
1982 break;
1983 }
1984 }
1985
1986 5 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1987 {
1988 5 int little_endian = avio_rb16(pb) & 0xFF;
1989 5 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
1990
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (little_endian == 1)
1991 1 set_last_stream_little_endian(c->fc);
1992 5 return 0;
1993 }
1994
1995 6 static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1996 {
1997 int format_flags;
1998 int version, flags;
1999 int pcm_sample_size;
2000 6 AVFormatContext *fc = c->fc;
2001 AVStream *st;
2002 MOVStreamContext *sc;
2003
2004
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 6) {
2005 av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n");
2006 return AVERROR_INVALIDDATA;
2007 }
2008
2009 6 version = avio_r8(pb);
2010 6 flags = avio_rb24(pb);
2011
2012
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) {
2013 av_log(c->fc, AV_LOG_ERROR,
2014 "Unsupported 'pcmC' box with version %d, flags: %x",
2015 version, flags);
2016 return AVERROR_INVALIDDATA;
2017 }
2018
2019 6 format_flags = avio_r8(pb);
2020 6 pcm_sample_size = avio_r8(pb);
2021
2022
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fc->nb_streams < 1)
2023 return AVERROR_INVALIDDATA;
2024
2025 6 st = fc->streams[fc->nb_streams - 1];
2026 6 sc = st->priv_data;
2027
2028
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (sc->format == MOV_MP4_FPCM_TAG) {
2029
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (pcm_sample_size) {
2030 1 case 32:
2031 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE;
2032 1 break;
2033 case 64:
2034 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE;
2035 break;
2036 default:
2037 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2038 pcm_sample_size,
2039 av_fourcc2str(sc->format));
2040 return AVERROR_INVALIDDATA;
2041 }
2042
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (sc->format == MOV_MP4_IPCM_TAG) {
2043
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 switch (pcm_sample_size) {
2044 5 case 16:
2045 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2046 5 break;
2047 case 24:
2048 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
2049 break;
2050 case 32:
2051 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
2052 break;
2053 default:
2054 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2055 pcm_sample_size,
2056 av_fourcc2str(sc->format));
2057 return AVERROR_INVALIDDATA;
2058 }
2059 } else {
2060 av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n",
2061 av_fourcc2str(sc->format));
2062 return AVERROR_INVALIDDATA;
2063 }
2064
2065
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
2066 6 set_last_stream_little_endian(c->fc);
2067 6 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2068
2069 6 return 0;
2070 }
2071
2072 46 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2073 {
2074 AVStream *st;
2075 46 HEIFItem *item = NULL;
2076 46 char color_parameter_type[5] = { 0 };
2077 uint16_t color_primaries, color_trc, color_matrix;
2078 int ret;
2079
2080 46 st = get_curr_st(c);
2081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!st) {
2082 item = get_heif_item(c, c->cur_item_id);
2083 if (!item)
2084 return 0;
2085 }
2086
2087 46 ret = ffio_read_size(pb, color_parameter_type, 4);
2088
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (ret < 0)
2089 return ret;
2090
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 13 times.
46 if (strncmp(color_parameter_type, "nclx", 4) &&
2091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 strncmp(color_parameter_type, "nclc", 4) &&
2092 strncmp(color_parameter_type, "prof", 4)) {
2093 av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
2094 color_parameter_type);
2095 return 0;
2096 }
2097
2098
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!strncmp(color_parameter_type, "prof", 4)) {
2099 AVPacketSideData *sd;
2100 uint8_t *icc_profile;
2101 if (st) {
2102 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
2103 &st->codecpar->nb_coded_side_data,
2104 AV_PKT_DATA_ICC_PROFILE,
2105 atom.size - 4, 0);
2106 if (!sd)
2107 return AVERROR(ENOMEM);
2108 icc_profile = sd->data;
2109 } else {
2110 av_freep(&item->icc_profile);
2111 icc_profile = item->icc_profile = av_malloc(atom.size - 4);
2112 if (!icc_profile) {
2113 item->icc_profile_size = 0;
2114 return AVERROR(ENOMEM);
2115 }
2116 item->icc_profile_size = atom.size - 4;
2117 }
2118 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
2119 if (ret < 0)
2120 return ret;
2121
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 } else if (st) {
2122 46 color_primaries = avio_rb16(pb);
2123 46 color_trc = avio_rb16(pb);
2124 46 color_matrix = avio_rb16(pb);
2125
2126 46 av_log(c->fc, AV_LOG_TRACE,
2127 "%s: pri %d trc %d matrix %d",
2128 color_parameter_type, color_primaries, color_trc, color_matrix);
2129
2130
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 33 times.
46 if (!strncmp(color_parameter_type, "nclx", 4)) {
2131 13 uint8_t color_range = avio_r8(pb) >> 7;
2132 13 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2133
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
13 if (color_range)
2134 2 st->codecpar->color_range = AVCOL_RANGE_JPEG;
2135 else
2136 11 st->codecpar->color_range = AVCOL_RANGE_MPEG;
2137 }
2138
2139
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if (!av_color_primaries_name(color_primaries))
2140 color_primaries = AVCOL_PRI_UNSPECIFIED;
2141
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if (!av_color_transfer_name(color_trc))
2142 color_trc = AVCOL_TRC_UNSPECIFIED;
2143
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if (!av_color_space_name(color_matrix))
2144 color_matrix = AVCOL_SPC_UNSPECIFIED;
2145
2146 46 st->codecpar->color_primaries = color_primaries;
2147 46 st->codecpar->color_trc = color_trc;
2148 46 st->codecpar->color_space = color_matrix;
2149 46 av_log(c->fc, AV_LOG_TRACE, "\n");
2150 }
2151 46 return 0;
2152 }
2153
2154 118 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2155 {
2156 AVStream *st;
2157 unsigned mov_field_order;
2158 118 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2159
2160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (c->fc->nb_streams < 1) // will happen with jp2 files
2161 return 0;
2162 118 st = c->fc->streams[c->fc->nb_streams-1];
2163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (atom.size < 2)
2164 return AVERROR_INVALIDDATA;
2165 118 mov_field_order = avio_rb16(pb);
2166
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 22 times.
118 if ((mov_field_order & 0xFF00) == 0x0100)
2167 96 decoded_field_order = AV_FIELD_PROGRESSIVE;
2168
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 else if ((mov_field_order & 0xFF00) == 0x0200) {
2169
3/5
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
22 switch (mov_field_order & 0xFF) {
2170 1 case 0x01: decoded_field_order = AV_FIELD_TT;
2171 1 break;
2172 case 0x06: decoded_field_order = AV_FIELD_BB;
2173 break;
2174 1 case 0x09: decoded_field_order = AV_FIELD_TB;
2175 1 break;
2176 20 case 0x0E: decoded_field_order = AV_FIELD_BT;
2177 20 break;
2178 }
2179 }
2180
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
118 if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) {
2181 av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
2182 }
2183 118 st->codecpar->field_order = decoded_field_order;
2184
2185 118 return 0;
2186 }
2187
2188 68 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
2189 {
2190 68 int err = 0;
2191 68 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
2192
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)
2193 return AVERROR_INVALIDDATA;
2194
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
68 if ((err = av_reallocp(&par->extradata, size)) < 0) {
2195 par->extradata_size = 0;
2196 return err;
2197 }
2198 68 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
2199 68 return 0;
2200 }
2201
2202 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
2203 65 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2204 AVCodecParameters *par, uint8_t *buf)
2205 {
2206 65 int64_t result = atom.size;
2207 int err;
2208
2209 65 AV_WB32(buf , atom.size + 8);
2210 65 AV_WL32(buf + 4, atom.type);
2211 65 err = ffio_read_size(pb, buf + 8, atom.size);
2212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (err < 0) {
2213 par->extradata_size -= atom.size;
2214 return err;
2215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 } else if (err < atom.size) {
2216 av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
2217 par->extradata_size -= atom.size - err;
2218 result = err;
2219 }
2220 65 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2221 65 return result;
2222 }
2223
2224 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
2225 58 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2226 enum AVCodecID codec_id)
2227 {
2228 AVStream *st;
2229 uint64_t original_size;
2230 int err;
2231
2232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (c->fc->nb_streams < 1) // will happen with jp2 files
2233 return 0;
2234 58 st = c->fc->streams[c->fc->nb_streams-1];
2235
2236
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
58 if (st->codecpar->codec_id != codec_id)
2237 19 return 0; /* unexpected codec_id - don't mess with extradata */
2238
2239 39 original_size = st->codecpar->extradata_size;
2240 39 err = mov_realloc_extradata(st->codecpar, atom);
2241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err)
2242 return err;
2243
2244 39 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
2245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err < 0)
2246 return err;
2247 39 return 0; // Note: this is the original behavior to ignore truncation.
2248 }
2249
2250 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
2251 16 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2252 {
2253 16 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
2254 }
2255
2256 static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2257 {
2258 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS);
2259 }
2260
2261 static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2262 {
2263 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
2264 }
2265
2266 static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2267 {
2268 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
2269 }
2270
2271 19 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2272 {
2273 19 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
2274
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!ret)
2275 19 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
2276 19 return ret;
2277 }
2278
2279 static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2280 {
2281 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
2282
2283 if (!ret && c->fc->nb_streams >= 1) {
2284 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2285 if (par->extradata_size >= 40) {
2286 par->height = AV_RB16(&par->extradata[36]);
2287 par->width = AV_RB16(&par->extradata[38]);
2288 }
2289 }
2290 return ret;
2291 }
2292
2293 16 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2294 {
2295
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (c->fc->nb_streams >= 1) {
2296 16 AVStream *const st = c->fc->streams[c->fc->nb_streams - 1];
2297 16 FFStream *const sti = ffstream(st);
2298 16 AVCodecParameters *par = st->codecpar;
2299
2300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
2301 par->codec_id == AV_CODEC_ID_H264 &&
2302 atom.size > 11) {
2303 int cid;
2304 avio_skip(pb, 10);
2305 cid = avio_rb16(pb);
2306 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
2307 if (cid == 0xd4d || cid == 0xd4e)
2308 par->width = 1440;
2309 return 0;
2310
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
2311
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
2312
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
2313
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 atom.size >= 24) {
2314 int num, den;
2315 13 avio_skip(pb, 12);
2316 13 num = avio_rb32(pb);
2317 13 den = avio_rb32(pb);
2318
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)
2319 return 0;
2320
2/3
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
13 switch (avio_rb32(pb)) {
2321 12 case 2:
2322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (den >= INT_MAX / 2)
2323 return 0;
2324 12 den *= 2;
2325 13 case 1:
2326 13 sti->display_aspect_ratio = (AVRational){ num, den };
2327 13 default:
2328 13 return 0;
2329 }
2330 }
2331 }
2332
2333 3 return mov_read_avid(c, pb, atom);
2334 }
2335
2336 26 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2337 {
2338 26 int ret = 0;
2339 26 int length = 0;
2340 uint64_t original_size;
2341
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (c->fc->nb_streams >= 1) {
2342 26 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2343
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (par->codec_id == AV_CODEC_ID_H264)
2344 return 0;
2345
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (atom.size == 16) {
2346 26 original_size = par->extradata_size;
2347 26 ret = mov_realloc_extradata(par, atom);
2348
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!ret) {
2349 26 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
2350
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (length == atom.size) {
2351 26 const uint8_t range_value = par->extradata[original_size + 19];
2352
1/3
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
26 switch (range_value) {
2353 26 case 1:
2354 26 par->color_range = AVCOL_RANGE_MPEG;
2355 26 break;
2356 case 2:
2357 par->color_range = AVCOL_RANGE_JPEG;
2358 break;
2359 default:
2360 av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
2361 break;
2362 }
2363 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
2364 } else {
2365 /* For some reason the whole atom was not added to the extradata */
2366 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
2367 }
2368 } else {
2369 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
2370 }
2371 } else {
2372 av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
2373 }
2374 }
2375
2376 26 return ret;
2377 }
2378
2379 4 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2380 {
2381 4 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
2382 }
2383
2384 34 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2385 {
2386 AVStream *st;
2387 int ret;
2388
2389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (c->fc->nb_streams < 1)
2390 return 0;
2391 34 st = c->fc->streams[c->fc->nb_streams-1];
2392
2393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if ((uint64_t)atom.size > (1<<30))
2394 return AVERROR_INVALIDDATA;
2395
2396
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2 times.
34 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2397
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
2399 // pass all frma atom to codec, needed at least for QDMC and QDM2
2400 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2402 return ret;
2403
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 } else if (atom.size > 8) { /* to read frma, esds atoms */
2404
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) {
2405 uint64_t buffer;
2406 10 ret = ffio_ensure_seekback(pb, 8);
2407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2408 return ret;
2409 10 buffer = avio_rb64(pb);
2410 10 atom.size -= 8;
2411
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
2412
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 <= atom.size
2413
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 >= 8) {
2414 10 avio_skip(pb, -8);
2415 10 atom.size += 8;
2416 } else if (!st->codecpar->extradata_size) {
2417 #define ALAC_EXTRADATA_SIZE 36
2418 st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
2419 if (!st->codecpar->extradata)
2420 return AVERROR(ENOMEM);
2421 st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
2422 AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
2423 AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
2424 AV_WB64(st->codecpar->extradata + 12, buffer);
2425 avio_read(pb, st->codecpar->extradata + 20, 16);
2426 avio_skip(pb, atom.size - 24);
2427 return 0;
2428 }
2429 }
2430
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if ((ret = mov_read_default(c, pb, atom)) < 0)
2431 return ret;
2432 } else
2433 avio_skip(pb, atom.size);
2434 34 return 0;
2435 }
2436
2437 /**
2438 * This function reads atom content and puts data in extradata without tag
2439 * nor size unlike mov_read_extradata.
2440 */
2441 152 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2442 {
2443 AVStream *st;
2444 int ret;
2445
2446 152 st = get_curr_st(c);
2447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 152 times.
152 if (!st)
2448 return 0;
2449
2450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 152 times.
152 if ((uint64_t)atom.size > (1<<30))
2451 return AVERROR_INVALIDDATA;
2452
2453
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 151 times.
152 if (atom.type == MKTAG('v','v','c','C')) {
2454 1 avio_skip(pb, 4);
2455 1 atom.size -= 4;
2456 }
2457
2458
2/2
✓ Branch 0 taken 148 times.
✓ Branch 1 taken 4 times.
152 if (atom.size >= 10) {
2459 // Broken files created by legacy versions of libavformat will
2460 // wrap a whole fiel atom inside of a glbl atom.
2461 148 unsigned size = avio_rb32(pb);
2462 148 unsigned type = avio_rl32(pb);
2463
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 148 times.
148 if (avio_feof(pb))
2464 return AVERROR_INVALIDDATA;
2465 148 avio_seek(pb, -8, SEEK_CUR);
2466
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 138 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
148 if (type == MKTAG('f','i','e','l') && size == atom.size)
2467 10 return mov_read_default(c, pb, atom);
2468 }
2469
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
142 if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
2470 av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
2471 return 0;
2472 }
2473 142 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2474
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 142 times.
142 if (ret < 0)
2475 return ret;
2476
3/4
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 43 times.
142 if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
2477 /* HEVC-based Dolby Vision derived from hvc1.
2478 Happens to match with an identifier
2479 previously utilized for DV. Thus, if we have
2480 the hvcC extradata box available as specified,
2481 set codec to HEVC */
2482 st->codecpar->codec_id = AV_CODEC_ID_HEVC;
2483
2484 142 return 0;
2485 }
2486
2487 2 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2488 {
2489 AVStream *st;
2490 uint8_t profile_level;
2491 int ret;
2492
2493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
2494 return 0;
2495 2 st = c->fc->streams[c->fc->nb_streams-1];
2496
2497
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)
2498 return AVERROR_INVALIDDATA;
2499
2500 2 profile_level = avio_r8(pb);
2501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((profile_level & 0xf0) != 0xc0)
2502 return 0;
2503
2504 2 avio_seek(pb, 6, SEEK_CUR);
2505 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
2506
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2507 return ret;
2508
2509 2 return 0;
2510 }
2511
2512 static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2513 {
2514 AVStream* st;
2515 MOVStreamContext* sc;
2516
2517 if (c->fc->nb_streams < 1)
2518 return 0;
2519
2520 /* For SBAS this should be fine - though beware if someone implements a
2521 * tref atom processor that doesn't drop down to default then this may
2522 * be lost. */
2523 if (atom.size > 4) {
2524 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2525 return AVERROR_PATCHWELCOME;
2526 }
2527
2528 st = c->fc->streams[c->fc->nb_streams - 1];
2529 sc = st->priv_data;
2530 sc->tref_id = avio_rb32(pb);
2531 sc->tref_flags |= MOV_TREF_FLAG_ENHANCEMENT;
2532
2533 return 0;
2534 }
2535
2536 /**
2537 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2538 * but can have extradata appended at the end after the 40 bytes belonging
2539 * to the struct.
2540 */
2541 static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2542 {
2543 AVStream *st;
2544 int ret;
2545
2546 if (c->fc->nb_streams < 1)
2547 return 0;
2548 if (atom.size <= 40)
2549 return 0;
2550 st = c->fc->streams[c->fc->nb_streams-1];
2551
2552 if ((uint64_t)atom.size > (1<<30))
2553 return AVERROR_INVALIDDATA;
2554
2555 avio_skip(pb, 40);
2556 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
2557 if (ret < 0)
2558 return ret;
2559
2560 return 0;
2561 }
2562
2563 612 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2564 {
2565 AVStream *st;
2566 MOVStreamContext *sc;
2567 unsigned int i, entries;
2568
2569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->trak_index < 0) {
2570 av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
2571 return 0;
2572 }
2573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->fc->nb_streams < 1)
2574 return 0;
2575 612 st = c->fc->streams[c->fc->nb_streams-1];
2576 612 sc = st->priv_data;
2577
2578 612 avio_r8(pb); /* version */
2579 612 avio_rb24(pb); /* flags */
2580
2581 // Clamp allocation size for `chunk_offsets` -- don't throw an error for an
2582 // invalid count since the EOF path doesn't throw either.
2583 612 entries = avio_rb32(pb);
2584 612 entries =
2585
2/2
✓ Branch 0 taken 607 times.
✓ Branch 1 taken 5 times.
612 FFMIN(entries,
2586 FFMAX(0, (atom.size - 8) /
2587 (atom.type == MKTAG('s', 't', 'c', 'o') ? 4 : 8)));
2588
2589
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 587 times.
612 if (!entries)
2590 25 return 0;
2591
2592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 587 times.
587 if (sc->chunk_offsets) {
2593 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2594 return 0;
2595 }
2596
2597 587 av_free(sc->chunk_offsets);
2598 587 sc->chunk_count = 0;
2599 587 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 587 times.
587 if (!sc->chunk_offsets)
2601 return AVERROR(ENOMEM);
2602 587 sc->chunk_count = entries;
2603
2604
2/2
✓ Branch 0 taken 583 times.
✓ Branch 1 taken 4 times.
587 if (atom.type == MKTAG('s','t','c','o'))
2605
3/4
✓ Branch 0 taken 43274 times.
✓ Branch 1 taken 583 times.
✓ Branch 2 taken 43274 times.
✗ Branch 3 not taken.
43857 for (i = 0; i < entries && !pb->eof_reached; i++)
2606 43274 sc->chunk_offsets[i] = avio_rb32(pb);
2607
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (atom.type == MKTAG('c','o','6','4'))
2608
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++) {
2609 136336 sc->chunk_offsets[i] = avio_rb64(pb);
2610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136336 times.
136336 if (sc->chunk_offsets[i] < 0) {
2611 av_log(c->fc, AV_LOG_WARNING, "Impossible chunk_offset\n");
2612 sc->chunk_offsets[i] = 0;
2613 }
2614 }
2615 else
2616 return AVERROR_INVALIDDATA;
2617
2618 587 sc->chunk_count = i;
2619
2620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 587 times.
587 if (pb->eof_reached) {
2621 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2622 return AVERROR_EOF;
2623 }
2624
2625 587 return 0;
2626 }
2627
2628 659 static int mov_codec_id(AVStream *st, uint32_t format)
2629 {
2630 659 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2631
2632
2/2
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 222 times.
659 if (id <= 0 &&
2633
2/2
✓ Branch 0 taken 434 times.
✓ Branch 1 taken 3 times.
437 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 434 times.
434 (format & 0xFFFF) == 'T' + ('S' << 8)))
2635 3 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2636
2637
4/4
✓ Branch 0 taken 299 times.
✓ Branch 1 taken 360 times.
✓ Branch 2 taken 225 times.
✓ Branch 3 taken 74 times.
659 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2638 225 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2639
3/4
✓ Branch 0 taken 416 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 416 times.
✗ Branch 3 not taken.
434 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2640 /* skip old ASF MPEG-4 tag */
2641
2/2
✓ Branch 0 taken 412 times.
✓ Branch 1 taken 4 times.
416 format && format != MKTAG('m','p','4','s')) {
2642 412 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2643
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 353 times.
412 if (id <= 0)
2644 59 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2645
2/2
✓ Branch 0 taken 357 times.
✓ Branch 1 taken 55 times.
412 if (id > 0)
2646 357 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2647
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 51 times.
55 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2648
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2650 51 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2651
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 6 times.
51 if (id <= 0) {
2652
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 4 times.
86 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2653
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 4 times.
86 AV_CODEC_ID_TTML : id;
2654 }
2655
2656
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 37 times.
51 if (id > 0)
2657 14 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2658 else
2659 37 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2660 }
2661 }
2662
2663 659 st->codecpar->codec_tag = format;
2664
2665 659 return id;
2666 }
2667
2668 326 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2669 AVStream *st, MOVStreamContext *sc)
2670 {
2671 326 uint8_t codec_name[32] = { 0 };
2672 int64_t stsd_start;
2673 unsigned int len;
2674 326 uint32_t id = 0;
2675
2676 /* The first 16 bytes of the video sample description are already
2677 * read in ff_mov_read_stsd_entries() */
2678 326 stsd_start = avio_tell(pb) - 16;
2679
2680 326 avio_rb16(pb); /* version */
2681 326 avio_rb16(pb); /* revision level */
2682 326 id = avio_rl32(pb); /* vendor */
2683 326 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2684 326 avio_rb32(pb); /* temporal quality */
2685 326 avio_rb32(pb); /* spatial quality */
2686
2687 326 st->codecpar->width = avio_rb16(pb); /* width */
2688 326 st->codecpar->height = avio_rb16(pb); /* height */
2689
2690 326 avio_rb32(pb); /* horiz resolution */
2691 326 avio_rb32(pb); /* vert resolution */
2692 326 avio_rb32(pb); /* data size, always 0 */
2693 326 avio_rb16(pb); /* frames per samples */
2694
2695 326 len = avio_r8(pb); /* codec name, pascal string */
2696
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 325 times.
326 if (len > 31)
2697 1 len = 31;
2698 326 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2699
2/2
✓ Branch 0 taken 323 times.
✓ Branch 1 taken 3 times.
326 if (len < 31)
2700 323 avio_skip(pb, 31 - len);
2701
2702
2/2
✓ Branch 0 taken 259 times.
✓ Branch 1 taken 67 times.
326 if (codec_name[0])
2703 259 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2704
2705 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 326 times.
326 if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2707 st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2708 st->codecpar->width &= ~1;
2709 st->codecpar->height &= ~1;
2710 }
2711 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 326 times.
326 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2713 !strncmp(codec_name, "Sorenson H263", 13))
2714 st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2715
2716 326 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2717
2718 326 avio_seek(pb, stsd_start, SEEK_SET);
2719
2720
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 308 times.
326 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2721 18 st->codecpar->bits_per_coded_sample &= 0x1F;
2722 18 sc->has_palette = 1;
2723 }
2724 326 }
2725
2726 243 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2727 AVStream *st, MOVStreamContext *sc)
2728 {
2729 int bits_per_sample, flags;
2730 243 uint16_t version = avio_rb16(pb);
2731 243 uint32_t id = 0;
2732 243 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2733 int channel_count;
2734
2735 243 avio_rb16(pb); /* revision level */
2736 243 id = avio_rl32(pb); /* vendor */
2737 243 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2738
2739 243 channel_count = avio_rb16(pb);
2740
2741 243 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2742 243 st->codecpar->ch_layout.nb_channels = channel_count;
2743 243 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
2744 243 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
2745
2746 243 sc->audio_cid = avio_rb16(pb);
2747 243 avio_rb16(pb); /* packet size = 0 */
2748
2749 243 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
2750
2751 // Read QT version 1 fields. In version 0 these do not exist.
2752 243 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
2753
3/4
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 86 times.
✓ Branch 2 taken 157 times.
✗ Branch 3 not taken.
243 if (!c->isom ||
2754
1/2
✓ Branch 0 taken 157 times.
✗ Branch 1 not taken.
157 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
2755
3/4
✓ Branch 0 taken 157 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 153 times.
157 (sc->stsd_version == 0 && version > 0)) {
2756
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 40 times.
90 if (version == 1) {
2757 50 sc->samples_per_frame = avio_rb32(pb);
2758 50 avio_rb32(pb); /* bytes per packet */
2759 50 sc->bytes_per_frame = avio_rb32(pb);
2760 50 avio_rb32(pb); /* bytes per sample */
2761
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
40 } else if (version == 2) {
2762 4 avio_rb32(pb); /* sizeof struct only */
2763 4 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
2764 4 channel_count = avio_rb32(pb);
2765 4 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2766 4 st->codecpar->ch_layout.nb_channels = channel_count;
2767 4 avio_rb32(pb); /* always 0x7F000000 */
2768 4 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
2769
2770 4 flags = avio_rb32(pb); /* lpcm format specific flag */
2771 4 sc->bytes_per_frame = avio_rb32(pb);
2772 4 sc->samples_per_frame = avio_rb32(pb);
2773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
2774 st->codecpar->codec_id =
2775 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
2776 flags);
2777 }
2778
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)) {
2779 /* can't correctly handle variable sized packet as audio unit */
2780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 switch (st->codecpar->codec_id) {
2781 case AV_CODEC_ID_MP2:
2782 case AV_CODEC_ID_MP3:
2783 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
2784 break;
2785 }
2786 }
2787 }
2788
2789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 243 times.
243 if (sc->format == 0) {
2790 if (st->codecpar->bits_per_coded_sample == 8)
2791 st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
2792 else if (st->codecpar->bits_per_coded_sample == 16)
2793 st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
2794 }
2795
2796
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 201 times.
243 switch (st->codecpar->codec_id) {
2797 7 case AV_CODEC_ID_PCM_S8:
2798 case AV_CODEC_ID_PCM_U8:
2799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
2800 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2801 7 break;
2802 19 case AV_CODEC_ID_PCM_S16LE:
2803 case AV_CODEC_ID_PCM_S16BE:
2804
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
19 if (st->codecpar->bits_per_coded_sample == 8)
2805 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
2806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 24)
2807 st->codecpar->codec_id =
2808 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2809 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
2810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 32)
2811 st->codecpar->codec_id =
2812 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2813 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
2814 19 break;
2815 /* set values for old format before stsd version 1 appeared */
2816 2 case AV_CODEC_ID_MACE3:
2817 2 sc->samples_per_frame = 6;
2818 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
2819 2 break;
2820 8 case AV_CODEC_ID_MACE6:
2821 8 sc->samples_per_frame = 6;
2822 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
2823 8 break;
2824 5 case AV_CODEC_ID_ADPCM_IMA_QT:
2825 5 sc->samples_per_frame = 64;
2826 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
2827 5 break;
2828 1 case AV_CODEC_ID_GSM:
2829 1 sc->samples_per_frame = 160;
2830 1 sc->bytes_per_frame = 33;
2831 1 break;
2832 201 default:
2833 201 break;
2834 }
2835
2836 243 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2837
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 195 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
243 if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->ch_layout.nb_channels <= INT_MAX) {
2838 48 st->codecpar->bits_per_coded_sample = bits_per_sample;
2839 48 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
2840 }
2841 243 }
2842
2843 15 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
2844 AVStream *st, MOVStreamContext *sc,
2845 int64_t size)
2846 {
2847 // ttxt stsd contains display flags, justification, background
2848 // color, fonts, and default styles, so fake an atom to read it
2849 15 MOVAtom fake_atom = { .size = size };
2850 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
2851 // in extradata unlike stpp MP4 TTML.
2852
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
2853
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
15 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
2854 11 mov_read_glbl(c, pb, fake_atom);
2855 15 st->codecpar->width = sc->width;
2856 15 st->codecpar->height = sc->height;
2857 15 }
2858
2859 41 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
2860 AVStream *st, MOVStreamContext *sc,
2861 int64_t size)
2862 {
2863 int ret;
2864
2865
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 22 times.
41 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
2866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if ((int)size != size)
2867 return AVERROR(ENOMEM);
2868
2869 19 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
2870
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
2871 return ret;
2872
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (size > 16) {
2873 19 MOVStreamContext *tmcd_ctx = st->priv_data;
2874 int val;
2875 19 val = AV_RB32(st->codecpar->extradata + 4);
2876 19 tmcd_ctx->tmcd_flags = val;
2877 19 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
2878 19 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
2879 19 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
2880
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (size > 30) {
2881 4 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
2882 4 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
2883
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) {
2884 4 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
2885
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 &&
2886
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 st->codecpar->extradata[30] /* Don't add empty string */) {
2887 4 char *reel_name = av_malloc(str_size + 1);
2888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!reel_name)
2889 return AVERROR(ENOMEM);
2890 4 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
2891 4 reel_name[str_size] = 0; /* Add null terminator */
2892 4 av_dict_set(&st->metadata, "reel_name", reel_name,
2893 AV_DICT_DONT_STRDUP_VAL);
2894 }
2895 }
2896 }
2897 }
2898 } else {
2899 /* other codec type, just skip (rtp, mp4s ...) */
2900 22 avio_skip(pb, size);
2901 }
2902 41 return 0;
2903 }
2904
2905 612 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
2906 AVStream *st, MOVStreamContext *sc)
2907 {
2908 612 FFStream *const sti = ffstream(st);
2909
2910
2/2
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 369 times.
612 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
2911
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 243 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
243 !st->codecpar->sample_rate && sc->time_scale > 1)
2912 st->codecpar->sample_rate = sc->time_scale;
2913
2914 /* special codec parameters handling */
2915
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 69 times.
✓ Branch 9 taken 490 times.
612 switch (st->codecpar->codec_id) {
2916 #if CONFIG_DV_DEMUXER
2917 case AV_CODEC_ID_DVAUDIO:
2918 if (c->dv_fctx) {
2919 avpriv_request_sample(c->fc, "multiple DV audio streams");
2920 return AVERROR(ENOSYS);
2921 }
2922
2923 c->dv_fctx = avformat_alloc_context();
2924 if (!c->dv_fctx) {
2925 av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
2926 return AVERROR(ENOMEM);
2927 }
2928 c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
2929 if (!c->dv_demux) {
2930 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
2931 return AVERROR(ENOMEM);
2932 }
2933 sc->dv_audio_container = 1;
2934 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2935 break;
2936 #endif
2937 /* no ifdef since parameters are always those */
2938 case AV_CODEC_ID_QCELP:
2939 av_channel_layout_uninit(&st->codecpar->ch_layout);
2940 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2941 // force sample rate for qcelp when not stored in mov
2942 if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
2943 st->codecpar->sample_rate = 8000;
2944 // FIXME: Why is the following needed for some files?
2945 sc->samples_per_frame = 160;
2946 if (!sc->bytes_per_frame)
2947 sc->bytes_per_frame = 35;
2948 break;
2949 case AV_CODEC_ID_AMR_NB:
2950 av_channel_layout_uninit(&st->codecpar->ch_layout);
2951 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2952 /* force sample rate for amr, stsd in 3gp does not store sample rate */
2953 st->codecpar->sample_rate = 8000;
2954 break;
2955 11 case AV_CODEC_ID_AMR_WB:
2956 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
2957 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2958 11 st->codecpar->sample_rate = 16000;
2959 11 break;
2960 1 case AV_CODEC_ID_MP2:
2961 case AV_CODEC_ID_MP3:
2962 /* force type after stsd for m1a hdlr */
2963 1 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2964 1 break;
2965 15 case AV_CODEC_ID_GSM:
2966 case AV_CODEC_ID_ADPCM_MS:
2967 case AV_CODEC_ID_ADPCM_IMA_WAV:
2968 case AV_CODEC_ID_ILBC:
2969 case AV_CODEC_ID_MACE3:
2970 case AV_CODEC_ID_MACE6:
2971 case AV_CODEC_ID_QDM2:
2972 15 st->codecpar->block_align = sc->bytes_per_frame;
2973 15 break;
2974 16 case AV_CODEC_ID_ALAC:
2975
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
2976 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
2977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
2978 av_channel_layout_uninit(&st->codecpar->ch_layout);
2979 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2980 st->codecpar->ch_layout.nb_channels = channel_count;
2981 }
2982 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
2983 }
2984 16 break;
2985 10 case AV_CODEC_ID_AC3:
2986 case AV_CODEC_ID_EAC3:
2987 case AV_CODEC_ID_MPEG1VIDEO:
2988 case AV_CODEC_ID_VC1:
2989 case AV_CODEC_ID_VP8:
2990 case AV_CODEC_ID_VP9:
2991 10 sti->need_parsing = AVSTREAM_PARSE_FULL;
2992 10 break;
2993 69 case AV_CODEC_ID_PRORES_RAW:
2994 case AV_CODEC_ID_APV:
2995 case AV_CODEC_ID_EVC:
2996 case AV_CODEC_ID_AV1:
2997 /* field_order detection of H264 requires parsing */
2998 case AV_CODEC_ID_H264:
2999 69 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3000 69 break;
3001 490 default:
3002 490 break;
3003 }
3004 612 return 0;
3005 }
3006
3007 625 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
3008 int codec_tag, int format,
3009 int64_t size)
3010 {
3011
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 612 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
625 if (codec_tag &&
3012 (codec_tag != format &&
3013 // AVID 1:1 samples with differing data format and codec tag exist
3014 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
3015 // prores is allowed to have differing data format and codec tag
3016 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
3017 // so is dv (sigh)
3018 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
3019 (c->fc->video_codec_id ? ff_codec_get_id(ff_codec_movvideo_tags, format) != c->fc->video_codec_id
3020 : codec_tag != MKTAG('j','p','e','g')))) {
3021 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3022 * export it as a separate AVStream but this needs a few changes
3023 * in the MOV demuxer, patch welcome. */
3024
3025 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3026 avio_skip(pb, size);
3027 return 1;
3028 }
3029
3030 625 return 0;
3031 }
3032
3033 625 static int mov_finalize_stsd_entry(MOVContext *c, AVStream *st)
3034 {
3035 int ret;
3036
3037 /* special codec parameters handling */
3038
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 550 times.
625 switch (st->codecpar->codec_id) {
3039 75 case AV_CODEC_ID_H264:
3040 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
3041
1/30
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
75 if (!st->codecpar->extradata_size && TAG_IS_AVCI(st->codecpar->codec_tag)) {
3042 ret = ff_generate_avci_extradata(st);
3043 if (ret < 0)
3044 return ret;
3045 }
3046 75 break;
3047 550 default:
3048 550 break;
3049 }
3050
3051 625 return 0;
3052 }
3053
3054 612 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3055 {
3056 AVStream *st;
3057 MOVStreamContext *sc;
3058 int pseudo_stream_id;
3059
3060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 av_assert0 (c->fc->nb_streams >= 1);
3061 612 st = c->fc->streams[c->fc->nb_streams-1];
3062 612 sc = st->priv_data;
3063
3064 612 for (pseudo_stream_id = 0;
3065
3/4
✓ Branch 0 taken 625 times.
✓ Branch 1 taken 612 times.
✓ Branch 2 taken 625 times.
✗ Branch 3 not taken.
1237 pseudo_stream_id < entries && !pb->eof_reached;
3066 625 pseudo_stream_id++) {
3067 //Parsing Sample description table
3068 enum AVCodecID id;
3069 625 int ret, dref_id = 1;
3070 625 MOVAtom a = { AV_RL32("stsd") };
3071 625 int64_t start_pos = avio_tell(pb);
3072 625 int64_t size = avio_rb32(pb); /* size */
3073 625 uint32_t format = avio_rl32(pb); /* data format */
3074
3075
1/2
✓ Branch 0 taken 625 times.
✗ Branch 1 not taken.
625 if (size >= 16) {
3076 625 avio_rb32(pb); /* reserved */
3077 625 avio_rb16(pb); /* reserved */
3078 625 dref_id = avio_rb16(pb);
3079 } else if (size <= 7) {
3080 av_log(c->fc, AV_LOG_ERROR,
3081 "invalid size %"PRId64" in stsd\n", size);
3082 return AVERROR_INVALIDDATA;
3083 }
3084
3085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
625 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3086 625 size - (avio_tell(pb) - start_pos))) {
3087 sc->stsd_count++;
3088 continue;
3089 }
3090
3091
2/2
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 13 times.
625 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
3092 625 sc->dref_id= dref_id;
3093 625 sc->format = format;
3094
3095 625 id = mov_codec_id(st, format);
3096
3097 625 av_log(c->fc, AV_LOG_TRACE,
3098 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3099 625 av_fourcc2str(format), st->codecpar->codec_type);
3100
3101 625 st->codecpar->codec_id = id;
3102
2/2
✓ Branch 0 taken 326 times.
✓ Branch 1 taken 299 times.
625 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3103 326 mov_parse_stsd_video(c, pb, st, sc);
3104
2/2
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 56 times.
299 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3105 243 mov_parse_stsd_audio(c, pb, st, sc);
3106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 243 times.
243 if (st->codecpar->sample_rate < 0) {
3107 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3108 return AVERROR_INVALIDDATA;
3109 }
3110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 243 times.
243 if (st->codecpar->ch_layout.nb_channels < 0) {
3111 av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3112 return AVERROR_INVALIDDATA;
3113 }
3114
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 41 times.
56 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3115 15 mov_parse_stsd_subtitle(c, pb, st, sc,
3116 15 size - (avio_tell(pb) - start_pos));
3117 } else {
3118 41 ret = mov_parse_stsd_data(c, pb, st, sc,
3119 41 size - (avio_tell(pb) - start_pos));
3120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ret < 0)
3121 return ret;
3122 }
3123 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3124 625 a.size = size - (avio_tell(pb) - start_pos);
3125
2/2
✓ Branch 0 taken 490 times.
✓ Branch 1 taken 135 times.
625 if (a.size > 8) {
3126
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 490 times.
490 if ((ret = mov_read_default(c, pb, a)) < 0)
3127 return ret;
3128
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 134 times.
135 } else if (a.size > 0)
3129 1 avio_skip(pb, a.size);
3130
3131 625 ret = mov_finalize_stsd_entry(c, st);
3132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
625 if (ret < 0)
3133 return ret;
3134
3135
3/4
✓ Branch 0 taken 625 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 350 times.
✓ Branch 3 taken 275 times.
625 if (sc->extradata && st->codecpar->extradata) {
3136 350 int extra_size = st->codecpar->extradata_size;
3137
3138 /* Move the current stream extradata to the stream context one. */
3139 350 sc->extradata_size[pseudo_stream_id] = extra_size;
3140 350 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3141 350 st->codecpar->extradata = NULL;
3142 350 st->codecpar->extradata_size = 0;
3143 }
3144 625 sc->stsd_count++;
3145 }
3146
3147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (pb->eof_reached) {
3148 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3149 return AVERROR_EOF;
3150 }
3151
3152 612 return 0;
3153 }
3154
3155 612 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3156 {
3157 AVStream *st;
3158 MOVStreamContext *sc;
3159 int ret, entries;
3160
3161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->fc->nb_streams < 1)
3162 return 0;
3163 612 st = c->fc->streams[c->fc->nb_streams - 1];
3164 612 sc = st->priv_data;
3165
3166 612 sc->stsd_version = avio_r8(pb);
3167 612 avio_rb24(pb); /* flags */
3168 612 entries = avio_rb32(pb);
3169
3170 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3171
3/6
✓ Branch 0 taken 612 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 612 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 612 times.
612 if (entries <= 0 || entries > atom.size / 8 || entries > 1024) {
3172 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3173 return AVERROR_INVALIDDATA;
3174 }
3175
3176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (sc->extradata) {
3177 av_log(c->fc, AV_LOG_ERROR,
3178 "Duplicate stsd found in this track.\n");
3179 return AVERROR_INVALIDDATA;
3180 }
3181
3182 /* Prepare space for hosting multiple extradata. */
3183 612 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (!sc->extradata)
3185 return AVERROR(ENOMEM);
3186
3187 612 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (!sc->extradata_size) {
3189 ret = AVERROR(ENOMEM);
3190 goto fail;
3191 }
3192
3193 612 ret = ff_mov_read_stsd_entries(c, pb, entries);
3194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (ret < 0)
3195 goto fail;
3196
3197 /* Restore back the primary extradata. */
3198 612 av_freep(&st->codecpar->extradata);
3199 612 st->codecpar->extradata_size = sc->extradata_size[0];
3200
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 274 times.
612 if (sc->extradata_size[0]) {
3201 338 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
338 if (!st->codecpar->extradata)
3203 return AVERROR(ENOMEM);
3204 338 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3205 }
3206
3207 612 return mov_finalize_stsd_codec(c, pb, st, sc);
3208 fail:
3209 if (sc->extradata) {
3210 int j;
3211 for (j = 0; j < sc->stsd_count; j++)
3212 av_freep(&sc->extradata[j]);
3213 }
3214
3215 av_freep(&sc->extradata);
3216 av_freep(&sc->extradata_size);
3217 return ret;
3218 }
3219
3220 612 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3221 {
3222 AVStream *st;
3223 MOVStreamContext *sc;
3224 unsigned int i, entries;
3225
3226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->trak_index < 0) {
3227 av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3228 return 0;
3229 }
3230
3231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->fc->nb_streams < 1)
3232 return 0;
3233 612 st = c->fc->streams[c->fc->nb_streams-1];
3234 612 sc = st->priv_data;
3235
3236 612 avio_r8(pb); /* version */
3237 612 avio_rb24(pb); /* flags */
3238
3239 612 entries = avio_rb32(pb);
3240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if ((uint64_t)entries * 12 + 4 > atom.size)
3241 return AVERROR_INVALIDDATA;
3242
3243 612 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3244
3245
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 588 times.
612 if (!entries)
3246 24 return 0;
3247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 588 times.
588 if (sc->stsc_data) {
3248 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3249 return 0;
3250 }
3251 588 av_free(sc->stsc_data);
3252 588 sc->stsc_count = 0;
3253 588 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 588 times.
588 if (!sc->stsc_data)
3255 return AVERROR(ENOMEM);
3256
3257
3/4
✓ Branch 0 taken 3790 times.
✓ Branch 1 taken 588 times.
✓ Branch 2 taken 3790 times.
✗ Branch 3 not taken.
4378 for (i = 0; i < entries && !pb->eof_reached; i++) {
3258 3790 sc->stsc_data[i].first = avio_rb32(pb);
3259 3790 sc->stsc_data[i].count = avio_rb32(pb);
3260 3790 sc->stsc_data[i].id = avio_rb32(pb);
3261 }
3262
3263 588 sc->stsc_count = i;
3264
2/2
✓ Branch 0 taken 3790 times.
✓ Branch 1 taken 588 times.
4378 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3265 3790 int64_t first_min = i + 1;
3266
5/6
✓ Branch 0 taken 3202 times.
✓ Branch 1 taken 588 times.
✓ Branch 2 taken 3202 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3202 times.
✓ Branch 5 taken 588 times.
3790 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
3267
1/2
✓ Branch 0 taken 3202 times.
✗ Branch 1 not taken.
3202 (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) ||
3268
1/2
✓ Branch 0 taken 3790 times.
✗ Branch 1 not taken.
3790 sc->stsc_data[i].first < first_min ||
3269
1/2
✓ Branch 0 taken 3790 times.
✗ Branch 1 not taken.
3790 sc->stsc_data[i].count < 1 ||
3270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3790 times.
3790 sc->stsc_data[i].id < 1) {
3271 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);
3272 if (i+1 >= sc->stsc_count) {
3273 if (sc->stsc_data[i].count == 0 && i > 0) {
3274 sc->stsc_count --;
3275 continue;
3276 }
3277 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3278 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3279 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3280 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3281 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3282 continue;
3283 }
3284 av_assert0(sc->stsc_data[i+1].first >= 2);
3285 // We replace this entry by the next valid
3286 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3287 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3288 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3289 }
3290 }
3291
3292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 588 times.
588 if (pb->eof_reached) {
3293 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3294 return AVERROR_EOF;
3295 }
3296
3297 588 return 0;
3298 }
3299
3300 341184 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3301 {
3302 341184 return index < count - 1;
3303 }
3304
3305 /* Compute the samples value for the stsc entry at the given index. */
3306 55561 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3307 {
3308 int chunk_count;
3309
3310
2/2
✓ Branch 1 taken 55365 times.
✓ Branch 2 taken 196 times.
55561 if (mov_stsc_index_valid(index, sc->stsc_count))
3311 55365 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3312 else {
3313 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3315 196 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3316 }
3317
3318 55561 return sc->stsc_data[index].count * (int64_t)chunk_count;
3319 }
3320
3321 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3322 {
3323 AVStream *st;
3324 MOVStreamContext *sc;
3325 unsigned i, entries;
3326
3327 if (c->trak_index < 0) {
3328 av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3329 return 0;
3330 }
3331
3332 if (c->fc->nb_streams < 1)
3333 return 0;
3334 st = c->fc->streams[c->fc->nb_streams-1];
3335 sc = st->priv_data;
3336
3337 avio_rb32(pb); // version + flags
3338
3339 entries = avio_rb32(pb);
3340 if (sc->stps_data)
3341 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3342 av_free(sc->stps_data);
3343 sc->stps_count = 0;
3344 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3345 if (!sc->stps_data)
3346 return AVERROR(ENOMEM);
3347
3348 for (i = 0; i < entries && !pb->eof_reached; i++) {
3349 sc->stps_data[i] = avio_rb32(pb);
3350 }
3351
3352 sc->stps_count = i;
3353
3354 if (pb->eof_reached) {
3355 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3356 return AVERROR_EOF;
3357 }
3358
3359 return 0;
3360 }
3361
3362 146 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3363 {
3364 AVStream *st;
3365 FFStream *sti;
3366 MOVStreamContext *sc;
3367 unsigned int i, entries;
3368
3369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (c->trak_index < 0) {
3370 av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3371 return 0;
3372 }
3373
3374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (c->fc->nb_streams < 1)
3375 return 0;
3376 146 st = c->fc->streams[c->fc->nb_streams-1];
3377 146 sti = ffstream(st);
3378 146 sc = st->priv_data;
3379
3380 146 avio_r8(pb); /* version */
3381 146 avio_rb24(pb); /* flags */
3382
3383 146 entries = avio_rb32(pb);
3384
3385 146 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3386
3387
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 140 times.
146 if (!entries) {
3388 6 sc->keyframe_absent = 1;
3389
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)
3390 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3391 6 return 0;
3392 }
3393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (sc->keyframes)
3394 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (entries >= UINT_MAX / sizeof(int))
3396 return AVERROR_INVALIDDATA;
3397 140 av_freep(&sc->keyframes);
3398 140 sc->keyframe_count = 0;
3399 140 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (!sc->keyframes)
3401 return AVERROR(ENOMEM);
3402
3403
3/4
✓ Branch 0 taken 5710 times.
✓ Branch 1 taken 140 times.
✓ Branch 2 taken 5710 times.
✗ Branch 3 not taken.
5850 for (i = 0; i < entries && !pb->eof_reached; i++) {
3404 5710 sc->keyframes[i] = avio_rb32(pb);
3405 }
3406
3407 140 sc->keyframe_count = i;
3408
3409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (pb->eof_reached) {
3410 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3411 return AVERROR_EOF;
3412 }
3413
3414 140 return 0;
3415 }
3416
3417 612 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3418 {
3419 AVStream *st;
3420 MOVStreamContext *sc;
3421 unsigned int i, entries, sample_size, field_size, num_bytes;
3422 GetBitContext gb;
3423 unsigned char* buf;
3424 int ret;
3425
3426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->trak_index < 0) {
3427 av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3428 return 0;
3429 }
3430
3431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->fc->nb_streams < 1)
3432 return 0;
3433 612 st = c->fc->streams[c->fc->nb_streams-1];
3434 612 sc = st->priv_data;
3435
3436 612 avio_r8(pb); /* version */
3437 612 avio_rb24(pb); /* flags */
3438
3439
1/2
✓ Branch 0 taken 612 times.
✗ Branch 1 not taken.
612 if (atom.type == MKTAG('s','t','s','z')) {
3440 612 sample_size = avio_rb32(pb);
3441
2/2
✓ Branch 0 taken 571 times.
✓ Branch 1 taken 41 times.
612 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3442 571 sc->sample_size = sample_size;
3443 612 sc->stsz_sample_size = sample_size;
3444 612 field_size = 32;
3445 } else {
3446 sample_size = 0;
3447 avio_rb24(pb); /* reserved */
3448 field_size = avio_r8(pb);
3449 }
3450 612 entries = avio_rb32(pb);
3451
3452 612 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3453
3454 612 sc->sample_count = entries;
3455
2/2
✓ Branch 0 taken 203 times.
✓ Branch 1 taken 409 times.
612 if (sample_size)
3456 203 return 0;
3457
3458
4/8
✓ Branch 0 taken 409 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 409 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 409 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 409 times.
409 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
3459 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3460 return AVERROR_INVALIDDATA;
3461 }
3462
3463
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 384 times.
409 if (!entries)
3464 25 return 0;
3465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 if (entries >= (INT_MAX - 4 - 8 * AV_INPUT_BUFFER_PADDING_SIZE) / field_size)
3466 return AVERROR_INVALIDDATA;
3467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 if (sc->sample_sizes)
3468 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3469 384 av_free(sc->sample_sizes);
3470 384 sc->sample_count = 0;
3471 384 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 if (!sc->sample_sizes)
3473 return AVERROR(ENOMEM);
3474
3475 384 num_bytes = (entries*field_size+4)>>3;
3476
3477 384 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 if (!buf) {
3479 av_freep(&sc->sample_sizes);
3480 return AVERROR(ENOMEM);
3481 }
3482
3483 384 ret = ffio_read_size(pb, buf, num_bytes);
3484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 if (ret < 0) {
3485 av_freep(&sc->sample_sizes);
3486 av_free(buf);
3487 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3488 return 0;
3489 }
3490
3491 384 init_get_bits(&gb, buf, 8*num_bytes);
3492
3493
2/2
✓ Branch 0 taken 227249 times.
✓ Branch 1 taken 384 times.
227633 for (i = 0; i < entries; i++) {
3494 227249 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 227249 times.
227249 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3496 av_free(buf);
3497 av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3498 return AVERROR_INVALIDDATA;
3499 }
3500 227249 sc->data_size += sc->sample_sizes[i];
3501 }
3502
3503 384 sc->sample_count = i;
3504
3505 384 av_free(buf);
3506
3507 384 return 0;
3508 }
3509
3510 612 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3511 {
3512 AVStream *st;
3513 MOVStreamContext *sc;
3514 unsigned int i, entries;
3515 612 int64_t duration = 0;
3516 612 int64_t total_sample_count = 0;
3517 612 int64_t current_dts = 0;
3518 612 int64_t corrected_dts = 0;
3519
3520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->trak_index < 0) {
3521 av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3522 return 0;
3523 }
3524
3525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->fc->nb_streams < 1)
3526 return 0;
3527 612 st = c->fc->streams[c->fc->nb_streams-1];
3528 612 sc = st->priv_data;
3529
3530 612 avio_r8(pb); /* version */
3531 612 avio_rb24(pb); /* flags */
3532 612 entries = avio_rb32(pb);
3533
3534 612 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3535 612 c->fc->nb_streams-1, entries);
3536
3537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (sc->stts_data)
3538 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3539 612 av_freep(&sc->stts_data);
3540 612 sc->stts_count = 0;
3541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3542 return AVERROR(ENOMEM);
3543
3544
3/4
✓ Branch 0 taken 2950 times.
✓ Branch 1 taken 612 times.
✓ Branch 2 taken 2950 times.
✗ Branch 3 not taken.
3562 for (i = 0; i < entries && !pb->eof_reached; i++) {
3545 unsigned int sample_duration;
3546 unsigned int sample_count;
3547 2950 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3548 2950 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3549 min_entries * sizeof(*sc->stts_data));
3550
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2950 times.
2950 if (!stts_data) {
3551 av_freep(&sc->stts_data);
3552 sc->stts_count = 0;
3553 return AVERROR(ENOMEM);
3554 }
3555 2950 sc->stts_count = min_entries;
3556 2950 sc->stts_data = stts_data;
3557
3558 2950 sample_count = avio_rb32(pb);
3559 2950 sample_duration = avio_rb32(pb);
3560
3561 2950 sc->stts_data[i].count= sample_count;
3562 2950 sc->stts_data[i].duration= sample_duration;
3563
3564 2950 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3565 sample_count, sample_duration);
3566
3567 /* STTS sample offsets are uint32 but some files store it as int32
3568 * with negative values used to correct DTS delays.
3569 There may be abnormally large values as well. */
3570
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2949 times.
2950 if (sample_duration > c->max_stts_delta) {
3571 // assume high delta is a correction if negative when cast as int32
3572 1 int32_t delta_magnitude = (int32_t)sample_duration;
3573 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",
3574 sample_duration, i, sample_count, st->index);
3575 1 sc->stts_data[i].duration = 1;
3576
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);
3577 } else {
3578 2949 corrected_dts += sample_duration * (uint64_t)sample_count;
3579 }
3580
3581 2950 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3582
3583
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2928 times.
2950 if (current_dts > corrected_dts) {
3584 22 int64_t drift = av_sat_sub64(current_dts, corrected_dts) / FFMAX(sample_count, 1);
3585
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;
3586 22 current_dts -= correction * (uint64_t)sample_count;
3587 22 sc->stts_data[i].duration -= correction;
3588 }
3589
3590 2950 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3591 2950 total_sample_count+=sc->stts_data[i].count;
3592 }
3593
3594 612 sc->stts_count = i;
3595
3596
2/2
✓ Branch 0 taken 587 times.
✓ Branch 1 taken 25 times.
612 if (duration > 0 &&
3597
1/2
✓ Branch 0 taken 587 times.
✗ Branch 1 not taken.
587 duration <= INT64_MAX - sc->duration_for_fps &&
3598
1/2
✓ Branch 0 taken 587 times.
✗ Branch 1 not taken.
587 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3599 587 sc->duration_for_fps += duration;
3600 587 sc->nb_frames_for_fps += total_sample_count;
3601 }
3602
3603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (pb->eof_reached) {
3604 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3605 return AVERROR_EOF;
3606 }
3607
3608 612 st->nb_frames= total_sample_count;
3609
2/2
✓ Branch 0 taken 587 times.
✓ Branch 1 taken 25 times.
612 if (duration)
3610 587 st->duration= FFMIN(st->duration, duration);
3611
3612 // All samples have zero duration. They have higher chance be chose by
3613 // mov_find_next_sample, which leads to seek again and again.
3614 //
3615 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3616 // So only mark data stream as discarded for safety.
3617
3/4
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 587 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 25 times.
612 if (!duration && sc->stts_count &&
3618 st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3619 av_log(c->fc, AV_LOG_WARNING,
3620 "All samples in data stream index:id [%d:%d] have zero "
3621 "duration, stream set to be discarded by default. Override "
3622 "using AVStream->discard or -discard for ffmpeg command.\n",
3623 st->index, sc->id);
3624 st->discard = AVDISCARD_ALL;
3625 }
3626 612 sc->track_end = duration;
3627 612 return 0;
3628 }
3629
3630 45 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3631 {
3632 AVStream *st;
3633 MOVStreamContext *sc;
3634 int64_t i, entries;
3635
3636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (c->fc->nb_streams < 1)
3637 return 0;
3638 45 st = c->fc->streams[c->fc->nb_streams - 1];
3639 45 sc = st->priv_data;
3640
3641 45 avio_r8(pb); /* version */
3642 45 avio_rb24(pb); /* flags */
3643 45 entries = atom.size - 4;
3644
3645 45 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3646 45 c->fc->nb_streams - 1, entries);
3647
3648
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 37 times.
45 if (sc->sdtp_data)
3649 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3650 45 av_freep(&sc->sdtp_data);
3651 45 sc->sdtp_count = 0;
3652
3653 45 sc->sdtp_data = av_malloc(entries);
3654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (!sc->sdtp_data)
3655 return AVERROR(ENOMEM);
3656
3657
3/4
✓ Branch 0 taken 3811 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 3811 times.
✗ Branch 3 not taken.
3856 for (i = 0; i < entries && !pb->eof_reached; i++)
3658 3811 sc->sdtp_data[i] = avio_r8(pb);
3659 45 sc->sdtp_count = i;
3660
3661 45 return 0;
3662 }
3663
3664 13275 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3665 {
3666
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 12139 times.
13275 if (duration < 0) {
3667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3668 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3669 duration++;
3670 }
3671 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3672 }
3673 13275 }
3674
3675 63 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3676 {
3677 AVStream *st;
3678 MOVStreamContext *sc;
3679 63 unsigned int i, entries, ctts_count = 0;
3680
3681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->trak_index < 0) {
3682 av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
3683 return 0;
3684 }
3685
3686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->fc->nb_streams < 1)
3687 return 0;
3688 63 st = c->fc->streams[c->fc->nb_streams-1];
3689 63 sc = st->priv_data;
3690
3691 63 avio_r8(pb); /* version */
3692 63 avio_rb24(pb); /* flags */
3693 63 entries = avio_rb32(pb);
3694
3695 63 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3696
3697
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 59 times.
63 if (!entries)
3698 4 return 0;
3699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
3700 return AVERROR_INVALIDDATA;
3701 59 av_freep(&sc->ctts_data);
3702 59 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
3703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->ctts_data)
3704 return AVERROR(ENOMEM);
3705
3706
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++) {
3707 MOVCtts *ctts_data;
3708 4874 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
3709 4874 const size_t requested_size =
3710 4874 min_size_needed > sc->ctts_allocated_size ?
3711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
3712 min_size_needed;
3713 4874 int count = avio_rb32(pb);
3714 4874 int duration = avio_rb32(pb);
3715
3716
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (count <= 0) {
3717 av_log(c->fc, AV_LOG_TRACE,
3718 "ignoring CTTS entry with count=%d duration=%d\n",
3719 count, duration);
3720 continue;
3721 }
3722
3723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
3724 return AVERROR(ENOMEM);
3725
3726 4874 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
3727
3728
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (!ctts_data)
3729 return AVERROR(ENOMEM);
3730
3731 4874 sc->ctts_data = ctts_data;
3732
3733 4874 ctts_data[ctts_count].count = count;
3734 4874 ctts_data[ctts_count].offset = duration;
3735 4874 ctts_count++;
3736
3737 4874 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
3738 count, duration);
3739
3740
2/2
✓ Branch 0 taken 4761 times.
✓ Branch 1 taken 113 times.
4874 if (i+2<entries)
3741 4761 mov_update_dts_shift(sc, duration, c->fc);
3742 }
3743
3744 59 sc->ctts_count = ctts_count;
3745
3746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (pb->eof_reached) {
3747 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
3748 return AVERROR_EOF;
3749 }
3750
3751 59 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
3752
3753 59 return 0;
3754 }
3755
3756 29 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3757 {
3758 AVStream *st;
3759 MOVStreamContext *sc;
3760 uint8_t version;
3761 uint32_t grouping_type;
3762 uint32_t default_length;
3763 av_unused uint32_t default_group_description_index;
3764 uint32_t entry_count;
3765
3766
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (c->fc->nb_streams < 1)
3767 return 0;
3768 29 st = c->fc->streams[c->fc->nb_streams - 1];
3769 29 sc = st->priv_data;
3770
3771 29 version = avio_r8(pb); /* version */
3772 29 avio_rb24(pb); /* flags */
3773 29 grouping_type = avio_rl32(pb);
3774
3775 /*
3776 * This function only supports "sync" boxes, but the code is able to parse
3777 * other boxes (such as "tscl", "tsas" and "stsa")
3778 */
3779
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 5 times.
29 if (grouping_type != MKTAG('s','y','n','c'))
3780 24 return 0;
3781
3782
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
3783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
3784 5 entry_count = avio_rb32(pb);
3785
3786 5 av_freep(&sc->sgpd_sync);
3787 5 sc->sgpd_sync_count = entry_count;
3788 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
3789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
3790 return AVERROR(ENOMEM);
3791
3792
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++) {
3793 8 uint32_t description_length = default_length;
3794
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)
3795 description_length = avio_rb32(pb);
3796
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
3797 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
3798 8 sc->sgpd_sync[i] = nal_unit_type;
3799 8 description_length -= 1;
3800 }
3801 8 avio_skip(pb, description_length);
3802 }
3803
3804
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
3805 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
3806 return AVERROR_EOF;
3807 }
3808
3809 5 return 0;
3810 }
3811
3812 26 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3813 {
3814 AVStream *st;
3815 MOVStreamContext *sc;
3816 unsigned int i, entries;
3817 uint8_t version;
3818 uint32_t grouping_type;
3819 MOVSbgp *table, **tablep;
3820 int *table_count;
3821
3822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (c->fc->nb_streams < 1)
3823 return 0;
3824 26 st = c->fc->streams[c->fc->nb_streams-1];
3825 26 sc = st->priv_data;
3826
3827 26 version = avio_r8(pb); /* version */
3828 26 avio_rb24(pb); /* flags */
3829 26 grouping_type = avio_rl32(pb);
3830
3831
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 25 times.
26 if (grouping_type == MKTAG('r','a','p',' ')) {
3832 1 tablep = &sc->rap_group;
3833 1 table_count = &sc->rap_group_count;
3834
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 20 times.
25 } else if (grouping_type == MKTAG('s','y','n','c')) {
3835 5 tablep = &sc->sync_group;
3836 5 table_count = &sc->sync_group_count;
3837 } else {
3838 20 return 0;
3839 }
3840
3841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
3842 avio_rb32(pb); /* grouping_type_parameter */
3843
3844 6 entries = avio_rb32(pb);
3845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
3846 return 0;
3847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
3848 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
3849 6 av_freep(tablep);
3850 6 table = av_malloc_array(entries, sizeof(*table));
3851
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
3852 return AVERROR(ENOMEM);
3853 6 *tablep = table;
3854
3855
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++) {
3856 32 table[i].count = avio_rb32(pb); /* sample_count */
3857 32 table[i].index = avio_rb32(pb); /* group_description_index */
3858 }
3859
3860 6 *table_count = i;
3861
3862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
3863 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
3864 return AVERROR_EOF;
3865 }
3866
3867 6 return 0;
3868 }
3869
3870 /**
3871 * Get ith edit list entry (media time, duration).
3872 */
3873 913 static int get_edit_list_entry(MOVContext *mov,
3874 const MOVStreamContext *msc,
3875 unsigned int edit_list_index,
3876 int64_t *edit_list_media_time,
3877 int64_t *edit_list_duration,
3878 int64_t global_timescale)
3879 {
3880
2/2
✓ Branch 0 taken 443 times.
✓ Branch 1 taken 470 times.
913 if (edit_list_index == msc->elst_count) {
3881 443 return 0;
3882 }
3883 470 *edit_list_media_time = msc->elst_data[edit_list_index].time;
3884 470 *edit_list_duration = msc->elst_data[edit_list_index].duration;
3885
3886 /* duration is in global timescale units;convert to msc timescale */
3887
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 if (global_timescale == 0) {
3888 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
3889 return 0;
3890 }
3891 470 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
3892 global_timescale);
3893
3894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 if (*edit_list_duration + (uint64_t)*edit_list_media_time > INT64_MAX)
3895 *edit_list_duration = 0;
3896
3897 470 return 1;
3898 }
3899
3900 /**
3901 * Find the closest previous frame to the timestamp_pts, in e_old index
3902 * entries. Searching for just any frame / just key frames can be controlled by
3903 * last argument 'flag'.
3904 * Note that if ctts_data is not NULL, we will always search for a key frame
3905 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
3906 * return the first frame of the video.
3907 *
3908 * Here the timestamp_pts is considered to be a presentation timestamp and
3909 * the timestamp of index entries are considered to be decoding timestamps.
3910 *
3911 * Returns 0 if successful in finding a frame, else returns -1.
3912 * Places the found index corresponding output arg.
3913 *
3914 * If ctts_old is not NULL, then refines the searched entry by searching
3915 * backwards from the found timestamp, to find the frame with correct PTS.
3916 *
3917 * Places the found ctts_index and ctts_sample in corresponding output args.
3918 */
3919 469 static int find_prev_closest_index(AVStream *st,
3920 AVIndexEntry *e_old,
3921 int nb_old,
3922 MOVTimeToSample *tts_data,
3923 int64_t tts_count,
3924 int64_t timestamp_pts,
3925 int flag,
3926 int64_t* index,
3927 int64_t* tts_index,
3928 int64_t* tts_sample)
3929 {
3930 469 MOVStreamContext *msc = st->priv_data;
3931 469 FFStream *const sti = ffstream(st);
3932 469 AVIndexEntry *e_keep = sti->index_entries;
3933 469 int nb_keep = sti->nb_index_entries;
3934 469 int64_t i = 0;
3935
3936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 469 times.
469 av_assert0(index);
3937
3938 // If dts_shift > 0, then all the index timestamps will have to be offset by
3939 // at least dts_shift amount to obtain PTS.
3940 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
3941
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 460 times.
469 if (msc->dts_shift > 0) {
3942 9 timestamp_pts -= msc->dts_shift;
3943 }
3944
3945 469 sti->index_entries = e_old;
3946 469 sti->nb_index_entries = nb_old;
3947 469 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
3948
3949 // Keep going backwards in the index entries until the timestamp is the same.
3950
2/2
✓ Branch 0 taken 468 times.
✓ Branch 1 taken 1 times.
469 if (*index >= 0) {
3951
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 444 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
468 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
3952 i--) {
3953 if ((flag & AVSEEK_FLAG_ANY) ||
3954 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
3955 *index = i - 1;
3956 }
3957 }
3958 }
3959
3960 // If we have CTTS then refine the search, by searching backwards over PTS
3961 // computed by adding corresponding CTTS durations to index timestamps.
3962
4/4
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 405 times.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 1 times.
469 if (msc->ctts_count && *index >= 0) {
3963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(tts_index);
3964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(tts_sample);
3965 // Find out the ctts_index for the found frame.
3966 63 *tts_index = 0;
3967 63 *tts_sample = 0;
3968
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++) {
3969
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (*tts_index < tts_count) {
3970 175 (*tts_sample)++;
3971
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (tts_data[*tts_index].count == *tts_sample) {
3972 175 (*tts_index)++;
3973 175 *tts_sample = 0;
3974 }
3975 }
3976 }
3977
3978
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) {
3979 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
3980 // No need to add dts_shift to the timestamp here because timestamp_pts has already been
3981 // compensated by dts_shift above.
3982
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 &&
3983
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 4 times.
62 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
3984 58 break;
3985 }
3986
3987 12 (*index)--;
3988
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (*tts_sample == 0) {
3989 12 (*tts_index)--;
3990
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 if (*tts_index >= 0)
3991 7 *tts_sample = tts_data[*tts_index].count - 1;
3992 } else {
3993 (*tts_sample)--;
3994 }
3995 }
3996 }
3997
3998 /* restore AVStream state*/
3999 469 sti->index_entries = e_keep;
4000 469 sti->nb_index_entries = nb_keep;
4001
2/2
✓ Branch 0 taken 463 times.
✓ Branch 1 taken 6 times.
469 return *index >= 0 ? 0 : -1;
4002 }
4003
4004 /**
4005 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
4006 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
4007 *
4008 * This function is similar to ff_add_index_entry in libavformat/utils.c
4009 * except that here we are always unconditionally adding an index entry to
4010 * the end, instead of searching the entries list and skipping the add if
4011 * there is an existing entry with the same timestamp.
4012 * This is needed because the mov_fix_index calls this func with the same
4013 * unincremented timestamp for successive discarded frames.
4014 */
4015 348561 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
4016 int size, int distance, int flags)
4017 {
4018 348561 FFStream *const sti = ffstream(st);
4019 AVIndexEntry *entries, *ie;
4020 348561 int64_t index = -1;
4021 348561 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
4022
4023 // Double the allocation each time, to lower memory fragmentation.
4024 // Another difference from ff_add_index_entry function.
4025 348561 const size_t requested_size =
4026 348561 min_size_needed > sti->index_entries_allocated_size ?
4027
2/2
✓ Branch 0 taken 1982 times.
✓ Branch 1 taken 346579 times.
348561 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
4028 min_size_needed;
4029
4030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348561 times.
348561 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
4031 return -1;
4032
4033 348561 entries = av_fast_realloc(sti->index_entries,
4034 &sti->index_entries_allocated_size,
4035 requested_size);
4036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348561 times.
348561 if (!entries)
4037 return -1;
4038
4039 348561 sti->index_entries = entries;
4040
4041 348561 index = sti->nb_index_entries++;
4042 348561 ie= &entries[index];
4043
4044 348561 ie->pos = pos;
4045 348561 ie->timestamp = timestamp;
4046 348561 ie->min_distance= distance;
4047 348561 ie->size= size;
4048 348561 ie->flags = flags;
4049 348561 return index;
4050 }
4051
4052 /**
4053 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4054 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4055 */
4056 27 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4057 int64_t* frame_duration_buffer,
4058 int frame_duration_buffer_size) {
4059 27 FFStream *const sti = ffstream(st);
4060 27 int i = 0;
4061
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);
4062
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 27 times.
164 for (i = 0; i < frame_duration_buffer_size; i++) {
4063 137 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4064 137 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4065 }
4066 27 }
4067
4068 186062 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4069 int count, int offset, unsigned int duration)
4070 {
4071 MOVTimeToSample *tts_buf_new;
4072 186062 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4073 186062 const size_t requested_size =
4074 186062 min_size_needed > *allocated_size ?
4075
2/2
✓ Branch 0 taken 1349 times.
✓ Branch 1 taken 184713 times.
186062 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4076 min_size_needed;
4077
4078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186062 times.
186062 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4079 return -1;
4080
4081 186062 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4082
4083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186062 times.
186062 if (!tts_buf_new)
4084 return -1;
4085
4086 186062 *tts_data = tts_buf_new;
4087
4088 186062 tts_buf_new[*tts_count].count = count;
4089 186062 tts_buf_new[*tts_count].offset = offset;
4090 186062 tts_buf_new[*tts_count].duration = duration;
4091
4092 186062 *tts_count = (*tts_count) + 1;
4093 186062 return 0;
4094 }
4095
4096 #define MAX_REORDER_DELAY 16
4097 618 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4098 {
4099 618 MOVStreamContext *msc = st->priv_data;
4100 618 FFStream *const sti = ffstream(st);
4101 618 int ctts_ind = 0;
4102 618 int ctts_sample = 0;
4103 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4104 618 int buf_start = 0;
4105 int j, r, num_swaps;
4106
4107
2/2
✓ Branch 0 taken 10506 times.
✓ Branch 1 taken 618 times.
11124 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4108 10506 pts_buf[j] = INT64_MIN;
4109
4110
3/4
✓ Branch 0 taken 618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 559 times.
618 if (st->codecpar->video_delay <= 0 && msc->ctts_count &&
4111
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 16 times.
59 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4112 43 st->codecpar->video_delay = 0;
4113
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) {
4114 // Point j to the last elem of the buffer and insert the current pts there.
4115 138279 j = buf_start;
4116 138279 buf_start = (buf_start + 1);
4117
2/2
✓ Branch 0 taken 8111 times.
✓ Branch 1 taken 130168 times.
138279 if (buf_start == MAX_REORDER_DELAY + 1)
4118 8111 buf_start = 0;
4119
4120 138279 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4121
4122 // The timestamps that are already in the sorted buffer, and are greater than the
4123 // current pts, are exactly the timestamps that need to be buffered to output PTS
4124 // in correct sorted order.
4125 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4126 // can be computed as the maximum no. of swaps any particular timestamp needs to
4127 // go through, to keep this buffer in sorted order.
4128 138279 num_swaps = 0;
4129
2/2
✓ Branch 0 taken 142294 times.
✓ Branch 1 taken 4 times.
142298 while (j != buf_start) {
4130 142294 r = j - 1;
4131
2/2
✓ Branch 0 taken 8389 times.
✓ Branch 1 taken 133905 times.
142294 if (r < 0) r = MAX_REORDER_DELAY;
4132
2/2
✓ Branch 0 taken 4019 times.
✓ Branch 1 taken 138275 times.
142294 if (pts_buf[j] < pts_buf[r]) {
4133 4019 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4134 4019 ++num_swaps;
4135 } else {
4136 138275 break;
4137 }
4138 4019 j = r;
4139 }
4140 138279 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4141
4142 138279 ctts_sample++;
4143
1/2
✓ Branch 0 taken 138279 times.
✗ Branch 1 not taken.
138279 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4144 138279 ctts_ind++;
4145 138279 ctts_sample = 0;
4146 }
4147 }
4148 43 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4149 43 st->codecpar->video_delay, st->index);
4150 }
4151 618 }
4152
4153 105962 static void mov_current_sample_inc(MOVStreamContext *sc)
4154 {
4155 105962 sc->current_sample++;
4156 105962 sc->current_index++;
4157
2/2
✓ Branch 0 taken 61450 times.
✓ Branch 1 taken 44512 times.
105962 if (sc->index_ranges &&
4158
2/2
✓ Branch 0 taken 428 times.
✓ Branch 1 taken 61022 times.
61450 sc->current_index >= sc->current_index_range->end &&
4159
1/2
✓ Branch 0 taken 428 times.
✗ Branch 1 not taken.
428 sc->current_index_range->end) {
4160 428 sc->current_index_range++;
4161 428 sc->current_index = sc->current_index_range->start;
4162 }
4163 105962 }
4164
4165 static void mov_current_sample_dec(MOVStreamContext *sc)
4166 {
4167 sc->current_sample--;
4168 sc->current_index--;
4169 if (sc->index_ranges &&
4170 sc->current_index < sc->current_index_range->start &&
4171 sc->current_index_range > sc->index_ranges) {
4172 sc->current_index_range--;
4173 sc->current_index = sc->current_index_range->end - 1;
4174 }
4175 }
4176
4177 335 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4178 {
4179 int64_t range_size;
4180
4181 335 sc->current_sample = current_sample;
4182 335 sc->current_index = current_sample;
4183
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 309 times.
335 if (!sc->index_ranges) {
4184 26 return;
4185 }
4186
4187 309 for (sc->current_index_range = sc->index_ranges;
4188
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 sc->current_index_range->end;
4189 sc->current_index_range++) {
4190 309 range_size = sc->current_index_range->end - sc->current_index_range->start;
4191
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 if (range_size > current_sample) {
4192 309 sc->current_index = sc->current_index_range->start + current_sample;
4193 309 break;
4194 }
4195 current_sample -= range_size;
4196 }
4197 }
4198
4199 /**
4200 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4201 * which are needed to decode them) that fall in the edit list time ranges.
4202 * Also fixes the timestamps of the index entries to match the timeline
4203 * specified the edit lists.
4204 */
4205 618 static void mov_fix_index(MOVContext *mov, AVStream *st)
4206 {
4207 618 MOVStreamContext *msc = st->priv_data;
4208 618 FFStream *const sti = ffstream(st);
4209 618 AVIndexEntry *e_old = sti->index_entries;
4210 618 int nb_old = sti->nb_index_entries;
4211 618 const AVIndexEntry *e_old_end = e_old + nb_old;
4212 618 const AVIndexEntry *current = NULL;
4213 618 MOVTimeToSample *tts_data_old = msc->tts_data;
4214 618 int64_t tts_index_old = 0;
4215 618 int64_t tts_sample_old = 0;
4216 618 int64_t tts_count_old = msc->tts_count;
4217 618 int64_t edit_list_media_time = 0;
4218 618 int64_t edit_list_duration = 0;
4219 618 int64_t frame_duration = 0;
4220 618 int64_t edit_list_dts_counter = 0;
4221 618 int64_t edit_list_dts_entry_end = 0;
4222 618 int64_t edit_list_start_tts_sample = 0;
4223 int64_t curr_cts;
4224 618 int64_t curr_ctts = 0;
4225 618 int64_t empty_edits_sum_duration = 0;
4226 618 int64_t edit_list_index = 0;
4227 int64_t index;
4228 int flags;
4229 618 int64_t start_dts = 0;
4230 618 int64_t edit_list_start_encountered = 0;
4231 618 int64_t search_timestamp = 0;
4232 618 int64_t* frame_duration_buffer = NULL;
4233 618 int num_discarded_begin = 0;
4234 618 int first_non_zero_audio_edit = -1;
4235 618 int packet_skip_samples = 0;
4236 618 MOVIndexRange *current_index_range = NULL;
4237 618 int found_keyframe_after_edit = 0;
4238 618 int found_non_empty_edit = 0;
4239
4240
4/6
✓ Branch 0 taken 443 times.
✓ Branch 1 taken 175 times.
✓ Branch 2 taken 443 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 443 times.
618 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
4241 175 return;
4242 }
4243
4244 // allocate the index ranges array
4245 443 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4246 sizeof(msc->index_ranges[0]));
4247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 443 times.
443 if (!msc->index_ranges) {
4248 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4249 return;
4250 }
4251 443 msc->current_index_range = msc->index_ranges;
4252
4253 // Clean AVStream from traces of old index
4254 443 sti->index_entries = NULL;
4255 443 sti->index_entries_allocated_size = 0;
4256 443 sti->nb_index_entries = 0;
4257
4258 // Clean time to sample fields of MOVStreamContext
4259 443 msc->tts_data = NULL;
4260 443 msc->tts_count = 0;
4261 443 msc->tts_index = 0;
4262 443 msc->tts_sample = 0;
4263 443 msc->tts_allocated_size = 0;
4264
4265 // Reinitialize min_corrected_pts so that it can be computed again.
4266 443 msc->min_corrected_pts = -1;
4267
4268 // If the dts_shift is positive (in case of negative ctts values in mov),
4269 // then negate the DTS by dts_shift
4270
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 434 times.
443 if (msc->dts_shift > 0) {
4271 9 edit_list_dts_entry_end -= msc->dts_shift;
4272 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4273 }
4274
4275 443 start_dts = edit_list_dts_entry_end;
4276
4277
2/2
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 443 times.
1356 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
4278 913 &edit_list_duration, mov->time_scale)) {
4279 470 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4280 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4281 470 edit_list_index++;
4282 470 edit_list_dts_counter = edit_list_dts_entry_end;
4283 470 edit_list_dts_entry_end += edit_list_duration;
4284 470 num_discarded_begin = 0;
4285
4/4
✓ Branch 0 taken 447 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 443 times.
470 if (!found_non_empty_edit && edit_list_media_time == -1) {
4286 4 empty_edits_sum_duration += edit_list_duration;
4287 4 continue;
4288 }
4289 466 found_non_empty_edit = 1;
4290
4291 // If we encounter a non-negative edit list reset the skip_samples/start_pad fields and set them
4292 // according to the edit list below.
4293
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 339 times.
466 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4294
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit < 0) {
4295 127 first_non_zero_audio_edit = 1;
4296 } else {
4297 first_non_zero_audio_edit = 0;
4298 }
4299
4300
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit > 0)
4301 127 sti->skip_samples = msc->start_pad = 0;
4302 }
4303
4304 // While reordering frame index according to edit list we must handle properly
4305 // the scenario when edit list entry starts from none key frame.
4306 // We find closest previous key frame and preserve it and consequent frames in index.
4307 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4308 466 search_timestamp = edit_list_media_time;
4309
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 339 times.
466 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4310 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4311 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4312 // edit_list_media_time to cover the decoder delay.
4313 127 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
4314 }
4315
4316
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 463 times.
466 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, 0,
4317 &index, &tts_index_old, &tts_sample_old) < 0) {
4318 3 av_log(mov->fc, AV_LOG_WARNING,
4319 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4320 st->index, edit_list_index, search_timestamp);
4321
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,
4322 &index, &tts_index_old, &tts_sample_old) < 0) {
4323 3 av_log(mov->fc, AV_LOG_WARNING,
4324 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4325 st->index, edit_list_index, search_timestamp);
4326 3 index = 0;
4327 3 tts_index_old = 0;
4328 3 tts_sample_old = 0;
4329 }
4330 }
4331 466 current = e_old + index;
4332 466 edit_list_start_tts_sample = tts_sample_old;
4333
4334 // Iterate over index and arrange it according to edit list
4335 466 edit_list_start_encountered = 0;
4336 466 found_keyframe_after_edit = 0;
4337
2/2
✓ Branch 0 taken 348561 times.
✓ Branch 1 taken 114 times.
348675 for (; current < e_old_end; current++, index++) {
4338 // check if frame outside edit list mark it for discard
4339 697122 frame_duration = (current + 1 < e_old_end) ?
4340
2/2
✓ Branch 0 taken 348122 times.
✓ Branch 1 taken 439 times.
348561 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4341
4342 348561 flags = current->flags;
4343
4344 // frames (pts) before or after edit list
4345 348561 curr_cts = current->timestamp + msc->dts_shift;
4346 348561 curr_ctts = 0;
4347
4348
4/4
✓ Branch 0 taken 186074 times.
✓ Branch 1 taken 162487 times.
✓ Branch 2 taken 186062 times.
✓ Branch 3 taken 12 times.
348561 if (tts_data_old && tts_index_old < tts_count_old) {
4349 186062 curr_ctts = tts_data_old[tts_index_old].offset;
4350 186062 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4351 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4352 186062 curr_cts += curr_ctts;
4353 186062 tts_sample_old++;
4354
1/2
✓ Branch 0 taken 186062 times.
✗ Branch 1 not taken.
186062 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186062 times.
186062 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4356 &msc->tts_allocated_size,
4357 186062 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4358 186062 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4359 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4360 tts_index_old,
4361 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4362 tts_data_old[tts_index_old].offset);
4363 break;
4364 }
4365 186062 tts_index_old++;
4366 186062 tts_sample_old = 0;
4367 186062 edit_list_start_tts_sample = 0;
4368 }
4369 }
4370
4371
4/4
✓ Branch 0 taken 348409 times.
✓ Branch 1 taken 152 times.
✓ Branch 2 taken 130 times.
✓ Branch 3 taken 348279 times.
348561 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
4372
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 &&
4373
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 &&
4374 first_non_zero_audio_edit > 0) {
4375 11 packet_skip_samples = edit_list_media_time - curr_cts;
4376 11 sti->skip_samples += packet_skip_samples;
4377
4378 // Shift the index entry timestamp by packet_skip_samples to be correct.
4379 11 edit_list_dts_counter -= packet_skip_samples;
4380
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (edit_list_start_encountered == 0) {
4381 11 edit_list_start_encountered = 1;
4382 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4383 // discarded packets.
4384
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 if (frame_duration_buffer) {
4385 6 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4386 frame_duration_buffer, num_discarded_begin);
4387 6 av_freep(&frame_duration_buffer);
4388 }
4389 }
4390
4391 11 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4392 } else {
4393 271 flags |= AVINDEX_DISCARD_FRAME;
4394 271 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4395
4396
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 132 times.
271 if (edit_list_start_encountered == 0) {
4397 139 num_discarded_begin++;
4398 139 frame_duration_buffer = av_realloc(frame_duration_buffer,
4399 num_discarded_begin * sizeof(int64_t));
4400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if (!frame_duration_buffer) {
4401 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4402 break;
4403 }
4404 139 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4405
4406 // Increment skip_samples for the first non-zero audio edit list
4407
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 &&
4408
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) {
4409 20 sti->skip_samples += frame_duration;
4410 }
4411 }
4412 }
4413 } else {
4414
2/2
✓ Branch 0 taken 442 times.
✓ Branch 1 taken 347837 times.
348279 if (msc->min_corrected_pts < 0) {
4415 442 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4416 } else {
4417 347837 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4418 }
4419
2/2
✓ Branch 0 taken 453 times.
✓ Branch 1 taken 347826 times.
348279 if (edit_list_start_encountered == 0) {
4420 453 edit_list_start_encountered = 1;
4421 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4422 // discarded packets.
4423
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 432 times.
453 if (frame_duration_buffer) {
4424 21 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4425 frame_duration_buffer, num_discarded_begin);
4426 21 av_freep(&frame_duration_buffer);
4427 }
4428 }
4429 }
4430
4431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348561 times.
348561 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
4432 348561 current->min_distance, flags) == -1) {
4433 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4434 break;
4435 }
4436
4437 // Update the index ranges array
4438
4/4
✓ Branch 0 taken 348118 times.
✓ Branch 1 taken 443 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 348097 times.
348561 if (!current_index_range || index != current_index_range->end) {
4439 464 current_index_range = current_index_range ? current_index_range + 1
4440
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 443 times.
464 : msc->index_ranges;
4441 464 current_index_range->start = index;
4442 }
4443 348561 current_index_range->end = index + 1;
4444
4445 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4446
2/2
✓ Branch 0 taken 348422 times.
✓ Branch 1 taken 139 times.
348561 if (edit_list_start_encountered > 0) {
4447 348422 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4448 }
4449
4450 // Break when found first key frame after edit entry completion
4451
2/2
✓ Branch 0 taken 622 times.
✓ Branch 1 taken 347939 times.
348561 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
4452
3/4
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 364 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 258 times.
622 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
4453
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 343 times.
364 if (msc->ctts_count) {
4454 // If we have CTTS and this is the first keyframe after edit elist,
4455 // wait for one more, because there might be trailing B-frames after this I-frame
4456 // that do belong to the edit.
4457
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) {
4458 12 found_keyframe_after_edit = 1;
4459 12 continue;
4460 }
4461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (tts_sample_old != 0) {
4462 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4463 &msc->tts_allocated_size,
4464 tts_sample_old - edit_list_start_tts_sample,
4465 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4466 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4467 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4468 tts_data_old[tts_index_old].offset);
4469 break;
4470 }
4471 }
4472 }
4473 352 break;
4474 }
4475 }
4476 }
4477 // If there are empty edits, then msc->min_corrected_pts might be positive
4478 // intentionally. So we subtract the sum duration of empty edits here.
4479 443 msc->min_corrected_pts -= empty_edits_sum_duration;
4480
4481 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4482 // dts by that amount to make the first pts zero.
4483
2/2
✓ Branch 0 taken 274 times.
✓ Branch 1 taken 169 times.
443 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4484
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 233 times.
274 if (msc->min_corrected_pts > 0) {
4485 41 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4486
2/2
✓ Branch 0 taken 2829 times.
✓ Branch 1 taken 41 times.
2870 for (int i = 0; i < sti->nb_index_entries; ++i)
4487 2829 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4488 }
4489 }
4490 // Start time should be equal to zero or the duration of any empty edits.
4491 443 st->start_time = empty_edits_sum_duration;
4492
4493 // Update av stream length, if it ends up shorter than the track's media duration
4494 443 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4495 443 msc->start_pad = sti->skip_samples;
4496
4497 // Free the old index and the old CTTS structures
4498 443 av_free(e_old);
4499 443 av_free(tts_data_old);
4500 443 av_freep(&frame_duration_buffer);
4501
4502 // Null terminate the index ranges array
4503 443 current_index_range = current_index_range ? current_index_range + 1
4504
1/2
✓ Branch 0 taken 443 times.
✗ Branch 1 not taken.
443 : msc->index_ranges;
4505 443 current_index_range->start = 0;
4506 443 current_index_range->end = 0;
4507 443 msc->current_index = msc->index_ranges[0].start;
4508 }
4509
4510 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4511 {
4512
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4513
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == nal_unit_type)
4514 5 return i + 1;
4515 return 0;
4516 }
4517
4518 643 static int build_open_gop_key_points(AVStream *st)
4519 {
4520 int k;
4521 643 int sample_id = 0;
4522 uint32_t cra_index;
4523 643 MOVStreamContext *sc = st->priv_data;
4524
4525
4/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 602 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 5 times.
643 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count)
4526 638 return 0;
4527
4528 /* Build an unrolled index of the samples */
4529 5 sc->sample_offsets_count = 0;
4530
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4532 return AVERROR(ENOMEM);
4533 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4534 }
4535 5 av_freep(&sc->sample_offsets);
4536 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4538 return AVERROR(ENOMEM);
4539 5 k = 0;
4540
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4541
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4542 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4543
4544 /* The following HEVC NAL type reveal the use of open GOP sync points
4545 * (TODO: BLA types may also be concerned) */
4546 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4548 return 0;
4549
4550 /* Build a list of open-GOP key samples */
4551 5 sc->open_key_samples_count = 0;
4552
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4553
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4554
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)
4555 return AVERROR(ENOMEM);
4556 11 sc->open_key_samples_count += sc->sync_group[i].count;
4557 }
4558 5 av_freep(&sc->open_key_samples);
4559 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4561 return AVERROR(ENOMEM);
4562 5 k = 0;
4563
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4564 28 const MOVSbgp *sg = &sc->sync_group[i];
4565
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4566
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4567 11 sc->open_key_samples[k++] = sample_id;
4568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4569 return AVERROR_PATCHWELCOME;
4570 28 sample_id += sg->count;
4571 }
4572
4573 /* Identify the minimal time step between samples */
4574 5 sc->min_sample_duration = UINT_MAX;
4575
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4576 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4577
4578 5 return 0;
4579 }
4580
4581 #define MOV_MERGE_CTTS 1
4582 #define MOV_MERGE_STTS 2
4583 /*
4584 * Merge stts and ctts arrays into a new combined array.
4585 * stts_count and ctts_count may be left untouched as they will be
4586 * used to check for the presence of either of them.
4587 */
4588 618 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4589 {
4590 618 MOVStreamContext *sc = st->priv_data;
4591
3/4
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 559 times.
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
618 int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS);
4592
3/4
✓ Branch 0 taken 618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 552 times.
✓ Branch 3 taken 66 times.
618 int stts = sc->stts_data && (flags & MOV_MERGE_STTS);
4593 618 int idx = 0;
4594
4595
3/4
✓ Branch 0 taken 559 times.
✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 559 times.
618 if (!sc->ctts_data && !sc->stts_data)
4596 return 0;
4597 // Expand time to sample entries such that we have a 1-1 mapping with samples
4598
2/4
✓ Branch 0 taken 618 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 618 times.
618 if (!sc->sample_count || sc->sample_count >= UINT_MAX / sizeof(*sc->tts_data))
4599 return -1;
4600
4601
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 559 times.
618 if (ctts) {
4602 118 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4603 59 sc->sample_count * sizeof(*sc->tts_data));
4604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->tts_data)
4605 return -1;
4606
4607 59 memset(sc->tts_data, 0, sc->tts_allocated_size);
4608
4609
2/2
✓ Branch 0 taken 4874 times.
✓ Branch 1 taken 59 times.
4933 for (int i = 0; i < sc->ctts_count &&
4610
1/2
✓ Branch 0 taken 4874 times.
✗ Branch 1 not taken.
9748 idx < sc->sample_count; i++)
4611
2/2
✓ Branch 0 taken 139017 times.
✓ Branch 1 taken 4874 times.
143891 for (int j = 0; j < sc->ctts_data[i].count &&
4612
1/2
✓ Branch 0 taken 139017 times.
✗ Branch 1 not taken.
139017 idx < sc->sample_count; j++) {
4613 139017 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4614 139017 sc->tts_data[idx++].count = 1;
4615 }
4616
4617 59 sc->tts_count = idx;
4618 } else
4619 559 sc->ctts_count = 0;
4620 618 av_freep(&sc->ctts_data);
4621 618 sc->ctts_allocated_size = 0;
4622
4623 618 idx = 0;
4624
2/2
✓ Branch 0 taken 552 times.
✓ Branch 1 taken 66 times.
618 if (stts) {
4625 552 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4626 552 sc->sample_count * sizeof(*sc->tts_data));
4627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 552 times.
552 if (!tts_data)
4628 return -1;
4629
4630
2/2
✓ Branch 0 taken 493 times.
✓ Branch 1 taken 59 times.
552 if (!sc->tts_data)
4631 493 memset(tts_data, 0, sc->tts_allocated_size);
4632 552 sc->tts_data = tts_data;
4633
4634
2/2
✓ Branch 0 taken 2915 times.
✓ Branch 1 taken 552 times.
3467 for (int i = 0; i < sc->stts_count &&
4635
1/2
✓ Branch 0 taken 2915 times.
✗ Branch 1 not taken.
5830 idx < sc->sample_count; i++)
4636
2/2
✓ Branch 0 taken 236273 times.
✓ Branch 1 taken 2915 times.
239188 for (int j = 0; j < sc->stts_data[i].count &&
4637
1/2
✓ Branch 0 taken 236273 times.
✗ Branch 1 not taken.
236273 idx < sc->sample_count; j++) {
4638 236273 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4639 236273 sc->tts_data[idx++].count = 1;
4640 }
4641
4642 552 sc->tts_count = FFMAX(sc->tts_count, idx);
4643 } else
4644 66 sc->stts_count = 0;
4645 618 av_freep(&sc->stts_data);
4646 618 sc->stts_allocated_size = 0;
4647
4648 618 return 0;
4649 }
4650
4651 643 static void mov_build_index(MOVContext *mov, AVStream *st)
4652 {
4653 643 MOVStreamContext *sc = st->priv_data;
4654 643 FFStream *const sti = ffstream(st);
4655 int64_t current_offset;
4656 643 int64_t current_dts = 0;
4657 643 unsigned int stts_index = 0;
4658 643 unsigned int stsc_index = 0;
4659 643 unsigned int stss_index = 0;
4660 643 unsigned int stps_index = 0;
4661 unsigned int i, j;
4662 643 uint64_t stream_size = 0;
4663
4664 643 int ret = build_open_gop_key_points(st);
4665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 643 times.
643 if (ret < 0)
4666 return;
4667
4668
2/2
✓ Branch 0 taken 446 times.
✓ Branch 1 taken 197 times.
643 if (sc->elst_count) {
4669 446 int i, edit_start_index = 0, multiple_edits = 0;
4670 446 int64_t empty_duration = 0; // empty duration of the first edit list entry
4671 446 int64_t start_time = 0; // start time of the media
4672
4673
2/2
✓ Branch 0 taken 473 times.
✓ Branch 1 taken 446 times.
919 for (i = 0; i < sc->elst_count; i++) {
4674 473 const MOVElst *e = &sc->elst_data[i];
4675
4/4
✓ Branch 0 taken 446 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 442 times.
473 if (i == 0 && e->time == -1) {
4676 /* if empty, the first entry is the start time of the stream
4677 * relative to the presentation itself */
4678 4 empty_duration = e->duration;
4679 4 edit_start_index = 1;
4680
3/4
✓ Branch 0 taken 446 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 446 times.
✗ Branch 3 not taken.
469 } else if (i == edit_start_index && e->time >= 0) {
4681 446 start_time = e->time;
4682 } else {
4683 23 multiple_edits = 1;
4684 }
4685 }
4686
4687
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 440 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
446 if (multiple_edits && !mov->advanced_editlist) {
4688 if (mov->advanced_editlist_autodisabled)
4689 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4690 "not supported in fragmented MP4 files\n");
4691 else
4692 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4693 "Use -advanced_editlist to correctly decode otherwise "
4694 "a/v desync might occur\n");
4695 }
4696
4697 /* adjust first dts according to edit list */
4698
5/6
✓ Branch 0 taken 442 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 373 times.
✓ Branch 4 taken 73 times.
✗ Branch 5 not taken.
446 if ((empty_duration || start_time) && mov->time_scale > 0) {
4699
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 69 times.
73 if (empty_duration)
4700 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
4701
4702
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)
4703 av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
4704
4705 73 sc->time_offset = start_time - (uint64_t)empty_duration;
4706 73 sc->min_corrected_pts = start_time;
4707
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 72 times.
73 if (!mov->advanced_editlist)
4708 1 current_dts = -sc->time_offset;
4709 }
4710
4711
4/4
✓ Branch 0 taken 440 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 437 times.
446 if (!multiple_edits && !mov->advanced_editlist &&
4712
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
3 st->codecpar->codec_id == AV_CODEC_ID_AAC && start_time > 0)
4713 sc->start_pad = start_time;
4714 }
4715
4716 /* only use old uncompressed audio chunk demuxing when stts specifies it */
4717
2/2
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 400 times.
643 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4718
5/6
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 122 times.
✓ Branch 5 taken 66 times.
795 sc->stts_count == 1 && sc->stts_data && sc->stts_data[0].duration == 1)) {
4719 577 unsigned int current_sample = 0;
4720 577 unsigned int stts_sample = 0;
4721 unsigned int sample_size;
4722 577 unsigned int distance = 0;
4723 577 unsigned int rap_group_index = 0;
4724 577 unsigned int rap_group_sample = 0;
4725
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 576 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
577 int rap_group_present = sc->rap_group_count && sc->rap_group;
4726
4/8
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 437 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 140 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 437 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
577 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
4727
4728 577 current_dts -= sc->dts_shift;
4729
4730
4/6
✓ Branch 0 taken 552 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 552 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 552 times.
577 if (!sc->sample_count || sti->nb_index_entries || sc->tts_count)
4731 25 return;
4732
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 552 times.
552 if (sc->sample_count >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4733 return;
4734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 552 times.
552 if (av_reallocp_array(&sti->index_entries,
4735 552 sti->nb_index_entries + sc->sample_count,
4736 sizeof(*sti->index_entries)) < 0) {
4737 sti->nb_index_entries = 0;
4738 return;
4739 }
4740 552 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
4741
4742 552 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
4743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 552 times.
552 if (ret < 0)
4744 return;
4745
4746
2/2
✓ Branch 0 taken 174213 times.
✓ Branch 1 taken 552 times.
174765 for (i = 0; i < sc->chunk_count; i++) {
4747
2/2
✓ Branch 0 taken 173661 times.
✓ Branch 1 taken 552 times.
174213 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
4748 174213 current_offset = sc->chunk_offsets[i];
4749
2/2
✓ Branch 1 taken 8863 times.
✓ Branch 2 taken 167895 times.
176758 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4750
2/2
✓ Branch 0 taken 2545 times.
✓ Branch 1 taken 6318 times.
8863 i + 1 == sc->stsc_data[stsc_index + 1].first)
4751 2545 stsc_index++;
4752
4753
4/6
✓ Branch 0 taken 174213 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7384 times.
✓ Branch 3 taken 166829 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7384 times.
174213 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
4754 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
4755 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
4756 sc->stsz_sample_size = sc->sample_size;
4757 }
4758
3/4
✓ Branch 0 taken 7384 times.
✓ Branch 1 taken 166829 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7384 times.
174213 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
4759 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
4760 sc->stsz_sample_size = sc->sample_size;
4761 }
4762
4763
2/2
✓ Branch 0 taken 236273 times.
✓ Branch 1 taken 174213 times.
410486 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
4764 236273 int keyframe = 0;
4765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 236273 times.
236273 if (current_sample >= sc->sample_count) {
4766 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
4767 return;
4768 }
4769
4770
6/6
✓ Branch 0 taken 231517 times.
✓ Branch 1 taken 4756 times.
✓ Branch 2 taken 152652 times.
✓ Branch 3 taken 78865 times.
✓ Branch 4 taken 5710 times.
✓ Branch 5 taken 146942 times.
236273 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
4771 84575 keyframe = 1;
4772
2/2
✓ Branch 0 taken 5570 times.
✓ Branch 1 taken 79005 times.
84575 if (stss_index + 1 < sc->keyframe_count)
4773 5570 stss_index++;
4774
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 151698 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
151698 } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
4775 keyframe = 1;
4776 if (stps_index + 1 < sc->stps_count)
4777 stps_index++;
4778 }
4779
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 236085 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
236273 if (rap_group_present && rap_group_index < sc->rap_group_count) {
4780
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
4781 2 keyframe = 1;
4782
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
4783 4 rap_group_sample = 0;
4784 4 rap_group_index++;
4785 }
4786 }
4787
2/2
✓ Branch 0 taken 4756 times.
✓ Branch 1 taken 231517 times.
236273 if (sc->keyframe_absent
4788
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !sc->stps_count
4789
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !rap_group_present
4790
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)))
4791 3884 keyframe = 1;
4792
2/2
✓ Branch 0 taken 88459 times.
✓ Branch 1 taken 147814 times.
236273 if (keyframe)
4793 88459 distance = 0;
4794
2/2
✓ Branch 0 taken 9024 times.
✓ Branch 1 taken 227249 times.
236273 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
4795
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 236273 times.
236273 if (current_offset > INT64_MAX - sample_size) {
4796 av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
4797 current_offset,
4798 sample_size);
4799 return;
4800 }
4801
4802
2/2
✓ Branch 0 taken 236184 times.
✓ Branch 1 taken 89 times.
236273 if (sc->pseudo_stream_id == -1 ||
4803
1/2
✓ Branch 0 taken 236184 times.
✗ Branch 1 not taken.
236184 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
4804 AVIndexEntry *e;
4805
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 236273 times.
236273 if (sample_size > 0x3FFFFFFF) {
4806 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
4807 return;
4808 }
4809 236273 e = &sti->index_entries[sti->nb_index_entries++];
4810 236273 e->pos = current_offset;
4811 236273 e->timestamp = current_dts;
4812 236273 e->size = sample_size;
4813 236273 e->min_distance = distance;
4814 236273 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
4815 236273 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
4816 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
4817 current_offset, current_dts, sample_size, distance, keyframe);
4818
4/4
✓ Branch 0 taken 155018 times.
✓ Branch 1 taken 81255 times.
✓ Branch 2 taken 10385 times.
✓ Branch 3 taken 144633 times.
236273 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries < 100)
4819 10385 ff_rfps_add_frame(mov->fc, st, current_dts);
4820 }
4821
4822 236273 current_offset += sample_size;
4823 236273 stream_size += sample_size;
4824
4825 236273 current_dts += sc->tts_data[stts_index].duration;
4826
4827 236273 distance++;
4828 236273 stts_sample++;
4829 236273 current_sample++;
4830
3/4
✓ Branch 0 taken 235721 times.
✓ Branch 1 taken 552 times.
✓ Branch 2 taken 235721 times.
✗ Branch 3 not taken.
236273 if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) {
4831 235721 stts_sample = 0;
4832 235721 stts_index++;
4833 }
4834 }
4835 }
4836
2/2
✓ Branch 0 taken 521 times.
✓ Branch 1 taken 31 times.
552 if (st->duration > 0)
4837 521 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
4838 } else {
4839 66 unsigned chunk_samples, total = 0;
4840
4841
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)
4842 return;
4843
4844 // compute total chunk count
4845
2/2
✓ Branch 0 taken 723 times.
✓ Branch 1 taken 66 times.
789 for (i = 0; i < sc->stsc_count; i++) {
4846 unsigned count, chunk_count;
4847
4848 723 chunk_samples = sc->stsc_data[i].count;
4849
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 66 times.
723 if (i != sc->stsc_count - 1 &&
4850
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) {
4851 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
4852 return;
4853 }
4854
4855
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 648 times.
723 if (sc->samples_per_frame >= 160) { // gsm
4856 75 count = chunk_samples / sc->samples_per_frame;
4857
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 117 times.
648 } else if (sc->samples_per_frame > 1) {
4858 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
4859 531 count = (chunk_samples+samples-1) / samples;
4860 } else {
4861 117 count = (chunk_samples+1023) / 1024;
4862 }
4863
4864
2/2
✓ Branch 1 taken 657 times.
✓ Branch 2 taken 66 times.
723 if (mov_stsc_index_valid(i, sc->stsc_count))
4865 657 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
4866 else
4867 66 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
4868 723 total += chunk_count * count;
4869 }
4870
4871 66 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
4872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4873 return;
4874
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (av_reallocp_array(&sti->index_entries,
4875 66 sti->nb_index_entries + total,
4876 sizeof(*sti->index_entries)) < 0) {
4877 sti->nb_index_entries = 0;
4878 return;
4879 }
4880 66 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
4881
4882 // populate index
4883
2/2
✓ Branch 0 taken 5428 times.
✓ Branch 1 taken 66 times.
5494 for (i = 0; i < sc->chunk_count; i++) {
4884 5428 current_offset = sc->chunk_offsets[i];
4885
2/2
✓ Branch 1 taken 5287 times.
✓ Branch 2 taken 141 times.
5428 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4886
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 4630 times.
5287 i + 1 == sc->stsc_data[stsc_index + 1].first)
4887 657 stsc_index++;
4888 5428 chunk_samples = sc->stsc_data[stsc_index].count;
4889
4890
2/2
✓ Branch 0 taken 162532 times.
✓ Branch 1 taken 5428 times.
167960 while (chunk_samples > 0) {
4891 AVIndexEntry *e;
4892 unsigned size, samples;
4893
4894
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) {
4895 avpriv_request_sample(mov->fc,
4896 "Zero bytes per frame, but %d samples per frame",
4897 sc->samples_per_frame);
4898 return;
4899 }
4900
4901
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 148174 times.
162532 if (sc->samples_per_frame >= 160) { // gsm
4902 14358 samples = sc->samples_per_frame;
4903 14358 size = sc->bytes_per_frame;
4904 } else {
4905
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 138611 times.
148174 if (sc->samples_per_frame > 1) {
4906 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
4907 sc->samples_per_frame, chunk_samples);
4908 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
4909 } else {
4910 138611 samples = FFMIN(1024, chunk_samples);
4911 138611 size = samples * sc->sample_size;
4912 }
4913 }
4914
4915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (sti->nb_index_entries >= total) {
4916 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
4917 return;
4918 }
4919
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (size > 0x3FFFFFFF) {
4920 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
4921 return;
4922 }
4923 162532 e = &sti->index_entries[sti->nb_index_entries++];
4924 162532 e->pos = current_offset;
4925 162532 e->timestamp = current_dts;
4926 162532 e->size = size;
4927 162532 e->min_distance = 0;
4928 162532 e->flags = AVINDEX_KEYFRAME;
4929 162532 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
4930 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
4931 size, samples);
4932
4933 162532 current_offset += size;
4934 162532 current_dts += samples;
4935 162532 chunk_samples -= samples;
4936 }
4937 }
4938
4939 66 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
4940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
4941 return;
4942 }
4943
4944
2/4
✓ Branch 0 taken 618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 618 times.
✗ Branch 3 not taken.
618 if (!mov->ignore_editlist && mov->advanced_editlist) {
4945 // Fix index according to edit lists.
4946 618 mov_fix_index(mov, st);
4947 }
4948
4949 // Update start time of the stream.
4950
5/6
✓ Branch 0 taken 175 times.
✓ Branch 1 taken 443 times.
✓ Branch 2 taken 57 times.
✓ Branch 3 taken 118 times.
✓ Branch 4 taken 57 times.
✗ Branch 5 not taken.
618 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) {
4951 57 st->start_time = sti->index_entries[0].timestamp + sc->dts_shift;
4952
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 if (sc->tts_data) {
4953 57 st->start_time += sc->tts_data[0].offset;
4954 }
4955 }
4956
4957 618 mov_estimate_video_delay(mov, st);
4958 }
4959
4960 static int test_same_origin(const char *src, const char *ref) {
4961 char src_proto[64];
4962 char ref_proto[64];
4963 char src_auth[256];
4964 char ref_auth[256];
4965 char src_host[256];
4966 char ref_host[256];
4967 int src_port=-1;
4968 int ref_port=-1;
4969
4970 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
4971 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
4972
4973 if (strlen(src) == 0) {
4974 return -1;
4975 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
4976 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
4977 strlen(src_host) + 1 >= sizeof(src_host) ||
4978 strlen(ref_host) + 1 >= sizeof(ref_host)) {
4979 return 0;
4980 } else if (strcmp(src_proto, ref_proto) ||
4981 strcmp(src_auth, ref_auth) ||
4982 strcmp(src_host, ref_host) ||
4983 src_port != ref_port) {
4984 return 0;
4985 } else
4986 return 1;
4987 }
4988
4989 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
4990 {
4991 /* try relative path, we do not try the absolute because it can leak information about our
4992 system to an attacker */
4993 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
4994 char filename[1025];
4995 const char *src_path;
4996 int i, l;
4997
4998 /* find a source dir */
4999 src_path = strrchr(src, '/');
5000 if (src_path)
5001 src_path++;
5002 else
5003 src_path = src;
5004
5005 /* find a next level down to target */
5006 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
5007 if (ref->path[l] == '/') {
5008 if (i == ref->nlvl_to - 1)
5009 break;
5010 else
5011 i++;
5012 }
5013
5014 /* compose filename if next level down to target was found */
5015 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
5016 memcpy(filename, src, src_path - src);
5017 filename[src_path - src] = 0;
5018
5019 for (i = 1; i < ref->nlvl_from; i++)
5020 av_strlcat(filename, "../", sizeof(filename));
5021
5022 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
5023 if (!c->use_absolute_path) {
5024 int same_origin = test_same_origin(src, filename);
5025
5026 if (!same_origin) {
5027 av_log(c->fc, AV_LOG_ERROR,
5028 "Reference with mismatching origin, %s not tried for security reasons, "
5029 "set demuxer option use_absolute_path to allow it anyway\n",
5030 ref->path);
5031 return AVERROR(ENOENT);
5032 }
5033
5034 if (strstr(ref->path + l + 1, "..") ||
5035 strstr(ref->path + l + 1, ":") ||
5036 (ref->nlvl_from > 1 && same_origin < 0) ||
5037 (filename[0] == '/' && src_path == src))
5038 return AVERROR(ENOENT);
5039 }
5040
5041 if (strlen(filename) + 1 == sizeof(filename))
5042 return AVERROR(ENOENT);
5043 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5044 return 0;
5045 }
5046 } else if (c->use_absolute_path) {
5047 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5048 "this is a possible security issue\n");
5049 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5050 return 0;
5051 } else {
5052 av_log(c->fc, AV_LOG_ERROR,
5053 "Absolute path %s not tried for security reasons, "
5054 "set demuxer option use_absolute_path to allow absolute paths\n",
5055 ref->path);
5056 }
5057
5058 return AVERROR(ENOENT);
5059 }
5060
5061 1309 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5062 {
5063
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1295 times.
1309 if (sc->time_scale <= 0) {
5064 14 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5065 14 sc->time_scale = c->time_scale;
5066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (sc->time_scale <= 0)
5067 sc->time_scale = 1;
5068 }
5069 1309 }
5070
5071 #if CONFIG_IAMFDEC
5072 10 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5073 {
5074 10 const MOVStreamContext *sc = st->priv_data;
5075 10 const IAMFContext *iamf = &sc->iamf->iamf;
5076
5077
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5078 10 const AVStreamGroup *stg = NULL;
5079
5080
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5081
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)
5082 10 stg = c->fc->stream_groups[j];
5083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 av_assert0(stg);
5084
5085
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int j = 0; j < stg->nb_streams; j++) {
5086 50 const FFStream *sti = cffstream(st);
5087 50 AVStream *out = stg->streams[j];
5088 50 FFStream *out_sti = ffstream(stg->streams[j]);
5089
5090 50 out->codecpar->bit_rate = 0;
5091
5092
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 40 times.
50 if (out == st)
5093 10 continue;
5094
5095 40 out->time_base = st->time_base;
5096 40 out->start_time = st->start_time;
5097 40 out->duration = st->duration;
5098 40 out->nb_frames = st->nb_frames;
5099 40 out->discard = st->discard;
5100
5101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 av_assert0(!out_sti->index_entries);
5102 40 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (!out_sti->index_entries)
5104 return AVERROR(ENOMEM);
5105
5106 40 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5107 40 out_sti->nb_index_entries = sti->nb_index_entries;
5108 40 out_sti->skip_samples = sti->skip_samples;
5109 40 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5110 }
5111 }
5112
5113 10 return 0;
5114 }
5115 #endif
5116
5117 643 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5118 {
5119
4/6
✓ Branch 0 taken 618 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 618 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 618 times.
✗ Branch 5 not taken.
643 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5120
3/4
✓ Branch 0 taken 384 times.
✓ Branch 1 taken 234 times.
✓ Branch 2 taken 384 times.
✗ Branch 3 not taken.
618 (!sc->sample_size && !sc->sample_count))) ||
5121
3/4
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 618 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 25 times.
643 (!sc->chunk_count && sc->sample_count)) {
5122 av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5123 index);
5124 return 1;
5125 }
5126
5127
3/4
✓ Branch 0 taken 618 times.
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 618 times.
643 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
5128 av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5129 index);
5130 return 2;
5131 }
5132 643 return 0;
5133 }
5134
5135 612 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5136 {
5137 AVStream *st;
5138 MOVStreamContext *sc;
5139 int ret;
5140
5141 612 st = avformat_new_stream(c->fc, NULL);
5142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (!st) return AVERROR(ENOMEM);
5143 612 st->id = -1;
5144 612 sc = av_mallocz(sizeof(MOVStreamContext));
5145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (!sc) return AVERROR(ENOMEM);
5146
5147 612 st->priv_data = sc;
5148 612 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5149 612 sc->ffindex = st->index;
5150 612 c->trak_index = st->index;
5151 612 sc->tref_flags = 0;
5152 612 sc->tref_id = -1;
5153 612 sc->refcount = 1;
5154
5155
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 612 times.
612 if ((ret = mov_read_default(c, pb, atom)) < 0)
5156 return ret;
5157
5158 612 c->trak_index = -1;
5159
5160 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5161 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5162
5/6
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 587 times.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 24 times.
612 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
5163 1 sc->stsc_count = 0;
5164 1 av_freep(&sc->stsc_data);
5165 }
5166
5167 612 ret = sanity_checks(c->fc, sc, st->index);
5168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (ret)
5169 return ret > 1 ? AVERROR_INVALIDDATA : 0;
5170
5171 612 fix_timescale(c, sc);
5172
5173 612 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5174
5175 /*
5176 * Advanced edit list support does not work with fragemented MP4s, which
5177 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5178 * In these files, trun atoms may be streamed in.
5179 */
5180
4/4
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 587 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 8 times.
612 if (!sc->stts_count && c->advanced_editlist) {
5181
5182 17 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5183 "MP4. disabling.\n");
5184 17 c->advanced_editlist = 0;
5185 17 c->advanced_editlist_autodisabled = 1;
5186 }
5187
5188 612 mov_build_index(c, st);
5189
5190 #if CONFIG_IAMFDEC
5191
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 602 times.
612 if (sc->iamf) {
5192 10 ret = mov_update_iamf_streams(c, st);
5193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
5194 return ret;
5195 }
5196 #endif
5197
5198
3/4
✓ Branch 0 taken 611 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 611 times.
612 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
5199 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5200 if (c->enable_drefs) {
5201 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5202 av_log(c->fc, AV_LOG_ERROR,
5203 "stream %d, error opening alias: path='%s', dir='%s', "
5204 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5205 st->index, dref->path, dref->dir, dref->filename,
5206 dref->volume, dref->nlvl_from, dref->nlvl_to);
5207 } else {
5208 av_log(c->fc, AV_LOG_WARNING,
5209 "Skipped opening external track: "
5210 "stream %d, alias: path='%s', dir='%s', "
5211 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5212 "Set enable_drefs to allow this.\n",
5213 st->index, dref->path, dref->dir, dref->filename,
5214 dref->volume, dref->nlvl_from, dref->nlvl_to);
5215 }
5216 } else {
5217 612 sc->pb = c->fc->pb;
5218 612 sc->pb_is_copied = 1;
5219 }
5220
5221
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 298 times.
612 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5222
3/4
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
314 int stts_constant = sc->stts_count && sc->tts_count;
5223
3/4
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 249 times.
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
314 if (sc->h_spacing && sc->v_spacing)
5224 65 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5225 65 sc->h_spacing, sc->v_spacing, INT_MAX);
5226
4/6
✓ Branch 0 taken 246 times.
✓ Branch 1 taken 68 times.
✓ Branch 2 taken 246 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 246 times.
✗ Branch 5 not taken.
314 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
5227
2/4
✓ Branch 0 taken 246 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 246 times.
✗ Branch 3 not taken.
246 sc->height && sc->width &&
5228
2/4
✓ Branch 0 taken 246 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 246 times.
246 (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
5229 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5230 (int64_t)st->codecpar->height * sc->width,
5231 (int64_t)st->codecpar->width * sc->height, INT_MAX);
5232 }
5233
5234 #if FF_API_R_FRAME_RATE
5235
4/4
✓ Branch 0 taken 154840 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 154540 times.
✓ Branch 3 taken 300 times.
154854 for (unsigned int i = 1; sc->stts_count && i + 1 < sc->tts_count; i++) {
5236
2/2
✓ Branch 0 taken 152113 times.
✓ Branch 1 taken 2427 times.
154540 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5237 152113 continue;
5238 2427 stts_constant = 0;
5239 }
5240
2/2
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 28 times.
314 if (stts_constant)
5241 286 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5242 286 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5243 #endif
5244 }
5245
5246
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 588 times.
612 switch (st->codecpar->codec_id) {
5247 24 case AV_CODEC_ID_H261:
5248 case AV_CODEC_ID_H263:
5249 case AV_CODEC_ID_MPEG4:
5250 24 st->codecpar->width = 0; /* let decoder init width/height */
5251 24 st->codecpar->height= 0;
5252 24 break;
5253 588 default:
5254 588 break;
5255 }
5256
5257 // If the duration of the mp3 packets is not constant, then they could need a parser
5258
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 611 times.
612 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5259
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 && sc->time_scale == st->codecpar->sample_rate) {
5260 1 int stts_constant = 1;
5261
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++) {
5262
1/2
✓ Branch 0 taken 287 times.
✗ Branch 1 not taken.
287 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5263 287 continue;
5264 stts_constant = 0;
5265 }
5266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!stts_constant)
5267 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5268 }
5269 /* Do not need those anymore. */
5270 612 av_freep(&sc->chunk_offsets);
5271 612 av_freep(&sc->sample_sizes);
5272 612 av_freep(&sc->keyframes);
5273 612 av_freep(&sc->stps_data);
5274 612 av_freep(&sc->elst_data);
5275 612 av_freep(&sc->rap_group);
5276 612 av_freep(&sc->sync_group);
5277 612 av_freep(&sc->sgpd_sync);
5278
5279 612 return 0;
5280 }
5281
5282 132 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5283 {
5284 int ret;
5285 132 c->itunes_metadata = 1;
5286 132 ret = mov_read_default(c, pb, atom);
5287 132 c->itunes_metadata = 0;
5288 132 return ret;
5289 }
5290
5291 11 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5292 {
5293 uint32_t count;
5294 uint32_t i;
5295
5296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
5297 return 0;
5298
5299 11 avio_skip(pb, 4);
5300 11 count = avio_rb32(pb);
5301 11 atom.size -= 8;
5302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (count >= UINT_MAX / sizeof(*c->meta_keys)) {
5303 av_log(c->fc, AV_LOG_ERROR,
5304 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5305 return AVERROR_INVALIDDATA;
5306 }
5307
5308 11 c->meta_keys_count = count + 1;
5309 11 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
5310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!c->meta_keys)
5311 return AVERROR(ENOMEM);
5312
5313
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i <= count; ++i) {
5314 58 uint32_t key_size = avio_rb32(pb);
5315 58 uint32_t type = avio_rl32(pb);
5316
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) {
5317 av_log(c->fc, AV_LOG_ERROR,
5318 "The key# %"PRIu32" in meta has invalid size:"
5319 "%"PRIu32"\n", i, key_size);
5320 return AVERROR_INVALIDDATA;
5321 }
5322 58 atom.size -= key_size;
5323 58 key_size -= 8;
5324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (type != MKTAG('m','d','t','a')) {
5325 avio_skip(pb, key_size);
5326 continue;
5327 }
5328 58 c->meta_keys[i] = av_mallocz(key_size + 1);
5329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!c->meta_keys[i])
5330 return AVERROR(ENOMEM);
5331 58 avio_read(pb, c->meta_keys[i], key_size);
5332 }
5333
5334 11 return 0;
5335 }
5336
5337 65 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5338 {
5339 65 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5340 65 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5341 int i;
5342 65 int ret = 0;
5343 AVStream *st;
5344 MOVStreamContext *sc;
5345
5346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (c->fc->nb_streams < 1)
5347 return 0;
5348 65 st = c->fc->streams[c->fc->nb_streams-1];
5349 65 sc = st->priv_data;
5350
5351
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 65 times.
260 for (i = 0; i < 3; i++) {
5352 uint8_t **p;
5353 uint32_t len, tag;
5354
5355
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 195 times.
195 if (end - avio_tell(pb) <= 12)
5356 break;
5357
5358 195 len = avio_rb32(pb);
5359 195 tag = avio_rl32(pb);
5360 195 avio_skip(pb, 4); // flags
5361
5362
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))
5363 break;
5364 195 len -= 12;
5365
5366
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 130 times.
195 if (tag == MKTAG('m', 'e', 'a', 'n'))
5367 65 p = &mean;
5368
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 65 times.
130 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5369 65 p = &key;
5370
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) {
5371 65 avio_skip(pb, 4);
5372 65 len -= 4;
5373 65 p = &val;
5374 } else
5375 break;
5376
5377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (*p)
5378 break;
5379
5380 195 *p = av_malloc(len + 1);
5381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*p) {
5382 ret = AVERROR(ENOMEM);
5383 break;
5384 }
5385 195 ret = ffio_read_size(pb, *p, len);
5386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (ret < 0) {
5387 av_freep(p);
5388 break;
5389 }
5390 195 (*p)[len] = 0;
5391 }
5392
5393
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) {
5394
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 32 times.
65 if (strcmp(key, "iTunSMPB") == 0) {
5395 int priming, remainder, samples;
5396
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
5397
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)
5398 33 sc->start_pad = priming;
5399 }
5400 }
5401
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 10 times.
120 if (strcmp(key, "cdec") != 0) {
5402 55 av_dict_set(&c->fc->metadata, key, val,
5403 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5404 55 key = val = NULL;
5405 }
5406 } else {
5407 av_log(c->fc, AV_LOG_VERBOSE,
5408 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5409 }
5410
5411 65 avio_seek(pb, end, SEEK_SET);
5412 65 av_freep(&key);
5413 65 av_freep(&val);
5414 65 av_freep(&mean);
5415 65 return ret;
5416 }
5417
5418 31 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5419 {
5420 MOVStreamContext *sc;
5421 AVStream *st;
5422
5423 31 st = avformat_new_stream(c->fc, NULL);
5424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!st)
5425 return AVERROR(ENOMEM);
5426 31 sc = av_mallocz(sizeof(MOVStreamContext));
5427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!sc)
5428 goto fail;
5429
5430 31 item->st = st;
5431 31 st->id = item->item_id;
5432 31 st->priv_data = sc;
5433 31 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5434 31 st->codecpar->codec_id = mov_codec_id(st, item->type);
5435 31 sc->id = st->id;
5436 31 sc->ffindex = st->index;
5437 31 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5438 31 st->time_base.num = st->time_base.den = 1;
5439 31 st->nb_frames = 1;
5440 31 sc->time_scale = 1;
5441 31 sc->pb = c->fc->pb;
5442 31 sc->pb_is_copied = 1;
5443 31 sc->refcount = 1;
5444
5445
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 if (item->name)
5446 31 av_dict_set(&st->metadata, "title", item->name, 0);
5447
5448 // Populate the necessary fields used by mov_build_index.
5449 31 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!sc->stsc_data)
5451 goto fail;
5452 31 sc->stsc_count = 1;
5453 31 sc->stsc_data[0].first = 1;
5454 31 sc->stsc_data[0].count = 1;
5455 31 sc->stsc_data[0].id = 1;
5456 31 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!sc->chunk_offsets)
5458 goto fail;
5459 31 sc->chunk_count = 1;
5460 31 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!sc->stts_data)
5462 goto fail;
5463 31 sc->stts_count = 1;
5464 31 sc->stts_data[0].count = 1;
5465 // Not used for still images. But needed by mov_build_index.
5466 31 sc->stts_data[0].duration = 0;
5467
5468 31 return 0;
5469 fail:
5470 mov_free_stream_context(c->fc, st);
5471 ff_remove_stream(c->fc, st);
5472 item->st = NULL;
5473
5474 return AVERROR(ENOMEM);
5475 }
5476
5477 149 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5478 {
5479
1/2
✓ Branch 0 taken 433 times.
✗ Branch 1 not taken.
433 while (atom.size > 8) {
5480 uint32_t tag;
5481
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 433 times.
433 if (avio_feof(pb))
5482 return AVERROR_EOF;
5483 433 tag = avio_rl32(pb);
5484 433 atom.size -= 4;
5485
2/2
✓ Branch 0 taken 149 times.
✓ Branch 1 taken 284 times.
433 if (tag == MKTAG('h','d','l','r')) {
5486 149 avio_seek(pb, -8, SEEK_CUR);
5487 149 atom.size += 8;
5488 149 return mov_read_default(c, pb, atom);
5489 }
5490 }
5491 return 0;
5492 }
5493
5494 // return 1 when matrix is identity, 0 otherwise
5495 #define IS_MATRIX_IDENT(matrix) \
5496 ( (matrix)[0][0] == (1 << 16) && \
5497 (matrix)[1][1] == (1 << 16) && \
5498 (matrix)[2][2] == (1 << 30) && \
5499 !(matrix)[0][1] && !(matrix)[0][2] && \
5500 !(matrix)[1][0] && !(matrix)[1][2] && \
5501 !(matrix)[2][0] && !(matrix)[2][1])
5502
5503 612 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5504 {
5505 int i, j, e;
5506 int width;
5507 int height;
5508 int display_matrix[3][3];
5509 612 int res_display_matrix[3][3] = { { 0 } };
5510 AVStream *st;
5511 MOVStreamContext *sc;
5512 int version;
5513 int flags;
5514
5515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->fc->nb_streams < 1)
5516 return 0;
5517 612 st = c->fc->streams[c->fc->nb_streams-1];
5518 612 sc = st->priv_data;
5519
5520 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5521 // avoids corrupting AVStreams mapped to an earlier tkhd.
5522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (st->id != -1)
5523 return AVERROR_INVALIDDATA;
5524
5525 612 version = avio_r8(pb);
5526 612 flags = avio_rb24(pb);
5527 612 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5528
5529
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 599 times.
612 if (version == 1) {
5530 13 avio_rb64(pb);
5531 13 avio_rb64(pb);
5532 } else {
5533 599 avio_rb32(pb); /* creation time */
5534 599 avio_rb32(pb); /* modification time */
5535 }
5536 612 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5537 612 sc->id = st->id;
5538 612 avio_rb32(pb); /* reserved */
5539
5540 /* highlevel (considering edits) duration in movie timebase */
5541
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 599 times.
612 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5542 612 avio_rb32(pb); /* reserved */
5543 612 avio_rb32(pb); /* reserved */
5544
5545 612 avio_rb16(pb); /* layer */
5546 612 avio_rb16(pb); /* alternate group */
5547 612 avio_rb16(pb); /* volume */
5548 612 avio_rb16(pb); /* reserved */
5549
5550 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
5551 // they're kept in fixed point format through all calculations
5552 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
5553 // side data, but the scale factor is not needed to calculate aspect ratio
5554
2/2
✓ Branch 0 taken 1836 times.
✓ Branch 1 taken 612 times.
2448 for (i = 0; i < 3; i++) {
5555 1836 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
5556 1836 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
5557 1836 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
5558 }
5559
5560 612 width = avio_rb32(pb); // 16.16 fixed point track width
5561 612 height = avio_rb32(pb); // 16.16 fixed point track height
5562 612 sc->width = width >> 16;
5563 612 sc->height = height >> 16;
5564
5565 // apply the moov display matrix (after the tkhd one)
5566
2/2
✓ Branch 0 taken 1836 times.
✓ Branch 1 taken 612 times.
2448 for (i = 0; i < 3; i++) {
5567 1836 const int sh[3] = { 16, 16, 30 };
5568
2/2
✓ Branch 0 taken 5508 times.
✓ Branch 1 taken 1836 times.
7344 for (j = 0; j < 3; j++) {
5569
2/2
✓ Branch 0 taken 16524 times.
✓ Branch 1 taken 5508 times.
22032 for (e = 0; e < 3; e++) {
5570 16524 res_display_matrix[i][j] +=
5571 16524 ((int64_t) display_matrix[i][e] *
5572 16524 c->movie_display_matrix[e][j]) >> sh[e];
5573 }
5574 }
5575 }
5576
5577 // save the matrix when it is not the default identity
5578
10/18
✓ Branch 0 taken 603 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 603 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 603 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 603 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 603 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 603 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 603 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 603 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 603 times.
612 if (!IS_MATRIX_IDENT(res_display_matrix)) {
5579 9 av_freep(&sc->display_matrix);
5580 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
5581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
5582 return AVERROR(ENOMEM);
5583
5584
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
5585
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
5586 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
5587 }
5588
5589 // transform the display width/height according to the matrix
5590 // to keep the same scale, use [width height 1<<16]
5591
5/6
✓ Branch 0 taken 324 times.
✓ Branch 1 taken 288 times.
✓ Branch 2 taken 324 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 316 times.
612 if (width && height && sc->display_matrix) {
5592 double disp_transform[2];
5593
5594
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
5595 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
5596 16 sc->display_matrix[3 + i]);
5597
5598
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 &&
5599
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) &&
5600
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
5601 3 st->sample_aspect_ratio = av_d2q(
5602 3 disp_transform[0] / disp_transform[1],
5603 INT_MAX);
5604 }
5605 612 return 0;
5606 }
5607
5608 493 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5609 {
5610 493 MOVFragment *frag = &c->fragment;
5611 493 MOVTrackExt *trex = NULL;
5612 int flags, track_id, i;
5613 MOVFragmentStreamInfo * frag_stream_info;
5614
5615 493 avio_r8(pb); /* version */
5616 493 flags = avio_rb24(pb);
5617
5618 493 track_id = avio_rb32(pb);
5619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (!track_id)
5620 return AVERROR_INVALIDDATA;
5621
1/2
✓ Branch 0 taken 551 times.
✗ Branch 1 not taken.
551 for (i = 0; i < c->trex_count; i++)
5622
2/2
✓ Branch 0 taken 493 times.
✓ Branch 1 taken 58 times.
551 if (c->trex_data[i].track_id == track_id) {
5623 493 trex = &c->trex_data[i];
5624 493 break;
5625 }
5626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (!trex) {
5627 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
5628 return 0;
5629 }
5630 493 c->fragment.found_tfhd = 1;
5631 493 frag->track_id = track_id;
5632 493 set_frag_stream(&c->frag_index, track_id);
5633
5634 986 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
5635
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
986 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
5636
2/2
✓ Branch 0 taken 420 times.
✓ Branch 1 taken 73 times.
493 frag->moof_offset : frag->implicit_offset;
5637
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 438 times.
493 frag->stsd_id = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id;
5638
5639 986 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
5640
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 435 times.
493 avio_rb32(pb) : trex->duration;
5641 986 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
5642
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 434 times.
493 avio_rb32(pb) : trex->size;
5643 986 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
5644
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 365 times.
493 avio_rb32(pb) : trex->flags;
5645 493 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
5646
5647 493 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5648
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (frag_stream_info) {
5649 493 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
5650 493 frag_stream_info->stsd_id = frag->stsd_id;
5651 }
5652 493 return 0;
5653 }
5654
5655 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5656 {
5657 unsigned i, num;
5658 void *new_tracks;
5659
5660 2 num = atom.size / 4;
5661
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
5662 return AVERROR(ENOMEM);
5663
5664 2 av_free(c->chapter_tracks);
5665 2 c->chapter_tracks = new_tracks;
5666 2 c->nb_chapter_tracks = num;
5667
5668
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++)
5669 2 c->chapter_tracks[i] = avio_rb32(pb);
5670
5671 2 c->nb_chapter_tracks = i;
5672
5673 2 return 0;
5674 }
5675
5676 24 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5677 {
5678 MOVTrackExt *trex;
5679 int err;
5680
5681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if ((uint64_t)c->trex_count+1 >= UINT_MAX / sizeof(*c->trex_data))
5682 return AVERROR_INVALIDDATA;
5683
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
24 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
5684 sizeof(*c->trex_data))) < 0) {
5685 c->trex_count = 0;
5686 return err;
5687 }
5688
5689 24 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
5690
5691 24 trex = &c->trex_data[c->trex_count++];
5692 24 avio_r8(pb); /* version */
5693 24 avio_rb24(pb); /* flags */
5694 24 trex->track_id = avio_rb32(pb);
5695 24 trex->stsd_id = avio_rb32(pb);
5696 24 trex->duration = avio_rb32(pb);
5697 24 trex->size = avio_rb32(pb);
5698 24 trex->flags = avio_rb32(pb);
5699 24 return 0;
5700 }
5701
5702 420 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5703 {
5704 420 MOVFragment *frag = &c->fragment;
5705 420 AVStream *st = NULL;
5706 MOVStreamContext *sc;
5707 int version, i;
5708 MOVFragmentStreamInfo * frag_stream_info;
5709 int64_t base_media_decode_time;
5710
5711
1/2
✓ Branch 0 taken 446 times.
✗ Branch 1 not taken.
446 for (i = 0; i < c->fc->nb_streams; i++) {
5712 446 sc = c->fc->streams[i]->priv_data;
5713
2/2
✓ Branch 0 taken 420 times.
✓ Branch 1 taken 26 times.
446 if (sc->id == frag->track_id) {
5714 420 st = c->fc->streams[i];
5715 420 break;
5716 }
5717 }
5718
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 420 times.
420 if (!st) {
5719 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5720 return 0;
5721 }
5722 420 sc = st->priv_data;
5723
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 418 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
420 if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1)
5724 return 0;
5725 420 version = avio_r8(pb);
5726 420 avio_rb24(pb); /* flags */
5727
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 367 times.
420 if (version) {
5728 53 base_media_decode_time = avio_rb64(pb);
5729 } else {
5730 367 base_media_decode_time = avio_rb32(pb);
5731 }
5732
5733 420 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5734
1/2
✓ Branch 0 taken 420 times.
✗ Branch 1 not taken.
420 if (frag_stream_info)
5735 420 frag_stream_info->tfdt_dts = base_media_decode_time;
5736 420 sc->track_end = base_media_decode_time;
5737
5738 420 return 0;
5739 }
5740
5741 493 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5742 {
5743 493 MOVFragment *frag = &c->fragment;
5744 493 AVStream *st = NULL;
5745 493 FFStream *sti = NULL;
5746 MOVStreamContext *sc;
5747 MOVTimeToSample *tts_data;
5748 uint64_t offset;
5749 493 int64_t dts, pts = AV_NOPTS_VALUE;
5750 493 int data_offset = 0;
5751 493 unsigned entries, first_sample_flags = frag->flags;
5752 int flags, distance, i;
5753 493 int64_t prev_dts = AV_NOPTS_VALUE;
5754 493 int next_frag_index = -1, index_entry_pos;
5755 size_t requested_size;
5756 size_t old_allocated_size;
5757 AVIndexEntry *new_entries;
5758 MOVFragmentStreamInfo * frag_stream_info;
5759
5760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (!frag->found_tfhd) {
5761 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
5762 return AVERROR_INVALIDDATA;
5763 }
5764
5765
1/2
✓ Branch 0 taken 551 times.
✗ Branch 1 not taken.
551 for (i = 0; i < c->fc->nb_streams; i++) {
5766 551 sc = c->fc->streams[i]->priv_data;
5767
2/2
✓ Branch 0 taken 493 times.
✓ Branch 1 taken 58 times.
551 if (sc->id == frag->track_id) {
5768 493 st = c->fc->streams[i];
5769 493 sti = ffstream(st);
5770 493 break;
5771 }
5772 }
5773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (!st) {
5774 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5775 return 0;
5776 }
5777 493 sc = st->priv_data;
5778
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 491 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
493 if (sc->pseudo_stream_id+1 != frag->stsd_id && sc->pseudo_stream_id != -1)
5779 return 0;
5780
5781 // Find the next frag_index index that has a valid index_entry for
5782 // the current track_id.
5783 //
5784 // A valid index_entry means the trun for the fragment was read
5785 // and it's samples are in index_entries at the given position.
5786 // New index entries will be inserted before the index_entry found.
5787 493 index_entry_pos = sti->nb_index_entries;
5788
2/2
✓ Branch 0 taken 1621 times.
✓ Branch 1 taken 493 times.
2114 for (i = c->frag_index.current + 1; i < c->frag_index.nb_items; i++) {
5789 1621 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
5790
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) {
5791 next_frag_index = i;
5792 index_entry_pos = frag_stream_info->index_entry;
5793 break;
5794 }
5795 }
5796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 av_assert0(index_entry_pos <= sti->nb_index_entries);
5797
5798 493 avio_r8(pb); /* version */
5799 493 flags = avio_rb24(pb);
5800 493 entries = avio_rb32(pb);
5801 493 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
5802
5803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if ((uint64_t)entries+sc->tts_count >= UINT_MAX/sizeof(*sc->tts_data))
5804 return AVERROR_INVALIDDATA;
5805
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
5806
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 420 times.
493 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb);
5807
5808 493 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5809
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (frag_stream_info) {
5810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
5811 dts = frag_stream_info->next_trun_dts - sc->time_offset;
5812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5813 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
5814 pts = frag_stream_info->first_tfra_pts;
5815 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5816 ", using it for pts\n", pts);
5817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5818 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
5819 dts = frag_stream_info->first_tfra_pts;
5820 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5821 ", using it for dts\n", pts);
5822 } else {
5823 493 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
5824 493 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
5825
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
493 int fallback_tfdt = !c->use_tfdt && !has_sidx && has_tfdt;
5826
4/6
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 420 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
493 int fallback_sidx = c->use_tfdt && !has_tfdt && has_sidx;
5827
5828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (fallback_sidx) {
5829 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
5830 }
5831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (fallback_tfdt) {
5832 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
5833 }
5834
5835
4/6
✓ Branch 0 taken 420 times.
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 420 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
493 if (has_tfdt && c->use_tfdt || fallback_tfdt) {
5836 420 dts = frag_stream_info->tfdt_dts - sc->time_offset;
5837 420 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
5838 ", using it for dts\n", dts);
5839
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
73 } else if (has_sidx && !c->use_tfdt || fallback_sidx) {
5840 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
5841 // pts = frag_stream_info->sidx_pts;
5842 dts = frag_stream_info->sidx_pts - sc->time_offset;
5843 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
5844 ", using it for dts\n", frag_stream_info->sidx_pts);
5845 } else {
5846 73 dts = sc->track_end - sc->time_offset;
5847 73 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5848 ", using it for dts\n", dts);
5849 }
5850 }
5851 } else {
5852 dts = sc->track_end - sc->time_offset;
5853 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5854 ", using it for dts\n", dts);
5855 }
5856 493 offset = frag->base_data_offset + data_offset;
5857 493 distance = 0;
5858 493 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
5859
5860 // realloc space for new index entries
5861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
5862 entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
5863 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
5864 }
5865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (entries == 0)
5866 return 0;
5867
5868 493 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
5869 493 new_entries = av_fast_realloc(sti->index_entries,
5870 &sti->index_entries_allocated_size,
5871 requested_size);
5872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (!new_entries)
5873 return AVERROR(ENOMEM);
5874 493 sti->index_entries= new_entries;
5875
5876 493 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
5877 493 old_allocated_size = sc->tts_allocated_size;
5878 493 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
5879 requested_size);
5880
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (!tts_data)
5881 return AVERROR(ENOMEM);
5882 493 sc->tts_data = tts_data;
5883
5884 // In case there were samples without time to sample entries, ensure they get
5885 // zero valued entries. This ensures clips which mix boxes with and
5886 // without time to sample entries don't pickup uninitialized data.
5887 493 memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0,
5888 493 sc->tts_allocated_size - old_allocated_size);
5889
5890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (index_entry_pos < sti->nb_index_entries) {
5891 // Make hole in index_entries and tts_data for new samples
5892 memmove(sti->index_entries + index_entry_pos + entries,
5893 sti->index_entries + index_entry_pos,
5894 sizeof(*sti->index_entries) *
5895 (sti->nb_index_entries - index_entry_pos));
5896 memmove(sc->tts_data + index_entry_pos + entries,
5897 sc->tts_data + index_entry_pos,
5898 sizeof(*sc->tts_data) * (sc->tts_count - index_entry_pos));
5899 if (index_entry_pos < sc->current_sample) {
5900 sc->current_sample += entries;
5901 }
5902 }
5903
5904 493 sti->nb_index_entries += entries;
5905 493 sc->tts_count = sti->nb_index_entries;
5906 493 sc->stts_count = sti->nb_index_entries;
5907
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 107 times.
493 if (flags & MOV_TRUN_SAMPLE_CTS)
5908 386 sc->ctts_count = sti->nb_index_entries;
5909
5910 // Record the index_entry position in frag_index of this fragment
5911
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (frag_stream_info) {
5912 493 frag_stream_info->index_entry = index_entry_pos;
5913
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (frag_stream_info->index_base < 0)
5914 493 frag_stream_info->index_base = index_entry_pos;
5915 }
5916
5917
2/2
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 23 times.
493 if (index_entry_pos > 0)
5918 470 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
5919
5920
3/4
✓ Branch 0 taken 8514 times.
✓ Branch 1 taken 493 times.
✓ Branch 2 taken 8514 times.
✗ Branch 3 not taken.
9007 for (i = 0; i < entries && !pb->eof_reached; i++) {
5921 8514 unsigned sample_size = frag->size;
5922
2/2
✓ Branch 0 taken 8021 times.
✓ Branch 1 taken 493 times.
8514 int sample_flags = i ? frag->flags : first_sample_flags;
5923 8514 unsigned sample_duration = frag->duration;
5924 8514 unsigned ctts_duration = 0;
5925 8514 int keyframe = 0;
5926 8514 int index_entry_flags = 0;
5927
5928
2/2
✓ Branch 0 taken 1674 times.
✓ Branch 1 taken 6840 times.
8514 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
5929
2/2
✓ Branch 0 taken 8456 times.
✓ Branch 1 taken 58 times.
8514 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
5930
2/2
✓ Branch 0 taken 933 times.
✓ Branch 1 taken 7581 times.
8514 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
5931
2/2
✓ Branch 0 taken 6576 times.
✓ Branch 1 taken 1938 times.
8514 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
5932
5933 8514 mov_update_dts_shift(sc, ctts_duration, c->fc);
5934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8514 times.
8514 if (pts != AV_NOPTS_VALUE) {
5935 dts = pts - sc->dts_shift;
5936 if (flags & MOV_TRUN_SAMPLE_CTS) {
5937 dts -= ctts_duration;
5938 } else {
5939 dts -= sc->time_offset;
5940 }
5941 av_log(c->fc, AV_LOG_DEBUG,
5942 "pts %"PRId64" calculated dts %"PRId64
5943 " sc->dts_shift %d ctts.duration %d"
5944 " sc->time_offset %"PRId64
5945 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
5946 pts, dts,
5947 sc->dts_shift, ctts_duration,
5948 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
5949 pts = AV_NOPTS_VALUE;
5950 }
5951
5952 8514 keyframe =
5953 8514 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
5954 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
5955
2/2
✓ Branch 0 taken 548 times.
✓ Branch 1 taken 7966 times.
8514 if (keyframe) {
5956 548 distance = 0;
5957 548 index_entry_flags |= AVINDEX_KEYFRAME;
5958 }
5959 // Fragments can overlap in time. Discard overlapping frames after
5960 // decoding.
5961
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8490 times.
8514 if (prev_dts >= dts)
5962 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
5963
5964 8514 sti->index_entries[index_entry_pos].pos = offset;
5965 8514 sti->index_entries[index_entry_pos].timestamp = dts;
5966 8514 sti->index_entries[index_entry_pos].size = sample_size;
5967 8514 sti->index_entries[index_entry_pos].min_distance = distance;
5968 8514 sti->index_entries[index_entry_pos].flags = index_entry_flags;
5969
5970 8514 sc->tts_data[index_entry_pos].count = 1;
5971 8514 sc->tts_data[index_entry_pos].offset = ctts_duration;
5972 8514 sc->tts_data[index_entry_pos].duration = sample_duration;
5973 8514 index_entry_pos++;
5974
5975 8514 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
5976 "size %u, distance %d, keyframe %d\n", st->index,
5977 index_entry_pos, offset, dts, sample_size, distance, keyframe);
5978 8514 distance++;
5979
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8514 times.
8514 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
5980 return AVERROR_INVALIDDATA;
5981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8514 times.
8514 if (!sample_size)
5982 return AVERROR_INVALIDDATA;
5983 8514 dts += sample_duration;
5984 8514 offset += sample_size;
5985 8514 sc->data_size += sample_size;
5986
5987
1/2
✓ Branch 0 taken 8514 times.
✗ Branch 1 not taken.
8514 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
5988
1/2
✓ Branch 0 taken 8514 times.
✗ Branch 1 not taken.
8514 1 <= INT_MAX - sc->nb_frames_for_fps
5989 ) {
5990 8514 sc->duration_for_fps += sample_duration;
5991 8514 sc->nb_frames_for_fps ++;
5992 }
5993 }
5994
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (frag_stream_info)
5995 493 frag_stream_info->next_trun_dts = dts + sc->time_offset;
5996
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (i < entries) {
5997 // EOF found before reading all entries. Fix the hole this would
5998 // leave in index_entries and tts_data
5999 int gap = entries - i;
6000 memmove(sti->index_entries + index_entry_pos,
6001 sti->index_entries + index_entry_pos + gap,
6002 sizeof(*sti->index_entries) *
6003 (sti->nb_index_entries - (index_entry_pos + gap)));
6004 memmove(sc->tts_data + index_entry_pos,
6005 sc->tts_data + index_entry_pos + gap,
6006 sizeof(*sc->tts_data) *
6007 (sc->tts_count - (index_entry_pos + gap)));
6008
6009 sti->nb_index_entries -= gap;
6010 sc->tts_count -= gap;
6011 if (index_entry_pos < sc->current_sample) {
6012 sc->current_sample -= gap;
6013 }
6014 entries = i;
6015 }
6016
6017 // The end of this new fragment may overlap in time with the start
6018 // of the next fragment in index_entries. Mark the samples in the next
6019 // fragment that overlap with AVINDEX_DISCARD_FRAME
6020 493 prev_dts = AV_NOPTS_VALUE;
6021
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (index_entry_pos > 0)
6022 493 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6023
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
6024 if (prev_dts < sti->index_entries[i].timestamp)
6025 break;
6026 sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6027 }
6028
6029 // If a hole was created to insert the new index_entries into,
6030 // the index_entry recorded for all subsequent moof must
6031 // be incremented by the number of entries inserted.
6032 493 fix_frag_index_entries(&c->frag_index, next_frag_index,
6033 493 frag->track_id, entries);
6034
6035
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (pb->eof_reached) {
6036 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6037 return AVERROR_EOF;
6038 }
6039
6040 493 frag->implicit_offset = offset;
6041
6042 493 sc->track_end = dts + sc->time_offset;
6043
2/2
✓ Branch 0 taken 113 times.
✓ Branch 1 taken 380 times.
493 if (st->duration < sc->track_end)
6044 113 st->duration = sc->track_end;
6045
6046 493 return 0;
6047 }
6048
6049 44 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6050 {
6051 44 int64_t stream_size = avio_size(pb);
6052 44 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6053 uint8_t version, is_complete;
6054 int64_t offadd;
6055 unsigned i, j, track_id, item_count;
6056 44 AVStream *st = NULL;
6057 44 AVStream *ref_st = NULL;
6058 44 MOVStreamContext *sc, *ref_sc = NULL;
6059 AVRational timescale;
6060
6061 44 version = avio_r8(pb);
6062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (version > 1) {
6063 avpriv_request_sample(c->fc, "sidx version %u", version);
6064 return 0;
6065 }
6066
6067 44 avio_rb24(pb); // flags
6068
6069 44 track_id = avio_rb32(pb); // Reference ID
6070
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 for (i = 0; i < c->fc->nb_streams; i++) {
6071 44 sc = c->fc->streams[i]->priv_data;
6072
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 if (sc->id == track_id) {
6073 44 st = c->fc->streams[i];
6074 44 break;
6075 }
6076 }
6077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (!st) {
6078 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6079 return 0;
6080 }
6081
6082 44 sc = st->priv_data;
6083
6084 44 timescale = av_make_q(1, avio_rb32(pb));
6085
6086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (timescale.den <= 0) {
6087 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6088 return AVERROR_INVALIDDATA;
6089 }
6090
6091
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 1 times.
44 if (version == 0) {
6092 43 pts = avio_rb32(pb);
6093 43 offadd= avio_rb32(pb);
6094 } else {
6095 1 pts = avio_rb64(pb);
6096 1 offadd= avio_rb64(pb);
6097 }
6098
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
44 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6099 return AVERROR_INVALIDDATA;
6100
6101 44 offset += (uint64_t)offadd;
6102
6103 44 avio_rb16(pb); // reserved
6104
6105 44 item_count = avio_rb16(pb);
6106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (item_count == 0)
6107 return AVERROR_INVALIDDATA;
6108
6109
2/2
✓ Branch 0 taken 369 times.
✓ Branch 1 taken 44 times.
413 for (i = 0; i < item_count; i++) {
6110 int index;
6111 MOVFragmentStreamInfo * frag_stream_info;
6112 369 uint32_t size = avio_rb32(pb);
6113 369 uint32_t duration = avio_rb32(pb);
6114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 369 times.
369 if (size & 0x80000000) {
6115 avpriv_request_sample(c->fc, "sidx reference_type 1");
6116 return AVERROR_PATCHWELCOME;
6117 }
6118 369 avio_rb32(pb); // sap_flags
6119 369 timestamp = av_rescale_q(pts, timescale, st->time_base);
6120
6121 369 index = update_frag_index(c, offset);
6122 369 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6123
1/2
✓ Branch 0 taken 369 times.
✗ Branch 1 not taken.
369 if (frag_stream_info)
6124 369 frag_stream_info->sidx_pts = timestamp;
6125
6126
1/2
✓ Branch 1 taken 369 times.
✗ Branch 2 not taken.
369 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6127
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 369 times.
369 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6128 )
6129 return AVERROR_INVALIDDATA;
6130 369 offset += size;
6131 369 pts += duration;
6132 }
6133
6134 44 st->duration = sc->track_end = pts;
6135
6136 44 sc->has_sidx = 1;
6137
6138 // See if the remaining bytes are just an mfra which we can ignore.
6139 44 is_complete = offset == stream_size;
6140
5/6
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
44 if (!is_complete && (pb->seekable & AVIO_SEEKABLE_NORMAL) && stream_size > 0 ) {
6141 int64_t ret;
6142 38 int64_t original_pos = avio_tell(pb);
6143
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
38 if (!c->have_read_mfra_size) {
6144
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6145 return ret;
6146 3 c->mfra_size = avio_rb32(pb);
6147 3 c->have_read_mfra_size = 1;
6148
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6149 return ret;
6150 }
6151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (offset == stream_size - c->mfra_size)
6152 is_complete = 1;
6153 }
6154
6155
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 39 times.
44 if (is_complete) {
6156 // Find first entry in fragment index that came from an sidx.
6157 // This will pretty much always be the first entry.
6158
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 5 times.
373 for (i = 0; i < c->frag_index.nb_items; i++) {
6159 368 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6160
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++) {
6161 MOVFragmentStreamInfo * si;
6162 5 si = &item->stream_info[j];
6163
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (si->sidx_pts != AV_NOPTS_VALUE) {
6164 5 ref_st = c->fc->streams[j];
6165 5 ref_sc = ref_st->priv_data;
6166 5 break;
6167 }
6168 }
6169 }
6170
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++) {
6171 5 st = c->fc->streams[i];
6172 5 sc = st->priv_data;
6173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->has_sidx) {
6174 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6175 }
6176 }
6177
6178 5 c->frag_index.complete = 1;
6179 }
6180
6181 44 return 0;
6182 }
6183
6184 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6185 /* like the files created with Adobe Premiere 5.0, for samples see */
6186 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6187 271 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6188 {
6189 int err;
6190
6191
1/2
✓ Branch 0 taken 271 times.
✗ Branch 1 not taken.
271 if (atom.size < 8)
6192 271 return 0; /* continue */
6193 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6194 avio_skip(pb, atom.size - 4);
6195 return 0;
6196 }
6197 atom.type = avio_rl32(pb);
6198 atom.size -= 8;
6199 if (atom.type != MKTAG('m','d','a','t')) {
6200 avio_skip(pb, atom.size);
6201 return 0;
6202 }
6203 err = mov_read_mdat(c, pb, atom);
6204 return err;
6205 }
6206
6207 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6208 {
6209 #if CONFIG_ZLIB
6210 FFIOContext ctx;
6211 uint8_t *cmov_data;
6212 uint8_t *moov_data; /* uncompressed data */
6213 long cmov_len, moov_len;
6214 3 int ret = -1;
6215
6216 3 avio_rb32(pb); /* dcom atom */
6217
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6218 return AVERROR_INVALIDDATA;
6219
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6220 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6221 return AVERROR_INVALIDDATA;
6222 }
6223 3 avio_rb32(pb); /* cmvd atom */
6224
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6225 return AVERROR_INVALIDDATA;
6226 3 moov_len = avio_rb32(pb); /* uncompressed size */
6227 3 cmov_len = atom.size - 6 * 4;
6228
6229 3 cmov_data = av_malloc(cmov_len);
6230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6231 return AVERROR(ENOMEM);
6232 3 moov_data = av_malloc(moov_len);
6233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6234 av_free(cmov_data);
6235 return AVERROR(ENOMEM);
6236 }
6237 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6239 goto free_and_return;
6240
6241 3 ret = AVERROR_INVALIDDATA;
6242
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)
6243 goto free_and_return;
6244 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6245 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6246 3 atom.type = MKTAG('m','o','o','v');
6247 3 atom.size = moov_len;
6248 3 ret = mov_read_default(c, &ctx.pub, atom);
6249 3 free_and_return:
6250 3 av_free(moov_data);
6251 3 av_free(cmov_data);
6252 3 return ret;
6253 #else
6254 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6255 return AVERROR(ENOSYS);
6256 #endif
6257 }
6258
6259 /* edit list atom */
6260 446 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6261 {
6262 MOVStreamContext *sc;
6263 int i, edit_count, version;
6264 int64_t elst_entry_size;
6265
6266
2/4
✓ Branch 0 taken 446 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 446 times.
446 if (c->fc->nb_streams < 1 || c->ignore_editlist)
6267 return 0;
6268 446 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6269
6270 446 version = avio_r8(pb); /* version */
6271 446 avio_rb24(pb); /* flags */
6272 446 edit_count = avio_rb32(pb); /* entries */
6273 446 atom.size -= 8;
6274
6275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 446 times.
446 elst_entry_size = version == 1 ? 20 : 12;
6276
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 445 times.
446 if (atom.size != edit_count * elst_entry_size) {
6277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6278 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6279 edit_count, atom.size + 8);
6280 return AVERROR_INVALIDDATA;
6281 } else {
6282 1 edit_count = atom.size / elst_entry_size;
6283
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6284 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6285 }
6286 }
6287 }
6288
6289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 446 times.
446 if (!edit_count)
6290 return 0;
6291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 446 times.
446 if (sc->elst_data)
6292 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6293 446 av_free(sc->elst_data);
6294 446 sc->elst_count = 0;
6295 446 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 446 times.
446 if (!sc->elst_data)
6297 return AVERROR(ENOMEM);
6298
6299 446 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6300
4/6
✓ Branch 0 taken 473 times.
✓ Branch 1 taken 446 times.
✓ Branch 2 taken 473 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 473 times.
✗ Branch 5 not taken.
919 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
6301 473 MOVElst *e = &sc->elst_data[i];
6302
6303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 473 times.
473 if (version == 1) {
6304 e->duration = avio_rb64(pb);
6305 e->time = avio_rb64(pb);
6306 atom.size -= 16;
6307 } else {
6308 473 e->duration = avio_rb32(pb); /* segment duration */
6309 473 e->time = (int32_t)avio_rb32(pb); /* media time */
6310 473 atom.size -= 8;
6311 }
6312 473 e->rate = avio_rb32(pb) / 65536.0;
6313 473 atom.size -= 4;
6314 473 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6315 473 e->duration, e->time, e->rate);
6316
6317
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 469 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
473 if (e->time < 0 && e->time != -1 &&
6318 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6319 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6320 c->fc->nb_streams-1, i, e->time);
6321 return AVERROR_INVALIDDATA;
6322 }
6323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 473 times.
473 if (e->duration < 0) {
6324 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list duration=%"PRId64"\n",
6325 c->fc->nb_streams-1, i, e->duration);
6326 return AVERROR_INVALIDDATA;
6327 }
6328 }
6329 446 sc->elst_count = i;
6330
6331 446 return 0;
6332 }
6333
6334 18 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6335 {
6336 MOVStreamContext *sc;
6337
6338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->fc->nb_streams < 1)
6339 return AVERROR_INVALIDDATA;
6340 18 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6341 18 sc->timecode_track = avio_rb32(pb);
6342 18 return 0;
6343 }
6344
6345 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6346 {
6347 AVStream *st;
6348 int version, color_range, color_primaries, color_trc, color_space;
6349
6350 if (c->fc->nb_streams < 1)
6351 return 0;
6352 st = c->fc->streams[c->fc->nb_streams - 1];
6353
6354 if (atom.size < 5) {
6355 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6356 return AVERROR_INVALIDDATA;
6357 }
6358
6359 version = avio_r8(pb);
6360 if (version != 1) {
6361 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6362 return 0;
6363 }
6364 avio_skip(pb, 3); /* flags */
6365
6366 avio_skip(pb, 2); /* profile + level */
6367 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6368 color_primaries = avio_r8(pb);
6369 color_trc = avio_r8(pb);
6370 color_space = avio_r8(pb);
6371 if (avio_rb16(pb)) /* codecIntializationDataSize */
6372 return AVERROR_INVALIDDATA;
6373
6374 if (!av_color_primaries_name(color_primaries))
6375 color_primaries = AVCOL_PRI_UNSPECIFIED;
6376 if (!av_color_transfer_name(color_trc))
6377 color_trc = AVCOL_TRC_UNSPECIFIED;
6378 if (!av_color_space_name(color_space))
6379 color_space = AVCOL_SPC_UNSPECIFIED;
6380
6381 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6382 st->codecpar->color_primaries = color_primaries;
6383 st->codecpar->color_trc = color_trc;
6384 st->codecpar->color_space = color_space;
6385
6386 return 0;
6387 }
6388
6389 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6390 {
6391 MOVStreamContext *sc;
6392 int i, version;
6393
6394 if (c->fc->nb_streams < 1)
6395 return AVERROR_INVALIDDATA;
6396
6397 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6398
6399 if (atom.size < 5) {
6400 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6401 return AVERROR_INVALIDDATA;
6402 }
6403
6404 version = avio_r8(pb);
6405 if (version) {
6406 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6407 return 0;
6408 }
6409 if (sc->mastering) {
6410 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6411 return 0;
6412 }
6413
6414 avio_skip(pb, 3); /* flags */
6415
6416 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6417 if (!sc->mastering)
6418 return AVERROR(ENOMEM);
6419
6420 for (i = 0; i < 3; i++) {
6421 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6422 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6423 }
6424 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6425 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6426
6427 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6428 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6429
6430 sc->mastering->has_primaries = 1;
6431 sc->mastering->has_luminance = 1;
6432
6433 return 0;
6434 }
6435
6436 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6437 {
6438 MOVStreamContext *sc;
6439 const int mapping[3] = {1, 2, 0};
6440 const int chroma_den = 50000;
6441 const int luma_den = 10000;
6442 int i;
6443
6444 if (c->fc->nb_streams < 1)
6445 return AVERROR_INVALIDDATA;
6446
6447 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6448
6449 if (atom.size < 24) {
6450 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6451 return AVERROR_INVALIDDATA;
6452 }
6453
6454 if (sc->mastering) {
6455 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6456 return 0;
6457 }
6458
6459 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6460 if (!sc->mastering)
6461 return AVERROR(ENOMEM);
6462
6463 for (i = 0; i < 3; i++) {
6464 const int j = mapping[i];
6465 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6466 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6467 }
6468 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6469 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6470
6471 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6472 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6473
6474 sc->mastering->has_luminance = 1;
6475 sc->mastering->has_primaries = 1;
6476
6477 return 0;
6478 }
6479
6480 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6481 {
6482 MOVStreamContext *sc;
6483 int version;
6484
6485 if (c->fc->nb_streams < 1)
6486 return AVERROR_INVALIDDATA;
6487
6488 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6489
6490 if (atom.size < 5) {
6491 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
6492 return AVERROR_INVALIDDATA;
6493 }
6494
6495 version = avio_r8(pb);
6496 if (version) {
6497 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
6498 return 0;
6499 }
6500 avio_skip(pb, 3); /* flags */
6501
6502 if (sc->coll){
6503 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate 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 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6518 {
6519 MOVStreamContext *sc;
6520
6521 if (c->fc->nb_streams < 1)
6522 return AVERROR_INVALIDDATA;
6523
6524 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6525
6526 if (atom.size < 4) {
6527 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
6528 return AVERROR_INVALIDDATA;
6529 }
6530
6531 if (sc->coll){
6532 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
6533 return 0;
6534 }
6535
6536 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6537 if (!sc->coll)
6538 return AVERROR(ENOMEM);
6539
6540 sc->coll->MaxCLL = avio_rb16(pb);
6541 sc->coll->MaxFALL = avio_rb16(pb);
6542
6543 return 0;
6544 }
6545
6546 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6547 {
6548 MOVStreamContext *sc;
6549 4 const int illuminance_den = 10000;
6550 4 const int ambient_den = 50000;
6551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
6552 return AVERROR_INVALIDDATA;
6553 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6554
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
6555 av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
6556 return AVERROR_INVALIDDATA;
6557 }
6558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
6559 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
6560 return 0;
6561 }
6562 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
6563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
6564 return AVERROR(ENOMEM);
6565 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
6566 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
6567 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
6568 4 return 0;
6569 }
6570
6571 1 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6572 {
6573 AVStream *st;
6574 MOVStreamContext *sc;
6575 enum AVStereo3DType type;
6576 int mode;
6577
6578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6579 return 0;
6580
6581 1 st = c->fc->streams[c->fc->nb_streams - 1];
6582 1 sc = st->priv_data;
6583
6584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 5) {
6585 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
6586 return AVERROR_INVALIDDATA;
6587 }
6588
6589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sc->stereo3d)
6590 return AVERROR_INVALIDDATA;
6591
6592 1 avio_skip(pb, 4); /* version + flags */
6593
6594 1 mode = avio_r8(pb);
6595
1/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 switch (mode) {
6596 1 case 0:
6597 1 type = AV_STEREO3D_2D;
6598 1 break;
6599 case 1:
6600 type = AV_STEREO3D_TOPBOTTOM;
6601 break;
6602 case 2:
6603 type = AV_STEREO3D_SIDEBYSIDE;
6604 break;
6605 default:
6606 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
6607 return 0;
6608 }
6609
6610 1 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->stereo3d)
6612 return AVERROR(ENOMEM);
6613
6614 1 sc->stereo3d->type = type;
6615 1 return 0;
6616 }
6617
6618 static int mov_read_pack(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6619 {
6620 AVStream *st;
6621 MOVStreamContext *sc;
6622 int size = 0;
6623 int64_t remaining;
6624 uint32_t tag = 0;
6625 enum AVStereo3DType type = AV_STEREO3D_2D;
6626
6627 if (c->fc->nb_streams < 1)
6628 return 0;
6629
6630 st = c->fc->streams[c->fc->nb_streams - 1];
6631 sc = st->priv_data;
6632
6633 remaining = atom.size;
6634 while (remaining > 0) {
6635 size = avio_rb32(pb);
6636 if (size < 8 || size > remaining ) {
6637 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in pack box\n");
6638 return AVERROR_INVALIDDATA;
6639 }
6640
6641 tag = avio_rl32(pb);
6642 switch (tag) {
6643 case MKTAG('p','k','i','n'): {
6644 if (size != 16) {
6645 av_log(c->fc, AV_LOG_ERROR, "Invalid size of pkin box: %d\n", size);
6646 return AVERROR_INVALIDDATA;
6647 }
6648 avio_skip(pb, 1); // version
6649 avio_skip(pb, 3); // flags
6650
6651 tag = avio_rl32(pb);
6652 switch (tag) {
6653 case MKTAG('s','i','d','e'):
6654 type = AV_STEREO3D_SIDEBYSIDE;
6655 break;
6656 case MKTAG('o','v','e','r'):
6657 type = AV_STEREO3D_TOPBOTTOM;
6658 break;
6659 case 0:
6660 // This means value will be set in another layer
6661 break;
6662 default:
6663 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pkin: 0x%08X\n", tag);
6664 avio_skip(pb, size - 8);
6665 break;
6666 }
6667
6668 break;
6669 }
6670 default:
6671 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pack: 0x%08X\n", tag);
6672 avio_skip(pb, size - 8);
6673 break;
6674 }
6675 remaining -= size;
6676 }
6677
6678 if (remaining != 0) {
6679 av_log(c->fc, AV_LOG_ERROR, "Broken pack box\n");
6680 return AVERROR_INVALIDDATA;
6681 }
6682
6683 if (type == AV_STEREO3D_2D)
6684 return 0;
6685
6686 if (!sc->stereo3d) {
6687 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6688 if (!sc->stereo3d)
6689 return AVERROR(ENOMEM);
6690 }
6691
6692 sc->stereo3d->type = type;
6693
6694 return 0;
6695 }
6696
6697 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6698 {
6699 AVStream *st;
6700 MOVStreamContext *sc;
6701 int size, version, layout;
6702 int32_t yaw, pitch, roll;
6703 1 uint32_t l = 0, t = 0, r = 0, b = 0;
6704 1 uint32_t tag, padding = 0;
6705 enum AVSphericalProjection projection;
6706
6707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6708 return 0;
6709
6710 1 st = c->fc->streams[c->fc->nb_streams - 1];
6711 1 sc = st->priv_data;
6712
6713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
6714 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
6715 return AVERROR_INVALIDDATA;
6716 }
6717
6718 1 size = avio_rb32(pb);
6719
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)
6720 return AVERROR_INVALIDDATA;
6721
6722 1 tag = avio_rl32(pb);
6723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
6724 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
6725 return 0;
6726 }
6727 1 version = avio_r8(pb);
6728
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6729 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6730 version);
6731 return 0;
6732 }
6733 1 avio_skip(pb, 3); /* flags */
6734 1 avio_skip(pb, size - 12); /* metadata_source */
6735
6736 1 size = avio_rb32(pb);
6737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6738 return AVERROR_INVALIDDATA;
6739
6740 1 tag = avio_rl32(pb);
6741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
6742 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
6743 return 0;
6744 }
6745
6746 1 size = avio_rb32(pb);
6747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6748 return AVERROR_INVALIDDATA;
6749
6750 1 tag = avio_rl32(pb);
6751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
6752 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
6753 return 0;
6754 }
6755 1 version = avio_r8(pb);
6756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6757 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6758 version);
6759 return 0;
6760 }
6761 1 avio_skip(pb, 3); /* flags */
6762
6763 /* 16.16 fixed point */
6764 1 yaw = avio_rb32(pb);
6765 1 pitch = avio_rb32(pb);
6766 1 roll = avio_rb32(pb);
6767
6768 1 size = avio_rb32(pb);
6769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6770 return AVERROR_INVALIDDATA;
6771
6772 1 tag = avio_rl32(pb);
6773 1 version = avio_r8(pb);
6774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6775 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6776 version);
6777 return 0;
6778 }
6779 1 avio_skip(pb, 3); /* flags */
6780
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
6781 case MKTAG('c','b','m','p'):
6782 layout = avio_rb32(pb);
6783 if (layout) {
6784 av_log(c->fc, AV_LOG_WARNING,
6785 "Unsupported cubemap layout %d\n", layout);
6786 return 0;
6787 }
6788 projection = AV_SPHERICAL_CUBEMAP;
6789 padding = avio_rb32(pb);
6790 break;
6791 1 case MKTAG('e','q','u','i'):
6792 1 t = avio_rb32(pb);
6793 1 b = avio_rb32(pb);
6794 1 l = avio_rb32(pb);
6795 1 r = avio_rb32(pb);
6796
6797
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) {
6798 av_log(c->fc, AV_LOG_ERROR,
6799 "Invalid bounding rectangle coordinates "
6800 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
6801 return AVERROR_INVALIDDATA;
6802 }
6803
6804
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)
6805 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
6806 else
6807 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6808 1 break;
6809 default:
6810 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
6811 return 0;
6812 }
6813
6814 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6815
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
6816 return AVERROR(ENOMEM);
6817
6818 1 sc->spherical->projection = projection;
6819
6820 1 sc->spherical->yaw = yaw;
6821 1 sc->spherical->pitch = pitch;
6822 1 sc->spherical->roll = roll;
6823
6824 1 sc->spherical->padding = padding;
6825
6826 1 sc->spherical->bound_left = l;
6827 1 sc->spherical->bound_top = t;
6828 1 sc->spherical->bound_right = r;
6829 1 sc->spherical->bound_bottom = b;
6830
6831 1 return 0;
6832 }
6833
6834 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6835 {
6836 AVStream *st;
6837 MOVStreamContext *sc;
6838 int size;
6839 uint32_t tag;
6840 enum AVSphericalProjection projection;
6841
6842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6843 return 0;
6844
6845 3 st = c->fc->streams[c->fc->nb_streams - 1];
6846 3 sc = st->priv_data;
6847
6848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 16) {
6849 av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
6850 return AVERROR_INVALIDDATA;
6851 }
6852
6853 3 size = avio_rb32(pb);
6854
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 16) {
6855 av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
6856 return AVERROR_INVALIDDATA;
6857 }
6858
6859 3 tag = avio_rl32(pb);
6860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
6861 av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: 0x%08X\n", tag);
6862 return AVERROR_INVALIDDATA;
6863 }
6864
6865 3 avio_skip(pb, 1); // version
6866 3 avio_skip(pb, 3); // flags
6867
6868 3 tag = avio_rl32(pb);
6869
1/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3 switch (tag) {
6870 3 case MKTAG('r','e','c','t'):
6871 3 projection = AV_SPHERICAL_RECTILINEAR;
6872 3 break;
6873 case MKTAG('e','q','u','i'):
6874 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6875 break;
6876 case MKTAG('h','e','q','u'):
6877 projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
6878 break;
6879 case MKTAG('f','i','s','h'):
6880 projection = AV_SPHERICAL_FISHEYE;
6881 break;
6882 case MKTAG('p','r','i','m'):
6883 projection = AV_SPHERICAL_PARAMETRIC_IMMERSIVE;
6884 break;
6885 default:
6886 av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: 0x%08X\n", tag);
6887 return AVERROR_INVALIDDATA;
6888 }
6889
6890 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
6892 return AVERROR(ENOMEM);
6893
6894 3 sc->spherical->projection = projection;
6895
6896 3 return 0;
6897 }
6898
6899 3 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6900 {
6901 AVStream *st;
6902 MOVStreamContext *sc;
6903 3 int size, flags = 0;
6904 int64_t remaining;
6905 3 uint32_t tag, baseline = 0;
6906 3 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
6907 3 enum AVStereo3DType type = AV_STEREO3D_2D;
6908 3 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
6909 3 AVRational horizontal_disparity_adjustment = { 0, 1 };
6910
6911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6912 return 0;
6913
6914 3 st = c->fc->streams[c->fc->nb_streams - 1];
6915 3 sc = st->priv_data;
6916
6917 3 remaining = atom.size;
6918
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 while (remaining > 0) {
6919 9 size = avio_rb32(pb);
6920
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 ) {
6921 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
6922 return AVERROR_INVALIDDATA;
6923 }
6924
6925 9 tag = avio_rl32(pb);
6926
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) {
6927 3 case MKTAG('s','t','r','i'): {
6928 int has_right, has_left;
6929 uint8_t tmp;
6930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 13) {
6931 av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
6932 return AVERROR_INVALIDDATA;
6933 }
6934 3 avio_skip(pb, 1); // version
6935 3 avio_skip(pb, 3); // flags
6936
6937 3 tmp = avio_r8(pb);
6938
6939 // eye_views_reversed
6940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tmp & 8) {
6941 flags |= AV_STEREO3D_FLAG_INVERT;
6942 }
6943 // has_additional_views
6944 3 if (tmp & 4) {
6945 // skip...
6946 }
6947
6948 3 has_right = tmp & 2; // has_right_eye_view
6949 3 has_left = tmp & 1; // has_left_eye_view
6950
6951
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)
6952 3 view = AV_STEREO3D_VIEW_PACKED;
6953 else if (has_left)
6954 view = AV_STEREO3D_VIEW_LEFT;
6955 else if (has_right)
6956 view = AV_STEREO3D_VIEW_RIGHT;
6957
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)
6958 3 type = AV_STEREO3D_UNSPEC;
6959
6960 3 break;
6961 }
6962 case MKTAG('h','e','r','o'): {
6963 int tmp;
6964 if (size != 13) {
6965 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
6966 return AVERROR_INVALIDDATA;
6967 }
6968 avio_skip(pb, 1); // version
6969 avio_skip(pb, 3); // flags
6970
6971 tmp = avio_r8(pb);
6972 if (tmp == 0)
6973 primary_eye = AV_PRIMARY_EYE_NONE;
6974 else if (tmp == 1)
6975 primary_eye = AV_PRIMARY_EYE_LEFT;
6976 else if (tmp == 2)
6977 primary_eye = AV_PRIMARY_EYE_RIGHT;
6978 else
6979 av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
6980
6981 break;
6982 }
6983 3 case MKTAG('c','a','m','s'): {
6984 uint32_t subtag;
6985 int subsize;
6986
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
6987 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
6988 return AVERROR_INVALIDDATA;
6989 }
6990
6991 3 subsize = avio_rb32(pb);
6992
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
6993 av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
6994 return AVERROR_INVALIDDATA;
6995 }
6996
6997 3 subtag = avio_rl32(pb);
6998
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
6999 av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got 0x%08X\n", subtag);
7000 return AVERROR_INVALIDDATA;
7001 }
7002
7003 3 avio_skip(pb, 1); // version
7004 3 avio_skip(pb, 3); // flags
7005
7006 3 baseline = avio_rb32(pb);
7007
7008 3 break;
7009 }
7010 3 case MKTAG('c','m','f','y'): {
7011 uint32_t subtag;
7012 int subsize;
7013 int32_t adjustment;
7014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7015 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
7016 return AVERROR_INVALIDDATA;
7017 }
7018
7019 3 subsize = avio_rb32(pb);
7020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7021 av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
7022 return AVERROR_INVALIDDATA;
7023 }
7024
7025 3 subtag = avio_rl32(pb);
7026
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
7027 av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got 0x%08X\n", subtag);
7028 return AVERROR_INVALIDDATA;
7029 }
7030
7031 3 avio_skip(pb, 1); // version
7032 3 avio_skip(pb, 3); // flags
7033
7034 3 adjustment = (int32_t) avio_rb32(pb);
7035
7036 3 horizontal_disparity_adjustment.num = (int) adjustment;
7037 3 horizontal_disparity_adjustment.den = 10000;
7038
7039 3 break;
7040 }
7041 default:
7042 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: 0x%08X\n", tag);
7043 avio_skip(pb, size - 8);
7044 break;
7045 }
7046 9 remaining -= size;
7047 }
7048
7049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7050 av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
7051 return AVERROR_INVALIDDATA;
7052 }
7053
7054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (type == AV_STEREO3D_2D)
7055 return 0;
7056
7057
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->stereo3d) {
7058 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7060 return AVERROR(ENOMEM);
7061 }
7062
7063 3 sc->stereo3d->flags = flags;
7064 3 sc->stereo3d->type = type;
7065 3 sc->stereo3d->view = view;
7066 3 sc->stereo3d->primary_eye = primary_eye;
7067 3 sc->stereo3d->baseline = baseline;
7068 3 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
7069
7070 3 return 0;
7071 }
7072
7073 3 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7074 {
7075 int size;
7076 int64_t remaining;
7077 uint32_t tag;
7078
7079
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7080 return 0;
7081
7082
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8) {
7083 av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
7084 return AVERROR_INVALIDDATA;
7085 }
7086
7087 3 remaining = atom.size;
7088
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 while (remaining > 0) {
7089 6 size = avio_rb32(pb);
7090
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 ) {
7091 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
7092 return AVERROR_INVALIDDATA;
7093 }
7094
7095 6 tag = avio_rl32(pb);
7096
2/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 switch (tag) {
7097 3 case MKTAG('p','r','o','j'): {
7098 3 MOVAtom proj = { tag, size - 8 };
7099 3 int ret = mov_read_vexu_proj(c, pb, proj);
7100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7101 return ret;
7102 3 break;
7103 }
7104 3 case MKTAG('e','y','e','s'): {
7105 3 MOVAtom eyes = { tag, size - 8 };
7106 3 int ret = mov_read_eyes(c, pb, eyes);
7107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7108 return ret;
7109 3 break;
7110 }
7111 case MKTAG('p','a','c','k'): {
7112 MOVAtom pack = { tag, size - 8 };
7113 int ret = mov_read_pack(c, pb, pack);
7114 if (ret < 0)
7115 return ret;
7116 break;
7117 }
7118 default:
7119 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: 0x%08X\n", tag);
7120 avio_skip(pb, size - 8);
7121 break;
7122 }
7123 6 remaining -= size;
7124 }
7125
7126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7127 av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7128 return AVERROR_INVALIDDATA;
7129 }
7130
7131 3 return 0;
7132 }
7133
7134 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7135 {
7136 AVStream *st;
7137 MOVStreamContext *sc;
7138
7139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7140 return 0;
7141
7142 3 st = c->fc->streams[c->fc->nb_streams - 1];
7143 3 sc = st->priv_data;
7144
7145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7146 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7147 return AVERROR_INVALIDDATA;
7148 }
7149
7150
7151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7152 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7153 if (!sc->stereo3d)
7154 return AVERROR(ENOMEM);
7155 }
7156
7157 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7158 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7159
7160 3 return 0;
7161 }
7162
7163 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7164 {
7165 int ret = 0;
7166 uint8_t *buffer = av_malloc(len + 1);
7167 const char *val;
7168
7169 if (!buffer)
7170 return AVERROR(ENOMEM);
7171 buffer[len] = '\0';
7172
7173 ret = ffio_read_size(pb, buffer, len);
7174 if (ret < 0)
7175 goto out;
7176
7177 /* Check for mandatory keys and values, try to support XML as best-effort */
7178 if (!sc->spherical &&
7179 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7180 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7181 av_stristr(val, "true") &&
7182 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7183 av_stristr(val, "true") &&
7184 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7185 av_stristr(val, "equirectangular")) {
7186 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7187 if (!sc->spherical)
7188 goto out;
7189
7190 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7191
7192 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7193 enum AVStereo3DType mode;
7194
7195 if (av_stristr(buffer, "left-right"))
7196 mode = AV_STEREO3D_SIDEBYSIDE;
7197 else if (av_stristr(buffer, "top-bottom"))
7198 mode = AV_STEREO3D_TOPBOTTOM;
7199 else
7200 mode = AV_STEREO3D_2D;
7201
7202 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7203 if (!sc->stereo3d)
7204 goto out;
7205
7206 sc->stereo3d->type = mode;
7207 }
7208
7209 /* orientation */
7210 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7211 if (val)
7212 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7213 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7214 if (val)
7215 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7216 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7217 if (val)
7218 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7219 }
7220
7221 out:
7222 av_free(buffer);
7223 return ret;
7224 }
7225
7226 69 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7227 {
7228 AVStream *st;
7229 MOVStreamContext *sc;
7230 int64_t ret;
7231 AVUUID uuid;
7232 static const AVUUID uuid_isml_manifest = {
7233 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7234 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7235 };
7236 static const AVUUID uuid_xmp = {
7237 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7238 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7239 };
7240 static const AVUUID uuid_spherical = {
7241 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7242 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7243 };
7244
7245
2/4
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
69 if (atom.size < AV_UUID_LEN || atom.size >= FFMIN(INT_MAX, SIZE_MAX))
7246 return AVERROR_INVALIDDATA;
7247
7248
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 66 times.
69 if (c->fc->nb_streams < 1)
7249 3 return 0;
7250 66 st = c->fc->streams[c->fc->nb_streams - 1];
7251 66 sc = st->priv_data;
7252
7253 66 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
7255 return ret;
7256
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7257 uint8_t *buffer, *ptr;
7258 char *endptr;
7259 size_t len = atom.size - AV_UUID_LEN;
7260
7261 if (len < 4) {
7262 return AVERROR_INVALIDDATA;
7263 }
7264 ret = avio_skip(pb, 4); // zeroes
7265 len -= 4;
7266
7267 buffer = av_mallocz(len + 1);
7268 if (!buffer) {
7269 return AVERROR(ENOMEM);
7270 }
7271 ret = ffio_read_size(pb, buffer, len);
7272 if (ret < 0) {
7273 av_free(buffer);
7274 return ret;
7275 }
7276
7277 ptr = buffer;
7278 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7279 ptr += sizeof("systemBitrate=\"") - 1;
7280 c->bitrates_count++;
7281 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7282 if (!c->bitrates) {
7283 c->bitrates_count = 0;
7284 av_free(buffer);
7285 return AVERROR(ENOMEM);
7286 }
7287 errno = 0;
7288 ret = strtol(ptr, &endptr, 10);
7289 if (ret < 0 || errno || *endptr != '"') {
7290 c->bitrates[c->bitrates_count - 1] = 0;
7291 } else {
7292 c->bitrates[c->bitrates_count - 1] = ret;
7293 }
7294 }
7295
7296 av_free(buffer);
7297
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7298 uint8_t *buffer;
7299 size_t len = atom.size - AV_UUID_LEN;
7300 if (c->export_xmp) {
7301 buffer = av_mallocz(len + 1);
7302 if (!buffer) {
7303 return AVERROR(ENOMEM);
7304 }
7305 ret = ffio_read_size(pb, buffer, len);
7306 if (ret < 0) {
7307 av_free(buffer);
7308 return ret;
7309 }
7310 buffer[len] = '\0';
7311 av_dict_set(&c->fc->metadata, "xmp",
7312 buffer, AV_DICT_DONT_STRDUP_VAL);
7313 } else {
7314 // skip all uuid atom, which makes it fast for long uuid-xmp file
7315 ret = avio_skip(pb, len);
7316 if (ret < 0)
7317 return ret;
7318 }
7319
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7320 size_t len = atom.size - AV_UUID_LEN;
7321 ret = mov_parse_uuid_spherical(sc, pb, len);
7322 if (ret < 0)
7323 return ret;
7324 if (!sc->spherical)
7325 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7326 }
7327
7328 66 return 0;
7329 }
7330
7331 194 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7332 {
7333 int ret;
7334 uint8_t content[16];
7335
7336
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 99 times.
194 if (atom.size < 8)
7337 95 return 0;
7338
7339 99 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (ret < 0)
7341 return ret;
7342
7343
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 56 times.
99 if ( !c->found_moov
7344
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 23 times.
43 && !c->found_mdat
7345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 && !memcmp(content, "Anevia\x1A\x1A", 8)
7346 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7347 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7348 }
7349
7350 99 return 0;
7351 }
7352
7353 35 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7354 {
7355 35 uint32_t format = avio_rl32(pb);
7356 MOVStreamContext *sc;
7357 enum AVCodecID id;
7358 AVStream *st;
7359
7360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (c->fc->nb_streams < 1)
7361 return 0;
7362 35 st = c->fc->streams[c->fc->nb_streams - 1];
7363 35 sc = st->priv_data;
7364
7365
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 32 times.
35 switch (sc->format)
7366 {
7367 3 case MKTAG('e','n','c','v'): // encrypted video
7368 case MKTAG('e','n','c','a'): // encrypted audio
7369 3 id = mov_codec_id(st, format);
7370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7371 st->codecpar->codec_id != id) {
7372 av_log(c->fc, AV_LOG_WARNING,
7373 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7374 (char*)&format, st->codecpar->codec_id);
7375 break;
7376 }
7377
7378 3 st->codecpar->codec_id = id;
7379 3 sc->format = format;
7380 3 break;
7381
7382 32 default:
7383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (format != sc->format) {
7384 av_log(c->fc, AV_LOG_WARNING,
7385 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7386 (char*)&format, (char*)&sc->format);
7387 }
7388 32 break;
7389 }
7390
7391 35 return 0;
7392 }
7393
7394 /**
7395 * Gets the current encryption info and associated current stream context. If
7396 * we are parsing a track fragment, this will return the specific encryption
7397 * info for this fragment; otherwise this will return the global encryption
7398 * info for the current stream.
7399 */
7400 6 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7401 {
7402 MOVFragmentStreamInfo *frag_stream_info;
7403 AVStream *st;
7404 int i;
7405
7406 6 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7407
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (frag_stream_info) {
7408
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 for (i = 0; i < c->fc->nb_streams; i++) {
7409 3 *sc = c->fc->streams[i]->priv_data;
7410
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if ((*sc)->id == frag_stream_info->id) {
7411 3 st = c->fc->streams[i];
7412 3 break;
7413 }
7414 }
7415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (i == c->fc->nb_streams)
7416 return 0;
7417 3 *sc = st->priv_data;
7418
7419
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!frag_stream_info->encryption_index) {
7420 // If this stream isn't encrypted, don't create the index.
7421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!(*sc)->cenc.default_encrypted_sample)
7422 return 0;
7423 1 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!frag_stream_info->encryption_index)
7425 return AVERROR(ENOMEM);
7426 }
7427 3 *encryption_index = frag_stream_info->encryption_index;
7428 3 return 1;
7429 } else {
7430 // No current track fragment, using stream level encryption info.
7431
7432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7433 return 0;
7434 3 st = c->fc->streams[c->fc->nb_streams - 1];
7435 3 *sc = st->priv_data;
7436
7437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!(*sc)->cenc.encryption_index) {
7438 // If this stream isn't encrypted, don't create the index.
7439 if (!(*sc)->cenc.default_encrypted_sample)
7440 return 0;
7441 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7442 if (!(*sc)->cenc.encryption_index)
7443 return AVERROR(ENOMEM);
7444 }
7445
7446 3 *encryption_index = (*sc)->cenc.encryption_index;
7447 3 return 1;
7448 }
7449 }
7450
7451 72 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7452 {
7453 int i, ret;
7454 unsigned int subsample_count;
7455 AVSubsampleEncryptionInfo *subsamples;
7456
7457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!sc->cenc.default_encrypted_sample) {
7458 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7459 return AVERROR_INVALIDDATA;
7460 }
7461
7462
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) {
7463 72 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!*sample)
7465 return AVERROR(ENOMEM);
7466 } else
7467 *sample = NULL;
7468
7469
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (sc->cenc.per_sample_iv_size != 0) {
7470
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) {
7471 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
7472 av_encryption_info_free(*sample);
7473 *sample = NULL;
7474 return ret;
7475 }
7476 }
7477
7478
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (use_subsamples) {
7479 72 subsample_count = avio_rb16(pb);
7480 72 av_free((*sample)->subsamples);
7481 72 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
7482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!(*sample)->subsamples) {
7483 av_encryption_info_free(*sample);
7484 *sample = NULL;
7485 return AVERROR(ENOMEM);
7486 }
7487
7488
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++) {
7489 72 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
7490 72 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
7491 }
7492
7493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (pb->eof_reached) {
7494 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
7495 av_encryption_info_free(*sample);
7496 *sample = NULL;
7497 return AVERROR_INVALIDDATA;
7498 }
7499 72 (*sample)->subsample_count = subsample_count;
7500 }
7501
7502 72 return 0;
7503 }
7504
7505 2 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7506 {
7507 AVEncryptionInfo **encrypted_samples;
7508 MOVEncryptionIndex *encryption_index;
7509 MOVStreamContext *sc;
7510 int use_subsamples, ret;
7511 2 unsigned int sample_count, i, alloc_size = 0;
7512
7513 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7515 return ret;
7516
7517
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7518 // This can happen if we have both saio/saiz and senc atoms.
7519 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
7520 1 return 0;
7521 }
7522
7523 1 avio_r8(pb); /* version */
7524 1 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
7525
7526 1 sample_count = avio_rb32(pb);
7527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7528 return AVERROR(ENOMEM);
7529
7530
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1 times.
49 for (i = 0; i < sample_count; i++) {
7531 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7532 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7533 min_samples * sizeof(*encrypted_samples));
7534
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (encrypted_samples) {
7535 48 encryption_index->encrypted_samples = encrypted_samples;
7536
7537 48 ret = mov_read_sample_encryption_info(
7538 48 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
7539 } else {
7540 ret = AVERROR(ENOMEM);
7541 }
7542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (pb->eof_reached) {
7543 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
7544 if (ret >= 0)
7545 av_encryption_info_free(encryption_index->encrypted_samples[i]);
7546 ret = AVERROR_INVALIDDATA;
7547 }
7548
7549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0) {
7550 for (; i > 0; i--)
7551 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7552 av_freep(&encryption_index->encrypted_samples);
7553 return ret;
7554 }
7555 }
7556 1 encryption_index->nb_encrypted_samples = sample_count;
7557
7558 1 return 0;
7559 }
7560
7561 1 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
7562 {
7563 AVEncryptionInfo **sample, **encrypted_samples;
7564 int64_t prev_pos;
7565 size_t sample_count, sample_info_size, i;
7566 1 int ret = 0;
7567 1 unsigned int alloc_size = 0;
7568
7569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->nb_encrypted_samples)
7570 return 0;
7571 1 sample_count = encryption_index->auxiliary_info_sample_count;
7572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count != 1) {
7573 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
7574 return AVERROR_PATCHWELCOME;
7575 }
7576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7577 return AVERROR(ENOMEM);
7578
7579 1 prev_pos = avio_tell(pb);
7580
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
7581
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]) {
7582 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
7583 goto finish;
7584 }
7585
7586
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++) {
7587 24 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7588 24 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7589 min_samples * sizeof(*encrypted_samples));
7590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!encrypted_samples) {
7591 ret = AVERROR(ENOMEM);
7592 goto finish;
7593 }
7594 24 encryption_index->encrypted_samples = encrypted_samples;
7595
7596 24 sample = &encryption_index->encrypted_samples[i];
7597 48 sample_info_size = encryption_index->auxiliary_info_default_size
7598 24 ? encryption_index->auxiliary_info_default_size
7599
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 : encryption_index->auxiliary_info_sizes[i];
7600
7601 24 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
7602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (ret < 0)
7603 goto finish;
7604 }
7605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7606 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
7607 ret = AVERROR_INVALIDDATA;
7608 } else {
7609 1 encryption_index->nb_encrypted_samples = sample_count;
7610 }
7611
7612 1 finish:
7613 1 avio_seek(pb, prev_pos, SEEK_SET);
7614
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
7615 for (; i > 0; i--) {
7616 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7617 }
7618 av_freep(&encryption_index->encrypted_samples);
7619 }
7620 1 return ret;
7621 }
7622
7623 2 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7624 {
7625 MOVEncryptionIndex *encryption_index;
7626 MOVStreamContext *sc;
7627 int ret;
7628 unsigned int sample_count, aux_info_type, aux_info_param;
7629
7630 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7631
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7632 return ret;
7633
7634
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7635 // This can happen if we have both saio/saiz and senc atoms.
7636 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
7637 1 return 0;
7638 }
7639
7640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_sample_count) {
7641 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
7642 return AVERROR_INVALIDDATA;
7643 }
7644
7645 1 avio_r8(pb); /* version */
7646
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7647 aux_info_type = avio_rb32(pb);
7648 aux_info_param = avio_rb32(pb);
7649 if (sc->cenc.default_encrypted_sample) {
7650 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7651 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
7652 return 0;
7653 }
7654 if (aux_info_param != 0) {
7655 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
7656 return 0;
7657 }
7658 } else {
7659 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7660 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7661 aux_info_type == MKBETAG('c','e','n','s') ||
7662 aux_info_type == MKBETAG('c','b','c','1') ||
7663 aux_info_type == MKBETAG('c','b','c','s')) &&
7664 aux_info_param == 0) {
7665 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
7666 return AVERROR_INVALIDDATA;
7667 } else {
7668 return 0;
7669 }
7670 }
7671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7672 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7673 return 0;
7674 }
7675
7676 1 encryption_index->auxiliary_info_default_size = avio_r8(pb);
7677 1 sample_count = avio_rb32(pb);
7678
7679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_default_size == 0) {
7680 if (sample_count == 0)
7681 return AVERROR_INVALIDDATA;
7682
7683 encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
7684 if (!encryption_index->auxiliary_info_sizes)
7685 return AVERROR(ENOMEM);
7686
7687 ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
7688 if (ret != sample_count) {
7689 av_freep(&encryption_index->auxiliary_info_sizes);
7690
7691 if (ret >= 0)
7692 ret = AVERROR_INVALIDDATA;
7693 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
7694 av_err2str(ret));
7695 return ret;
7696 }
7697 }
7698 1 encryption_index->auxiliary_info_sample_count = sample_count;
7699
7700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7701 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7702 }
7703
7704 1 return 0;
7705 }
7706
7707 2 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7708 {
7709 uint64_t *auxiliary_offsets;
7710 MOVEncryptionIndex *encryption_index;
7711 MOVStreamContext *sc;
7712 int i, ret;
7713 unsigned int version, entry_count, aux_info_type, aux_info_param;
7714 2 unsigned int alloc_size = 0;
7715
7716 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7718 return ret;
7719
7720
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7721 // This can happen if we have both saio/saiz and senc atoms.
7722 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
7723 1 return 0;
7724 }
7725
7726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7727 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
7728 return AVERROR_INVALIDDATA;
7729 }
7730
7731 1 version = avio_r8(pb); /* version */
7732
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7733 aux_info_type = avio_rb32(pb);
7734 aux_info_param = avio_rb32(pb);
7735 if (sc->cenc.default_encrypted_sample) {
7736 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7737 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
7738 return 0;
7739 }
7740 if (aux_info_param != 0) {
7741 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
7742 return 0;
7743 }
7744 } else {
7745 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7746 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7747 aux_info_type == MKBETAG('c','e','n','s') ||
7748 aux_info_type == MKBETAG('c','b','c','1') ||
7749 aux_info_type == MKBETAG('c','b','c','s')) &&
7750 aux_info_param == 0) {
7751 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
7752 return AVERROR_INVALIDDATA;
7753 } else {
7754 return 0;
7755 }
7756 }
7757
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7758 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7759 return 0;
7760 }
7761
7762 1 entry_count = avio_rb32(pb);
7763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
7764 return AVERROR(ENOMEM);
7765
7766
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++) {
7767
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);
7768 1 auxiliary_offsets = av_fast_realloc(
7769 1 encryption_index->auxiliary_offsets, &alloc_size,
7770 min_offsets * sizeof(*auxiliary_offsets));
7771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!auxiliary_offsets) {
7772 av_freep(&encryption_index->auxiliary_offsets);
7773 return AVERROR(ENOMEM);
7774 }
7775 1 encryption_index->auxiliary_offsets = auxiliary_offsets;
7776
7777
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (version == 0) {
7778 1 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
7779 } else {
7780 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
7781 }
7782
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (c->frag_index.current >= 0) {
7783 1 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
7784 }
7785 }
7786
7787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7788 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
7789 av_freep(&encryption_index->auxiliary_offsets);
7790 return AVERROR_INVALIDDATA;
7791 }
7792
7793 1 encryption_index->auxiliary_offsets_count = entry_count;
7794
7795
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (encryption_index->auxiliary_info_sample_count) {
7796 1 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7797 }
7798
7799 return 0;
7800 }
7801
7802 2 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7803 {
7804 AVEncryptionInitInfo *info, *old_init_info;
7805 uint8_t **key_ids;
7806 AVStream *st;
7807 const AVPacketSideData *old_side_data;
7808 uint8_t *side_data, *extra_data;
7809 size_t side_data_size;
7810 2 int ret = 0;
7811 2 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
7812
7813
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
7814 return 0;
7815 2 st = c->fc->streams[c->fc->nb_streams-1];
7816
7817 2 version = avio_r8(pb); /* version */
7818 2 avio_rb24(pb); /* flags */
7819
7820 2 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
7821 /* key_id_size */ 16, /* data_size */ 0);
7822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info)
7823 return AVERROR(ENOMEM);
7824
7825
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
7826 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
7827 goto finish;
7828 }
7829
7830
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version > 0) {
7831 2 kid_count = avio_rb32(pb);
7832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
7833 ret = AVERROR(ENOMEM);
7834 goto finish;
7835 }
7836
7837
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++) {
7838 2 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
7839 2 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
7840 min_kid_count * sizeof(*key_ids));
7841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!key_ids) {
7842 ret = AVERROR(ENOMEM);
7843 goto finish;
7844 }
7845 2 info->key_ids = key_ids;
7846
7847 2 info->key_ids[i] = av_mallocz(16);
7848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info->key_ids[i]) {
7849 ret = AVERROR(ENOMEM);
7850 goto finish;
7851 }
7852 2 info->num_key_ids = i + 1;
7853
7854
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
7855 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
7856 goto finish;
7857 }
7858 }
7859
7860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
7861 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
7862 ret = AVERROR_INVALIDDATA;
7863 goto finish;
7864 }
7865 }
7866
7867 2 extra_data_size = avio_rb32(pb);
7868 2 extra_data = av_malloc(extra_data_size);
7869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!extra_data) {
7870 ret = AVERROR(ENOMEM);
7871 goto finish;
7872 }
7873 2 ret = avio_read(pb, extra_data, extra_data_size);
7874
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != extra_data_size) {
7875 av_free(extra_data);
7876
7877 if (ret >= 0)
7878 ret = AVERROR_INVALIDDATA;
7879 goto finish;
7880 }
7881
7882 2 av_freep(&info->data); // malloc(0) may still allocate something.
7883 2 info->data = extra_data;
7884 2 info->data_size = extra_data_size;
7885
7886 // If there is existing initialization data, append to the list.
7887 2 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
7888 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
7889
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (old_side_data) {
7890 old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
7891 if (old_init_info) {
7892 // Append to the end of the list.
7893 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
7894 if (!cur->next) {
7895 cur->next = info;
7896 break;
7897 }
7898 }
7899 info = old_init_info;
7900 } else {
7901 // Assume existing side-data will be valid, so the only error we could get is OOM.
7902 ret = AVERROR(ENOMEM);
7903 goto finish;
7904 }
7905 }
7906
7907 2 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
7908
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!side_data) {
7909 ret = AVERROR(ENOMEM);
7910 goto finish;
7911 }
7912
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
7913 2 &st->codecpar->nb_coded_side_data,
7914 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
7915 side_data, side_data_size, 0))
7916 av_free(side_data);
7917
7918 2 finish:
7919 2 av_encryption_init_info_free(info);
7920 2 return ret;
7921 }
7922
7923 3 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7924 {
7925 AVStream *st;
7926 MOVStreamContext *sc;
7927
7928
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7929 return 0;
7930 3 st = c->fc->streams[c->fc->nb_streams-1];
7931 3 sc = st->priv_data;
7932
7933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7934 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
7935 return AVERROR_PATCHWELCOME;
7936 }
7937
7938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8)
7939 return AVERROR_INVALIDDATA;
7940
7941 3 avio_rb32(pb); /* version and flags */
7942
7943
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->cenc.default_encrypted_sample) {
7944 3 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7946 return AVERROR(ENOMEM);
7947 }
7948 }
7949
7950 3 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
7951 3 return 0;
7952 }
7953
7954 3 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7955 {
7956 AVStream *st;
7957 MOVStreamContext *sc;
7958 unsigned int version, pattern, is_protected, iv_size;
7959
7960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7961 return 0;
7962 3 st = c->fc->streams[c->fc->nb_streams-1];
7963 3 sc = st->priv_data;
7964
7965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7966 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
7967 return AVERROR_PATCHWELCOME;
7968 }
7969
7970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7971 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7972 if (!sc->cenc.default_encrypted_sample) {
7973 return AVERROR(ENOMEM);
7974 }
7975 }
7976
7977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 20)
7978 return AVERROR_INVALIDDATA;
7979
7980 3 version = avio_r8(pb); /* version */
7981 3 avio_rb24(pb); /* flags */
7982
7983 3 avio_r8(pb); /* reserved */
7984 3 pattern = avio_r8(pb);
7985
7986
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (version > 0) {
7987 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
7988 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
7989 }
7990
7991 3 is_protected = avio_r8(pb);
7992
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) {
7993 // The whole stream should be by-default encrypted.
7994 3 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
7995
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.encryption_index)
7996 return AVERROR(ENOMEM);
7997 }
7998 3 sc->cenc.per_sample_iv_size = avio_r8(pb);
7999
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 &&
8000 sc->cenc.per_sample_iv_size != 16) {
8001 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
8002 return AVERROR_INVALIDDATA;
8003 }
8004
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) {
8005 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
8006 return AVERROR_INVALIDDATA;
8007 }
8008
8009
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) {
8010 1 iv_size = avio_r8(pb);
8011
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) {
8012 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
8013 return AVERROR_INVALIDDATA;
8014 }
8015
8016
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) {
8017 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
8018 return AVERROR_INVALIDDATA;
8019 }
8020 }
8021
8022 3 return 0;
8023 }
8024
8025 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8026 {
8027 AVStream *st;
8028 int last, type, size, ret;
8029 uint8_t buf[4];
8030
8031 if (c->fc->nb_streams < 1)
8032 return 0;
8033 st = c->fc->streams[c->fc->nb_streams-1];
8034
8035 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
8036 return AVERROR_INVALIDDATA;
8037
8038 /* Check FlacSpecificBox version. */
8039 if (avio_r8(pb) != 0)
8040 return AVERROR_INVALIDDATA;
8041
8042 avio_rb24(pb); /* Flags */
8043
8044 if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
8045 av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
8046 return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
8047 }
8048 flac_parse_block_header(buf, &last, &type, &size);
8049
8050 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
8051 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
8052 return AVERROR_INVALIDDATA;
8053 }
8054
8055 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
8056 if (ret < 0)
8057 return ret;
8058
8059 if (!last)
8060 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
8061
8062 return 0;
8063 }
8064
8065 146 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8066 {
8067 int i, ret;
8068 int bytes_of_protected_data;
8069
8070
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 143 times.
146 if (!sc->cenc.aes_ctr) {
8071 /* initialize the cipher */
8072 3 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.aes_ctr) {
8074 return AVERROR(ENOMEM);
8075 }
8076
8077 3 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
8078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8079 return ret;
8080 }
8081 }
8082
8083 146 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8084
8085
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!sample->subsample_count) {
8086 /* decrypt the whole packet */
8087 48 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8088 48 return 0;
8089 }
8090
8091
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 98 times.
196 for (i = 0; i < sample->subsample_count; i++) {
8092
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) {
8093 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8094 return AVERROR_INVALIDDATA;
8095 }
8096
8097 /* skip the clear bytes */
8098 98 input += sample->subsamples[i].bytes_of_clear_data;
8099 98 size -= sample->subsamples[i].bytes_of_clear_data;
8100
8101 /* decrypt the encrypted bytes */
8102
8103 98 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
8104 98 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
8105
8106 98 input += bytes_of_protected_data;
8107 98 size -= bytes_of_protected_data;
8108 }
8109
8110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (size > 0) {
8111 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8112 return AVERROR_INVALIDDATA;
8113 }
8114
8115 98 return 0;
8116 }
8117
8118 static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8119 {
8120 int i, ret;
8121 int num_of_encrypted_blocks;
8122 uint8_t iv[16];
8123
8124 if (!sc->cenc.aes_ctx) {
8125 /* initialize the cipher */
8126 sc->cenc.aes_ctx = av_aes_alloc();
8127 if (!sc->cenc.aes_ctx) {
8128 return AVERROR(ENOMEM);
8129 }
8130
8131 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8132 if (ret < 0) {
8133 return ret;
8134 }
8135 }
8136
8137 memcpy(iv, sample->iv, 16);
8138
8139 /* whole-block full sample encryption */
8140 if (!sample->subsample_count) {
8141 /* decrypt the whole packet */
8142 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8143 return 0;
8144 }
8145
8146 for (i = 0; i < sample->subsample_count; i++) {
8147 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8148 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8149 return AVERROR_INVALIDDATA;
8150 }
8151
8152 if (sample->subsamples[i].bytes_of_protected_data % 16) {
8153 av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8154 return AVERROR_INVALIDDATA;
8155 }
8156
8157 /* skip the clear bytes */
8158 input += sample->subsamples[i].bytes_of_clear_data;
8159 size -= sample->subsamples[i].bytes_of_clear_data;
8160
8161 /* decrypt the encrypted bytes */
8162 num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8163 if (num_of_encrypted_blocks > 0) {
8164 av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8165 }
8166 input += sample->subsamples[i].bytes_of_protected_data;
8167 size -= sample->subsamples[i].bytes_of_protected_data;
8168 }
8169
8170 if (size > 0) {
8171 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8172 return AVERROR_INVALIDDATA;
8173 }
8174
8175 return 0;
8176 }
8177
8178 static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8179 {
8180 int i, ret, rem_bytes;
8181 uint8_t *data;
8182
8183 if (!sc->cenc.aes_ctr) {
8184 /* initialize the cipher */
8185 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8186 if (!sc->cenc.aes_ctr) {
8187 return AVERROR(ENOMEM);
8188 }
8189
8190 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
8191 if (ret < 0) {
8192 return ret;
8193 }
8194 }
8195
8196 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8197
8198 /* whole-block full sample encryption */
8199 if (!sample->subsample_count) {
8200 /* decrypt the whole packet */
8201 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8202 return 0;
8203 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8204 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8205 return AVERROR_INVALIDDATA;
8206 }
8207
8208 for (i = 0; i < sample->subsample_count; i++) {
8209 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8210 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8211 return AVERROR_INVALIDDATA;
8212 }
8213
8214 /* skip the clear bytes */
8215 input += sample->subsamples[i].bytes_of_clear_data;
8216 size -= sample->subsamples[i].bytes_of_clear_data;
8217
8218 /* decrypt the encrypted bytes */
8219 data = input;
8220 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8221 while (rem_bytes > 0) {
8222 if (rem_bytes < 16*sample->crypt_byte_block) {
8223 break;
8224 }
8225 av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8226 data += 16*sample->crypt_byte_block;
8227 rem_bytes -= 16*sample->crypt_byte_block;
8228 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8229 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8230 }
8231 input += sample->subsamples[i].bytes_of_protected_data;
8232 size -= sample->subsamples[i].bytes_of_protected_data;
8233 }
8234
8235 if (size > 0) {
8236 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8237 return AVERROR_INVALIDDATA;
8238 }
8239
8240 return 0;
8241 }
8242
8243 static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8244 {
8245 int i, ret, rem_bytes;
8246 uint8_t iv[16];
8247 uint8_t *data;
8248
8249 if (!sc->cenc.aes_ctx) {
8250 /* initialize the cipher */
8251 sc->cenc.aes_ctx = av_aes_alloc();
8252 if (!sc->cenc.aes_ctx) {
8253 return AVERROR(ENOMEM);
8254 }
8255
8256 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8257 if (ret < 0) {
8258 return ret;
8259 }
8260 }
8261
8262 /* whole-block full sample encryption */
8263 if (!sample->subsample_count) {
8264 /* decrypt the whole packet */
8265 memcpy(iv, sample->iv, 16);
8266 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8267 return 0;
8268 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8269 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8270 return AVERROR_INVALIDDATA;
8271 }
8272
8273 for (i = 0; i < sample->subsample_count; i++) {
8274 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8275 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8276 return AVERROR_INVALIDDATA;
8277 }
8278
8279 /* skip the clear bytes */
8280 input += sample->subsamples[i].bytes_of_clear_data;
8281 size -= sample->subsamples[i].bytes_of_clear_data;
8282
8283 /* decrypt the encrypted bytes */
8284 memcpy(iv, sample->iv, 16);
8285 data = input;
8286 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8287 while (rem_bytes > 0) {
8288 if (rem_bytes < 16*sample->crypt_byte_block) {
8289 break;
8290 }
8291 av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8292 data += 16*sample->crypt_byte_block;
8293 rem_bytes -= 16*sample->crypt_byte_block;
8294 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8295 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8296 }
8297 input += sample->subsamples[i].bytes_of_protected_data;
8298 size -= sample->subsamples[i].bytes_of_protected_data;
8299 }
8300
8301 if (size > 0) {
8302 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8303 return AVERROR_INVALIDDATA;
8304 }
8305
8306 return 0;
8307 }
8308
8309 146 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8310 {
8311
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) {
8312 146 return cenc_scheme_decrypt(c, sc, sample, input, size);
8313 } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8314 return cbc1_scheme_decrypt(c, sc, sample, input, size);
8315 } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8316 return cens_scheme_decrypt(c, sc, sample, input, size);
8317 } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8318 return cbcs_scheme_decrypt(c, sc, sample, input, size);
8319 } else {
8320 av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8321 return AVERROR_INVALIDDATA;
8322 }
8323 }
8324
8325 96806 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8326 {
8327 96806 int current = frag_index->current;
8328
8329
2/2
✓ Branch 0 taken 95965 times.
✓ Branch 1 taken 841 times.
96806 if (!frag_index->nb_items)
8330 95965 return NULL;
8331
8332 // Check frag_index->current is the right one for pkt. It can out of sync.
8333
2/4
✓ Branch 0 taken 841 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 841 times.
✗ Branch 3 not taken.
841 if (current >= 0 && current < frag_index->nb_items) {
8334
2/2
✓ Branch 0 taken 815 times.
✓ Branch 1 taken 26 times.
841 if (frag_index->item[current].moof_offset < pkt->pos &&
8335
2/2
✓ Branch 0 taken 545 times.
✓ Branch 1 taken 270 times.
815 (current + 1 == frag_index->nb_items ||
8336
2/2
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 75 times.
545 frag_index->item[current + 1].moof_offset > pkt->pos))
8337 740 return get_frag_stream_info(frag_index, current, id);
8338 }
8339
8340
8341
2/2
✓ Branch 0 taken 4553 times.
✓ Branch 1 taken 8 times.
4561 for (int i = 0; i < frag_index->nb_items; i++) {
8342
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 4460 times.
4553 if (frag_index->item[i].moof_offset > pkt->pos)
8343 93 break;
8344 4460 current = i;
8345 }
8346 101 frag_index->current = current;
8347 101 return get_frag_stream_info(frag_index, current, id);
8348 }
8349
8350 96806 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8351 {
8352 MOVFragmentStreamInfo *frag_stream_info;
8353 MOVEncryptionIndex *encryption_index;
8354 AVEncryptionInfo *encrypted_sample;
8355 int encrypted_index, ret;
8356
8357 96806 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8358 96806 encrypted_index = current_index;
8359 96806 encryption_index = NULL;
8360
2/2
✓ Branch 0 taken 841 times.
✓ Branch 1 taken 95965 times.
96806 if (frag_stream_info) {
8361 // Note this only supports encryption info in the first sample descriptor.
8362
2/2
✓ Branch 0 taken 817 times.
✓ Branch 1 taken 24 times.
841 if (frag_stream_info->stsd_id == 1) {
8363
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 793 times.
817 if (frag_stream_info->encryption_index) {
8364 24 encrypted_index = current_index - frag_stream_info->index_base;
8365 24 encryption_index = frag_stream_info->encryption_index;
8366 } else {
8367 793 encryption_index = sc->cenc.encryption_index;
8368 }
8369 }
8370 } else {
8371 95965 encryption_index = sc->cenc.encryption_index;
8372 }
8373
8374
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 96660 times.
96806 if (encryption_index) {
8375
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_info_sample_count &&
8376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8377 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8378 return AVERROR_INVALIDDATA;
8379 }
8380
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_offsets_count &&
8381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8382 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8383 return AVERROR_INVALIDDATA;
8384 }
8385
8386 146 encrypted_sample = NULL;
8387
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!encryption_index->nb_encrypted_samples) {
8388 // Full-sample encryption with default settings.
8389 48 encrypted_sample = sc->cenc.default_encrypted_sample;
8390
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) {
8391 // Per-sample setting override.
8392 98 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (!encrypted_sample) {
8394 encrypted_sample = sc->cenc.default_encrypted_sample;
8395 }
8396 }
8397
8398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (!encrypted_sample) {
8399 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8400 return AVERROR_INVALIDDATA;
8401 }
8402
8403
1/2
✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
146 if (mov->decryption_key) {
8404 146 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
8405 } else {
8406 size_t size;
8407 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
8408 if (!side_data)
8409 return AVERROR(ENOMEM);
8410 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
8411 if (ret < 0)
8412 av_free(side_data);
8413 return ret;
8414 }
8415 }
8416
8417 96660 return 0;
8418 }
8419
8420 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8421 {
8422 const int OPUS_SEEK_PREROLL_MS = 80;
8423 int ret;
8424 AVStream *st;
8425 size_t size;
8426 uint16_t pre_skip;
8427
8428 if (c->fc->nb_streams < 1)
8429 return 0;
8430 st = c->fc->streams[c->fc->nb_streams-1];
8431
8432 if ((uint64_t)atom.size > (1<<30) || atom.size < 11)
8433 return AVERROR_INVALIDDATA;
8434
8435 /* Check OpusSpecificBox version. */
8436 if (avio_r8(pb) != 0) {
8437 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
8438 return AVERROR_INVALIDDATA;
8439 }
8440
8441 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
8442 size = atom.size + 8;
8443
8444 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
8445 return ret;
8446
8447 AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
8448 AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
8449 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
8450 avio_read(pb, st->codecpar->extradata + 9, size - 9);
8451
8452 /* OpusSpecificBox is stored in big-endian, but OpusHead is
8453 little-endian; aside from the preceding magic and version they're
8454 otherwise currently identical. Data after output gain at offset 16
8455 doesn't need to be bytewapped. */
8456 pre_skip = AV_RB16A(st->codecpar->extradata + 10);
8457 AV_WL16A(st->codecpar->extradata + 10, pre_skip);
8458 AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
8459 AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
8460
8461 st->codecpar->initial_padding = pre_skip;
8462 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
8463 (AVRational){1, 1000},
8464 (AVRational){1, 48000});
8465
8466 return 0;
8467 }
8468
8469 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8470 {
8471 AVStream *st;
8472 unsigned format_info;
8473 int channel_assignment, channel_assignment1, channel_assignment2;
8474 int ratebits;
8475 uint64_t chmask;
8476
8477 if (c->fc->nb_streams < 1)
8478 return 0;
8479 st = c->fc->streams[c->fc->nb_streams-1];
8480
8481 if (atom.size < 10)
8482 return AVERROR_INVALIDDATA;
8483
8484 format_info = avio_rb32(pb);
8485
8486 ratebits = (format_info >> 28) & 0xF;
8487 channel_assignment1 = (format_info >> 15) & 0x1F;
8488 channel_assignment2 = format_info & 0x1FFF;
8489 if (channel_assignment2)
8490 channel_assignment = channel_assignment2;
8491 else
8492 channel_assignment = channel_assignment1;
8493
8494 st->codecpar->frame_size = 40 << (ratebits & 0x7);
8495 st->codecpar->sample_rate = mlp_samplerate(ratebits);
8496
8497 av_channel_layout_uninit(&st->codecpar->ch_layout);
8498 chmask = truehd_layout(channel_assignment);
8499 av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
8500
8501 return 0;
8502 }
8503
8504 4 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8505 {
8506 AVStream *st;
8507 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
8508 int ret;
8509 4 int64_t read_size = atom.size;
8510
8511
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8512 return 0;
8513 4 st = c->fc->streams[c->fc->nb_streams-1];
8514
8515 // At most 24 bytes
8516 4 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
8517
8518
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
8519 return ret;
8520
8521 4 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
8522 }
8523
8524 3 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8525 {
8526 AVStream *st;
8527 uint8_t *buf;
8528 int ret, old_size, num_arrays;
8529
8530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
8531 return 0;
8532 3 st = c->fc->streams[c->fc->nb_streams-1];
8533
8534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata_size)
8535 // TODO: handle lhvC when present before hvcC
8536 return 0;
8537
8538
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)
8539 return AVERROR_INVALIDDATA;
8540
8541 3 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
8542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!buf)
8543 return AVERROR(ENOMEM);
8544 3 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8545
8546 3 ret = ffio_read_size(pb, buf, atom.size);
8547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8548 av_free(buf);
8549 av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
8550 return 0;
8551 }
8552
8553 3 num_arrays = buf[5];
8554 3 old_size = st->codecpar->extradata_size;
8555 3 atom.size -= 8 /* account for mov_realloc_extradata offsetting */
8556 + 6 /* lhvC bytes before the arrays*/;
8557
8558 3 ret = mov_realloc_extradata(st->codecpar, atom);
8559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8560 av_free(buf);
8561 return ret;
8562 }
8563
8564 3 st->codecpar->extradata[22] += num_arrays;
8565 3 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
8566
8567 3 st->disposition |= AV_DISPOSITION_MULTILAYER;
8568
8569 3 av_free(buf);
8570 3 return 0;
8571 }
8572
8573 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8574 {
8575 4 AVFormatContext *ctx = c->fc;
8576 4 AVStream *st = NULL;
8577 AVBPrint scheme_buf, value_buf;
8578 4 int64_t scheme_str_len = 0, value_str_len = 0;
8579 4 int version, flags, ret = AVERROR_BUG;
8580 4 int64_t size = atom.size;
8581
8582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
8583 // 4 bytes for version + flags, 2x 1 byte for null
8584 return AVERROR_INVALIDDATA;
8585
8586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8587 return 0;
8588 4 st = c->fc->streams[c->fc->nb_streams-1];
8589
8590 4 version = avio_r8(pb);
8591 4 flags = avio_rb24(pb);
8592 4 size -= 4;
8593
8594
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) {
8595 av_log(ctx, AV_LOG_ERROR,
8596 "Unsupported 'kind' box with version %d, flags: %x",
8597 version, flags);
8598 return AVERROR_INVALIDDATA;
8599 }
8600
8601 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8602 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8603
8604
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,
8605 size)) < 0) {
8606 ret = scheme_str_len;
8607 goto cleanup;
8608 }
8609
8610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
8611 // we need to have another string, even if nullptr.
8612 // we check with + 1 since we expect that if size was not hit,
8613 // an additional null was read.
8614 ret = AVERROR_INVALIDDATA;
8615 goto cleanup;
8616 }
8617
8618 4 size -= scheme_str_len + 1;
8619
8620
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,
8621 size)) < 0) {
8622 ret = value_str_len;
8623 goto cleanup;
8624 }
8625
8626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
8627 // in case of no trailing null, box is not valid.
8628 ret = AVERROR_INVALIDDATA;
8629 goto cleanup;
8630 }
8631
8632 4 av_log(ctx, AV_LOG_TRACE,
8633 "%s stream %d KindBox(scheme: %s, value: %s)\n",
8634 4 av_get_media_type_string(st->codecpar->codec_type),
8635 st->index,
8636 scheme_buf.str, value_buf.str);
8637
8638
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++) {
8639 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
8640
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
8641 continue;
8642
8643
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
8644 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
8645
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
8646 16 continue;
8647
8648 4 st->disposition |= value_map.disposition;
8649 }
8650 }
8651
8652 4 ret = 0;
8653
8654 4 cleanup:
8655
8656 4 av_bprint_finalize(&scheme_buf, NULL);
8657 4 av_bprint_finalize(&value_buf, NULL);
8658
8659 4 return ret;
8660 }
8661
8662 static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8663 {
8664 AVStream *st;
8665 AVChannelLayout ch_layout = { 0 };
8666 int ret, i, version, type;
8667 int ambisonic_order, channel_order, normalization, channel_count;
8668 int ambi_channels, non_diegetic_channels;
8669
8670 if (c->fc->nb_streams < 1)
8671 return 0;
8672
8673 st = c->fc->streams[c->fc->nb_streams - 1];
8674
8675 if (atom.size < 16) {
8676 av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
8677 return AVERROR_INVALIDDATA;
8678 }
8679
8680 version = avio_r8(pb);
8681 if (version) {
8682 av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
8683 return 0;
8684 }
8685
8686 type = avio_r8(pb);
8687 if (type & 0x7f) {
8688 av_log(c->fc, AV_LOG_WARNING,
8689 "Unsupported ambisonic type %d\n", type & 0x7f);
8690 return 0;
8691 }
8692 non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
8693
8694 ambisonic_order = avio_rb32(pb);
8695
8696 channel_order = avio_r8(pb);
8697 if (channel_order) {
8698 av_log(c->fc, AV_LOG_WARNING,
8699 "Unsupported channel_order %d\n", channel_order);
8700 return 0;
8701 }
8702
8703 normalization = avio_r8(pb);
8704 if (normalization) {
8705 av_log(c->fc, AV_LOG_WARNING,
8706 "Unsupported normalization %d\n", normalization);
8707 return 0;
8708 }
8709
8710 channel_count = avio_rb32(pb);
8711 if (ambisonic_order < 0 || ambisonic_order > 31 ||
8712 channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
8713 non_diegetic_channels)) {
8714 av_log(c->fc, AV_LOG_ERROR,
8715 "Invalid number of channels (%d / %d)\n",
8716 channel_count, ambisonic_order);
8717 return 0;
8718 }
8719 ambi_channels = channel_count - non_diegetic_channels;
8720
8721 ret = av_channel_layout_custom_init(&ch_layout, channel_count);
8722 if (ret < 0)
8723 return 0;
8724
8725 for (i = 0; i < channel_count; i++) {
8726 unsigned channel = avio_rb32(pb);
8727
8728 if (channel >= channel_count) {
8729 av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
8730 channel, ambisonic_order);
8731 av_channel_layout_uninit(&ch_layout);
8732 return 0;
8733 }
8734 if (channel >= ambi_channels)
8735 ch_layout.u.map[i].id = channel - ambi_channels;
8736 else
8737 ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
8738 }
8739
8740 ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
8741 if (ret < 0) {
8742 av_channel_layout_uninit(&ch_layout);
8743 return 0;
8744 }
8745
8746 av_channel_layout_uninit(&st->codecpar->ch_layout);
8747 st->codecpar->ch_layout = ch_layout;
8748
8749 return 0;
8750 }
8751
8752 static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8753 {
8754 AVStream *st;
8755 int version;
8756
8757 if (c->fc->nb_streams < 1)
8758 return 0;
8759
8760 st = c->fc->streams[c->fc->nb_streams - 1];
8761
8762 if (atom.size < 5) {
8763 av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
8764 return AVERROR_INVALIDDATA;
8765 }
8766
8767 version = avio_r8(pb);
8768 if (version) {
8769 av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
8770 return 0;
8771 }
8772
8773 st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
8774
8775 return 0;
8776 }
8777
8778 126 static int rb_size(AVIOContext *pb, int64_t *value, int size)
8779 {
8780
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 115 times.
126 if (size == 0)
8781 11 *value = 0;
8782
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 115 times.
115 else if (size == 1)
8783 *value = avio_r8(pb);
8784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 115 times.
115 else if (size == 2)
8785 *value = avio_rb16(pb);
8786
1/2
✓ Branch 0 taken 115 times.
✗ Branch 1 not taken.
115 else if (size == 4)
8787 115 *value = avio_rb32(pb);
8788 else if (size == 8) {
8789 *value = avio_rb64(pb);
8790 if (*value < 0)
8791 return -1;
8792 } else
8793 return -1;
8794 126 return size;
8795 }
8796
8797 15 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8798 {
8799 15 avio_rb32(pb); // version & flags.
8800 15 c->primary_item_id = avio_rb16(pb);
8801 15 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
8802 15 return atom.size;
8803 }
8804
8805 6 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8806 {
8807 6 c->idat_offset = avio_tell(pb);
8808 6 return 0;
8809 }
8810
8811 15 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8812 {
8813 HEIFItem **heif_item;
8814 int version, offset_size, length_size, base_offset_size, index_size;
8815 int item_count, extent_count;
8816 int64_t base_offset, extent_offset, extent_length;
8817 uint8_t value;
8818
8819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (c->found_iloc) {
8820 av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
8821 return 0;
8822 }
8823
8824 15 version = avio_r8(pb);
8825 15 avio_rb24(pb); // flags.
8826
8827 15 value = avio_r8(pb);
8828 15 offset_size = (value >> 4) & 0xF;
8829 15 length_size = value & 0xF;
8830 15 value = avio_r8(pb);
8831 15 base_offset_size = (value >> 4) & 0xF;
8832
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7 times.
15 index_size = !version ? 0 : (value & 0xF);
8833
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (index_size) {
8834 avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
8835 return AVERROR_PATCHWELCOME;
8836 }
8837
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8838
8839 15 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
8840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!heif_item)
8841 return AVERROR(ENOMEM);
8842 15 c->heif_item = heif_item;
8843
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (item_count > c->nb_heif_item)
8844 15 memset(&c->heif_item[c->nb_heif_item], 0,
8845 15 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
8846 15 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
8847
8848 15 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
8849
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 15 times.
57 for (int i = 0; i < item_count; i++) {
8850 42 HEIFItem *item = NULL;
8851
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8852
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
8853
8854
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
42 if (avio_feof(pb))
8855 return AVERROR_INVALIDDATA;
8856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (offset_type > 1) {
8857 avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
8858 return AVERROR_PATCHWELCOME;
8859 }
8860
8861 42 avio_rb16(pb); // data_reference_index.
8862
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
42 if (rb_size(pb, &base_offset, base_offset_size) < 0)
8863 return AVERROR_INVALIDDATA;
8864 42 extent_count = avio_rb16(pb);
8865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (extent_count > 1) {
8866 // For still AVIF images, we only support one extent item.
8867 avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
8868 return AVERROR_PATCHWELCOME;
8869 }
8870
8871
2/4
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 42 times.
✗ Branch 4 not taken.
84 if (rb_size(pb, &extent_offset, offset_size) < 0 ||
8872 42 rb_size(pb, &extent_length, length_size) < 0 ||
8873
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 base_offset > INT64_MAX - extent_offset)
8874 return AVERROR_INVALIDDATA;
8875
8876
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 for (int j = 0; j < c->nb_heif_item; j++) {
8877 95 item = c->heif_item[j];
8878
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 53 times.
95 if (!item)
8879 42 item = c->heif_item[j] = av_mallocz(sizeof(*item));
8880
1/2
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
53 else if (item->item_id != item_id)
8881 53 continue;
8882 42 break;
8883 }
8884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!item)
8885 return AVERROR(ENOMEM);
8886
8887 42 item->item_id = item_id;
8888
8889
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 36 times.
42 if (offset_type == 1)
8890 6 item->is_idat_relative = 1;
8891 42 item->extent_length = extent_length;
8892 42 item->extent_offset = base_offset + extent_offset;
8893 42 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, item->item_id %d, offset_type %d, "
8894 "extent_offset %"PRId64", extent_length %"PRId64"\n",
8895 i, item->item_id, offset_type, item->extent_offset, item->extent_length);
8896 }
8897
8898 15 c->found_iloc = 1;
8899 15 return atom.size;
8900 }
8901
8902 42 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8903 {
8904 42 HEIFItem *item = NULL;
8905 AVBPrint item_name;
8906 42 int64_t size = atom.size;
8907 uint32_t item_type;
8908 int item_id;
8909 int version, ret;
8910
8911 42 version = avio_r8(pb);
8912 42 avio_rb24(pb); // flags.
8913 42 size -= 4;
8914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (size < 0)
8915 return AVERROR_INVALIDDATA;
8916
8917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (version < 2) {
8918 avpriv_report_missing_feature(c->fc, "infe version < 2");
8919 avio_skip(pb, size);
8920 return 1;
8921 }
8922
8923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
8924 42 avio_rb16(pb); // item_protection_index
8925 42 item_type = avio_rl32(pb);
8926 42 size -= 8;
8927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (size < 1)
8928 return AVERROR_INVALIDDATA;
8929
8930 42 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
8931 42 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
8932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0) {
8933 av_bprint_finalize(&item_name, NULL);
8934 return ret;
8935 }
8936
8937 42 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
8938 42 item_id, av_fourcc2str(item_type), item_name.str);
8939
8940 42 size -= ret + 1;
8941
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 40 times.
42 if (size > 0)
8942 2 avio_skip(pb, size);
8943
8944
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 for (int i = 0; i < c->nb_heif_item; i++) {
8945 95 item = c->heif_item[i];
8946
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
95 if (!item)
8947 item = c->heif_item[i] = av_mallocz(sizeof(*item));
8948
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 42 times.
95 else if (item->item_id != item_id)
8949 53 continue;
8950 42 break;
8951 }
8952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!item) {
8953 av_bprint_finalize(&item_name, NULL);
8954 return AVERROR(ENOMEM);
8955 }
8956
8957 42 av_freep(&item->name);
8958
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 1 times.
42 av_bprint_finalize(&item_name, ret ? &item->name : NULL);
8959 42 item->item_id = item_id;
8960 42 item->type = item_type;
8961
8962
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 11 times.
42 switch (item_type) {
8963 31 case MKTAG('a','v','0','1'):
8964 case MKTAG('j','p','e','g'):
8965 case MKTAG('h','v','c','1'):
8966 31 ret = heif_add_stream(c, item);
8967
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (ret < 0)
8968 return ret;
8969 31 break;
8970 }
8971
8972 42 return 0;
8973 }
8974
8975 15 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8976 {
8977 HEIFItem **heif_item;
8978 int entry_count;
8979 15 int version, got_stream = 0, ret, i;
8980
8981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (c->found_iinf) {
8982 av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
8983 return 0;
8984 }
8985
8986 15 version = avio_r8(pb);
8987 15 avio_rb24(pb); // flags.
8988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
8989
8990 15 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
8991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!heif_item)
8992 return AVERROR(ENOMEM);
8993 15 c->heif_item = heif_item;
8994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (entry_count > c->nb_heif_item)
8995 memset(&c->heif_item[c->nb_heif_item], 0,
8996 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
8997 15 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
8998
8999
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 15 times.
57 for (i = 0; i < entry_count; i++) {
9000 MOVAtom infe;
9001
9002 42 infe.size = avio_rb32(pb) - 8;
9003 42 infe.type = avio_rl32(pb);
9004
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
42 if (avio_feof(pb)) {
9005 ret = AVERROR_INVALIDDATA;
9006 goto fail;
9007 }
9008 42 ret = mov_read_infe(c, pb, infe);
9009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0)
9010 goto fail;
9011
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 if (!ret)
9012 42 got_stream = 1;
9013 }
9014
9015 15 c->found_iinf = got_stream;
9016 15 return 0;
9017 fail:
9018 for (; i >= 0; i--) {
9019 HEIFItem *item = c->heif_item[i];
9020
9021 if (!item)
9022 continue;
9023
9024 av_freep(&item->name);
9025 }
9026 return ret;
9027 }
9028
9029 6 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
9030 {
9031 6 HEIFItem *item = NULL;
9032 HEIFGrid *grid;
9033 int entries, i;
9034
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9035
9036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 for (int i = 0; i < c->nb_heif_grid; i++) {
9037 if (c->heif_grid[i].item->item_id == from_item_id) {
9038 av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
9039 "referencing the same Derived Image item\n");
9040 return AVERROR_INVALIDDATA;
9041 }
9042 }
9043
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 for (int i = 0; i < c->nb_heif_item; i++) {
9044
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)
9045 14 continue;
9046 6 item = c->heif_item[i];
9047
9048
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 switch (item->type) {
9049 6 case MKTAG('g','r','i','d'):
9050 case MKTAG('i','o','v','l'):
9051 6 break;
9052 default:
9053 avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
9054 av_fourcc2str(item->type));
9055 return 0;
9056 }
9057 6 break;
9058 }
9059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!item) {
9060 av_log(c->fc, AV_LOG_ERROR, "Missing grid information\n");
9061 return AVERROR_INVALIDDATA;
9062 }
9063
9064 6 grid = av_realloc_array(c->heif_grid, c->nb_heif_grid + 1U,
9065 sizeof(*c->heif_grid));
9066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!grid)
9067 return AVERROR(ENOMEM);
9068 6 c->heif_grid = grid;
9069 6 grid = &grid[c->nb_heif_grid++];
9070
9071 6 entries = avio_rb16(pb);
9072 6 grid->tile_id_list = av_malloc_array(entries, sizeof(*grid->tile_id_list));
9073 6 grid->tile_idx_list = av_calloc(entries, sizeof(*grid->tile_idx_list));
9074 6 grid->tile_item_list = av_calloc(entries, sizeof(*grid->tile_item_list));
9075
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)
9076 return AVERROR(ENOMEM);
9077 /* 'to' item ids */
9078
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (i = 0; i < entries; i++)
9079
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 grid->tile_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
9080 6 grid->nb_tiles = entries;
9081 6 grid->item = item;
9082
9083 6 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
9084 from_item_id, entries);
9085
9086 6 return 0;
9087 }
9088
9089 11 static int mov_read_iref_cdsc(MOVContext *c, AVIOContext *pb, uint32_t type, int version)
9090 {
9091 11 HEIFItem *from_item = NULL;
9092 int entries;
9093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9094 11 const HEIFItemRef ref = { type, from_item_id };
9095
9096 11 from_item = get_heif_item(c, from_item_id);
9097
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!from_item) {
9098 av_log(c->fc, AV_LOG_ERROR, "Missing stream referenced by thmb item\n");
9099 return AVERROR_INVALIDDATA;
9100 }
9101
9102 11 entries = avio_rb16(pb);
9103 /* 'to' item ids */
9104
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (int i = 0; i < entries; i++) {
9105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 HEIFItem *item = get_heif_item(c, version ? avio_rb32(pb) : avio_rb16(pb));
9106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!item) {
9107 av_log(c->fc, AV_LOG_WARNING, "Missing stream referenced by %s item\n",
9108 av_fourcc2str(type));
9109 continue;
9110 }
9111
9112
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (!av_dynarray2_add((void **)&item->iref_list, &item->nb_iref_list,
9113 sizeof(*item->iref_list), (const uint8_t *)&ref))
9114 return AVERROR(ENOMEM);
9115 }
9116
9117 11 av_log(c->fc, AV_LOG_TRACE, "%s: from_item_id %d, entries %d\n",
9118 11 av_fourcc2str(type), from_item_id, entries);
9119
9120 11 return 0;
9121 }
9122
9123 11 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9124 {
9125 11 int version = avio_r8(pb);
9126 11 avio_rb24(pb); // flags
9127 11 atom.size -= 4;
9128
9129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (version > 1) {
9130 av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
9131 return 0;
9132 }
9133
9134
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 11 times.
28 while (atom.size) {
9135 17 uint32_t type, size = avio_rb32(pb);
9136 17 int64_t next = avio_tell(pb);
9137
9138
3/6
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 17 times.
17 if (size < 14 || next < 0 || next > INT64_MAX - size)
9139 return AVERROR_INVALIDDATA;
9140
9141 17 next += size - 4;
9142 17 type = avio_rl32(pb);
9143
2/3
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
17 switch (type) {
9144 6 case MKTAG('d','i','m','g'):
9145 6 mov_read_iref_dimg(c, pb, version);
9146 17 break;
9147 11 case MKTAG('c','d','s','c'):
9148 case MKTAG('t','h','m','b'):
9149 11 mov_read_iref_cdsc(c, pb, type, version);
9150 11 break;
9151 default:
9152 av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
9153 av_fourcc2str(type), size);
9154 }
9155
9156 17 atom.size -= size;
9157 17 avio_seek(pb, next, SEEK_SET);
9158 }
9159 11 return 0;
9160 }
9161
9162 37 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9163 {
9164 HEIFItem *item;
9165 uint32_t width, height;
9166
9167 37 avio_r8(pb); /* version */
9168 37 avio_rb24(pb); /* flags */
9169 37 width = avio_rb32(pb);
9170 37 height = avio_rb32(pb);
9171
9172 37 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %u, height %u\n",
9173 c->cur_item_id, width, height);
9174
9175 37 item = get_heif_item(c, c->cur_item_id);
9176
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if (item) {
9177 37 item->width = width;
9178 37 item->height = height;
9179 }
9180
9181 37 return 0;
9182 }
9183
9184 8 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9185 {
9186 HEIFItem *item;
9187 int angle;
9188
9189 8 angle = avio_r8(pb) & 0x3;
9190
9191 8 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
9192 c->cur_item_id, angle);
9193
9194 8 item = get_heif_item(c, c->cur_item_id);
9195
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (item) {
9196 // angle * 90 specifies the angle (in anti-clockwise direction)
9197 // in units of degrees.
9198 8 item->rotation = angle * 90;
9199 }
9200
9201 8 return 0;
9202 }
9203
9204 6 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9205 {
9206 HEIFItem *item;
9207 int axis;
9208
9209 6 axis = avio_r8(pb) & 0x1;
9210
9211 6 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
9212 c->cur_item_id, axis);
9213
9214 6 item = get_heif_item(c, c->cur_item_id);
9215
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
9216 6 item->hflip = axis;
9217 6 item->vflip = !axis;
9218 }
9219
9220 6 return 0;
9221 }
9222
9223 15 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9224 {
9225 typedef struct MOVAtoms {
9226 FFIOContext b;
9227 uint32_t type;
9228 int64_t size;
9229 uint8_t *data;
9230 } MOVAtoms;
9231 15 MOVAtoms *atoms = NULL;
9232 MOVAtom a;
9233 unsigned count;
9234 15 int nb_atoms = 0;
9235 int version, flags;
9236 int ret;
9237
9238 15 a.size = avio_rb32(pb);
9239 15 a.type = avio_rl32(pb);
9240
9241
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 if (a.size < 8 || a.type != MKTAG('i','p','c','o'))
9242 return AVERROR_INVALIDDATA;
9243
9244 15 a.size -= 8;
9245
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 15 times.
86 while (a.size >= 8) {
9246 71 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
9247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (!ref) {
9248 ret = AVERROR(ENOMEM);
9249 goto fail;
9250 }
9251 71 ref->data = NULL;
9252 71 ref->size = avio_rb32(pb);
9253 71 ref->type = avio_rl32(pb);
9254
2/4
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 71 times.
✗ Branch 3 not taken.
71 if (ref->size > a.size || ref->size < 8)
9255 break;
9256 71 ref->data = av_malloc(ref->size);
9257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (!ref->data) {
9258 ret = AVERROR_INVALIDDATA;
9259 goto fail;
9260 }
9261 71 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
9262 71 avio_seek(pb, -8, SEEK_CUR);
9263
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 71 times.
71 if (avio_read(pb, ref->data, ref->size) != ref->size) {
9264 ret = AVERROR_INVALIDDATA;
9265 goto fail;
9266 }
9267 71 ffio_init_read_context(&ref->b, ref->data, ref->size);
9268 71 a.size -= ref->size;
9269 }
9270
9271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (a.size) {
9272 ret = AVERROR_INVALIDDATA;
9273 goto fail;
9274 }
9275
9276 15 a.size = avio_rb32(pb);
9277 15 a.type = avio_rl32(pb);
9278
9279
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 if (a.size < 8 || a.type != MKTAG('i','p','m','a')) {
9280 ret = AVERROR_INVALIDDATA;
9281 goto fail;
9282 }
9283
9284 15 version = avio_r8(pb);
9285 15 flags = avio_rb24(pb);
9286 15 count = avio_rb32(pb);
9287
9288
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 15 times.
52 for (int i = 0; i < count; i++) {
9289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9290 37 int assoc_count = avio_r8(pb);
9291
9292
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
37 if (avio_feof(pb)) {
9293 ret = AVERROR_INVALIDDATA;
9294 goto fail;
9295 }
9296
9297
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 37 times.
135 for (int j = 0; j < assoc_count; j++) {
9298 MOVAtoms *ref;
9299 98 int index = avio_r8(pb) & 0x7f;
9300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (flags & 1) {
9301 index <<= 8;
9302 index |= avio_r8(pb);
9303 }
9304
2/4
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 98 times.
98 if (index > nb_atoms || index <= 0) {
9305 ret = AVERROR_INVALIDDATA;
9306 goto fail;
9307 }
9308 98 ref = &atoms[--index];
9309
9310 98 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
9311 98 index + 1, item_id, av_fourcc2str(ref->type));
9312
9313 98 c->cur_item_id = item_id;
9314
9315 98 ret = mov_read_default(c, &ref->b.pub,
9316 98 (MOVAtom) { .size = ref->size,
9317 .type = MKTAG('i','p','c','o') });
9318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (ret < 0)
9319 goto fail;
9320 98 ffio_init_read_context(&ref->b, ref->data, ref->size);
9321 }
9322 }
9323
9324 15 ret = 0;
9325 15 fail:
9326 15 c->cur_item_id = -1;
9327
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 15 times.
86 for (int i = 0; i < nb_atoms; i++)
9328 71 av_free(atoms[i].data);
9329 15 av_free(atoms);
9330
9331 15 return ret;
9332 }
9333
9334 static const MOVParseTableEntry mov_default_parse_table[] = {
9335 { MKTAG('A','C','L','R'), mov_read_aclr },
9336 { MKTAG('A','P','R','G'), mov_read_avid },
9337 { MKTAG('A','A','L','P'), mov_read_avid },
9338 { MKTAG('A','R','E','S'), mov_read_ares },
9339 { MKTAG('a','v','s','s'), mov_read_avss },
9340 { MKTAG('a','v','1','C'), mov_read_glbl },
9341 { MKTAG('c','h','p','l'), mov_read_chpl },
9342 { MKTAG('c','o','6','4'), mov_read_stco },
9343 { MKTAG('c','o','l','r'), mov_read_colr },
9344 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
9345 { MKTAG('d','i','n','f'), mov_read_default },
9346 { MKTAG('D','p','x','E'), mov_read_dpxe },
9347 { MKTAG('d','r','e','f'), mov_read_dref },
9348 { MKTAG('e','d','t','s'), mov_read_default },
9349 { MKTAG('e','l','s','t'), mov_read_elst },
9350 { MKTAG('e','n','d','a'), mov_read_enda },
9351 { MKTAG('f','i','e','l'), mov_read_fiel },
9352 { MKTAG('a','d','r','m'), mov_read_adrm },
9353 { MKTAG('f','t','y','p'), mov_read_ftyp },
9354 { MKTAG('g','l','b','l'), mov_read_glbl },
9355 { MKTAG('h','d','l','r'), mov_read_hdlr },
9356 { MKTAG('i','l','s','t'), mov_read_ilst },
9357 { MKTAG('j','p','2','h'), mov_read_jp2h },
9358 { MKTAG('m','d','a','t'), mov_read_mdat },
9359 { MKTAG('m','d','h','d'), mov_read_mdhd },
9360 { MKTAG('m','d','i','a'), mov_read_default },
9361 { MKTAG('m','e','t','a'), mov_read_meta },
9362 { MKTAG('m','i','n','f'), mov_read_default },
9363 { MKTAG('m','o','o','f'), mov_read_moof },
9364 { MKTAG('m','o','o','v'), mov_read_moov },
9365 { MKTAG('m','v','e','x'), mov_read_default },
9366 { MKTAG('m','v','h','d'), mov_read_mvhd },
9367 { MKTAG('S','M','I',' '), mov_read_svq3 },
9368 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
9369 { MKTAG('a','v','c','C'), mov_read_glbl },
9370 { MKTAG('p','a','s','p'), mov_read_pasp },
9371 { MKTAG('c','l','a','p'), mov_read_clap },
9372 { MKTAG('s','b','a','s'), mov_read_sbas },
9373 { MKTAG('s','i','d','x'), mov_read_sidx },
9374 { MKTAG('s','t','b','l'), mov_read_default },
9375 { MKTAG('s','t','c','o'), mov_read_stco },
9376 { MKTAG('s','t','p','s'), mov_read_stps },
9377 { MKTAG('s','t','r','f'), mov_read_strf },
9378 { MKTAG('s','t','s','c'), mov_read_stsc },
9379 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
9380 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
9381 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
9382 { MKTAG('s','t','t','s'), mov_read_stts },
9383 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
9384 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
9385 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
9386 { MKTAG('t','f','d','t'), mov_read_tfdt },
9387 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
9388 { MKTAG('t','r','a','k'), mov_read_trak },
9389 { MKTAG('t','r','a','f'), mov_read_default },
9390 { MKTAG('t','r','e','f'), mov_read_default },
9391 { MKTAG('t','m','c','d'), mov_read_tmcd },
9392 { MKTAG('c','h','a','p'), mov_read_chap },
9393 { MKTAG('t','r','e','x'), mov_read_trex },
9394 { MKTAG('t','r','u','n'), mov_read_trun },
9395 { MKTAG('u','d','t','a'), mov_read_default },
9396 { MKTAG('w','a','v','e'), mov_read_wave },
9397 { MKTAG('e','s','d','s'), mov_read_esds },
9398 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
9399 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
9400 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
9401 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
9402 { MKTAG('w','f','e','x'), mov_read_wfex },
9403 { MKTAG('c','m','o','v'), mov_read_cmov },
9404 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
9405 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
9406 { MKTAG('d','v','c','1'), mov_read_dvc1 },
9407 { MKTAG('s','g','p','d'), mov_read_sgpd },
9408 { MKTAG('s','b','g','p'), mov_read_sbgp },
9409 { MKTAG('h','v','c','C'), mov_read_glbl },
9410 { MKTAG('v','v','c','C'), mov_read_glbl },
9411 { MKTAG('u','u','i','d'), mov_read_uuid },
9412 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
9413 { MKTAG('f','r','e','e'), mov_read_free },
9414 { MKTAG('-','-','-','-'), mov_read_custom },
9415 { MKTAG('s','i','n','f'), mov_read_default },
9416 { MKTAG('f','r','m','a'), mov_read_frma },
9417 { MKTAG('s','e','n','c'), mov_read_senc },
9418 { MKTAG('s','a','i','z'), mov_read_saiz },
9419 { MKTAG('s','a','i','o'), mov_read_saio },
9420 { MKTAG('p','s','s','h'), mov_read_pssh },
9421 { MKTAG('s','c','h','m'), mov_read_schm },
9422 { MKTAG('s','c','h','i'), mov_read_default },
9423 { MKTAG('t','e','n','c'), mov_read_tenc },
9424 { MKTAG('d','f','L','a'), mov_read_dfla },
9425 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
9426 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
9427 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
9428 { MKTAG('h','f','o','v'), mov_read_hfov },
9429 { MKTAG('d','O','p','s'), mov_read_dops },
9430 { MKTAG('d','m','l','p'), mov_read_dmlp },
9431 { MKTAG('S','m','D','m'), mov_read_smdm },
9432 { MKTAG('C','o','L','L'), mov_read_coll },
9433 { MKTAG('v','p','c','C'), mov_read_vpcc },
9434 { MKTAG('m','d','c','v'), mov_read_mdcv },
9435 { MKTAG('c','l','l','i'), mov_read_clli },
9436 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
9437 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
9438 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
9439 { MKTAG('k','i','n','d'), mov_read_kind },
9440 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
9441 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
9442 { MKTAG('i','l','o','c'), mov_read_iloc },
9443 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
9444 { MKTAG('p','i','t','m'), mov_read_pitm },
9445 { MKTAG('e','v','c','C'), mov_read_glbl },
9446 { MKTAG('i','d','a','t'), mov_read_idat },
9447 { MKTAG('i','m','i','r'), mov_read_imir },
9448 { MKTAG('i','r','e','f'), mov_read_iref },
9449 { MKTAG('i','s','p','e'), mov_read_ispe },
9450 { MKTAG('i','r','o','t'), mov_read_irot },
9451 { MKTAG('i','p','r','p'), mov_read_iprp },
9452 { MKTAG('i','i','n','f'), mov_read_iinf },
9453 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
9454 { MKTAG('l','h','v','C'), mov_read_lhvc },
9455 { MKTAG('l','v','c','C'), mov_read_glbl },
9456 { MKTAG('a','p','v','C'), mov_read_glbl },
9457 #if CONFIG_IAMFDEC
9458 { MKTAG('i','a','c','b'), mov_read_iacb },
9459 #endif
9460 { 0, NULL }
9461 };
9462
9463 6703 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9464 {
9465 6703 int64_t total_size = 0;
9466 MOVAtom a;
9467 int i;
9468
9469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6703 times.
6703 if (c->atom_depth > 10) {
9470 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
9471 return AVERROR_INVALIDDATA;
9472 }
9473 6703 c->atom_depth ++;
9474
9475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6703 times.
6703 if (atom.size < 0)
9476 atom.size = INT64_MAX;
9477
2/2
✓ Branch 0 taken 19278 times.
✓ Branch 1 taken 6212 times.
25490 while (total_size <= atom.size - 8) {
9478 19278 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
9479 19278 a.size = avio_rb32(pb);
9480 19278 a.type = avio_rl32(pb);
9481
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 19273 times.
19278 if (avio_feof(pb))
9482 5 break;
9483
3/4
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 19079 times.
✓ Branch 2 taken 194 times.
✗ Branch 3 not taken.
19273 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
9484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19273 times.
19273 a.type == MKTAG('h','o','o','v')) &&
9485 a.size >= 8 &&
9486 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
9487 uint32_t type;
9488 avio_skip(pb, 4);
9489 type = avio_rl32(pb);
9490 if (avio_feof(pb))
9491 break;
9492 avio_seek(pb, -8, SEEK_CUR);
9493 if (type == MKTAG('m','v','h','d') ||
9494 type == MKTAG('c','m','o','v')) {
9495 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
9496 a.type = MKTAG('m','o','o','v');
9497 }
9498 }
9499
2/2
✓ Branch 0 taken 16366 times.
✓ Branch 1 taken 2907 times.
19273 if (atom.type != MKTAG('r','o','o','t') &&
9500
2/2
✓ Branch 0 taken 14919 times.
✓ Branch 1 taken 1447 times.
16366 atom.type != MKTAG('m','o','o','v')) {
9501
1/2
✓ Branch 0 taken 14919 times.
✗ Branch 1 not taken.
14919 if (a.type == MKTAG('t','r','a','k') ||
9502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14919 times.
14919 a.type == MKTAG('m','d','a','t')) {
9503 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
9504 avio_skip(pb, -8);
9505 c->atom_depth --;
9506 486 return 0;
9507 }
9508 }
9509 19273 total_size += 8;
9510
3/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 19247 times.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
19273 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
9511 26 a.size = avio_rb64(pb) - 8;
9512 26 total_size += 8;
9513 }
9514 19273 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
9515 19273 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
9516
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19268 times.
19273 if (a.size == 0) {
9517 5 a.size = atom.size - total_size + 8;
9518 }
9519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19273 times.
19273 if (a.size < 0)
9520 break;
9521 19273 a.size -= 8;
9522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19273 times.
19273 if (a.size < 0)
9523 break;
9524 19273 a.size = FFMIN(a.size, atom.size - total_size);
9525
9526
2/2
✓ Branch 0 taken 888143 times.
✓ Branch 1 taken 1961 times.
890104 for (i = 0; mov_default_parse_table[i].type; i++)
9527
2/2
✓ Branch 0 taken 17312 times.
✓ Branch 1 taken 870831 times.
888143 if (mov_default_parse_table[i].type == a.type) {
9528 17312 parse = mov_default_parse_table[i].parse;
9529 17312 break;
9530 }
9531
9532 // container is user data
9533
4/4
✓ Branch 0 taken 1961 times.
✓ Branch 1 taken 17312 times.
✓ Branch 2 taken 1784 times.
✓ Branch 3 taken 177 times.
19273 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
9534
2/2
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 1484 times.
1784 atom.type == MKTAG('i','l','s','t')))
9535 477 parse = mov_read_udta_string;
9536
9537 // Supports parsing the QuickTime Metadata Keys.
9538 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
9539
4/4
✓ Branch 0 taken 1484 times.
✓ Branch 1 taken 17789 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 1473 times.
19273 if (!parse && c->found_hdlr_mdta &&
9540
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 atom.type == MKTAG('m','e','t','a') &&
9541
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 a.type == MKTAG('k','e','y','s') &&
9542
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 c->meta_keys_count == 0) {
9543 11 parse = mov_read_keys;
9544 }
9545
9546
2/2
✓ Branch 0 taken 1473 times.
✓ Branch 1 taken 17800 times.
19273 if (!parse) { /* skip leaf atoms data */
9547 1473 avio_skip(pb, a.size);
9548 } else {
9549 17800 int64_t start_pos = avio_tell(pb);
9550 int64_t left;
9551 17800 int err = parse(c, pb, a);
9552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17800 times.
17800 if (err < 0) {
9553 c->atom_depth --;
9554 return err;
9555 }
9556
5/6
✓ Branch 0 taken 3673 times.
✓ Branch 1 taken 14127 times.
✓ Branch 2 taken 3335 times.
✓ Branch 3 taken 338 times.
✓ Branch 4 taken 3335 times.
✗ Branch 5 not taken.
17800 if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos &&
9557
7/8
✓ Branch 0 taken 3334 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3334 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3326 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 477 times.
✓ Branch 7 taken 2849 times.
6661 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
9558 3326 start_pos + a.size == avio_size(pb))) {
9559
5/6
✓ Branch 0 taken 485 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 485 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 477 times.
486 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
9560 9 c->next_root_atom = start_pos + a.size;
9561 486 c->atom_depth --;
9562 486 return 0;
9563 }
9564 17314 left = a.size - avio_tell(pb) + start_pos;
9565
2/2
✓ Branch 0 taken 1465 times.
✓ Branch 1 taken 15849 times.
17314 if (left > 0) /* skip garbage at atom end */
9566 1465 avio_skip(pb, left);
9567
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 15847 times.
15849 else if (left < 0) {
9568 2 av_log(c->fc, AV_LOG_WARNING,
9569 "overread end of atom '%s' by %"PRId64" bytes\n",
9570 2 av_fourcc2str(a.type), -left);
9571 2 avio_seek(pb, left, SEEK_CUR);
9572 }
9573 }
9574
9575 18787 total_size += a.size;
9576 }
9577
9578
4/4
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 6110 times.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 5 times.
6217 if (total_size < atom.size && atom.size < 0x7ffff)
9579 102 avio_skip(pb, atom.size - total_size);
9580
9581 6217 c->atom_depth --;
9582 6217 return 0;
9583 }
9584
9585 7279 static int mov_probe(const AVProbeData *p)
9586 {
9587 int64_t offset;
9588 uint32_t tag;
9589 7279 int score = 0;
9590 7279 int moov_offset = -1;
9591
9592 /* check file header */
9593 7279 offset = 0;
9594 8980 for (;;) {
9595 int64_t size;
9596 16259 int minsize = 8;
9597 /* ignore invalid offset */
9598
2/2
✓ Branch 0 taken 7279 times.
✓ Branch 1 taken 8980 times.
16259 if ((offset + 8ULL) > (unsigned int)p->buf_size)
9599 7279 break;
9600 8980 size = AV_RB32(p->buf + offset);
9601
3/4
✓ Branch 0 taken 524 times.
✓ Branch 1 taken 8456 times.
✓ Branch 2 taken 524 times.
✗ Branch 3 not taken.
8980 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
9602 524 size = AV_RB64(p->buf+offset + 8);
9603 524 minsize = 16;
9604
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 8401 times.
8456 } else if (size == 0) {
9605 55 size = p->buf_size - offset;
9606 }
9607
2/2
✓ Branch 0 taken 399 times.
✓ Branch 1 taken 8581 times.
8980 if (size < minsize) {
9608 399 offset += 4;
9609 399 continue;
9610 }
9611 8581 tag = AV_RL32(p->buf + offset + 4);
9612
5/6
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 850 times.
✓ Branch 2 taken 358 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7243 times.
8581 switch(tag) {
9613 /* check for obvious tags */
9614 129 case MKTAG('m','o','o','v'):
9615 129 moov_offset = offset + 4;
9616 979 case MKTAG('m','d','a','t'):
9617 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
9618 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
9619 case MKTAG('f','t','y','p'):
9620
2/2
✓ Branch 0 taken 444 times.
✓ Branch 1 taken 535 times.
979 if (tag == MKTAG('f','t','y','p') &&
9621
1/2
✓ Branch 0 taken 444 times.
✗ Branch 1 not taken.
444 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
9622
1/2
✓ Branch 0 taken 444 times.
✗ Branch 1 not taken.
444 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
9623
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 438 times.
444 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
9624 )) {
9625 6 score = FFMAX(score, 5);
9626 } else {
9627 973 score = AVPROBE_SCORE_MAX;
9628 }
9629 979 break;
9630 /* those are more common words, so rate then a bit less */
9631 358 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
9632 case MKTAG('w','i','d','e'):
9633 case MKTAG('f','r','e','e'):
9634 case MKTAG('j','u','n','k'):
9635 case MKTAG('p','i','c','t'):
9636 358 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
9637 358 break;
9638 case MKTAG(0x82,0x82,0x7f,0x7d):
9639 score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
9640 break;
9641 1 case MKTAG('s','k','i','p'):
9642 case MKTAG('u','u','i','d'):
9643 case MKTAG('p','r','f','l'):
9644 /* if we only find those cause probedata is too small at least rate them */
9645 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
9646 1 break;
9647 }
9648
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8581 times.
8581 if (size > INT64_MAX - offset)
9649 break;
9650 8581 offset += size;
9651 }
9652
4/4
✓ Branch 0 taken 475 times.
✓ Branch 1 taken 6804 times.
✓ Branch 2 taken 129 times.
✓ Branch 3 taken 346 times.
7279 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
9653 /* moov atom in the header - we should make sure that this is not a
9654 * MOV-packed MPEG-PS */
9655 129 offset = moov_offset;
9656
9657
2/2
✓ Branch 0 taken 126614 times.
✓ Branch 1 taken 129 times.
126743 while (offset < (p->buf_size - 16)) { /* Sufficient space */
9658 /* We found an actual hdlr atom */
9659
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 126477 times.
126614 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
9660
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 116 times.
137 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
9661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
9662 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
9663 /* We found a media handler reference atom describing an
9664 * MPEG-PS-in-MOV, return a
9665 * low score to force expanding the probe window until
9666 * mpegps_probe finds what it needs */
9667 return 5;
9668 } else {
9669 /* Keep looking */
9670 126614 offset += 2;
9671 }
9672 }
9673 }
9674
9675 7279 return score;
9676 }
9677
9678 // must be done after parsing all trak because there's no order requirement
9679 2 static void mov_read_chapters(AVFormatContext *s)
9680 {
9681 2 MOVContext *mov = s->priv_data;
9682 MOVStreamContext *sc;
9683 int64_t cur_pos;
9684 int i, j;
9685 int chapter_track;
9686
9687
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
9688 2 AVStream *st = NULL;
9689 2 FFStream *sti = NULL;
9690 2 chapter_track = mov->chapter_tracks[j];
9691
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
9692 4 sc = mov->fc->streams[i]->priv_data;
9693
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
9694 2 st = s->streams[i];
9695 2 break;
9696 }
9697 }
9698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
9699 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
9700 continue;
9701 }
9702 2 sti = ffstream(st);
9703
9704 2 sc = st->priv_data;
9705 2 cur_pos = avio_tell(sc->pb);
9706
9707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
9708 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
9709 if (!st->attached_pic.data && sti->nb_index_entries) {
9710 // Retrieve the first frame, if possible
9711 AVIndexEntry *sample = &sti->index_entries[0];
9712 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9713 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
9714 goto finish;
9715 }
9716
9717 if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
9718 goto finish;
9719 }
9720 } else {
9721 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
9722 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
9723 2 st->discard = AVDISCARD_ALL;
9724
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
9725 8 AVIndexEntry *sample = &sti->index_entries[i];
9726
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;
9727 uint8_t *title;
9728 uint16_t ch;
9729 int len, title_len;
9730
9731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
9732 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
9733 end = AV_NOPTS_VALUE;
9734 }
9735
9736
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9737 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
9738 goto finish;
9739 }
9740
9741 // the first two bytes are the length of the title
9742 8 len = avio_rb16(sc->pb);
9743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
9744 continue;
9745 8 title_len = 2*len + 1;
9746
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
9747 goto finish;
9748
9749 // The samples could theoretically be in any encoding if there's an encd
9750 // atom following, but in practice are only utf-8 or utf-16, distinguished
9751 // instead by the presence of a BOM
9752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
9753 title[0] = 0;
9754 } else {
9755 8 ch = avio_rb16(sc->pb);
9756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
9757 avio_get_str16be(sc->pb, len, title, title_len);
9758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
9759 avio_get_str16le(sc->pb, len, title, title_len);
9760 else {
9761 8 AV_WB16(title, ch);
9762
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)
9763 title[len] = 0;
9764 else
9765 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
9766 }
9767 }
9768
9769 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
9770 8 av_freep(&title);
9771 }
9772 }
9773 2 finish:
9774 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
9775 }
9776 2 }
9777
9778 19 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
9779 int64_t value, int flags)
9780 {
9781 AVTimecode tc;
9782 char buf[AV_TIMECODE_STR_SIZE];
9783 19 AVRational rate = st->avg_frame_rate;
9784 19 int ret = av_timecode_init(&tc, rate, flags, 0, s);
9785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
9786 return ret;
9787 19 av_dict_set(&st->metadata, "timecode",
9788 19 av_timecode_make_string(&tc, buf, value), 0);
9789 19 return 0;
9790 }
9791
9792 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
9793 {
9794 MOVStreamContext *sc = st->priv_data;
9795 FFStream *const sti = ffstream(st);
9796 char buf[AV_TIMECODE_STR_SIZE];
9797 int64_t cur_pos = avio_tell(sc->pb);
9798 int hh, mm, ss, ff, drop;
9799
9800 if (!sti->nb_index_entries)
9801 return -1;
9802
9803 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9804 avio_skip(s->pb, 13);
9805 hh = avio_r8(s->pb);
9806 mm = avio_r8(s->pb);
9807 ss = avio_r8(s->pb);
9808 drop = avio_r8(s->pb);
9809 ff = avio_r8(s->pb);
9810 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
9811 hh, mm, ss, drop ? ';' : ':', ff);
9812 av_dict_set(&st->metadata, "timecode", buf, 0);
9813
9814 avio_seek(sc->pb, cur_pos, SEEK_SET);
9815 return 0;
9816 }
9817
9818 19 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
9819 {
9820 19 MOVStreamContext *sc = st->priv_data;
9821 19 FFStream *const sti = ffstream(st);
9822 19 int flags = 0;
9823 19 int64_t cur_pos = avio_tell(sc->pb);
9824 int64_t value;
9825 19 AVRational tc_rate = st->avg_frame_rate;
9826 19 int tmcd_nb_frames = sc->tmcd_nb_frames;
9827 int rounded_tc_rate;
9828
9829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!sti->nb_index_entries)
9830 return -1;
9831
9832
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)
9833 return -1;
9834
9835 19 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9836 19 value = avio_rb32(s->pb);
9837
9838
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13 times.
19 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
9839
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
9840
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
9841
9842 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
9843 * not the case) and thus assume "frame number format" instead of QT one.
9844 * No sample with tmcd track can be found with a QT timecode at the moment,
9845 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
9846 * format). */
9847
9848 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
9849 * we multiply the frame number with the quotient.
9850 * See tickets #9492, #9710. */
9851 19 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
9852 /* Work around files where tmcd_nb_frames is rounded down from frame rate
9853 * instead of up. See ticket #5978. */
9854
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
9855
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
9856 10 tmcd_nb_frames = rounded_tc_rate;
9857 19 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
9858
9859 19 parse_timecode_in_framenum_format(s, st, value, flags);
9860
9861 19 avio_seek(sc->pb, cur_pos, SEEK_SET);
9862 19 return 0;
9863 }
9864
9865 1221 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
9866 int i;
9867
3/4
✓ Branch 0 taken 1221 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1217 times.
✓ Branch 3 taken 4 times.
1221 if (!index || !*index) return;
9868
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 4 times.
76 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
9869 72 av_encryption_info_free((*index)->encrypted_samples[i]);
9870 }
9871 4 av_freep(&(*index)->encrypted_samples);
9872 4 av_freep(&(*index)->auxiliary_info_sizes);
9873 4 av_freep(&(*index)->auxiliary_offsets);
9874 4 av_freep(index);
9875 }
9876
9877 697 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
9878 {
9879 697 MOVStreamContext *sc = st->priv_data;
9880
9881
3/4
✓ Branch 0 taken 697 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 657 times.
697 if (!sc || --sc->refcount) {
9882 40 st->priv_data = NULL;
9883 40 return;
9884 }
9885
9886 657 av_freep(&sc->tts_data);
9887
2/2
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 657 times.
1269 for (int i = 0; i < sc->drefs_count; i++) {
9888 612 av_freep(&sc->drefs[i].path);
9889 612 av_freep(&sc->drefs[i].dir);
9890 }
9891 657 av_freep(&sc->drefs);
9892
9893 657 sc->drefs_count = 0;
9894
9895
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 643 times.
657 if (!sc->pb_is_copied)
9896 14 ff_format_io_close(s, &sc->pb);
9897
9898 657 sc->pb = NULL;
9899 657 av_freep(&sc->chunk_offsets);
9900 657 av_freep(&sc->stsc_data);
9901 657 av_freep(&sc->sample_sizes);
9902 657 av_freep(&sc->keyframes);
9903 657 av_freep(&sc->ctts_data);
9904 657 av_freep(&sc->stts_data);
9905 657 av_freep(&sc->sdtp_data);
9906 657 av_freep(&sc->stps_data);
9907 657 av_freep(&sc->elst_data);
9908 657 av_freep(&sc->rap_group);
9909 657 av_freep(&sc->sync_group);
9910 657 av_freep(&sc->sgpd_sync);
9911 657 av_freep(&sc->sample_offsets);
9912 657 av_freep(&sc->open_key_samples);
9913 657 av_freep(&sc->display_matrix);
9914 657 av_freep(&sc->index_ranges);
9915
9916
2/2
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 45 times.
657 if (sc->extradata)
9917
2/2
✓ Branch 0 taken 625 times.
✓ Branch 1 taken 612 times.
1237 for (int i = 0; i < sc->stsd_count; i++)
9918 625 av_free(sc->extradata[i]);
9919 657 av_freep(&sc->extradata);
9920 657 av_freep(&sc->extradata_size);
9921
9922 657 mov_free_encryption_index(&sc->cenc.encryption_index);
9923 657 av_encryption_info_free(sc->cenc.default_encrypted_sample);
9924 657 av_aes_ctr_free(sc->cenc.aes_ctr);
9925
9926 657 av_freep(&sc->stereo3d);
9927 657 av_freep(&sc->spherical);
9928 657 av_freep(&sc->mastering);
9929 657 av_freep(&sc->coll);
9930 657 av_freep(&sc->ambient);
9931
9932 #if CONFIG_IAMFDEC
9933
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 647 times.
657 if (sc->iamf)
9934 10 ff_iamf_read_deinit(sc->iamf);
9935 #endif
9936 657 av_freep(&sc->iamf);
9937 }
9938
9939 509 static int mov_read_close(AVFormatContext *s)
9940 {
9941 509 MOVContext *mov = s->priv_data;
9942 int i, j;
9943
9944
2/2
✓ Branch 0 taken 697 times.
✓ Branch 1 taken 509 times.
1206 for (i = 0; i < s->nb_streams; i++) {
9945 697 AVStream *st = s->streams[i];
9946
9947 697 mov_free_stream_context(s, st);
9948 }
9949
9950 509 av_freep(&mov->dv_demux);
9951 509 avformat_free_context(mov->dv_fctx);
9952 509 mov->dv_fctx = NULL;
9953
9954
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 498 times.
509 if (mov->meta_keys) {
9955
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i < mov->meta_keys_count; i++) {
9956 58 av_freep(&mov->meta_keys[i]);
9957 }
9958 11 av_freep(&mov->meta_keys);
9959 }
9960
9961 509 av_freep(&mov->trex_data);
9962 509 av_freep(&mov->bitrates);
9963
9964
2/2
✓ Branch 0 taken 468 times.
✓ Branch 1 taken 509 times.
977 for (i = 0; i < mov->frag_index.nb_items; i++) {
9965 468 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
9966
2/2
✓ Branch 0 taken 564 times.
✓ Branch 1 taken 468 times.
1032 for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) {
9967 564 mov_free_encryption_index(&frag[j].encryption_index);
9968 }
9969 468 av_freep(&mov->frag_index.item[i].stream_info);
9970 }
9971 509 av_freep(&mov->frag_index.item);
9972
9973 509 av_freep(&mov->aes_decrypt);
9974 509 av_freep(&mov->chapter_tracks);
9975
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 509 times.
551 for (i = 0; i < mov->nb_heif_item; i++) {
9976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!mov->heif_item[i])
9977 continue;
9978 42 av_freep(&mov->heif_item[i]->name);
9979 42 av_freep(&mov->heif_item[i]->iref_list);
9980 42 av_freep(&mov->heif_item[i]->icc_profile);
9981 42 av_freep(&mov->heif_item[i]);
9982 }
9983 509 av_freep(&mov->heif_item);
9984
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 509 times.
515 for (i = 0; i < mov->nb_heif_grid; i++) {
9985 6 av_freep(&mov->heif_grid[i].tile_id_list);
9986 6 av_freep(&mov->heif_grid[i].tile_idx_list);
9987 6 av_freep(&mov->heif_grid[i].tile_item_list);
9988 }
9989 509 av_freep(&mov->heif_grid);
9990
9991 509 return 0;
9992 }
9993
9994 16 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
9995 {
9996 int i;
9997
9998
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 for (i = 0; i < s->nb_streams; i++) {
9999 24 AVStream *st = s->streams[i];
10000 24 MOVStreamContext *sc = st->priv_data;
10001
10002
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
10003
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 sc->timecode_track == tmcd_id)
10004 14 return 1;
10005 }
10006 2 return 0;
10007 }
10008
10009 /* look for a tmcd track not referenced by any video track, and export it globally */
10010 509 static void export_orphan_timecode(AVFormatContext *s)
10011 {
10012 int i;
10013
10014
2/2
✓ Branch 0 taken 694 times.
✓ Branch 1 taken 507 times.
1201 for (i = 0; i < s->nb_streams; i++) {
10015 694 AVStream *st = s->streams[i];
10016
10017
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 678 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 14 times.
710 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
10018 16 !tmcd_is_referenced(s, i + 1)) {
10019 2 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
10020
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (tcr) {
10021 2 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
10022 2 break;
10023 }
10024 }
10025 }
10026 509 }
10027
10028 static int read_tfra(MOVContext *mov, AVIOContext *f)
10029 {
10030 int version, fieldlength, i, j;
10031 int64_t pos = avio_tell(f);
10032 uint32_t size = avio_rb32(f);
10033 unsigned track_id, item_count;
10034
10035 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
10036 return 1;
10037 }
10038 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
10039
10040 version = avio_r8(f);
10041 avio_rb24(f);
10042 track_id = avio_rb32(f);
10043 fieldlength = avio_rb32(f);
10044 item_count = avio_rb32(f);
10045 for (i = 0; i < item_count; i++) {
10046 int64_t time, offset;
10047 int index;
10048 MOVFragmentStreamInfo * frag_stream_info;
10049
10050 if (avio_feof(f)) {
10051 return AVERROR_INVALIDDATA;
10052 }
10053
10054 if (version == 1) {
10055 time = avio_rb64(f);
10056 offset = avio_rb64(f);
10057 } else {
10058 time = avio_rb32(f);
10059 offset = avio_rb32(f);
10060 }
10061
10062 // The first sample of each stream in a fragment is always a random
10063 // access sample. So it's entry in the tfra can be used as the
10064 // initial PTS of the fragment.
10065 index = update_frag_index(mov, offset);
10066 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
10067 if (frag_stream_info &&
10068 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
10069 frag_stream_info->first_tfra_pts = time;
10070
10071 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
10072 avio_r8(f);
10073 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
10074 avio_r8(f);
10075 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
10076 avio_r8(f);
10077 }
10078
10079 avio_seek(f, pos + size, SEEK_SET);
10080 return 0;
10081 }
10082
10083 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
10084 {
10085 int64_t stream_size = avio_size(f);
10086 int64_t original_pos = avio_tell(f);
10087 int64_t seek_ret;
10088 int ret = -1;
10089 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
10090 ret = seek_ret;
10091 goto fail;
10092 }
10093 c->mfra_size = avio_rb32(f);
10094 c->have_read_mfra_size = 1;
10095 if (!c->mfra_size || c->mfra_size > stream_size) {
10096 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
10097 goto fail;
10098 }
10099 if ((seek_ret = avio_seek(f, -((int64_t) c->mfra_size), SEEK_CUR)) < 0) {
10100 ret = seek_ret;
10101 goto fail;
10102 }
10103 if (avio_rb32(f) != c->mfra_size) {
10104 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
10105 goto fail;
10106 }
10107 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
10108 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
10109 goto fail;
10110 }
10111 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
10112 do {
10113 ret = read_tfra(c, f);
10114 if (ret < 0)
10115 goto fail;
10116 } while (!ret);
10117 ret = 0;
10118 c->frag_index.complete = 1;
10119 fail:
10120 seek_ret = avio_seek(f, original_pos, SEEK_SET);
10121 if (seek_ret < 0) {
10122 av_log(c->fc, AV_LOG_ERROR,
10123 "failed to seek back after looking for mfra\n");
10124 ret = seek_ret;
10125 }
10126 return ret;
10127 }
10128
10129 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10130 const HEIFItem *item)
10131 {
10132 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
10133 AV_PKT_DATA_ICC_PROFILE,
10134 item->icc_profile_size, 0);
10135 if (!sd)
10136 return AVERROR(ENOMEM);
10137
10138 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
10139
10140 return 0;
10141 }
10142
10143 6 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10144 const HEIFItem *item)
10145 {
10146 int32_t *matrix;
10147 6 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data,
10148 nb_coded_side_data,
10149 AV_PKT_DATA_DISPLAYMATRIX,
10150 9 * sizeof(*matrix), 0);
10151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sd)
10152 return AVERROR(ENOMEM);
10153
10154 6 matrix = (int32_t*)sd->data;
10155 /* rotation is in the counter-clockwise direction whereas
10156 * av_display_rotation_set() expects its argument to be
10157 * oriented clockwise, so we need to negate it. */
10158 6 av_display_rotation_set(matrix, -item->rotation);
10159 6 av_display_matrix_flip(matrix, item->hflip, item->vflip);
10160
10161 6 return 0;
10162 }
10163
10164 2 static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid,
10165 AVStreamGroupTileGrid *tile_grid)
10166 {
10167 2 MOVContext *c = s->priv_data;
10168 2 const HEIFItem *item = grid->item;
10169 2 int64_t offset = 0, pos = avio_tell(s->pb);
10170 2 int x = 0, y = 0, i = 0;
10171 int tile_rows, tile_cols;
10172 int flags, size;
10173
10174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10175 av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
10176 return AVERROR_PATCHWELCOME;
10177 }
10178
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (item->is_idat_relative) {
10179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!c->idat_offset) {
10180 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
10181 return AVERROR_INVALIDDATA;
10182 }
10183 2 offset = c->idat_offset;
10184 }
10185
10186 2 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10187
10188 2 avio_r8(s->pb); /* version */
10189 2 flags = avio_r8(s->pb);
10190
10191 2 tile_rows = avio_r8(s->pb) + 1;
10192 2 tile_cols = avio_r8(s->pb) + 1;
10193 /* actual width and height of output image */
10194
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);
10195
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);
10196
10197 2 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
10198 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
10199
10200 2 avio_seek(s->pb, pos, SEEK_SET);
10201
10202 2 size = tile_rows * tile_cols;
10203 2 tile_grid->nb_tiles = grid->nb_tiles;
10204
10205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tile_grid->nb_tiles != size)
10206 return AVERROR_INVALIDDATA;
10207
10208
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < tile_cols; i++)
10209 4 tile_grid->coded_width += grid->tile_item_list[i]->width;
10210
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < size; i += tile_cols)
10211 4 tile_grid->coded_height += grid->tile_item_list[i]->height;
10212
10213 2 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!tile_grid->offsets)
10215 return AVERROR(ENOMEM);
10216
10217
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 while (y < tile_grid->coded_height) {
10218 4 int left_col = i;
10219
10220
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 while (x < tile_grid->coded_width) {
10221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (i == tile_grid->nb_tiles)
10222 return AVERROR_INVALIDDATA;
10223
10224 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10225 8 tile_grid->offsets[i].horizontal = x;
10226 8 tile_grid->offsets[i].vertical = y;
10227
10228 8 x += grid->tile_item_list[i++]->width;
10229 }
10230
10231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (x > tile_grid->coded_width) {
10232 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10233 return AVERROR_INVALIDDATA;
10234 }
10235
10236 4 x = 0;
10237 4 y += grid->tile_item_list[left_col]->height;
10238 }
10239
10240
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) {
10241 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10242 return AVERROR_INVALIDDATA;
10243 }
10244
10245 2 return 0;
10246 }
10247
10248 4 static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid,
10249 AVStreamGroupTileGrid *tile_grid)
10250 {
10251 4 MOVContext *c = s->priv_data;
10252 4 const HEIFItem *item = grid->item;
10253 uint16_t canvas_fill_value[4];
10254 4 int64_t offset = 0, pos = avio_tell(s->pb);
10255 4 int ret = 0, flags;
10256
10257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10258 av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
10259 return AVERROR_PATCHWELCOME;
10260 }
10261
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
10262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
10263 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
10264 return AVERROR_INVALIDDATA;
10265 }
10266 4 offset = c->idat_offset;
10267 }
10268
10269 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10270
10271 4 avio_r8(s->pb); /* version */
10272 4 flags = avio_r8(s->pb);
10273
10274
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10275 16 canvas_fill_value[i] = avio_rb16(s->pb);
10276 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
10277 4 canvas_fill_value[0], canvas_fill_value[1],
10278 4 canvas_fill_value[2], canvas_fill_value[3]);
10279
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10280 16 tile_grid->background[i] = canvas_fill_value[i];
10281
10282 /* actual width and height of output image */
10283 4 tile_grid->width =
10284
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);
10285 4 tile_grid->height =
10286
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);
10287
10288 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
10289 tile_grid->width, tile_grid->height);
10290
10291 4 tile_grid->nb_tiles = grid->nb_tiles;
10292 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10293
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
10294 ret = AVERROR(ENOMEM);
10295 goto fail;
10296 }
10297
10298
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
10299 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10300
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);
10301
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);
10302 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
10303 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
10304 8 i, tile_grid->offsets[i].idx,
10305 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
10306 }
10307
10308 4 fail:
10309 4 avio_seek(s->pb, pos, SEEK_SET);
10310
10311 4 return ret;
10312 }
10313
10314 2 static int mov_parse_exif_item(AVFormatContext *s,
10315 AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10316 const HEIFItem *ref)
10317 {
10318 2 MOVContext *c = s->priv_data;
10319 AVPacketSideData *sd;
10320 2 AVExifMetadata ifd = { 0 };
10321 AVBufferRef *buf;
10322 2 int64_t offset = 0, pos = avio_tell(s->pb);
10323 2 unsigned orientation_id = av_exif_get_tag_id("Orientation");
10324 int err;
10325
10326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10327 av_log(c->fc, AV_LOG_WARNING, "Exif metadata with non seekable input\n");
10328 return AVERROR_PATCHWELCOME;
10329 }
10330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ref->is_idat_relative) {
10331 if (!c->idat_offset) {
10332 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the Exif metadata\n");
10333 return AVERROR_INVALIDDATA;
10334 }
10335 offset = c->idat_offset;
10336 }
10337
10338 2 buf = av_buffer_alloc(ref->extent_length);
10339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!buf)
10340 return AVERROR(ENOMEM);
10341
10342 2 avio_seek(s->pb, ref->extent_offset + offset, SEEK_SET);
10343 2 err = avio_read(s->pb, buf->data, ref->extent_length);
10344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != ref->extent_length) {
10345 if (err > 0)
10346 err = AVERROR_INVALIDDATA;
10347 goto fail;
10348 }
10349
10350 // HEIF spec states that Exif metadata is informative. The irot item property is
10351 // the normative source of rotation information. So we remove any Orientation tag
10352 // present in the Exif buffer.
10353 2 err = av_exif_parse_buffer(s, buf->data, ref->extent_length, &ifd, AV_EXIF_T_OFF);
10354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0) {
10355 av_log(s, AV_LOG_ERROR, "Unable to parse Exif metadata\n");
10356 goto fail;
10357 }
10358
10359 2 err = av_exif_remove_entry(s, &ifd, orientation_id, 0);
10360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
10361 goto fail;
10362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (!err)
10363 goto finish;
10364
10365 2 av_buffer_unref(&buf);
10366 2 err = av_exif_write(s, &ifd, &buf, AV_EXIF_T_OFF);
10367
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
10368 goto fail;
10369
10370 2 finish:
10371 2 offset = AV_RB32(buf->data) + 4;
10372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset >= buf->size) {
10373 err = AVERROR_INVALIDDATA;
10374 goto fail;
10375 }
10376 2 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
10377 2 AV_PKT_DATA_EXIF, buf->size - offset, 0);
10378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!sd) {
10379 err = AVERROR(ENOMEM);
10380 goto fail;
10381 }
10382 2 memcpy(sd->data, buf->data + offset, buf->size - offset);
10383
10384 2 err = 0;
10385 2 fail:
10386 2 av_buffer_unref(&buf);
10387 2 av_exif_free(&ifd);
10388 2 avio_seek(s->pb, pos, SEEK_SET);
10389
10390 2 return err;
10391 }
10392
10393 6 static int mov_parse_tiles(AVFormatContext *s)
10394 {
10395 6 MOVContext *mov = s->priv_data;
10396
10397
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (int i = 0; i < mov->nb_heif_grid; i++) {
10398 6 AVStreamGroup *stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
10399 AVStreamGroupTileGrid *tile_grid;
10400 6 const HEIFGrid *grid = &mov->heif_grid[i];
10401 6 int err, loop = 1;
10402
10403
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!stg)
10404 return AVERROR(ENOMEM);
10405
10406 6 stg->id = grid->item->item_id;
10407 6 tile_grid = stg->params.tile_grid;
10408
10409
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (int j = 0; j < grid->nb_tiles; j++) {
10410 16 int tile_id = grid->tile_id_list[j];
10411 int k;
10412
10413
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 for (k = 0; k < mov->nb_heif_item; k++) {
10414 30 HEIFItem *item = mov->heif_item[k];
10415 AVStream *st;
10416
10417
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)
10418 14 continue;
10419 16 st = item->st;
10420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!st) {
10421 av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
10422 "reference a stream\n",
10423 tile_id, grid->item->item_id);
10424 ff_remove_stream_group(s, stg);
10425 loop = 0;
10426 break;
10427 }
10428
10429 16 grid->tile_item_list[j] = item;
10430 16 grid->tile_idx_list[j] = stg->nb_streams;
10431
10432 16 err = avformat_stream_group_add_stream(stg, st);
10433
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (err < 0) {
10434 int l;
10435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
10436 return err;
10437
10438
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_streams; l++)
10439
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->streams[l]->index == st->index)
10440 2 break;
10441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_streams);
10442 2 grid->tile_idx_list[j] = l;
10443 }
10444
10445
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
16 if (item->item_id != mov->primary_item_id)
10446 10 st->disposition |= AV_DISPOSITION_DEPENDENT;
10447 16 break;
10448 }
10449
10450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (k == mov->nb_heif_item) {
10451 av_assert0(loop);
10452 av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
10453 "exist\n",
10454 tile_id, grid->item->item_id);
10455 ff_remove_stream_group(s, stg);
10456 loop = 0;
10457 }
10458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!loop)
10459 break;
10460 }
10461
10462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!loop)
10463 continue;
10464
10465
2/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
6 switch (grid->item->type) {
10466 2 case MKTAG('g','r','i','d'):
10467 2 err = read_image_grid(s, grid, tile_grid);
10468 2 break;
10469 4 case MKTAG('i','o','v','l'):
10470 4 err = read_image_iovl(s, grid, tile_grid);
10471 4 break;
10472 default:
10473 av_assert0(0);
10474 }
10475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10476 return err;
10477
10478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 for (int j = 0; j < grid->item->nb_iref_list; j++) {
10479 HEIFItem *ref = get_heif_item(mov, grid->item->iref_list[j].item_id);
10480
10481 av_assert0(ref);
10482 switch(ref->type) {
10483 case MKTAG('E','x','i','f'):
10484 err = mov_parse_exif_item(s, &tile_grid->coded_side_data,
10485 &tile_grid->nb_coded_side_data, ref);
10486 if (err < 0 && (s->error_recognition & AV_EF_EXPLODE))
10487 return err;
10488 break;
10489 default:
10490 break;
10491 }
10492 }
10493
10494 /* rotation */
10495
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->item->rotation || grid->item->hflip || grid->item->vflip) {
10496 err = set_display_matrix_from_item(&tile_grid->coded_side_data,
10497 &tile_grid->nb_coded_side_data, grid->item);
10498 if (err < 0)
10499 return err;
10500 }
10501
10502 /* ICC profile */
10503
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (grid->item->icc_profile_size) {
10504 err = set_icc_profile_from_item(&tile_grid->coded_side_data,
10505 &tile_grid->nb_coded_side_data, grid->item);
10506 if (err < 0)
10507 return err;
10508 }
10509
10510
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (grid->item->name)
10511 6 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
10512
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (grid->item->item_id == mov->primary_item_id)
10513 2 stg->disposition |= AV_DISPOSITION_DEFAULT;
10514 }
10515
10516 6 return 0;
10517 }
10518
10519 15 static int mov_parse_heif_items(AVFormatContext *s)
10520 {
10521 15 MOVContext *mov = s->priv_data;
10522 int err;
10523
10524
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 15 times.
57 for (int i = 0; i < mov->nb_heif_item; i++) {
10525 42 HEIFItem *item = mov->heif_item[i];
10526 MOVStreamContext *sc;
10527 AVStream *st;
10528 42 int64_t offset = 0;
10529
10530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!item)
10531 continue;
10532
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 31 times.
42 if (!item->st) {
10533 11 continue;
10534 }
10535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (item->is_idat_relative) {
10536 if (!mov->idat_offset) {
10537 av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
10538 return AVERROR_INVALIDDATA;
10539 }
10540 offset = mov->idat_offset;
10541 }
10542
10543 31 st = item->st;
10544 31 sc = st->priv_data;
10545 31 st->codecpar->width = item->width;
10546 31 st->codecpar->height = item->height;
10547
10548 31 sc->sample_size = sc->stsz_sample_size = item->extent_length;
10549 31 sc->sample_count = 1;
10550
10551 31 err = sanity_checks(s, sc, st->index);
10552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (err)
10553 return AVERROR_INVALIDDATA;
10554
10555 31 sc->chunk_offsets[0] = item->extent_offset + offset;
10556
10557
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 18 times.
31 if (item->item_id == mov->primary_item_id)
10558 13 st->disposition |= AV_DISPOSITION_DEFAULT;
10559
10560
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 31 times.
42 for (int j = 0; j < item->nb_iref_list; j++) {
10561 11 HEIFItem *ref = get_heif_item(mov, item->iref_list[j].item_id);
10562
10563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 av_assert0(ref);
10564
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 switch(ref->type) {
10565 2 case MKTAG('E','x','i','f'):
10566 2 err = mov_parse_exif_item(s, &st->codecpar->coded_side_data,
10567 2 &st->codecpar->nb_coded_side_data, ref);
10568
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (err < 0 && (s->error_recognition & AV_EF_EXPLODE))
10569 return err;
10570 2 break;
10571 9 default:
10572 9 break;
10573 }
10574 }
10575
10576
4/6
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 25 times.
31 if (item->rotation || item->hflip || item->vflip) {
10577 6 err = set_display_matrix_from_item(&st->codecpar->coded_side_data,
10578 6 &st->codecpar->nb_coded_side_data, item);
10579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10580 return err;
10581 }
10582
10583 31 mov_build_index(mov, st);
10584 }
10585
10586
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
15 if (mov->nb_heif_grid) {
10587 6 err = mov_parse_tiles(s);
10588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10589 return err;
10590 }
10591
10592 15 return 0;
10593 }
10594
10595 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
10596 int first_index)
10597 {
10598 MOVStreamContext *sc = st->priv_data;
10599
10600 if (sc->tref_id < 0)
10601 return NULL;
10602
10603 for (int i = first_index; i < s->nb_streams; i++)
10604 if (s->streams[i]->id == sc->tref_id)
10605 return s->streams[i];
10606
10607 return NULL;
10608 }
10609
10610 509 static int mov_parse_lcevc_streams(AVFormatContext *s)
10611 {
10612 int err;
10613
10614
2/2
✓ Branch 0 taken 697 times.
✓ Branch 1 taken 509 times.
1206 for (int i = 0; i < s->nb_streams; i++) {
10615 AVStreamGroup *stg;
10616 697 AVStream *st = s->streams[i];
10617 AVStream *st_base;
10618 697 MOVStreamContext *sc = st->priv_data;
10619 697 int j = 0;
10620
10621 /* Find an enhancement stream. */
10622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 697 times.
697 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC ||
10623 !(sc->tref_flags & MOV_TREF_FLAG_ENHANCEMENT))
10624 697 continue;
10625
10626 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10627
10628 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
10629 if (!stg)
10630 return AVERROR(ENOMEM);
10631
10632 stg->id = st->id;
10633 stg->params.lcevc->width = st->codecpar->width;
10634 stg->params.lcevc->height = st->codecpar->height;
10635 st->codecpar->width = 0;
10636 st->codecpar->height = 0;
10637
10638 while (st_base = mov_find_reference_track(s, st, j)) {
10639 err = avformat_stream_group_add_stream(stg, st_base);
10640 if (err < 0)
10641 return err;
10642
10643 j = st_base->index + 1;
10644 }
10645 if (!j) {
10646 av_log(s, AV_LOG_ERROR, "Failed to find base stream for enhancement stream\n");
10647 return AVERROR_INVALIDDATA;
10648 }
10649
10650 err = avformat_stream_group_add_stream(stg, st);
10651 if (err < 0)
10652 return err;
10653
10654 stg->params.lcevc->lcevc_index = stg->nb_streams - 1;
10655 }
10656
10657 509 return 0;
10658 }
10659
10660 509 static void fix_stream_ids(AVFormatContext *s)
10661 {
10662 509 int highest_id = 0;
10663
10664
2/2
✓ Branch 0 taken 697 times.
✓ Branch 1 taken 509 times.
1206 for (int i = 0; i < s->nb_streams; i++) {
10665 697 const AVStream *st = s->streams[i];
10666 697 const MOVStreamContext *sc = st->priv_data;
10667
2/2
✓ Branch 0 taken 647 times.
✓ Branch 1 taken 50 times.
697 if (!sc->iamf)
10668 647 highest_id = FFMAX(highest_id, st->id);
10669 }
10670 509 highest_id += !highest_id;
10671
4/4
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 417 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 92 times.
519 for (int i = 0; highest_id > 1 && i < s->nb_stream_groups; i++) {
10672 10 AVStreamGroup *stg = s->stream_groups[i];
10673
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
10674 8 continue;
10675
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_streams; j++) {
10676 14 AVStream *st = stg->streams[j];
10677 14 MOVStreamContext *sc = st->priv_data;
10678 14 st->id += highest_id;
10679 14 sc->iamf_stream_offset = highest_id;
10680 }
10681 }
10682 509 }
10683
10684 509 static int mov_read_header(AVFormatContext *s)
10685 {
10686 509 MOVContext *mov = s->priv_data;
10687 509 AVIOContext *pb = s->pb;
10688 int j, err;
10689 509 MOVAtom atom = { AV_RL32("root") };
10690 int i;
10691
10692
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 506 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
509 if (mov->decryption_key_len != 0 && mov->decryption_key_len != AES_CTR_KEY_SIZE) {
10693 av_log(s, AV_LOG_ERROR, "Invalid decryption key len %d expected %d\n",
10694 mov->decryption_key_len, AES_CTR_KEY_SIZE);
10695 return AVERROR(EINVAL);
10696 }
10697
10698 509 mov->fc = s;
10699 509 mov->trak_index = -1;
10700 509 mov->primary_item_id = -1;
10701 509 mov->cur_item_id = -1;
10702 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
10703
2/2
✓ Branch 0 taken 508 times.
✓ Branch 1 taken 1 times.
509 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
10704 508 atom.size = avio_size(pb);
10705 else
10706 1 atom.size = INT64_MAX;
10707
10708 /* check MOV header */
10709 do {
10710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 509 times.
509 if (mov->moov_retry)
10711 avio_seek(pb, 0, SEEK_SET);
10712
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 509 times.
509 if ((err = mov_read_default(mov, pb, atom)) < 0) {
10713 av_log(s, AV_LOG_ERROR, "error reading header\n");
10714 return err;
10715 }
10716 1017 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10717
6/10
✓ Branch 0 taken 508 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 493 times.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 15 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
509 !mov->found_moov && (!mov->found_iloc || !mov->found_iinf) && !mov->moov_retry++);
10718
3/6
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 494 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
509 if (!mov->found_moov && !mov->found_iloc && !mov->found_iinf) {
10719 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
10720 return AVERROR_INVALIDDATA;
10721 }
10722 509 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
10723
10724
3/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 494 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
509 if (mov->found_iloc && mov->found_iinf) {
10725 15 err = mov_parse_heif_items(s);
10726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (err < 0)
10727 return err;
10728 }
10729 // prevent iloc and iinf boxes from being parsed while reading packets.
10730 // this is needed because an iinf box may have been parsed but ignored
10731 // for having old infe boxes which create no streams.
10732 509 mov->found_iloc = mov->found_iinf = 1;
10733
10734
2/2
✓ Branch 0 taken 508 times.
✓ Branch 1 taken 1 times.
509 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
10735
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 506 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
508 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
10736 2 mov_read_chapters(s);
10737
2/2
✓ Branch 0 taken 696 times.
✓ Branch 1 taken 508 times.
1204 for (i = 0; i < s->nb_streams; i++)
10738
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 677 times.
696 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
10739 19 mov_read_timecode_track(s, s->streams[i]);
10740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 677 times.
677 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
10741 mov_read_rtmd_track(s, s->streams[i]);
10742 }
10743 }
10744
10745 /* copy timecode metadata from tmcd tracks to the related video streams */
10746
2/2
✓ Branch 0 taken 697 times.
✓ Branch 1 taken 509 times.
1206 for (i = 0; i < s->nb_streams; i++) {
10747 697 AVStream *st = s->streams[i];
10748 697 MOVStreamContext *sc = st->priv_data;
10749
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 679 times.
697 if (sc->timecode_track > 0) {
10750 AVDictionaryEntry *tcr;
10751 18 int tmcd_st_id = -1;
10752
10753
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 18 times.
66 for (j = 0; j < s->nb_streams; j++) {
10754 48 MOVStreamContext *sc2 = s->streams[j]->priv_data;
10755
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 30 times.
48 if (sc2->id == sc->timecode_track)
10756 18 tmcd_st_id = j;
10757 }
10758
10759
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)
10760 continue;
10761 18 tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
10762
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 if (tcr)
10763 16 av_dict_set(&st->metadata, "timecode", tcr->value, 0);
10764 }
10765 }
10766 509 export_orphan_timecode(s);
10767
10768 /* Create LCEVC stream groups. */
10769 509 err = mov_parse_lcevc_streams(s);
10770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 509 times.
509 if (err < 0)
10771 return err;
10772
10773
2/2
✓ Branch 0 taken 697 times.
✓ Branch 1 taken 509 times.
1206 for (i = 0; i < s->nb_streams; i++) {
10774 697 AVStream *st = s->streams[i];
10775 697 FFStream *const sti = ffstream(st);
10776 697 MOVStreamContext *sc = st->priv_data;
10777 697 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
10778 697 fix_timescale(mov, sc);
10779
10780 /* Set the primary extradata based on the first Sample if it doesn't reference the first stsd entry. */
10781
6/6
✓ Branch 0 taken 658 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 627 times.
✓ Branch 3 taken 31 times.
✓ Branch 4 taken 577 times.
✓ Branch 5 taken 50 times.
697 if (sc->stsc_count && sc->extradata_size && !sc->iamf &&
10782
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 574 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
577 sc->stsc_data[0].id > 1 && sc->stsc_data[0].id <= sc->stsd_count) {
10783 3 sc->last_stsd_index = sc->stsc_data[0].id - 1;
10784 3 av_freep(&st->codecpar->extradata);
10785 3 st->codecpar->extradata_size = sc->extradata_size[sc->last_stsd_index];
10786
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (sc->extradata_size[sc->last_stsd_index]) {
10787 3 st->codecpar->extradata = av_mallocz(sc->extradata_size[sc->last_stsd_index] + AV_INPUT_BUFFER_PADDING_SIZE);
10788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata)
10789 return AVERROR(ENOMEM);
10790 3 memcpy(st->codecpar->extradata, sc->extradata[sc->last_stsd_index], sc->extradata_size[sc->last_stsd_index]);
10791 }
10792 }
10793
10794
2/2
✓ Branch 0 taken 283 times.
✓ Branch 1 taken 414 times.
697 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
10795
2/2
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 165 times.
283 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
10796 118 sti->skip_samples = sc->start_pad;
10797 }
10798
5/6
✓ Branch 0 taken 359 times.
✓ Branch 1 taken 338 times.
✓ Branch 2 taken 314 times.
✓ Branch 3 taken 45 times.
✓ Branch 4 taken 314 times.
✗ Branch 5 not taken.
697 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
10799 314 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
10800 314 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
10801
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 685 times.
697 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
10802
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
12 if (st->codecpar->width <= 0 || st->codecpar->height <= 0) {
10803 8 st->codecpar->width = sc->width;
10804 8 st->codecpar->height = sc->height;
10805 }
10806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
10807 st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
10808
10809 for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
10810 dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
10811
10812 err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
10813 if (err < 0)
10814 return err;
10815
10816 av_freep(&st->codecpar->extradata);
10817 st->codecpar->extradata_size = 0;
10818
10819 err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
10820 st->codecpar);
10821 if (err < 0)
10822 return err;
10823 }
10824 }
10825
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 697 times.
697 if (mov->handbrake_version &&
10826 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
10827 st->codecpar->codec_id == AV_CODEC_ID_MP3) {
10828 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
10829 sti->need_parsing = AVSTREAM_PARSE_FULL;
10830 }
10831 }
10832
10833
3/4
✓ Branch 0 taken 493 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 493 times.
509 if (mov->trex_data || mov->use_mfra_for > 0) {
10834
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 16 times.
40 for (i = 0; i < s->nb_streams; i++) {
10835 24 AVStream *st = s->streams[i];
10836 24 MOVStreamContext *sc = st->priv_data;
10837
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 3 times.
24 if (sc->duration_for_fps > 0) {
10838 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
10839 21 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
10840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (st->codecpar->bit_rate == INT64_MIN) {
10841 av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
10842 sc->data_size, sc->time_scale);
10843 st->codecpar->bit_rate = 0;
10844 if (s->error_recognition & AV_EF_EXPLODE)
10845 return AVERROR_INVALIDDATA;
10846 }
10847 }
10848 }
10849 }
10850
10851
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 509 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
509 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
10852 if (mov->bitrates[i]) {
10853 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
10854 }
10855 }
10856
10857 509 ff_rfps_calculate(s);
10858
10859
2/2
✓ Branch 0 taken 697 times.
✓ Branch 1 taken 509 times.
1206 for (i = 0; i < s->nb_streams; i++) {
10860 697 AVStream *st = s->streams[i];
10861 697 MOVStreamContext *sc = st->priv_data;
10862
10863
3/3
✓ Branch 0 taken 283 times.
✓ Branch 1 taken 359 times.
✓ Branch 2 taken 55 times.
697 switch (st->codecpar->codec_type) {
10864 283 case AVMEDIA_TYPE_AUDIO:
10865 283 err = ff_replaygain_export(st, s->metadata);
10866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 283 times.
283 if (err < 0)
10867 return err;
10868 283 break;
10869 359 case AVMEDIA_TYPE_VIDEO:
10870
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 351 times.
359 if (sc->display_matrix) {
10871
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,
10872 AV_PKT_DATA_DISPLAYMATRIX,
10873 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
10874 return AVERROR(ENOMEM);
10875
10876 8 sc->display_matrix = NULL;
10877 }
10878
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 355 times.
359 if (sc->stereo3d) {
10879
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,
10880 AV_PKT_DATA_STEREO3D,
10881 4 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
10882 return AVERROR(ENOMEM);
10883
10884 4 sc->stereo3d = NULL;
10885 }
10886
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 355 times.
359 if (sc->spherical) {
10887
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,
10888 AV_PKT_DATA_SPHERICAL,
10889 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
10890 return AVERROR(ENOMEM);
10891
10892 4 sc->spherical = NULL;
10893 }
10894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 359 times.
359 if (sc->mastering) {
10895 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10896 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
10897 (uint8_t *)sc->mastering, sc->mastering_size, 0))
10898 return AVERROR(ENOMEM);
10899
10900 sc->mastering = NULL;
10901 }
10902
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 359 times.
359 if (sc->coll) {
10903 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10904 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
10905 (uint8_t *)sc->coll, sc->coll_size, 0))
10906 return AVERROR(ENOMEM);
10907
10908 sc->coll = NULL;
10909 }
10910
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 355 times.
359 if (sc->ambient) {
10911
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,
10912 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
10913 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
10914 return AVERROR(ENOMEM);
10915
10916 4 sc->ambient = NULL;
10917 }
10918 359 break;
10919 }
10920 }
10921
10922 509 fix_stream_ids(s);
10923
10924 509 ff_configure_buffers_for_index(s, AV_TIME_BASE);
10925
10926
2/2
✓ Branch 0 taken 468 times.
✓ Branch 1 taken 509 times.
977 for (i = 0; i < mov->frag_index.nb_items; i++)
10927
2/2
✓ Branch 0 taken 464 times.
✓ Branch 1 taken 4 times.
468 if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset)
10928 464 mov->frag_index.item[i].headers_read = 1;
10929
10930 509 return 0;
10931 }
10932
10933 106503 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
10934 {
10935 106503 AVIndexEntry *sample = NULL;
10936 106503 int64_t best_dts = INT64_MAX;
10937 int i;
10938 106503 MOVContext *mov = s->priv_data;
10939
3/4
✓ Branch 0 taken 106503 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 106458 times.
106503 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
10940
2/2
✓ Branch 0 taken 138910 times.
✓ Branch 1 taken 106503 times.
245413 for (i = 0; i < s->nb_streams; i++) {
10941 138910 AVStream *avst = s->streams[i];
10942 138910 FFStream *const avsti = ffstream(avst);
10943 138910 MOVStreamContext *msc = avst->priv_data;
10944
4/4
✓ Branch 0 taken 130672 times.
✓ Branch 1 taken 8238 times.
✓ Branch 2 taken 127349 times.
✓ Branch 3 taken 3323 times.
138910 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
10945 127349 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
10946 127349 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
10947
2/2
✓ Branch 0 taken 112403 times.
✓ Branch 1 taken 14946 times.
127349 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
10948 127349 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
10949
3/6
✓ Branch 0 taken 21352 times.
✓ Branch 1 taken 105997 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 21352 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
127349 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
10950
1/2
✓ Branch 0 taken 21352 times.
✗ Branch 1 not taken.
21352 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10951
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 21352 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 21352 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 21352 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19139 times.
✓ Branch 9 taken 2213 times.
21352 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
10952
4/4
✓ Branch 0 taken 10996 times.
✓ Branch 1 taken 8143 times.
✓ Branch 2 taken 2213 times.
✓ Branch 3 taken 10996 times.
21352 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
10953
3/4
✓ Branch 0 taken 762 times.
✓ Branch 1 taken 1451 times.
✓ Branch 2 taken 762 times.
✗ Branch 3 not taken.
2213 (dtsdiff > AV_TIME_BASE && dts < best_dts && mov->interleaved_read)))))) {
10954 114902 sample = current_sample;
10955 114902 best_dts = dts;
10956 114902 *st = avst;
10957 }
10958 }
10959 }
10960 106503 return sample;
10961 }
10962
10963 9 static int should_retry(AVIOContext *pb, int error_code) {
10964
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))
10965 9 return 0;
10966
10967 return 1;
10968 }
10969
10970 43 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
10971 {
10972 int ret;
10973 43 MOVContext *mov = s->priv_data;
10974
10975
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
43 if (index >= 0 && index < mov->frag_index.nb_items)
10976 target = mov->frag_index.item[index].moof_offset;
10977
2/4
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
43 if (target >= 0 && avio_seek(s->pb, target, SEEK_SET) != target) {
10978 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
10979 return AVERROR_INVALIDDATA;
10980 }
10981
10982 43 mov->next_root_atom = 0;
10983
2/6
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 43 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
43 if ((index < 0 && target >= 0) || index >= mov->frag_index.nb_items)
10984 43 index = search_frag_moof_offset(&mov->frag_index, target);
10985
3/4
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 5 times.
43 if (index >= 0 && index < mov->frag_index.nb_items &&
10986
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 mov->frag_index.item[index].moof_offset == target) {
10987
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (index + 1 < mov->frag_index.nb_items)
10988 35 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
10989
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (mov->frag_index.item[index].headers_read)
10990 35 return 0;
10991 3 mov->frag_index.item[index].headers_read = 1;
10992 }
10993
10994 8 mov->found_mdat = 0;
10995
10996 8 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
10997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ret < 0)
10998 return ret;
10999
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 3 times.
8 if (avio_feof(s->pb))
11000 5 return AVERROR_EOF;
11001 3 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
11002
11003 3 return 1;
11004 }
11005
11006 15 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
11007 {
11008 15 MOVStreamContext *sc = st->priv_data;
11009 uint8_t *side, *extradata;
11010 int extradata_size;
11011
11012 /* Save the current index. */
11013 15 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
11014
11015 /* Notify the decoder that extradata changed. */
11016 15 extradata_size = sc->extradata_size[sc->last_stsd_index];
11017 15 extradata = sc->extradata[sc->last_stsd_index];
11018
4/6
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
15 if (st->discard != AVDISCARD_ALL && extradata_size > 0 && extradata) {
11019 12 side = av_packet_new_side_data(pkt,
11020 AV_PKT_DATA_NEW_EXTRADATA,
11021 extradata_size);
11022
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!side)
11023 return AVERROR(ENOMEM);
11024 12 memcpy(side, extradata, extradata_size);
11025 }
11026
11027 15 return 0;
11028 }
11029
11030 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
11031 {
11032 /* We can't make assumptions about the structure of the payload,
11033 because it may include multiple cdat and cdt2 samples. */
11034 const uint32_t cdat = AV_RB32("cdat");
11035 const uint32_t cdt2 = AV_RB32("cdt2");
11036 int ret, out_size = 0;
11037
11038 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
11039 if (src_size < 10)
11040 return AVERROR_INVALIDDATA;
11041
11042 /* avoid an int overflow: */
11043 if ((src_size - 8) / 2 >= INT_MAX / 3)
11044 return AVERROR_INVALIDDATA;
11045
11046 ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
11047 if (ret < 0)
11048 return ret;
11049
11050 /* parse and re-format the c608 payload in one pass. */
11051 while (src_size >= 10) {
11052 const uint32_t atom_size = avio_rb32(pb);
11053 const uint32_t atom_type = avio_rb32(pb);
11054 const uint32_t data_size = atom_size - 8;
11055 const uint8_t cc_field =
11056 atom_type == cdat ? 1 :
11057 atom_type == cdt2 ? 2 :
11058 0;
11059
11060 /* account for bytes consumed for atom size and type. */
11061 src_size -= 8;
11062
11063 /* make sure the data size stays within the buffer boundaries. */
11064 if (data_size < 2 || data_size > src_size) {
11065 ret = AVERROR_INVALIDDATA;
11066 break;
11067 }
11068
11069 /* make sure the data size is consistent with N byte pairs. */
11070 if (data_size % 2 != 0) {
11071 ret = AVERROR_INVALIDDATA;
11072 break;
11073 }
11074
11075 if (!cc_field) {
11076 /* neither cdat or cdt2 ... skip it */
11077 avio_skip(pb, data_size);
11078 src_size -= data_size;
11079 continue;
11080 }
11081
11082 for (uint32_t i = 0; i < data_size; i += 2) {
11083 pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
11084 pkt->data[out_size + 1] = avio_r8(pb);
11085 pkt->data[out_size + 2] = avio_r8(pb);
11086 out_size += 3;
11087 src_size -= 2;
11088 }
11089 }
11090
11091 if (src_size > 0)
11092 /* skip any remaining unread portion of the input payload */
11093 avio_skip(pb, src_size);
11094
11095 av_shrink_packet(pkt, out_size);
11096 return ret;
11097 }
11098
11099 105953 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
11100 int64_t current_index, AVPacket *pkt)
11101 {
11102 105953 MOVStreamContext *sc = st->priv_data;
11103
11104 105953 pkt->stream_index = sc->ffindex;
11105 105953 pkt->dts = sample->timestamp;
11106
2/2
✓ Branch 0 taken 237 times.
✓ Branch 1 taken 105716 times.
105953 if (sample->flags & AVINDEX_DISCARD_FRAME) {
11107 237 pkt->flags |= AV_PKT_FLAG_DISCARD;
11108 }
11109
4/4
✓ Branch 0 taken 86068 times.
✓ Branch 1 taken 19885 times.
✓ Branch 2 taken 86056 times.
✓ Branch 3 taken 12 times.
105953 if (sc->stts_count && sc->tts_index < sc->tts_count)
11110 86056 pkt->duration = sc->tts_data[sc->tts_index].duration;
11111
3/4
✓ Branch 0 taken 4194 times.
✓ Branch 1 taken 101759 times.
✓ Branch 2 taken 4194 times.
✗ Branch 3 not taken.
105953 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
11112 4194 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
11113 } else {
11114
2/2
✓ Branch 0 taken 15810 times.
✓ Branch 1 taken 85949 times.
101759 if (pkt->duration == 0) {
11115 15810 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
11116
2/2
✓ Branch 0 taken 15729 times.
✓ Branch 1 taken 81 times.
15810 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
11117
2/2
✓ Branch 0 taken 15776 times.
✓ Branch 1 taken 34 times.
15810 if (next_dts >= pkt->dts)
11118 15776 pkt->duration = next_dts - pkt->dts;
11119 }
11120 101759 pkt->pts = pkt->dts;
11121 }
11122
11123
4/4
✓ Branch 0 taken 86068 times.
✓ Branch 1 taken 19885 times.
✓ Branch 2 taken 86056 times.
✓ Branch 3 taken 12 times.
105953 if (sc->tts_data && sc->tts_index < sc->tts_count) {
11124 /* update tts context */
11125 86056 sc->tts_sample++;
11126
1/2
✓ Branch 0 taken 86056 times.
✗ Branch 1 not taken.
86056 if (sc->tts_index < sc->tts_count &&
11127
1/2
✓ Branch 0 taken 86056 times.
✗ Branch 1 not taken.
86056 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
11128 86056 sc->tts_index++;
11129 86056 sc->tts_sample = 0;
11130 }
11131 }
11132
11133
4/4
✓ Branch 0 taken 1043 times.
✓ Branch 1 taken 104910 times.
✓ Branch 2 taken 911 times.
✓ Branch 3 taken 132 times.
105953 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
11134 911 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
11135 911 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
11136
2/2
✓ Branch 0 taken 315 times.
✓ Branch 1 taken 596 times.
911 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
11137 }
11138 105953 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
11139 105953 pkt->pos = sample->pos;
11140
11141 /* Multiple stsd handling. */
11142
2/2
✓ Branch 0 taken 102714 times.
✓ Branch 1 taken 3239 times.
105953 if (sc->stsc_data) {
11143
1/2
✓ Branch 0 taken 102714 times.
✗ Branch 1 not taken.
102714 if (sc->stsc_data[sc->stsc_index].id > 0 &&
11144
2/2
✓ Branch 0 taken 102683 times.
✓ Branch 1 taken 31 times.
102714 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
11145
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 102668 times.
102683 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
11146 15 int ret = mov_change_extradata(st, pkt);
11147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (ret < 0)
11148 return ret;
11149 }
11150
11151 /* Update the stsc index for the next sample */
11152 102714 sc->stsc_sample++;
11153
2/2
✓ Branch 1 taken 55180 times.
✓ Branch 2 taken 47534 times.
102714 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
11154
2/2
✓ Branch 1 taken 1192 times.
✓ Branch 2 taken 53988 times.
55180 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
11155 1192 sc->stsc_index++;
11156 1192 sc->stsc_sample = 0;
11157 }
11158 }
11159
11160 105953 return 0;
11161 }
11162
11163 97373 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
11164 {
11165 97373 MOVContext *mov = s->priv_data;
11166 MOVStreamContext *sc;
11167 AVIndexEntry *sample;
11168 97373 AVStream *st = NULL;
11169 97373 FFStream *avsti = NULL;
11170 int64_t current_index;
11171 int ret;
11172 int i;
11173 97373 mov->fc = s;
11174 9130 retry:
11175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106503 times.
106503 if (s->pb->pos == 0) {
11176
11177 // Discard current fragment index
11178 if (mov->frag_index.allocated_size > 0) {
11179 for(int i = 0; i < mov->frag_index.nb_items; i++) {
11180 av_freep(&mov->frag_index.item[i].stream_info);
11181 }
11182 av_freep(&mov->frag_index.item);
11183 mov->frag_index.nb_items = 0;
11184 mov->frag_index.allocated_size = 0;
11185 mov->frag_index.current = -1;
11186 mov->frag_index.complete = 0;
11187 }
11188
11189 for (i = 0; i < s->nb_streams; i++) {
11190 AVStream *avst = s->streams[i];
11191 MOVStreamContext *msc = avst->priv_data;
11192
11193 // Clear current sample
11194 mov_current_sample_set(msc, 0);
11195 msc->tts_index = 0;
11196
11197 // Discard current index entries
11198 avsti = ffstream(avst);
11199 if (avsti->index_entries_allocated_size > 0) {
11200 av_freep(&avsti->index_entries);
11201 avsti->index_entries_allocated_size = 0;
11202 avsti->nb_index_entries = 0;
11203 }
11204 }
11205
11206 if ((ret = mov_switch_root(s, -1, -1)) < 0)
11207 return ret;
11208 }
11209 106503 sample = mov_find_next_sample(s, &st);
11210
6/6
✓ Branch 0 taken 105997 times.
✓ Branch 1 taken 506 times.
✓ Branch 2 taken 516 times.
✓ Branch 3 taken 105481 times.
✓ Branch 4 taken 35 times.
✓ Branch 5 taken 481 times.
106503 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
11211
2/2
✓ Branch 0 taken 498 times.
✓ Branch 1 taken 43 times.
541 if (!mov->next_root_atom)
11212 498 return AVERROR_EOF;
11213
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 38 times.
43 if ((ret = mov_switch_root(s, mov->next_root_atom, -1)) < 0)
11214 5 return ret;
11215 38 goto retry;
11216 }
11217 105962 sc = st->priv_data;
11218 /* must be done just before reading, to avoid infinite loop on sample */
11219 105962 current_index = sc->current_index;
11220 105962 mov_current_sample_inc(sc);
11221
11222
2/2
✓ Branch 0 taken 481 times.
✓ Branch 1 taken 105481 times.
105962 if (mov->next_root_atom) {
11223 481 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
11224 481 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
11225 }
11226
11227
2/2
✓ Branch 0 taken 96870 times.
✓ Branch 1 taken 9092 times.
105962 if (st->discard != AVDISCARD_ALL) {
11228 96870 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
11229
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 96863 times.
96870 if (ret64 != sample->pos) {
11230 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
11231 sc->ffindex, sample->pos);
11232
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
11233 mov_current_sample_dec(sc);
11234
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
11235 7 return (int)ret64;
11236 }
11237 return AVERROR_INVALIDDATA;
11238 }
11239
11240
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96863 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96863 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
11241 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
11242 goto retry;
11243 }
11244
11245
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96863 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96863 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
11246 ret = get_eia608_packet(sc->pb, pkt, sample->size);
11247 #if CONFIG_IAMFDEC
11248
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 96808 times.
96863 else if (sc->iamf) {
11249 int64_t pts, dts, pos, duration;
11250 55 int flags, size = sample->size;
11251 55 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11252 55 pts = pkt->pts; dts = pkt->dts;
11253 55 pos = pkt->pos; flags = pkt->flags;
11254 55 duration = pkt->duration;
11255
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) {
11256 275 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
11257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
275 if (ret < 0) {
11258 if (should_retry(sc->pb, ret))
11259 mov_current_sample_dec(sc);
11260 return ret;
11261 }
11262 275 size -= ret;
11263 275 pkt->pts = pts; pkt->dts = dts;
11264 275 pkt->pos = pos; pkt->flags |= flags;
11265 275 pkt->duration = duration;
11266 275 ret = ff_buffer_packet(s, pkt);
11267 }
11268
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 if (!ret)
11269 55 return FFERROR_REDO;
11270 }
11271 #endif
11272
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 96805 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
96811 else if (st->codecpar->codec_id == AV_CODEC_ID_APV && sample->size > 4) {
11273 3 const uint32_t au_size = avio_rb32(sc->pb);
11274 3 ret = av_get_packet(sc->pb, pkt, au_size);
11275 } else
11276 96805 ret = av_get_packet(sc->pb, pkt, sample->size);
11277
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 96806 times.
96808 if (ret < 0) {
11278
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (should_retry(sc->pb, ret)) {
11279 mov_current_sample_dec(sc);
11280 }
11281 2 return ret;
11282 }
11283 #if CONFIG_DV_DEMUXER
11284
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96806 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96806 if (mov->dv_demux && sc->dv_audio_container) {
11285 ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
11286 av_packet_unref(pkt);
11287 if (ret < 0)
11288 return ret;
11289 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
11290 if (ret < 0)
11291 return ret;
11292 }
11293 #endif
11294
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 96788 times.
96806 if (sc->has_palette) {
11295 uint8_t *pal;
11296
11297 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
11298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
11299 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
11300 } else {
11301 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
11302 18 sc->has_palette = 0;
11303 }
11304 }
11305
4/6
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 96518 times.
✓ Branch 3 taken 288 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 288 times.
✗ Branch 6 not taken.
96806 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
11306
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 288 times.
288 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
11307 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
11308 }
11309 }
11310
11311 105898 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11312
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 105898 times.
105898 if (ret < 0)
11313 return ret;
11314
11315
2/2
✓ Branch 0 taken 9092 times.
✓ Branch 1 taken 96806 times.
105898 if (st->discard == AVDISCARD_ALL)
11316 9092 goto retry;
11317
11318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96806 times.
96806 if (mov->aax_mode)
11319 aax_filter(pkt->data, pkt->size, mov);
11320
11321 96806 ret = cenc_filter(mov, st, sc, pkt, current_index);
11322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96806 times.
96806 if (ret < 0) {
11323 return ret;
11324 }
11325
11326 96806 return 0;
11327 }
11328
11329 361 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
11330 {
11331 361 MOVContext *mov = s->priv_data;
11332 int index;
11333
11334
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 26 times.
361 if (!mov->frag_index.complete)
11335 335 return 0;
11336
11337 26 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
11338
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 22 times.
26 if (index < 0)
11339 4 index = 0;
11340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (!mov->frag_index.item[index].headers_read)
11341 return mov_switch_root(s, -1, index);
11342
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (index + 1 < mov->frag_index.nb_items)
11343 26 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11344
11345 26 return 0;
11346 }
11347
11348 static int is_open_key_sample(const MOVStreamContext *sc, int sample)
11349 {
11350 // TODO: a bisect search would scale much better
11351 for (int i = 0; i < sc->open_key_samples_count; i++) {
11352 const int oks = sc->open_key_samples[i];
11353 if (oks == sample)
11354 return 1;
11355 if (oks > sample) /* list is monotically increasing so we can stop early */
11356 break;
11357 }
11358 return 0;
11359 }
11360
11361 /*
11362 * Some key sample may be key frames but not IDR frames, so a random access to
11363 * them may not be allowed.
11364 */
11365 229 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
11366 {
11367 229 MOVStreamContext *sc = st->priv_data;
11368 229 FFStream *const sti = ffstream(st);
11369 int64_t key_sample_dts, key_sample_pts;
11370
11371
1/2
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
229 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
11372 229 return 1;
11373
11374 if (sample >= sc->sample_offsets_count)
11375 return 1;
11376
11377 key_sample_dts = sti->index_entries[sample].timestamp;
11378 key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
11379
11380 /*
11381 * If the sample needs to be presented before an open key sample, they may
11382 * not be decodable properly, even though they come after in decoding
11383 * order.
11384 */
11385 if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
11386 return 0;
11387
11388 return 1;
11389 }
11390
11391 361 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
11392 {
11393 361 MOVStreamContext *sc = st->priv_data;
11394 361 FFStream *const sti = ffstream(st);
11395 int sample, time_sample, ret, requested_sample;
11396 int64_t next_ts;
11397 unsigned int i;
11398
11399 // Here we consider timestamp to be PTS, hence try to offset it so that we
11400 // can search over the DTS timeline.
11401 361 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
11402
11403 361 ret = mov_seek_fragment(s, st, timestamp);
11404
1/2
✓ Branch 0 taken 361 times.
✗ Branch 1 not taken.
361 if (ret < 0)
11405 return ret;
11406
11407 for (;;) {
11408 361 sample = av_index_search_timestamp(st, timestamp, flags);
11409 361 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
11410
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)
11411 43 sample = 0;
11412
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 335 times.
361 if (sample < 0) /* not sure what to do */
11413 26 return AVERROR_INVALIDDATA;
11414
11415
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))
11416 break;
11417
11418 next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
11419 requested_sample = av_index_search_timestamp(st, next_ts, flags);
11420
11421 // If we've reached a different sample trying to find a good pts to
11422 // seek to, give up searching because we'll end up seeking back to
11423 // sample 0 on every seek.
11424 if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
11425 break;
11426
11427 timestamp = next_ts;
11428 }
11429
11430 335 mov_current_sample_set(sc, sample);
11431 335 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
11432 /* adjust time to sample index */
11433
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 125 times.
335 if (sc->tts_data) {
11434 210 time_sample = 0;
11435
1/2
✓ Branch 0 taken 60235 times.
✗ Branch 1 not taken.
60235 for (i = 0; i < sc->tts_count; i++) {
11436 60235 int next = time_sample + sc->tts_data[i].count;
11437
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 60025 times.
60235 if (next > sc->current_sample) {
11438 210 sc->tts_index = i;
11439 210 sc->tts_sample = sc->current_sample - time_sample;
11440 210 break;
11441 }
11442 60025 time_sample = next;
11443 }
11444 }
11445
11446 /* adjust stsd index */
11447
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 26 times.
335 if (sc->chunk_count) {
11448 309 time_sample = 0;
11449
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
381 for (i = 0; i < sc->stsc_count; i++) {
11450 381 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
11451
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 72 times.
381 if (next > sc->current_sample) {
11452 309 sc->stsc_index = i;
11453 309 sc->stsc_sample = sc->current_sample - time_sample;
11454 309 break;
11455 }
11456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
11457 72 time_sample = next;
11458 }
11459 }
11460
11461 335 return sample;
11462 }
11463
11464 335 static int64_t mov_get_skip_samples(AVStream *st, int sample)
11465 {
11466 335 MOVStreamContext *sc = st->priv_data;
11467 335 FFStream *const sti = ffstream(st);
11468 335 int64_t first_ts = sti->index_entries[0].timestamp;
11469 335 int64_t ts = sti->index_entries[sample].timestamp;
11470 int64_t off;
11471
11472
2/2
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 151 times.
335 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
11473 184 return 0;
11474
11475 /* compute skip samples according to stream start_pad, seek ts and first ts */
11476 151 off = av_rescale_q(ts - first_ts, st->time_base,
11477 151 (AVRational){1, st->codecpar->sample_rate});
11478 151 return FFMAX(sc->start_pad - off, 0);
11479 }
11480
11481 340 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
11482 {
11483 340 MOVContext *mc = s->priv_data;
11484 AVStream *st;
11485 FFStream *sti;
11486 int sample;
11487 int i;
11488
11489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 340 times.
340 if (stream_index >= s->nb_streams)
11490 return AVERROR_INVALIDDATA;
11491
11492 340 st = s->streams[stream_index];
11493 340 sti = ffstream(st);
11494 340 sample = mov_seek_stream(s, st, sample_time, flags);
11495
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 314 times.
340 if (sample < 0)
11496 26 return sample;
11497
11498
1/2
✓ Branch 0 taken 314 times.
✗ Branch 1 not taken.
314 if (mc->seek_individually) {
11499 /* adjust seek timestamp to found sample timestamp */
11500 314 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
11501 314 sti->skip_samples = mov_get_skip_samples(st, sample);
11502
11503
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 314 times.
649 for (i = 0; i < s->nb_streams; i++) {
11504 335 AVStream *const st = s->streams[i];
11505 335 FFStream *const sti = ffstream(st);
11506 int64_t timestamp;
11507
11508
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 21 times.
335 if (stream_index == i)
11509 314 continue;
11510
11511 21 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
11512 21 sample = mov_seek_stream(s, st, timestamp, flags);
11513
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (sample >= 0)
11514 21 sti->skip_samples = mov_get_skip_samples(st, sample);
11515 }
11516 } else {
11517 for (i = 0; i < s->nb_streams; i++) {
11518 MOVStreamContext *sc;
11519 st = s->streams[i];
11520 sc = st->priv_data;
11521 mov_current_sample_set(sc, 0);
11522 }
11523 while (1) {
11524 MOVStreamContext *sc;
11525 AVIndexEntry *entry = mov_find_next_sample(s, &st);
11526 if (!entry)
11527 return AVERROR_INVALIDDATA;
11528 sc = st->priv_data;
11529 if (sc->ffindex == stream_index && sc->current_sample == sample)
11530 break;
11531 mov_current_sample_inc(sc);
11532 }
11533 }
11534 314 return 0;
11535 }
11536
11537 #define OFFSET(x) offsetof(MOVContext, x)
11538 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
11539 static const AVOption mov_options[] = {
11540 {"use_absolute_path",
11541 "allow using absolute path when opening alias, this is a possible security issue",
11542 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
11543 0, 1, FLAGS},
11544 {"seek_streams_individually",
11545 "Seek each stream individually to the closest point",
11546 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
11547 0, 1, FLAGS},
11548 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
11549 0, 1, FLAGS},
11550 {"advanced_editlist",
11551 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
11552 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
11553 0, 1, FLAGS},
11554 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
11555 0, 1, FLAGS},
11556 {"use_mfra_for",
11557 "use mfra for fragment timestamps",
11558 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
11559 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
11560 .unit = "use_mfra_for"},
11561 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
11562 FLAGS, .unit = "use_mfra_for" },
11563 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
11564 FLAGS, .unit = "use_mfra_for" },
11565 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
11566 FLAGS, .unit = "use_mfra_for" },
11567 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
11568 0, 1, FLAGS},
11569 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
11570 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11571 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
11572 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11573 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
11574 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11575 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
11576 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11577 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
11578 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11579 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
11580 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
11581 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
11582 .flags = AV_OPT_FLAG_DECODING_PARAM },
11583 { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11584 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
11585 {.i64 = 0}, 0, 1, FLAGS },
11586 { "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 },
11587 { "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 },
11588
11589 { NULL },
11590 };
11591
11592 static const AVClass mov_class = {
11593 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
11594 .item_name = av_default_item_name,
11595 .option = mov_options,
11596 .version = LIBAVUTIL_VERSION_INT,
11597 };
11598
11599 const FFInputFormat ff_mov_demuxer = {
11600 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
11601 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
11602 .p.priv_class = &mov_class,
11603 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v,avif,heic,heif",
11604 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
11605 .priv_data_size = sizeof(MOVContext),
11606 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
11607 .read_probe = mov_probe,
11608 .read_header = mov_read_header,
11609 .read_packet = mov_read_packet,
11610 .read_close = mov_read_close,
11611 .read_seek = mov_read_seek,
11612 };
11613