FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2025-10-26 07:25:09
Exec Total Coverage
Lines: 4364 6954 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 101 times.
✓ Branch 9 taken 458 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 101 case AV_CODEC_ID_PRORES_RAW:
2994 case AV_CODEC_ID_PRORES:
2995 case AV_CODEC_ID_APV:
2996 case AV_CODEC_ID_EVC:
2997 case AV_CODEC_ID_AV1:
2998 /* field_order detection of H264 requires parsing */
2999 case AV_CODEC_ID_H264:
3000 101 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3001 101 break;
3002 458 default:
3003 458 break;
3004 }
3005 612 return 0;
3006 }
3007
3008 625 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
3009 int codec_tag, int format,
3010 int64_t size)
3011 {
3012
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 &&
3013 (codec_tag != format &&
3014 // AVID 1:1 samples with differing data format and codec tag exist
3015 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
3016 // prores is allowed to have differing data format and codec tag
3017 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
3018 // so is dv (sigh)
3019 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
3020 (c->fc->video_codec_id ? ff_codec_get_id(ff_codec_movvideo_tags, format) != c->fc->video_codec_id
3021 : codec_tag != MKTAG('j','p','e','g')))) {
3022 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3023 * export it as a separate AVStream but this needs a few changes
3024 * in the MOV demuxer, patch welcome. */
3025
3026 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3027 avio_skip(pb, size);
3028 return 1;
3029 }
3030
3031 625 return 0;
3032 }
3033
3034 625 static int mov_finalize_stsd_entry(MOVContext *c, AVStream *st)
3035 {
3036 int ret;
3037
3038 /* special codec parameters handling */
3039
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 550 times.
625 switch (st->codecpar->codec_id) {
3040 75 case AV_CODEC_ID_H264:
3041 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
3042
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)) {
3043 ret = ff_generate_avci_extradata(st);
3044 if (ret < 0)
3045 return ret;
3046 }
3047 75 break;
3048 550 default:
3049 550 break;
3050 }
3051
3052 625 return 0;
3053 }
3054
3055 612 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3056 {
3057 AVStream *st;
3058 MOVStreamContext *sc;
3059 int pseudo_stream_id;
3060
3061
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 av_assert0 (c->fc->nb_streams >= 1);
3062 612 st = c->fc->streams[c->fc->nb_streams-1];
3063 612 sc = st->priv_data;
3064
3065 612 for (pseudo_stream_id = 0;
3066
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;
3067 625 pseudo_stream_id++) {
3068 //Parsing Sample description table
3069 enum AVCodecID id;
3070 625 int ret, dref_id = 1;
3071 625 MOVAtom a = { AV_RL32("stsd") };
3072 625 int64_t start_pos = avio_tell(pb);
3073 625 int64_t size = avio_rb32(pb); /* size */
3074 625 uint32_t format = avio_rl32(pb); /* data format */
3075
3076
1/2
✓ Branch 0 taken 625 times.
✗ Branch 1 not taken.
625 if (size >= 16) {
3077 625 avio_rb32(pb); /* reserved */
3078 625 avio_rb16(pb); /* reserved */
3079 625 dref_id = avio_rb16(pb);
3080 } else if (size <= 7) {
3081 av_log(c->fc, AV_LOG_ERROR,
3082 "invalid size %"PRId64" in stsd\n", size);
3083 return AVERROR_INVALIDDATA;
3084 }
3085
3086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
625 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3087 625 size - (avio_tell(pb) - start_pos))) {
3088 sc->stsd_count++;
3089 continue;
3090 }
3091
3092
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;
3093 625 sc->dref_id= dref_id;
3094 625 sc->format = format;
3095
3096 625 id = mov_codec_id(st, format);
3097
3098 625 av_log(c->fc, AV_LOG_TRACE,
3099 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3100 625 av_fourcc2str(format), st->codecpar->codec_type);
3101
3102 625 st->codecpar->codec_id = id;
3103
2/2
✓ Branch 0 taken 326 times.
✓ Branch 1 taken 299 times.
625 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3104 326 mov_parse_stsd_video(c, pb, st, sc);
3105
2/2
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 56 times.
299 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3106 243 mov_parse_stsd_audio(c, pb, st, sc);
3107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 243 times.
243 if (st->codecpar->sample_rate < 0) {
3108 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3109 return AVERROR_INVALIDDATA;
3110 }
3111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 243 times.
243 if (st->codecpar->ch_layout.nb_channels < 0) {
3112 av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3113 return AVERROR_INVALIDDATA;
3114 }
3115
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 41 times.
56 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3116 15 mov_parse_stsd_subtitle(c, pb, st, sc,
3117 15 size - (avio_tell(pb) - start_pos));
3118 } else {
3119 41 ret = mov_parse_stsd_data(c, pb, st, sc,
3120 41 size - (avio_tell(pb) - start_pos));
3121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ret < 0)
3122 return ret;
3123 }
3124 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3125 625 a.size = size - (avio_tell(pb) - start_pos);
3126
2/2
✓ Branch 0 taken 490 times.
✓ Branch 1 taken 135 times.
625 if (a.size > 8) {
3127
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 490 times.
490 if ((ret = mov_read_default(c, pb, a)) < 0)
3128 return ret;
3129
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 134 times.
135 } else if (a.size > 0)
3130 1 avio_skip(pb, a.size);
3131
3132 625 ret = mov_finalize_stsd_entry(c, st);
3133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
625 if (ret < 0)
3134 return ret;
3135
3136
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) {
3137 350 int extra_size = st->codecpar->extradata_size;
3138
3139 /* Move the current stream extradata to the stream context one. */
3140 350 sc->extradata_size[pseudo_stream_id] = extra_size;
3141 350 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3142 350 st->codecpar->extradata = NULL;
3143 350 st->codecpar->extradata_size = 0;
3144 }
3145 625 sc->stsd_count++;
3146 }
3147
3148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (pb->eof_reached) {
3149 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3150 return AVERROR_EOF;
3151 }
3152
3153 612 return 0;
3154 }
3155
3156 612 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3157 {
3158 AVStream *st;
3159 MOVStreamContext *sc;
3160 int ret, entries;
3161
3162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->fc->nb_streams < 1)
3163 return 0;
3164 612 st = c->fc->streams[c->fc->nb_streams - 1];
3165 612 sc = st->priv_data;
3166
3167 612 sc->stsd_version = avio_r8(pb);
3168 612 avio_rb24(pb); /* flags */
3169 612 entries = avio_rb32(pb);
3170
3171 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3172
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) {
3173 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3174 return AVERROR_INVALIDDATA;
3175 }
3176
3177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (sc->extradata) {
3178 av_log(c->fc, AV_LOG_ERROR,
3179 "Duplicate stsd found in this track.\n");
3180 return AVERROR_INVALIDDATA;
3181 }
3182
3183 /* Prepare space for hosting multiple extradata. */
3184 612 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (!sc->extradata)
3186 return AVERROR(ENOMEM);
3187
3188 612 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (!sc->extradata_size) {
3190 ret = AVERROR(ENOMEM);
3191 goto fail;
3192 }
3193
3194 612 ret = ff_mov_read_stsd_entries(c, pb, entries);
3195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (ret < 0)
3196 goto fail;
3197
3198 /* Restore back the primary extradata. */
3199 612 av_freep(&st->codecpar->extradata);
3200 612 st->codecpar->extradata_size = sc->extradata_size[0];
3201
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 274 times.
612 if (sc->extradata_size[0]) {
3202 338 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
338 if (!st->codecpar->extradata)
3204 return AVERROR(ENOMEM);
3205 338 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3206 }
3207
3208 612 return mov_finalize_stsd_codec(c, pb, st, sc);
3209 fail:
3210 if (sc->extradata) {
3211 int j;
3212 for (j = 0; j < sc->stsd_count; j++)
3213 av_freep(&sc->extradata[j]);
3214 }
3215
3216 av_freep(&sc->extradata);
3217 av_freep(&sc->extradata_size);
3218 return ret;
3219 }
3220
3221 612 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3222 {
3223 AVStream *st;
3224 MOVStreamContext *sc;
3225 unsigned int i, entries;
3226
3227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->trak_index < 0) {
3228 av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3229 return 0;
3230 }
3231
3232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->fc->nb_streams < 1)
3233 return 0;
3234 612 st = c->fc->streams[c->fc->nb_streams-1];
3235 612 sc = st->priv_data;
3236
3237 612 avio_r8(pb); /* version */
3238 612 avio_rb24(pb); /* flags */
3239
3240 612 entries = avio_rb32(pb);
3241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if ((uint64_t)entries * 12 + 4 > atom.size)
3242 return AVERROR_INVALIDDATA;
3243
3244 612 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3245
3246
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 588 times.
612 if (!entries)
3247 24 return 0;
3248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 588 times.
588 if (sc->stsc_data) {
3249 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3250 return 0;
3251 }
3252 588 av_free(sc->stsc_data);
3253 588 sc->stsc_count = 0;
3254 588 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 588 times.
588 if (!sc->stsc_data)
3256 return AVERROR(ENOMEM);
3257
3258
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++) {
3259 3790 sc->stsc_data[i].first = avio_rb32(pb);
3260 3790 sc->stsc_data[i].count = avio_rb32(pb);
3261 3790 sc->stsc_data[i].id = avio_rb32(pb);
3262 }
3263
3264 588 sc->stsc_count = i;
3265
2/2
✓ Branch 0 taken 3790 times.
✓ Branch 1 taken 588 times.
4378 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3266 3790 int64_t first_min = i + 1;
3267
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) ||
3268
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) ||
3269
1/2
✓ Branch 0 taken 3790 times.
✗ Branch 1 not taken.
3790 sc->stsc_data[i].first < first_min ||
3270
1/2
✓ Branch 0 taken 3790 times.
✗ Branch 1 not taken.
3790 sc->stsc_data[i].count < 1 ||
3271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3790 times.
3790 sc->stsc_data[i].id < 1) {
3272 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);
3273 if (i+1 >= sc->stsc_count) {
3274 if (sc->stsc_data[i].count == 0 && i > 0) {
3275 sc->stsc_count --;
3276 continue;
3277 }
3278 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3279 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3280 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3281 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3282 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3283 continue;
3284 }
3285 av_assert0(sc->stsc_data[i+1].first >= 2);
3286 // We replace this entry by the next valid
3287 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3288 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3289 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3290 }
3291 }
3292
3293
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 588 times.
588 if (pb->eof_reached) {
3294 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3295 return AVERROR_EOF;
3296 }
3297
3298 588 return 0;
3299 }
3300
3301 341108 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3302 {
3303 341108 return index < count - 1;
3304 }
3305
3306 /* Compute the samples value for the stsc entry at the given index. */
3307 55530 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3308 {
3309 int chunk_count;
3310
3311
2/2
✓ Branch 1 taken 55334 times.
✓ Branch 2 taken 196 times.
55530 if (mov_stsc_index_valid(index, sc->stsc_count))
3312 55334 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3313 else {
3314 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3316 196 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3317 }
3318
3319 55530 return sc->stsc_data[index].count * (int64_t)chunk_count;
3320 }
3321
3322 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3323 {
3324 AVStream *st;
3325 MOVStreamContext *sc;
3326 unsigned i, entries;
3327
3328 if (c->trak_index < 0) {
3329 av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3330 return 0;
3331 }
3332
3333 if (c->fc->nb_streams < 1)
3334 return 0;
3335 st = c->fc->streams[c->fc->nb_streams-1];
3336 sc = st->priv_data;
3337
3338 avio_rb32(pb); // version + flags
3339
3340 entries = avio_rb32(pb);
3341 if (sc->stps_data)
3342 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3343 av_free(sc->stps_data);
3344 sc->stps_count = 0;
3345 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3346 if (!sc->stps_data)
3347 return AVERROR(ENOMEM);
3348
3349 for (i = 0; i < entries && !pb->eof_reached; i++) {
3350 sc->stps_data[i] = avio_rb32(pb);
3351 }
3352
3353 sc->stps_count = i;
3354
3355 if (pb->eof_reached) {
3356 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3357 return AVERROR_EOF;
3358 }
3359
3360 return 0;
3361 }
3362
3363 146 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3364 {
3365 AVStream *st;
3366 FFStream *sti;
3367 MOVStreamContext *sc;
3368 unsigned int i, entries;
3369
3370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (c->trak_index < 0) {
3371 av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3372 return 0;
3373 }
3374
3375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (c->fc->nb_streams < 1)
3376 return 0;
3377 146 st = c->fc->streams[c->fc->nb_streams-1];
3378 146 sti = ffstream(st);
3379 146 sc = st->priv_data;
3380
3381 146 avio_r8(pb); /* version */
3382 146 avio_rb24(pb); /* flags */
3383
3384 146 entries = avio_rb32(pb);
3385
3386 146 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3387
3388
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 140 times.
146 if (!entries) {
3389 6 sc->keyframe_absent = 1;
3390
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)
3391 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3392 6 return 0;
3393 }
3394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (sc->keyframes)
3395 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (entries >= UINT_MAX / sizeof(int))
3397 return AVERROR_INVALIDDATA;
3398 140 av_freep(&sc->keyframes);
3399 140 sc->keyframe_count = 0;
3400 140 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (!sc->keyframes)
3402 return AVERROR(ENOMEM);
3403
3404
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++) {
3405 5710 sc->keyframes[i] = avio_rb32(pb);
3406 }
3407
3408 140 sc->keyframe_count = i;
3409
3410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (pb->eof_reached) {
3411 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3412 return AVERROR_EOF;
3413 }
3414
3415 140 return 0;
3416 }
3417
3418 612 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3419 {
3420 AVStream *st;
3421 MOVStreamContext *sc;
3422 unsigned int i, entries, sample_size, field_size, num_bytes;
3423 GetBitContext gb;
3424 unsigned char* buf;
3425 int ret;
3426
3427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->trak_index < 0) {
3428 av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3429 return 0;
3430 }
3431
3432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->fc->nb_streams < 1)
3433 return 0;
3434 612 st = c->fc->streams[c->fc->nb_streams-1];
3435 612 sc = st->priv_data;
3436
3437 612 avio_r8(pb); /* version */
3438 612 avio_rb24(pb); /* flags */
3439
3440
1/2
✓ Branch 0 taken 612 times.
✗ Branch 1 not taken.
612 if (atom.type == MKTAG('s','t','s','z')) {
3441 612 sample_size = avio_rb32(pb);
3442
2/2
✓ Branch 0 taken 571 times.
✓ Branch 1 taken 41 times.
612 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3443 571 sc->sample_size = sample_size;
3444 612 sc->stsz_sample_size = sample_size;
3445 612 field_size = 32;
3446 } else {
3447 sample_size = 0;
3448 avio_rb24(pb); /* reserved */
3449 field_size = avio_r8(pb);
3450 }
3451 612 entries = avio_rb32(pb);
3452
3453 612 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3454
3455 612 sc->sample_count = entries;
3456
2/2
✓ Branch 0 taken 203 times.
✓ Branch 1 taken 409 times.
612 if (sample_size)
3457 203 return 0;
3458
3459
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) {
3460 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3461 return AVERROR_INVALIDDATA;
3462 }
3463
3464
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 384 times.
409 if (!entries)
3465 25 return 0;
3466
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)
3467 return AVERROR_INVALIDDATA;
3468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 if (sc->sample_sizes)
3469 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3470 384 av_free(sc->sample_sizes);
3471 384 sc->sample_count = 0;
3472 384 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3473
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 if (!sc->sample_sizes)
3474 return AVERROR(ENOMEM);
3475
3476 384 num_bytes = (entries*field_size+4)>>3;
3477
3478 384 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 if (!buf) {
3480 av_freep(&sc->sample_sizes);
3481 return AVERROR(ENOMEM);
3482 }
3483
3484 384 ret = ffio_read_size(pb, buf, num_bytes);
3485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 if (ret < 0) {
3486 av_freep(&sc->sample_sizes);
3487 av_free(buf);
3488 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3489 return 0;
3490 }
3491
3492 384 init_get_bits(&gb, buf, 8*num_bytes);
3493
3494
2/2
✓ Branch 0 taken 227249 times.
✓ Branch 1 taken 384 times.
227633 for (i = 0; i < entries; i++) {
3495 227249 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 227249 times.
227249 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3497 av_free(buf);
3498 av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3499 return AVERROR_INVALIDDATA;
3500 }
3501 227249 sc->data_size += sc->sample_sizes[i];
3502 }
3503
3504 384 sc->sample_count = i;
3505
3506 384 av_free(buf);
3507
3508 384 return 0;
3509 }
3510
3511 612 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3512 {
3513 AVStream *st;
3514 MOVStreamContext *sc;
3515 unsigned int i, entries;
3516 612 int64_t duration = 0;
3517 612 int64_t total_sample_count = 0;
3518 612 int64_t current_dts = 0;
3519 612 int64_t corrected_dts = 0;
3520
3521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->trak_index < 0) {
3522 av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3523 return 0;
3524 }
3525
3526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->fc->nb_streams < 1)
3527 return 0;
3528 612 st = c->fc->streams[c->fc->nb_streams-1];
3529 612 sc = st->priv_data;
3530
3531 612 avio_r8(pb); /* version */
3532 612 avio_rb24(pb); /* flags */
3533 612 entries = avio_rb32(pb);
3534
3535 612 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3536 612 c->fc->nb_streams-1, entries);
3537
3538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (sc->stts_data)
3539 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3540 612 av_freep(&sc->stts_data);
3541 612 sc->stts_count = 0;
3542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3543 return AVERROR(ENOMEM);
3544
3545
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++) {
3546 unsigned int sample_duration;
3547 unsigned int sample_count;
3548 2950 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3549 2950 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3550 min_entries * sizeof(*sc->stts_data));
3551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2950 times.
2950 if (!stts_data) {
3552 av_freep(&sc->stts_data);
3553 sc->stts_count = 0;
3554 return AVERROR(ENOMEM);
3555 }
3556 2950 sc->stts_count = min_entries;
3557 2950 sc->stts_data = stts_data;
3558
3559 2950 sample_count = avio_rb32(pb);
3560 2950 sample_duration = avio_rb32(pb);
3561
3562 2950 sc->stts_data[i].count= sample_count;
3563 2950 sc->stts_data[i].duration= sample_duration;
3564
3565 2950 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3566 sample_count, sample_duration);
3567
3568 /* STTS sample offsets are uint32 but some files store it as int32
3569 * with negative values used to correct DTS delays.
3570 There may be abnormally large values as well. */
3571
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2949 times.
2950 if (sample_duration > c->max_stts_delta) {
3572 // assume high delta is a correction if negative when cast as int32
3573 1 int32_t delta_magnitude = (int32_t)sample_duration;
3574 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",
3575 sample_duration, i, sample_count, st->index);
3576 1 sc->stts_data[i].duration = 1;
3577
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);
3578 } else {
3579 2949 corrected_dts += sample_duration * (uint64_t)sample_count;
3580 }
3581
3582 2950 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3583
3584
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2928 times.
2950 if (current_dts > corrected_dts) {
3585 22 int64_t drift = av_sat_sub64(current_dts, corrected_dts) / FFMAX(sample_count, 1);
3586
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;
3587 22 current_dts -= correction * (uint64_t)sample_count;
3588 22 sc->stts_data[i].duration -= correction;
3589 }
3590
3591 2950 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3592 2950 total_sample_count+=sc->stts_data[i].count;
3593 }
3594
3595 612 sc->stts_count = i;
3596
3597
2/2
✓ Branch 0 taken 587 times.
✓ Branch 1 taken 25 times.
612 if (duration > 0 &&
3598
1/2
✓ Branch 0 taken 587 times.
✗ Branch 1 not taken.
587 duration <= INT64_MAX - sc->duration_for_fps &&
3599
1/2
✓ Branch 0 taken 587 times.
✗ Branch 1 not taken.
587 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3600 587 sc->duration_for_fps += duration;
3601 587 sc->nb_frames_for_fps += total_sample_count;
3602 }
3603
3604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (pb->eof_reached) {
3605 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3606 return AVERROR_EOF;
3607 }
3608
3609 612 st->nb_frames= total_sample_count;
3610
2/2
✓ Branch 0 taken 587 times.
✓ Branch 1 taken 25 times.
612 if (duration)
3611 587 st->duration= FFMIN(st->duration, duration);
3612
3613 // All samples have zero duration. They have higher chance be chose by
3614 // mov_find_next_sample, which leads to seek again and again.
3615 //
3616 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3617 // So only mark data stream as discarded for safety.
3618
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 &&
3619 st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3620 av_log(c->fc, AV_LOG_WARNING,
3621 "All samples in data stream index:id [%d:%d] have zero "
3622 "duration, stream set to be discarded by default. Override "
3623 "using AVStream->discard or -discard for ffmpeg command.\n",
3624 st->index, sc->id);
3625 st->discard = AVDISCARD_ALL;
3626 }
3627 612 sc->track_end = duration;
3628 612 return 0;
3629 }
3630
3631 45 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3632 {
3633 AVStream *st;
3634 MOVStreamContext *sc;
3635 int64_t i, entries;
3636
3637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (c->fc->nb_streams < 1)
3638 return 0;
3639 45 st = c->fc->streams[c->fc->nb_streams - 1];
3640 45 sc = st->priv_data;
3641
3642 45 avio_r8(pb); /* version */
3643 45 avio_rb24(pb); /* flags */
3644 45 entries = atom.size - 4;
3645
3646 45 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3647 45 c->fc->nb_streams - 1, entries);
3648
3649
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 37 times.
45 if (sc->sdtp_data)
3650 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3651 45 av_freep(&sc->sdtp_data);
3652 45 sc->sdtp_count = 0;
3653
3654 45 sc->sdtp_data = av_malloc(entries);
3655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (!sc->sdtp_data)
3656 return AVERROR(ENOMEM);
3657
3658
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++)
3659 3811 sc->sdtp_data[i] = avio_r8(pb);
3660 45 sc->sdtp_count = i;
3661
3662 45 return 0;
3663 }
3664
3665 13275 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3666 {
3667
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 12139 times.
13275 if (duration < 0) {
3668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3669 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3670 duration++;
3671 }
3672 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3673 }
3674 13275 }
3675
3676 63 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3677 {
3678 AVStream *st;
3679 MOVStreamContext *sc;
3680 63 unsigned int i, entries, ctts_count = 0;
3681
3682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->trak_index < 0) {
3683 av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
3684 return 0;
3685 }
3686
3687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->fc->nb_streams < 1)
3688 return 0;
3689 63 st = c->fc->streams[c->fc->nb_streams-1];
3690 63 sc = st->priv_data;
3691
3692 63 avio_r8(pb); /* version */
3693 63 avio_rb24(pb); /* flags */
3694 63 entries = avio_rb32(pb);
3695
3696 63 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3697
3698
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 59 times.
63 if (!entries)
3699 4 return 0;
3700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
3701 return AVERROR_INVALIDDATA;
3702 59 av_freep(&sc->ctts_data);
3703 59 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
3704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->ctts_data)
3705 return AVERROR(ENOMEM);
3706
3707
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++) {
3708 MOVCtts *ctts_data;
3709 4874 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
3710 4874 const size_t requested_size =
3711 4874 min_size_needed > sc->ctts_allocated_size ?
3712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
3713 min_size_needed;
3714 4874 int count = avio_rb32(pb);
3715 4874 int duration = avio_rb32(pb);
3716
3717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (count <= 0) {
3718 av_log(c->fc, AV_LOG_TRACE,
3719 "ignoring CTTS entry with count=%d duration=%d\n",
3720 count, duration);
3721 continue;
3722 }
3723
3724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
3725 return AVERROR(ENOMEM);
3726
3727 4874 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
3728
3729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (!ctts_data)
3730 return AVERROR(ENOMEM);
3731
3732 4874 sc->ctts_data = ctts_data;
3733
3734 4874 ctts_data[ctts_count].count = count;
3735 4874 ctts_data[ctts_count].offset = duration;
3736 4874 ctts_count++;
3737
3738 4874 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
3739 count, duration);
3740
3741
2/2
✓ Branch 0 taken 4761 times.
✓ Branch 1 taken 113 times.
4874 if (i+2<entries)
3742 4761 mov_update_dts_shift(sc, duration, c->fc);
3743 }
3744
3745 59 sc->ctts_count = ctts_count;
3746
3747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (pb->eof_reached) {
3748 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
3749 return AVERROR_EOF;
3750 }
3751
3752 59 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
3753
3754 59 return 0;
3755 }
3756
3757 29 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3758 {
3759 AVStream *st;
3760 MOVStreamContext *sc;
3761 uint8_t version;
3762 uint32_t grouping_type;
3763 uint32_t default_length;
3764 av_unused uint32_t default_group_description_index;
3765 uint32_t entry_count;
3766
3767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (c->fc->nb_streams < 1)
3768 return 0;
3769 29 st = c->fc->streams[c->fc->nb_streams - 1];
3770 29 sc = st->priv_data;
3771
3772 29 version = avio_r8(pb); /* version */
3773 29 avio_rb24(pb); /* flags */
3774 29 grouping_type = avio_rl32(pb);
3775
3776 /*
3777 * This function only supports "sync" boxes, but the code is able to parse
3778 * other boxes (such as "tscl", "tsas" and "stsa")
3779 */
3780
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 5 times.
29 if (grouping_type != MKTAG('s','y','n','c'))
3781 24 return 0;
3782
3783
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
3784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
3785 5 entry_count = avio_rb32(pb);
3786
3787 5 av_freep(&sc->sgpd_sync);
3788 5 sc->sgpd_sync_count = entry_count;
3789 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
3790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
3791 return AVERROR(ENOMEM);
3792
3793
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++) {
3794 8 uint32_t description_length = default_length;
3795
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)
3796 description_length = avio_rb32(pb);
3797
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
3798 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
3799 8 sc->sgpd_sync[i] = nal_unit_type;
3800 8 description_length -= 1;
3801 }
3802 8 avio_skip(pb, description_length);
3803 }
3804
3805
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
3806 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
3807 return AVERROR_EOF;
3808 }
3809
3810 5 return 0;
3811 }
3812
3813 26 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3814 {
3815 AVStream *st;
3816 MOVStreamContext *sc;
3817 unsigned int i, entries;
3818 uint8_t version;
3819 uint32_t grouping_type;
3820 MOVSbgp *table, **tablep;
3821 int *table_count;
3822
3823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (c->fc->nb_streams < 1)
3824 return 0;
3825 26 st = c->fc->streams[c->fc->nb_streams-1];
3826 26 sc = st->priv_data;
3827
3828 26 version = avio_r8(pb); /* version */
3829 26 avio_rb24(pb); /* flags */
3830 26 grouping_type = avio_rl32(pb);
3831
3832
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 25 times.
26 if (grouping_type == MKTAG('r','a','p',' ')) {
3833 1 tablep = &sc->rap_group;
3834 1 table_count = &sc->rap_group_count;
3835
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 20 times.
25 } else if (grouping_type == MKTAG('s','y','n','c')) {
3836 5 tablep = &sc->sync_group;
3837 5 table_count = &sc->sync_group_count;
3838 } else {
3839 20 return 0;
3840 }
3841
3842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
3843 avio_rb32(pb); /* grouping_type_parameter */
3844
3845 6 entries = avio_rb32(pb);
3846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
3847 return 0;
3848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
3849 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
3850 6 av_freep(tablep);
3851 6 table = av_malloc_array(entries, sizeof(*table));
3852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
3853 return AVERROR(ENOMEM);
3854 6 *tablep = table;
3855
3856
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++) {
3857 32 table[i].count = avio_rb32(pb); /* sample_count */
3858 32 table[i].index = avio_rb32(pb); /* group_description_index */
3859 }
3860
3861 6 *table_count = i;
3862
3863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
3864 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
3865 return AVERROR_EOF;
3866 }
3867
3868 6 return 0;
3869 }
3870
3871 /**
3872 * Get ith edit list entry (media time, duration).
3873 */
3874 913 static int get_edit_list_entry(MOVContext *mov,
3875 const MOVStreamContext *msc,
3876 unsigned int edit_list_index,
3877 int64_t *edit_list_media_time,
3878 int64_t *edit_list_duration,
3879 int64_t global_timescale)
3880 {
3881
2/2
✓ Branch 0 taken 443 times.
✓ Branch 1 taken 470 times.
913 if (edit_list_index == msc->elst_count) {
3882 443 return 0;
3883 }
3884 470 *edit_list_media_time = msc->elst_data[edit_list_index].time;
3885 470 *edit_list_duration = msc->elst_data[edit_list_index].duration;
3886
3887 /* duration is in global timescale units;convert to msc timescale */
3888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 if (global_timescale == 0) {
3889 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
3890 return 0;
3891 }
3892 470 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
3893 global_timescale);
3894
3895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 if (*edit_list_duration + (uint64_t)*edit_list_media_time > INT64_MAX)
3896 *edit_list_duration = 0;
3897
3898 470 return 1;
3899 }
3900
3901 /**
3902 * Find the closest previous frame to the timestamp_pts, in e_old index
3903 * entries. Searching for just any frame / just key frames can be controlled by
3904 * last argument 'flag'.
3905 * Note that if ctts_data is not NULL, we will always search for a key frame
3906 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
3907 * return the first frame of the video.
3908 *
3909 * Here the timestamp_pts is considered to be a presentation timestamp and
3910 * the timestamp of index entries are considered to be decoding timestamps.
3911 *
3912 * Returns 0 if successful in finding a frame, else returns -1.
3913 * Places the found index corresponding output arg.
3914 *
3915 * If ctts_old is not NULL, then refines the searched entry by searching
3916 * backwards from the found timestamp, to find the frame with correct PTS.
3917 *
3918 * Places the found ctts_index and ctts_sample in corresponding output args.
3919 */
3920 469 static int find_prev_closest_index(AVStream *st,
3921 AVIndexEntry *e_old,
3922 int nb_old,
3923 MOVTimeToSample *tts_data,
3924 int64_t tts_count,
3925 int64_t timestamp_pts,
3926 int flag,
3927 int64_t* index,
3928 int64_t* tts_index,
3929 int64_t* tts_sample)
3930 {
3931 469 MOVStreamContext *msc = st->priv_data;
3932 469 FFStream *const sti = ffstream(st);
3933 469 AVIndexEntry *e_keep = sti->index_entries;
3934 469 int nb_keep = sti->nb_index_entries;
3935 469 int64_t i = 0;
3936
3937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 469 times.
469 av_assert0(index);
3938
3939 // If dts_shift > 0, then all the index timestamps will have to be offset by
3940 // at least dts_shift amount to obtain PTS.
3941 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
3942
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 460 times.
469 if (msc->dts_shift > 0) {
3943 9 timestamp_pts -= msc->dts_shift;
3944 }
3945
3946 469 sti->index_entries = e_old;
3947 469 sti->nb_index_entries = nb_old;
3948 469 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
3949
3950 // Keep going backwards in the index entries until the timestamp is the same.
3951
2/2
✓ Branch 0 taken 468 times.
✓ Branch 1 taken 1 times.
469 if (*index >= 0) {
3952
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;
3953 i--) {
3954 if ((flag & AVSEEK_FLAG_ANY) ||
3955 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
3956 *index = i - 1;
3957 }
3958 }
3959 }
3960
3961 // If we have CTTS then refine the search, by searching backwards over PTS
3962 // computed by adding corresponding CTTS durations to index timestamps.
3963
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) {
3964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(tts_index);
3965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(tts_sample);
3966 // Find out the ctts_index for the found frame.
3967 63 *tts_index = 0;
3968 63 *tts_sample = 0;
3969
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++) {
3970
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (*tts_index < tts_count) {
3971 175 (*tts_sample)++;
3972
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (tts_data[*tts_index].count == *tts_sample) {
3973 175 (*tts_index)++;
3974 175 *tts_sample = 0;
3975 }
3976 }
3977 }
3978
3979
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) {
3980 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
3981 // No need to add dts_shift to the timestamp here because timestamp_pts has already been
3982 // compensated by dts_shift above.
3983
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 &&
3984
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 4 times.
62 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
3985 58 break;
3986 }
3987
3988 12 (*index)--;
3989
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (*tts_sample == 0) {
3990 12 (*tts_index)--;
3991
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 if (*tts_index >= 0)
3992 7 *tts_sample = tts_data[*tts_index].count - 1;
3993 } else {
3994 (*tts_sample)--;
3995 }
3996 }
3997 }
3998
3999 /* restore AVStream state*/
4000 469 sti->index_entries = e_keep;
4001 469 sti->nb_index_entries = nb_keep;
4002
2/2
✓ Branch 0 taken 463 times.
✓ Branch 1 taken 6 times.
469 return *index >= 0 ? 0 : -1;
4003 }
4004
4005 /**
4006 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
4007 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
4008 *
4009 * This function is similar to ff_add_index_entry in libavformat/utils.c
4010 * except that here we are always unconditionally adding an index entry to
4011 * the end, instead of searching the entries list and skipping the add if
4012 * there is an existing entry with the same timestamp.
4013 * This is needed because the mov_fix_index calls this func with the same
4014 * unincremented timestamp for successive discarded frames.
4015 */
4016 348561 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
4017 int size, int distance, int flags)
4018 {
4019 348561 FFStream *const sti = ffstream(st);
4020 AVIndexEntry *entries, *ie;
4021 348561 int64_t index = -1;
4022 348561 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
4023
4024 // Double the allocation each time, to lower memory fragmentation.
4025 // Another difference from ff_add_index_entry function.
4026 348561 const size_t requested_size =
4027 348561 min_size_needed > sti->index_entries_allocated_size ?
4028
2/2
✓ Branch 0 taken 1982 times.
✓ Branch 1 taken 346579 times.
348561 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
4029 min_size_needed;
4030
4031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348561 times.
348561 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
4032 return -1;
4033
4034 348561 entries = av_fast_realloc(sti->index_entries,
4035 &sti->index_entries_allocated_size,
4036 requested_size);
4037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348561 times.
348561 if (!entries)
4038 return -1;
4039
4040 348561 sti->index_entries = entries;
4041
4042 348561 index = sti->nb_index_entries++;
4043 348561 ie= &entries[index];
4044
4045 348561 ie->pos = pos;
4046 348561 ie->timestamp = timestamp;
4047 348561 ie->min_distance= distance;
4048 348561 ie->size= size;
4049 348561 ie->flags = flags;
4050 348561 return index;
4051 }
4052
4053 /**
4054 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4055 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4056 */
4057 27 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4058 int64_t* frame_duration_buffer,
4059 int frame_duration_buffer_size) {
4060 27 FFStream *const sti = ffstream(st);
4061 27 int i = 0;
4062
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);
4063
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 27 times.
164 for (i = 0; i < frame_duration_buffer_size; i++) {
4064 137 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4065 137 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4066 }
4067 27 }
4068
4069 186062 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4070 int count, int offset, unsigned int duration)
4071 {
4072 MOVTimeToSample *tts_buf_new;
4073 186062 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4074 186062 const size_t requested_size =
4075 186062 min_size_needed > *allocated_size ?
4076
2/2
✓ Branch 0 taken 1349 times.
✓ Branch 1 taken 184713 times.
186062 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4077 min_size_needed;
4078
4079
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186062 times.
186062 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4080 return -1;
4081
4082 186062 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4083
4084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186062 times.
186062 if (!tts_buf_new)
4085 return -1;
4086
4087 186062 *tts_data = tts_buf_new;
4088
4089 186062 tts_buf_new[*tts_count].count = count;
4090 186062 tts_buf_new[*tts_count].offset = offset;
4091 186062 tts_buf_new[*tts_count].duration = duration;
4092
4093 186062 *tts_count = (*tts_count) + 1;
4094 186062 return 0;
4095 }
4096
4097 #define MAX_REORDER_DELAY 16
4098 618 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4099 {
4100 618 MOVStreamContext *msc = st->priv_data;
4101 618 FFStream *const sti = ffstream(st);
4102 618 int ctts_ind = 0;
4103 618 int ctts_sample = 0;
4104 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4105 618 int buf_start = 0;
4106 int j, r, num_swaps;
4107
4108
2/2
✓ Branch 0 taken 10506 times.
✓ Branch 1 taken 618 times.
11124 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4109 10506 pts_buf[j] = INT64_MIN;
4110
4111
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 &&
4112
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 16 times.
59 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4113 43 st->codecpar->video_delay = 0;
4114
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) {
4115 // Point j to the last elem of the buffer and insert the current pts there.
4116 138279 j = buf_start;
4117 138279 buf_start = (buf_start + 1);
4118
2/2
✓ Branch 0 taken 8111 times.
✓ Branch 1 taken 130168 times.
138279 if (buf_start == MAX_REORDER_DELAY + 1)
4119 8111 buf_start = 0;
4120
4121 138279 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4122
4123 // The timestamps that are already in the sorted buffer, and are greater than the
4124 // current pts, are exactly the timestamps that need to be buffered to output PTS
4125 // in correct sorted order.
4126 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4127 // can be computed as the maximum no. of swaps any particular timestamp needs to
4128 // go through, to keep this buffer in sorted order.
4129 138279 num_swaps = 0;
4130
2/2
✓ Branch 0 taken 142294 times.
✓ Branch 1 taken 4 times.
142298 while (j != buf_start) {
4131 142294 r = j - 1;
4132
2/2
✓ Branch 0 taken 8389 times.
✓ Branch 1 taken 133905 times.
142294 if (r < 0) r = MAX_REORDER_DELAY;
4133
2/2
✓ Branch 0 taken 4019 times.
✓ Branch 1 taken 138275 times.
142294 if (pts_buf[j] < pts_buf[r]) {
4134 4019 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4135 4019 ++num_swaps;
4136 } else {
4137 138275 break;
4138 }
4139 4019 j = r;
4140 }
4141 138279 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4142
4143 138279 ctts_sample++;
4144
1/2
✓ Branch 0 taken 138279 times.
✗ Branch 1 not taken.
138279 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4145 138279 ctts_ind++;
4146 138279 ctts_sample = 0;
4147 }
4148 }
4149 43 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4150 43 st->codecpar->video_delay, st->index);
4151 }
4152 618 }
4153
4154 105917 static void mov_current_sample_inc(MOVStreamContext *sc)
4155 {
4156 105917 sc->current_sample++;
4157 105917 sc->current_index++;
4158
2/2
✓ Branch 0 taken 61411 times.
✓ Branch 1 taken 44506 times.
105917 if (sc->index_ranges &&
4159
2/2
✓ Branch 0 taken 427 times.
✓ Branch 1 taken 60984 times.
61411 sc->current_index >= sc->current_index_range->end &&
4160
1/2
✓ Branch 0 taken 427 times.
✗ Branch 1 not taken.
427 sc->current_index_range->end) {
4161 427 sc->current_index_range++;
4162 427 sc->current_index = sc->current_index_range->start;
4163 }
4164 105917 }
4165
4166 static void mov_current_sample_dec(MOVStreamContext *sc)
4167 {
4168 sc->current_sample--;
4169 sc->current_index--;
4170 if (sc->index_ranges &&
4171 sc->current_index < sc->current_index_range->start &&
4172 sc->current_index_range > sc->index_ranges) {
4173 sc->current_index_range--;
4174 sc->current_index = sc->current_index_range->end - 1;
4175 }
4176 }
4177
4178 335 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4179 {
4180 int64_t range_size;
4181
4182 335 sc->current_sample = current_sample;
4183 335 sc->current_index = current_sample;
4184
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 309 times.
335 if (!sc->index_ranges) {
4185 26 return;
4186 }
4187
4188 309 for (sc->current_index_range = sc->index_ranges;
4189
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 sc->current_index_range->end;
4190 sc->current_index_range++) {
4191 309 range_size = sc->current_index_range->end - sc->current_index_range->start;
4192
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 if (range_size > current_sample) {
4193 309 sc->current_index = sc->current_index_range->start + current_sample;
4194 309 break;
4195 }
4196 current_sample -= range_size;
4197 }
4198 }
4199
4200 /**
4201 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4202 * which are needed to decode them) that fall in the edit list time ranges.
4203 * Also fixes the timestamps of the index entries to match the timeline
4204 * specified the edit lists.
4205 */
4206 618 static void mov_fix_index(MOVContext *mov, AVStream *st)
4207 {
4208 618 MOVStreamContext *msc = st->priv_data;
4209 618 FFStream *const sti = ffstream(st);
4210 618 AVIndexEntry *e_old = sti->index_entries;
4211 618 int nb_old = sti->nb_index_entries;
4212 618 const AVIndexEntry *e_old_end = e_old + nb_old;
4213 618 const AVIndexEntry *current = NULL;
4214 618 MOVTimeToSample *tts_data_old = msc->tts_data;
4215 618 int64_t tts_index_old = 0;
4216 618 int64_t tts_sample_old = 0;
4217 618 int64_t tts_count_old = msc->tts_count;
4218 618 int64_t edit_list_media_time = 0;
4219 618 int64_t edit_list_duration = 0;
4220 618 int64_t frame_duration = 0;
4221 618 int64_t edit_list_dts_counter = 0;
4222 618 int64_t edit_list_dts_entry_end = 0;
4223 618 int64_t edit_list_start_tts_sample = 0;
4224 int64_t curr_cts;
4225 618 int64_t curr_ctts = 0;
4226 618 int64_t empty_edits_sum_duration = 0;
4227 618 int64_t edit_list_index = 0;
4228 int64_t index;
4229 int flags;
4230 618 int64_t start_dts = 0;
4231 618 int64_t edit_list_start_encountered = 0;
4232 618 int64_t search_timestamp = 0;
4233 618 int64_t* frame_duration_buffer = NULL;
4234 618 int num_discarded_begin = 0;
4235 618 int first_non_zero_audio_edit = -1;
4236 618 int packet_skip_samples = 0;
4237 618 MOVIndexRange *current_index_range = NULL;
4238 618 int found_keyframe_after_edit = 0;
4239 618 int found_non_empty_edit = 0;
4240
4241
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) {
4242 175 return;
4243 }
4244
4245 // allocate the index ranges array
4246 443 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4247 sizeof(msc->index_ranges[0]));
4248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 443 times.
443 if (!msc->index_ranges) {
4249 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4250 return;
4251 }
4252 443 msc->current_index_range = msc->index_ranges;
4253
4254 // Clean AVStream from traces of old index
4255 443 sti->index_entries = NULL;
4256 443 sti->index_entries_allocated_size = 0;
4257 443 sti->nb_index_entries = 0;
4258
4259 // Clean time to sample fields of MOVStreamContext
4260 443 msc->tts_data = NULL;
4261 443 msc->tts_count = 0;
4262 443 msc->tts_index = 0;
4263 443 msc->tts_sample = 0;
4264 443 msc->tts_allocated_size = 0;
4265
4266 // Reinitialize min_corrected_pts so that it can be computed again.
4267 443 msc->min_corrected_pts = -1;
4268
4269 // If the dts_shift is positive (in case of negative ctts values in mov),
4270 // then negate the DTS by dts_shift
4271
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 434 times.
443 if (msc->dts_shift > 0) {
4272 9 edit_list_dts_entry_end -= msc->dts_shift;
4273 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4274 }
4275
4276 443 start_dts = edit_list_dts_entry_end;
4277
4278
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,
4279 913 &edit_list_duration, mov->time_scale)) {
4280 470 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4281 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4282 470 edit_list_index++;
4283 470 edit_list_dts_counter = edit_list_dts_entry_end;
4284 470 edit_list_dts_entry_end += edit_list_duration;
4285 470 num_discarded_begin = 0;
4286
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) {
4287 4 empty_edits_sum_duration += edit_list_duration;
4288 4 continue;
4289 }
4290 466 found_non_empty_edit = 1;
4291
4292 // If we encounter a non-negative edit list reset the skip_samples/start_pad fields and set them
4293 // according to the edit list below.
4294
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 339 times.
466 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4295
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit < 0) {
4296 127 first_non_zero_audio_edit = 1;
4297 } else {
4298 first_non_zero_audio_edit = 0;
4299 }
4300
4301
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit > 0)
4302 127 sti->skip_samples = msc->start_pad = 0;
4303 }
4304
4305 // While reordering frame index according to edit list we must handle properly
4306 // the scenario when edit list entry starts from none key frame.
4307 // We find closest previous key frame and preserve it and consequent frames in index.
4308 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4309 466 search_timestamp = edit_list_media_time;
4310
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 339 times.
466 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4311 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4312 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4313 // edit_list_media_time to cover the decoder delay.
4314 127 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
4315 }
4316
4317
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,
4318 &index, &tts_index_old, &tts_sample_old) < 0) {
4319 3 av_log(mov->fc, AV_LOG_WARNING,
4320 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4321 st->index, edit_list_index, search_timestamp);
4322
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,
4323 &index, &tts_index_old, &tts_sample_old) < 0) {
4324 3 av_log(mov->fc, AV_LOG_WARNING,
4325 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4326 st->index, edit_list_index, search_timestamp);
4327 3 index = 0;
4328 3 tts_index_old = 0;
4329 3 tts_sample_old = 0;
4330 }
4331 }
4332 466 current = e_old + index;
4333 466 edit_list_start_tts_sample = tts_sample_old;
4334
4335 // Iterate over index and arrange it according to edit list
4336 466 edit_list_start_encountered = 0;
4337 466 found_keyframe_after_edit = 0;
4338
2/2
✓ Branch 0 taken 348561 times.
✓ Branch 1 taken 114 times.
348675 for (; current < e_old_end; current++, index++) {
4339 // check if frame outside edit list mark it for discard
4340 697122 frame_duration = (current + 1 < e_old_end) ?
4341
2/2
✓ Branch 0 taken 348122 times.
✓ Branch 1 taken 439 times.
348561 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4342
4343 348561 flags = current->flags;
4344
4345 // frames (pts) before or after edit list
4346 348561 curr_cts = current->timestamp + msc->dts_shift;
4347 348561 curr_ctts = 0;
4348
4349
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) {
4350 186062 curr_ctts = tts_data_old[tts_index_old].offset;
4351 186062 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4352 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4353 186062 curr_cts += curr_ctts;
4354 186062 tts_sample_old++;
4355
1/2
✓ Branch 0 taken 186062 times.
✗ Branch 1 not taken.
186062 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186062 times.
186062 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4357 &msc->tts_allocated_size,
4358 186062 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4359 186062 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4360 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4361 tts_index_old,
4362 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4363 tts_data_old[tts_index_old].offset);
4364 break;
4365 }
4366 186062 tts_index_old++;
4367 186062 tts_sample_old = 0;
4368 186062 edit_list_start_tts_sample = 0;
4369 }
4370 }
4371
4372
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)) {
4373
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 &&
4374
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 &&
4375 first_non_zero_audio_edit > 0) {
4376 11 packet_skip_samples = edit_list_media_time - curr_cts;
4377 11 sti->skip_samples += packet_skip_samples;
4378
4379 // Shift the index entry timestamp by packet_skip_samples to be correct.
4380 11 edit_list_dts_counter -= packet_skip_samples;
4381
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (edit_list_start_encountered == 0) {
4382 11 edit_list_start_encountered = 1;
4383 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4384 // discarded packets.
4385
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 if (frame_duration_buffer) {
4386 6 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4387 frame_duration_buffer, num_discarded_begin);
4388 6 av_freep(&frame_duration_buffer);
4389 }
4390 }
4391
4392 11 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4393 } else {
4394 271 flags |= AVINDEX_DISCARD_FRAME;
4395 271 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4396
4397
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 132 times.
271 if (edit_list_start_encountered == 0) {
4398 139 num_discarded_begin++;
4399 139 frame_duration_buffer = av_realloc(frame_duration_buffer,
4400 num_discarded_begin * sizeof(int64_t));
4401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if (!frame_duration_buffer) {
4402 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4403 break;
4404 }
4405 139 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4406
4407 // Increment skip_samples for the first non-zero audio edit list
4408
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 &&
4409
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) {
4410 20 sti->skip_samples += frame_duration;
4411 }
4412 }
4413 }
4414 } else {
4415
2/2
✓ Branch 0 taken 442 times.
✓ Branch 1 taken 347837 times.
348279 if (msc->min_corrected_pts < 0) {
4416 442 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4417 } else {
4418 347837 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4419 }
4420
2/2
✓ Branch 0 taken 453 times.
✓ Branch 1 taken 347826 times.
348279 if (edit_list_start_encountered == 0) {
4421 453 edit_list_start_encountered = 1;
4422 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4423 // discarded packets.
4424
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 432 times.
453 if (frame_duration_buffer) {
4425 21 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4426 frame_duration_buffer, num_discarded_begin);
4427 21 av_freep(&frame_duration_buffer);
4428 }
4429 }
4430 }
4431
4432
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,
4433 348561 current->min_distance, flags) == -1) {
4434 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4435 break;
4436 }
4437
4438 // Update the index ranges array
4439
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) {
4440 464 current_index_range = current_index_range ? current_index_range + 1
4441
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 443 times.
464 : msc->index_ranges;
4442 464 current_index_range->start = index;
4443 }
4444 348561 current_index_range->end = index + 1;
4445
4446 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4447
2/2
✓ Branch 0 taken 348422 times.
✓ Branch 1 taken 139 times.
348561 if (edit_list_start_encountered > 0) {
4448 348422 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4449 }
4450
4451 // Break when found first key frame after edit entry completion
4452
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)) &&
4453
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)))) {
4454
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 343 times.
364 if (msc->ctts_count) {
4455 // If we have CTTS and this is the first keyframe after edit elist,
4456 // wait for one more, because there might be trailing B-frames after this I-frame
4457 // that do belong to the edit.
4458
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) {
4459 12 found_keyframe_after_edit = 1;
4460 12 continue;
4461 }
4462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (tts_sample_old != 0) {
4463 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4464 &msc->tts_allocated_size,
4465 tts_sample_old - edit_list_start_tts_sample,
4466 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4467 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4468 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4469 tts_data_old[tts_index_old].offset);
4470 break;
4471 }
4472 }
4473 }
4474 352 break;
4475 }
4476 }
4477 }
4478 // If there are empty edits, then msc->min_corrected_pts might be positive
4479 // intentionally. So we subtract the sum duration of empty edits here.
4480 443 msc->min_corrected_pts -= empty_edits_sum_duration;
4481
4482 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4483 // dts by that amount to make the first pts zero.
4484
2/2
✓ Branch 0 taken 274 times.
✓ Branch 1 taken 169 times.
443 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4485
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 233 times.
274 if (msc->min_corrected_pts > 0) {
4486 41 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4487
2/2
✓ Branch 0 taken 2829 times.
✓ Branch 1 taken 41 times.
2870 for (int i = 0; i < sti->nb_index_entries; ++i)
4488 2829 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4489 }
4490 }
4491 // Start time should be equal to zero or the duration of any empty edits.
4492 443 st->start_time = empty_edits_sum_duration;
4493
4494 // Update av stream length, if it ends up shorter than the track's media duration
4495 443 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4496 443 msc->start_pad = sti->skip_samples;
4497
4498 // Free the old index and the old CTTS structures
4499 443 av_free(e_old);
4500 443 av_free(tts_data_old);
4501 443 av_freep(&frame_duration_buffer);
4502
4503 // Null terminate the index ranges array
4504 443 current_index_range = current_index_range ? current_index_range + 1
4505
1/2
✓ Branch 0 taken 443 times.
✗ Branch 1 not taken.
443 : msc->index_ranges;
4506 443 current_index_range->start = 0;
4507 443 current_index_range->end = 0;
4508 443 msc->current_index = msc->index_ranges[0].start;
4509 }
4510
4511 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4512 {
4513
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4514
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == nal_unit_type)
4515 5 return i + 1;
4516 return 0;
4517 }
4518
4519 643 static int build_open_gop_key_points(AVStream *st)
4520 {
4521 int k;
4522 643 int sample_id = 0;
4523 uint32_t cra_index;
4524 643 MOVStreamContext *sc = st->priv_data;
4525
4526
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)
4527 638 return 0;
4528
4529 /* Build an unrolled index of the samples */
4530 5 sc->sample_offsets_count = 0;
4531
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4533 return AVERROR(ENOMEM);
4534 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4535 }
4536 5 av_freep(&sc->sample_offsets);
4537 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4539 return AVERROR(ENOMEM);
4540 5 k = 0;
4541
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4542
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4543 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4544
4545 /* The following HEVC NAL type reveal the use of open GOP sync points
4546 * (TODO: BLA types may also be concerned) */
4547 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4549 return 0;
4550
4551 /* Build a list of open-GOP key samples */
4552 5 sc->open_key_samples_count = 0;
4553
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4554
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4555
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)
4556 return AVERROR(ENOMEM);
4557 11 sc->open_key_samples_count += sc->sync_group[i].count;
4558 }
4559 5 av_freep(&sc->open_key_samples);
4560 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4562 return AVERROR(ENOMEM);
4563 5 k = 0;
4564
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4565 28 const MOVSbgp *sg = &sc->sync_group[i];
4566
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4567
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4568 11 sc->open_key_samples[k++] = sample_id;
4569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4570 return AVERROR_PATCHWELCOME;
4571 28 sample_id += sg->count;
4572 }
4573
4574 /* Identify the minimal time step between samples */
4575 5 sc->min_sample_duration = UINT_MAX;
4576
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4577 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4578
4579 5 return 0;
4580 }
4581
4582 #define MOV_MERGE_CTTS 1
4583 #define MOV_MERGE_STTS 2
4584 /*
4585 * Merge stts and ctts arrays into a new combined array.
4586 * stts_count and ctts_count may be left untouched as they will be
4587 * used to check for the presence of either of them.
4588 */
4589 618 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4590 {
4591 618 MOVStreamContext *sc = st->priv_data;
4592
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);
4593
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);
4594 618 int idx = 0;
4595
4596
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)
4597 return 0;
4598 // Expand time to sample entries such that we have a 1-1 mapping with samples
4599
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))
4600 return -1;
4601
4602
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 559 times.
618 if (ctts) {
4603 118 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4604 59 sc->sample_count * sizeof(*sc->tts_data));
4605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->tts_data)
4606 return -1;
4607
4608 59 memset(sc->tts_data, 0, sc->tts_allocated_size);
4609
4610
2/2
✓ Branch 0 taken 4874 times.
✓ Branch 1 taken 59 times.
4933 for (int i = 0; i < sc->ctts_count &&
4611
1/2
✓ Branch 0 taken 4874 times.
✗ Branch 1 not taken.
9748 idx < sc->sample_count; i++)
4612
2/2
✓ Branch 0 taken 139017 times.
✓ Branch 1 taken 4874 times.
143891 for (int j = 0; j < sc->ctts_data[i].count &&
4613
1/2
✓ Branch 0 taken 139017 times.
✗ Branch 1 not taken.
139017 idx < sc->sample_count; j++) {
4614 139017 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4615 139017 sc->tts_data[idx++].count = 1;
4616 }
4617
4618 59 sc->tts_count = idx;
4619 } else
4620 559 sc->ctts_count = 0;
4621 618 av_freep(&sc->ctts_data);
4622 618 sc->ctts_allocated_size = 0;
4623
4624 618 idx = 0;
4625
2/2
✓ Branch 0 taken 552 times.
✓ Branch 1 taken 66 times.
618 if (stts) {
4626 552 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4627 552 sc->sample_count * sizeof(*sc->tts_data));
4628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 552 times.
552 if (!tts_data)
4629 return -1;
4630
4631
2/2
✓ Branch 0 taken 493 times.
✓ Branch 1 taken 59 times.
552 if (!sc->tts_data)
4632 493 memset(tts_data, 0, sc->tts_allocated_size);
4633 552 sc->tts_data = tts_data;
4634
4635
2/2
✓ Branch 0 taken 2915 times.
✓ Branch 1 taken 552 times.
3467 for (int i = 0; i < sc->stts_count &&
4636
1/2
✓ Branch 0 taken 2915 times.
✗ Branch 1 not taken.
5830 idx < sc->sample_count; i++)
4637
2/2
✓ Branch 0 taken 236273 times.
✓ Branch 1 taken 2915 times.
239188 for (int j = 0; j < sc->stts_data[i].count &&
4638
1/2
✓ Branch 0 taken 236273 times.
✗ Branch 1 not taken.
236273 idx < sc->sample_count; j++) {
4639 236273 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4640 236273 sc->tts_data[idx++].count = 1;
4641 }
4642
4643 552 sc->tts_count = FFMAX(sc->tts_count, idx);
4644 } else
4645 66 sc->stts_count = 0;
4646 618 av_freep(&sc->stts_data);
4647 618 sc->stts_allocated_size = 0;
4648
4649 618 return 0;
4650 }
4651
4652 643 static void mov_build_index(MOVContext *mov, AVStream *st)
4653 {
4654 643 MOVStreamContext *sc = st->priv_data;
4655 643 FFStream *const sti = ffstream(st);
4656 int64_t current_offset;
4657 643 int64_t current_dts = 0;
4658 643 unsigned int stts_index = 0;
4659 643 unsigned int stsc_index = 0;
4660 643 unsigned int stss_index = 0;
4661 643 unsigned int stps_index = 0;
4662 unsigned int i, j;
4663 643 uint64_t stream_size = 0;
4664
4665 643 int ret = build_open_gop_key_points(st);
4666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 643 times.
643 if (ret < 0)
4667 return;
4668
4669
2/2
✓ Branch 0 taken 446 times.
✓ Branch 1 taken 197 times.
643 if (sc->elst_count) {
4670 446 int i, edit_start_index = 0, multiple_edits = 0;
4671 446 int64_t empty_duration = 0; // empty duration of the first edit list entry
4672 446 int64_t start_time = 0; // start time of the media
4673
4674
2/2
✓ Branch 0 taken 473 times.
✓ Branch 1 taken 446 times.
919 for (i = 0; i < sc->elst_count; i++) {
4675 473 const MOVElst *e = &sc->elst_data[i];
4676
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) {
4677 /* if empty, the first entry is the start time of the stream
4678 * relative to the presentation itself */
4679 4 empty_duration = e->duration;
4680 4 edit_start_index = 1;
4681
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) {
4682 446 start_time = e->time;
4683 } else {
4684 23 multiple_edits = 1;
4685 }
4686 }
4687
4688
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) {
4689 if (mov->advanced_editlist_autodisabled)
4690 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4691 "not supported in fragmented MP4 files\n");
4692 else
4693 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4694 "Use -advanced_editlist to correctly decode otherwise "
4695 "a/v desync might occur\n");
4696 }
4697
4698 /* adjust first dts according to edit list */
4699
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) {
4700
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 69 times.
73 if (empty_duration)
4701 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
4702
4703
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)
4704 av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
4705
4706 73 sc->time_offset = start_time - (uint64_t)empty_duration;
4707 73 sc->min_corrected_pts = start_time;
4708
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 72 times.
73 if (!mov->advanced_editlist)
4709 1 current_dts = -sc->time_offset;
4710 }
4711
4712
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 &&
4713
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)
4714 sc->start_pad = start_time;
4715 }
4716
4717 /* only use old uncompressed audio chunk demuxing when stts specifies it */
4718
2/2
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 400 times.
643 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4719
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)) {
4720 577 unsigned int current_sample = 0;
4721 577 unsigned int stts_sample = 0;
4722 unsigned int sample_size;
4723 577 unsigned int distance = 0;
4724 577 unsigned int rap_group_index = 0;
4725 577 unsigned int rap_group_sample = 0;
4726
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;
4727
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);
4728
4729 577 current_dts -= sc->dts_shift;
4730
4731
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)
4732 25 return;
4733
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)
4734 return;
4735
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 552 times.
552 if (av_reallocp_array(&sti->index_entries,
4736 552 sti->nb_index_entries + sc->sample_count,
4737 sizeof(*sti->index_entries)) < 0) {
4738 sti->nb_index_entries = 0;
4739 return;
4740 }
4741 552 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
4742
4743 552 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
4744
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 552 times.
552 if (ret < 0)
4745 return;
4746
4747
2/2
✓ Branch 0 taken 174213 times.
✓ Branch 1 taken 552 times.
174765 for (i = 0; i < sc->chunk_count; i++) {
4748
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;
4749 174213 current_offset = sc->chunk_offsets[i];
4750
2/2
✓ Branch 1 taken 8863 times.
✓ Branch 2 taken 167895 times.
176758 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4751
2/2
✓ Branch 0 taken 2545 times.
✓ Branch 1 taken 6318 times.
8863 i + 1 == sc->stsc_data[stsc_index + 1].first)
4752 2545 stsc_index++;
4753
4754
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 &&
4755 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
4756 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
4757 sc->stsz_sample_size = sc->sample_size;
4758 }
4759
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) {
4760 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
4761 sc->stsz_sample_size = sc->sample_size;
4762 }
4763
4764
2/2
✓ Branch 0 taken 236273 times.
✓ Branch 1 taken 174213 times.
410486 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
4765 236273 int keyframe = 0;
4766
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 236273 times.
236273 if (current_sample >= sc->sample_count) {
4767 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
4768 return;
4769 }
4770
4771
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])) {
4772 84575 keyframe = 1;
4773
2/2
✓ Branch 0 taken 5570 times.
✓ Branch 1 taken 79005 times.
84575 if (stss_index + 1 < sc->keyframe_count)
4774 5570 stss_index++;
4775
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]) {
4776 keyframe = 1;
4777 if (stps_index + 1 < sc->stps_count)
4778 stps_index++;
4779 }
4780
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) {
4781
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
4782 2 keyframe = 1;
4783
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
4784 4 rap_group_sample = 0;
4785 4 rap_group_index++;
4786 }
4787 }
4788
2/2
✓ Branch 0 taken 4756 times.
✓ Branch 1 taken 231517 times.
236273 if (sc->keyframe_absent
4789
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !sc->stps_count
4790
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !rap_group_present
4791
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)))
4792 3884 keyframe = 1;
4793
2/2
✓ Branch 0 taken 88459 times.
✓ Branch 1 taken 147814 times.
236273 if (keyframe)
4794 88459 distance = 0;
4795
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];
4796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 236273 times.
236273 if (current_offset > INT64_MAX - sample_size) {
4797 av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
4798 current_offset,
4799 sample_size);
4800 return;
4801 }
4802
4803
2/2
✓ Branch 0 taken 236184 times.
✓ Branch 1 taken 89 times.
236273 if (sc->pseudo_stream_id == -1 ||
4804
1/2
✓ Branch 0 taken 236184 times.
✗ Branch 1 not taken.
236184 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
4805 AVIndexEntry *e;
4806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 236273 times.
236273 if (sample_size > 0x3FFFFFFF) {
4807 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
4808 return;
4809 }
4810 236273 e = &sti->index_entries[sti->nb_index_entries++];
4811 236273 e->pos = current_offset;
4812 236273 e->timestamp = current_dts;
4813 236273 e->size = sample_size;
4814 236273 e->min_distance = distance;
4815 236273 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
4816 236273 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
4817 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
4818 current_offset, current_dts, sample_size, distance, keyframe);
4819
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)
4820 10385 ff_rfps_add_frame(mov->fc, st, current_dts);
4821 }
4822
4823 236273 current_offset += sample_size;
4824 236273 stream_size += sample_size;
4825
4826 236273 current_dts += sc->tts_data[stts_index].duration;
4827
4828 236273 distance++;
4829 236273 stts_sample++;
4830 236273 current_sample++;
4831
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) {
4832 235721 stts_sample = 0;
4833 235721 stts_index++;
4834 }
4835 }
4836 }
4837
2/2
✓ Branch 0 taken 521 times.
✓ Branch 1 taken 31 times.
552 if (st->duration > 0)
4838 521 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
4839 } else {
4840 66 unsigned chunk_samples, total = 0;
4841
4842
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)
4843 return;
4844
4845 // compute total chunk count
4846
2/2
✓ Branch 0 taken 723 times.
✓ Branch 1 taken 66 times.
789 for (i = 0; i < sc->stsc_count; i++) {
4847 unsigned count, chunk_count;
4848
4849 723 chunk_samples = sc->stsc_data[i].count;
4850
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 66 times.
723 if (i != sc->stsc_count - 1 &&
4851
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) {
4852 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
4853 return;
4854 }
4855
4856
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 648 times.
723 if (sc->samples_per_frame >= 160) { // gsm
4857 75 count = chunk_samples / sc->samples_per_frame;
4858
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 117 times.
648 } else if (sc->samples_per_frame > 1) {
4859 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
4860 531 count = (chunk_samples+samples-1) / samples;
4861 } else {
4862 117 count = (chunk_samples+1023) / 1024;
4863 }
4864
4865
2/2
✓ Branch 1 taken 657 times.
✓ Branch 2 taken 66 times.
723 if (mov_stsc_index_valid(i, sc->stsc_count))
4866 657 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
4867 else
4868 66 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
4869 723 total += chunk_count * count;
4870 }
4871
4872 66 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
4873
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4874 return;
4875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (av_reallocp_array(&sti->index_entries,
4876 66 sti->nb_index_entries + total,
4877 sizeof(*sti->index_entries)) < 0) {
4878 sti->nb_index_entries = 0;
4879 return;
4880 }
4881 66 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
4882
4883 // populate index
4884
2/2
✓ Branch 0 taken 5428 times.
✓ Branch 1 taken 66 times.
5494 for (i = 0; i < sc->chunk_count; i++) {
4885 5428 current_offset = sc->chunk_offsets[i];
4886
2/2
✓ Branch 1 taken 5287 times.
✓ Branch 2 taken 141 times.
5428 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4887
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 4630 times.
5287 i + 1 == sc->stsc_data[stsc_index + 1].first)
4888 657 stsc_index++;
4889 5428 chunk_samples = sc->stsc_data[stsc_index].count;
4890
4891
2/2
✓ Branch 0 taken 162532 times.
✓ Branch 1 taken 5428 times.
167960 while (chunk_samples > 0) {
4892 AVIndexEntry *e;
4893 unsigned size, samples;
4894
4895
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) {
4896 avpriv_request_sample(mov->fc,
4897 "Zero bytes per frame, but %d samples per frame",
4898 sc->samples_per_frame);
4899 return;
4900 }
4901
4902
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 148174 times.
162532 if (sc->samples_per_frame >= 160) { // gsm
4903 14358 samples = sc->samples_per_frame;
4904 14358 size = sc->bytes_per_frame;
4905 } else {
4906
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 138611 times.
148174 if (sc->samples_per_frame > 1) {
4907 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
4908 sc->samples_per_frame, chunk_samples);
4909 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
4910 } else {
4911 138611 samples = FFMIN(1024, chunk_samples);
4912 138611 size = samples * sc->sample_size;
4913 }
4914 }
4915
4916
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (sti->nb_index_entries >= total) {
4917 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
4918 return;
4919 }
4920
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (size > 0x3FFFFFFF) {
4921 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
4922 return;
4923 }
4924 162532 e = &sti->index_entries[sti->nb_index_entries++];
4925 162532 e->pos = current_offset;
4926 162532 e->timestamp = current_dts;
4927 162532 e->size = size;
4928 162532 e->min_distance = 0;
4929 162532 e->flags = AVINDEX_KEYFRAME;
4930 162532 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
4931 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
4932 size, samples);
4933
4934 162532 current_offset += size;
4935 162532 current_dts += samples;
4936 162532 chunk_samples -= samples;
4937 }
4938 }
4939
4940 66 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
4941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
4942 return;
4943 }
4944
4945
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) {
4946 // Fix index according to edit lists.
4947 618 mov_fix_index(mov, st);
4948 }
4949
4950 // Update start time of the stream.
4951
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) {
4952 57 st->start_time = sti->index_entries[0].timestamp + sc->dts_shift;
4953
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 if (sc->tts_data) {
4954 57 st->start_time += sc->tts_data[0].offset;
4955 }
4956 }
4957
4958 618 mov_estimate_video_delay(mov, st);
4959 }
4960
4961 static int test_same_origin(const char *src, const char *ref) {
4962 char src_proto[64];
4963 char ref_proto[64];
4964 char src_auth[256];
4965 char ref_auth[256];
4966 char src_host[256];
4967 char ref_host[256];
4968 int src_port=-1;
4969 int ref_port=-1;
4970
4971 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
4972 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
4973
4974 if (strlen(src) == 0) {
4975 return -1;
4976 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
4977 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
4978 strlen(src_host) + 1 >= sizeof(src_host) ||
4979 strlen(ref_host) + 1 >= sizeof(ref_host)) {
4980 return 0;
4981 } else if (strcmp(src_proto, ref_proto) ||
4982 strcmp(src_auth, ref_auth) ||
4983 strcmp(src_host, ref_host) ||
4984 src_port != ref_port) {
4985 return 0;
4986 } else
4987 return 1;
4988 }
4989
4990 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
4991 {
4992 /* try relative path, we do not try the absolute because it can leak information about our
4993 system to an attacker */
4994 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
4995 char filename[1025];
4996 const char *src_path;
4997 int i, l;
4998
4999 /* find a source dir */
5000 src_path = strrchr(src, '/');
5001 if (src_path)
5002 src_path++;
5003 else
5004 src_path = src;
5005
5006 /* find a next level down to target */
5007 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
5008 if (ref->path[l] == '/') {
5009 if (i == ref->nlvl_to - 1)
5010 break;
5011 else
5012 i++;
5013 }
5014
5015 /* compose filename if next level down to target was found */
5016 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
5017 memcpy(filename, src, src_path - src);
5018 filename[src_path - src] = 0;
5019
5020 for (i = 1; i < ref->nlvl_from; i++)
5021 av_strlcat(filename, "../", sizeof(filename));
5022
5023 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
5024 if (!c->use_absolute_path) {
5025 int same_origin = test_same_origin(src, filename);
5026
5027 if (!same_origin) {
5028 av_log(c->fc, AV_LOG_ERROR,
5029 "Reference with mismatching origin, %s not tried for security reasons, "
5030 "set demuxer option use_absolute_path to allow it anyway\n",
5031 ref->path);
5032 return AVERROR(ENOENT);
5033 }
5034
5035 if (strstr(ref->path + l + 1, "..") ||
5036 strstr(ref->path + l + 1, ":") ||
5037 (ref->nlvl_from > 1 && same_origin < 0) ||
5038 (filename[0] == '/' && src_path == src))
5039 return AVERROR(ENOENT);
5040 }
5041
5042 if (strlen(filename) + 1 == sizeof(filename))
5043 return AVERROR(ENOENT);
5044 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5045 return 0;
5046 }
5047 } else if (c->use_absolute_path) {
5048 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5049 "this is a possible security issue\n");
5050 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5051 return 0;
5052 } else {
5053 av_log(c->fc, AV_LOG_ERROR,
5054 "Absolute path %s not tried for security reasons, "
5055 "set demuxer option use_absolute_path to allow absolute paths\n",
5056 ref->path);
5057 }
5058
5059 return AVERROR(ENOENT);
5060 }
5061
5062 1309 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5063 {
5064
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1295 times.
1309 if (sc->time_scale <= 0) {
5065 14 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5066 14 sc->time_scale = c->time_scale;
5067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (sc->time_scale <= 0)
5068 sc->time_scale = 1;
5069 }
5070 1309 }
5071
5072 #if CONFIG_IAMFDEC
5073 10 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5074 {
5075 10 const MOVStreamContext *sc = st->priv_data;
5076 10 const IAMFContext *iamf = &sc->iamf->iamf;
5077
5078
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5079 10 const AVStreamGroup *stg = NULL;
5080
5081
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5082
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)
5083 10 stg = c->fc->stream_groups[j];
5084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 av_assert0(stg);
5085
5086
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int j = 0; j < stg->nb_streams; j++) {
5087 50 const FFStream *sti = cffstream(st);
5088 50 AVStream *out = stg->streams[j];
5089 50 FFStream *out_sti = ffstream(stg->streams[j]);
5090
5091 50 out->codecpar->bit_rate = 0;
5092
5093
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 40 times.
50 if (out == st)
5094 10 continue;
5095
5096 40 out->time_base = st->time_base;
5097 40 out->start_time = st->start_time;
5098 40 out->duration = st->duration;
5099 40 out->nb_frames = st->nb_frames;
5100 40 out->discard = st->discard;
5101
5102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 av_assert0(!out_sti->index_entries);
5103 40 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (!out_sti->index_entries)
5105 return AVERROR(ENOMEM);
5106
5107 40 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5108 40 out_sti->nb_index_entries = sti->nb_index_entries;
5109 40 out_sti->skip_samples = sti->skip_samples;
5110 40 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5111 }
5112 }
5113
5114 10 return 0;
5115 }
5116 #endif
5117
5118 643 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5119 {
5120
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 ||
5121
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))) ||
5122
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)) {
5123 av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5124 index);
5125 return 1;
5126 }
5127
5128
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) {
5129 av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5130 index);
5131 return 2;
5132 }
5133 643 return 0;
5134 }
5135
5136 612 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5137 {
5138 AVStream *st;
5139 MOVStreamContext *sc;
5140 int ret;
5141
5142 612 st = avformat_new_stream(c->fc, NULL);
5143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (!st) return AVERROR(ENOMEM);
5144 612 st->id = -1;
5145 612 sc = av_mallocz(sizeof(MOVStreamContext));
5146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (!sc) return AVERROR(ENOMEM);
5147
5148 612 st->priv_data = sc;
5149 612 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5150 612 sc->ffindex = st->index;
5151 612 c->trak_index = st->index;
5152 612 sc->tref_flags = 0;
5153 612 sc->tref_id = -1;
5154 612 sc->refcount = 1;
5155
5156
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 612 times.
612 if ((ret = mov_read_default(c, pb, atom)) < 0)
5157 return ret;
5158
5159 612 c->trak_index = -1;
5160
5161 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5162 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5163
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) {
5164 1 sc->stsc_count = 0;
5165 1 av_freep(&sc->stsc_data);
5166 }
5167
5168 612 ret = sanity_checks(c->fc, sc, st->index);
5169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (ret)
5170 return ret > 1 ? AVERROR_INVALIDDATA : 0;
5171
5172 612 fix_timescale(c, sc);
5173
5174 612 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5175
5176 /*
5177 * Advanced edit list support does not work with fragemented MP4s, which
5178 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5179 * In these files, trun atoms may be streamed in.
5180 */
5181
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) {
5182
5183 17 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5184 "MP4. disabling.\n");
5185 17 c->advanced_editlist = 0;
5186 17 c->advanced_editlist_autodisabled = 1;
5187 }
5188
5189 612 mov_build_index(c, st);
5190
5191 #if CONFIG_IAMFDEC
5192
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 602 times.
612 if (sc->iamf) {
5193 10 ret = mov_update_iamf_streams(c, st);
5194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
5195 return ret;
5196 }
5197 #endif
5198
5199
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) {
5200 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5201 if (c->enable_drefs) {
5202 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5203 av_log(c->fc, AV_LOG_ERROR,
5204 "stream %d, error opening alias: path='%s', dir='%s', "
5205 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5206 st->index, dref->path, dref->dir, dref->filename,
5207 dref->volume, dref->nlvl_from, dref->nlvl_to);
5208 } else {
5209 av_log(c->fc, AV_LOG_WARNING,
5210 "Skipped opening external track: "
5211 "stream %d, alias: path='%s', dir='%s', "
5212 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5213 "Set enable_drefs to allow this.\n",
5214 st->index, dref->path, dref->dir, dref->filename,
5215 dref->volume, dref->nlvl_from, dref->nlvl_to);
5216 }
5217 } else {
5218 612 sc->pb = c->fc->pb;
5219 612 sc->pb_is_copied = 1;
5220 }
5221
5222
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 298 times.
612 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5223
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;
5224
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)
5225 65 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5226 65 sc->h_spacing, sc->v_spacing, INT_MAX);
5227
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 &&
5228
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 &&
5229
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)) {
5230 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5231 (int64_t)st->codecpar->height * sc->width,
5232 (int64_t)st->codecpar->width * sc->height, INT_MAX);
5233 }
5234
5235 #if FF_API_R_FRAME_RATE
5236
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++) {
5237
2/2
✓ Branch 0 taken 152113 times.
✓ Branch 1 taken 2427 times.
154540 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5238 152113 continue;
5239 2427 stts_constant = 0;
5240 }
5241
2/2
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 28 times.
314 if (stts_constant)
5242 286 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5243 286 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5244 #endif
5245 }
5246
5247 #if CONFIG_H261_DECODER || CONFIG_H263_DECODER || CONFIG_MPEG4_DECODER
5248
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 588 times.
612 switch (st->codecpar->codec_id) {
5249 #if CONFIG_H261_DECODER
5250 24 case AV_CODEC_ID_H261:
5251 #endif
5252 #if CONFIG_H263_DECODER
5253 case AV_CODEC_ID_H263:
5254 #endif
5255 #if CONFIG_MPEG4_DECODER
5256 case AV_CODEC_ID_MPEG4:
5257 #endif
5258 24 st->codecpar->width = 0; /* let decoder init width/height */
5259 24 st->codecpar->height= 0;
5260 24 break;
5261 }
5262 #endif
5263
5264 // If the duration of the mp3 packets is not constant, then they could need a parser
5265
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 611 times.
612 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5266
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 && sc->time_scale == st->codecpar->sample_rate) {
5267 1 int stts_constant = 1;
5268
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++) {
5269
1/2
✓ Branch 0 taken 287 times.
✗ Branch 1 not taken.
287 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5270 287 continue;
5271 stts_constant = 0;
5272 }
5273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!stts_constant)
5274 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5275 }
5276 /* Do not need those anymore. */
5277 612 av_freep(&sc->chunk_offsets);
5278 612 av_freep(&sc->sample_sizes);
5279 612 av_freep(&sc->keyframes);
5280 612 av_freep(&sc->stps_data);
5281 612 av_freep(&sc->elst_data);
5282 612 av_freep(&sc->rap_group);
5283 612 av_freep(&sc->sync_group);
5284 612 av_freep(&sc->sgpd_sync);
5285
5286 612 return 0;
5287 }
5288
5289 132 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5290 {
5291 int ret;
5292 132 c->itunes_metadata = 1;
5293 132 ret = mov_read_default(c, pb, atom);
5294 132 c->itunes_metadata = 0;
5295 132 return ret;
5296 }
5297
5298 11 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5299 {
5300 uint32_t count;
5301 uint32_t i;
5302
5303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
5304 return 0;
5305
5306 11 avio_skip(pb, 4);
5307 11 count = avio_rb32(pb);
5308 11 atom.size -= 8;
5309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (count >= UINT_MAX / sizeof(*c->meta_keys)) {
5310 av_log(c->fc, AV_LOG_ERROR,
5311 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5312 return AVERROR_INVALIDDATA;
5313 }
5314
5315 11 c->meta_keys_count = count + 1;
5316 11 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
5317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!c->meta_keys)
5318 return AVERROR(ENOMEM);
5319
5320
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i <= count; ++i) {
5321 58 uint32_t key_size = avio_rb32(pb);
5322 58 uint32_t type = avio_rl32(pb);
5323
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) {
5324 av_log(c->fc, AV_LOG_ERROR,
5325 "The key# %"PRIu32" in meta has invalid size:"
5326 "%"PRIu32"\n", i, key_size);
5327 return AVERROR_INVALIDDATA;
5328 }
5329 58 atom.size -= key_size;
5330 58 key_size -= 8;
5331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (type != MKTAG('m','d','t','a')) {
5332 avio_skip(pb, key_size);
5333 continue;
5334 }
5335 58 c->meta_keys[i] = av_mallocz(key_size + 1);
5336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!c->meta_keys[i])
5337 return AVERROR(ENOMEM);
5338 58 avio_read(pb, c->meta_keys[i], key_size);
5339 }
5340
5341 11 return 0;
5342 }
5343
5344 65 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5345 {
5346 65 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5347 65 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5348 int i;
5349 65 int ret = 0;
5350 AVStream *st;
5351 MOVStreamContext *sc;
5352
5353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (c->fc->nb_streams < 1)
5354 return 0;
5355 65 st = c->fc->streams[c->fc->nb_streams-1];
5356 65 sc = st->priv_data;
5357
5358
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 65 times.
260 for (i = 0; i < 3; i++) {
5359 uint8_t **p;
5360 uint32_t len, tag;
5361
5362
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 195 times.
195 if (end - avio_tell(pb) <= 12)
5363 break;
5364
5365 195 len = avio_rb32(pb);
5366 195 tag = avio_rl32(pb);
5367 195 avio_skip(pb, 4); // flags
5368
5369
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))
5370 break;
5371 195 len -= 12;
5372
5373
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 130 times.
195 if (tag == MKTAG('m', 'e', 'a', 'n'))
5374 65 p = &mean;
5375
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 65 times.
130 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5376 65 p = &key;
5377
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) {
5378 65 avio_skip(pb, 4);
5379 65 len -= 4;
5380 65 p = &val;
5381 } else
5382 break;
5383
5384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (*p)
5385 break;
5386
5387 195 *p = av_malloc(len + 1);
5388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*p) {
5389 ret = AVERROR(ENOMEM);
5390 break;
5391 }
5392 195 ret = ffio_read_size(pb, *p, len);
5393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (ret < 0) {
5394 av_freep(p);
5395 break;
5396 }
5397 195 (*p)[len] = 0;
5398 }
5399
5400
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) {
5401
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 32 times.
65 if (strcmp(key, "iTunSMPB") == 0) {
5402 int priming, remainder, samples;
5403
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
5404
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)
5405 33 sc->start_pad = priming;
5406 }
5407 }
5408
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 10 times.
120 if (strcmp(key, "cdec") != 0) {
5409 55 av_dict_set(&c->fc->metadata, key, val,
5410 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5411 55 key = val = NULL;
5412 }
5413 } else {
5414 av_log(c->fc, AV_LOG_VERBOSE,
5415 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5416 }
5417
5418 65 avio_seek(pb, end, SEEK_SET);
5419 65 av_freep(&key);
5420 65 av_freep(&val);
5421 65 av_freep(&mean);
5422 65 return ret;
5423 }
5424
5425 31 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5426 {
5427 MOVStreamContext *sc;
5428 AVStream *st;
5429
5430 31 st = avformat_new_stream(c->fc, NULL);
5431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!st)
5432 return AVERROR(ENOMEM);
5433 31 sc = av_mallocz(sizeof(MOVStreamContext));
5434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!sc)
5435 goto fail;
5436
5437 31 item->st = st;
5438 31 st->id = item->item_id;
5439 31 st->priv_data = sc;
5440 31 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5441 31 st->codecpar->codec_id = mov_codec_id(st, item->type);
5442 31 sc->id = st->id;
5443 31 sc->ffindex = st->index;
5444 31 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5445 31 st->time_base.num = st->time_base.den = 1;
5446 31 st->nb_frames = 1;
5447 31 sc->time_scale = 1;
5448 31 sc->pb = c->fc->pb;
5449 31 sc->pb_is_copied = 1;
5450 31 sc->refcount = 1;
5451
5452
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 if (item->name)
5453 31 av_dict_set(&st->metadata, "title", item->name, 0);
5454
5455 // Populate the necessary fields used by mov_build_index.
5456 31 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!sc->stsc_data)
5458 goto fail;
5459 31 sc->stsc_count = 1;
5460 31 sc->stsc_data[0].first = 1;
5461 31 sc->stsc_data[0].count = 1;
5462 31 sc->stsc_data[0].id = 1;
5463 31 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!sc->chunk_offsets)
5465 goto fail;
5466 31 sc->chunk_count = 1;
5467 31 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!sc->stts_data)
5469 goto fail;
5470 31 sc->stts_count = 1;
5471 31 sc->stts_data[0].count = 1;
5472 // Not used for still images. But needed by mov_build_index.
5473 31 sc->stts_data[0].duration = 0;
5474
5475 31 return 0;
5476 fail:
5477 mov_free_stream_context(c->fc, st);
5478 ff_remove_stream(c->fc, st);
5479 item->st = NULL;
5480
5481 return AVERROR(ENOMEM);
5482 }
5483
5484 149 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5485 {
5486
1/2
✓ Branch 0 taken 433 times.
✗ Branch 1 not taken.
433 while (atom.size > 8) {
5487 uint32_t tag;
5488
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 433 times.
433 if (avio_feof(pb))
5489 return AVERROR_EOF;
5490 433 tag = avio_rl32(pb);
5491 433 atom.size -= 4;
5492
2/2
✓ Branch 0 taken 149 times.
✓ Branch 1 taken 284 times.
433 if (tag == MKTAG('h','d','l','r')) {
5493 149 avio_seek(pb, -8, SEEK_CUR);
5494 149 atom.size += 8;
5495 149 return mov_read_default(c, pb, atom);
5496 }
5497 }
5498 return 0;
5499 }
5500
5501 // return 1 when matrix is identity, 0 otherwise
5502 #define IS_MATRIX_IDENT(matrix) \
5503 ( (matrix)[0][0] == (1 << 16) && \
5504 (matrix)[1][1] == (1 << 16) && \
5505 (matrix)[2][2] == (1 << 30) && \
5506 !(matrix)[0][1] && !(matrix)[0][2] && \
5507 !(matrix)[1][0] && !(matrix)[1][2] && \
5508 !(matrix)[2][0] && !(matrix)[2][1])
5509
5510 612 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5511 {
5512 int i, j, e;
5513 int width;
5514 int height;
5515 int display_matrix[3][3];
5516 612 int res_display_matrix[3][3] = { { 0 } };
5517 AVStream *st;
5518 MOVStreamContext *sc;
5519 int version;
5520 int flags;
5521
5522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (c->fc->nb_streams < 1)
5523 return 0;
5524 612 st = c->fc->streams[c->fc->nb_streams-1];
5525 612 sc = st->priv_data;
5526
5527 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5528 // avoids corrupting AVStreams mapped to an earlier tkhd.
5529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
612 if (st->id != -1)
5530 return AVERROR_INVALIDDATA;
5531
5532 612 version = avio_r8(pb);
5533 612 flags = avio_rb24(pb);
5534 612 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5535
5536
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 599 times.
612 if (version == 1) {
5537 13 avio_rb64(pb);
5538 13 avio_rb64(pb);
5539 } else {
5540 599 avio_rb32(pb); /* creation time */
5541 599 avio_rb32(pb); /* modification time */
5542 }
5543 612 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5544 612 sc->id = st->id;
5545 612 avio_rb32(pb); /* reserved */
5546
5547 /* highlevel (considering edits) duration in movie timebase */
5548
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 599 times.
612 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5549 612 avio_rb32(pb); /* reserved */
5550 612 avio_rb32(pb); /* reserved */
5551
5552 612 avio_rb16(pb); /* layer */
5553 612 avio_rb16(pb); /* alternate group */
5554 612 avio_rb16(pb); /* volume */
5555 612 avio_rb16(pb); /* reserved */
5556
5557 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
5558 // they're kept in fixed point format through all calculations
5559 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
5560 // side data, but the scale factor is not needed to calculate aspect ratio
5561
2/2
✓ Branch 0 taken 1836 times.
✓ Branch 1 taken 612 times.
2448 for (i = 0; i < 3; i++) {
5562 1836 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
5563 1836 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
5564 1836 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
5565 }
5566
5567 612 width = avio_rb32(pb); // 16.16 fixed point track width
5568 612 height = avio_rb32(pb); // 16.16 fixed point track height
5569 612 sc->width = width >> 16;
5570 612 sc->height = height >> 16;
5571
5572 // apply the moov display matrix (after the tkhd one)
5573
2/2
✓ Branch 0 taken 1836 times.
✓ Branch 1 taken 612 times.
2448 for (i = 0; i < 3; i++) {
5574 1836 const int sh[3] = { 16, 16, 30 };
5575
2/2
✓ Branch 0 taken 5508 times.
✓ Branch 1 taken 1836 times.
7344 for (j = 0; j < 3; j++) {
5576
2/2
✓ Branch 0 taken 16524 times.
✓ Branch 1 taken 5508 times.
22032 for (e = 0; e < 3; e++) {
5577 16524 res_display_matrix[i][j] +=
5578 16524 ((int64_t) display_matrix[i][e] *
5579 16524 c->movie_display_matrix[e][j]) >> sh[e];
5580 }
5581 }
5582 }
5583
5584 // save the matrix when it is not the default identity
5585
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)) {
5586 9 av_freep(&sc->display_matrix);
5587 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
5588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
5589 return AVERROR(ENOMEM);
5590
5591
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
5592
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
5593 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
5594 }
5595
5596 // transform the display width/height according to the matrix
5597 // to keep the same scale, use [width height 1<<16]
5598
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) {
5599 double disp_transform[2];
5600
5601
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
5602 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
5603 16 sc->display_matrix[3 + i]);
5604
5605
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 &&
5606
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) &&
5607
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
5608 3 st->sample_aspect_ratio = av_d2q(
5609 3 disp_transform[0] / disp_transform[1],
5610 INT_MAX);
5611 }
5612 612 return 0;
5613 }
5614
5615 493 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5616 {
5617 493 MOVFragment *frag = &c->fragment;
5618 493 MOVTrackExt *trex = NULL;
5619 int flags, track_id, i;
5620 MOVFragmentStreamInfo * frag_stream_info;
5621
5622 493 avio_r8(pb); /* version */
5623 493 flags = avio_rb24(pb);
5624
5625 493 track_id = avio_rb32(pb);
5626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (!track_id)
5627 return AVERROR_INVALIDDATA;
5628
1/2
✓ Branch 0 taken 551 times.
✗ Branch 1 not taken.
551 for (i = 0; i < c->trex_count; i++)
5629
2/2
✓ Branch 0 taken 493 times.
✓ Branch 1 taken 58 times.
551 if (c->trex_data[i].track_id == track_id) {
5630 493 trex = &c->trex_data[i];
5631 493 break;
5632 }
5633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (!trex) {
5634 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
5635 return 0;
5636 }
5637 493 c->fragment.found_tfhd = 1;
5638 493 frag->track_id = track_id;
5639 493 set_frag_stream(&c->frag_index, track_id);
5640
5641 986 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
5642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
986 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
5643
2/2
✓ Branch 0 taken 420 times.
✓ Branch 1 taken 73 times.
493 frag->moof_offset : frag->implicit_offset;
5644
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;
5645
5646 986 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
5647
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 435 times.
493 avio_rb32(pb) : trex->duration;
5648 986 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
5649
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 434 times.
493 avio_rb32(pb) : trex->size;
5650 986 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
5651
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 365 times.
493 avio_rb32(pb) : trex->flags;
5652 493 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
5653
5654 493 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5655
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (frag_stream_info) {
5656 493 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
5657 493 frag_stream_info->stsd_id = frag->stsd_id;
5658 }
5659 493 return 0;
5660 }
5661
5662 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5663 {
5664 unsigned i, num;
5665 void *new_tracks;
5666
5667 2 num = atom.size / 4;
5668
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
5669 return AVERROR(ENOMEM);
5670
5671 2 av_free(c->chapter_tracks);
5672 2 c->chapter_tracks = new_tracks;
5673 2 c->nb_chapter_tracks = num;
5674
5675
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++)
5676 2 c->chapter_tracks[i] = avio_rb32(pb);
5677
5678 2 c->nb_chapter_tracks = i;
5679
5680 2 return 0;
5681 }
5682
5683 24 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5684 {
5685 MOVTrackExt *trex;
5686 int err;
5687
5688
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))
5689 return AVERROR_INVALIDDATA;
5690
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
24 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
5691 sizeof(*c->trex_data))) < 0) {
5692 c->trex_count = 0;
5693 return err;
5694 }
5695
5696 24 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
5697
5698 24 trex = &c->trex_data[c->trex_count++];
5699 24 avio_r8(pb); /* version */
5700 24 avio_rb24(pb); /* flags */
5701 24 trex->track_id = avio_rb32(pb);
5702 24 trex->stsd_id = avio_rb32(pb);
5703 24 trex->duration = avio_rb32(pb);
5704 24 trex->size = avio_rb32(pb);
5705 24 trex->flags = avio_rb32(pb);
5706 24 return 0;
5707 }
5708
5709 420 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5710 {
5711 420 MOVFragment *frag = &c->fragment;
5712 420 AVStream *st = NULL;
5713 MOVStreamContext *sc;
5714 int version, i;
5715 MOVFragmentStreamInfo * frag_stream_info;
5716 int64_t base_media_decode_time;
5717
5718
1/2
✓ Branch 0 taken 446 times.
✗ Branch 1 not taken.
446 for (i = 0; i < c->fc->nb_streams; i++) {
5719 446 sc = c->fc->streams[i]->priv_data;
5720
2/2
✓ Branch 0 taken 420 times.
✓ Branch 1 taken 26 times.
446 if (sc->id == frag->track_id) {
5721 420 st = c->fc->streams[i];
5722 420 break;
5723 }
5724 }
5725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 420 times.
420 if (!st) {
5726 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5727 return 0;
5728 }
5729 420 sc = st->priv_data;
5730
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)
5731 return 0;
5732 420 version = avio_r8(pb);
5733 420 avio_rb24(pb); /* flags */
5734
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 367 times.
420 if (version) {
5735 53 base_media_decode_time = avio_rb64(pb);
5736 } else {
5737 367 base_media_decode_time = avio_rb32(pb);
5738 }
5739
5740 420 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5741
1/2
✓ Branch 0 taken 420 times.
✗ Branch 1 not taken.
420 if (frag_stream_info)
5742 420 frag_stream_info->tfdt_dts = base_media_decode_time;
5743 420 sc->track_end = base_media_decode_time;
5744
5745 420 return 0;
5746 }
5747
5748 493 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5749 {
5750 493 MOVFragment *frag = &c->fragment;
5751 493 AVStream *st = NULL;
5752 493 FFStream *sti = NULL;
5753 MOVStreamContext *sc;
5754 MOVTimeToSample *tts_data;
5755 uint64_t offset;
5756 493 int64_t dts, pts = AV_NOPTS_VALUE;
5757 493 int data_offset = 0;
5758 493 unsigned entries, first_sample_flags = frag->flags;
5759 int flags, distance, i;
5760 493 int64_t prev_dts = AV_NOPTS_VALUE;
5761 493 int next_frag_index = -1, index_entry_pos;
5762 size_t requested_size;
5763 size_t old_allocated_size;
5764 AVIndexEntry *new_entries;
5765 MOVFragmentStreamInfo * frag_stream_info;
5766
5767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (!frag->found_tfhd) {
5768 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
5769 return AVERROR_INVALIDDATA;
5770 }
5771
5772
1/2
✓ Branch 0 taken 551 times.
✗ Branch 1 not taken.
551 for (i = 0; i < c->fc->nb_streams; i++) {
5773 551 sc = c->fc->streams[i]->priv_data;
5774
2/2
✓ Branch 0 taken 493 times.
✓ Branch 1 taken 58 times.
551 if (sc->id == frag->track_id) {
5775 493 st = c->fc->streams[i];
5776 493 sti = ffstream(st);
5777 493 break;
5778 }
5779 }
5780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (!st) {
5781 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5782 return 0;
5783 }
5784 493 sc = st->priv_data;
5785
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)
5786 return 0;
5787
5788 // Find the next frag_index index that has a valid index_entry for
5789 // the current track_id.
5790 //
5791 // A valid index_entry means the trun for the fragment was read
5792 // and it's samples are in index_entries at the given position.
5793 // New index entries will be inserted before the index_entry found.
5794 493 index_entry_pos = sti->nb_index_entries;
5795
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++) {
5796 1621 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
5797
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) {
5798 next_frag_index = i;
5799 index_entry_pos = frag_stream_info->index_entry;
5800 break;
5801 }
5802 }
5803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 av_assert0(index_entry_pos <= sti->nb_index_entries);
5804
5805 493 avio_r8(pb); /* version */
5806 493 flags = avio_rb24(pb);
5807 493 entries = avio_rb32(pb);
5808 493 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
5809
5810
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))
5811 return AVERROR_INVALIDDATA;
5812
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
5813
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);
5814
5815 493 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5816
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (frag_stream_info) {
5817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
5818 dts = frag_stream_info->next_trun_dts - sc->time_offset;
5819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5820 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
5821 pts = frag_stream_info->first_tfra_pts;
5822 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5823 ", using it for pts\n", pts);
5824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5825 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
5826 dts = frag_stream_info->first_tfra_pts;
5827 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5828 ", using it for dts\n", pts);
5829 } else {
5830 493 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
5831 493 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
5832
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;
5833
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;
5834
5835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (fallback_sidx) {
5836 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
5837 }
5838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (fallback_tfdt) {
5839 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
5840 }
5841
5842
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) {
5843 420 dts = frag_stream_info->tfdt_dts - sc->time_offset;
5844 420 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
5845 ", using it for dts\n", dts);
5846
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) {
5847 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
5848 // pts = frag_stream_info->sidx_pts;
5849 dts = frag_stream_info->sidx_pts;
5850 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
5851 ", using it for dts\n", frag_stream_info->sidx_pts);
5852 } else {
5853 73 dts = sc->track_end - sc->time_offset;
5854 73 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5855 ", using it for dts\n", dts);
5856 }
5857 }
5858 } else {
5859 dts = sc->track_end - sc->time_offset;
5860 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5861 ", using it for dts\n", dts);
5862 }
5863 493 offset = frag->base_data_offset + data_offset;
5864 493 distance = 0;
5865 493 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
5866
5867 // realloc space for new index entries
5868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
5869 entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
5870 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
5871 }
5872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (entries == 0)
5873 return 0;
5874
5875 493 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
5876 493 new_entries = av_fast_realloc(sti->index_entries,
5877 &sti->index_entries_allocated_size,
5878 requested_size);
5879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (!new_entries)
5880 return AVERROR(ENOMEM);
5881 493 sti->index_entries= new_entries;
5882
5883 493 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
5884 493 old_allocated_size = sc->tts_allocated_size;
5885 493 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
5886 requested_size);
5887
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (!tts_data)
5888 return AVERROR(ENOMEM);
5889 493 sc->tts_data = tts_data;
5890
5891 // In case there were samples without time to sample entries, ensure they get
5892 // zero valued entries. This ensures clips which mix boxes with and
5893 // without time to sample entries don't pickup uninitialized data.
5894 493 memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0,
5895 493 sc->tts_allocated_size - old_allocated_size);
5896
5897
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (index_entry_pos < sti->nb_index_entries) {
5898 // Make hole in index_entries and tts_data for new samples
5899 memmove(sti->index_entries + index_entry_pos + entries,
5900 sti->index_entries + index_entry_pos,
5901 sizeof(*sti->index_entries) *
5902 (sti->nb_index_entries - index_entry_pos));
5903 memmove(sc->tts_data + index_entry_pos + entries,
5904 sc->tts_data + index_entry_pos,
5905 sizeof(*sc->tts_data) * (sc->tts_count - index_entry_pos));
5906 if (index_entry_pos < sc->current_sample) {
5907 sc->current_sample += entries;
5908 }
5909 }
5910
5911 493 sti->nb_index_entries += entries;
5912 493 sc->tts_count = sti->nb_index_entries;
5913 493 sc->stts_count = sti->nb_index_entries;
5914
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 107 times.
493 if (flags & MOV_TRUN_SAMPLE_CTS)
5915 386 sc->ctts_count = sti->nb_index_entries;
5916
5917 // Record the index_entry position in frag_index of this fragment
5918
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (frag_stream_info) {
5919 493 frag_stream_info->index_entry = index_entry_pos;
5920
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (frag_stream_info->index_base < 0)
5921 493 frag_stream_info->index_base = index_entry_pos;
5922 }
5923
5924
2/2
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 23 times.
493 if (index_entry_pos > 0)
5925 470 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
5926
5927
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++) {
5928 8514 unsigned sample_size = frag->size;
5929
2/2
✓ Branch 0 taken 8021 times.
✓ Branch 1 taken 493 times.
8514 int sample_flags = i ? frag->flags : first_sample_flags;
5930 8514 unsigned sample_duration = frag->duration;
5931 8514 unsigned ctts_duration = 0;
5932 8514 int keyframe = 0;
5933 8514 int index_entry_flags = 0;
5934
5935
2/2
✓ Branch 0 taken 1674 times.
✓ Branch 1 taken 6840 times.
8514 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
5936
2/2
✓ Branch 0 taken 8456 times.
✓ Branch 1 taken 58 times.
8514 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
5937
2/2
✓ Branch 0 taken 933 times.
✓ Branch 1 taken 7581 times.
8514 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
5938
2/2
✓ Branch 0 taken 6576 times.
✓ Branch 1 taken 1938 times.
8514 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
5939
5940 8514 mov_update_dts_shift(sc, ctts_duration, c->fc);
5941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8514 times.
8514 if (pts != AV_NOPTS_VALUE) {
5942 dts = pts - sc->dts_shift;
5943 if (flags & MOV_TRUN_SAMPLE_CTS) {
5944 dts -= ctts_duration;
5945 } else {
5946 dts -= sc->time_offset;
5947 }
5948 av_log(c->fc, AV_LOG_DEBUG,
5949 "pts %"PRId64" calculated dts %"PRId64
5950 " sc->dts_shift %d ctts.duration %d"
5951 " sc->time_offset %"PRId64
5952 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
5953 pts, dts,
5954 sc->dts_shift, ctts_duration,
5955 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
5956 pts = AV_NOPTS_VALUE;
5957 }
5958
5959 8514 keyframe =
5960 8514 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
5961 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
5962
2/2
✓ Branch 0 taken 548 times.
✓ Branch 1 taken 7966 times.
8514 if (keyframe) {
5963 548 distance = 0;
5964 548 index_entry_flags |= AVINDEX_KEYFRAME;
5965 }
5966 // Fragments can overlap in time. Discard overlapping frames after
5967 // decoding.
5968
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8490 times.
8514 if (prev_dts >= dts)
5969 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
5970
5971 8514 sti->index_entries[index_entry_pos].pos = offset;
5972 8514 sti->index_entries[index_entry_pos].timestamp = dts;
5973 8514 sti->index_entries[index_entry_pos].size = sample_size;
5974 8514 sti->index_entries[index_entry_pos].min_distance = distance;
5975 8514 sti->index_entries[index_entry_pos].flags = index_entry_flags;
5976
5977 8514 sc->tts_data[index_entry_pos].count = 1;
5978 8514 sc->tts_data[index_entry_pos].offset = ctts_duration;
5979 8514 sc->tts_data[index_entry_pos].duration = sample_duration;
5980 8514 index_entry_pos++;
5981
5982 8514 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
5983 "size %u, distance %d, keyframe %d\n", st->index,
5984 index_entry_pos, offset, dts, sample_size, distance, keyframe);
5985 8514 distance++;
5986
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8514 times.
8514 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
5987 return AVERROR_INVALIDDATA;
5988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8514 times.
8514 if (!sample_size)
5989 return AVERROR_INVALIDDATA;
5990 8514 dts += sample_duration;
5991 8514 offset += sample_size;
5992 8514 sc->data_size += sample_size;
5993
5994
1/2
✓ Branch 0 taken 8514 times.
✗ Branch 1 not taken.
8514 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
5995
1/2
✓ Branch 0 taken 8514 times.
✗ Branch 1 not taken.
8514 1 <= INT_MAX - sc->nb_frames_for_fps
5996 ) {
5997 8514 sc->duration_for_fps += sample_duration;
5998 8514 sc->nb_frames_for_fps ++;
5999 }
6000 }
6001
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (frag_stream_info)
6002 493 frag_stream_info->next_trun_dts = dts + sc->time_offset;
6003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (i < entries) {
6004 // EOF found before reading all entries. Fix the hole this would
6005 // leave in index_entries and tts_data
6006 int gap = entries - i;
6007 memmove(sti->index_entries + index_entry_pos,
6008 sti->index_entries + index_entry_pos + gap,
6009 sizeof(*sti->index_entries) *
6010 (sti->nb_index_entries - (index_entry_pos + gap)));
6011 memmove(sc->tts_data + index_entry_pos,
6012 sc->tts_data + index_entry_pos + gap,
6013 sizeof(*sc->tts_data) *
6014 (sc->tts_count - (index_entry_pos + gap)));
6015
6016 sti->nb_index_entries -= gap;
6017 sc->tts_count -= gap;
6018 if (index_entry_pos < sc->current_sample) {
6019 sc->current_sample -= gap;
6020 }
6021 entries = i;
6022 }
6023
6024 // The end of this new fragment may overlap in time with the start
6025 // of the next fragment in index_entries. Mark the samples in the next
6026 // fragment that overlap with AVINDEX_DISCARD_FRAME
6027 493 prev_dts = AV_NOPTS_VALUE;
6028
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (index_entry_pos > 0)
6029 493 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
6031 if (prev_dts < sti->index_entries[i].timestamp)
6032 break;
6033 sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6034 }
6035
6036 // If a hole was created to insert the new index_entries into,
6037 // the index_entry recorded for all subsequent moof must
6038 // be incremented by the number of entries inserted.
6039 493 fix_frag_index_entries(&c->frag_index, next_frag_index,
6040 493 frag->track_id, entries);
6041
6042
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (pb->eof_reached) {
6043 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6044 return AVERROR_EOF;
6045 }
6046
6047 493 frag->implicit_offset = offset;
6048
6049 493 sc->track_end = dts + sc->time_offset;
6050
2/2
✓ Branch 0 taken 113 times.
✓ Branch 1 taken 380 times.
493 if (st->duration < sc->track_end)
6051 113 st->duration = sc->track_end;
6052
6053 493 return 0;
6054 }
6055
6056 44 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6057 {
6058 44 int64_t stream_size = avio_size(pb);
6059 44 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6060 uint8_t version, is_complete;
6061 int64_t offadd;
6062 unsigned i, j, track_id, item_count;
6063 44 AVStream *st = NULL;
6064 44 AVStream *ref_st = NULL;
6065 44 MOVStreamContext *sc, *ref_sc = NULL;
6066 AVRational timescale;
6067
6068 44 version = avio_r8(pb);
6069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (version > 1) {
6070 avpriv_request_sample(c->fc, "sidx version %u", version);
6071 return 0;
6072 }
6073
6074 44 avio_rb24(pb); // flags
6075
6076 44 track_id = avio_rb32(pb); // Reference ID
6077
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 for (i = 0; i < c->fc->nb_streams; i++) {
6078 44 sc = c->fc->streams[i]->priv_data;
6079
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 if (sc->id == track_id) {
6080 44 st = c->fc->streams[i];
6081 44 break;
6082 }
6083 }
6084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (!st) {
6085 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6086 return 0;
6087 }
6088
6089 44 sc = st->priv_data;
6090
6091 44 timescale = av_make_q(1, avio_rb32(pb));
6092
6093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (timescale.den <= 0) {
6094 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6095 return AVERROR_INVALIDDATA;
6096 }
6097
6098
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 1 times.
44 if (version == 0) {
6099 43 pts = avio_rb32(pb);
6100 43 offadd= avio_rb32(pb);
6101 } else {
6102 1 pts = avio_rb64(pb);
6103 1 offadd= avio_rb64(pb);
6104 }
6105
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
44 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6106 return AVERROR_INVALIDDATA;
6107
6108 44 offset += (uint64_t)offadd;
6109
6110 44 avio_rb16(pb); // reserved
6111
6112 44 item_count = avio_rb16(pb);
6113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (item_count == 0)
6114 return AVERROR_INVALIDDATA;
6115
6116
2/2
✓ Branch 0 taken 369 times.
✓ Branch 1 taken 44 times.
413 for (i = 0; i < item_count; i++) {
6117 int index;
6118 MOVFragmentStreamInfo * frag_stream_info;
6119 369 uint32_t size = avio_rb32(pb);
6120 369 uint32_t duration = avio_rb32(pb);
6121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 369 times.
369 if (size & 0x80000000) {
6122 avpriv_request_sample(c->fc, "sidx reference_type 1");
6123 return AVERROR_PATCHWELCOME;
6124 }
6125 369 avio_rb32(pb); // sap_flags
6126 369 timestamp = av_rescale_q(pts, timescale, st->time_base);
6127
6128 369 index = update_frag_index(c, offset);
6129 369 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6130
1/2
✓ Branch 0 taken 369 times.
✗ Branch 1 not taken.
369 if (frag_stream_info)
6131 369 frag_stream_info->sidx_pts = timestamp;
6132
6133
1/2
✓ Branch 1 taken 369 times.
✗ Branch 2 not taken.
369 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6134
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 369 times.
369 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6135 )
6136 return AVERROR_INVALIDDATA;
6137 369 offset += size;
6138 369 pts += duration;
6139 }
6140
6141 44 st->duration = sc->track_end = pts;
6142
6143 44 sc->has_sidx = 1;
6144
6145 // See if the remaining bytes are just an mfra which we can ignore.
6146 44 is_complete = offset == stream_size;
6147
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 ) {
6148 int64_t ret;
6149 38 int64_t original_pos = avio_tell(pb);
6150
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
38 if (!c->have_read_mfra_size) {
6151
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6152 return ret;
6153 3 c->mfra_size = avio_rb32(pb);
6154 3 c->have_read_mfra_size = 1;
6155
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6156 return ret;
6157 }
6158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (offset == stream_size - c->mfra_size)
6159 is_complete = 1;
6160 }
6161
6162
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 39 times.
44 if (is_complete) {
6163 // Find first entry in fragment index that came from an sidx.
6164 // This will pretty much always be the first entry.
6165
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 5 times.
373 for (i = 0; i < c->frag_index.nb_items; i++) {
6166 368 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6167
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++) {
6168 MOVFragmentStreamInfo * si;
6169 5 si = &item->stream_info[j];
6170
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (si->sidx_pts != AV_NOPTS_VALUE) {
6171 5 ref_st = c->fc->streams[j];
6172 5 ref_sc = ref_st->priv_data;
6173 5 break;
6174 }
6175 }
6176 }
6177
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++) {
6178 5 st = c->fc->streams[i];
6179 5 sc = st->priv_data;
6180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->has_sidx) {
6181 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6182 }
6183 }
6184
6185 5 c->frag_index.complete = 1;
6186 }
6187
6188 44 return 0;
6189 }
6190
6191 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6192 /* like the files created with Adobe Premiere 5.0, for samples see */
6193 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6194 271 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6195 {
6196 int err;
6197
6198
1/2
✓ Branch 0 taken 271 times.
✗ Branch 1 not taken.
271 if (atom.size < 8)
6199 271 return 0; /* continue */
6200 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6201 avio_skip(pb, atom.size - 4);
6202 return 0;
6203 }
6204 atom.type = avio_rl32(pb);
6205 atom.size -= 8;
6206 if (atom.type != MKTAG('m','d','a','t')) {
6207 avio_skip(pb, atom.size);
6208 return 0;
6209 }
6210 err = mov_read_mdat(c, pb, atom);
6211 return err;
6212 }
6213
6214 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6215 {
6216 #if CONFIG_ZLIB
6217 FFIOContext ctx;
6218 uint8_t *cmov_data;
6219 uint8_t *moov_data; /* uncompressed data */
6220 long cmov_len, moov_len;
6221 3 int ret = -1;
6222
6223 3 avio_rb32(pb); /* dcom atom */
6224
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6225 return AVERROR_INVALIDDATA;
6226
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6227 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6228 return AVERROR_INVALIDDATA;
6229 }
6230 3 avio_rb32(pb); /* cmvd atom */
6231
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6232 return AVERROR_INVALIDDATA;
6233 3 moov_len = avio_rb32(pb); /* uncompressed size */
6234 3 cmov_len = atom.size - 6 * 4;
6235
6236 3 cmov_data = av_malloc(cmov_len);
6237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6238 return AVERROR(ENOMEM);
6239 3 moov_data = av_malloc(moov_len);
6240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6241 av_free(cmov_data);
6242 return AVERROR(ENOMEM);
6243 }
6244 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6246 goto free_and_return;
6247
6248 3 ret = AVERROR_INVALIDDATA;
6249
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)
6250 goto free_and_return;
6251 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6252 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6253 3 atom.type = MKTAG('m','o','o','v');
6254 3 atom.size = moov_len;
6255 3 ret = mov_read_default(c, &ctx.pub, atom);
6256 3 free_and_return:
6257 3 av_free(moov_data);
6258 3 av_free(cmov_data);
6259 3 return ret;
6260 #else
6261 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6262 return AVERROR(ENOSYS);
6263 #endif
6264 }
6265
6266 /* edit list atom */
6267 446 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6268 {
6269 MOVStreamContext *sc;
6270 int i, edit_count, version;
6271 int64_t elst_entry_size;
6272
6273
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)
6274 return 0;
6275 446 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6276
6277 446 version = avio_r8(pb); /* version */
6278 446 avio_rb24(pb); /* flags */
6279 446 edit_count = avio_rb32(pb); /* entries */
6280 446 atom.size -= 8;
6281
6282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 446 times.
446 elst_entry_size = version == 1 ? 20 : 12;
6283
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 445 times.
446 if (atom.size != edit_count * elst_entry_size) {
6284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6285 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6286 edit_count, atom.size + 8);
6287 return AVERROR_INVALIDDATA;
6288 } else {
6289 1 edit_count = atom.size / elst_entry_size;
6290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6291 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6292 }
6293 }
6294 }
6295
6296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 446 times.
446 if (!edit_count)
6297 return 0;
6298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 446 times.
446 if (sc->elst_data)
6299 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6300 446 av_free(sc->elst_data);
6301 446 sc->elst_count = 0;
6302 446 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 446 times.
446 if (!sc->elst_data)
6304 return AVERROR(ENOMEM);
6305
6306 446 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6307
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++) {
6308 473 MOVElst *e = &sc->elst_data[i];
6309
6310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 473 times.
473 if (version == 1) {
6311 e->duration = avio_rb64(pb);
6312 e->time = avio_rb64(pb);
6313 atom.size -= 16;
6314 } else {
6315 473 e->duration = avio_rb32(pb); /* segment duration */
6316 473 e->time = (int32_t)avio_rb32(pb); /* media time */
6317 473 atom.size -= 8;
6318 }
6319 473 e->rate = avio_rb32(pb) / 65536.0;
6320 473 atom.size -= 4;
6321 473 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6322 473 e->duration, e->time, e->rate);
6323
6324
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 &&
6325 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6326 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6327 c->fc->nb_streams-1, i, e->time);
6328 return AVERROR_INVALIDDATA;
6329 }
6330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 473 times.
473 if (e->duration < 0) {
6331 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list duration=%"PRId64"\n",
6332 c->fc->nb_streams-1, i, e->duration);
6333 return AVERROR_INVALIDDATA;
6334 }
6335 }
6336 446 sc->elst_count = i;
6337
6338 446 return 0;
6339 }
6340
6341 18 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6342 {
6343 MOVStreamContext *sc;
6344
6345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->fc->nb_streams < 1)
6346 return AVERROR_INVALIDDATA;
6347 18 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6348 18 sc->timecode_track = avio_rb32(pb);
6349 18 return 0;
6350 }
6351
6352 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6353 {
6354 AVStream *st;
6355 int version, color_range, color_primaries, color_trc, color_space;
6356
6357 if (c->fc->nb_streams < 1)
6358 return 0;
6359 st = c->fc->streams[c->fc->nb_streams - 1];
6360
6361 if (atom.size < 5) {
6362 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6363 return AVERROR_INVALIDDATA;
6364 }
6365
6366 version = avio_r8(pb);
6367 if (version != 1) {
6368 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6369 return 0;
6370 }
6371 avio_skip(pb, 3); /* flags */
6372
6373 avio_skip(pb, 2); /* profile + level */
6374 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6375 color_primaries = avio_r8(pb);
6376 color_trc = avio_r8(pb);
6377 color_space = avio_r8(pb);
6378 if (avio_rb16(pb)) /* codecIntializationDataSize */
6379 return AVERROR_INVALIDDATA;
6380
6381 if (!av_color_primaries_name(color_primaries))
6382 color_primaries = AVCOL_PRI_UNSPECIFIED;
6383 if (!av_color_transfer_name(color_trc))
6384 color_trc = AVCOL_TRC_UNSPECIFIED;
6385 if (!av_color_space_name(color_space))
6386 color_space = AVCOL_SPC_UNSPECIFIED;
6387
6388 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6389 st->codecpar->color_primaries = color_primaries;
6390 st->codecpar->color_trc = color_trc;
6391 st->codecpar->color_space = color_space;
6392
6393 return 0;
6394 }
6395
6396 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6397 {
6398 MOVStreamContext *sc;
6399 int i, version;
6400
6401 if (c->fc->nb_streams < 1)
6402 return AVERROR_INVALIDDATA;
6403
6404 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6405
6406 if (atom.size < 5) {
6407 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6408 return AVERROR_INVALIDDATA;
6409 }
6410
6411 version = avio_r8(pb);
6412 if (version) {
6413 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6414 return 0;
6415 }
6416 if (sc->mastering) {
6417 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6418 return 0;
6419 }
6420
6421 avio_skip(pb, 3); /* flags */
6422
6423 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6424 if (!sc->mastering)
6425 return AVERROR(ENOMEM);
6426
6427 for (i = 0; i < 3; i++) {
6428 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6429 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6430 }
6431 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6432 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6433
6434 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6435 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6436
6437 sc->mastering->has_primaries = 1;
6438 sc->mastering->has_luminance = 1;
6439
6440 return 0;
6441 }
6442
6443 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6444 {
6445 MOVStreamContext *sc;
6446 const int mapping[3] = {1, 2, 0};
6447 const int chroma_den = 50000;
6448 const int luma_den = 10000;
6449 int i;
6450
6451 if (c->fc->nb_streams < 1)
6452 return AVERROR_INVALIDDATA;
6453
6454 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6455
6456 if (atom.size < 24) {
6457 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6458 return AVERROR_INVALIDDATA;
6459 }
6460
6461 if (sc->mastering) {
6462 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6463 return 0;
6464 }
6465
6466 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6467 if (!sc->mastering)
6468 return AVERROR(ENOMEM);
6469
6470 for (i = 0; i < 3; i++) {
6471 const int j = mapping[i];
6472 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6473 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6474 }
6475 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6476 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6477
6478 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6479 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6480
6481 sc->mastering->has_luminance = 1;
6482 sc->mastering->has_primaries = 1;
6483
6484 return 0;
6485 }
6486
6487 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6488 {
6489 MOVStreamContext *sc;
6490 int version;
6491
6492 if (c->fc->nb_streams < 1)
6493 return AVERROR_INVALIDDATA;
6494
6495 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6496
6497 if (atom.size < 5) {
6498 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
6499 return AVERROR_INVALIDDATA;
6500 }
6501
6502 version = avio_r8(pb);
6503 if (version) {
6504 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
6505 return 0;
6506 }
6507 avio_skip(pb, 3); /* flags */
6508
6509 if (sc->coll){
6510 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
6511 return 0;
6512 }
6513
6514 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6515 if (!sc->coll)
6516 return AVERROR(ENOMEM);
6517
6518 sc->coll->MaxCLL = avio_rb16(pb);
6519 sc->coll->MaxFALL = avio_rb16(pb);
6520
6521 return 0;
6522 }
6523
6524 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6525 {
6526 MOVStreamContext *sc;
6527
6528 if (c->fc->nb_streams < 1)
6529 return AVERROR_INVALIDDATA;
6530
6531 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6532
6533 if (atom.size < 4) {
6534 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
6535 return AVERROR_INVALIDDATA;
6536 }
6537
6538 if (sc->coll){
6539 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
6540 return 0;
6541 }
6542
6543 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6544 if (!sc->coll)
6545 return AVERROR(ENOMEM);
6546
6547 sc->coll->MaxCLL = avio_rb16(pb);
6548 sc->coll->MaxFALL = avio_rb16(pb);
6549
6550 return 0;
6551 }
6552
6553 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6554 {
6555 MOVStreamContext *sc;
6556 4 const int illuminance_den = 10000;
6557 4 const int ambient_den = 50000;
6558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
6559 return AVERROR_INVALIDDATA;
6560 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
6562 av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
6563 return AVERROR_INVALIDDATA;
6564 }
6565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
6566 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
6567 return 0;
6568 }
6569 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
6570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
6571 return AVERROR(ENOMEM);
6572 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
6573 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
6574 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
6575 4 return 0;
6576 }
6577
6578 1 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6579 {
6580 AVStream *st;
6581 MOVStreamContext *sc;
6582 enum AVStereo3DType type;
6583 int mode;
6584
6585
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6586 return 0;
6587
6588 1 st = c->fc->streams[c->fc->nb_streams - 1];
6589 1 sc = st->priv_data;
6590
6591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 5) {
6592 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
6593 return AVERROR_INVALIDDATA;
6594 }
6595
6596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sc->stereo3d)
6597 return AVERROR_INVALIDDATA;
6598
6599 1 avio_skip(pb, 4); /* version + flags */
6600
6601 1 mode = avio_r8(pb);
6602
1/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 switch (mode) {
6603 1 case 0:
6604 1 type = AV_STEREO3D_2D;
6605 1 break;
6606 case 1:
6607 type = AV_STEREO3D_TOPBOTTOM;
6608 break;
6609 case 2:
6610 type = AV_STEREO3D_SIDEBYSIDE;
6611 break;
6612 default:
6613 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
6614 return 0;
6615 }
6616
6617 1 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->stereo3d)
6619 return AVERROR(ENOMEM);
6620
6621 1 sc->stereo3d->type = type;
6622 1 return 0;
6623 }
6624
6625 static int mov_read_pack(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6626 {
6627 AVStream *st;
6628 MOVStreamContext *sc;
6629 int size = 0;
6630 int64_t remaining;
6631 uint32_t tag = 0;
6632 enum AVStereo3DType type = AV_STEREO3D_2D;
6633
6634 if (c->fc->nb_streams < 1)
6635 return 0;
6636
6637 st = c->fc->streams[c->fc->nb_streams - 1];
6638 sc = st->priv_data;
6639
6640 remaining = atom.size;
6641 while (remaining > 0) {
6642 size = avio_rb32(pb);
6643 if (size < 8 || size > remaining ) {
6644 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in pack box\n");
6645 return AVERROR_INVALIDDATA;
6646 }
6647
6648 tag = avio_rl32(pb);
6649 switch (tag) {
6650 case MKTAG('p','k','i','n'): {
6651 if (size != 16) {
6652 av_log(c->fc, AV_LOG_ERROR, "Invalid size of pkin box: %d\n", size);
6653 return AVERROR_INVALIDDATA;
6654 }
6655 avio_skip(pb, 1); // version
6656 avio_skip(pb, 3); // flags
6657
6658 tag = avio_rl32(pb);
6659 switch (tag) {
6660 case MKTAG('s','i','d','e'):
6661 type = AV_STEREO3D_SIDEBYSIDE;
6662 break;
6663 case MKTAG('o','v','e','r'):
6664 type = AV_STEREO3D_TOPBOTTOM;
6665 break;
6666 case 0:
6667 // This means value will be set in another layer
6668 break;
6669 default:
6670 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pkin: 0x%08X\n", tag);
6671 avio_skip(pb, size - 8);
6672 break;
6673 }
6674
6675 break;
6676 }
6677 default:
6678 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pack: 0x%08X\n", tag);
6679 avio_skip(pb, size - 8);
6680 break;
6681 }
6682 remaining -= size;
6683 }
6684
6685 if (remaining != 0) {
6686 av_log(c->fc, AV_LOG_ERROR, "Broken pack box\n");
6687 return AVERROR_INVALIDDATA;
6688 }
6689
6690 if (type == AV_STEREO3D_2D)
6691 return 0;
6692
6693 if (!sc->stereo3d) {
6694 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6695 if (!sc->stereo3d)
6696 return AVERROR(ENOMEM);
6697 }
6698
6699 sc->stereo3d->type = type;
6700
6701 return 0;
6702 }
6703
6704 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6705 {
6706 AVStream *st;
6707 MOVStreamContext *sc;
6708 int size, version, layout;
6709 int32_t yaw, pitch, roll;
6710 1 uint32_t l = 0, t = 0, r = 0, b = 0;
6711 1 uint32_t tag, padding = 0;
6712 enum AVSphericalProjection projection;
6713
6714
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6715 return 0;
6716
6717 1 st = c->fc->streams[c->fc->nb_streams - 1];
6718 1 sc = st->priv_data;
6719
6720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
6721 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
6722 return AVERROR_INVALIDDATA;
6723 }
6724
6725 1 size = avio_rb32(pb);
6726
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)
6727 return AVERROR_INVALIDDATA;
6728
6729 1 tag = avio_rl32(pb);
6730
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
6731 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
6732 return 0;
6733 }
6734 1 version = avio_r8(pb);
6735
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6736 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6737 version);
6738 return 0;
6739 }
6740 1 avio_skip(pb, 3); /* flags */
6741 1 avio_skip(pb, size - 12); /* metadata_source */
6742
6743 1 size = avio_rb32(pb);
6744
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6745 return AVERROR_INVALIDDATA;
6746
6747 1 tag = avio_rl32(pb);
6748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
6749 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
6750 return 0;
6751 }
6752
6753 1 size = avio_rb32(pb);
6754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6755 return AVERROR_INVALIDDATA;
6756
6757 1 tag = avio_rl32(pb);
6758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
6759 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
6760 return 0;
6761 }
6762 1 version = avio_r8(pb);
6763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6764 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6765 version);
6766 return 0;
6767 }
6768 1 avio_skip(pb, 3); /* flags */
6769
6770 /* 16.16 fixed point */
6771 1 yaw = avio_rb32(pb);
6772 1 pitch = avio_rb32(pb);
6773 1 roll = avio_rb32(pb);
6774
6775 1 size = avio_rb32(pb);
6776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6777 return AVERROR_INVALIDDATA;
6778
6779 1 tag = avio_rl32(pb);
6780 1 version = avio_r8(pb);
6781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6782 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6783 version);
6784 return 0;
6785 }
6786 1 avio_skip(pb, 3); /* flags */
6787
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
6788 case MKTAG('c','b','m','p'):
6789 layout = avio_rb32(pb);
6790 if (layout) {
6791 av_log(c->fc, AV_LOG_WARNING,
6792 "Unsupported cubemap layout %d\n", layout);
6793 return 0;
6794 }
6795 projection = AV_SPHERICAL_CUBEMAP;
6796 padding = avio_rb32(pb);
6797 break;
6798 1 case MKTAG('e','q','u','i'):
6799 1 t = avio_rb32(pb);
6800 1 b = avio_rb32(pb);
6801 1 l = avio_rb32(pb);
6802 1 r = avio_rb32(pb);
6803
6804
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) {
6805 av_log(c->fc, AV_LOG_ERROR,
6806 "Invalid bounding rectangle coordinates "
6807 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
6808 return AVERROR_INVALIDDATA;
6809 }
6810
6811
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)
6812 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
6813 else
6814 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6815 1 break;
6816 default:
6817 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
6818 return 0;
6819 }
6820
6821 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
6823 return AVERROR(ENOMEM);
6824
6825 1 sc->spherical->projection = projection;
6826
6827 1 sc->spherical->yaw = yaw;
6828 1 sc->spherical->pitch = pitch;
6829 1 sc->spherical->roll = roll;
6830
6831 1 sc->spherical->padding = padding;
6832
6833 1 sc->spherical->bound_left = l;
6834 1 sc->spherical->bound_top = t;
6835 1 sc->spherical->bound_right = r;
6836 1 sc->spherical->bound_bottom = b;
6837
6838 1 return 0;
6839 }
6840
6841 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6842 {
6843 AVStream *st;
6844 MOVStreamContext *sc;
6845 int size;
6846 uint32_t tag;
6847 enum AVSphericalProjection projection;
6848
6849
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6850 return 0;
6851
6852 3 st = c->fc->streams[c->fc->nb_streams - 1];
6853 3 sc = st->priv_data;
6854
6855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 16) {
6856 av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
6857 return AVERROR_INVALIDDATA;
6858 }
6859
6860 3 size = avio_rb32(pb);
6861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 16) {
6862 av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
6863 return AVERROR_INVALIDDATA;
6864 }
6865
6866 3 tag = avio_rl32(pb);
6867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
6868 av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: 0x%08X\n", tag);
6869 return AVERROR_INVALIDDATA;
6870 }
6871
6872 3 avio_skip(pb, 1); // version
6873 3 avio_skip(pb, 3); // flags
6874
6875 3 tag = avio_rl32(pb);
6876
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) {
6877 3 case MKTAG('r','e','c','t'):
6878 3 projection = AV_SPHERICAL_RECTILINEAR;
6879 3 break;
6880 case MKTAG('e','q','u','i'):
6881 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6882 break;
6883 case MKTAG('h','e','q','u'):
6884 projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
6885 break;
6886 case MKTAG('f','i','s','h'):
6887 projection = AV_SPHERICAL_FISHEYE;
6888 break;
6889 case MKTAG('p','r','i','m'):
6890 projection = AV_SPHERICAL_PARAMETRIC_IMMERSIVE;
6891 break;
6892 default:
6893 av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: 0x%08X\n", tag);
6894 return AVERROR_INVALIDDATA;
6895 }
6896
6897 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6898
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
6899 return AVERROR(ENOMEM);
6900
6901 3 sc->spherical->projection = projection;
6902
6903 3 return 0;
6904 }
6905
6906 3 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6907 {
6908 AVStream *st;
6909 MOVStreamContext *sc;
6910 3 int size, flags = 0;
6911 int64_t remaining;
6912 3 uint32_t tag, baseline = 0;
6913 3 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
6914 3 enum AVStereo3DType type = AV_STEREO3D_2D;
6915 3 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
6916 3 AVRational horizontal_disparity_adjustment = { 0, 1 };
6917
6918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6919 return 0;
6920
6921 3 st = c->fc->streams[c->fc->nb_streams - 1];
6922 3 sc = st->priv_data;
6923
6924 3 remaining = atom.size;
6925
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 while (remaining > 0) {
6926 9 size = avio_rb32(pb);
6927
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 ) {
6928 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
6929 return AVERROR_INVALIDDATA;
6930 }
6931
6932 9 tag = avio_rl32(pb);
6933
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) {
6934 3 case MKTAG('s','t','r','i'): {
6935 int has_right, has_left;
6936 uint8_t tmp;
6937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 13) {
6938 av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
6939 return AVERROR_INVALIDDATA;
6940 }
6941 3 avio_skip(pb, 1); // version
6942 3 avio_skip(pb, 3); // flags
6943
6944 3 tmp = avio_r8(pb);
6945
6946 // eye_views_reversed
6947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tmp & 8) {
6948 flags |= AV_STEREO3D_FLAG_INVERT;
6949 }
6950 // has_additional_views
6951 3 if (tmp & 4) {
6952 // skip...
6953 }
6954
6955 3 has_right = tmp & 2; // has_right_eye_view
6956 3 has_left = tmp & 1; // has_left_eye_view
6957
6958
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)
6959 3 view = AV_STEREO3D_VIEW_PACKED;
6960 else if (has_left)
6961 view = AV_STEREO3D_VIEW_LEFT;
6962 else if (has_right)
6963 view = AV_STEREO3D_VIEW_RIGHT;
6964
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)
6965 3 type = AV_STEREO3D_UNSPEC;
6966
6967 3 break;
6968 }
6969 case MKTAG('h','e','r','o'): {
6970 int tmp;
6971 if (size != 13) {
6972 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
6973 return AVERROR_INVALIDDATA;
6974 }
6975 avio_skip(pb, 1); // version
6976 avio_skip(pb, 3); // flags
6977
6978 tmp = avio_r8(pb);
6979 if (tmp == 0)
6980 primary_eye = AV_PRIMARY_EYE_NONE;
6981 else if (tmp == 1)
6982 primary_eye = AV_PRIMARY_EYE_LEFT;
6983 else if (tmp == 2)
6984 primary_eye = AV_PRIMARY_EYE_RIGHT;
6985 else
6986 av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
6987
6988 break;
6989 }
6990 3 case MKTAG('c','a','m','s'): {
6991 uint32_t subtag;
6992 int subsize;
6993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
6994 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
6995 return AVERROR_INVALIDDATA;
6996 }
6997
6998 3 subsize = avio_rb32(pb);
6999
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7000 av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
7001 return AVERROR_INVALIDDATA;
7002 }
7003
7004 3 subtag = avio_rl32(pb);
7005
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
7006 av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got 0x%08X\n", subtag);
7007 return AVERROR_INVALIDDATA;
7008 }
7009
7010 3 avio_skip(pb, 1); // version
7011 3 avio_skip(pb, 3); // flags
7012
7013 3 baseline = avio_rb32(pb);
7014
7015 3 break;
7016 }
7017 3 case MKTAG('c','m','f','y'): {
7018 uint32_t subtag;
7019 int subsize;
7020 int32_t adjustment;
7021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7022 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
7023 return AVERROR_INVALIDDATA;
7024 }
7025
7026 3 subsize = avio_rb32(pb);
7027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7028 av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
7029 return AVERROR_INVALIDDATA;
7030 }
7031
7032 3 subtag = avio_rl32(pb);
7033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
7034 av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got 0x%08X\n", subtag);
7035 return AVERROR_INVALIDDATA;
7036 }
7037
7038 3 avio_skip(pb, 1); // version
7039 3 avio_skip(pb, 3); // flags
7040
7041 3 adjustment = (int32_t) avio_rb32(pb);
7042
7043 3 horizontal_disparity_adjustment.num = (int) adjustment;
7044 3 horizontal_disparity_adjustment.den = 10000;
7045
7046 3 break;
7047 }
7048 default:
7049 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: 0x%08X\n", tag);
7050 avio_skip(pb, size - 8);
7051 break;
7052 }
7053 9 remaining -= size;
7054 }
7055
7056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7057 av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
7058 return AVERROR_INVALIDDATA;
7059 }
7060
7061
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (type == AV_STEREO3D_2D)
7062 return 0;
7063
7064
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->stereo3d) {
7065 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7067 return AVERROR(ENOMEM);
7068 }
7069
7070 3 sc->stereo3d->flags = flags;
7071 3 sc->stereo3d->type = type;
7072 3 sc->stereo3d->view = view;
7073 3 sc->stereo3d->primary_eye = primary_eye;
7074 3 sc->stereo3d->baseline = baseline;
7075 3 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
7076
7077 3 return 0;
7078 }
7079
7080 3 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7081 {
7082 int size;
7083 int64_t remaining;
7084 uint32_t tag;
7085
7086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7087 return 0;
7088
7089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8) {
7090 av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
7091 return AVERROR_INVALIDDATA;
7092 }
7093
7094 3 remaining = atom.size;
7095
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 while (remaining > 0) {
7096 6 size = avio_rb32(pb);
7097
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 ) {
7098 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
7099 return AVERROR_INVALIDDATA;
7100 }
7101
7102 6 tag = avio_rl32(pb);
7103
2/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 switch (tag) {
7104 3 case MKTAG('p','r','o','j'): {
7105 3 MOVAtom proj = { tag, size - 8 };
7106 3 int ret = mov_read_vexu_proj(c, pb, proj);
7107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7108 return ret;
7109 3 break;
7110 }
7111 3 case MKTAG('e','y','e','s'): {
7112 3 MOVAtom eyes = { tag, size - 8 };
7113 3 int ret = mov_read_eyes(c, pb, eyes);
7114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7115 return ret;
7116 3 break;
7117 }
7118 case MKTAG('p','a','c','k'): {
7119 MOVAtom pack = { tag, size - 8 };
7120 int ret = mov_read_pack(c, pb, pack);
7121 if (ret < 0)
7122 return ret;
7123 break;
7124 }
7125 default:
7126 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: 0x%08X\n", tag);
7127 avio_skip(pb, size - 8);
7128 break;
7129 }
7130 6 remaining -= size;
7131 }
7132
7133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7134 av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7135 return AVERROR_INVALIDDATA;
7136 }
7137
7138 3 return 0;
7139 }
7140
7141 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7142 {
7143 AVStream *st;
7144 MOVStreamContext *sc;
7145
7146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7147 return 0;
7148
7149 3 st = c->fc->streams[c->fc->nb_streams - 1];
7150 3 sc = st->priv_data;
7151
7152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7153 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7154 return AVERROR_INVALIDDATA;
7155 }
7156
7157
7158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7159 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7160 if (!sc->stereo3d)
7161 return AVERROR(ENOMEM);
7162 }
7163
7164 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7165 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7166
7167 3 return 0;
7168 }
7169
7170 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7171 {
7172 int ret = 0;
7173 uint8_t *buffer = av_malloc(len + 1);
7174 const char *val;
7175
7176 if (!buffer)
7177 return AVERROR(ENOMEM);
7178 buffer[len] = '\0';
7179
7180 ret = ffio_read_size(pb, buffer, len);
7181 if (ret < 0)
7182 goto out;
7183
7184 /* Check for mandatory keys and values, try to support XML as best-effort */
7185 if (!sc->spherical &&
7186 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7187 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7188 av_stristr(val, "true") &&
7189 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7190 av_stristr(val, "true") &&
7191 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7192 av_stristr(val, "equirectangular")) {
7193 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7194 if (!sc->spherical)
7195 goto out;
7196
7197 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7198
7199 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7200 enum AVStereo3DType mode;
7201
7202 if (av_stristr(buffer, "left-right"))
7203 mode = AV_STEREO3D_SIDEBYSIDE;
7204 else if (av_stristr(buffer, "top-bottom"))
7205 mode = AV_STEREO3D_TOPBOTTOM;
7206 else
7207 mode = AV_STEREO3D_2D;
7208
7209 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7210 if (!sc->stereo3d)
7211 goto out;
7212
7213 sc->stereo3d->type = mode;
7214 }
7215
7216 /* orientation */
7217 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7218 if (val)
7219 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7220 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7221 if (val)
7222 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7223 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7224 if (val)
7225 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7226 }
7227
7228 out:
7229 av_free(buffer);
7230 return ret;
7231 }
7232
7233 69 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7234 {
7235 AVStream *st;
7236 MOVStreamContext *sc;
7237 int64_t ret;
7238 AVUUID uuid;
7239 static const AVUUID uuid_isml_manifest = {
7240 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7241 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7242 };
7243 static const AVUUID uuid_xmp = {
7244 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7245 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7246 };
7247 static const AVUUID uuid_spherical = {
7248 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7249 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7250 };
7251
7252
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))
7253 return AVERROR_INVALIDDATA;
7254
7255
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 66 times.
69 if (c->fc->nb_streams < 1)
7256 3 return 0;
7257 66 st = c->fc->streams[c->fc->nb_streams - 1];
7258 66 sc = st->priv_data;
7259
7260 66 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7261
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
7262 return ret;
7263
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7264 uint8_t *buffer, *ptr;
7265 char *endptr;
7266 size_t len = atom.size - AV_UUID_LEN;
7267
7268 if (len < 4) {
7269 return AVERROR_INVALIDDATA;
7270 }
7271 ret = avio_skip(pb, 4); // zeroes
7272 len -= 4;
7273
7274 buffer = av_mallocz(len + 1);
7275 if (!buffer) {
7276 return AVERROR(ENOMEM);
7277 }
7278 ret = ffio_read_size(pb, buffer, len);
7279 if (ret < 0) {
7280 av_free(buffer);
7281 return ret;
7282 }
7283
7284 ptr = buffer;
7285 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7286 ptr += sizeof("systemBitrate=\"") - 1;
7287 c->bitrates_count++;
7288 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7289 if (!c->bitrates) {
7290 c->bitrates_count = 0;
7291 av_free(buffer);
7292 return AVERROR(ENOMEM);
7293 }
7294 errno = 0;
7295 ret = strtol(ptr, &endptr, 10);
7296 if (ret < 0 || errno || *endptr != '"') {
7297 c->bitrates[c->bitrates_count - 1] = 0;
7298 } else {
7299 c->bitrates[c->bitrates_count - 1] = ret;
7300 }
7301 }
7302
7303 av_free(buffer);
7304
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7305 uint8_t *buffer;
7306 size_t len = atom.size - AV_UUID_LEN;
7307 if (c->export_xmp) {
7308 buffer = av_mallocz(len + 1);
7309 if (!buffer) {
7310 return AVERROR(ENOMEM);
7311 }
7312 ret = ffio_read_size(pb, buffer, len);
7313 if (ret < 0) {
7314 av_free(buffer);
7315 return ret;
7316 }
7317 buffer[len] = '\0';
7318 av_dict_set(&c->fc->metadata, "xmp",
7319 buffer, AV_DICT_DONT_STRDUP_VAL);
7320 } else {
7321 // skip all uuid atom, which makes it fast for long uuid-xmp file
7322 ret = avio_skip(pb, len);
7323 if (ret < 0)
7324 return ret;
7325 }
7326
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7327 size_t len = atom.size - AV_UUID_LEN;
7328 ret = mov_parse_uuid_spherical(sc, pb, len);
7329 if (ret < 0)
7330 return ret;
7331 if (!sc->spherical)
7332 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7333 }
7334
7335 66 return 0;
7336 }
7337
7338 194 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7339 {
7340 int ret;
7341 uint8_t content[16];
7342
7343
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 99 times.
194 if (atom.size < 8)
7344 95 return 0;
7345
7346 99 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (ret < 0)
7348 return ret;
7349
7350
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 56 times.
99 if ( !c->found_moov
7351
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 23 times.
43 && !c->found_mdat
7352
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 && !memcmp(content, "Anevia\x1A\x1A", 8)
7353 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7354 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7355 }
7356
7357 99 return 0;
7358 }
7359
7360 35 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7361 {
7362 35 uint32_t format = avio_rl32(pb);
7363 MOVStreamContext *sc;
7364 enum AVCodecID id;
7365 AVStream *st;
7366
7367
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (c->fc->nb_streams < 1)
7368 return 0;
7369 35 st = c->fc->streams[c->fc->nb_streams - 1];
7370 35 sc = st->priv_data;
7371
7372
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 32 times.
35 switch (sc->format)
7373 {
7374 3 case MKTAG('e','n','c','v'): // encrypted video
7375 case MKTAG('e','n','c','a'): // encrypted audio
7376 3 id = mov_codec_id(st, format);
7377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7378 st->codecpar->codec_id != id) {
7379 av_log(c->fc, AV_LOG_WARNING,
7380 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7381 (char*)&format, st->codecpar->codec_id);
7382 break;
7383 }
7384
7385 3 st->codecpar->codec_id = id;
7386 3 sc->format = format;
7387 3 break;
7388
7389 32 default:
7390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (format != sc->format) {
7391 av_log(c->fc, AV_LOG_WARNING,
7392 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7393 (char*)&format, (char*)&sc->format);
7394 }
7395 32 break;
7396 }
7397
7398 35 return 0;
7399 }
7400
7401 /**
7402 * Gets the current encryption info and associated current stream context. If
7403 * we are parsing a track fragment, this will return the specific encryption
7404 * info for this fragment; otherwise this will return the global encryption
7405 * info for the current stream.
7406 */
7407 6 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7408 {
7409 MOVFragmentStreamInfo *frag_stream_info;
7410 AVStream *st;
7411 int i;
7412
7413 6 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7414
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (frag_stream_info) {
7415
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 for (i = 0; i < c->fc->nb_streams; i++) {
7416 3 *sc = c->fc->streams[i]->priv_data;
7417
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if ((*sc)->id == frag_stream_info->id) {
7418 3 st = c->fc->streams[i];
7419 3 break;
7420 }
7421 }
7422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (i == c->fc->nb_streams)
7423 return 0;
7424 3 *sc = st->priv_data;
7425
7426
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!frag_stream_info->encryption_index) {
7427 // If this stream isn't encrypted, don't create the index.
7428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!(*sc)->cenc.default_encrypted_sample)
7429 return 0;
7430 1 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!frag_stream_info->encryption_index)
7432 return AVERROR(ENOMEM);
7433 }
7434 3 *encryption_index = frag_stream_info->encryption_index;
7435 3 return 1;
7436 } else {
7437 // No current track fragment, using stream level encryption info.
7438
7439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7440 return 0;
7441 3 st = c->fc->streams[c->fc->nb_streams - 1];
7442 3 *sc = st->priv_data;
7443
7444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!(*sc)->cenc.encryption_index) {
7445 // If this stream isn't encrypted, don't create the index.
7446 if (!(*sc)->cenc.default_encrypted_sample)
7447 return 0;
7448 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7449 if (!(*sc)->cenc.encryption_index)
7450 return AVERROR(ENOMEM);
7451 }
7452
7453 3 *encryption_index = (*sc)->cenc.encryption_index;
7454 3 return 1;
7455 }
7456 }
7457
7458 72 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7459 {
7460 int i, ret;
7461 unsigned int subsample_count;
7462 AVSubsampleEncryptionInfo *subsamples;
7463
7464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!sc->cenc.default_encrypted_sample) {
7465 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7466 return AVERROR_INVALIDDATA;
7467 }
7468
7469
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) {
7470 72 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!*sample)
7472 return AVERROR(ENOMEM);
7473 } else
7474 *sample = NULL;
7475
7476
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (sc->cenc.per_sample_iv_size != 0) {
7477
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) {
7478 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
7479 av_encryption_info_free(*sample);
7480 *sample = NULL;
7481 return ret;
7482 }
7483 }
7484
7485
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (use_subsamples) {
7486 72 subsample_count = avio_rb16(pb);
7487 72 av_free((*sample)->subsamples);
7488 72 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
7489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!(*sample)->subsamples) {
7490 av_encryption_info_free(*sample);
7491 *sample = NULL;
7492 return AVERROR(ENOMEM);
7493 }
7494
7495
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++) {
7496 72 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
7497 72 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
7498 }
7499
7500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (pb->eof_reached) {
7501 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
7502 av_encryption_info_free(*sample);
7503 *sample = NULL;
7504 return AVERROR_INVALIDDATA;
7505 }
7506 72 (*sample)->subsample_count = subsample_count;
7507 }
7508
7509 72 return 0;
7510 }
7511
7512 2 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7513 {
7514 AVEncryptionInfo **encrypted_samples;
7515 MOVEncryptionIndex *encryption_index;
7516 MOVStreamContext *sc;
7517 int use_subsamples, ret;
7518 2 unsigned int sample_count, i, alloc_size = 0;
7519
7520 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7522 return ret;
7523
7524
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7525 // This can happen if we have both saio/saiz and senc atoms.
7526 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
7527 1 return 0;
7528 }
7529
7530 1 avio_r8(pb); /* version */
7531 1 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
7532
7533 1 sample_count = avio_rb32(pb);
7534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7535 return AVERROR(ENOMEM);
7536
7537
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1 times.
49 for (i = 0; i < sample_count; i++) {
7538 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7539 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7540 min_samples * sizeof(*encrypted_samples));
7541
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (encrypted_samples) {
7542 48 encryption_index->encrypted_samples = encrypted_samples;
7543
7544 48 ret = mov_read_sample_encryption_info(
7545 48 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
7546 } else {
7547 ret = AVERROR(ENOMEM);
7548 }
7549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (pb->eof_reached) {
7550 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
7551 if (ret >= 0)
7552 av_encryption_info_free(encryption_index->encrypted_samples[i]);
7553 ret = AVERROR_INVALIDDATA;
7554 }
7555
7556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0) {
7557 for (; i > 0; i--)
7558 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7559 av_freep(&encryption_index->encrypted_samples);
7560 return ret;
7561 }
7562 }
7563 1 encryption_index->nb_encrypted_samples = sample_count;
7564
7565 1 return 0;
7566 }
7567
7568 1 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
7569 {
7570 AVEncryptionInfo **sample, **encrypted_samples;
7571 int64_t prev_pos;
7572 size_t sample_count, sample_info_size, i;
7573 1 int ret = 0;
7574 1 unsigned int alloc_size = 0;
7575
7576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->nb_encrypted_samples)
7577 return 0;
7578 1 sample_count = encryption_index->auxiliary_info_sample_count;
7579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count != 1) {
7580 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
7581 return AVERROR_PATCHWELCOME;
7582 }
7583
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7584 return AVERROR(ENOMEM);
7585
7586 1 prev_pos = avio_tell(pb);
7587
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
7588
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]) {
7589 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
7590 goto finish;
7591 }
7592
7593
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++) {
7594 24 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7595 24 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7596 min_samples * sizeof(*encrypted_samples));
7597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!encrypted_samples) {
7598 ret = AVERROR(ENOMEM);
7599 goto finish;
7600 }
7601 24 encryption_index->encrypted_samples = encrypted_samples;
7602
7603 24 sample = &encryption_index->encrypted_samples[i];
7604 48 sample_info_size = encryption_index->auxiliary_info_default_size
7605 24 ? encryption_index->auxiliary_info_default_size
7606
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 : encryption_index->auxiliary_info_sizes[i];
7607
7608 24 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
7609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (ret < 0)
7610 goto finish;
7611 }
7612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7613 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
7614 ret = AVERROR_INVALIDDATA;
7615 } else {
7616 1 encryption_index->nb_encrypted_samples = sample_count;
7617 }
7618
7619 1 finish:
7620 1 avio_seek(pb, prev_pos, SEEK_SET);
7621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
7622 for (; i > 0; i--) {
7623 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7624 }
7625 av_freep(&encryption_index->encrypted_samples);
7626 }
7627 1 return ret;
7628 }
7629
7630 2 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7631 {
7632 MOVEncryptionIndex *encryption_index;
7633 MOVStreamContext *sc;
7634 int ret;
7635 unsigned int sample_count, aux_info_type, aux_info_param;
7636
7637 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7638
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7639 return ret;
7640
7641
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7642 // This can happen if we have both saio/saiz and senc atoms.
7643 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
7644 1 return 0;
7645 }
7646
7647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_sample_count) {
7648 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
7649 return AVERROR_INVALIDDATA;
7650 }
7651
7652 1 avio_r8(pb); /* version */
7653
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7654 aux_info_type = avio_rb32(pb);
7655 aux_info_param = avio_rb32(pb);
7656 if (sc->cenc.default_encrypted_sample) {
7657 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7658 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
7659 return 0;
7660 }
7661 if (aux_info_param != 0) {
7662 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
7663 return 0;
7664 }
7665 } else {
7666 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7667 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7668 aux_info_type == MKBETAG('c','e','n','s') ||
7669 aux_info_type == MKBETAG('c','b','c','1') ||
7670 aux_info_type == MKBETAG('c','b','c','s')) &&
7671 aux_info_param == 0) {
7672 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
7673 return AVERROR_INVALIDDATA;
7674 } else {
7675 return 0;
7676 }
7677 }
7678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7679 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7680 return 0;
7681 }
7682
7683 1 encryption_index->auxiliary_info_default_size = avio_r8(pb);
7684 1 sample_count = avio_rb32(pb);
7685
7686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_default_size == 0) {
7687 if (sample_count == 0)
7688 return AVERROR_INVALIDDATA;
7689
7690 encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
7691 if (!encryption_index->auxiliary_info_sizes)
7692 return AVERROR(ENOMEM);
7693
7694 ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
7695 if (ret != sample_count) {
7696 av_freep(&encryption_index->auxiliary_info_sizes);
7697
7698 if (ret >= 0)
7699 ret = AVERROR_INVALIDDATA;
7700 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
7701 av_err2str(ret));
7702 return ret;
7703 }
7704 }
7705 1 encryption_index->auxiliary_info_sample_count = sample_count;
7706
7707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7708 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7709 }
7710
7711 1 return 0;
7712 }
7713
7714 2 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7715 {
7716 uint64_t *auxiliary_offsets;
7717 MOVEncryptionIndex *encryption_index;
7718 MOVStreamContext *sc;
7719 int i, ret;
7720 unsigned int version, entry_count, aux_info_type, aux_info_param;
7721 2 unsigned int alloc_size = 0;
7722
7723 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7725 return ret;
7726
7727
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7728 // This can happen if we have both saio/saiz and senc atoms.
7729 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
7730 1 return 0;
7731 }
7732
7733
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7734 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
7735 return AVERROR_INVALIDDATA;
7736 }
7737
7738 1 version = avio_r8(pb); /* version */
7739
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7740 aux_info_type = avio_rb32(pb);
7741 aux_info_param = avio_rb32(pb);
7742 if (sc->cenc.default_encrypted_sample) {
7743 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7744 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
7745 return 0;
7746 }
7747 if (aux_info_param != 0) {
7748 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
7749 return 0;
7750 }
7751 } else {
7752 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7753 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7754 aux_info_type == MKBETAG('c','e','n','s') ||
7755 aux_info_type == MKBETAG('c','b','c','1') ||
7756 aux_info_type == MKBETAG('c','b','c','s')) &&
7757 aux_info_param == 0) {
7758 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
7759 return AVERROR_INVALIDDATA;
7760 } else {
7761 return 0;
7762 }
7763 }
7764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7765 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7766 return 0;
7767 }
7768
7769 1 entry_count = avio_rb32(pb);
7770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
7771 return AVERROR(ENOMEM);
7772
7773
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++) {
7774
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);
7775 1 auxiliary_offsets = av_fast_realloc(
7776 1 encryption_index->auxiliary_offsets, &alloc_size,
7777 min_offsets * sizeof(*auxiliary_offsets));
7778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!auxiliary_offsets) {
7779 av_freep(&encryption_index->auxiliary_offsets);
7780 return AVERROR(ENOMEM);
7781 }
7782 1 encryption_index->auxiliary_offsets = auxiliary_offsets;
7783
7784
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (version == 0) {
7785 1 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
7786 } else {
7787 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
7788 }
7789
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (c->frag_index.current >= 0) {
7790 1 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
7791 }
7792 }
7793
7794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7795 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
7796 av_freep(&encryption_index->auxiliary_offsets);
7797 return AVERROR_INVALIDDATA;
7798 }
7799
7800 1 encryption_index->auxiliary_offsets_count = entry_count;
7801
7802
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (encryption_index->auxiliary_info_sample_count) {
7803 1 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7804 }
7805
7806 return 0;
7807 }
7808
7809 2 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7810 {
7811 AVEncryptionInitInfo *info, *old_init_info;
7812 uint8_t **key_ids;
7813 AVStream *st;
7814 const AVPacketSideData *old_side_data;
7815 uint8_t *side_data, *extra_data;
7816 size_t side_data_size;
7817 2 int ret = 0;
7818 2 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
7819
7820
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
7821 return 0;
7822 2 st = c->fc->streams[c->fc->nb_streams-1];
7823
7824 2 version = avio_r8(pb); /* version */
7825 2 avio_rb24(pb); /* flags */
7826
7827 2 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
7828 /* key_id_size */ 16, /* data_size */ 0);
7829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info)
7830 return AVERROR(ENOMEM);
7831
7832
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
7833 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
7834 goto finish;
7835 }
7836
7837
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version > 0) {
7838 2 kid_count = avio_rb32(pb);
7839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
7840 ret = AVERROR(ENOMEM);
7841 goto finish;
7842 }
7843
7844
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++) {
7845 2 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
7846 2 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
7847 min_kid_count * sizeof(*key_ids));
7848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!key_ids) {
7849 ret = AVERROR(ENOMEM);
7850 goto finish;
7851 }
7852 2 info->key_ids = key_ids;
7853
7854 2 info->key_ids[i] = av_mallocz(16);
7855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info->key_ids[i]) {
7856 ret = AVERROR(ENOMEM);
7857 goto finish;
7858 }
7859 2 info->num_key_ids = i + 1;
7860
7861
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
7862 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
7863 goto finish;
7864 }
7865 }
7866
7867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
7868 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
7869 ret = AVERROR_INVALIDDATA;
7870 goto finish;
7871 }
7872 }
7873
7874 2 extra_data_size = avio_rb32(pb);
7875 2 extra_data = av_malloc(extra_data_size);
7876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!extra_data) {
7877 ret = AVERROR(ENOMEM);
7878 goto finish;
7879 }
7880 2 ret = avio_read(pb, extra_data, extra_data_size);
7881
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != extra_data_size) {
7882 av_free(extra_data);
7883
7884 if (ret >= 0)
7885 ret = AVERROR_INVALIDDATA;
7886 goto finish;
7887 }
7888
7889 2 av_freep(&info->data); // malloc(0) may still allocate something.
7890 2 info->data = extra_data;
7891 2 info->data_size = extra_data_size;
7892
7893 // If there is existing initialization data, append to the list.
7894 2 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
7895 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
7896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (old_side_data) {
7897 old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
7898 if (old_init_info) {
7899 // Append to the end of the list.
7900 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
7901 if (!cur->next) {
7902 cur->next = info;
7903 break;
7904 }
7905 }
7906 info = old_init_info;
7907 } else {
7908 // Assume existing side-data will be valid, so the only error we could get is OOM.
7909 ret = AVERROR(ENOMEM);
7910 goto finish;
7911 }
7912 }
7913
7914 2 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
7915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!side_data) {
7916 ret = AVERROR(ENOMEM);
7917 goto finish;
7918 }
7919
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
7920 2 &st->codecpar->nb_coded_side_data,
7921 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
7922 side_data, side_data_size, 0))
7923 av_free(side_data);
7924
7925 2 finish:
7926 2 av_encryption_init_info_free(info);
7927 2 return ret;
7928 }
7929
7930 3 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7931 {
7932 AVStream *st;
7933 MOVStreamContext *sc;
7934
7935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7936 return 0;
7937 3 st = c->fc->streams[c->fc->nb_streams-1];
7938 3 sc = st->priv_data;
7939
7940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7941 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
7942 return AVERROR_PATCHWELCOME;
7943 }
7944
7945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8)
7946 return AVERROR_INVALIDDATA;
7947
7948 3 avio_rb32(pb); /* version and flags */
7949
7950
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->cenc.default_encrypted_sample) {
7951 3 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7953 return AVERROR(ENOMEM);
7954 }
7955 }
7956
7957 3 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
7958 3 return 0;
7959 }
7960
7961 3 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7962 {
7963 AVStream *st;
7964 MOVStreamContext *sc;
7965 unsigned int version, pattern, is_protected, iv_size;
7966
7967
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7968 return 0;
7969 3 st = c->fc->streams[c->fc->nb_streams-1];
7970 3 sc = st->priv_data;
7971
7972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7973 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
7974 return AVERROR_PATCHWELCOME;
7975 }
7976
7977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7978 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7979 if (!sc->cenc.default_encrypted_sample) {
7980 return AVERROR(ENOMEM);
7981 }
7982 }
7983
7984
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 20)
7985 return AVERROR_INVALIDDATA;
7986
7987 3 version = avio_r8(pb); /* version */
7988 3 avio_rb24(pb); /* flags */
7989
7990 3 avio_r8(pb); /* reserved */
7991 3 pattern = avio_r8(pb);
7992
7993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (version > 0) {
7994 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
7995 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
7996 }
7997
7998 3 is_protected = avio_r8(pb);
7999
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) {
8000 // The whole stream should be by-default encrypted.
8001 3 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
8002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.encryption_index)
8003 return AVERROR(ENOMEM);
8004 }
8005 3 sc->cenc.per_sample_iv_size = avio_r8(pb);
8006
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 &&
8007 sc->cenc.per_sample_iv_size != 16) {
8008 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
8009 return AVERROR_INVALIDDATA;
8010 }
8011
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) {
8012 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
8013 return AVERROR_INVALIDDATA;
8014 }
8015
8016
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) {
8017 1 iv_size = avio_r8(pb);
8018
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) {
8019 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
8020 return AVERROR_INVALIDDATA;
8021 }
8022
8023
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) {
8024 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
8025 return AVERROR_INVALIDDATA;
8026 }
8027 }
8028
8029 3 return 0;
8030 }
8031
8032 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8033 {
8034 AVStream *st;
8035 int last, type, size, ret;
8036 uint8_t buf[4];
8037
8038 if (c->fc->nb_streams < 1)
8039 return 0;
8040 st = c->fc->streams[c->fc->nb_streams-1];
8041
8042 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
8043 return AVERROR_INVALIDDATA;
8044
8045 /* Check FlacSpecificBox version. */
8046 if (avio_r8(pb) != 0)
8047 return AVERROR_INVALIDDATA;
8048
8049 avio_rb24(pb); /* Flags */
8050
8051 if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
8052 av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
8053 return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
8054 }
8055 flac_parse_block_header(buf, &last, &type, &size);
8056
8057 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
8058 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
8059 return AVERROR_INVALIDDATA;
8060 }
8061
8062 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
8063 if (ret < 0)
8064 return ret;
8065
8066 if (!last)
8067 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
8068
8069 return 0;
8070 }
8071
8072 146 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8073 {
8074 int i, ret;
8075 int bytes_of_protected_data;
8076
8077
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 143 times.
146 if (!sc->cenc.aes_ctr) {
8078 /* initialize the cipher */
8079 3 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.aes_ctr) {
8081 return AVERROR(ENOMEM);
8082 }
8083
8084 3 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
8085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8086 return ret;
8087 }
8088 }
8089
8090 146 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8091
8092
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!sample->subsample_count) {
8093 /* decrypt the whole packet */
8094 48 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8095 48 return 0;
8096 }
8097
8098
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 98 times.
196 for (i = 0; i < sample->subsample_count; i++) {
8099
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) {
8100 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8101 return AVERROR_INVALIDDATA;
8102 }
8103
8104 /* skip the clear bytes */
8105 98 input += sample->subsamples[i].bytes_of_clear_data;
8106 98 size -= sample->subsamples[i].bytes_of_clear_data;
8107
8108 /* decrypt the encrypted bytes */
8109
8110 98 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
8111 98 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
8112
8113 98 input += bytes_of_protected_data;
8114 98 size -= bytes_of_protected_data;
8115 }
8116
8117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (size > 0) {
8118 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8119 return AVERROR_INVALIDDATA;
8120 }
8121
8122 98 return 0;
8123 }
8124
8125 static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8126 {
8127 int i, ret;
8128 int num_of_encrypted_blocks;
8129 uint8_t iv[16];
8130
8131 if (!sc->cenc.aes_ctx) {
8132 /* initialize the cipher */
8133 sc->cenc.aes_ctx = av_aes_alloc();
8134 if (!sc->cenc.aes_ctx) {
8135 return AVERROR(ENOMEM);
8136 }
8137
8138 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8139 if (ret < 0) {
8140 return ret;
8141 }
8142 }
8143
8144 memcpy(iv, sample->iv, 16);
8145
8146 /* whole-block full sample encryption */
8147 if (!sample->subsample_count) {
8148 /* decrypt the whole packet */
8149 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8150 return 0;
8151 }
8152
8153 for (i = 0; i < sample->subsample_count; i++) {
8154 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8155 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8156 return AVERROR_INVALIDDATA;
8157 }
8158
8159 if (sample->subsamples[i].bytes_of_protected_data % 16) {
8160 av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8161 return AVERROR_INVALIDDATA;
8162 }
8163
8164 /* skip the clear bytes */
8165 input += sample->subsamples[i].bytes_of_clear_data;
8166 size -= sample->subsamples[i].bytes_of_clear_data;
8167
8168 /* decrypt the encrypted bytes */
8169 num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8170 if (num_of_encrypted_blocks > 0) {
8171 av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8172 }
8173 input += sample->subsamples[i].bytes_of_protected_data;
8174 size -= sample->subsamples[i].bytes_of_protected_data;
8175 }
8176
8177 if (size > 0) {
8178 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8179 return AVERROR_INVALIDDATA;
8180 }
8181
8182 return 0;
8183 }
8184
8185 static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8186 {
8187 int i, ret, rem_bytes;
8188 uint8_t *data;
8189
8190 if (!sc->cenc.aes_ctr) {
8191 /* initialize the cipher */
8192 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8193 if (!sc->cenc.aes_ctr) {
8194 return AVERROR(ENOMEM);
8195 }
8196
8197 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
8198 if (ret < 0) {
8199 return ret;
8200 }
8201 }
8202
8203 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8204
8205 /* whole-block full sample encryption */
8206 if (!sample->subsample_count) {
8207 /* decrypt the whole packet */
8208 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8209 return 0;
8210 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8211 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8212 return AVERROR_INVALIDDATA;
8213 }
8214
8215 for (i = 0; i < sample->subsample_count; i++) {
8216 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8217 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8218 return AVERROR_INVALIDDATA;
8219 }
8220
8221 /* skip the clear bytes */
8222 input += sample->subsamples[i].bytes_of_clear_data;
8223 size -= sample->subsamples[i].bytes_of_clear_data;
8224
8225 /* decrypt the encrypted bytes */
8226 data = input;
8227 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8228 while (rem_bytes > 0) {
8229 if (rem_bytes < 16*sample->crypt_byte_block) {
8230 break;
8231 }
8232 av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8233 data += 16*sample->crypt_byte_block;
8234 rem_bytes -= 16*sample->crypt_byte_block;
8235 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8236 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8237 }
8238 input += sample->subsamples[i].bytes_of_protected_data;
8239 size -= sample->subsamples[i].bytes_of_protected_data;
8240 }
8241
8242 if (size > 0) {
8243 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8244 return AVERROR_INVALIDDATA;
8245 }
8246
8247 return 0;
8248 }
8249
8250 static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8251 {
8252 int i, ret, rem_bytes;
8253 uint8_t iv[16];
8254 uint8_t *data;
8255
8256 if (!sc->cenc.aes_ctx) {
8257 /* initialize the cipher */
8258 sc->cenc.aes_ctx = av_aes_alloc();
8259 if (!sc->cenc.aes_ctx) {
8260 return AVERROR(ENOMEM);
8261 }
8262
8263 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8264 if (ret < 0) {
8265 return ret;
8266 }
8267 }
8268
8269 /* whole-block full sample encryption */
8270 if (!sample->subsample_count) {
8271 /* decrypt the whole packet */
8272 memcpy(iv, sample->iv, 16);
8273 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8274 return 0;
8275 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8276 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8277 return AVERROR_INVALIDDATA;
8278 }
8279
8280 for (i = 0; i < sample->subsample_count; i++) {
8281 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8282 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8283 return AVERROR_INVALIDDATA;
8284 }
8285
8286 /* skip the clear bytes */
8287 input += sample->subsamples[i].bytes_of_clear_data;
8288 size -= sample->subsamples[i].bytes_of_clear_data;
8289
8290 /* decrypt the encrypted bytes */
8291 memcpy(iv, sample->iv, 16);
8292 data = input;
8293 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8294 while (rem_bytes > 0) {
8295 if (rem_bytes < 16*sample->crypt_byte_block) {
8296 break;
8297 }
8298 av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8299 data += 16*sample->crypt_byte_block;
8300 rem_bytes -= 16*sample->crypt_byte_block;
8301 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8302 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8303 }
8304 input += sample->subsamples[i].bytes_of_protected_data;
8305 size -= sample->subsamples[i].bytes_of_protected_data;
8306 }
8307
8308 if (size > 0) {
8309 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8310 return AVERROR_INVALIDDATA;
8311 }
8312
8313 return 0;
8314 }
8315
8316 146 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8317 {
8318
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) {
8319 146 return cenc_scheme_decrypt(c, sc, sample, input, size);
8320 } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8321 return cbc1_scheme_decrypt(c, sc, sample, input, size);
8322 } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8323 return cens_scheme_decrypt(c, sc, sample, input, size);
8324 } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8325 return cbcs_scheme_decrypt(c, sc, sample, input, size);
8326 } else {
8327 av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8328 return AVERROR_INVALIDDATA;
8329 }
8330 }
8331
8332 96761 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8333 {
8334 96761 int current = frag_index->current;
8335
8336
2/2
✓ Branch 0 taken 95920 times.
✓ Branch 1 taken 841 times.
96761 if (!frag_index->nb_items)
8337 95920 return NULL;
8338
8339 // Check frag_index->current is the right one for pkt. It can out of sync.
8340
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) {
8341
2/2
✓ Branch 0 taken 815 times.
✓ Branch 1 taken 26 times.
841 if (frag_index->item[current].moof_offset < pkt->pos &&
8342
2/2
✓ Branch 0 taken 545 times.
✓ Branch 1 taken 270 times.
815 (current + 1 == frag_index->nb_items ||
8343
2/2
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 75 times.
545 frag_index->item[current + 1].moof_offset > pkt->pos))
8344 740 return get_frag_stream_info(frag_index, current, id);
8345 }
8346
8347
8348
2/2
✓ Branch 0 taken 4553 times.
✓ Branch 1 taken 8 times.
4561 for (int i = 0; i < frag_index->nb_items; i++) {
8349
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 4460 times.
4553 if (frag_index->item[i].moof_offset > pkt->pos)
8350 93 break;
8351 4460 current = i;
8352 }
8353 101 frag_index->current = current;
8354 101 return get_frag_stream_info(frag_index, current, id);
8355 }
8356
8357 96761 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8358 {
8359 MOVFragmentStreamInfo *frag_stream_info;
8360 MOVEncryptionIndex *encryption_index;
8361 AVEncryptionInfo *encrypted_sample;
8362 int encrypted_index, ret;
8363
8364 96761 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8365 96761 encrypted_index = current_index;
8366 96761 encryption_index = NULL;
8367
2/2
✓ Branch 0 taken 841 times.
✓ Branch 1 taken 95920 times.
96761 if (frag_stream_info) {
8368 // Note this only supports encryption info in the first sample descriptor.
8369
2/2
✓ Branch 0 taken 817 times.
✓ Branch 1 taken 24 times.
841 if (frag_stream_info->stsd_id == 1) {
8370
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 793 times.
817 if (frag_stream_info->encryption_index) {
8371 24 encrypted_index = current_index - frag_stream_info->index_base;
8372 24 encryption_index = frag_stream_info->encryption_index;
8373 } else {
8374 793 encryption_index = sc->cenc.encryption_index;
8375 }
8376 }
8377 } else {
8378 95920 encryption_index = sc->cenc.encryption_index;
8379 }
8380
8381
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 96615 times.
96761 if (encryption_index) {
8382
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_info_sample_count &&
8383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8384 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8385 return AVERROR_INVALIDDATA;
8386 }
8387
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_offsets_count &&
8388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8389 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8390 return AVERROR_INVALIDDATA;
8391 }
8392
8393 146 encrypted_sample = NULL;
8394
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!encryption_index->nb_encrypted_samples) {
8395 // Full-sample encryption with default settings.
8396 48 encrypted_sample = sc->cenc.default_encrypted_sample;
8397
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) {
8398 // Per-sample setting override.
8399 98 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (!encrypted_sample) {
8401 encrypted_sample = sc->cenc.default_encrypted_sample;
8402 }
8403 }
8404
8405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (!encrypted_sample) {
8406 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8407 return AVERROR_INVALIDDATA;
8408 }
8409
8410
1/2
✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
146 if (mov->decryption_key) {
8411 146 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
8412 } else {
8413 size_t size;
8414 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
8415 if (!side_data)
8416 return AVERROR(ENOMEM);
8417 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
8418 if (ret < 0)
8419 av_free(side_data);
8420 return ret;
8421 }
8422 }
8423
8424 96615 return 0;
8425 }
8426
8427 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8428 {
8429 const int OPUS_SEEK_PREROLL_MS = 80;
8430 int ret;
8431 AVStream *st;
8432 size_t size;
8433 uint16_t pre_skip;
8434
8435 if (c->fc->nb_streams < 1)
8436 return 0;
8437 st = c->fc->streams[c->fc->nb_streams-1];
8438
8439 if ((uint64_t)atom.size > (1<<30) || atom.size < 11)
8440 return AVERROR_INVALIDDATA;
8441
8442 /* Check OpusSpecificBox version. */
8443 if (avio_r8(pb) != 0) {
8444 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
8445 return AVERROR_INVALIDDATA;
8446 }
8447
8448 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
8449 size = atom.size + 8;
8450
8451 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
8452 return ret;
8453
8454 AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
8455 AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
8456 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
8457 avio_read(pb, st->codecpar->extradata + 9, size - 9);
8458
8459 /* OpusSpecificBox is stored in big-endian, but OpusHead is
8460 little-endian; aside from the preceding magic and version they're
8461 otherwise currently identical. Data after output gain at offset 16
8462 doesn't need to be bytewapped. */
8463 pre_skip = AV_RB16A(st->codecpar->extradata + 10);
8464 AV_WL16A(st->codecpar->extradata + 10, pre_skip);
8465 AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
8466 AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
8467
8468 st->codecpar->initial_padding = pre_skip;
8469 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
8470 (AVRational){1, 1000},
8471 (AVRational){1, 48000});
8472
8473 return 0;
8474 }
8475
8476 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8477 {
8478 AVStream *st;
8479 unsigned format_info;
8480 int channel_assignment, channel_assignment1, channel_assignment2;
8481 int ratebits;
8482 uint64_t chmask;
8483
8484 if (c->fc->nb_streams < 1)
8485 return 0;
8486 st = c->fc->streams[c->fc->nb_streams-1];
8487
8488 if (atom.size < 10)
8489 return AVERROR_INVALIDDATA;
8490
8491 format_info = avio_rb32(pb);
8492
8493 ratebits = (format_info >> 28) & 0xF;
8494 channel_assignment1 = (format_info >> 15) & 0x1F;
8495 channel_assignment2 = format_info & 0x1FFF;
8496 if (channel_assignment2)
8497 channel_assignment = channel_assignment2;
8498 else
8499 channel_assignment = channel_assignment1;
8500
8501 st->codecpar->frame_size = 40 << (ratebits & 0x7);
8502 st->codecpar->sample_rate = mlp_samplerate(ratebits);
8503
8504 av_channel_layout_uninit(&st->codecpar->ch_layout);
8505 chmask = truehd_layout(channel_assignment);
8506 av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
8507
8508 return 0;
8509 }
8510
8511 4 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8512 {
8513 AVStream *st;
8514 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
8515 int ret;
8516 4 int64_t read_size = atom.size;
8517
8518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8519 return 0;
8520 4 st = c->fc->streams[c->fc->nb_streams-1];
8521
8522 // At most 24 bytes
8523 4 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
8524
8525
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
8526 return ret;
8527
8528 4 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
8529 }
8530
8531 3 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8532 {
8533 AVStream *st;
8534 uint8_t *buf;
8535 int ret, old_size, num_arrays;
8536
8537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
8538 return 0;
8539 3 st = c->fc->streams[c->fc->nb_streams-1];
8540
8541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata_size)
8542 // TODO: handle lhvC when present before hvcC
8543 return 0;
8544
8545
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)
8546 return AVERROR_INVALIDDATA;
8547
8548 3 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
8549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!buf)
8550 return AVERROR(ENOMEM);
8551 3 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8552
8553 3 ret = ffio_read_size(pb, buf, atom.size);
8554
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8555 av_free(buf);
8556 av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
8557 return 0;
8558 }
8559
8560 3 num_arrays = buf[5];
8561 3 old_size = st->codecpar->extradata_size;
8562 3 atom.size -= 8 /* account for mov_realloc_extradata offsetting */
8563 + 6 /* lhvC bytes before the arrays*/;
8564
8565 3 ret = mov_realloc_extradata(st->codecpar, atom);
8566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8567 av_free(buf);
8568 return ret;
8569 }
8570
8571 3 st->codecpar->extradata[22] += num_arrays;
8572 3 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
8573
8574 3 st->disposition |= AV_DISPOSITION_MULTILAYER;
8575
8576 3 av_free(buf);
8577 3 return 0;
8578 }
8579
8580 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8581 {
8582 4 AVFormatContext *ctx = c->fc;
8583 4 AVStream *st = NULL;
8584 AVBPrint scheme_buf, value_buf;
8585 4 int64_t scheme_str_len = 0, value_str_len = 0;
8586 4 int version, flags, ret = AVERROR_BUG;
8587 4 int64_t size = atom.size;
8588
8589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
8590 // 4 bytes for version + flags, 2x 1 byte for null
8591 return AVERROR_INVALIDDATA;
8592
8593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8594 return 0;
8595 4 st = c->fc->streams[c->fc->nb_streams-1];
8596
8597 4 version = avio_r8(pb);
8598 4 flags = avio_rb24(pb);
8599 4 size -= 4;
8600
8601
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) {
8602 av_log(ctx, AV_LOG_ERROR,
8603 "Unsupported 'kind' box with version %d, flags: %x",
8604 version, flags);
8605 return AVERROR_INVALIDDATA;
8606 }
8607
8608 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8609 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8610
8611
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,
8612 size)) < 0) {
8613 ret = scheme_str_len;
8614 goto cleanup;
8615 }
8616
8617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
8618 // we need to have another string, even if nullptr.
8619 // we check with + 1 since we expect that if size was not hit,
8620 // an additional null was read.
8621 ret = AVERROR_INVALIDDATA;
8622 goto cleanup;
8623 }
8624
8625 4 size -= scheme_str_len + 1;
8626
8627
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,
8628 size)) < 0) {
8629 ret = value_str_len;
8630 goto cleanup;
8631 }
8632
8633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
8634 // in case of no trailing null, box is not valid.
8635 ret = AVERROR_INVALIDDATA;
8636 goto cleanup;
8637 }
8638
8639 4 av_log(ctx, AV_LOG_TRACE,
8640 "%s stream %d KindBox(scheme: %s, value: %s)\n",
8641 4 av_get_media_type_string(st->codecpar->codec_type),
8642 st->index,
8643 scheme_buf.str, value_buf.str);
8644
8645
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++) {
8646 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
8647
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
8648 continue;
8649
8650
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
8651 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
8652
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
8653 16 continue;
8654
8655 4 st->disposition |= value_map.disposition;
8656 }
8657 }
8658
8659 4 ret = 0;
8660
8661 4 cleanup:
8662
8663 4 av_bprint_finalize(&scheme_buf, NULL);
8664 4 av_bprint_finalize(&value_buf, NULL);
8665
8666 4 return ret;
8667 }
8668
8669 static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8670 {
8671 AVStream *st;
8672 AVChannelLayout ch_layout = { 0 };
8673 int ret, i, version, type;
8674 int ambisonic_order, channel_order, normalization, channel_count;
8675 int ambi_channels, non_diegetic_channels;
8676
8677 if (c->fc->nb_streams < 1)
8678 return 0;
8679
8680 st = c->fc->streams[c->fc->nb_streams - 1];
8681
8682 if (atom.size < 16) {
8683 av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
8684 return AVERROR_INVALIDDATA;
8685 }
8686
8687 version = avio_r8(pb);
8688 if (version) {
8689 av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
8690 return 0;
8691 }
8692
8693 type = avio_r8(pb);
8694 if (type & 0x7f) {
8695 av_log(c->fc, AV_LOG_WARNING,
8696 "Unsupported ambisonic type %d\n", type & 0x7f);
8697 return 0;
8698 }
8699 non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
8700
8701 ambisonic_order = avio_rb32(pb);
8702
8703 channel_order = avio_r8(pb);
8704 if (channel_order) {
8705 av_log(c->fc, AV_LOG_WARNING,
8706 "Unsupported channel_order %d\n", channel_order);
8707 return 0;
8708 }
8709
8710 normalization = avio_r8(pb);
8711 if (normalization) {
8712 av_log(c->fc, AV_LOG_WARNING,
8713 "Unsupported normalization %d\n", normalization);
8714 return 0;
8715 }
8716
8717 channel_count = avio_rb32(pb);
8718 if (ambisonic_order < 0 || ambisonic_order > 31 ||
8719 channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
8720 non_diegetic_channels)) {
8721 av_log(c->fc, AV_LOG_ERROR,
8722 "Invalid number of channels (%d / %d)\n",
8723 channel_count, ambisonic_order);
8724 return 0;
8725 }
8726 ambi_channels = channel_count - non_diegetic_channels;
8727
8728 ret = av_channel_layout_custom_init(&ch_layout, channel_count);
8729 if (ret < 0)
8730 return 0;
8731
8732 for (i = 0; i < channel_count; i++) {
8733 unsigned channel = avio_rb32(pb);
8734
8735 if (channel >= channel_count) {
8736 av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
8737 channel, ambisonic_order);
8738 av_channel_layout_uninit(&ch_layout);
8739 return 0;
8740 }
8741 if (channel >= ambi_channels)
8742 ch_layout.u.map[i].id = channel - ambi_channels;
8743 else
8744 ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
8745 }
8746
8747 ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
8748 if (ret < 0) {
8749 av_channel_layout_uninit(&ch_layout);
8750 return 0;
8751 }
8752
8753 av_channel_layout_uninit(&st->codecpar->ch_layout);
8754 st->codecpar->ch_layout = ch_layout;
8755
8756 return 0;
8757 }
8758
8759 static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8760 {
8761 AVStream *st;
8762 int version;
8763
8764 if (c->fc->nb_streams < 1)
8765 return 0;
8766
8767 st = c->fc->streams[c->fc->nb_streams - 1];
8768
8769 if (atom.size < 5) {
8770 av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
8771 return AVERROR_INVALIDDATA;
8772 }
8773
8774 version = avio_r8(pb);
8775 if (version) {
8776 av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
8777 return 0;
8778 }
8779
8780 st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
8781
8782 return 0;
8783 }
8784
8785 126 static int rb_size(AVIOContext *pb, int64_t *value, int size)
8786 {
8787
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 115 times.
126 if (size == 0)
8788 11 *value = 0;
8789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 115 times.
115 else if (size == 1)
8790 *value = avio_r8(pb);
8791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 115 times.
115 else if (size == 2)
8792 *value = avio_rb16(pb);
8793
1/2
✓ Branch 0 taken 115 times.
✗ Branch 1 not taken.
115 else if (size == 4)
8794 115 *value = avio_rb32(pb);
8795 else if (size == 8) {
8796 *value = avio_rb64(pb);
8797 if (*value < 0)
8798 return -1;
8799 } else
8800 return -1;
8801 126 return size;
8802 }
8803
8804 15 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8805 {
8806 15 avio_rb32(pb); // version & flags.
8807 15 c->primary_item_id = avio_rb16(pb);
8808 15 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
8809 15 return atom.size;
8810 }
8811
8812 6 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8813 {
8814 6 c->idat_offset = avio_tell(pb);
8815 6 return 0;
8816 }
8817
8818 15 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8819 {
8820 HEIFItem **heif_item;
8821 int version, offset_size, length_size, base_offset_size, index_size;
8822 int item_count, extent_count;
8823 int64_t base_offset, extent_offset, extent_length;
8824 uint8_t value;
8825
8826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (c->found_iloc) {
8827 av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
8828 return 0;
8829 }
8830
8831 15 version = avio_r8(pb);
8832 15 avio_rb24(pb); // flags.
8833
8834 15 value = avio_r8(pb);
8835 15 offset_size = (value >> 4) & 0xF;
8836 15 length_size = value & 0xF;
8837 15 value = avio_r8(pb);
8838 15 base_offset_size = (value >> 4) & 0xF;
8839
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7 times.
15 index_size = !version ? 0 : (value & 0xF);
8840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (index_size) {
8841 avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
8842 return AVERROR_PATCHWELCOME;
8843 }
8844
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8845
8846 15 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
8847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!heif_item)
8848 return AVERROR(ENOMEM);
8849 15 c->heif_item = heif_item;
8850
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (item_count > c->nb_heif_item)
8851 15 memset(&c->heif_item[c->nb_heif_item], 0,
8852 15 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
8853 15 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
8854
8855 15 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
8856
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 15 times.
57 for (int i = 0; i < item_count; i++) {
8857 42 HEIFItem *item = NULL;
8858
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8859
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
8860
8861
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
42 if (avio_feof(pb))
8862 return AVERROR_INVALIDDATA;
8863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (offset_type > 1) {
8864 avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
8865 return AVERROR_PATCHWELCOME;
8866 }
8867
8868 42 avio_rb16(pb); // data_reference_index.
8869
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
42 if (rb_size(pb, &base_offset, base_offset_size) < 0)
8870 return AVERROR_INVALIDDATA;
8871 42 extent_count = avio_rb16(pb);
8872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (extent_count > 1) {
8873 // For still AVIF images, we only support one extent item.
8874 avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
8875 return AVERROR_PATCHWELCOME;
8876 }
8877
8878
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 ||
8879 42 rb_size(pb, &extent_length, length_size) < 0 ||
8880
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 base_offset > INT64_MAX - extent_offset)
8881 return AVERROR_INVALIDDATA;
8882
8883
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 for (int j = 0; j < c->nb_heif_item; j++) {
8884 95 item = c->heif_item[j];
8885
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 53 times.
95 if (!item)
8886 42 item = c->heif_item[j] = av_mallocz(sizeof(*item));
8887
1/2
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
53 else if (item->item_id != item_id)
8888 53 continue;
8889 42 break;
8890 }
8891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!item)
8892 return AVERROR(ENOMEM);
8893
8894 42 item->item_id = item_id;
8895
8896
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 36 times.
42 if (offset_type == 1)
8897 6 item->is_idat_relative = 1;
8898 42 item->extent_length = extent_length;
8899 42 item->extent_offset = base_offset + extent_offset;
8900 42 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, item->item_id %d, offset_type %d, "
8901 "extent_offset %"PRId64", extent_length %"PRId64"\n",
8902 i, item->item_id, offset_type, item->extent_offset, item->extent_length);
8903 }
8904
8905 15 c->found_iloc = 1;
8906 15 return atom.size;
8907 }
8908
8909 42 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8910 {
8911 42 HEIFItem *item = NULL;
8912 AVBPrint item_name;
8913 42 int64_t size = atom.size;
8914 uint32_t item_type;
8915 int item_id;
8916 int version, ret;
8917
8918 42 version = avio_r8(pb);
8919 42 avio_rb24(pb); // flags.
8920 42 size -= 4;
8921
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (size < 0)
8922 return AVERROR_INVALIDDATA;
8923
8924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (version < 2) {
8925 avpriv_report_missing_feature(c->fc, "infe version < 2");
8926 avio_skip(pb, size);
8927 return 1;
8928 }
8929
8930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
8931 42 avio_rb16(pb); // item_protection_index
8932 42 item_type = avio_rl32(pb);
8933 42 size -= 8;
8934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (size < 1)
8935 return AVERROR_INVALIDDATA;
8936
8937 42 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
8938 42 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
8939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0) {
8940 av_bprint_finalize(&item_name, NULL);
8941 return ret;
8942 }
8943
8944 42 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
8945 42 item_id, av_fourcc2str(item_type), item_name.str);
8946
8947 42 size -= ret + 1;
8948
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 40 times.
42 if (size > 0)
8949 2 avio_skip(pb, size);
8950
8951
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 for (int i = 0; i < c->nb_heif_item; i++) {
8952 95 item = c->heif_item[i];
8953
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
95 if (!item)
8954 item = c->heif_item[i] = av_mallocz(sizeof(*item));
8955
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 42 times.
95 else if (item->item_id != item_id)
8956 53 continue;
8957 42 break;
8958 }
8959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!item) {
8960 av_bprint_finalize(&item_name, NULL);
8961 return AVERROR(ENOMEM);
8962 }
8963
8964 42 av_freep(&item->name);
8965
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 1 times.
42 av_bprint_finalize(&item_name, ret ? &item->name : NULL);
8966 42 item->item_id = item_id;
8967 42 item->type = item_type;
8968
8969
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 11 times.
42 switch (item_type) {
8970 31 case MKTAG('a','v','0','1'):
8971 case MKTAG('j','p','e','g'):
8972 case MKTAG('h','v','c','1'):
8973 31 ret = heif_add_stream(c, item);
8974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (ret < 0)
8975 return ret;
8976 31 break;
8977 }
8978
8979 42 return 0;
8980 }
8981
8982 15 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8983 {
8984 HEIFItem **heif_item;
8985 int entry_count;
8986 15 int version, got_stream = 0, ret, i;
8987
8988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (c->found_iinf) {
8989 av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
8990 return 0;
8991 }
8992
8993 15 version = avio_r8(pb);
8994 15 avio_rb24(pb); // flags.
8995
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
8996
8997 15 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
8998
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!heif_item)
8999 return AVERROR(ENOMEM);
9000 15 c->heif_item = heif_item;
9001
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (entry_count > c->nb_heif_item)
9002 memset(&c->heif_item[c->nb_heif_item], 0,
9003 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
9004 15 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
9005
9006
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 15 times.
57 for (i = 0; i < entry_count; i++) {
9007 MOVAtom infe;
9008
9009 42 infe.size = avio_rb32(pb) - 8;
9010 42 infe.type = avio_rl32(pb);
9011
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
42 if (avio_feof(pb)) {
9012 ret = AVERROR_INVALIDDATA;
9013 goto fail;
9014 }
9015 42 ret = mov_read_infe(c, pb, infe);
9016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0)
9017 goto fail;
9018
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 if (!ret)
9019 42 got_stream = 1;
9020 }
9021
9022 15 c->found_iinf = got_stream;
9023 15 return 0;
9024 fail:
9025 for (; i >= 0; i--) {
9026 HEIFItem *item = c->heif_item[i];
9027
9028 if (!item)
9029 continue;
9030
9031 av_freep(&item->name);
9032 }
9033 return ret;
9034 }
9035
9036 6 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
9037 {
9038 6 HEIFItem *item = NULL;
9039 HEIFGrid *grid;
9040 int entries, i;
9041
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9042
9043
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 for (int i = 0; i < c->nb_heif_grid; i++) {
9044 if (c->heif_grid[i].item->item_id == from_item_id) {
9045 av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
9046 "referencing the same Derived Image item\n");
9047 return AVERROR_INVALIDDATA;
9048 }
9049 }
9050
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 for (int i = 0; i < c->nb_heif_item; i++) {
9051
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)
9052 14 continue;
9053 6 item = c->heif_item[i];
9054
9055
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 switch (item->type) {
9056 6 case MKTAG('g','r','i','d'):
9057 case MKTAG('i','o','v','l'):
9058 6 break;
9059 default:
9060 avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
9061 av_fourcc2str(item->type));
9062 return 0;
9063 }
9064 6 break;
9065 }
9066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!item) {
9067 av_log(c->fc, AV_LOG_ERROR, "Missing grid information\n");
9068 return AVERROR_INVALIDDATA;
9069 }
9070
9071 6 grid = av_realloc_array(c->heif_grid, c->nb_heif_grid + 1U,
9072 sizeof(*c->heif_grid));
9073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!grid)
9074 return AVERROR(ENOMEM);
9075 6 c->heif_grid = grid;
9076 6 grid = &grid[c->nb_heif_grid++];
9077
9078 6 entries = avio_rb16(pb);
9079 6 grid->tile_id_list = av_malloc_array(entries, sizeof(*grid->tile_id_list));
9080 6 grid->tile_idx_list = av_calloc(entries, sizeof(*grid->tile_idx_list));
9081 6 grid->tile_item_list = av_calloc(entries, sizeof(*grid->tile_item_list));
9082
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)
9083 return AVERROR(ENOMEM);
9084 /* 'to' item ids */
9085
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (i = 0; i < entries; i++)
9086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 grid->tile_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
9087 6 grid->nb_tiles = entries;
9088 6 grid->item = item;
9089
9090 6 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
9091 from_item_id, entries);
9092
9093 6 return 0;
9094 }
9095
9096 11 static int mov_read_iref_cdsc(MOVContext *c, AVIOContext *pb, uint32_t type, int version)
9097 {
9098 11 HEIFItem *from_item = NULL;
9099 int entries;
9100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9101 11 const HEIFItemRef ref = { type, from_item_id };
9102
9103 11 from_item = get_heif_item(c, from_item_id);
9104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!from_item) {
9105 av_log(c->fc, AV_LOG_ERROR, "Missing stream referenced by thmb item\n");
9106 return AVERROR_INVALIDDATA;
9107 }
9108
9109 11 entries = avio_rb16(pb);
9110 /* 'to' item ids */
9111
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (int i = 0; i < entries; i++) {
9112
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));
9113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!item) {
9114 av_log(c->fc, AV_LOG_WARNING, "Missing stream referenced by %s item\n",
9115 av_fourcc2str(type));
9116 continue;
9117 }
9118
9119
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (!av_dynarray2_add((void **)&item->iref_list, &item->nb_iref_list,
9120 sizeof(*item->iref_list), (const uint8_t *)&ref))
9121 return AVERROR(ENOMEM);
9122 }
9123
9124 11 av_log(c->fc, AV_LOG_TRACE, "%s: from_item_id %d, entries %d\n",
9125 11 av_fourcc2str(type), from_item_id, entries);
9126
9127 11 return 0;
9128 }
9129
9130 11 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9131 {
9132 11 int version = avio_r8(pb);
9133 11 avio_rb24(pb); // flags
9134 11 atom.size -= 4;
9135
9136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (version > 1) {
9137 av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
9138 return 0;
9139 }
9140
9141
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 11 times.
28 while (atom.size) {
9142 17 uint32_t type, size = avio_rb32(pb);
9143 17 int64_t next = avio_tell(pb);
9144
9145
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)
9146 return AVERROR_INVALIDDATA;
9147
9148 17 next += size - 4;
9149 17 type = avio_rl32(pb);
9150
2/3
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
17 switch (type) {
9151 6 case MKTAG('d','i','m','g'):
9152 6 mov_read_iref_dimg(c, pb, version);
9153 17 break;
9154 11 case MKTAG('c','d','s','c'):
9155 case MKTAG('t','h','m','b'):
9156 11 mov_read_iref_cdsc(c, pb, type, version);
9157 11 break;
9158 default:
9159 av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
9160 av_fourcc2str(type), size);
9161 }
9162
9163 17 atom.size -= size;
9164 17 avio_seek(pb, next, SEEK_SET);
9165 }
9166 11 return 0;
9167 }
9168
9169 37 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9170 {
9171 HEIFItem *item;
9172 uint32_t width, height;
9173
9174 37 avio_r8(pb); /* version */
9175 37 avio_rb24(pb); /* flags */
9176 37 width = avio_rb32(pb);
9177 37 height = avio_rb32(pb);
9178
9179 37 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %u, height %u\n",
9180 c->cur_item_id, width, height);
9181
9182 37 item = get_heif_item(c, c->cur_item_id);
9183
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if (item) {
9184 37 item->width = width;
9185 37 item->height = height;
9186 }
9187
9188 37 return 0;
9189 }
9190
9191 8 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9192 {
9193 HEIFItem *item;
9194 int angle;
9195
9196 8 angle = avio_r8(pb) & 0x3;
9197
9198 8 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
9199 c->cur_item_id, angle);
9200
9201 8 item = get_heif_item(c, c->cur_item_id);
9202
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (item) {
9203 // angle * 90 specifies the angle (in anti-clockwise direction)
9204 // in units of degrees.
9205 8 item->rotation = angle * 90;
9206 }
9207
9208 8 return 0;
9209 }
9210
9211 6 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9212 {
9213 HEIFItem *item;
9214 int axis;
9215
9216 6 axis = avio_r8(pb) & 0x1;
9217
9218 6 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
9219 c->cur_item_id, axis);
9220
9221 6 item = get_heif_item(c, c->cur_item_id);
9222
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
9223 6 item->hflip = axis;
9224 6 item->vflip = !axis;
9225 }
9226
9227 6 return 0;
9228 }
9229
9230 15 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9231 {
9232 typedef struct MOVAtoms {
9233 FFIOContext b;
9234 uint32_t type;
9235 int64_t size;
9236 uint8_t *data;
9237 } MOVAtoms;
9238 15 MOVAtoms *atoms = NULL;
9239 MOVAtom a;
9240 unsigned count;
9241 15 int nb_atoms = 0;
9242 int version, flags;
9243 int ret;
9244
9245 15 a.size = avio_rb32(pb);
9246 15 a.type = avio_rl32(pb);
9247
9248
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'))
9249 return AVERROR_INVALIDDATA;
9250
9251 15 a.size -= 8;
9252
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 15 times.
86 while (a.size >= 8) {
9253 71 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
9254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (!ref) {
9255 ret = AVERROR(ENOMEM);
9256 goto fail;
9257 }
9258 71 ref->data = NULL;
9259 71 ref->size = avio_rb32(pb);
9260 71 ref->type = avio_rl32(pb);
9261
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)
9262 break;
9263 71 ref->data = av_malloc(ref->size);
9264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (!ref->data) {
9265 ret = AVERROR_INVALIDDATA;
9266 goto fail;
9267 }
9268 71 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
9269 71 avio_seek(pb, -8, SEEK_CUR);
9270
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 71 times.
71 if (avio_read(pb, ref->data, ref->size) != ref->size) {
9271 ret = AVERROR_INVALIDDATA;
9272 goto fail;
9273 }
9274 71 ffio_init_read_context(&ref->b, ref->data, ref->size);
9275 71 a.size -= ref->size;
9276 }
9277
9278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (a.size) {
9279 ret = AVERROR_INVALIDDATA;
9280 goto fail;
9281 }
9282
9283 15 a.size = avio_rb32(pb);
9284 15 a.type = avio_rl32(pb);
9285
9286
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')) {
9287 ret = AVERROR_INVALIDDATA;
9288 goto fail;
9289 }
9290
9291 15 version = avio_r8(pb);
9292 15 flags = avio_rb24(pb);
9293 15 count = avio_rb32(pb);
9294
9295
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 15 times.
52 for (int i = 0; i < count; i++) {
9296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9297 37 int assoc_count = avio_r8(pb);
9298
9299
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
37 if (avio_feof(pb)) {
9300 ret = AVERROR_INVALIDDATA;
9301 goto fail;
9302 }
9303
9304
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 37 times.
135 for (int j = 0; j < assoc_count; j++) {
9305 MOVAtoms *ref;
9306 98 int index = avio_r8(pb) & 0x7f;
9307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (flags & 1) {
9308 index <<= 8;
9309 index |= avio_r8(pb);
9310 }
9311
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) {
9312 ret = AVERROR_INVALIDDATA;
9313 goto fail;
9314 }
9315 98 ref = &atoms[--index];
9316
9317 98 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
9318 98 index + 1, item_id, av_fourcc2str(ref->type));
9319
9320 98 c->cur_item_id = item_id;
9321
9322 98 ret = mov_read_default(c, &ref->b.pub,
9323 98 (MOVAtom) { .size = ref->size,
9324 .type = MKTAG('i','p','c','o') });
9325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (ret < 0)
9326 goto fail;
9327 98 ffio_init_read_context(&ref->b, ref->data, ref->size);
9328 }
9329 }
9330
9331 15 ret = 0;
9332 15 fail:
9333 15 c->cur_item_id = -1;
9334
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 15 times.
86 for (int i = 0; i < nb_atoms; i++)
9335 71 av_free(atoms[i].data);
9336 15 av_free(atoms);
9337
9338 15 return ret;
9339 }
9340
9341 static const MOVParseTableEntry mov_default_parse_table[] = {
9342 { MKTAG('A','C','L','R'), mov_read_aclr },
9343 { MKTAG('A','P','R','G'), mov_read_avid },
9344 { MKTAG('A','A','L','P'), mov_read_avid },
9345 { MKTAG('A','R','E','S'), mov_read_ares },
9346 { MKTAG('a','v','s','s'), mov_read_avss },
9347 { MKTAG('a','v','1','C'), mov_read_glbl },
9348 { MKTAG('c','h','p','l'), mov_read_chpl },
9349 { MKTAG('c','o','6','4'), mov_read_stco },
9350 { MKTAG('c','o','l','r'), mov_read_colr },
9351 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
9352 { MKTAG('d','i','n','f'), mov_read_default },
9353 { MKTAG('D','p','x','E'), mov_read_dpxe },
9354 { MKTAG('d','r','e','f'), mov_read_dref },
9355 { MKTAG('e','d','t','s'), mov_read_default },
9356 { MKTAG('e','l','s','t'), mov_read_elst },
9357 { MKTAG('e','n','d','a'), mov_read_enda },
9358 { MKTAG('f','i','e','l'), mov_read_fiel },
9359 { MKTAG('a','d','r','m'), mov_read_adrm },
9360 { MKTAG('f','t','y','p'), mov_read_ftyp },
9361 { MKTAG('g','l','b','l'), mov_read_glbl },
9362 { MKTAG('h','d','l','r'), mov_read_hdlr },
9363 { MKTAG('i','l','s','t'), mov_read_ilst },
9364 { MKTAG('j','p','2','h'), mov_read_jp2h },
9365 { MKTAG('m','d','a','t'), mov_read_mdat },
9366 { MKTAG('m','d','h','d'), mov_read_mdhd },
9367 { MKTAG('m','d','i','a'), mov_read_default },
9368 { MKTAG('m','e','t','a'), mov_read_meta },
9369 { MKTAG('m','i','n','f'), mov_read_default },
9370 { MKTAG('m','o','o','f'), mov_read_moof },
9371 { MKTAG('m','o','o','v'), mov_read_moov },
9372 { MKTAG('m','v','e','x'), mov_read_default },
9373 { MKTAG('m','v','h','d'), mov_read_mvhd },
9374 { MKTAG('S','M','I',' '), mov_read_svq3 },
9375 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
9376 { MKTAG('a','v','c','C'), mov_read_glbl },
9377 { MKTAG('p','a','s','p'), mov_read_pasp },
9378 { MKTAG('c','l','a','p'), mov_read_clap },
9379 { MKTAG('s','b','a','s'), mov_read_sbas },
9380 { MKTAG('s','i','d','x'), mov_read_sidx },
9381 { MKTAG('s','t','b','l'), mov_read_default },
9382 { MKTAG('s','t','c','o'), mov_read_stco },
9383 { MKTAG('s','t','p','s'), mov_read_stps },
9384 { MKTAG('s','t','r','f'), mov_read_strf },
9385 { MKTAG('s','t','s','c'), mov_read_stsc },
9386 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
9387 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
9388 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
9389 { MKTAG('s','t','t','s'), mov_read_stts },
9390 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
9391 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
9392 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
9393 { MKTAG('t','f','d','t'), mov_read_tfdt },
9394 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
9395 { MKTAG('t','r','a','k'), mov_read_trak },
9396 { MKTAG('t','r','a','f'), mov_read_default },
9397 { MKTAG('t','r','e','f'), mov_read_default },
9398 { MKTAG('t','m','c','d'), mov_read_tmcd },
9399 { MKTAG('c','h','a','p'), mov_read_chap },
9400 { MKTAG('t','r','e','x'), mov_read_trex },
9401 { MKTAG('t','r','u','n'), mov_read_trun },
9402 { MKTAG('u','d','t','a'), mov_read_default },
9403 { MKTAG('w','a','v','e'), mov_read_wave },
9404 { MKTAG('e','s','d','s'), mov_read_esds },
9405 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
9406 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
9407 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
9408 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
9409 { MKTAG('w','f','e','x'), mov_read_wfex },
9410 { MKTAG('c','m','o','v'), mov_read_cmov },
9411 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
9412 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
9413 { MKTAG('d','v','c','1'), mov_read_dvc1 },
9414 { MKTAG('s','g','p','d'), mov_read_sgpd },
9415 { MKTAG('s','b','g','p'), mov_read_sbgp },
9416 { MKTAG('h','v','c','C'), mov_read_glbl },
9417 { MKTAG('v','v','c','C'), mov_read_glbl },
9418 { MKTAG('u','u','i','d'), mov_read_uuid },
9419 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
9420 { MKTAG('f','r','e','e'), mov_read_free },
9421 { MKTAG('-','-','-','-'), mov_read_custom },
9422 { MKTAG('s','i','n','f'), mov_read_default },
9423 { MKTAG('f','r','m','a'), mov_read_frma },
9424 { MKTAG('s','e','n','c'), mov_read_senc },
9425 { MKTAG('s','a','i','z'), mov_read_saiz },
9426 { MKTAG('s','a','i','o'), mov_read_saio },
9427 { MKTAG('p','s','s','h'), mov_read_pssh },
9428 { MKTAG('s','c','h','m'), mov_read_schm },
9429 { MKTAG('s','c','h','i'), mov_read_default },
9430 { MKTAG('t','e','n','c'), mov_read_tenc },
9431 { MKTAG('d','f','L','a'), mov_read_dfla },
9432 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
9433 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
9434 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
9435 { MKTAG('h','f','o','v'), mov_read_hfov },
9436 { MKTAG('d','O','p','s'), mov_read_dops },
9437 { MKTAG('d','m','l','p'), mov_read_dmlp },
9438 { MKTAG('S','m','D','m'), mov_read_smdm },
9439 { MKTAG('C','o','L','L'), mov_read_coll },
9440 { MKTAG('v','p','c','C'), mov_read_vpcc },
9441 { MKTAG('m','d','c','v'), mov_read_mdcv },
9442 { MKTAG('c','l','l','i'), mov_read_clli },
9443 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
9444 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
9445 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
9446 { MKTAG('k','i','n','d'), mov_read_kind },
9447 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
9448 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
9449 { MKTAG('i','l','o','c'), mov_read_iloc },
9450 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
9451 { MKTAG('p','i','t','m'), mov_read_pitm },
9452 { MKTAG('e','v','c','C'), mov_read_glbl },
9453 { MKTAG('i','d','a','t'), mov_read_idat },
9454 { MKTAG('i','m','i','r'), mov_read_imir },
9455 { MKTAG('i','r','e','f'), mov_read_iref },
9456 { MKTAG('i','s','p','e'), mov_read_ispe },
9457 { MKTAG('i','r','o','t'), mov_read_irot },
9458 { MKTAG('i','p','r','p'), mov_read_iprp },
9459 { MKTAG('i','i','n','f'), mov_read_iinf },
9460 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
9461 { MKTAG('l','h','v','C'), mov_read_lhvc },
9462 { MKTAG('l','v','c','C'), mov_read_glbl },
9463 { MKTAG('a','p','v','C'), mov_read_glbl },
9464 #if CONFIG_IAMFDEC
9465 { MKTAG('i','a','c','b'), mov_read_iacb },
9466 #endif
9467 { 0, NULL }
9468 };
9469
9470 6703 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9471 {
9472 6703 int64_t total_size = 0;
9473 MOVAtom a;
9474 int i;
9475
9476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6703 times.
6703 if (c->atom_depth > 10) {
9477 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
9478 return AVERROR_INVALIDDATA;
9479 }
9480 6703 c->atom_depth ++;
9481
9482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6703 times.
6703 if (atom.size < 0)
9483 atom.size = INT64_MAX;
9484
2/2
✓ Branch 0 taken 19278 times.
✓ Branch 1 taken 6212 times.
25490 while (total_size <= atom.size - 8) {
9485 19278 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
9486 19278 a.size = avio_rb32(pb);
9487 19278 a.type = avio_rl32(pb);
9488
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 19273 times.
19278 if (avio_feof(pb))
9489 5 break;
9490
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) ||
9491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19273 times.
19273 a.type == MKTAG('h','o','o','v')) &&
9492 a.size >= 8 &&
9493 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
9494 uint32_t type;
9495 avio_skip(pb, 4);
9496 type = avio_rl32(pb);
9497 if (avio_feof(pb))
9498 break;
9499 avio_seek(pb, -8, SEEK_CUR);
9500 if (type == MKTAG('m','v','h','d') ||
9501 type == MKTAG('c','m','o','v')) {
9502 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
9503 a.type = MKTAG('m','o','o','v');
9504 }
9505 }
9506
2/2
✓ Branch 0 taken 16366 times.
✓ Branch 1 taken 2907 times.
19273 if (atom.type != MKTAG('r','o','o','t') &&
9507
2/2
✓ Branch 0 taken 14919 times.
✓ Branch 1 taken 1447 times.
16366 atom.type != MKTAG('m','o','o','v')) {
9508
1/2
✓ Branch 0 taken 14919 times.
✗ Branch 1 not taken.
14919 if (a.type == MKTAG('t','r','a','k') ||
9509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14919 times.
14919 a.type == MKTAG('m','d','a','t')) {
9510 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
9511 avio_skip(pb, -8);
9512 c->atom_depth --;
9513 486 return 0;
9514 }
9515 }
9516 19273 total_size += 8;
9517
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 */
9518 26 a.size = avio_rb64(pb) - 8;
9519 26 total_size += 8;
9520 }
9521 19273 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
9522 19273 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
9523
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19268 times.
19273 if (a.size == 0) {
9524 5 a.size = atom.size - total_size + 8;
9525 }
9526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19273 times.
19273 if (a.size < 0)
9527 break;
9528 19273 a.size -= 8;
9529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19273 times.
19273 if (a.size < 0)
9530 break;
9531 19273 a.size = FFMIN(a.size, atom.size - total_size);
9532
9533
2/2
✓ Branch 0 taken 888143 times.
✓ Branch 1 taken 1961 times.
890104 for (i = 0; mov_default_parse_table[i].type; i++)
9534
2/2
✓ Branch 0 taken 17312 times.
✓ Branch 1 taken 870831 times.
888143 if (mov_default_parse_table[i].type == a.type) {
9535 17312 parse = mov_default_parse_table[i].parse;
9536 17312 break;
9537 }
9538
9539 // container is user data
9540
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') ||
9541
2/2
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 1484 times.
1784 atom.type == MKTAG('i','l','s','t')))
9542 477 parse = mov_read_udta_string;
9543
9544 // Supports parsing the QuickTime Metadata Keys.
9545 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
9546
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 &&
9547
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 atom.type == MKTAG('m','e','t','a') &&
9548
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 a.type == MKTAG('k','e','y','s') &&
9549
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 c->meta_keys_count == 0) {
9550 11 parse = mov_read_keys;
9551 }
9552
9553
2/2
✓ Branch 0 taken 1473 times.
✓ Branch 1 taken 17800 times.
19273 if (!parse) { /* skip leaf atoms data */
9554 1473 avio_skip(pb, a.size);
9555 } else {
9556 17800 int64_t start_pos = avio_tell(pb);
9557 int64_t left;
9558 17800 int err = parse(c, pb, a);
9559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17800 times.
17800 if (err < 0) {
9560 c->atom_depth --;
9561 return err;
9562 }
9563
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 &&
9564
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) ||
9565 3326 start_pos + a.size == avio_size(pb))) {
9566
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)
9567 9 c->next_root_atom = start_pos + a.size;
9568 486 c->atom_depth --;
9569 486 return 0;
9570 }
9571 17314 left = a.size - avio_tell(pb) + start_pos;
9572
2/2
✓ Branch 0 taken 1465 times.
✓ Branch 1 taken 15849 times.
17314 if (left > 0) /* skip garbage at atom end */
9573 1465 avio_skip(pb, left);
9574
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 15847 times.
15849 else if (left < 0) {
9575 2 av_log(c->fc, AV_LOG_WARNING,
9576 "overread end of atom '%s' by %"PRId64" bytes\n",
9577 2 av_fourcc2str(a.type), -left);
9578 2 avio_seek(pb, left, SEEK_CUR);
9579 }
9580 }
9581
9582 18787 total_size += a.size;
9583 }
9584
9585
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)
9586 102 avio_skip(pb, atom.size - total_size);
9587
9588 6217 c->atom_depth --;
9589 6217 return 0;
9590 }
9591
9592 7279 static int mov_probe(const AVProbeData *p)
9593 {
9594 int64_t offset;
9595 uint32_t tag;
9596 7279 int score = 0;
9597 7279 int moov_offset = -1;
9598
9599 /* check file header */
9600 7279 offset = 0;
9601 8980 for (;;) {
9602 int64_t size;
9603 16259 int minsize = 8;
9604 /* ignore invalid offset */
9605
2/2
✓ Branch 0 taken 7279 times.
✓ Branch 1 taken 8980 times.
16259 if ((offset + 8ULL) > (unsigned int)p->buf_size)
9606 7279 break;
9607 8980 size = AV_RB32(p->buf + offset);
9608
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) {
9609 524 size = AV_RB64(p->buf+offset + 8);
9610 524 minsize = 16;
9611
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 8401 times.
8456 } else if (size == 0) {
9612 55 size = p->buf_size - offset;
9613 }
9614
2/2
✓ Branch 0 taken 399 times.
✓ Branch 1 taken 8581 times.
8980 if (size < minsize) {
9615 399 offset += 4;
9616 399 continue;
9617 }
9618 8581 tag = AV_RL32(p->buf + offset + 4);
9619
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) {
9620 /* check for obvious tags */
9621 129 case MKTAG('m','o','o','v'):
9622 129 moov_offset = offset + 4;
9623 979 case MKTAG('m','d','a','t'):
9624 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
9625 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
9626 case MKTAG('f','t','y','p'):
9627
2/2
✓ Branch 0 taken 444 times.
✓ Branch 1 taken 535 times.
979 if (tag == MKTAG('f','t','y','p') &&
9628
1/2
✓ Branch 0 taken 444 times.
✗ Branch 1 not taken.
444 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
9629
1/2
✓ Branch 0 taken 444 times.
✗ Branch 1 not taken.
444 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
9630
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 438 times.
444 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
9631 )) {
9632 6 score = FFMAX(score, 5);
9633 } else {
9634 973 score = AVPROBE_SCORE_MAX;
9635 }
9636 979 break;
9637 /* those are more common words, so rate then a bit less */
9638 358 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
9639 case MKTAG('w','i','d','e'):
9640 case MKTAG('f','r','e','e'):
9641 case MKTAG('j','u','n','k'):
9642 case MKTAG('p','i','c','t'):
9643 358 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
9644 358 break;
9645 case MKTAG(0x82,0x82,0x7f,0x7d):
9646 score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
9647 break;
9648 1 case MKTAG('s','k','i','p'):
9649 case MKTAG('u','u','i','d'):
9650 case MKTAG('p','r','f','l'):
9651 /* if we only find those cause probedata is too small at least rate them */
9652 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
9653 1 break;
9654 }
9655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8581 times.
8581 if (size > INT64_MAX - offset)
9656 break;
9657 8581 offset += size;
9658 }
9659
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) {
9660 /* moov atom in the header - we should make sure that this is not a
9661 * MOV-packed MPEG-PS */
9662 129 offset = moov_offset;
9663
9664
2/2
✓ Branch 0 taken 126614 times.
✓ Branch 1 taken 129 times.
126743 while (offset < (p->buf_size - 16)) { /* Sufficient space */
9665 /* We found an actual hdlr atom */
9666
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 126477 times.
126614 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
9667
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 116 times.
137 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
9668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
9669 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
9670 /* We found a media handler reference atom describing an
9671 * MPEG-PS-in-MOV, return a
9672 * low score to force expanding the probe window until
9673 * mpegps_probe finds what it needs */
9674 return 5;
9675 } else {
9676 /* Keep looking */
9677 126614 offset += 2;
9678 }
9679 }
9680 }
9681
9682 7279 return score;
9683 }
9684
9685 // must be done after parsing all trak because there's no order requirement
9686 2 static void mov_read_chapters(AVFormatContext *s)
9687 {
9688 2 MOVContext *mov = s->priv_data;
9689 MOVStreamContext *sc;
9690 int64_t cur_pos;
9691 int i, j;
9692 int chapter_track;
9693
9694
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
9695 2 AVStream *st = NULL;
9696 2 FFStream *sti = NULL;
9697 2 chapter_track = mov->chapter_tracks[j];
9698
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
9699 4 sc = mov->fc->streams[i]->priv_data;
9700
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
9701 2 st = s->streams[i];
9702 2 break;
9703 }
9704 }
9705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
9706 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
9707 continue;
9708 }
9709 2 sti = ffstream(st);
9710
9711 2 sc = st->priv_data;
9712 2 cur_pos = avio_tell(sc->pb);
9713
9714
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
9715 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
9716 if (!st->attached_pic.data && sti->nb_index_entries) {
9717 // Retrieve the first frame, if possible
9718 AVIndexEntry *sample = &sti->index_entries[0];
9719 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9720 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
9721 goto finish;
9722 }
9723
9724 if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
9725 goto finish;
9726 }
9727 } else {
9728 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
9729 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
9730 2 st->discard = AVDISCARD_ALL;
9731
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
9732 8 AVIndexEntry *sample = &sti->index_entries[i];
9733
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;
9734 uint8_t *title;
9735 uint16_t ch;
9736 int len, title_len;
9737
9738
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
9739 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
9740 end = AV_NOPTS_VALUE;
9741 }
9742
9743
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9744 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
9745 goto finish;
9746 }
9747
9748 // the first two bytes are the length of the title
9749 8 len = avio_rb16(sc->pb);
9750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
9751 continue;
9752 8 title_len = 2*len + 1;
9753
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
9754 goto finish;
9755
9756 // The samples could theoretically be in any encoding if there's an encd
9757 // atom following, but in practice are only utf-8 or utf-16, distinguished
9758 // instead by the presence of a BOM
9759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
9760 title[0] = 0;
9761 } else {
9762 8 ch = avio_rb16(sc->pb);
9763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
9764 avio_get_str16be(sc->pb, len, title, title_len);
9765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
9766 avio_get_str16le(sc->pb, len, title, title_len);
9767 else {
9768 8 AV_WB16(title, ch);
9769
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)
9770 title[len] = 0;
9771 else
9772 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
9773 }
9774 }
9775
9776 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
9777 8 av_freep(&title);
9778 }
9779 }
9780 2 finish:
9781 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
9782 }
9783 2 }
9784
9785 19 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
9786 int64_t value, int flags)
9787 {
9788 AVTimecode tc;
9789 char buf[AV_TIMECODE_STR_SIZE];
9790 19 AVRational rate = st->avg_frame_rate;
9791 19 int ret = av_timecode_init(&tc, rate, flags, 0, s);
9792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
9793 return ret;
9794 19 av_dict_set(&st->metadata, "timecode",
9795 19 av_timecode_make_string(&tc, buf, value), 0);
9796 19 return 0;
9797 }
9798
9799 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
9800 {
9801 MOVStreamContext *sc = st->priv_data;
9802 FFStream *const sti = ffstream(st);
9803 char buf[AV_TIMECODE_STR_SIZE];
9804 int64_t cur_pos = avio_tell(sc->pb);
9805 int hh, mm, ss, ff, drop;
9806
9807 if (!sti->nb_index_entries)
9808 return -1;
9809
9810 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9811 avio_skip(s->pb, 13);
9812 hh = avio_r8(s->pb);
9813 mm = avio_r8(s->pb);
9814 ss = avio_r8(s->pb);
9815 drop = avio_r8(s->pb);
9816 ff = avio_r8(s->pb);
9817 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
9818 hh, mm, ss, drop ? ';' : ':', ff);
9819 av_dict_set(&st->metadata, "timecode", buf, 0);
9820
9821 avio_seek(sc->pb, cur_pos, SEEK_SET);
9822 return 0;
9823 }
9824
9825 19 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
9826 {
9827 19 MOVStreamContext *sc = st->priv_data;
9828 19 FFStream *const sti = ffstream(st);
9829 19 int flags = 0;
9830 19 int64_t cur_pos = avio_tell(sc->pb);
9831 int64_t value;
9832 19 AVRational tc_rate = st->avg_frame_rate;
9833 19 int tmcd_nb_frames = sc->tmcd_nb_frames;
9834 int rounded_tc_rate;
9835
9836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!sti->nb_index_entries)
9837 return -1;
9838
9839
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)
9840 return -1;
9841
9842 19 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9843 19 value = avio_rb32(s->pb);
9844
9845
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13 times.
19 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
9846
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
9847
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
9848
9849 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
9850 * not the case) and thus assume "frame number format" instead of QT one.
9851 * No sample with tmcd track can be found with a QT timecode at the moment,
9852 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
9853 * format). */
9854
9855 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
9856 * we multiply the frame number with the quotient.
9857 * See tickets #9492, #9710. */
9858 19 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
9859 /* Work around files where tmcd_nb_frames is rounded down from frame rate
9860 * instead of up. See ticket #5978. */
9861
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
9862
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
9863 10 tmcd_nb_frames = rounded_tc_rate;
9864 19 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
9865
9866 19 parse_timecode_in_framenum_format(s, st, value, flags);
9867
9868 19 avio_seek(sc->pb, cur_pos, SEEK_SET);
9869 19 return 0;
9870 }
9871
9872 1221 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
9873 int i;
9874
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;
9875
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 4 times.
76 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
9876 72 av_encryption_info_free((*index)->encrypted_samples[i]);
9877 }
9878 4 av_freep(&(*index)->encrypted_samples);
9879 4 av_freep(&(*index)->auxiliary_info_sizes);
9880 4 av_freep(&(*index)->auxiliary_offsets);
9881 4 av_freep(index);
9882 }
9883
9884 697 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
9885 {
9886 697 MOVStreamContext *sc = st->priv_data;
9887
9888
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) {
9889 40 st->priv_data = NULL;
9890 40 return;
9891 }
9892
9893 657 av_freep(&sc->tts_data);
9894
2/2
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 657 times.
1269 for (int i = 0; i < sc->drefs_count; i++) {
9895 612 av_freep(&sc->drefs[i].path);
9896 612 av_freep(&sc->drefs[i].dir);
9897 }
9898 657 av_freep(&sc->drefs);
9899
9900 657 sc->drefs_count = 0;
9901
9902
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 643 times.
657 if (!sc->pb_is_copied)
9903 14 ff_format_io_close(s, &sc->pb);
9904
9905 657 sc->pb = NULL;
9906 657 av_freep(&sc->chunk_offsets);
9907 657 av_freep(&sc->stsc_data);
9908 657 av_freep(&sc->sample_sizes);
9909 657 av_freep(&sc->keyframes);
9910 657 av_freep(&sc->ctts_data);
9911 657 av_freep(&sc->stts_data);
9912 657 av_freep(&sc->sdtp_data);
9913 657 av_freep(&sc->stps_data);
9914 657 av_freep(&sc->elst_data);
9915 657 av_freep(&sc->rap_group);
9916 657 av_freep(&sc->sync_group);
9917 657 av_freep(&sc->sgpd_sync);
9918 657 av_freep(&sc->sample_offsets);
9919 657 av_freep(&sc->open_key_samples);
9920 657 av_freep(&sc->display_matrix);
9921 657 av_freep(&sc->index_ranges);
9922
9923
2/2
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 45 times.
657 if (sc->extradata)
9924
2/2
✓ Branch 0 taken 625 times.
✓ Branch 1 taken 612 times.
1237 for (int i = 0; i < sc->stsd_count; i++)
9925 625 av_free(sc->extradata[i]);
9926 657 av_freep(&sc->extradata);
9927 657 av_freep(&sc->extradata_size);
9928
9929 657 mov_free_encryption_index(&sc->cenc.encryption_index);
9930 657 av_encryption_info_free(sc->cenc.default_encrypted_sample);
9931 657 av_aes_ctr_free(sc->cenc.aes_ctr);
9932
9933 657 av_freep(&sc->stereo3d);
9934 657 av_freep(&sc->spherical);
9935 657 av_freep(&sc->mastering);
9936 657 av_freep(&sc->coll);
9937 657 av_freep(&sc->ambient);
9938
9939 #if CONFIG_IAMFDEC
9940
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 647 times.
657 if (sc->iamf)
9941 10 ff_iamf_read_deinit(sc->iamf);
9942 #endif
9943 657 av_freep(&sc->iamf);
9944 }
9945
9946 509 static int mov_read_close(AVFormatContext *s)
9947 {
9948 509 MOVContext *mov = s->priv_data;
9949 int i, j;
9950
9951
2/2
✓ Branch 0 taken 697 times.
✓ Branch 1 taken 509 times.
1206 for (i = 0; i < s->nb_streams; i++) {
9952 697 AVStream *st = s->streams[i];
9953
9954 697 mov_free_stream_context(s, st);
9955 }
9956
9957 509 av_freep(&mov->dv_demux);
9958 509 avformat_free_context(mov->dv_fctx);
9959 509 mov->dv_fctx = NULL;
9960
9961
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 498 times.
509 if (mov->meta_keys) {
9962
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i < mov->meta_keys_count; i++) {
9963 58 av_freep(&mov->meta_keys[i]);
9964 }
9965 11 av_freep(&mov->meta_keys);
9966 }
9967
9968 509 av_freep(&mov->trex_data);
9969 509 av_freep(&mov->bitrates);
9970
9971
2/2
✓ Branch 0 taken 468 times.
✓ Branch 1 taken 509 times.
977 for (i = 0; i < mov->frag_index.nb_items; i++) {
9972 468 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
9973
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++) {
9974 564 mov_free_encryption_index(&frag[j].encryption_index);
9975 }
9976 468 av_freep(&mov->frag_index.item[i].stream_info);
9977 }
9978 509 av_freep(&mov->frag_index.item);
9979
9980 509 av_freep(&mov->aes_decrypt);
9981 509 av_freep(&mov->chapter_tracks);
9982
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 509 times.
551 for (i = 0; i < mov->nb_heif_item; i++) {
9983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!mov->heif_item[i])
9984 continue;
9985 42 av_freep(&mov->heif_item[i]->name);
9986 42 av_freep(&mov->heif_item[i]->iref_list);
9987 42 av_freep(&mov->heif_item[i]->icc_profile);
9988 42 av_freep(&mov->heif_item[i]);
9989 }
9990 509 av_freep(&mov->heif_item);
9991
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 509 times.
515 for (i = 0; i < mov->nb_heif_grid; i++) {
9992 6 av_freep(&mov->heif_grid[i].tile_id_list);
9993 6 av_freep(&mov->heif_grid[i].tile_idx_list);
9994 6 av_freep(&mov->heif_grid[i].tile_item_list);
9995 }
9996 509 av_freep(&mov->heif_grid);
9997
9998 509 return 0;
9999 }
10000
10001 16 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
10002 {
10003 int i;
10004
10005
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 for (i = 0; i < s->nb_streams; i++) {
10006 24 AVStream *st = s->streams[i];
10007 24 MOVStreamContext *sc = st->priv_data;
10008
10009
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
10010
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 sc->timecode_track == tmcd_id)
10011 14 return 1;
10012 }
10013 2 return 0;
10014 }
10015
10016 /* look for a tmcd track not referenced by any video track, and export it globally */
10017 509 static void export_orphan_timecode(AVFormatContext *s)
10018 {
10019 int i;
10020
10021
2/2
✓ Branch 0 taken 694 times.
✓ Branch 1 taken 507 times.
1201 for (i = 0; i < s->nb_streams; i++) {
10022 694 AVStream *st = s->streams[i];
10023
10024
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') &&
10025 16 !tmcd_is_referenced(s, i + 1)) {
10026 2 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
10027
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (tcr) {
10028 2 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
10029 2 break;
10030 }
10031 }
10032 }
10033 509 }
10034
10035 static int read_tfra(MOVContext *mov, AVIOContext *f)
10036 {
10037 int version, fieldlength, i, j;
10038 int64_t pos = avio_tell(f);
10039 uint32_t size = avio_rb32(f);
10040 unsigned track_id, item_count;
10041
10042 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
10043 return 1;
10044 }
10045 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
10046
10047 version = avio_r8(f);
10048 avio_rb24(f);
10049 track_id = avio_rb32(f);
10050 fieldlength = avio_rb32(f);
10051 item_count = avio_rb32(f);
10052 for (i = 0; i < item_count; i++) {
10053 int64_t time, offset;
10054 int index;
10055 MOVFragmentStreamInfo * frag_stream_info;
10056
10057 if (avio_feof(f)) {
10058 return AVERROR_INVALIDDATA;
10059 }
10060
10061 if (version == 1) {
10062 time = avio_rb64(f);
10063 offset = avio_rb64(f);
10064 } else {
10065 time = avio_rb32(f);
10066 offset = avio_rb32(f);
10067 }
10068
10069 // The first sample of each stream in a fragment is always a random
10070 // access sample. So it's entry in the tfra can be used as the
10071 // initial PTS of the fragment.
10072 index = update_frag_index(mov, offset);
10073 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
10074 if (frag_stream_info &&
10075 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
10076 frag_stream_info->first_tfra_pts = time;
10077
10078 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
10079 avio_r8(f);
10080 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
10081 avio_r8(f);
10082 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
10083 avio_r8(f);
10084 }
10085
10086 avio_seek(f, pos + size, SEEK_SET);
10087 return 0;
10088 }
10089
10090 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
10091 {
10092 int64_t stream_size = avio_size(f);
10093 int64_t original_pos = avio_tell(f);
10094 int64_t seek_ret;
10095 int ret = -1;
10096 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
10097 ret = seek_ret;
10098 goto fail;
10099 }
10100 c->mfra_size = avio_rb32(f);
10101 c->have_read_mfra_size = 1;
10102 if (!c->mfra_size || c->mfra_size > stream_size) {
10103 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
10104 goto fail;
10105 }
10106 if ((seek_ret = avio_seek(f, -((int64_t) c->mfra_size), SEEK_CUR)) < 0) {
10107 ret = seek_ret;
10108 goto fail;
10109 }
10110 if (avio_rb32(f) != c->mfra_size) {
10111 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
10112 goto fail;
10113 }
10114 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
10115 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
10116 goto fail;
10117 }
10118 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
10119 do {
10120 ret = read_tfra(c, f);
10121 if (ret < 0)
10122 goto fail;
10123 } while (!ret);
10124 ret = 0;
10125 c->frag_index.complete = 1;
10126 fail:
10127 seek_ret = avio_seek(f, original_pos, SEEK_SET);
10128 if (seek_ret < 0) {
10129 av_log(c->fc, AV_LOG_ERROR,
10130 "failed to seek back after looking for mfra\n");
10131 ret = seek_ret;
10132 }
10133 return ret;
10134 }
10135
10136 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10137 const HEIFItem *item)
10138 {
10139 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
10140 AV_PKT_DATA_ICC_PROFILE,
10141 item->icc_profile_size, 0);
10142 if (!sd)
10143 return AVERROR(ENOMEM);
10144
10145 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
10146
10147 return 0;
10148 }
10149
10150 6 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10151 const HEIFItem *item)
10152 {
10153 int32_t *matrix;
10154 6 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data,
10155 nb_coded_side_data,
10156 AV_PKT_DATA_DISPLAYMATRIX,
10157 9 * sizeof(*matrix), 0);
10158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sd)
10159 return AVERROR(ENOMEM);
10160
10161 6 matrix = (int32_t*)sd->data;
10162 /* rotation is in the counter-clockwise direction whereas
10163 * av_display_rotation_set() expects its argument to be
10164 * oriented clockwise, so we need to negate it. */
10165 6 av_display_rotation_set(matrix, -item->rotation);
10166 6 av_display_matrix_flip(matrix, item->hflip, item->vflip);
10167
10168 6 return 0;
10169 }
10170
10171 2 static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid,
10172 AVStreamGroupTileGrid *tile_grid)
10173 {
10174 2 MOVContext *c = s->priv_data;
10175 2 const HEIFItem *item = grid->item;
10176 2 int64_t offset = 0, pos = avio_tell(s->pb);
10177 2 int x = 0, y = 0, i = 0;
10178 int tile_rows, tile_cols;
10179 int flags, size;
10180
10181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10182 av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
10183 return AVERROR_PATCHWELCOME;
10184 }
10185
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (item->is_idat_relative) {
10186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!c->idat_offset) {
10187 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
10188 return AVERROR_INVALIDDATA;
10189 }
10190 2 offset = c->idat_offset;
10191 }
10192
10193 2 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10194
10195 2 avio_r8(s->pb); /* version */
10196 2 flags = avio_r8(s->pb);
10197
10198 2 tile_rows = avio_r8(s->pb) + 1;
10199 2 tile_cols = avio_r8(s->pb) + 1;
10200 /* actual width and height of output image */
10201
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);
10202
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);
10203
10204 2 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
10205 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
10206
10207 2 avio_seek(s->pb, pos, SEEK_SET);
10208
10209 2 size = tile_rows * tile_cols;
10210 2 tile_grid->nb_tiles = grid->nb_tiles;
10211
10212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tile_grid->nb_tiles != size)
10213 return AVERROR_INVALIDDATA;
10214
10215
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < tile_cols; i++)
10216 4 tile_grid->coded_width += grid->tile_item_list[i]->width;
10217
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < size; i += tile_cols)
10218 4 tile_grid->coded_height += grid->tile_item_list[i]->height;
10219
10220 2 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!tile_grid->offsets)
10222 return AVERROR(ENOMEM);
10223
10224
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 while (y < tile_grid->coded_height) {
10225 4 int left_col = i;
10226
10227
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 while (x < tile_grid->coded_width) {
10228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (i == tile_grid->nb_tiles)
10229 return AVERROR_INVALIDDATA;
10230
10231 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10232 8 tile_grid->offsets[i].horizontal = x;
10233 8 tile_grid->offsets[i].vertical = y;
10234
10235 8 x += grid->tile_item_list[i++]->width;
10236 }
10237
10238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (x > tile_grid->coded_width) {
10239 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10240 return AVERROR_INVALIDDATA;
10241 }
10242
10243 4 x = 0;
10244 4 y += grid->tile_item_list[left_col]->height;
10245 }
10246
10247
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) {
10248 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10249 return AVERROR_INVALIDDATA;
10250 }
10251
10252 2 return 0;
10253 }
10254
10255 4 static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid,
10256 AVStreamGroupTileGrid *tile_grid)
10257 {
10258 4 MOVContext *c = s->priv_data;
10259 4 const HEIFItem *item = grid->item;
10260 uint16_t canvas_fill_value[4];
10261 4 int64_t offset = 0, pos = avio_tell(s->pb);
10262 4 int ret = 0, flags;
10263
10264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10265 av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
10266 return AVERROR_PATCHWELCOME;
10267 }
10268
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
10269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
10270 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
10271 return AVERROR_INVALIDDATA;
10272 }
10273 4 offset = c->idat_offset;
10274 }
10275
10276 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10277
10278 4 avio_r8(s->pb); /* version */
10279 4 flags = avio_r8(s->pb);
10280
10281
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10282 16 canvas_fill_value[i] = avio_rb16(s->pb);
10283 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
10284 4 canvas_fill_value[0], canvas_fill_value[1],
10285 4 canvas_fill_value[2], canvas_fill_value[3]);
10286
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10287 16 tile_grid->background[i] = canvas_fill_value[i];
10288
10289 /* actual width and height of output image */
10290 4 tile_grid->width =
10291
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);
10292 4 tile_grid->height =
10293
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);
10294
10295 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
10296 tile_grid->width, tile_grid->height);
10297
10298 4 tile_grid->nb_tiles = grid->nb_tiles;
10299 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
10301 ret = AVERROR(ENOMEM);
10302 goto fail;
10303 }
10304
10305
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
10306 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10307
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);
10308
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);
10309 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
10310 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
10311 8 i, tile_grid->offsets[i].idx,
10312 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
10313 }
10314
10315 4 fail:
10316 4 avio_seek(s->pb, pos, SEEK_SET);
10317
10318 4 return ret;
10319 }
10320
10321 2 static int mov_parse_exif_item(AVFormatContext *s,
10322 AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10323 const HEIFItem *ref)
10324 {
10325 2 MOVContext *c = s->priv_data;
10326 AVPacketSideData *sd;
10327 2 AVExifMetadata ifd = { 0 };
10328 AVBufferRef *buf;
10329 2 int64_t offset = 0, pos = avio_tell(s->pb);
10330 2 unsigned orientation_id = av_exif_get_tag_id("Orientation");
10331 int err;
10332
10333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10334 av_log(c->fc, AV_LOG_WARNING, "Exif metadata with non seekable input\n");
10335 return AVERROR_PATCHWELCOME;
10336 }
10337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ref->is_idat_relative) {
10338 if (!c->idat_offset) {
10339 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the Exif metadata\n");
10340 return AVERROR_INVALIDDATA;
10341 }
10342 offset = c->idat_offset;
10343 }
10344
10345 2 buf = av_buffer_alloc(ref->extent_length);
10346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!buf)
10347 return AVERROR(ENOMEM);
10348
10349 2 avio_seek(s->pb, ref->extent_offset + offset, SEEK_SET);
10350 2 err = avio_read(s->pb, buf->data, ref->extent_length);
10351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != ref->extent_length) {
10352 if (err > 0)
10353 err = AVERROR_INVALIDDATA;
10354 goto fail;
10355 }
10356
10357 // HEIF spec states that Exif metadata is informative. The irot item property is
10358 // the normative source of rotation information. So we remove any Orientation tag
10359 // present in the Exif buffer.
10360 2 err = av_exif_parse_buffer(s, buf->data, ref->extent_length, &ifd, AV_EXIF_T_OFF);
10361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0) {
10362 av_log(s, AV_LOG_ERROR, "Unable to parse Exif metadata\n");
10363 goto fail;
10364 }
10365
10366 2 err = av_exif_remove_entry(s, &ifd, orientation_id, 0);
10367
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
10368 goto fail;
10369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (!err)
10370 goto finish;
10371
10372 2 av_buffer_unref(&buf);
10373 2 err = av_exif_write(s, &ifd, &buf, AV_EXIF_T_OFF);
10374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
10375 goto fail;
10376
10377 2 finish:
10378 2 offset = AV_RB32(buf->data) + 4;
10379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset >= buf->size) {
10380 err = AVERROR_INVALIDDATA;
10381 goto fail;
10382 }
10383 2 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
10384 2 AV_PKT_DATA_EXIF, buf->size - offset, 0);
10385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!sd) {
10386 err = AVERROR(ENOMEM);
10387 goto fail;
10388 }
10389 2 memcpy(sd->data, buf->data + offset, buf->size - offset);
10390
10391 2 err = 0;
10392 2 fail:
10393 2 av_buffer_unref(&buf);
10394 2 av_exif_free(&ifd);
10395 2 avio_seek(s->pb, pos, SEEK_SET);
10396
10397 2 return err;
10398 }
10399
10400 6 static int mov_parse_tiles(AVFormatContext *s)
10401 {
10402 6 MOVContext *mov = s->priv_data;
10403
10404
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (int i = 0; i < mov->nb_heif_grid; i++) {
10405 6 AVStreamGroup *stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
10406 AVStreamGroupTileGrid *tile_grid;
10407 6 const HEIFGrid *grid = &mov->heif_grid[i];
10408 6 int err, loop = 1;
10409
10410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!stg)
10411 return AVERROR(ENOMEM);
10412
10413 6 stg->id = grid->item->item_id;
10414 6 tile_grid = stg->params.tile_grid;
10415
10416
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (int j = 0; j < grid->nb_tiles; j++) {
10417 16 int tile_id = grid->tile_id_list[j];
10418 int k;
10419
10420
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 for (k = 0; k < mov->nb_heif_item; k++) {
10421 30 HEIFItem *item = mov->heif_item[k];
10422 AVStream *st;
10423
10424
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)
10425 14 continue;
10426 16 st = item->st;
10427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!st) {
10428 av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
10429 "reference a stream\n",
10430 tile_id, grid->item->item_id);
10431 ff_remove_stream_group(s, stg);
10432 loop = 0;
10433 break;
10434 }
10435
10436 16 grid->tile_item_list[j] = item;
10437 16 grid->tile_idx_list[j] = stg->nb_streams;
10438
10439 16 err = avformat_stream_group_add_stream(stg, st);
10440
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (err < 0) {
10441 int l;
10442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
10443 return err;
10444
10445
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_streams; l++)
10446
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->streams[l]->index == st->index)
10447 2 break;
10448
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_streams);
10449 2 grid->tile_idx_list[j] = l;
10450 }
10451
10452
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
16 if (item->item_id != mov->primary_item_id)
10453 10 st->disposition |= AV_DISPOSITION_DEPENDENT;
10454 16 break;
10455 }
10456
10457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (k == mov->nb_heif_item) {
10458 av_assert0(loop);
10459 av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
10460 "exist\n",
10461 tile_id, grid->item->item_id);
10462 ff_remove_stream_group(s, stg);
10463 loop = 0;
10464 }
10465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!loop)
10466 break;
10467 }
10468
10469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!loop)
10470 continue;
10471
10472
2/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
6 switch (grid->item->type) {
10473 2 case MKTAG('g','r','i','d'):
10474 2 err = read_image_grid(s, grid, tile_grid);
10475 2 break;
10476 4 case MKTAG('i','o','v','l'):
10477 4 err = read_image_iovl(s, grid, tile_grid);
10478 4 break;
10479 default:
10480 av_assert0(0);
10481 }
10482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10483 return err;
10484
10485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 for (int j = 0; j < grid->item->nb_iref_list; j++) {
10486 HEIFItem *ref = get_heif_item(mov, grid->item->iref_list[j].item_id);
10487
10488 av_assert0(ref);
10489 switch(ref->type) {
10490 case MKTAG('E','x','i','f'):
10491 err = mov_parse_exif_item(s, &tile_grid->coded_side_data,
10492 &tile_grid->nb_coded_side_data, ref);
10493 if (err < 0 && (s->error_recognition & AV_EF_EXPLODE))
10494 return err;
10495 break;
10496 default:
10497 break;
10498 }
10499 }
10500
10501 /* rotation */
10502
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) {
10503 err = set_display_matrix_from_item(&tile_grid->coded_side_data,
10504 &tile_grid->nb_coded_side_data, grid->item);
10505 if (err < 0)
10506 return err;
10507 }
10508
10509 /* ICC profile */
10510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (grid->item->icc_profile_size) {
10511 err = set_icc_profile_from_item(&tile_grid->coded_side_data,
10512 &tile_grid->nb_coded_side_data, grid->item);
10513 if (err < 0)
10514 return err;
10515 }
10516
10517
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (grid->item->name)
10518 6 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
10519
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (grid->item->item_id == mov->primary_item_id)
10520 2 stg->disposition |= AV_DISPOSITION_DEFAULT;
10521 }
10522
10523 6 return 0;
10524 }
10525
10526 15 static int mov_parse_heif_items(AVFormatContext *s)
10527 {
10528 15 MOVContext *mov = s->priv_data;
10529 int err;
10530
10531
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 15 times.
57 for (int i = 0; i < mov->nb_heif_item; i++) {
10532 42 HEIFItem *item = mov->heif_item[i];
10533 MOVStreamContext *sc;
10534 AVStream *st;
10535 42 int64_t offset = 0;
10536
10537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!item)
10538 continue;
10539
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 31 times.
42 if (!item->st) {
10540 11 continue;
10541 }
10542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (item->is_idat_relative) {
10543 if (!mov->idat_offset) {
10544 av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
10545 return AVERROR_INVALIDDATA;
10546 }
10547 offset = mov->idat_offset;
10548 }
10549
10550 31 st = item->st;
10551 31 sc = st->priv_data;
10552 31 st->codecpar->width = item->width;
10553 31 st->codecpar->height = item->height;
10554
10555 31 sc->sample_size = sc->stsz_sample_size = item->extent_length;
10556 31 sc->sample_count = 1;
10557
10558 31 err = sanity_checks(s, sc, st->index);
10559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (err)
10560 return AVERROR_INVALIDDATA;
10561
10562 31 sc->chunk_offsets[0] = item->extent_offset + offset;
10563
10564
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 18 times.
31 if (item->item_id == mov->primary_item_id)
10565 13 st->disposition |= AV_DISPOSITION_DEFAULT;
10566
10567
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 31 times.
42 for (int j = 0; j < item->nb_iref_list; j++) {
10568 11 HEIFItem *ref = get_heif_item(mov, item->iref_list[j].item_id);
10569
10570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 av_assert0(ref);
10571
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 switch(ref->type) {
10572 2 case MKTAG('E','x','i','f'):
10573 2 err = mov_parse_exif_item(s, &st->codecpar->coded_side_data,
10574 2 &st->codecpar->nb_coded_side_data, ref);
10575
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))
10576 return err;
10577 2 break;
10578 9 default:
10579 9 break;
10580 }
10581 }
10582
10583
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) {
10584 6 err = set_display_matrix_from_item(&st->codecpar->coded_side_data,
10585 6 &st->codecpar->nb_coded_side_data, item);
10586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10587 return err;
10588 }
10589
10590 31 mov_build_index(mov, st);
10591 }
10592
10593
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
15 if (mov->nb_heif_grid) {
10594 6 err = mov_parse_tiles(s);
10595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10596 return err;
10597 }
10598
10599 15 return 0;
10600 }
10601
10602 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
10603 int first_index)
10604 {
10605 MOVStreamContext *sc = st->priv_data;
10606
10607 if (sc->tref_id < 0)
10608 return NULL;
10609
10610 for (int i = first_index; i < s->nb_streams; i++)
10611 if (s->streams[i]->id == sc->tref_id)
10612 return s->streams[i];
10613
10614 return NULL;
10615 }
10616
10617 509 static int mov_parse_lcevc_streams(AVFormatContext *s)
10618 {
10619 int err;
10620
10621
2/2
✓ Branch 0 taken 697 times.
✓ Branch 1 taken 509 times.
1206 for (int i = 0; i < s->nb_streams; i++) {
10622 AVStreamGroup *stg;
10623 697 AVStream *st = s->streams[i];
10624 AVStream *st_base;
10625 697 MOVStreamContext *sc = st->priv_data;
10626 697 int j = 0;
10627
10628 /* Find an enhancement stream. */
10629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 697 times.
697 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC ||
10630 !(sc->tref_flags & MOV_TREF_FLAG_ENHANCEMENT))
10631 697 continue;
10632
10633 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10634
10635 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
10636 if (!stg)
10637 return AVERROR(ENOMEM);
10638
10639 stg->id = st->id;
10640 stg->params.lcevc->width = st->codecpar->width;
10641 stg->params.lcevc->height = st->codecpar->height;
10642 st->codecpar->width = 0;
10643 st->codecpar->height = 0;
10644
10645 while (st_base = mov_find_reference_track(s, st, j)) {
10646 err = avformat_stream_group_add_stream(stg, st_base);
10647 if (err < 0)
10648 return err;
10649
10650 j = st_base->index + 1;
10651 }
10652 if (!j) {
10653 av_log(s, AV_LOG_ERROR, "Failed to find base stream for enhancement stream\n");
10654 return AVERROR_INVALIDDATA;
10655 }
10656
10657 err = avformat_stream_group_add_stream(stg, st);
10658 if (err < 0)
10659 return err;
10660
10661 stg->params.lcevc->lcevc_index = stg->nb_streams - 1;
10662 }
10663
10664 509 return 0;
10665 }
10666
10667 509 static void fix_stream_ids(AVFormatContext *s)
10668 {
10669 509 int highest_id = 0;
10670
10671
2/2
✓ Branch 0 taken 697 times.
✓ Branch 1 taken 509 times.
1206 for (int i = 0; i < s->nb_streams; i++) {
10672 697 const AVStream *st = s->streams[i];
10673 697 const MOVStreamContext *sc = st->priv_data;
10674
2/2
✓ Branch 0 taken 647 times.
✓ Branch 1 taken 50 times.
697 if (!sc->iamf)
10675 647 highest_id = FFMAX(highest_id, st->id);
10676 }
10677 509 highest_id += !highest_id;
10678
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++) {
10679 10 AVStreamGroup *stg = s->stream_groups[i];
10680
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
10681 8 continue;
10682
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_streams; j++) {
10683 14 AVStream *st = stg->streams[j];
10684 14 MOVStreamContext *sc = st->priv_data;
10685 14 st->id += highest_id;
10686 14 sc->iamf_stream_offset = highest_id;
10687 }
10688 }
10689 509 }
10690
10691 509 static int mov_read_header(AVFormatContext *s)
10692 {
10693 509 MOVContext *mov = s->priv_data;
10694 509 AVIOContext *pb = s->pb;
10695 int j, err;
10696 509 MOVAtom atom = { AV_RL32("root") };
10697 int i;
10698
10699
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) {
10700 av_log(s, AV_LOG_ERROR, "Invalid decryption key len %d expected %d\n",
10701 mov->decryption_key_len, AES_CTR_KEY_SIZE);
10702 return AVERROR(EINVAL);
10703 }
10704
10705 509 mov->fc = s;
10706 509 mov->trak_index = -1;
10707 509 mov->primary_item_id = -1;
10708 509 mov->cur_item_id = -1;
10709 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
10710
2/2
✓ Branch 0 taken 508 times.
✓ Branch 1 taken 1 times.
509 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
10711 508 atom.size = avio_size(pb);
10712 else
10713 1 atom.size = INT64_MAX;
10714
10715 /* check MOV header */
10716 do {
10717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 509 times.
509 if (mov->moov_retry)
10718 avio_seek(pb, 0, SEEK_SET);
10719
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 509 times.
509 if ((err = mov_read_default(mov, pb, atom)) < 0) {
10720 av_log(s, AV_LOG_ERROR, "error reading header\n");
10721 return err;
10722 }
10723 1017 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10724
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++);
10725
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) {
10726 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
10727 return AVERROR_INVALIDDATA;
10728 }
10729 509 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
10730
10731
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) {
10732 15 err = mov_parse_heif_items(s);
10733
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (err < 0)
10734 return err;
10735 }
10736 // prevent iloc and iinf boxes from being parsed while reading packets.
10737 // this is needed because an iinf box may have been parsed but ignored
10738 // for having old infe boxes which create no streams.
10739 509 mov->found_iloc = mov->found_iinf = 1;
10740
10741
2/2
✓ Branch 0 taken 508 times.
✓ Branch 1 taken 1 times.
509 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
10742
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)
10743 2 mov_read_chapters(s);
10744
2/2
✓ Branch 0 taken 696 times.
✓ Branch 1 taken 508 times.
1204 for (i = 0; i < s->nb_streams; i++)
10745
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 677 times.
696 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
10746 19 mov_read_timecode_track(s, s->streams[i]);
10747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 677 times.
677 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
10748 mov_read_rtmd_track(s, s->streams[i]);
10749 }
10750 }
10751
10752 /* copy timecode metadata from tmcd tracks to the related video streams */
10753
2/2
✓ Branch 0 taken 697 times.
✓ Branch 1 taken 509 times.
1206 for (i = 0; i < s->nb_streams; i++) {
10754 697 AVStream *st = s->streams[i];
10755 697 MOVStreamContext *sc = st->priv_data;
10756
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 679 times.
697 if (sc->timecode_track > 0) {
10757 AVDictionaryEntry *tcr;
10758 18 int tmcd_st_id = -1;
10759
10760
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 18 times.
66 for (j = 0; j < s->nb_streams; j++) {
10761 48 MOVStreamContext *sc2 = s->streams[j]->priv_data;
10762
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 30 times.
48 if (sc2->id == sc->timecode_track)
10763 18 tmcd_st_id = j;
10764 }
10765
10766
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)
10767 continue;
10768 18 tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
10769
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 if (tcr)
10770 16 av_dict_set(&st->metadata, "timecode", tcr->value, 0);
10771 }
10772 }
10773 509 export_orphan_timecode(s);
10774
10775 /* Create LCEVC stream groups. */
10776 509 err = mov_parse_lcevc_streams(s);
10777
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 509 times.
509 if (err < 0)
10778 return err;
10779
10780
2/2
✓ Branch 0 taken 697 times.
✓ Branch 1 taken 509 times.
1206 for (i = 0; i < s->nb_streams; i++) {
10781 697 AVStream *st = s->streams[i];
10782 697 FFStream *const sti = ffstream(st);
10783 697 MOVStreamContext *sc = st->priv_data;
10784 697 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
10785 697 fix_timescale(mov, sc);
10786
10787 /* Set the primary extradata based on the first Sample if it doesn't reference the first stsd entry. */
10788
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 &&
10789
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) {
10790 3 sc->last_stsd_index = sc->stsc_data[0].id - 1;
10791 3 av_freep(&st->codecpar->extradata);
10792 3 st->codecpar->extradata_size = sc->extradata_size[sc->last_stsd_index];
10793
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (sc->extradata_size[sc->last_stsd_index]) {
10794 3 st->codecpar->extradata = av_mallocz(sc->extradata_size[sc->last_stsd_index] + AV_INPUT_BUFFER_PADDING_SIZE);
10795
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata)
10796 return AVERROR(ENOMEM);
10797 3 memcpy(st->codecpar->extradata, sc->extradata[sc->last_stsd_index], sc->extradata_size[sc->last_stsd_index]);
10798 }
10799 }
10800
10801
2/2
✓ Branch 0 taken 283 times.
✓ Branch 1 taken 414 times.
697 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
10802
2/2
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 165 times.
283 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
10803 118 sti->skip_samples = sc->start_pad;
10804 }
10805
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)
10806 314 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
10807 314 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
10808
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 685 times.
697 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
10809
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) {
10810 8 st->codecpar->width = sc->width;
10811 8 st->codecpar->height = sc->height;
10812 }
10813
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
10814 st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
10815
10816 for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
10817 dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
10818
10819 err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
10820 if (err < 0)
10821 return err;
10822
10823 av_freep(&st->codecpar->extradata);
10824 st->codecpar->extradata_size = 0;
10825
10826 err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
10827 st->codecpar);
10828 if (err < 0)
10829 return err;
10830 }
10831 }
10832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 697 times.
697 if (mov->handbrake_version &&
10833 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
10834 st->codecpar->codec_id == AV_CODEC_ID_MP3) {
10835 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
10836 sti->need_parsing = AVSTREAM_PARSE_FULL;
10837 }
10838 }
10839
10840
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) {
10841
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 16 times.
40 for (i = 0; i < s->nb_streams; i++) {
10842 24 AVStream *st = s->streams[i];
10843 24 MOVStreamContext *sc = st->priv_data;
10844
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 3 times.
24 if (sc->duration_for_fps > 0) {
10845 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
10846 21 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
10847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (st->codecpar->bit_rate == INT64_MIN) {
10848 av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
10849 sc->data_size, sc->time_scale);
10850 st->codecpar->bit_rate = 0;
10851 if (s->error_recognition & AV_EF_EXPLODE)
10852 return AVERROR_INVALIDDATA;
10853 }
10854 }
10855 }
10856 }
10857
10858
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++) {
10859 if (mov->bitrates[i]) {
10860 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
10861 }
10862 }
10863
10864 509 ff_rfps_calculate(s);
10865
10866
2/2
✓ Branch 0 taken 697 times.
✓ Branch 1 taken 509 times.
1206 for (i = 0; i < s->nb_streams; i++) {
10867 697 AVStream *st = s->streams[i];
10868 697 MOVStreamContext *sc = st->priv_data;
10869
10870
3/3
✓ Branch 0 taken 283 times.
✓ Branch 1 taken 359 times.
✓ Branch 2 taken 55 times.
697 switch (st->codecpar->codec_type) {
10871 283 case AVMEDIA_TYPE_AUDIO:
10872 283 err = ff_replaygain_export(st, s->metadata);
10873
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 283 times.
283 if (err < 0)
10874 return err;
10875 283 break;
10876 359 case AVMEDIA_TYPE_VIDEO:
10877
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 351 times.
359 if (sc->display_matrix) {
10878
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,
10879 AV_PKT_DATA_DISPLAYMATRIX,
10880 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
10881 return AVERROR(ENOMEM);
10882
10883 8 sc->display_matrix = NULL;
10884 }
10885
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 355 times.
359 if (sc->stereo3d) {
10886
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,
10887 AV_PKT_DATA_STEREO3D,
10888 4 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
10889 return AVERROR(ENOMEM);
10890
10891 4 sc->stereo3d = NULL;
10892 }
10893
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 355 times.
359 if (sc->spherical) {
10894
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,
10895 AV_PKT_DATA_SPHERICAL,
10896 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
10897 return AVERROR(ENOMEM);
10898
10899 4 sc->spherical = NULL;
10900 }
10901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 359 times.
359 if (sc->mastering) {
10902 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10903 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
10904 (uint8_t *)sc->mastering, sc->mastering_size, 0))
10905 return AVERROR(ENOMEM);
10906
10907 sc->mastering = NULL;
10908 }
10909
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 359 times.
359 if (sc->coll) {
10910 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10911 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
10912 (uint8_t *)sc->coll, sc->coll_size, 0))
10913 return AVERROR(ENOMEM);
10914
10915 sc->coll = NULL;
10916 }
10917
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 355 times.
359 if (sc->ambient) {
10918
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,
10919 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
10920 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
10921 return AVERROR(ENOMEM);
10922
10923 4 sc->ambient = NULL;
10924 }
10925 359 break;
10926 }
10927 }
10928
10929 509 fix_stream_ids(s);
10930
10931 509 ff_configure_buffers_for_index(s, AV_TIME_BASE);
10932
10933
2/2
✓ Branch 0 taken 468 times.
✓ Branch 1 taken 509 times.
977 for (i = 0; i < mov->frag_index.nb_items; i++)
10934
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)
10935 464 mov->frag_index.item[i].headers_read = 1;
10936
10937 509 return 0;
10938 }
10939
10940 106457 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
10941 {
10942 106457 AVIndexEntry *sample = NULL;
10943 106457 int64_t best_dts = INT64_MAX;
10944 int i;
10945 106457 MOVContext *mov = s->priv_data;
10946
3/4
✓ Branch 0 taken 106457 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 106412 times.
106457 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
10947
2/2
✓ Branch 0 taken 138788 times.
✓ Branch 1 taken 106457 times.
245245 for (i = 0; i < s->nb_streams; i++) {
10948 138788 AVStream *avst = s->streams[i];
10949 138788 FFStream *const avsti = ffstream(avst);
10950 138788 MOVStreamContext *msc = avst->priv_data;
10951
4/4
✓ Branch 0 taken 130550 times.
✓ Branch 1 taken 8238 times.
✓ Branch 2 taken 127228 times.
✓ Branch 3 taken 3322 times.
138788 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
10952 127228 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
10953 127228 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
10954
2/2
✓ Branch 0 taken 112312 times.
✓ Branch 1 taken 14916 times.
127228 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
10955 127228 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
10956
3/6
✓ Branch 0 taken 21276 times.
✓ Branch 1 taken 105952 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 21276 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
127228 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
10957
1/2
✓ Branch 0 taken 21276 times.
✗ Branch 1 not taken.
21276 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10958
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 21276 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 21276 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 21276 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19067 times.
✓ Branch 9 taken 2209 times.
21276 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
10959
4/4
✓ Branch 0 taken 10940 times.
✓ Branch 1 taken 8127 times.
✓ Branch 2 taken 2209 times.
✓ Branch 3 taken 10940 times.
21276 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
10960
3/4
✓ Branch 0 taken 762 times.
✓ Branch 1 taken 1447 times.
✓ Branch 2 taken 762 times.
✗ Branch 3 not taken.
2209 (dtsdiff > AV_TIME_BASE && dts < best_dts && mov->interleaved_read)))))) {
10961 114841 sample = current_sample;
10962 114841 best_dts = dts;
10963 114841 *st = avst;
10964 }
10965 }
10966 }
10967 106457 return sample;
10968 }
10969
10970 9 static int should_retry(AVIOContext *pb, int error_code) {
10971
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))
10972 9 return 0;
10973
10974 return 1;
10975 }
10976
10977 43 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
10978 {
10979 int ret;
10980 43 MOVContext *mov = s->priv_data;
10981
10982
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)
10983 target = mov->frag_index.item[index].moof_offset;
10984
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) {
10985 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
10986 return AVERROR_INVALIDDATA;
10987 }
10988
10989 43 mov->next_root_atom = 0;
10990
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)
10991 43 index = search_frag_moof_offset(&mov->frag_index, target);
10992
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 &&
10993
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 mov->frag_index.item[index].moof_offset == target) {
10994
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (index + 1 < mov->frag_index.nb_items)
10995 35 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
10996
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (mov->frag_index.item[index].headers_read)
10997 35 return 0;
10998 3 mov->frag_index.item[index].headers_read = 1;
10999 }
11000
11001 8 mov->found_mdat = 0;
11002
11003 8 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
11004
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ret < 0)
11005 return ret;
11006
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 3 times.
8 if (avio_feof(s->pb))
11007 5 return AVERROR_EOF;
11008 3 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
11009
11010 3 return 1;
11011 }
11012
11013 15 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
11014 {
11015 15 MOVStreamContext *sc = st->priv_data;
11016 uint8_t *side, *extradata;
11017 int extradata_size;
11018
11019 /* Save the current index. */
11020 15 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
11021
11022 /* Notify the decoder that extradata changed. */
11023 15 extradata_size = sc->extradata_size[sc->last_stsd_index];
11024 15 extradata = sc->extradata[sc->last_stsd_index];
11025
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) {
11026 12 side = av_packet_new_side_data(pkt,
11027 AV_PKT_DATA_NEW_EXTRADATA,
11028 extradata_size);
11029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!side)
11030 return AVERROR(ENOMEM);
11031 12 memcpy(side, extradata, extradata_size);
11032 }
11033
11034 15 return 0;
11035 }
11036
11037 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
11038 {
11039 /* We can't make assumptions about the structure of the payload,
11040 because it may include multiple cdat and cdt2 samples. */
11041 const uint32_t cdat = AV_RB32("cdat");
11042 const uint32_t cdt2 = AV_RB32("cdt2");
11043 int ret, out_size = 0;
11044
11045 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
11046 if (src_size < 10)
11047 return AVERROR_INVALIDDATA;
11048
11049 /* avoid an int overflow: */
11050 if ((src_size - 8) / 2 >= INT_MAX / 3)
11051 return AVERROR_INVALIDDATA;
11052
11053 ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
11054 if (ret < 0)
11055 return ret;
11056
11057 /* parse and re-format the c608 payload in one pass. */
11058 while (src_size >= 10) {
11059 const uint32_t atom_size = avio_rb32(pb);
11060 const uint32_t atom_type = avio_rb32(pb);
11061 const uint32_t data_size = atom_size - 8;
11062 const uint8_t cc_field =
11063 atom_type == cdat ? 1 :
11064 atom_type == cdt2 ? 2 :
11065 0;
11066
11067 /* account for bytes consumed for atom size and type. */
11068 src_size -= 8;
11069
11070 /* make sure the data size stays within the buffer boundaries. */
11071 if (data_size < 2 || data_size > src_size) {
11072 ret = AVERROR_INVALIDDATA;
11073 break;
11074 }
11075
11076 /* make sure the data size is consistent with N byte pairs. */
11077 if (data_size % 2 != 0) {
11078 ret = AVERROR_INVALIDDATA;
11079 break;
11080 }
11081
11082 if (!cc_field) {
11083 /* neither cdat or cdt2 ... skip it */
11084 avio_skip(pb, data_size);
11085 src_size -= data_size;
11086 continue;
11087 }
11088
11089 for (uint32_t i = 0; i < data_size; i += 2) {
11090 pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
11091 pkt->data[out_size + 1] = avio_r8(pb);
11092 pkt->data[out_size + 2] = avio_r8(pb);
11093 out_size += 3;
11094 src_size -= 2;
11095 }
11096 }
11097
11098 if (src_size > 0)
11099 /* skip any remaining unread portion of the input payload */
11100 avio_skip(pb, src_size);
11101
11102 av_shrink_packet(pkt, out_size);
11103 return ret;
11104 }
11105
11106 105908 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
11107 int64_t current_index, AVPacket *pkt)
11108 {
11109 105908 MOVStreamContext *sc = st->priv_data;
11110
11111 105908 pkt->stream_index = sc->ffindex;
11112 105908 pkt->dts = sample->timestamp;
11113
2/2
✓ Branch 0 taken 237 times.
✓ Branch 1 taken 105671 times.
105908 if (sample->flags & AVINDEX_DISCARD_FRAME) {
11114 237 pkt->flags |= AV_PKT_FLAG_DISCARD;
11115 }
11116
4/4
✓ Branch 0 taken 86050 times.
✓ Branch 1 taken 19858 times.
✓ Branch 2 taken 86038 times.
✓ Branch 3 taken 12 times.
105908 if (sc->stts_count && sc->tts_index < sc->tts_count)
11117 86038 pkt->duration = sc->tts_data[sc->tts_index].duration;
11118
3/4
✓ Branch 0 taken 4191 times.
✓ Branch 1 taken 101717 times.
✓ Branch 2 taken 4191 times.
✗ Branch 3 not taken.
105908 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
11119 4191 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
11120 } else {
11121
2/2
✓ Branch 0 taken 15783 times.
✓ Branch 1 taken 85934 times.
101717 if (pkt->duration == 0) {
11122 15783 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
11123
2/2
✓ Branch 0 taken 15702 times.
✓ Branch 1 taken 81 times.
15783 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
11124
2/2
✓ Branch 0 taken 15749 times.
✓ Branch 1 taken 34 times.
15783 if (next_dts >= pkt->dts)
11125 15749 pkt->duration = next_dts - pkt->dts;
11126 }
11127 101717 pkt->pts = pkt->dts;
11128 }
11129
11130
4/4
✓ Branch 0 taken 86050 times.
✓ Branch 1 taken 19858 times.
✓ Branch 2 taken 86038 times.
✓ Branch 3 taken 12 times.
105908 if (sc->tts_data && sc->tts_index < sc->tts_count) {
11131 /* update tts context */
11132 86038 sc->tts_sample++;
11133
1/2
✓ Branch 0 taken 86038 times.
✗ Branch 1 not taken.
86038 if (sc->tts_index < sc->tts_count &&
11134
1/2
✓ Branch 0 taken 86038 times.
✗ Branch 1 not taken.
86038 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
11135 86038 sc->tts_index++;
11136 86038 sc->tts_sample = 0;
11137 }
11138 }
11139
11140
4/4
✓ Branch 0 taken 1043 times.
✓ Branch 1 taken 104865 times.
✓ Branch 2 taken 911 times.
✓ Branch 3 taken 132 times.
105908 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
11141 911 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
11142 911 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
11143
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;
11144 }
11145 105908 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
11146 105908 pkt->pos = sample->pos;
11147
11148 /* Multiple stsd handling. */
11149
2/2
✓ Branch 0 taken 102669 times.
✓ Branch 1 taken 3239 times.
105908 if (sc->stsc_data) {
11150
1/2
✓ Branch 0 taken 102669 times.
✗ Branch 1 not taken.
102669 if (sc->stsc_data[sc->stsc_index].id > 0 &&
11151
2/2
✓ Branch 0 taken 102638 times.
✓ Branch 1 taken 31 times.
102669 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
11152
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 102623 times.
102638 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
11153 15 int ret = mov_change_extradata(st, pkt);
11154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (ret < 0)
11155 return ret;
11156 }
11157
11158 /* Update the stsc index for the next sample */
11159 102669 sc->stsc_sample++;
11160
2/2
✓ Branch 1 taken 55149 times.
✓ Branch 2 taken 47520 times.
102669 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
11161
2/2
✓ Branch 1 taken 1191 times.
✓ Branch 2 taken 53958 times.
55149 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
11162 1191 sc->stsc_index++;
11163 1191 sc->stsc_sample = 0;
11164 }
11165 }
11166
11167 105908 return 0;
11168 }
11169
11170 97327 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
11171 {
11172 97327 MOVContext *mov = s->priv_data;
11173 MOVStreamContext *sc;
11174 AVIndexEntry *sample;
11175 97327 AVStream *st = NULL;
11176 97327 FFStream *avsti = NULL;
11177 int64_t current_index;
11178 int ret;
11179 int i;
11180 97327 mov->fc = s;
11181 9130 retry:
11182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106457 times.
106457 if (s->pb->pos == 0) {
11183
11184 // Discard current fragment index
11185 if (mov->frag_index.allocated_size > 0) {
11186 for(int i = 0; i < mov->frag_index.nb_items; i++) {
11187 av_freep(&mov->frag_index.item[i].stream_info);
11188 }
11189 av_freep(&mov->frag_index.item);
11190 mov->frag_index.nb_items = 0;
11191 mov->frag_index.allocated_size = 0;
11192 mov->frag_index.current = -1;
11193 mov->frag_index.complete = 0;
11194 }
11195
11196 for (i = 0; i < s->nb_streams; i++) {
11197 AVStream *avst = s->streams[i];
11198 MOVStreamContext *msc = avst->priv_data;
11199
11200 // Clear current sample
11201 mov_current_sample_set(msc, 0);
11202 msc->tts_index = 0;
11203
11204 // Discard current index entries
11205 avsti = ffstream(avst);
11206 if (avsti->index_entries_allocated_size > 0) {
11207 av_freep(&avsti->index_entries);
11208 avsti->index_entries_allocated_size = 0;
11209 avsti->nb_index_entries = 0;
11210 }
11211 }
11212
11213 if ((ret = mov_switch_root(s, -1, -1)) < 0)
11214 return ret;
11215 }
11216 106457 sample = mov_find_next_sample(s, &st);
11217
6/6
✓ Branch 0 taken 105952 times.
✓ Branch 1 taken 505 times.
✓ Branch 2 taken 516 times.
✓ Branch 3 taken 105436 times.
✓ Branch 4 taken 35 times.
✓ Branch 5 taken 481 times.
106457 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
11218
2/2
✓ Branch 0 taken 497 times.
✓ Branch 1 taken 43 times.
540 if (!mov->next_root_atom)
11219 497 return AVERROR_EOF;
11220
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)
11221 5 return ret;
11222 38 goto retry;
11223 }
11224 105917 sc = st->priv_data;
11225 /* must be done just before reading, to avoid infinite loop on sample */
11226 105917 current_index = sc->current_index;
11227 105917 mov_current_sample_inc(sc);
11228
11229
2/2
✓ Branch 0 taken 481 times.
✓ Branch 1 taken 105436 times.
105917 if (mov->next_root_atom) {
11230 481 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
11231 481 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
11232 }
11233
11234
2/2
✓ Branch 0 taken 96825 times.
✓ Branch 1 taken 9092 times.
105917 if (st->discard != AVDISCARD_ALL) {
11235 96825 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
11236
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 96818 times.
96825 if (ret64 != sample->pos) {
11237 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
11238 sc->ffindex, sample->pos);
11239
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
11240 mov_current_sample_dec(sc);
11241
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
11242 7 return (int)ret64;
11243 }
11244 return AVERROR_INVALIDDATA;
11245 }
11246
11247
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96818 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96818 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
11248 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
11249 goto retry;
11250 }
11251
11252
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96818 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96818 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
11253 ret = get_eia608_packet(sc->pb, pkt, sample->size);
11254 #if CONFIG_IAMFDEC
11255
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 96763 times.
96818 else if (sc->iamf) {
11256 int64_t pts, dts, pos, duration;
11257 55 int flags, size = sample->size;
11258 55 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11259 55 pts = pkt->pts; dts = pkt->dts;
11260 55 pos = pkt->pos; flags = pkt->flags;
11261 55 duration = pkt->duration;
11262
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) {
11263 275 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
11264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
275 if (ret < 0) {
11265 if (should_retry(sc->pb, ret))
11266 mov_current_sample_dec(sc);
11267 return ret;
11268 }
11269 275 size -= ret;
11270 275 pkt->pts = pts; pkt->dts = dts;
11271 275 pkt->pos = pos; pkt->flags |= flags;
11272 275 pkt->duration = duration;
11273 275 ret = ff_buffer_packet(s, pkt);
11274 }
11275
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 if (!ret)
11276 55 return FFERROR_REDO;
11277 }
11278 #endif
11279
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 96760 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
96766 else if (st->codecpar->codec_id == AV_CODEC_ID_APV && sample->size > 4) {
11280 3 const uint32_t au_size = avio_rb32(sc->pb);
11281 3 ret = av_get_packet(sc->pb, pkt, au_size);
11282 } else
11283 96760 ret = av_get_packet(sc->pb, pkt, sample->size);
11284
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 96761 times.
96763 if (ret < 0) {
11285
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (should_retry(sc->pb, ret)) {
11286 mov_current_sample_dec(sc);
11287 }
11288 2 return ret;
11289 }
11290 #if CONFIG_DV_DEMUXER
11291
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96761 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96761 if (mov->dv_demux && sc->dv_audio_container) {
11292 ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
11293 av_packet_unref(pkt);
11294 if (ret < 0)
11295 return ret;
11296 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
11297 if (ret < 0)
11298 return ret;
11299 }
11300 #endif
11301
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 96743 times.
96761 if (sc->has_palette) {
11302 uint8_t *pal;
11303
11304 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
11305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
11306 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
11307 } else {
11308 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
11309 18 sc->has_palette = 0;
11310 }
11311 }
11312
4/6
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 96473 times.
✓ Branch 3 taken 288 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 288 times.
✗ Branch 6 not taken.
96761 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
11313
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 288 times.
288 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
11314 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
11315 }
11316 }
11317
11318 105853 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 105853 times.
105853 if (ret < 0)
11320 return ret;
11321
11322
2/2
✓ Branch 0 taken 9092 times.
✓ Branch 1 taken 96761 times.
105853 if (st->discard == AVDISCARD_ALL)
11323 9092 goto retry;
11324
11325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96761 times.
96761 if (mov->aax_mode)
11326 aax_filter(pkt->data, pkt->size, mov);
11327
11328 96761 ret = cenc_filter(mov, st, sc, pkt, current_index);
11329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96761 times.
96761 if (ret < 0) {
11330 return ret;
11331 }
11332
11333 96761 return 0;
11334 }
11335
11336 361 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
11337 {
11338 361 MOVContext *mov = s->priv_data;
11339 int index;
11340
11341
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 26 times.
361 if (!mov->frag_index.complete)
11342 335 return 0;
11343
11344 26 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
11345
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 22 times.
26 if (index < 0)
11346 4 index = 0;
11347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (!mov->frag_index.item[index].headers_read)
11348 return mov_switch_root(s, -1, index);
11349
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (index + 1 < mov->frag_index.nb_items)
11350 26 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11351
11352 26 return 0;
11353 }
11354
11355 static int is_open_key_sample(const MOVStreamContext *sc, int sample)
11356 {
11357 // TODO: a bisect search would scale much better
11358 for (int i = 0; i < sc->open_key_samples_count; i++) {
11359 const int oks = sc->open_key_samples[i];
11360 if (oks == sample)
11361 return 1;
11362 if (oks > sample) /* list is monotically increasing so we can stop early */
11363 break;
11364 }
11365 return 0;
11366 }
11367
11368 /*
11369 * Some key sample may be key frames but not IDR frames, so a random access to
11370 * them may not be allowed.
11371 */
11372 229 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
11373 {
11374 229 MOVStreamContext *sc = st->priv_data;
11375 229 FFStream *const sti = ffstream(st);
11376 int64_t key_sample_dts, key_sample_pts;
11377
11378
1/2
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
229 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
11379 229 return 1;
11380
11381 if (sample >= sc->sample_offsets_count)
11382 return 1;
11383
11384 key_sample_dts = sti->index_entries[sample].timestamp;
11385 key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
11386
11387 /*
11388 * If the sample needs to be presented before an open key sample, they may
11389 * not be decodable properly, even though they come after in decoding
11390 * order.
11391 */
11392 if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
11393 return 0;
11394
11395 return 1;
11396 }
11397
11398 361 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
11399 {
11400 361 MOVStreamContext *sc = st->priv_data;
11401 361 FFStream *const sti = ffstream(st);
11402 int sample, time_sample, ret, requested_sample;
11403 int64_t next_ts;
11404 unsigned int i;
11405
11406 // Here we consider timestamp to be PTS, hence try to offset it so that we
11407 // can search over the DTS timeline.
11408 361 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
11409
11410 361 ret = mov_seek_fragment(s, st, timestamp);
11411
1/2
✓ Branch 0 taken 361 times.
✗ Branch 1 not taken.
361 if (ret < 0)
11412 return ret;
11413
11414 for (;;) {
11415 361 sample = av_index_search_timestamp(st, timestamp, flags);
11416 361 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
11417
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)
11418 43 sample = 0;
11419
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 335 times.
361 if (sample < 0) /* not sure what to do */
11420 26 return AVERROR_INVALIDDATA;
11421
11422
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))
11423 break;
11424
11425 next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
11426 requested_sample = av_index_search_timestamp(st, next_ts, flags);
11427
11428 // If we've reached a different sample trying to find a good pts to
11429 // seek to, give up searching because we'll end up seeking back to
11430 // sample 0 on every seek.
11431 if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
11432 break;
11433
11434 timestamp = next_ts;
11435 }
11436
11437 335 mov_current_sample_set(sc, sample);
11438 335 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
11439 /* adjust time to sample index */
11440
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 125 times.
335 if (sc->tts_data) {
11441 210 time_sample = 0;
11442
1/2
✓ Branch 0 taken 60235 times.
✗ Branch 1 not taken.
60235 for (i = 0; i < sc->tts_count; i++) {
11443 60235 int next = time_sample + sc->tts_data[i].count;
11444
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 60025 times.
60235 if (next > sc->current_sample) {
11445 210 sc->tts_index = i;
11446 210 sc->tts_sample = sc->current_sample - time_sample;
11447 210 break;
11448 }
11449 60025 time_sample = next;
11450 }
11451 }
11452
11453 /* adjust stsd index */
11454
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 26 times.
335 if (sc->chunk_count) {
11455 309 time_sample = 0;
11456
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
381 for (i = 0; i < sc->stsc_count; i++) {
11457 381 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
11458
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 72 times.
381 if (next > sc->current_sample) {
11459 309 sc->stsc_index = i;
11460 309 sc->stsc_sample = sc->current_sample - time_sample;
11461 309 break;
11462 }
11463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
11464 72 time_sample = next;
11465 }
11466 }
11467
11468 335 return sample;
11469 }
11470
11471 335 static int64_t mov_get_skip_samples(AVStream *st, int sample)
11472 {
11473 335 MOVStreamContext *sc = st->priv_data;
11474 335 FFStream *const sti = ffstream(st);
11475 335 int64_t first_ts = sti->index_entries[0].timestamp;
11476 335 int64_t ts = sti->index_entries[sample].timestamp;
11477 int64_t off;
11478
11479
2/2
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 151 times.
335 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
11480 184 return 0;
11481
11482 /* compute skip samples according to stream start_pad, seek ts and first ts */
11483 151 off = av_rescale_q(ts - first_ts, st->time_base,
11484 151 (AVRational){1, st->codecpar->sample_rate});
11485 151 return FFMAX(sc->start_pad - off, 0);
11486 }
11487
11488 340 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
11489 {
11490 340 MOVContext *mc = s->priv_data;
11491 AVStream *st;
11492 FFStream *sti;
11493 int sample;
11494 int i;
11495
11496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 340 times.
340 if (stream_index >= s->nb_streams)
11497 return AVERROR_INVALIDDATA;
11498
11499 340 st = s->streams[stream_index];
11500 340 sti = ffstream(st);
11501 340 sample = mov_seek_stream(s, st, sample_time, flags);
11502
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 314 times.
340 if (sample < 0)
11503 26 return sample;
11504
11505
1/2
✓ Branch 0 taken 314 times.
✗ Branch 1 not taken.
314 if (mc->seek_individually) {
11506 /* adjust seek timestamp to found sample timestamp */
11507 314 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
11508 314 sti->skip_samples = mov_get_skip_samples(st, sample);
11509
11510
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 314 times.
649 for (i = 0; i < s->nb_streams; i++) {
11511 335 AVStream *const st = s->streams[i];
11512 335 FFStream *const sti = ffstream(st);
11513 int64_t timestamp;
11514
11515
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 21 times.
335 if (stream_index == i)
11516 314 continue;
11517
11518 21 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
11519 21 sample = mov_seek_stream(s, st, timestamp, flags);
11520
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (sample >= 0)
11521 21 sti->skip_samples = mov_get_skip_samples(st, sample);
11522 }
11523 } else {
11524 for (i = 0; i < s->nb_streams; i++) {
11525 MOVStreamContext *sc;
11526 st = s->streams[i];
11527 sc = st->priv_data;
11528 mov_current_sample_set(sc, 0);
11529 }
11530 while (1) {
11531 MOVStreamContext *sc;
11532 AVIndexEntry *entry = mov_find_next_sample(s, &st);
11533 if (!entry)
11534 return AVERROR_INVALIDDATA;
11535 sc = st->priv_data;
11536 if (sc->ffindex == stream_index && sc->current_sample == sample)
11537 break;
11538 mov_current_sample_inc(sc);
11539 }
11540 }
11541 314 return 0;
11542 }
11543
11544 #define OFFSET(x) offsetof(MOVContext, x)
11545 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
11546 static const AVOption mov_options[] = {
11547 {"use_absolute_path",
11548 "allow using absolute path when opening alias, this is a possible security issue",
11549 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
11550 0, 1, FLAGS},
11551 {"seek_streams_individually",
11552 "Seek each stream individually to the closest point",
11553 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
11554 0, 1, FLAGS},
11555 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
11556 0, 1, FLAGS},
11557 {"advanced_editlist",
11558 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
11559 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
11560 0, 1, FLAGS},
11561 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
11562 0, 1, FLAGS},
11563 {"use_mfra_for",
11564 "use mfra for fragment timestamps",
11565 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
11566 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
11567 .unit = "use_mfra_for"},
11568 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
11569 FLAGS, .unit = "use_mfra_for" },
11570 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
11571 FLAGS, .unit = "use_mfra_for" },
11572 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
11573 FLAGS, .unit = "use_mfra_for" },
11574 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
11575 0, 1, FLAGS},
11576 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
11577 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11578 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
11579 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11580 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
11581 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11582 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
11583 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11584 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
11585 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11586 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
11587 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
11588 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
11589 .flags = AV_OPT_FLAG_DECODING_PARAM },
11590 { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11591 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
11592 {.i64 = 0}, 0, 1, FLAGS },
11593 { "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 },
11594 { "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 },
11595
11596 { NULL },
11597 };
11598
11599 static const AVClass mov_class = {
11600 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
11601 .item_name = av_default_item_name,
11602 .option = mov_options,
11603 .version = LIBAVUTIL_VERSION_INT,
11604 };
11605
11606 const FFInputFormat ff_mov_demuxer = {
11607 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
11608 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
11609 .p.priv_class = &mov_class,
11610 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v,avif,heic,heif",
11611 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
11612 .priv_data_size = sizeof(MOVContext),
11613 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
11614 .read_probe = mov_probe,
11615 .read_header = mov_read_header,
11616 .read_packet = mov_read_packet,
11617 .read_close = mov_read_close,
11618 .read_seek = mov_read_seek,
11619 };
11620