FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2025-06-23 20:06:14
Exec Total Coverage
Lines: 4282 6786 63.1%
Functions: 173 212 81.6%
Branches: 2411 4560 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/flac.h"
55 #include "libavcodec/hevc/hevc.h"
56 #include "libavcodec/mpegaudiodecheader.h"
57 #include "libavcodec/mlp_parse.h"
58 #include "avformat.h"
59 #include "internal.h"
60 #include "avio_internal.h"
61 #include "demux.h"
62 #include "dvdclut.h"
63 #include "iamf_parse.h"
64 #include "iamf_reader.h"
65 #include "dovi_isom.h"
66 #include "riff.h"
67 #include "isom.h"
68 #include "libavcodec/get_bits.h"
69 #include "id3v1.h"
70 #include "mov_chan.h"
71 #include "replaygain.h"
72
73 #if CONFIG_ZLIB
74 #include <zlib.h>
75 #endif
76
77 #include "qtpalette.h"
78
79 /* those functions parse an atom */
80 /* links atom IDs to parse functions */
81 typedef struct MOVParseTableEntry {
82 uint32_t type;
83 int (*parse)(MOVContext *ctx, AVIOContext *pb, MOVAtom atom);
84 } MOVParseTableEntry;
85
86 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom);
87 static int mov_read_mfra(MOVContext *c, AVIOContext *f);
88 static void mov_free_stream_context(AVFormatContext *s, AVStream *st);
89
90 24 static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
91 unsigned len, const char *key)
92 {
93 char buf[16];
94
95 24 short current, total = 0;
96 24 avio_rb16(pb); // unknown
97 24 current = avio_rb16(pb);
98
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (len >= 6)
99 24 total = avio_rb16(pb);
100
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19 times.
24 if (!total)
101 5 snprintf(buf, sizeof(buf), "%d", current);
102 else
103 19 snprintf(buf, sizeof(buf), "%d/%d", current, total);
104 24 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
105 24 av_dict_set(&c->fc->metadata, key, buf, 0);
106
107 24 return 0;
108 }
109
110 static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
111 unsigned len, const char *key)
112 {
113 /* bypass padding bytes */
114 avio_r8(pb);
115 avio_r8(pb);
116 avio_r8(pb);
117
118 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
119 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
120
121 return 0;
122 }
123
124 26 static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
125 unsigned len, const char *key)
126 {
127 26 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
128 26 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
129
130 26 return 0;
131 }
132
133 10 static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
134 unsigned len, const char *key)
135 {
136 short genre;
137
138 10 avio_r8(pb); // unknown
139
140 10 genre = avio_r8(pb);
141
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (genre < 1 || genre > ID3v1_GENRE_MAX)
142 return 0;
143 10 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
144 10 av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
145
146 10 return 0;
147 }
148
149 static const uint32_t mac_to_unicode[128] = {
150 0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
151 0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
152 0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,
153 0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,
154 0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,
155 0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,
156 0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,
157 0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,
158 0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,
159 0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,
160 0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,
161 0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,
162 0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,
163 0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,
164 0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,
165 0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7,
166 };
167
168 329 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
169 char *dst, int dstlen)
170 {
171 329 char *p = dst;
172 329 char *end = dst+dstlen-1;
173 int i;
174
175
2/2
✓ Branch 0 taken 2945 times.
✓ Branch 1 taken 329 times.
3274 for (i = 0; i < len; i++) {
176 2945 uint8_t t, c = avio_r8(pb);
177
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2945 times.
2945 if (p >= end)
179 continue;
180
181
2/2
✓ Branch 0 taken 2937 times.
✓ Branch 1 taken 8 times.
2945 if (c < 0x80)
182 2937 *p++ = c;
183
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 else if (p < end)
184
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✓ Branch 9 taken 8 times.
16 PUT_UTF8(mac_to_unicode[c-0x80], t, if (p < end) *p++ = t;);
185 }
186 329 *p = 0;
187 329 return p - dst;
188 }
189
190 /**
191 * Get the current item in the parsing process.
192 */
193 94 static HEIFItem *heif_cur_item(MOVContext *c)
194 {
195 94 HEIFItem *item = NULL;
196
197
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 12 times.
156 for (int i = 0; i < c->nb_heif_item; i++) {
198
3/4
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 82 times.
144 if (!c->heif_item[i] || c->heif_item[i]->item_id != c->cur_item_id)
199 62 continue;
200
201 82 item = c->heif_item[i];
202 82 break;
203 }
204
205 94 return item;
206 }
207
208 /**
209 * Get the current stream in the parsing process. This can either be the
210 * latest stream added to the context, or the stream referenced by an item.
211 */
212 202 static AVStream *get_curr_st(MOVContext *c)
213 {
214 202 AVStream *st = NULL;
215 HEIFItem *item;
216
217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 202 times.
202 if (c->fc->nb_streams < 1)
218 return NULL;
219
220
2/2
✓ Branch 0 taken 169 times.
✓ Branch 1 taken 33 times.
202 if (c->cur_item_id == -1)
221 169 return c->fc->streams[c->fc->nb_streams-1];
222
223 33 item = heif_cur_item(c);
224
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if (item)
225 33 st = item->st;
226
227 33 return st;
228 }
229
230 14 static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
231 {
232 AVStream *st;
233 MOVStreamContext *sc;
234 enum AVCodecID id;
235 int ret;
236
237
2/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
14 switch (type) {
238 7 case 0xd: id = AV_CODEC_ID_MJPEG; break;
239 7 case 0xe: id = AV_CODEC_ID_PNG; break;
240 case 0x1b: id = AV_CODEC_ID_BMP; break;
241 default:
242 av_log(c->fc, AV_LOG_WARNING, "Unknown cover type: 0x%x.\n", type);
243 avio_skip(pb, len);
244 return 0;
245 }
246
247 14 sc = av_mallocz(sizeof(*sc));
248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!sc)
249 return AVERROR(ENOMEM);
250 14 ret = ff_add_attached_pic(c->fc, NULL, pb, NULL, len);
251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0) {
252 av_free(sc);
253 return ret;
254 }
255 14 st = c->fc->streams[c->fc->nb_streams - 1];
256 14 st->priv_data = sc;
257 14 sc->id = st->id;
258 14 sc->refcount = 1;
259
260
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 if (st->attached_pic.size >= 8 && id != AV_CODEC_ID_BMP) {
261
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
262 7 id = AV_CODEC_ID_PNG;
263 } else {
264 7 id = AV_CODEC_ID_MJPEG;
265 }
266 }
267 14 st->codecpar->codec_id = id;
268
269 14 return 0;
270 }
271
272 // 3GPP TS 26.244
273 static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
274 {
275 char language[4] = { 0 };
276 char buf[200], place[100];
277 uint16_t langcode = 0;
278 double longitude, latitude, altitude;
279 const char *key = "location";
280
281 if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) {
282 av_log(c->fc, AV_LOG_ERROR, "loci too short\n");
283 return AVERROR_INVALIDDATA;
284 }
285
286 avio_skip(pb, 4); // version+flags
287 langcode = avio_rb16(pb);
288 ff_mov_lang_to_iso639(langcode, language);
289 len -= 6;
290
291 len -= avio_get_str(pb, len, place, sizeof(place));
292 if (len < 1) {
293 av_log(c->fc, AV_LOG_ERROR, "place name too long\n");
294 return AVERROR_INVALIDDATA;
295 }
296 avio_skip(pb, 1); // role
297 len -= 1;
298
299 if (len < 12) {
300 av_log(c->fc, AV_LOG_ERROR,
301 "loci too short (%u bytes left, need at least %d)\n", len, 12);
302 return AVERROR_INVALIDDATA;
303 }
304 longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
305 latitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
306 altitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
307
308 // Try to output in the same format as the ?xyz field
309 snprintf(buf, sizeof(buf), "%+08.4f%+09.4f", latitude, longitude);
310 if (altitude)
311 av_strlcatf(buf, sizeof(buf), "%+f", altitude);
312 av_strlcatf(buf, sizeof(buf), "/%s", place);
313
314 if (*language && strcmp(language, "und")) {
315 char key2[16];
316 snprintf(key2, sizeof(key2), "%s-%s", key, language);
317 av_dict_set(&c->fc->metadata, key2, buf, 0);
318 }
319 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
320 return av_dict_set(&c->fc->metadata, key, buf, 0);
321 }
322
323 static int mov_metadata_hmmt(MOVContext *c, AVIOContext *pb, unsigned len)
324 {
325 int i, n_hmmt;
326
327 if (len < 2)
328 return 0;
329 if (c->ignore_chapters)
330 return 0;
331
332 n_hmmt = avio_rb32(pb);
333 if (n_hmmt > len / 4)
334 return AVERROR_INVALIDDATA;
335 for (i = 0; i < n_hmmt && !pb->eof_reached; i++) {
336 int moment_time = avio_rb32(pb);
337 avpriv_new_chapter(c->fc, i, av_make_q(1, 1000), moment_time, AV_NOPTS_VALUE, NULL);
338 }
339 if (avio_feof(pb))
340 return AVERROR_INVALIDDATA;
341 return 0;
342 }
343
344 473 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
345 {
346 473 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
347 473 char key2[32], language[4] = {0};
348 473 char *str = NULL;
349 473 const char *key = NULL;
350 473 uint16_t langcode = 0;
351 473 uint32_t data_type = 0, str_size_alloc;
352 uint64_t str_size;
353 473 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
354 473 int raw = 0;
355 473 int num = 0;
356 AVDictionary **metadata;
357
358
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 444 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
473 if (c->trak_index >= 0 && c->trak_index < c->fc->nb_streams)
359 29 metadata = &c->fc->streams[c->trak_index]->metadata;
360 else
361 444 metadata = &c->fc->metadata;
362
363
25/74
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 158 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 13 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 12 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 10 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 13 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✓ Branch 33 taken 12 times.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✓ Branch 39 taken 17 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 16 times.
✓ Branch 42 taken 3 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 8 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 4 times.
✓ Branch 47 taken 16 times.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✓ Branch 51 taken 2 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 3 times.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✓ Branch 58 taken 5 times.
✓ Branch 59 taken 5 times.
✓ Branch 60 taken 41 times.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✓ Branch 67 taken 59 times.
✓ Branch 68 taken 50 times.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✓ Branch 72 taken 1 times.
✓ Branch 73 taken 5 times.
473 switch (atom.type) {
364 3 case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break;
365 3 case MKTAG( '@','P','R','Q'): key = "quicktime_version"; raw = 1; break;
366 2 case MKTAG( 'X','M','P','_'):
367
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->export_xmp) { key = "xmp"; raw = 1; } break;
368 12 case MKTAG( 'a','A','R','T'): key = "album_artist"; break;
369 case MKTAG( 'a','k','I','D'): key = "account_type";
370 parse = mov_metadata_int8_no_padding; break;
371 case MKTAG( 'a','p','I','D'): key = "account_id"; break;
372 case MKTAG( 'c','a','t','g'): key = "category"; break;
373 13 case MKTAG( 'c','p','i','l'): key = "compilation";
374 13 parse = mov_metadata_int8_no_padding; break;
375 case MKTAG( 'c','p','r','t'): key = "copyright"; break;
376 case MKTAG( 'd','e','s','c'): key = "description"; break;
377 12 case MKTAG( 'd','i','s','k'): key = "disc";
378 12 parse = mov_metadata_track_or_disc_number; break;
379 case MKTAG( 'e','g','i','d'): key = "episode_uid";
380 parse = mov_metadata_int8_no_padding; break;
381 case MKTAG( 'F','I','R','M'): key = "firmware"; raw = 1; break;
382 10 case MKTAG( 'g','n','r','e'): key = "genre";
383 10 parse = mov_metadata_gnre; break;
384 case MKTAG( 'h','d','v','d'): key = "hd_video";
385 parse = mov_metadata_int8_no_padding; break;
386 case MKTAG( 'H','M','M','T'):
387 return mov_metadata_hmmt(c, pb, atom.size);
388 case MKTAG( 'k','e','y','w'): key = "keywords"; break;
389 case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
390 case MKTAG( 'l','o','c','i'):
391 return mov_metadata_loci(c, pb, atom.size);
392 case MKTAG( 'm','a','n','u'): key = "make"; break;
393 case MKTAG( 'm','o','d','l'): key = "model"; break;
394 case MKTAG( 'p','c','s','t'): key = "podcast";
395 parse = mov_metadata_int8_no_padding; break;
396 13 case MKTAG( 'p','g','a','p'): key = "gapless_playback";
397 13 parse = mov_metadata_int8_no_padding; break;
398 case MKTAG( 'p','u','r','d'): key = "purchase_date"; break;
399 case MKTAG( 'r','t','n','g'): key = "rating";
400 parse = mov_metadata_int8_no_padding; break;
401 case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break;
402 case MKTAG( 's','o','a','l'): key = "sort_album"; break;
403 case MKTAG( 's','o','a','r'): key = "sort_artist"; break;
404 case MKTAG( 's','o','c','o'): key = "sort_composer"; break;
405 case MKTAG( 's','o','n','m'): key = "sort_name"; break;
406 case MKTAG( 's','o','s','n'): key = "sort_show"; break;
407 case MKTAG( 's','t','i','k'): key = "media_type";
408 parse = mov_metadata_int8_no_padding; break;
409 12 case MKTAG( 't','r','k','n'): key = "track";
410 12 parse = mov_metadata_track_or_disc_number; break;
411 case MKTAG( 't','v','e','n'): key = "episode_id"; break;
412 case MKTAG( 't','v','e','s'): key = "episode_sort";
413 parse = mov_metadata_int8_bypass_padding; break;
414 case MKTAG( 't','v','n','n'): key = "network"; break;
415 case MKTAG( 't','v','s','h'): key = "show"; break;
416 case MKTAG( 't','v','s','n'): key = "season_number";
417 parse = mov_metadata_int8_bypass_padding; break;
418 17 case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
419 case MKTAG(0xa9,'P','R','D'): key = "producer"; break;
420 16 case MKTAG(0xa9,'a','l','b'): key = "album"; break;
421 3 case MKTAG(0xa9,'a','u','t'): key = "artist"; break;
422 case MKTAG(0xa9,'c','h','p'): key = "chapter"; break;
423 8 case MKTAG(0xa9,'c','m','t'): key = "comment"; break;
424 case MKTAG(0xa9,'c','o','m'): key = "composer"; break;
425 4 case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
426 16 case MKTAG(0xa9,'d','a','y'): key = "date"; break;
427 case MKTAG(0xa9,'d','i','r'): key = "director"; break;
428 case MKTAG(0xa9,'d','i','s'): key = "disclaimer"; break;
429 case MKTAG(0xa9,'e','d','1'): key = "edit_date"; break;
430 2 case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
431 case MKTAG(0xa9,'f','m','t'): key = "original_format"; break;
432 3 case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
433 case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
434 case MKTAG(0xa9,'h','s','t'): key = "host_computer"; break;
435 case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
436 case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
437 5 case MKTAG(0xa9,'m','a','k'): key = "make"; break;
438 5 case MKTAG(0xa9,'m','o','d'): key = "model"; break;
439 41 case MKTAG(0xa9,'n','a','m'): key = "title"; break;
440 case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break;
441 case MKTAG(0xa9,'p','r','d'): key = "producer"; break;
442 case MKTAG(0xa9,'p','r','f'): key = "performers"; break;
443 case MKTAG(0xa9,'r','e','q'): key = "playback_requirements"; break;
444 case MKTAG(0xa9,'s','r','c'): key = "original_source"; break;
445 case MKTAG(0xa9,'s','t','3'): key = "subtitle"; break;
446 59 case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
447 50 case MKTAG(0xa9,'t','o','o'): key = "encoder"; break;
448 case MKTAG(0xa9,'t','r','k'): key = "track"; break;
449 case MKTAG(0xa9,'u','r','l'): key = "URL"; break;
450 case MKTAG(0xa9,'w','r','n'): key = "warning"; break;
451 1 case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
452 5 case MKTAG(0xa9,'x','y','z'): key = "location"; break;
453 }
454 2 retry:
455
3/4
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 175 times.
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
761 if (c->itunes_metadata && atom.size > 8) {
456 300 int data_size = avio_rb32(pb);
457 300 int tag = avio_rl32(pb);
458
3/6
✓ Branch 0 taken 300 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 300 times.
✗ Branch 5 not taken.
300 if (tag == MKTAG('d','a','t','a') && data_size <= atom.size && data_size >= 16) {
459 300 data_type = avio_rb32(pb); // type
460 300 avio_rb32(pb); // unknown
461 300 str_size = data_size - 16;
462 300 atom.size -= 16;
463
464
5/6
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 207 times.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 34 times.
✓ Branch 4 taken 59 times.
✗ Branch 5 not taken.
300 if (!key && c->found_hdlr_mdta && c->meta_keys) {
465 59 uint32_t index = av_bswap32(atom.type); // BE number has been read as LE
466
2/4
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
59 if (index < c->meta_keys_count && index > 0) {
467 59 key = c->meta_keys[index];
468 } else if (atom.type != MKTAG('c', 'o', 'v', 'r')) {
469 av_log(c->fc, AV_LOG_WARNING,
470 "The index of 'data' is out of range: %"PRId32" < 1 or >= %d.\n",
471 index, c->meta_keys_count);
472 }
473 }
474
4/4
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 266 times.
✓ Branch 3 taken 20 times.
300 if (atom.type == MKTAG('c', 'o', 'v', 'r') ||
475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 266 times.
266 (key && !strcmp(key, "com.apple.quicktime.artwork"))) {
476 14 int ret = mov_read_covr(c, pb, data_type, str_size);
477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0) {
478 av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
479 return ret;
480 }
481 14 atom.size -= str_size;
482
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (atom.size > 8)
483 2 goto retry;
484 12 return ret;
485 }
486 } else return 0;
487
7/8
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 106 times.
✓ Branch 3 taken 51 times.
✓ Branch 4 taken 106 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 100 times.
✓ Branch 7 taken 6 times.
175 } else if (atom.size > 4 && key && !c->itunes_metadata && !raw) {
488 100 str_size = avio_rb16(pb); // string length
489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (str_size > atom.size) {
490 raw = 1;
491 avio_seek(pb, -2, SEEK_CUR);
492 av_log(c->fc, AV_LOG_WARNING, "UDTA parsing failed retrying raw\n");
493 goto retry;
494 }
495 100 langcode = avio_rb16(pb);
496 100 ff_mov_lang_to_iso639(langcode, language);
497 100 atom.size -= 4;
498 } else
499 75 str_size = atom.size;
500
501
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 461 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
461 if (c->export_all && !key) {
502 key = av_fourcc_make_string(tmp_key, atom.type);
503 }
504
505
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 372 times.
461 if (!key)
506 89 return 0;
507
2/4
✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 372 times.
372 if (atom.size < 0 || str_size >= INT_MAX/2)
508 return AVERROR_INVALIDDATA;
509
510 // Allocates enough space if data_type is a int32 or float32 number, otherwise
511 // worst-case requirement for output string in case of utf8 coded input
512
3/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 331 times.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
372 num = (data_type >= 21 && data_type <= 23);
513
4/4
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 325 times.
✓ Branch 3 taken 6 times.
372 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
514 372 str = av_mallocz(str_size_alloc);
515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
372 if (!str)
516 return AVERROR(ENOMEM);
517
518
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 312 times.
372 if (parse)
519 60 parse(c, pb, str_size, key);
520 else {
521
8/10
✓ Branch 0 taken 306 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 306 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 101 times.
✓ Branch 5 taken 205 times.
✓ Branch 6 taken 87 times.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 87 times.
312 if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
522 14 mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
523
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 296 times.
298 } else if (data_type == 21) { // BE signed integer, variable size
524 2 int val = 0;
525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (str_size == 1)
526 val = (int8_t)avio_r8(pb);
527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 2)
528 val = (int16_t)avio_rb16(pb);
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 3)
530 val = ((int32_t)(avio_rb24(pb)<<8))>>8;
531
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (str_size == 4)
532 2 val = (int32_t)avio_rb32(pb);
533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
534 av_log(c->fc, AV_LOG_ERROR,
535 "Failed to store the number (%d) in string.\n", val);
536 av_free(str);
537 return AVERROR_INVALIDDATA;
538 }
539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 296 times.
296 } else if (data_type == 22) { // BE unsigned integer, variable size
540 unsigned int val = 0;
541 if (str_size == 1)
542 val = avio_r8(pb);
543 else if (str_size == 2)
544 val = avio_rb16(pb);
545 else if (str_size == 3)
546 val = avio_rb24(pb);
547 else if (str_size == 4)
548 val = avio_rb32(pb);
549 if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
550 av_log(c->fc, AV_LOG_ERROR,
551 "Failed to store the number (%u) in string.\n", val);
552 av_free(str);
553 return AVERROR_INVALIDDATA;
554 }
555
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 283 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
309 } else if (data_type == 23 && str_size >= 4) { // BE float32
556 13 float val = av_int2float(avio_rb32(pb));
557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
558 av_log(c->fc, AV_LOG_ERROR,
559 "Failed to store the float32 number (%f) in string.\n", val);
560 av_free(str);
561 return AVERROR_INVALIDDATA;
562 }
563
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 283 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
283 } else if (data_type > 1 && data_type != 4) {
564 // data_type can be 0 if not set at all above. data_type 1 means
565 // UTF8 and 4 means "UTF8 sort". For any other type (UTF16 or e.g.
566 // a picture), don't return it blindly in a string that is supposed
567 // to be UTF8 text.
568 av_log(c->fc, AV_LOG_WARNING, "Skipping unhandled metadata %s of type %d\n", key, data_type);
569 av_free(str);
570 return 0;
571 } else {
572 283 int ret = ffio_read_size(pb, str, str_size);
573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 283 times.
283 if (ret < 0) {
574 av_free(str);
575 return ret;
576 }
577 283 str[str_size] = 0;
578 }
579 312 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
580 312 av_dict_set(metadata, key, str, 0);
581
4/4
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 212 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 63 times.
312 if (*language && strcmp(language, "und")) {
582 37 snprintf(key2, sizeof(key2), "%s-%s", key, language);
583 37 av_dict_set(metadata, key2, str, 0);
584 }
585
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 201 times.
312 if (!strcmp(key, "encoder")) {
586 int major, minor, micro;
587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111 times.
111 if (sscanf(str, "HandBrake %d.%d.%d", &major, &minor, &micro) == 3) {
588 c->handbrake_version = 1000000*major + 1000*minor + micro;
589 }
590 }
591 }
592
593 372 av_freep(&str);
594 372 return 0;
595 }
596
597 12 static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
598 {
599 int64_t start;
600 int i, nb_chapters, str_len, version;
601 char str[256+1];
602 int ret;
603
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->ignore_chapters)
605 return 0;
606
607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if ((atom.size -= 5) < 0)
608 return 0;
609
610 12 version = avio_r8(pb);
611 12 avio_rb24(pb);
612
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (version)
613 12 avio_rb32(pb); // ???
614 12 nb_chapters = avio_r8(pb);
615
616
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
30 for (i = 0; i < nb_chapters; i++) {
617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size < 9)
618 return 0;
619
620 18 start = avio_rb64(pb);
621 18 str_len = avio_r8(pb);
622
623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if ((atom.size -= 9+str_len) < 0)
624 return 0;
625
626 18 ret = ffio_read_size(pb, str, str_len);
627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (ret < 0)
628 return ret;
629 18 str[str_len] = 0;
630 18 avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
631 }
632 12 return 0;
633 }
634
635 #define MIN_DATA_ENTRY_BOX_SIZE 12
636 597 static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
637 {
638 AVStream *st;
639 MOVStreamContext *sc;
640 int entries, i, j;
641
642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (c->fc->nb_streams < 1)
643 return 0;
644 597 st = c->fc->streams[c->fc->nb_streams-1];
645 597 sc = st->priv_data;
646
647 597 avio_rb32(pb); // version + flags
648 597 entries = avio_rb32(pb);
649
1/2
✓ Branch 0 taken 597 times.
✗ Branch 1 not taken.
597 if (!entries ||
650
1/2
✓ Branch 0 taken 597 times.
✗ Branch 1 not taken.
597 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 entries >= UINT_MAX / sizeof(*sc->drefs))
652 return AVERROR_INVALIDDATA;
653
654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 for (i = 0; i < sc->drefs_count; i++) {
655 MOVDref *dref = &sc->drefs[i];
656 av_freep(&dref->path);
657 av_freep(&dref->dir);
658 }
659 597 av_free(sc->drefs);
660 597 sc->drefs_count = 0;
661 597 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (!sc->drefs)
663 return AVERROR(ENOMEM);
664 597 sc->drefs_count = entries;
665
666
2/2
✓ Branch 0 taken 597 times.
✓ Branch 1 taken 597 times.
1194 for (i = 0; i < entries; i++) {
667 597 MOVDref *dref = &sc->drefs[i];
668 597 uint32_t size = avio_rb32(pb);
669 597 int64_t next = avio_tell(pb);
670
671
3/6
✓ Branch 0 taken 597 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 597 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 597 times.
597 if (size < 12 || next < 0 || next > INT64_MAX - size)
672 return AVERROR_INVALIDDATA;
673
674 597 next += size - 4;
675
676 597 dref->type = avio_rl32(pb);
677 597 avio_rb32(pb); // version + flags
678
679
3/4
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 479 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 118 times.
597 if (dref->type == MKTAG('a','l','i','s') && size > 150) {
680 /* macintosh alias record */
681 uint16_t volume_len, len;
682 int16_t type;
683 int ret;
684
685 avio_skip(pb, 10);
686
687 volume_len = avio_r8(pb);
688 volume_len = FFMIN(volume_len, 27);
689 ret = ffio_read_size(pb, dref->volume, 27);
690 if (ret < 0)
691 return ret;
692 dref->volume[volume_len] = 0;
693 av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
694
695 avio_skip(pb, 12);
696
697 len = avio_r8(pb);
698 len = FFMIN(len, 63);
699 ret = ffio_read_size(pb, dref->filename, 63);
700 if (ret < 0)
701 return ret;
702 dref->filename[len] = 0;
703 av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
704
705 avio_skip(pb, 16);
706
707 /* read next level up_from_alias/down_to_target */
708 dref->nlvl_from = avio_rb16(pb);
709 dref->nlvl_to = avio_rb16(pb);
710 av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
711 dref->nlvl_from, dref->nlvl_to);
712
713 avio_skip(pb, 16);
714
715 for (type = 0; type != -1 && avio_tell(pb) < next; ) {
716 if (avio_feof(pb))
717 return AVERROR_EOF;
718 type = avio_rb16(pb);
719 len = avio_rb16(pb);
720 av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
721 if (len&1)
722 len += 1;
723 if (type == 2) { // absolute path
724 av_free(dref->path);
725 dref->path = av_mallocz(len+1);
726 if (!dref->path)
727 return AVERROR(ENOMEM);
728
729 ret = ffio_read_size(pb, dref->path, len);
730 if (ret < 0) {
731 av_freep(&dref->path);
732 return ret;
733 }
734 if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
735 len -= volume_len;
736 memmove(dref->path, dref->path+volume_len, len);
737 dref->path[len] = 0;
738 }
739 // trim string of any ending zeros
740 for (j = len - 1; j >= 0; j--) {
741 if (dref->path[j] == 0)
742 len--;
743 else
744 break;
745 }
746 for (j = 0; j < len; j++)
747 if (dref->path[j] == ':' || dref->path[j] == 0)
748 dref->path[j] = '/';
749 av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
750 } else if (type == 0) { // directory name
751 av_free(dref->dir);
752 dref->dir = av_malloc(len+1);
753 if (!dref->dir)
754 return AVERROR(ENOMEM);
755
756 ret = ffio_read_size(pb, dref->dir, len);
757 if (ret < 0) {
758 av_freep(&dref->dir);
759 return ret;
760 }
761 dref->dir[len] = 0;
762 for (j = 0; j < len; j++)
763 if (dref->dir[j] == ':')
764 dref->dir[j] = '/';
765 av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
766 } else
767 avio_skip(pb, len);
768 }
769 } else {
770 597 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
771 dref->type, size);
772 597 entries--;
773 597 i--;
774 }
775 597 avio_seek(pb, next, SEEK_SET);
776 }
777 597 return 0;
778 }
779
780 1094 static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
781 {
782 AVStream *st;
783 uint32_t type;
784 uint32_t ctype;
785 int64_t title_size;
786 char *title_str;
787 int ret;
788
789 1094 avio_r8(pb); /* version */
790 1094 avio_rb24(pb); /* flags */
791
792 /* component type */
793 1094 ctype = avio_rl32(pb);
794 1094 type = avio_rl32(pb); /* component subtype */
795
796 1094 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
797 1094 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
798
799
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 957 times.
1094 if (c->trak_index < 0) { // meta not inside a trak
800
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 126 times.
137 if (type == MKTAG('m','d','t','a')) {
801 11 c->found_hdlr_mdta = 1;
802 }
803 137 return 0;
804 }
805
806 957 st = c->fc->streams[c->fc->nb_streams-1];
807
808
2/2
✓ Branch 0 taken 305 times.
✓ Branch 1 taken 652 times.
957 if (type == MKTAG('v','i','d','e'))
809 305 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
810
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 411 times.
652 else if (type == MKTAG('s','o','u','n'))
811 241 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 411 times.
411 else if (type == MKTAG('m','1','a',' '))
813 st->codecpar->codec_id = AV_CODEC_ID_MP2;
814
2/4
✓ Branch 0 taken 411 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 411 times.
411 else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
815 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
816
817 957 avio_rb32(pb); /* component manufacture */
818 957 avio_rb32(pb); /* component flags */
819 957 avio_rb32(pb); /* component flags mask */
820
821 957 title_size = atom.size - 24;
822
2/2
✓ Branch 0 taken 954 times.
✓ Branch 1 taken 3 times.
957 if (title_size > 0) {
823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 954 times.
954 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
824 return AVERROR_INVALIDDATA;
825 954 title_str = av_malloc(title_size + 1); /* Add null terminator */
826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 954 times.
954 if (!title_str)
827 return AVERROR(ENOMEM);
828
829 954 ret = ffio_read_size(pb, title_str, title_size);
830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 954 times.
954 if (ret < 0) {
831 av_freep(&title_str);
832 return ret;
833 }
834 954 title_str[title_size] = 0;
835
2/2
✓ Branch 0 taken 903 times.
✓ Branch 1 taken 51 times.
954 if (title_str[0]) {
836
4/4
✓ Branch 0 taken 696 times.
✓ Branch 1 taken 207 times.
✓ Branch 2 taken 694 times.
✓ Branch 3 taken 2 times.
903 int off = (!c->isom && title_str[0] == title_size - 1);
837 // flag added so as to not set stream handler name if already set from mdia->hdlr
838 903 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
839 }
840 954 av_freep(&title_str);
841 }
842
843 957 return 0;
844 }
845
846 150 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
847 {
848 150 return ff_mov_read_esds(c->fc, pb);
849 }
850
851 7 static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
852 {
853 AVStream *st;
854 AVPacketSideData *sd;
855 enum AVAudioServiceType *ast;
856 int ac3info, acmod, lfeon, bsmod;
857 uint64_t mask;
858
859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (c->fc->nb_streams < 1)
860 return 0;
861 7 st = c->fc->streams[c->fc->nb_streams-1];
862
863 7 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
864 7 &st->codecpar->nb_coded_side_data,
865 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
866 sizeof(*ast), 0);
867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sd)
868 return AVERROR(ENOMEM);
869
870 7 ast = (enum AVAudioServiceType*)sd->data;
871 7 ac3info = avio_rb24(pb);
872 7 bsmod = (ac3info >> 14) & 0x7;
873 7 acmod = (ac3info >> 11) & 0x7;
874 7 lfeon = (ac3info >> 10) & 0x1;
875
876 7 mask = ff_ac3_channel_layout_tab[acmod];
877
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (lfeon)
878 1 mask |= AV_CH_LOW_FREQUENCY;
879 7 av_channel_layout_uninit(&st->codecpar->ch_layout);
880 7 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
881
882 7 *ast = bsmod;
883
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
7 if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7)
884 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
885
886 7 return 0;
887 }
888
889 #if CONFIG_IAMFDEC
890 10 static int mov_read_iacb(MOVContext *c, AVIOContext *pb, MOVAtom atom)
891 {
892 AVStream *st;
893 MOVStreamContext *sc;
894 FFIOContext b;
895 AVIOContext *descriptor_pb;
896 AVDictionary *metadata;
897 IAMFContext *iamf;
898 int64_t start_time, duration;
899 unsigned descriptors_size;
900 int nb_frames, disposition;
901 int version, ret;
902
903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (atom.size < 5)
904 return AVERROR_INVALIDDATA;
905
906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (c->fc->nb_streams < 1)
907 return 0;
908
909 10 version = avio_r8(pb);
910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (version != 1) {
911 av_log(c->fc, AV_LOG_ERROR, "%s configurationVersion %d",
912 version < 1 ? "invalid" : "unsupported", version);
913 return AVERROR_INVALIDDATA;
914 }
915
916 10 descriptors_size = ffio_read_leb(pb);
917
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (!descriptors_size || descriptors_size > INT_MAX)
918 return AVERROR_INVALIDDATA;
919
920 10 st = c->fc->streams[c->fc->nb_streams - 1];
921 10 sc = st->priv_data;
922
923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (st->codecpar->extradata) {
924 av_log(c->fc, AV_LOG_WARNING, "ignoring iacb\n");
925 return 0;
926 }
927
928 10 sc->iamf = av_mallocz(sizeof(*sc->iamf));
929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!sc->iamf)
930 return AVERROR(ENOMEM);
931 10 iamf = &sc->iamf->iamf;
932
933 10 st->codecpar->extradata = av_malloc(descriptors_size);
934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!st->codecpar->extradata)
935 return AVERROR(ENOMEM);
936 10 st->codecpar->extradata_size = descriptors_size;
937
938 10 ret = avio_read(pb, st->codecpar->extradata, descriptors_size);
939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret != descriptors_size)
940 return ret < 0 ? ret : AVERROR_INVALIDDATA;
941
942 10 ffio_init_read_context(&b, st->codecpar->extradata, descriptors_size);
943 10 descriptor_pb = &b.pub;
944
945 10 ret = ff_iamfdec_read_descriptors(iamf, descriptor_pb, descriptors_size, c->fc);
946
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
947 return ret;
948
949 10 metadata = st->metadata;
950 10 st->metadata = NULL;
951 10 start_time = st->start_time;
952 10 nb_frames = st->nb_frames;
953 10 duration = st->duration;
954 10 disposition = st->disposition;
955
956
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_audio_elements; i++) {
957 10 IAMFAudioElement *audio_element = iamf->audio_elements[i];
958 const AVIAMFAudioElement *element;
959 AVStreamGroup *stg =
960 10 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, NULL);
961
962
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!stg) {
963 ret = AVERROR(ENOMEM);
964 goto fail;
965 }
966
967 10 av_iamf_audio_element_free(&stg->params.iamf_audio_element);
968 10 stg->id = audio_element->audio_element_id;
969 /* Transfer ownership */
970 10 element = stg->params.iamf_audio_element = audio_element->element;
971 10 audio_element->element = NULL;
972
973
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int j = 0; j < audio_element->nb_substreams; j++) {
974 50 IAMFSubStream *substream = &audio_element->substreams[j];
975 AVStream *stream;
976
977
3/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 40 times.
50 if (!i && !j) {
978
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (audio_element->layers[0].substream_count != 1)
979 2 disposition &= ~AV_DISPOSITION_DEFAULT;
980 10 stream = st;
981 } else
982 40 stream = avformat_new_stream(c->fc, NULL);
983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (!stream) {
984 ret = AVERROR(ENOMEM);
985 goto fail;
986 }
987
988 50 stream->start_time = start_time;
989 50 stream->nb_frames = nb_frames;
990 50 stream->duration = duration;
991 50 stream->disposition = disposition;
992
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 10 times.
50 if (stream != st) {
993 40 stream->priv_data = sc;
994 40 sc->refcount++;
995 }
996
997
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 42 times.
50 if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
998 8 stream->disposition |= AV_DISPOSITION_DEPENDENT;
999
3/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 10 times.
50 if (i || j) {
1000 40 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1001
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 6 times.
40 if (audio_element->layers[0].substream_count == 1)
1002 34 stream->disposition &= ~AV_DISPOSITION_DEFAULT;
1003 }
1004
1005 50 ret = avcodec_parameters_copy(stream->codecpar, substream->codecpar);
1006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (ret < 0)
1007 goto fail;
1008
1009 50 stream->id = substream->audio_substream_id;
1010
1011 50 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
1012
1013 50 ret = avformat_stream_group_add_stream(stg, stream);
1014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (ret < 0)
1015 goto fail;
1016 }
1017
1018 10 ret = av_dict_copy(&stg->metadata, metadata, 0);
1019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
1020 goto fail;
1021 }
1022
1023
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1024 10 IAMFMixPresentation *mix_presentation = iamf->mix_presentations[i];
1025 10 const AVIAMFMixPresentation *mix = mix_presentation->cmix;
1026 AVStreamGroup *stg =
1027 10 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, NULL);
1028
1029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!stg) {
1030 ret = AVERROR(ENOMEM);
1031 goto fail;
1032 }
1033
1034 10 av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
1035 10 stg->id = mix_presentation->mix_presentation_id;
1036 /* Transfer ownership */
1037 10 stg->params.iamf_mix_presentation = mix_presentation->mix;
1038 10 mix_presentation->mix = NULL;
1039
1040
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 10 times.
22 for (int j = 0; j < mix->nb_submixes; j++) {
1041 12 const AVIAMFSubmix *submix = mix->submixes[j];
1042
1043
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int k = 0; k < submix->nb_elements; k++) {
1044 12 const AVIAMFSubmixElement *submix_element = submix->elements[k];
1045 12 const AVStreamGroup *audio_element = NULL;
1046
1047
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 for (int l = 0; l < c->fc->nb_stream_groups; l++)
1048
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (c->fc->stream_groups[l]->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT &&
1049
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 c->fc->stream_groups[l]->id == submix_element->audio_element_id) {
1050 12 audio_element = c->fc->stream_groups[l];
1051 12 break;
1052 }
1053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 av_assert0(audio_element);
1054
1055
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 12 times.
64 for (int l = 0; l < audio_element->nb_streams; l++) {
1056 52 ret = avformat_stream_group_add_stream(stg, audio_element->streams[l]);
1057
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
52 if (ret < 0 && ret != AVERROR(EEXIST))
1058 goto fail;
1059 }
1060 }
1061 }
1062
1063 10 ret = av_dict_copy(&stg->metadata, metadata, 0);
1064
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
1065 goto fail;
1066 }
1067
1068 10 ret = 0;
1069 10 fail:
1070 10 av_dict_free(&metadata);
1071
1072 10 return ret;
1073 }
1074 #endif
1075
1076 1 static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1077 {
1078 AVStream *st;
1079 AVPacketSideData *sd;
1080 enum AVAudioServiceType *ast;
1081 int eac3info, acmod, lfeon, bsmod;
1082 uint64_t mask;
1083
1084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
1085 return 0;
1086 1 st = c->fc->streams[c->fc->nb_streams-1];
1087
1088 1 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1089 1 &st->codecpar->nb_coded_side_data,
1090 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
1091 sizeof(*ast), 0);
1092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sd)
1093 return AVERROR(ENOMEM);
1094
1095 1 ast = (enum AVAudioServiceType*)sd->data;
1096
1097 /* No need to parse fields for additional independent substreams and its
1098 * associated dependent substreams since libavcodec's E-AC-3 decoder
1099 * does not support them yet. */
1100 1 avio_rb16(pb); /* data_rate and num_ind_sub */
1101 1 eac3info = avio_rb24(pb);
1102 1 bsmod = (eac3info >> 12) & 0x1f;
1103 1 acmod = (eac3info >> 9) & 0x7;
1104 1 lfeon = (eac3info >> 8) & 0x1;
1105
1106 1 mask = ff_ac3_channel_layout_tab[acmod];
1107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (lfeon)
1108 mask |= AV_CH_LOW_FREQUENCY;
1109 1 av_channel_layout_uninit(&st->codecpar->ch_layout);
1110 1 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
1111
1112 1 *ast = bsmod;
1113
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7)
1114 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
1115
1116 1 return 0;
1117 }
1118
1119 static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1120 {
1121 #define DDTS_SIZE 20
1122 uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
1123 AVStream *st = NULL;
1124 uint32_t frame_duration_code = 0;
1125 uint32_t channel_layout_code = 0;
1126 GetBitContext gb;
1127 int ret;
1128
1129 if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
1130 return ret;
1131
1132 init_get_bits(&gb, buf, 8 * DDTS_SIZE);
1133
1134 if (c->fc->nb_streams < 1) {
1135 return 0;
1136 }
1137 st = c->fc->streams[c->fc->nb_streams-1];
1138
1139 st->codecpar->sample_rate = get_bits_long(&gb, 32);
1140 if (st->codecpar->sample_rate <= 0) {
1141 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
1142 return AVERROR_INVALIDDATA;
1143 }
1144 skip_bits_long(&gb, 32); /* max bitrate */
1145 st->codecpar->bit_rate = get_bits_long(&gb, 32);
1146 st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
1147 frame_duration_code = get_bits(&gb, 2);
1148 skip_bits(&gb, 30); /* various fields */
1149 channel_layout_code = get_bits(&gb, 16);
1150
1151 st->codecpar->frame_size =
1152 (frame_duration_code == 0) ? 512 :
1153 (frame_duration_code == 1) ? 1024 :
1154 (frame_duration_code == 2) ? 2048 :
1155 (frame_duration_code == 3) ? 4096 : 0;
1156
1157 if (channel_layout_code > 0xff) {
1158 av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout\n");
1159 }
1160 av_channel_layout_uninit(&st->codecpar->ch_layout);
1161 av_channel_layout_from_mask(&st->codecpar->ch_layout,
1162 ((channel_layout_code & 0x1) ? AV_CH_FRONT_CENTER : 0) |
1163 ((channel_layout_code & 0x2) ? AV_CH_FRONT_LEFT : 0) |
1164 ((channel_layout_code & 0x2) ? AV_CH_FRONT_RIGHT : 0) |
1165 ((channel_layout_code & 0x4) ? AV_CH_SIDE_LEFT : 0) |
1166 ((channel_layout_code & 0x4) ? AV_CH_SIDE_RIGHT : 0) |
1167 ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0));
1168
1169 return 0;
1170 }
1171
1172 51 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1173 {
1174 AVStream *st;
1175
1176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (c->fc->nb_streams < 1)
1177 return 0;
1178 51 st = c->fc->streams[c->fc->nb_streams-1];
1179
1180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (atom.size < 16)
1181 return 0;
1182
1183 /* skip version and flags */
1184 51 avio_skip(pb, 4);
1185
1186 51 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
1187
1188 51 return 0;
1189 }
1190
1191 5 static int mov_read_chnl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1192 {
1193 5 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
1194 int version, flags;
1195 int ret;
1196 AVStream *st;
1197
1198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
1199 return 0;
1200 5 st = c->fc->streams[c->fc->nb_streams-1];
1201
1202 5 version = avio_r8(pb);
1203 5 flags = avio_rb24(pb);
1204
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (version != 0 || flags != 0) {
1205 av_log(c->fc, AV_LOG_ERROR,
1206 "Unsupported 'chnl' box with version %d, flags: %#x",
1207 version, flags);
1208 return AVERROR_INVALIDDATA;
1209 }
1210
1211 5 ret = ff_mov_read_chnl(c->fc, pb, st);
1212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
1213 return ret;
1214
1215
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_tell(pb) != end) {
1216 av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data inside chnl\n",
1217 end - avio_tell(pb));
1218 avio_seek(pb, end, SEEK_SET);
1219 }
1220 5 return ret;
1221 }
1222
1223 2 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1224 {
1225 AVStream *st;
1226 int ret;
1227
1228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
1229 return 0;
1230 2 st = c->fc->streams[c->fc->nb_streams-1];
1231
1232
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ff_get_wav_header(c->fc, pb, st->codecpar, atom.size, 0)) < 0)
1233 av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
1234
1235 2 return ret;
1236 }
1237
1238 18 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1239 {
1240 AVStream *st;
1241 HEIFItem *item;
1242 AVPacketSideData *sd;
1243 18 int width, height, err = 0;
1244 AVRational aperture_width, aperture_height, horiz_off, vert_off;
1245 AVRational pc_x, pc_y;
1246 uint64_t top, bottom, left, right;
1247
1248 18 item = heif_cur_item(c);
1249 18 st = get_curr_st(c);
1250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!st)
1251 return 0;
1252
1253 18 width = st->codecpar->width;
1254 18 height = st->codecpar->height;
1255
4/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
18 if ((!width || !height) && item) {
1256 6 width = item->width;
1257 6 height = item->height;
1258 }
1259
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (!width || !height) {
1260 err = AVERROR_INVALIDDATA;
1261 goto fail;
1262 }
1263
1264 18 aperture_width.num = avio_rb32(pb);
1265 18 aperture_width.den = avio_rb32(pb);
1266 18 aperture_height.num = avio_rb32(pb);
1267 18 aperture_height.den = avio_rb32(pb);
1268
1269 18 horiz_off.num = avio_rb32(pb);
1270 18 horiz_off.den = avio_rb32(pb);
1271 18 vert_off.num = avio_rb32(pb);
1272 18 vert_off.den = avio_rb32(pb);
1273
1274
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 if (aperture_width.num < 0 || aperture_width.den < 0 ||
1275
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 aperture_height.num < 0 || aperture_height.den < 0 ||
1276
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 horiz_off.den < 0 || vert_off.den < 0) {
1277 err = AVERROR_INVALIDDATA;
1278 goto fail;
1279 }
1280
3/4
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
33 if ((av_cmp_q((AVRational) { width, 1 }, aperture_width) < 0) ||
1281 15 (av_cmp_q((AVRational) { height, 1 }, aperture_height) < 0)) {
1282 3 err = AVERROR_INVALIDDATA;
1283 3 goto fail;
1284 }
1285 15 av_log(c->fc, AV_LOG_TRACE, "clap: apertureWidth %d/%d, apertureHeight %d/%d "
1286 "horizOff %d/%d vertOff %d/%d\n",
1287 aperture_width.num, aperture_width.den, aperture_height.num, aperture_height.den,
1288 horiz_off.num, horiz_off.den, vert_off.num, vert_off.den);
1289
1290 15 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1291 15 pc_x = av_add_q(pc_x, horiz_off);
1292 15 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1293 15 pc_y = av_add_q(pc_y, vert_off);
1294
1295 15 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1296 15 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1297 15 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1298 15 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1299
1300 15 left = av_q2d(av_sub_q(pc_x, aperture_width));
1301 15 right = av_q2d(av_add_q(pc_x, aperture_width));
1302 15 top = av_q2d(av_sub_q(pc_y, aperture_height));
1303 15 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1304
1305
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (bottom > (height - 1) ||
1306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 right > (width - 1)) {
1307 err = AVERROR_INVALIDDATA;
1308 goto fail;
1309 }
1310
1311 15 bottom = height - 1 - bottom;
1312 15 right = width - 1 - right;
1313
1314
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
15 if (!(left | right | top | bottom))
1315 6 return 0;
1316
1317
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if ((left + right) >= width ||
1318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 (top + bottom) >= height) {
1319 err = AVERROR_INVALIDDATA;
1320 goto fail;
1321 }
1322
1323 9 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1324 9 &st->codecpar->nb_coded_side_data,
1325 AV_PKT_DATA_FRAME_CROPPING,
1326 sizeof(uint32_t) * 4, 0);
1327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sd)
1328 return AVERROR(ENOMEM);
1329
1330 9 AV_WL32A(sd->data, top);
1331 9 AV_WL32A(sd->data + 4, bottom);
1332 9 AV_WL32A(sd->data + 8, left);
1333 9 AV_WL32A(sd->data + 12, right);
1334
1335 12 fail:
1336
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 if (err < 0) {
1337 3 int explode = !!(c->fc->error_recognition & AV_EF_EXPLODE);
1338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 av_log(c->fc, explode ? AV_LOG_ERROR : AV_LOG_WARNING, "Invalid clap box\n");
1339
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!explode)
1340 3 err = 0;
1341 }
1342
1343 12 return err;
1344 }
1345
1346 /* This atom overrides any previously set aspect ratio */
1347 66 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1348 {
1349 66 const int num = avio_rb32(pb);
1350 66 const int den = avio_rb32(pb);
1351 AVStream *st;
1352 MOVStreamContext *sc;
1353
1354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (c->fc->nb_streams < 1)
1355 return 0;
1356 66 st = c->fc->streams[c->fc->nb_streams-1];
1357 66 sc = st->priv_data;
1358
1359 66 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1360
1361
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 2 times.
66 if (den != 0) {
1362 64 sc->h_spacing = num;
1363 64 sc->v_spacing = den;
1364 }
1365 66 return 0;
1366 }
1367
1368 /* this atom contains actual media data */
1369 876 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1370 {
1371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 876 times.
876 if (atom.size == 0) /* wrong one (MP4) */
1372 return 0;
1373 876 c->found_mdat=1;
1374 876 return 0; /* now go for moov */
1375 }
1376
1377 #define DRM_BLOB_SIZE 56
1378
1379 static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1380 {
1381 uint8_t intermediate_key[20];
1382 uint8_t intermediate_iv[20];
1383 uint8_t input[64];
1384 uint8_t output[64];
1385 uint8_t file_checksum[20];
1386 uint8_t calculated_checksum[20];
1387 char checksum_string[2 * sizeof(file_checksum) + 1];
1388 struct AVSHA *sha;
1389 int i;
1390 int ret = 0;
1391 uint8_t *activation_bytes = c->activation_bytes;
1392 uint8_t *fixed_key = c->audible_fixed_key;
1393
1394 c->aax_mode = 1;
1395
1396 sha = av_sha_alloc();
1397 if (!sha)
1398 return AVERROR(ENOMEM);
1399 av_free(c->aes_decrypt);
1400 c->aes_decrypt = av_aes_alloc();
1401 if (!c->aes_decrypt) {
1402 ret = AVERROR(ENOMEM);
1403 goto fail;
1404 }
1405
1406 /* drm blob processing */
1407 avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1408 avio_read(pb, input, DRM_BLOB_SIZE);
1409 avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1410 avio_read(pb, file_checksum, 20);
1411
1412 // required by external tools
1413 ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1);
1414 av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string);
1415
1416 /* verify activation data */
1417 if (!activation_bytes) {
1418 av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1419 ret = 0; /* allow ffprobe to continue working on .aax files */
1420 goto fail;
1421 }
1422 if (c->activation_bytes_size != 4) {
1423 av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1424 ret = AVERROR(EINVAL);
1425 goto fail;
1426 }
1427
1428 /* verify fixed key */
1429 if (c->audible_fixed_key_size != 16) {
1430 av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1431 ret = AVERROR(EINVAL);
1432 goto fail;
1433 }
1434
1435 /* AAX (and AAX+) key derivation */
1436 av_sha_init(sha, 160);
1437 av_sha_update(sha, fixed_key, 16);
1438 av_sha_update(sha, activation_bytes, 4);
1439 av_sha_final(sha, intermediate_key);
1440 av_sha_init(sha, 160);
1441 av_sha_update(sha, fixed_key, 16);
1442 av_sha_update(sha, intermediate_key, 20);
1443 av_sha_update(sha, activation_bytes, 4);
1444 av_sha_final(sha, intermediate_iv);
1445 av_sha_init(sha, 160);
1446 av_sha_update(sha, intermediate_key, 16);
1447 av_sha_update(sha, intermediate_iv, 16);
1448 av_sha_final(sha, calculated_checksum);
1449 if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1450 av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1451 ret = AVERROR_INVALIDDATA;
1452 goto fail;
1453 }
1454 av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1455 av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1456 for (i = 0; i < 4; i++) {
1457 // file data (in output) is stored in big-endian mode
1458 if (activation_bytes[i] != output[3 - i]) { // critical error
1459 av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1460 ret = AVERROR_INVALIDDATA;
1461 goto fail;
1462 }
1463 }
1464 memcpy(c->file_key, output + 8, 16);
1465 memcpy(input, output + 26, 16);
1466 av_sha_init(sha, 160);
1467 av_sha_update(sha, input, 16);
1468 av_sha_update(sha, c->file_key, 16);
1469 av_sha_update(sha, fixed_key, 16);
1470 av_sha_final(sha, c->file_iv);
1471
1472 fail:
1473 av_free(sha);
1474
1475 return ret;
1476 }
1477
1478 static int mov_aaxc_crypto(MOVContext *c)
1479 {
1480 if (c->audible_key_size != 16) {
1481 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n");
1482 return AVERROR(EINVAL);
1483 }
1484
1485 if (c->audible_iv_size != 16) {
1486 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n");
1487 return AVERROR(EINVAL);
1488 }
1489
1490 c->aes_decrypt = av_aes_alloc();
1491 if (!c->aes_decrypt) {
1492 return AVERROR(ENOMEM);
1493 }
1494
1495 memcpy(c->file_key, c->audible_key, 16);
1496 memcpy(c->file_iv, c->audible_iv, 16);
1497 c->aax_mode = 1;
1498
1499 return 0;
1500 }
1501
1502 // Audible AAX (and AAX+) bytestream decryption
1503 static int aax_filter(uint8_t *input, int size, MOVContext *c)
1504 {
1505 int blocks = 0;
1506 unsigned char iv[16];
1507
1508 memcpy(iv, c->file_iv, 16); // iv is overwritten
1509 blocks = size >> 4; // trailing bytes are not encrypted!
1510 av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1511 av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1512
1513 return 0;
1514 }
1515
1516 /* read major brand, minor version and compatible brands and store them as metadata */
1517 455 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1518 {
1519 uint32_t minor_ver;
1520 int comp_brand_size;
1521 char* comp_brands_str;
1522 455 uint8_t type[5] = {0};
1523 455 int ret = ffio_read_size(pb, type, 4);
1524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 455 times.
455 if (ret < 0)
1525 return ret;
1526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 455 times.
455 if (c->fc->nb_streams) {
1527 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1528 return AVERROR_INVALIDDATA;
1529 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate FTYP\n");
1530 return 0;
1531 }
1532
1533
2/2
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 234 times.
455 if (strcmp(type, "qt "))
1534 221 c->isom = 1;
1535 455 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1536 455 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1537 455 minor_ver = avio_rb32(pb); /* minor version */
1538 455 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1539
1540 455 comp_brand_size = atom.size - 8;
1541
2/4
✓ Branch 0 taken 455 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 455 times.
455 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1542 return AVERROR_INVALIDDATA;
1543 455 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 455 times.
455 if (!comp_brands_str)
1545 return AVERROR(ENOMEM);
1546
1547 455 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 455 times.
455 if (ret < 0) {
1549 av_freep(&comp_brands_str);
1550 return ret;
1551 }
1552 455 comp_brands_str[comp_brand_size] = 0;
1553 455 av_dict_set(&c->fc->metadata, "compatible_brands",
1554 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1555
1556 // Logic for handling Audible's .aaxc files
1557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 455 times.
455 if (!strcmp(type, "aaxc")) {
1558 mov_aaxc_crypto(c);
1559 }
1560
1561 455 return 0;
1562 }
1563
1564 /* this atom should contain all header atoms */
1565 486 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1566 {
1567 int ret;
1568
1569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486 times.
486 if (c->found_moov) {
1570 av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1571 avio_skip(pb, atom.size);
1572 return 0;
1573 }
1574
1575
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 486 times.
486 if ((ret = mov_read_default(c, pb, atom)) < 0)
1576 return ret;
1577 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1578 /* so we don't parse the whole file if over a network */
1579 486 c->found_moov=1;
1580 486 return 0; /* now go for mdat */
1581 }
1582
1583 2869 static MOVFragmentStreamInfo * get_frag_stream_info(
1584 MOVFragmentIndex *frag_index,
1585 int index,
1586 int id)
1587 {
1588 int i;
1589 MOVFragmentIndexItem * item;
1590
1591
2/4
✓ Branch 0 taken 2869 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2869 times.
2869 if (index < 0 || index >= frag_index->nb_items)
1592 return NULL;
1593 2869 item = &frag_index->item[index];
1594
1/2
✓ Branch 0 taken 2993 times.
✗ Branch 1 not taken.
2993 for (i = 0; i < item->nb_stream_info; i++)
1595
2/2
✓ Branch 0 taken 2869 times.
✓ Branch 1 taken 124 times.
2993 if (item->stream_info[i].id == id)
1596 2869 return &item->stream_info[i];
1597
1598 // This shouldn't happen
1599 return NULL;
1600 }
1601
1602 388 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1603 {
1604 int i;
1605 MOVFragmentIndexItem * item;
1606
1607
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_index->current < 0 ||
1608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 frag_index->current >= frag_index->nb_items)
1609 return;
1610
1611 388 item = &frag_index->item[frag_index->current];
1612
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < item->nb_stream_info; i++)
1613
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (item->stream_info[i].id == id) {
1614 388 item->current = i;
1615 388 return;
1616 }
1617
1618 // id not found. This shouldn't happen.
1619 item->current = -1;
1620 }
1621
1622 1149 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1623 MOVFragmentIndex *frag_index)
1624 {
1625 MOVFragmentIndexItem *item;
1626
1/2
✓ Branch 0 taken 1149 times.
✗ Branch 1 not taken.
1149 if (frag_index->current < 0 ||
1627
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1146 times.
1149 frag_index->current >= frag_index->nb_items)
1628 3 return NULL;
1629
1630 1146 item = &frag_index->item[frag_index->current];
1631
2/4
✓ Branch 0 taken 1146 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1146 times.
✗ Branch 3 not taken.
1146 if (item->current >= 0 && item->current < item->nb_stream_info)
1632 1146 return &item->stream_info[item->current];
1633
1634 // This shouldn't happen
1635 return NULL;
1636 }
1637
1638 798 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1639 {
1640 int a, b, m;
1641 int64_t moof_offset;
1642
1643 // Optimize for appending new entries
1644
2/2
✓ Branch 0 taken 788 times.
✓ Branch 1 taken 10 times.
798 if (!frag_index->nb_items ||
1645
2/2
✓ Branch 0 taken 383 times.
✓ Branch 1 taken 405 times.
788 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1646 393 return frag_index->nb_items;
1647
1648 405 a = -1;
1649 405 b = frag_index->nb_items;
1650
1651
2/2
✓ Branch 0 taken 2655 times.
✓ Branch 1 taken 405 times.
3060 while (b - a > 1) {
1652 2655 m = (a + b) >> 1;
1653 2655 moof_offset = frag_index->item[m].moof_offset;
1654
2/2
✓ Branch 0 taken 732 times.
✓ Branch 1 taken 1923 times.
2655 if (moof_offset >= offset)
1655 732 b = m;
1656
2/2
✓ Branch 0 taken 2328 times.
✓ Branch 1 taken 327 times.
2655 if (moof_offset <= offset)
1657 2328 a = m;
1658 }
1659 405 return b;
1660 }
1661
1662 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1663 {
1664 av_assert0(frag_stream_info);
1665 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1666 return frag_stream_info->sidx_pts;
1667 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1668 return frag_stream_info->first_tfra_pts;
1669 return frag_stream_info->tfdt_dts;
1670 }
1671
1672 219 static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1673 MOVFragmentIndex *frag_index, int index)
1674 {
1675 MOVFragmentStreamInfo * frag_stream_info;
1676 219 MOVStreamContext *sc = dst_st->priv_data;
1677 int64_t timestamp;
1678 int i, j;
1679
1680 // If the stream is referenced by any sidx, limit the search
1681 // to fragments that referenced this stream in the sidx
1682
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (sc->has_sidx) {
1683 219 frag_stream_info = get_frag_stream_info(frag_index, index, sc->id);
1684
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!frag_stream_info)
1685 return AV_NOPTS_VALUE;
1686
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1687 219 return frag_stream_info->sidx_pts;
1688 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1689 return frag_stream_info->first_tfra_pts;
1690 return frag_stream_info->sidx_pts;
1691 }
1692
1693 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
1694 AVStream *frag_stream = NULL;
1695 frag_stream_info = &frag_index->item[index].stream_info[i];
1696 for (j = 0; j < s->nb_streams; j++) {
1697 MOVStreamContext *sc2 = s->streams[j]->priv_data;
1698 if (sc2->id == frag_stream_info->id)
1699 frag_stream = s->streams[j];
1700 }
1701 if (!frag_stream) {
1702 av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1703 continue;
1704 }
1705 timestamp = get_stream_info_time(frag_stream_info);
1706 if (timestamp != AV_NOPTS_VALUE)
1707 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1708 }
1709 return AV_NOPTS_VALUE;
1710 }
1711
1712 26 static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1713 AVStream *st, int64_t timestamp)
1714 {
1715 int a, b, m, m0;
1716 int64_t frag_time;
1717
1718 26 a = -1;
1719 26 b = frag_index->nb_items;
1720
1721
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 26 times.
245 while (b - a > 1) {
1722 219 m0 = m = (a + b) >> 1;
1723
1724
2/4
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 219 times.
438 while (m < b &&
1725 219 (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
1726 m++;
1727
1728
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)
1729 93 a = m;
1730 else
1731 126 b = m0;
1732 }
1733
1734 26 return a;
1735 }
1736
1737 756 static int update_frag_index(MOVContext *c, int64_t offset)
1738 {
1739 int index, i;
1740 MOVFragmentIndexItem * item;
1741 MOVFragmentStreamInfo * frag_stream_info;
1742
1743 // If moof_offset already exists in frag_index, return index to it
1744 756 index = search_frag_moof_offset(&c->frag_index, offset);
1745
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 389 times.
756 if (index < c->frag_index.nb_items &&
1746
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 c->frag_index.item[index].moof_offset == offset)
1747 367 return index;
1748
1749 // offset is not yet in frag index.
1750 // Insert new item at index (sorted by moof offset)
1751 389 item = av_fast_realloc(c->frag_index.item,
1752 389 &c->frag_index.allocated_size,
1753 389 (c->frag_index.nb_items + 1) *
1754 sizeof(*c->frag_index.item));
1755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (!item)
1756 return -1;
1757 389 c->frag_index.item = item;
1758
1759 389 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1760 sizeof(*item->stream_info));
1761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (!frag_stream_info)
1762 return -1;
1763
1764
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 389 times.
796 for (i = 0; i < c->fc->nb_streams; i++) {
1765 // Avoid building frag index if streams lack track id.
1766 407 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 407 times.
407 if (sc->id < 0) {
1768 av_free(frag_stream_info);
1769 return AVERROR_INVALIDDATA;
1770 }
1771
1772 407 frag_stream_info[i].id = sc->id;
1773 407 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1774 407 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1775 407 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1776 407 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1777 407 frag_stream_info[i].index_base = -1;
1778 407 frag_stream_info[i].index_entry = -1;
1779 407 frag_stream_info[i].encryption_index = NULL;
1780 407 frag_stream_info[i].stsd_id = -1;
1781 }
1782
1783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (index < c->frag_index.nb_items)
1784 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1785 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1786
1787 389 item = &c->frag_index.item[index];
1788 389 item->headers_read = 0;
1789 389 item->current = 0;
1790 389 item->nb_stream_info = c->fc->nb_streams;
1791 389 item->moof_offset = offset;
1792 389 item->stream_info = frag_stream_info;
1793 389 c->frag_index.nb_items++;
1794
1795 389 return index;
1796 }
1797
1798 388 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1799 int id, int entries)
1800 {
1801 int i;
1802 MOVFragmentStreamInfo * frag_stream_info;
1803
1804
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (index < 0)
1805 388 return;
1806 for (i = index; i < frag_index->nb_items; i++) {
1807 frag_stream_info = get_frag_stream_info(frag_index, i, id);
1808 if (frag_stream_info && frag_stream_info->index_entry >= 0)
1809 frag_stream_info->index_entry += entries;
1810 }
1811 }
1812
1813 388 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1814 {
1815 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1816 388 c->fragment.found_tfhd = 0;
1817
1818
2/4
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 388 times.
388 if (!c->has_looked_for_mfra && c->use_mfra_for > 0) {
1819 c->has_looked_for_mfra = 1;
1820 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1821 int ret;
1822 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1823 "for a mfra\n");
1824 if ((ret = mov_read_mfra(c, pb)) < 0) {
1825 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1826 "read the mfra (may be a live ismv)\n");
1827 }
1828 } else {
1829 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1830 "seekable, can not look for mfra\n");
1831 }
1832 }
1833 388 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1834 388 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1835 388 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1836 388 return mov_read_default(c, pb, atom);
1837 }
1838
1839 1080 static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version)
1840 {
1841 int64_t time;
1842
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1069 times.
1080 if (version == 1) {
1843 11 time = avio_rb64(pb);
1844 11 avio_rb64(pb);
1845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (time < 0) {
1846 av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n");
1847 return;
1848 }
1849 } else {
1850 1069 time = avio_rb32(pb);
1851 1069 avio_rb32(pb); /* modification time */
1852
4/4
✓ Branch 0 taken 519 times.
✓ Branch 1 taken 550 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 471 times.
1069 if (time > 0 && time < 2082844800) {
1853 48 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1854 48 time += 2082844800;
1855 }
1856 }
1857
2/2
✓ Branch 0 taken 525 times.
✓ Branch 1 taken 555 times.
1080 if (time) {
1858 525 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1859
1860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 525 times.
525 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1861 av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n");
1862 return;
1863 }
1864
1865 525 ff_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1866 }
1867 }
1868
1869 597 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1870 {
1871 AVStream *st;
1872 MOVStreamContext *sc;
1873 int version;
1874 597 char language[4] = {0};
1875 unsigned lang;
1876
1877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (c->fc->nb_streams < 1)
1878 return 0;
1879 597 st = c->fc->streams[c->fc->nb_streams-1];
1880 597 sc = st->priv_data;
1881
1882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (sc->time_scale) {
1883 av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
1884 return AVERROR_INVALIDDATA;
1885 }
1886
1887 597 version = avio_r8(pb);
1888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (version > 1) {
1889 avpriv_request_sample(c->fc, "Version %d", version);
1890 return AVERROR_PATCHWELCOME;
1891 }
1892 597 avio_rb24(pb); /* flags */
1893 597 mov_metadata_creation_time(c, pb, &st->metadata, version);
1894
1895 597 sc->time_scale = avio_rb32(pb);
1896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (sc->time_scale <= 0) {
1897 av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
1898 sc->time_scale = 1;
1899 }
1900
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 588 times.
597 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1901
1902
6/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 588 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 588 times.
✓ Branch 5 taken 4 times.
597 if ((version == 1 && st->duration == UINT64_MAX) ||
1903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 588 times.
588 (version != 1 && st->duration == UINT32_MAX)) {
1904 5 st->duration = 0;
1905 }
1906
1907 597 lang = avio_rb16(pb); /* language */
1908
2/2
✓ Branch 1 taken 425 times.
✓ Branch 2 taken 172 times.
597 if (ff_mov_lang_to_iso639(lang, language))
1909 425 av_dict_set(&st->metadata, "language", language, 0);
1910 597 avio_rb16(pb); /* quality */
1911
1912 597 return 0;
1913 }
1914
1915 483 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1916 {
1917 int i;
1918 483 int version = avio_r8(pb); /* version */
1919 483 avio_rb24(pb); /* flags */
1920
1921 483 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
1922 483 c->time_scale = avio_rb32(pb); /* time scale */
1923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
483 if (c->time_scale <= 0) {
1924 av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
1925 c->time_scale = 1;
1926 }
1927 483 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
1928
1929
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 481 times.
483 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1930 483 avio_rb32(pb); /* preferred scale */
1931
1932 483 avio_rb16(pb); /* preferred volume */
1933
1934 483 avio_skip(pb, 10); /* reserved */
1935
1936 /* movie display matrix, store it in main context and use it later on */
1937
2/2
✓ Branch 0 taken 1449 times.
✓ Branch 1 taken 483 times.
1932 for (i = 0; i < 3; i++) {
1938 1449 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
1939 1449 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
1940 1449 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
1941 }
1942
1943 483 avio_rb32(pb); /* preview time */
1944 483 avio_rb32(pb); /* preview duration */
1945 483 avio_rb32(pb); /* poster time */
1946 483 avio_rb32(pb); /* selection time */
1947 483 avio_rb32(pb); /* selection duration */
1948 483 avio_rb32(pb); /* current time */
1949 483 avio_rb32(pb); /* next track ID */
1950
1951 483 return 0;
1952 }
1953
1954 7 static void set_last_stream_little_endian(AVFormatContext *fc)
1955 {
1956 AVStream *st;
1957
1958
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (fc->nb_streams < 1)
1959 return;
1960 7 st = fc->streams[fc->nb_streams-1];
1961
1962
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) {
1963 5 case AV_CODEC_ID_PCM_S16BE:
1964 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
1965 5 break;
1966 1 case AV_CODEC_ID_PCM_S24BE:
1967 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
1968 1 break;
1969 case AV_CODEC_ID_PCM_S32BE:
1970 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
1971 break;
1972 1 case AV_CODEC_ID_PCM_F32BE:
1973 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
1974 1 break;
1975 case AV_CODEC_ID_PCM_F64BE:
1976 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
1977 break;
1978 default:
1979 break;
1980 }
1981 }
1982
1983 5 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1984 {
1985 5 int little_endian = avio_rb16(pb) & 0xFF;
1986 5 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
1987
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (little_endian == 1)
1988 1 set_last_stream_little_endian(c->fc);
1989 5 return 0;
1990 }
1991
1992 6 static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1993 {
1994 int format_flags;
1995 int version, flags;
1996 int pcm_sample_size;
1997 6 AVFormatContext *fc = c->fc;
1998 AVStream *st;
1999 MOVStreamContext *sc;
2000
2001
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 6) {
2002 av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n");
2003 return AVERROR_INVALIDDATA;
2004 }
2005
2006 6 version = avio_r8(pb);
2007 6 flags = avio_rb24(pb);
2008
2009
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) {
2010 av_log(c->fc, AV_LOG_ERROR,
2011 "Unsupported 'pcmC' box with version %d, flags: %x",
2012 version, flags);
2013 return AVERROR_INVALIDDATA;
2014 }
2015
2016 6 format_flags = avio_r8(pb);
2017 6 pcm_sample_size = avio_r8(pb);
2018
2019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fc->nb_streams < 1)
2020 return AVERROR_INVALIDDATA;
2021
2022 6 st = fc->streams[fc->nb_streams - 1];
2023 6 sc = st->priv_data;
2024
2025
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (sc->format == MOV_MP4_FPCM_TAG) {
2026
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (pcm_sample_size) {
2027 1 case 32:
2028 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE;
2029 1 break;
2030 case 64:
2031 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE;
2032 break;
2033 default:
2034 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2035 pcm_sample_size,
2036 av_fourcc2str(sc->format));
2037 return AVERROR_INVALIDDATA;
2038 }
2039
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (sc->format == MOV_MP4_IPCM_TAG) {
2040
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 switch (pcm_sample_size) {
2041 5 case 16:
2042 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2043 5 break;
2044 case 24:
2045 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
2046 break;
2047 case 32:
2048 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
2049 break;
2050 default:
2051 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2052 pcm_sample_size,
2053 av_fourcc2str(sc->format));
2054 return AVERROR_INVALIDDATA;
2055 }
2056 } else {
2057 av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n",
2058 av_fourcc2str(sc->format));
2059 return AVERROR_INVALIDDATA;
2060 }
2061
2062
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
2063 6 set_last_stream_little_endian(c->fc);
2064 6 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2065
2066 6 return 0;
2067 }
2068
2069 43 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2070 {
2071 AVStream *st;
2072 43 HEIFItem *item = NULL;
2073 43 char color_parameter_type[5] = { 0 };
2074 uint16_t color_primaries, color_trc, color_matrix;
2075 int ret;
2076
2077 43 st = get_curr_st(c);
2078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st) {
2079 item = heif_cur_item(c);
2080 if (!item)
2081 return 0;
2082 }
2083
2084 43 ret = ffio_read_size(pb, color_parameter_type, 4);
2085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
2086 return ret;
2087
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 10 times.
43 if (strncmp(color_parameter_type, "nclx", 4) &&
2088
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 strncmp(color_parameter_type, "nclc", 4) &&
2089 strncmp(color_parameter_type, "prof", 4)) {
2090 av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
2091 color_parameter_type);
2092 return 0;
2093 }
2094
2095
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!strncmp(color_parameter_type, "prof", 4)) {
2096 AVPacketSideData *sd;
2097 uint8_t *icc_profile;
2098 if (st) {
2099 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
2100 &st->codecpar->nb_coded_side_data,
2101 AV_PKT_DATA_ICC_PROFILE,
2102 atom.size - 4, 0);
2103 if (!sd)
2104 return AVERROR(ENOMEM);
2105 icc_profile = sd->data;
2106 } else {
2107 av_freep(&item->icc_profile);
2108 icc_profile = item->icc_profile = av_malloc(atom.size - 4);
2109 if (!icc_profile) {
2110 item->icc_profile_size = 0;
2111 return AVERROR(ENOMEM);
2112 }
2113 item->icc_profile_size = atom.size - 4;
2114 }
2115 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
2116 if (ret < 0)
2117 return ret;
2118
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 } else if (st) {
2119 43 color_primaries = avio_rb16(pb);
2120 43 color_trc = avio_rb16(pb);
2121 43 color_matrix = avio_rb16(pb);
2122
2123 43 av_log(c->fc, AV_LOG_TRACE,
2124 "%s: pri %d trc %d matrix %d",
2125 color_parameter_type, color_primaries, color_trc, color_matrix);
2126
2127
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 33 times.
43 if (!strncmp(color_parameter_type, "nclx", 4)) {
2128 10 uint8_t color_range = avio_r8(pb) >> 7;
2129 10 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (color_range)
2131 st->codecpar->color_range = AVCOL_RANGE_JPEG;
2132 else
2133 10 st->codecpar->color_range = AVCOL_RANGE_MPEG;
2134 }
2135
2136
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_primaries_name(color_primaries))
2137 color_primaries = AVCOL_PRI_UNSPECIFIED;
2138
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_transfer_name(color_trc))
2139 color_trc = AVCOL_TRC_UNSPECIFIED;
2140
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_space_name(color_matrix))
2141 color_matrix = AVCOL_SPC_UNSPECIFIED;
2142
2143 43 st->codecpar->color_primaries = color_primaries;
2144 43 st->codecpar->color_trc = color_trc;
2145 43 st->codecpar->color_space = color_matrix;
2146 43 av_log(c->fc, AV_LOG_TRACE, "\n");
2147 }
2148 43 return 0;
2149 }
2150
2151 112 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2152 {
2153 AVStream *st;
2154 unsigned mov_field_order;
2155 112 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2156
2157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (c->fc->nb_streams < 1) // will happen with jp2 files
2158 return 0;
2159 112 st = c->fc->streams[c->fc->nb_streams-1];
2160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (atom.size < 2)
2161 return AVERROR_INVALIDDATA;
2162 112 mov_field_order = avio_rb16(pb);
2163
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 20 times.
112 if ((mov_field_order & 0xFF00) == 0x0100)
2164 92 decoded_field_order = AV_FIELD_PROGRESSIVE;
2165
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 else if ((mov_field_order & 0xFF00) == 0x0200) {
2166
3/5
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
20 switch (mov_field_order & 0xFF) {
2167 1 case 0x01: decoded_field_order = AV_FIELD_TT;
2168 1 break;
2169 case 0x06: decoded_field_order = AV_FIELD_BB;
2170 break;
2171 1 case 0x09: decoded_field_order = AV_FIELD_TB;
2172 1 break;
2173 18 case 0x0E: decoded_field_order = AV_FIELD_BT;
2174 18 break;
2175 }
2176 }
2177
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
112 if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) {
2178 av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
2179 }
2180 112 st->codecpar->field_order = decoded_field_order;
2181
2182 112 return 0;
2183 }
2184
2185 68 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
2186 {
2187 68 int err = 0;
2188 68 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
2189
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)
2190 return AVERROR_INVALIDDATA;
2191
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
68 if ((err = av_reallocp(&par->extradata, size)) < 0) {
2192 par->extradata_size = 0;
2193 return err;
2194 }
2195 68 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
2196 68 return 0;
2197 }
2198
2199 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
2200 65 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2201 AVCodecParameters *par, uint8_t *buf)
2202 {
2203 65 int64_t result = atom.size;
2204 int err;
2205
2206 65 AV_WB32(buf , atom.size + 8);
2207 65 AV_WL32(buf + 4, atom.type);
2208 65 err = ffio_read_size(pb, buf + 8, atom.size);
2209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (err < 0) {
2210 par->extradata_size -= atom.size;
2211 return err;
2212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 } else if (err < atom.size) {
2213 av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
2214 par->extradata_size -= atom.size - err;
2215 result = err;
2216 }
2217 65 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2218 65 return result;
2219 }
2220
2221 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
2222 58 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2223 enum AVCodecID codec_id)
2224 {
2225 AVStream *st;
2226 uint64_t original_size;
2227 int err;
2228
2229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (c->fc->nb_streams < 1) // will happen with jp2 files
2230 return 0;
2231 58 st = c->fc->streams[c->fc->nb_streams-1];
2232
2233
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
58 if (st->codecpar->codec_id != codec_id)
2234 19 return 0; /* unexpected codec_id - don't mess with extradata */
2235
2236 39 original_size = st->codecpar->extradata_size;
2237 39 err = mov_realloc_extradata(st->codecpar, atom);
2238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err)
2239 return err;
2240
2241 39 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
2242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err < 0)
2243 return err;
2244 39 return 0; // Note: this is the original behavior to ignore truncation.
2245 }
2246
2247 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
2248 16 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2249 {
2250 16 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
2251 }
2252
2253 static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2254 {
2255 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS);
2256 }
2257
2258 static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2259 {
2260 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
2261 }
2262
2263 static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2264 {
2265 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
2266 }
2267
2268 19 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2269 {
2270 19 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
2271
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!ret)
2272 19 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
2273 19 return ret;
2274 }
2275
2276 static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2277 {
2278 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
2279
2280 if (!ret && c->fc->nb_streams >= 1) {
2281 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2282 if (par->extradata_size >= 40) {
2283 par->height = AV_RB16(&par->extradata[36]);
2284 par->width = AV_RB16(&par->extradata[38]);
2285 }
2286 }
2287 return ret;
2288 }
2289
2290 16 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2291 {
2292
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (c->fc->nb_streams >= 1) {
2293 16 AVStream *const st = c->fc->streams[c->fc->nb_streams - 1];
2294 16 FFStream *const sti = ffstream(st);
2295 16 AVCodecParameters *par = st->codecpar;
2296
2297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
2298 par->codec_id == AV_CODEC_ID_H264 &&
2299 atom.size > 11) {
2300 int cid;
2301 avio_skip(pb, 10);
2302 cid = avio_rb16(pb);
2303 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
2304 if (cid == 0xd4d || cid == 0xd4e)
2305 par->width = 1440;
2306 return 0;
2307
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
2308
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
2309
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
2310
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 atom.size >= 24) {
2311 int num, den;
2312 13 avio_skip(pb, 12);
2313 13 num = avio_rb32(pb);
2314 13 den = avio_rb32(pb);
2315
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)
2316 return 0;
2317
2/3
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
13 switch (avio_rb32(pb)) {
2318 12 case 2:
2319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (den >= INT_MAX / 2)
2320 return 0;
2321 12 den *= 2;
2322 13 case 1:
2323 13 sti->display_aspect_ratio = (AVRational){ num, den };
2324 13 default:
2325 13 return 0;
2326 }
2327 }
2328 }
2329
2330 3 return mov_read_avid(c, pb, atom);
2331 }
2332
2333 26 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2334 {
2335 26 int ret = 0;
2336 26 int length = 0;
2337 uint64_t original_size;
2338
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (c->fc->nb_streams >= 1) {
2339 26 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (par->codec_id == AV_CODEC_ID_H264)
2341 return 0;
2342
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (atom.size == 16) {
2343 26 original_size = par->extradata_size;
2344 26 ret = mov_realloc_extradata(par, atom);
2345
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!ret) {
2346 26 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
2347
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (length == atom.size) {
2348 26 const uint8_t range_value = par->extradata[original_size + 19];
2349
1/3
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
26 switch (range_value) {
2350 26 case 1:
2351 26 par->color_range = AVCOL_RANGE_MPEG;
2352 26 break;
2353 case 2:
2354 par->color_range = AVCOL_RANGE_JPEG;
2355 break;
2356 default:
2357 av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
2358 break;
2359 }
2360 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
2361 } else {
2362 /* For some reason the whole atom was not added to the extradata */
2363 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
2364 }
2365 } else {
2366 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
2367 }
2368 } else {
2369 av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
2370 }
2371 }
2372
2373 26 return ret;
2374 }
2375
2376 4 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2377 {
2378 4 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
2379 }
2380
2381 34 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2382 {
2383 AVStream *st;
2384 int ret;
2385
2386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (c->fc->nb_streams < 1)
2387 return 0;
2388 34 st = c->fc->streams[c->fc->nb_streams-1];
2389
2390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if ((uint64_t)atom.size > (1<<30))
2391 return AVERROR_INVALIDDATA;
2392
2393
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2 times.
34 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2394
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
2396 // pass all frma atom to codec, needed at least for QDMC and QDM2
2397 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2399 return ret;
2400
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 } else if (atom.size > 8) { /* to read frma, esds atoms */
2401
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) {
2402 uint64_t buffer;
2403 10 ret = ffio_ensure_seekback(pb, 8);
2404
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2405 return ret;
2406 10 buffer = avio_rb64(pb);
2407 10 atom.size -= 8;
2408
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
2409
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 <= atom.size
2410
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 >= 8) {
2411 10 avio_skip(pb, -8);
2412 10 atom.size += 8;
2413 } else if (!st->codecpar->extradata_size) {
2414 #define ALAC_EXTRADATA_SIZE 36
2415 st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
2416 if (!st->codecpar->extradata)
2417 return AVERROR(ENOMEM);
2418 st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
2419 AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
2420 AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
2421 AV_WB64(st->codecpar->extradata + 12, buffer);
2422 avio_read(pb, st->codecpar->extradata + 20, 16);
2423 avio_skip(pb, atom.size - 24);
2424 return 0;
2425 }
2426 }
2427
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if ((ret = mov_read_default(c, pb, atom)) < 0)
2428 return ret;
2429 } else
2430 avio_skip(pb, atom.size);
2431 34 return 0;
2432 }
2433
2434 /**
2435 * This function reads atom content and puts data in extradata without tag
2436 * nor size unlike mov_read_extradata.
2437 */
2438 141 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2439 {
2440 AVStream *st;
2441 int ret;
2442
2443 141 st = get_curr_st(c);
2444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
141 if (!st)
2445 return 0;
2446
2447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
141 if ((uint64_t)atom.size > (1<<30))
2448 return AVERROR_INVALIDDATA;
2449
2450
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 140 times.
141 if (atom.type == MKTAG('v','v','c','C')) {
2451 1 avio_skip(pb, 4);
2452 1 atom.size -= 4;
2453 }
2454
2455
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 4 times.
141 if (atom.size >= 10) {
2456 // Broken files created by legacy versions of libavformat will
2457 // wrap a whole fiel atom inside of a glbl atom.
2458 137 unsigned size = avio_rb32(pb);
2459 137 unsigned type = avio_rl32(pb);
2460
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 137 times.
137 if (avio_feof(pb))
2461 return AVERROR_INVALIDDATA;
2462 137 avio_seek(pb, -8, SEEK_CUR);
2463
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 129 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
137 if (type == MKTAG('f','i','e','l') && size == atom.size)
2464 8 return mov_read_default(c, pb, atom);
2465 }
2466
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
133 if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
2467 av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
2468 return 0;
2469 }
2470 133 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
133 if (ret < 0)
2472 return ret;
2473
3/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 41 times.
133 if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
2474 /* HEVC-based Dolby Vision derived from hvc1.
2475 Happens to match with an identifier
2476 previously utilized for DV. Thus, if we have
2477 the hvcC extradata box available as specified,
2478 set codec to HEVC */
2479 st->codecpar->codec_id = AV_CODEC_ID_HEVC;
2480
2481 133 return 0;
2482 }
2483
2484 2 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2485 {
2486 AVStream *st;
2487 uint8_t profile_level;
2488 int ret;
2489
2490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
2491 return 0;
2492 2 st = c->fc->streams[c->fc->nb_streams-1];
2493
2494
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)
2495 return AVERROR_INVALIDDATA;
2496
2497 2 profile_level = avio_r8(pb);
2498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((profile_level & 0xf0) != 0xc0)
2499 return 0;
2500
2501 2 avio_seek(pb, 6, SEEK_CUR);
2502 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
2503
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2504 return ret;
2505
2506 2 return 0;
2507 }
2508
2509 static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2510 {
2511 AVStream* st;
2512 MOVStreamContext* sc;
2513
2514 if (c->fc->nb_streams < 1)
2515 return 0;
2516
2517 /* For SBAS this should be fine - though beware if someone implements a
2518 * tref atom processor that doesn't drop down to default then this may
2519 * be lost. */
2520 if (atom.size > 4) {
2521 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2522 return AVERROR_PATCHWELCOME;
2523 }
2524
2525 st = c->fc->streams[c->fc->nb_streams - 1];
2526 sc = st->priv_data;
2527 sc->tref_id = avio_rb32(pb);
2528 sc->tref_flags |= MOV_TREF_FLAG_ENHANCEMENT;
2529
2530 return 0;
2531 }
2532
2533 /**
2534 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2535 * but can have extradata appended at the end after the 40 bytes belonging
2536 * to the struct.
2537 */
2538 static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2539 {
2540 AVStream *st;
2541 int ret;
2542
2543 if (c->fc->nb_streams < 1)
2544 return 0;
2545 if (atom.size <= 40)
2546 return 0;
2547 st = c->fc->streams[c->fc->nb_streams-1];
2548
2549 if ((uint64_t)atom.size > (1<<30))
2550 return AVERROR_INVALIDDATA;
2551
2552 avio_skip(pb, 40);
2553 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
2554 if (ret < 0)
2555 return ret;
2556
2557 return 0;
2558 }
2559
2560 597 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2561 {
2562 AVStream *st;
2563 MOVStreamContext *sc;
2564 unsigned int i, entries;
2565
2566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (c->trak_index < 0) {
2567 av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
2568 return 0;
2569 }
2570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (c->fc->nb_streams < 1)
2571 return 0;
2572 597 st = c->fc->streams[c->fc->nb_streams-1];
2573 597 sc = st->priv_data;
2574
2575 597 avio_r8(pb); /* version */
2576 597 avio_rb24(pb); /* flags */
2577
2578 // Clamp allocation size for `chunk_offsets` -- don't throw an error for an
2579 // invalid count since the EOF path doesn't throw either.
2580 597 entries = avio_rb32(pb);
2581 597 entries =
2582
2/2
✓ Branch 0 taken 592 times.
✓ Branch 1 taken 5 times.
597 FFMIN(entries,
2583 FFMAX(0, (atom.size - 8) /
2584 (atom.type == MKTAG('s', 't', 'c', 'o') ? 4 : 8)));
2585
2586
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 581 times.
597 if (!entries)
2587 16 return 0;
2588
2589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 581 times.
581 if (sc->chunk_offsets) {
2590 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2591 return 0;
2592 }
2593
2594 581 av_free(sc->chunk_offsets);
2595 581 sc->chunk_count = 0;
2596 581 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 581 times.
581 if (!sc->chunk_offsets)
2598 return AVERROR(ENOMEM);
2599 581 sc->chunk_count = entries;
2600
2601
2/2
✓ Branch 0 taken 577 times.
✓ Branch 1 taken 4 times.
581 if (atom.type == MKTAG('s','t','c','o'))
2602
3/4
✓ Branch 0 taken 42910 times.
✓ Branch 1 taken 577 times.
✓ Branch 2 taken 42910 times.
✗ Branch 3 not taken.
43487 for (i = 0; i < entries && !pb->eof_reached; i++)
2603 42910 sc->chunk_offsets[i] = avio_rb32(pb);
2604
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (atom.type == MKTAG('c','o','6','4'))
2605
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++) {
2606 136336 sc->chunk_offsets[i] = avio_rb64(pb);
2607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136336 times.
136336 if (sc->chunk_offsets[i] < 0) {
2608 av_log(c->fc, AV_LOG_WARNING, "Impossible chunk_offset\n");
2609 sc->chunk_offsets[i] = 0;
2610 }
2611 }
2612 else
2613 return AVERROR_INVALIDDATA;
2614
2615 581 sc->chunk_count = i;
2616
2617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 581 times.
581 if (pb->eof_reached) {
2618 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2619 return AVERROR_EOF;
2620 }
2621
2622 581 return 0;
2623 }
2624
2625 636 static int mov_codec_id(AVStream *st, uint32_t format)
2626 {
2627 636 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2628
2629
2/2
✓ Branch 0 taken 416 times.
✓ Branch 1 taken 220 times.
636 if (id <= 0 &&
2630
2/2
✓ Branch 0 taken 413 times.
✓ Branch 1 taken 3 times.
416 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2631
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 413 times.
413 (format & 0xFFFF) == 'T' + ('S' << 8)))
2632 3 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2633
2634
4/4
✓ Branch 0 taken 293 times.
✓ Branch 1 taken 343 times.
✓ Branch 2 taken 223 times.
✓ Branch 3 taken 70 times.
636 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2635 223 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2636
3/4
✓ Branch 0 taken 395 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 395 times.
✗ Branch 3 not taken.
413 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2637 /* skip old ASF MPEG-4 tag */
2638
2/2
✓ Branch 0 taken 391 times.
✓ Branch 1 taken 4 times.
395 format && format != MKTAG('m','p','4','s')) {
2639 391 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2640
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 336 times.
391 if (id <= 0)
2641 55 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2642
2/2
✓ Branch 0 taken 340 times.
✓ Branch 1 taken 51 times.
391 if (id > 0)
2643 340 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2644
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 47 times.
51 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2645
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2647 47 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2648
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6 times.
47 if (id <= 0) {
2649
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 2 times.
80 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2650
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 2 times.
80 AV_CODEC_ID_TTML : id;
2651 }
2652
2653
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 37 times.
47 if (id > 0)
2654 10 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2655 else
2656 37 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2657 }
2658 }
2659
2660 636 st->codecpar->codec_tag = format;
2661
2662 636 return id;
2663 }
2664
2665 315 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2666 AVStream *st, MOVStreamContext *sc)
2667 {
2668 315 uint8_t codec_name[32] = { 0 };
2669 int64_t stsd_start;
2670 unsigned int len;
2671 315 uint32_t id = 0;
2672
2673 /* The first 16 bytes of the video sample description are already
2674 * read in ff_mov_read_stsd_entries() */
2675 315 stsd_start = avio_tell(pb) - 16;
2676
2677 315 avio_rb16(pb); /* version */
2678 315 avio_rb16(pb); /* revision level */
2679 315 id = avio_rl32(pb); /* vendor */
2680 315 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2681 315 avio_rb32(pb); /* temporal quality */
2682 315 avio_rb32(pb); /* spatial quality */
2683
2684 315 st->codecpar->width = avio_rb16(pb); /* width */
2685 315 st->codecpar->height = avio_rb16(pb); /* height */
2686
2687 315 avio_rb32(pb); /* horiz resolution */
2688 315 avio_rb32(pb); /* vert resolution */
2689 315 avio_rb32(pb); /* data size, always 0 */
2690 315 avio_rb16(pb); /* frames per samples */
2691
2692 315 len = avio_r8(pb); /* codec name, pascal string */
2693
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 314 times.
315 if (len > 31)
2694 1 len = 31;
2695 315 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2696
2/2
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 3 times.
315 if (len < 31)
2697 312 avio_skip(pb, 31 - len);
2698
2699
2/2
✓ Branch 0 taken 253 times.
✓ Branch 1 taken 62 times.
315 if (codec_name[0])
2700 253 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2701
2702 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 315 times.
315 if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2704 st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2705 st->codecpar->width &= ~1;
2706 st->codecpar->height &= ~1;
2707 }
2708 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2709
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 315 times.
315 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2710 !strncmp(codec_name, "Sorenson H263", 13))
2711 st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2712
2713 315 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2714
2715 315 avio_seek(pb, stsd_start, SEEK_SET);
2716
2717
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 297 times.
315 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2718 18 st->codecpar->bits_per_coded_sample &= 0x1F;
2719 18 sc->has_palette = 1;
2720 }
2721 315 }
2722
2723 241 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2724 AVStream *st, MOVStreamContext *sc)
2725 {
2726 int bits_per_sample, flags;
2727 241 uint16_t version = avio_rb16(pb);
2728 241 uint32_t id = 0;
2729 241 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2730 int channel_count;
2731
2732 241 avio_rb16(pb); /* revision level */
2733 241 id = avio_rl32(pb); /* vendor */
2734 241 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2735
2736 241 channel_count = avio_rb16(pb);
2737
2738 241 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2739 241 st->codecpar->ch_layout.nb_channels = channel_count;
2740 241 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
2741 241 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
2742
2743 241 sc->audio_cid = avio_rb16(pb);
2744 241 avio_rb16(pb); /* packet size = 0 */
2745
2746 241 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
2747
2748 // Read QT version 1 fields. In version 0 these do not exist.
2749 241 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
2750
3/4
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 86 times.
✓ Branch 2 taken 155 times.
✗ Branch 3 not taken.
241 if (!c->isom ||
2751
1/2
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
155 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
2752
3/4
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 151 times.
155 (sc->stsd_version == 0 && version > 0)) {
2753
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 40 times.
90 if (version == 1) {
2754 50 sc->samples_per_frame = avio_rb32(pb);
2755 50 avio_rb32(pb); /* bytes per packet */
2756 50 sc->bytes_per_frame = avio_rb32(pb);
2757 50 avio_rb32(pb); /* bytes per sample */
2758
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
40 } else if (version == 2) {
2759 4 avio_rb32(pb); /* sizeof struct only */
2760 4 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
2761 4 channel_count = avio_rb32(pb);
2762 4 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2763 4 st->codecpar->ch_layout.nb_channels = channel_count;
2764 4 avio_rb32(pb); /* always 0x7F000000 */
2765 4 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
2766
2767 4 flags = avio_rb32(pb); /* lpcm format specific flag */
2768 4 sc->bytes_per_frame = avio_rb32(pb);
2769 4 sc->samples_per_frame = avio_rb32(pb);
2770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
2771 st->codecpar->codec_id =
2772 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
2773 flags);
2774 }
2775
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)) {
2776 /* can't correctly handle variable sized packet as audio unit */
2777
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 switch (st->codecpar->codec_id) {
2778 case AV_CODEC_ID_MP2:
2779 case AV_CODEC_ID_MP3:
2780 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
2781 break;
2782 }
2783 }
2784 }
2785
2786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (sc->format == 0) {
2787 if (st->codecpar->bits_per_coded_sample == 8)
2788 st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
2789 else if (st->codecpar->bits_per_coded_sample == 16)
2790 st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
2791 }
2792
2793
7/7
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 199 times.
241 switch (st->codecpar->codec_id) {
2794 7 case AV_CODEC_ID_PCM_S8:
2795 case AV_CODEC_ID_PCM_U8:
2796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
2797 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2798 7 break;
2799 19 case AV_CODEC_ID_PCM_S16LE:
2800 case AV_CODEC_ID_PCM_S16BE:
2801
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
19 if (st->codecpar->bits_per_coded_sample == 8)
2802 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
2803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 24)
2804 st->codecpar->codec_id =
2805 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2806 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
2807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 32)
2808 st->codecpar->codec_id =
2809 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2810 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
2811 19 break;
2812 /* set values for old format before stsd version 1 appeared */
2813 2 case AV_CODEC_ID_MACE3:
2814 2 sc->samples_per_frame = 6;
2815 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
2816 2 break;
2817 8 case AV_CODEC_ID_MACE6:
2818 8 sc->samples_per_frame = 6;
2819 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
2820 8 break;
2821 5 case AV_CODEC_ID_ADPCM_IMA_QT:
2822 5 sc->samples_per_frame = 64;
2823 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
2824 5 break;
2825 1 case AV_CODEC_ID_GSM:
2826 1 sc->samples_per_frame = 160;
2827 1 sc->bytes_per_frame = 33;
2828 1 break;
2829 199 default:
2830 199 break;
2831 }
2832
2833 241 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2834
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 193 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
241 if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->ch_layout.nb_channels <= INT_MAX) {
2835 48 st->codecpar->bits_per_coded_sample = bits_per_sample;
2836 48 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
2837 }
2838 241 }
2839
2840 11 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
2841 AVStream *st, MOVStreamContext *sc,
2842 int64_t size)
2843 {
2844 // ttxt stsd contains display flags, justification, background
2845 // color, fonts, and default styles, so fake an atom to read it
2846 11 MOVAtom fake_atom = { .size = size };
2847 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
2848 // in extradata unlike stpp MP4 TTML.
2849
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
2850
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
2851 9 mov_read_glbl(c, pb, fake_atom);
2852 11 st->codecpar->width = sc->width;
2853 11 st->codecpar->height = sc->height;
2854 11 }
2855
2856 41 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
2857 AVStream *st, MOVStreamContext *sc,
2858 int64_t size)
2859 {
2860 int ret;
2861
2862
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 22 times.
41 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
2863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if ((int)size != size)
2864 return AVERROR(ENOMEM);
2865
2866 19 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
2867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
2868 return ret;
2869
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (size > 16) {
2870 19 MOVStreamContext *tmcd_ctx = st->priv_data;
2871 int val;
2872 19 val = AV_RB32(st->codecpar->extradata + 4);
2873 19 tmcd_ctx->tmcd_flags = val;
2874 19 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
2875 19 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
2876 19 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
2877
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (size > 30) {
2878 4 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
2879 4 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
2880
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) {
2881 4 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
2882
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 &&
2883
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 st->codecpar->extradata[30] /* Don't add empty string */) {
2884 4 char *reel_name = av_malloc(str_size + 1);
2885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!reel_name)
2886 return AVERROR(ENOMEM);
2887 4 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
2888 4 reel_name[str_size] = 0; /* Add null terminator */
2889 4 av_dict_set(&st->metadata, "reel_name", reel_name,
2890 AV_DICT_DONT_STRDUP_VAL);
2891 }
2892 }
2893 }
2894 }
2895 } else {
2896 /* other codec type, just skip (rtp, mp4s ...) */
2897 22 avio_skip(pb, size);
2898 }
2899 41 return 0;
2900 }
2901
2902 597 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
2903 AVStream *st, MOVStreamContext *sc)
2904 {
2905 597 FFStream *const sti = ffstream(st);
2906
2907
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 356 times.
597 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
2908
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
241 !st->codecpar->sample_rate && sc->time_scale > 1)
2909 st->codecpar->sample_rate = sc->time_scale;
2910
2911 /* special codec parameters handling */
2912
7/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 15 times.
✓ Branch 6 taken 16 times.
✓ Branch 7 taken 10 times.
✓ Branch 8 taken 66 times.
✓ Branch 9 taken 478 times.
597 switch (st->codecpar->codec_id) {
2913 #if CONFIG_DV_DEMUXER
2914 case AV_CODEC_ID_DVAUDIO:
2915 if (c->dv_fctx) {
2916 avpriv_request_sample(c->fc, "multiple DV audio streams");
2917 return AVERROR(ENOSYS);
2918 }
2919
2920 c->dv_fctx = avformat_alloc_context();
2921 if (!c->dv_fctx) {
2922 av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
2923 return AVERROR(ENOMEM);
2924 }
2925 c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
2926 if (!c->dv_demux) {
2927 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
2928 return AVERROR(ENOMEM);
2929 }
2930 sc->dv_audio_container = 1;
2931 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2932 break;
2933 #endif
2934 /* no ifdef since parameters are always those */
2935 case AV_CODEC_ID_QCELP:
2936 av_channel_layout_uninit(&st->codecpar->ch_layout);
2937 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2938 // force sample rate for qcelp when not stored in mov
2939 if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
2940 st->codecpar->sample_rate = 8000;
2941 // FIXME: Why is the following needed for some files?
2942 sc->samples_per_frame = 160;
2943 if (!sc->bytes_per_frame)
2944 sc->bytes_per_frame = 35;
2945 break;
2946 case AV_CODEC_ID_AMR_NB:
2947 av_channel_layout_uninit(&st->codecpar->ch_layout);
2948 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2949 /* force sample rate for amr, stsd in 3gp does not store sample rate */
2950 st->codecpar->sample_rate = 8000;
2951 break;
2952 11 case AV_CODEC_ID_AMR_WB:
2953 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
2954 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2955 11 st->codecpar->sample_rate = 16000;
2956 11 break;
2957 1 case AV_CODEC_ID_MP2:
2958 case AV_CODEC_ID_MP3:
2959 /* force type after stsd for m1a hdlr */
2960 1 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2961 1 break;
2962 15 case AV_CODEC_ID_GSM:
2963 case AV_CODEC_ID_ADPCM_MS:
2964 case AV_CODEC_ID_ADPCM_IMA_WAV:
2965 case AV_CODEC_ID_ILBC:
2966 case AV_CODEC_ID_MACE3:
2967 case AV_CODEC_ID_MACE6:
2968 case AV_CODEC_ID_QDM2:
2969 15 st->codecpar->block_align = sc->bytes_per_frame;
2970 15 break;
2971 16 case AV_CODEC_ID_ALAC:
2972
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
2973 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
2974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
2975 av_channel_layout_uninit(&st->codecpar->ch_layout);
2976 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2977 st->codecpar->ch_layout.nb_channels = channel_count;
2978 }
2979 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
2980 }
2981 16 break;
2982 10 case AV_CODEC_ID_AC3:
2983 case AV_CODEC_ID_EAC3:
2984 case AV_CODEC_ID_MPEG1VIDEO:
2985 case AV_CODEC_ID_VC1:
2986 case AV_CODEC_ID_VP8:
2987 case AV_CODEC_ID_VP9:
2988 10 sti->need_parsing = AVSTREAM_PARSE_FULL;
2989 10 break;
2990 66 case AV_CODEC_ID_EVC:
2991 case AV_CODEC_ID_AV1:
2992 /* field_order detection of H264 requires parsing */
2993 case AV_CODEC_ID_H264:
2994 66 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
2995 66 break;
2996 478 default:
2997 478 break;
2998 }
2999 597 return 0;
3000 }
3001
3002 608 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
3003 int codec_tag, int format,
3004 int64_t size)
3005 {
3006
3/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 597 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
608 if (codec_tag &&
3007 (codec_tag != format &&
3008 // AVID 1:1 samples with differing data format and codec tag exist
3009 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
3010 // prores is allowed to have differing data format and codec tag
3011 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
3012 // so is dv (sigh)
3013 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
3014 (c->fc->video_codec_id ? ff_codec_get_id(ff_codec_movvideo_tags, format) != c->fc->video_codec_id
3015 : codec_tag != MKTAG('j','p','e','g')))) {
3016 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3017 * export it as a separate AVStream but this needs a few changes
3018 * in the MOV demuxer, patch welcome. */
3019
3020 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3021 avio_skip(pb, size);
3022 return 1;
3023 }
3024
3025 608 return 0;
3026 }
3027
3028 597 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3029 {
3030 AVStream *st;
3031 MOVStreamContext *sc;
3032 int pseudo_stream_id;
3033
3034
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 av_assert0 (c->fc->nb_streams >= 1);
3035 597 st = c->fc->streams[c->fc->nb_streams-1];
3036 597 sc = st->priv_data;
3037
3038 597 for (pseudo_stream_id = 0;
3039
3/4
✓ Branch 0 taken 608 times.
✓ Branch 1 taken 597 times.
✓ Branch 2 taken 608 times.
✗ Branch 3 not taken.
1205 pseudo_stream_id < entries && !pb->eof_reached;
3040 608 pseudo_stream_id++) {
3041 //Parsing Sample description table
3042 enum AVCodecID id;
3043 608 int ret, dref_id = 1;
3044 608 MOVAtom a = { AV_RL32("stsd") };
3045 608 int64_t start_pos = avio_tell(pb);
3046 608 int64_t size = avio_rb32(pb); /* size */
3047 608 uint32_t format = avio_rl32(pb); /* data format */
3048
3049
1/2
✓ Branch 0 taken 608 times.
✗ Branch 1 not taken.
608 if (size >= 16) {
3050 608 avio_rb32(pb); /* reserved */
3051 608 avio_rb16(pb); /* reserved */
3052 608 dref_id = avio_rb16(pb);
3053 } else if (size <= 7) {
3054 av_log(c->fc, AV_LOG_ERROR,
3055 "invalid size %"PRId64" in stsd\n", size);
3056 return AVERROR_INVALIDDATA;
3057 }
3058
3059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3060 608 size - (avio_tell(pb) - start_pos))) {
3061 sc->stsd_count++;
3062 continue;
3063 }
3064
3065
2/2
✓ Branch 0 taken 597 times.
✓ Branch 1 taken 11 times.
608 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
3066 608 sc->dref_id= dref_id;
3067 608 sc->format = format;
3068
3069 608 id = mov_codec_id(st, format);
3070
3071 608 av_log(c->fc, AV_LOG_TRACE,
3072 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3073 608 av_fourcc2str(format), st->codecpar->codec_type);
3074
3075 608 st->codecpar->codec_id = id;
3076
2/2
✓ Branch 0 taken 315 times.
✓ Branch 1 taken 293 times.
608 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3077 315 mov_parse_stsd_video(c, pb, st, sc);
3078
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 52 times.
293 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3079 241 mov_parse_stsd_audio(c, pb, st, sc);
3080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (st->codecpar->sample_rate < 0) {
3081 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3082 return AVERROR_INVALIDDATA;
3083 }
3084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (st->codecpar->ch_layout.nb_channels < 0) {
3085 av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3086 return AVERROR_INVALIDDATA;
3087 }
3088
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 41 times.
52 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3089 11 mov_parse_stsd_subtitle(c, pb, st, sc,
3090 11 size - (avio_tell(pb) - start_pos));
3091 } else {
3092 41 ret = mov_parse_stsd_data(c, pb, st, sc,
3093 41 size - (avio_tell(pb) - start_pos));
3094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ret < 0)
3095 return ret;
3096 }
3097 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3098 608 a.size = size - (avio_tell(pb) - start_pos);
3099
2/2
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 131 times.
608 if (a.size > 8) {
3100
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 477 times.
477 if ((ret = mov_read_default(c, pb, a)) < 0)
3101 return ret;
3102
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 130 times.
131 } else if (a.size > 0)
3103 1 avio_skip(pb, a.size);
3104
3105
3/4
✓ Branch 0 taken 608 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 341 times.
✓ Branch 3 taken 267 times.
608 if (sc->extradata && st->codecpar->extradata) {
3106 341 int extra_size = st->codecpar->extradata_size;
3107
3108 /* Move the current stream extradata to the stream context one. */
3109 341 sc->extradata_size[pseudo_stream_id] = extra_size;
3110 341 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3111 341 st->codecpar->extradata = NULL;
3112 341 st->codecpar->extradata_size = 0;
3113 }
3114 608 sc->stsd_count++;
3115 }
3116
3117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (pb->eof_reached) {
3118 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3119 return AVERROR_EOF;
3120 }
3121
3122 597 return 0;
3123 }
3124
3125 597 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3126 {
3127 AVStream *st;
3128 MOVStreamContext *sc;
3129 int ret, entries;
3130
3131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (c->fc->nb_streams < 1)
3132 return 0;
3133 597 st = c->fc->streams[c->fc->nb_streams - 1];
3134 597 sc = st->priv_data;
3135
3136 597 sc->stsd_version = avio_r8(pb);
3137 597 avio_rb24(pb); /* flags */
3138 597 entries = avio_rb32(pb);
3139
3140 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3141
3/6
✓ Branch 0 taken 597 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 597 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 597 times.
597 if (entries <= 0 || entries > atom.size / 8 || entries > 1024) {
3142 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3143 return AVERROR_INVALIDDATA;
3144 }
3145
3146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (sc->extradata) {
3147 av_log(c->fc, AV_LOG_ERROR,
3148 "Duplicate stsd found in this track.\n");
3149 return AVERROR_INVALIDDATA;
3150 }
3151
3152 /* Prepare space for hosting multiple extradata. */
3153 597 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (!sc->extradata)
3155 return AVERROR(ENOMEM);
3156
3157 597 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (!sc->extradata_size) {
3159 ret = AVERROR(ENOMEM);
3160 goto fail;
3161 }
3162
3163 597 ret = ff_mov_read_stsd_entries(c, pb, entries);
3164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (ret < 0)
3165 goto fail;
3166
3167 /* Restore back the primary extradata. */
3168 597 av_freep(&st->codecpar->extradata);
3169 597 st->codecpar->extradata_size = sc->extradata_size[0];
3170
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 266 times.
597 if (sc->extradata_size[0]) {
3171 331 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 331 times.
331 if (!st->codecpar->extradata)
3173 return AVERROR(ENOMEM);
3174 331 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3175 }
3176
3177 597 return mov_finalize_stsd_codec(c, pb, st, sc);
3178 fail:
3179 if (sc->extradata) {
3180 int j;
3181 for (j = 0; j < sc->stsd_count; j++)
3182 av_freep(&sc->extradata[j]);
3183 }
3184
3185 av_freep(&sc->extradata);
3186 av_freep(&sc->extradata_size);
3187 return ret;
3188 }
3189
3190 597 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3191 {
3192 AVStream *st;
3193 MOVStreamContext *sc;
3194 unsigned int i, entries;
3195
3196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (c->trak_index < 0) {
3197 av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3198 return 0;
3199 }
3200
3201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (c->fc->nb_streams < 1)
3202 return 0;
3203 597 st = c->fc->streams[c->fc->nb_streams-1];
3204 597 sc = st->priv_data;
3205
3206 597 avio_r8(pb); /* version */
3207 597 avio_rb24(pb); /* flags */
3208
3209 597 entries = avio_rb32(pb);
3210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if ((uint64_t)entries * 12 + 4 > atom.size)
3211 return AVERROR_INVALIDDATA;
3212
3213 597 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3214
3215
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 582 times.
597 if (!entries)
3216 15 return 0;
3217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 582 times.
582 if (sc->stsc_data) {
3218 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3219 return 0;
3220 }
3221 582 av_free(sc->stsc_data);
3222 582 sc->stsc_count = 0;
3223 582 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 582 times.
582 if (!sc->stsc_data)
3225 return AVERROR(ENOMEM);
3226
3227
3/4
✓ Branch 0 taken 3782 times.
✓ Branch 1 taken 582 times.
✓ Branch 2 taken 3782 times.
✗ Branch 3 not taken.
4364 for (i = 0; i < entries && !pb->eof_reached; i++) {
3228 3782 sc->stsc_data[i].first = avio_rb32(pb);
3229 3782 sc->stsc_data[i].count = avio_rb32(pb);
3230 3782 sc->stsc_data[i].id = avio_rb32(pb);
3231 }
3232
3233 582 sc->stsc_count = i;
3234
2/2
✓ Branch 0 taken 3782 times.
✓ Branch 1 taken 582 times.
4364 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3235 3782 int64_t first_min = i + 1;
3236
5/6
✓ Branch 0 taken 3200 times.
✓ Branch 1 taken 582 times.
✓ Branch 2 taken 3200 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3200 times.
✓ Branch 5 taken 582 times.
3782 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
3237
1/2
✓ Branch 0 taken 3200 times.
✗ Branch 1 not taken.
3200 (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) ||
3238
1/2
✓ Branch 0 taken 3782 times.
✗ Branch 1 not taken.
3782 sc->stsc_data[i].first < first_min ||
3239
1/2
✓ Branch 0 taken 3782 times.
✗ Branch 1 not taken.
3782 sc->stsc_data[i].count < 1 ||
3240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3782 times.
3782 sc->stsc_data[i].id < 1) {
3241 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);
3242 if (i+1 >= sc->stsc_count) {
3243 if (sc->stsc_data[i].count == 0 && i > 0) {
3244 sc->stsc_count --;
3245 continue;
3246 }
3247 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3248 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3249 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3250 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3251 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3252 continue;
3253 }
3254 av_assert0(sc->stsc_data[i+1].first >= 2);
3255 // We replace this entry by the next valid
3256 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3257 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3258 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3259 }
3260 }
3261
3262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 582 times.
582 if (pb->eof_reached) {
3263 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3264 return AVERROR_EOF;
3265 }
3266
3267 582 return 0;
3268 }
3269
3270 340685 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3271 {
3272 340685 return index < count - 1;
3273 }
3274
3275 /* Compute the samples value for the stsc entry at the given index. */
3276 55533 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3277 {
3278 int chunk_count;
3279
3280
2/2
✓ Branch 1 taken 55337 times.
✓ Branch 2 taken 196 times.
55533 if (mov_stsc_index_valid(index, sc->stsc_count))
3281 55337 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3282 else {
3283 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3285 196 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3286 }
3287
3288 55533 return sc->stsc_data[index].count * (int64_t)chunk_count;
3289 }
3290
3291 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3292 {
3293 AVStream *st;
3294 MOVStreamContext *sc;
3295 unsigned i, entries;
3296
3297 if (c->trak_index < 0) {
3298 av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3299 return 0;
3300 }
3301
3302 if (c->fc->nb_streams < 1)
3303 return 0;
3304 st = c->fc->streams[c->fc->nb_streams-1];
3305 sc = st->priv_data;
3306
3307 avio_rb32(pb); // version + flags
3308
3309 entries = avio_rb32(pb);
3310 if (sc->stps_data)
3311 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3312 av_free(sc->stps_data);
3313 sc->stps_count = 0;
3314 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3315 if (!sc->stps_data)
3316 return AVERROR(ENOMEM);
3317
3318 for (i = 0; i < entries && !pb->eof_reached; i++) {
3319 sc->stps_data[i] = avio_rb32(pb);
3320 }
3321
3322 sc->stps_count = i;
3323
3324 if (pb->eof_reached) {
3325 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3326 return AVERROR_EOF;
3327 }
3328
3329 return 0;
3330 }
3331
3332 144 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3333 {
3334 AVStream *st;
3335 FFStream *sti;
3336 MOVStreamContext *sc;
3337 unsigned int i, entries;
3338
3339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (c->trak_index < 0) {
3340 av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3341 return 0;
3342 }
3343
3344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (c->fc->nb_streams < 1)
3345 return 0;
3346 144 st = c->fc->streams[c->fc->nb_streams-1];
3347 144 sti = ffstream(st);
3348 144 sc = st->priv_data;
3349
3350 144 avio_r8(pb); /* version */
3351 144 avio_rb24(pb); /* flags */
3352
3353 144 entries = avio_rb32(pb);
3354
3355 144 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3356
3357
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 138 times.
144 if (!entries) {
3358 6 sc->keyframe_absent = 1;
3359
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)
3360 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3361 6 return 0;
3362 }
3363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (sc->keyframes)
3364 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (entries >= UINT_MAX / sizeof(int))
3366 return AVERROR_INVALIDDATA;
3367 138 av_freep(&sc->keyframes);
3368 138 sc->keyframe_count = 0;
3369 138 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (!sc->keyframes)
3371 return AVERROR(ENOMEM);
3372
3373
3/4
✓ Branch 0 taken 5706 times.
✓ Branch 1 taken 138 times.
✓ Branch 2 taken 5706 times.
✗ Branch 3 not taken.
5844 for (i = 0; i < entries && !pb->eof_reached; i++) {
3374 5706 sc->keyframes[i] = avio_rb32(pb);
3375 }
3376
3377 138 sc->keyframe_count = i;
3378
3379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (pb->eof_reached) {
3380 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3381 return AVERROR_EOF;
3382 }
3383
3384 138 return 0;
3385 }
3386
3387 597 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3388 {
3389 AVStream *st;
3390 MOVStreamContext *sc;
3391 unsigned int i, entries, sample_size, field_size, num_bytes;
3392 GetBitContext gb;
3393 unsigned char* buf;
3394 int ret;
3395
3396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (c->trak_index < 0) {
3397 av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3398 return 0;
3399 }
3400
3401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (c->fc->nb_streams < 1)
3402 return 0;
3403 597 st = c->fc->streams[c->fc->nb_streams-1];
3404 597 sc = st->priv_data;
3405
3406 597 avio_r8(pb); /* version */
3407 597 avio_rb24(pb); /* flags */
3408
3409
1/2
✓ Branch 0 taken 597 times.
✗ Branch 1 not taken.
597 if (atom.type == MKTAG('s','t','s','z')) {
3410 597 sample_size = avio_rb32(pb);
3411
2/2
✓ Branch 0 taken 556 times.
✓ Branch 1 taken 41 times.
597 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3412 556 sc->sample_size = sample_size;
3413 597 sc->stsz_sample_size = sample_size;
3414 597 field_size = 32;
3415 } else {
3416 sample_size = 0;
3417 avio_rb24(pb); /* reserved */
3418 field_size = avio_r8(pb);
3419 }
3420 597 entries = avio_rb32(pb);
3421
3422 597 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3423
3424 597 sc->sample_count = entries;
3425
2/2
✓ Branch 0 taken 201 times.
✓ Branch 1 taken 396 times.
597 if (sample_size)
3426 201 return 0;
3427
3428
4/8
✓ Branch 0 taken 396 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 396 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 396 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 396 times.
396 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
3429 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3430 return AVERROR_INVALIDDATA;
3431 }
3432
3433
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 380 times.
396 if (!entries)
3434 16 return 0;
3435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (entries >= (INT_MAX - 4 - 8 * AV_INPUT_BUFFER_PADDING_SIZE) / field_size)
3436 return AVERROR_INVALIDDATA;
3437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (sc->sample_sizes)
3438 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3439 380 av_free(sc->sample_sizes);
3440 380 sc->sample_count = 0;
3441 380 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (!sc->sample_sizes)
3443 return AVERROR(ENOMEM);
3444
3445 380 num_bytes = (entries*field_size+4)>>3;
3446
3447 380 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3448
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (!buf) {
3449 av_freep(&sc->sample_sizes);
3450 return AVERROR(ENOMEM);
3451 }
3452
3453 380 ret = ffio_read_size(pb, buf, num_bytes);
3454
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (ret < 0) {
3455 av_freep(&sc->sample_sizes);
3456 av_free(buf);
3457 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3458 return 0;
3459 }
3460
3461 380 init_get_bits(&gb, buf, 8*num_bytes);
3462
3463
2/2
✓ Branch 0 taken 226883 times.
✓ Branch 1 taken 380 times.
227263 for (i = 0; i < entries; i++) {
3464 226883 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 226883 times.
226883 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3466 av_free(buf);
3467 av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3468 return AVERROR_INVALIDDATA;
3469 }
3470 226883 sc->data_size += sc->sample_sizes[i];
3471 }
3472
3473 380 sc->sample_count = i;
3474
3475 380 av_free(buf);
3476
3477 380 return 0;
3478 }
3479
3480 597 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3481 {
3482 AVStream *st;
3483 MOVStreamContext *sc;
3484 unsigned int i, entries;
3485 597 int64_t duration = 0;
3486 597 int64_t total_sample_count = 0;
3487 597 int64_t current_dts = 0;
3488 597 int64_t corrected_dts = 0;
3489
3490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (c->trak_index < 0) {
3491 av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3492 return 0;
3493 }
3494
3495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (c->fc->nb_streams < 1)
3496 return 0;
3497 597 st = c->fc->streams[c->fc->nb_streams-1];
3498 597 sc = st->priv_data;
3499
3500 597 avio_r8(pb); /* version */
3501 597 avio_rb24(pb); /* flags */
3502 597 entries = avio_rb32(pb);
3503
3504 597 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3505 597 c->fc->nb_streams-1, entries);
3506
3507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (sc->stts_data)
3508 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3509 597 av_freep(&sc->stts_data);
3510 597 sc->stts_count = 0;
3511
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3512 return AVERROR(ENOMEM);
3513
3514
3/4
✓ Branch 0 taken 2944 times.
✓ Branch 1 taken 597 times.
✓ Branch 2 taken 2944 times.
✗ Branch 3 not taken.
3541 for (i = 0; i < entries && !pb->eof_reached; i++) {
3515 unsigned int sample_duration;
3516 unsigned int sample_count;
3517 2944 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3518 2944 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3519 min_entries * sizeof(*sc->stts_data));
3520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2944 times.
2944 if (!stts_data) {
3521 av_freep(&sc->stts_data);
3522 sc->stts_count = 0;
3523 return AVERROR(ENOMEM);
3524 }
3525 2944 sc->stts_count = min_entries;
3526 2944 sc->stts_data = stts_data;
3527
3528 2944 sample_count = avio_rb32(pb);
3529 2944 sample_duration = avio_rb32(pb);
3530
3531 2944 sc->stts_data[i].count= sample_count;
3532 2944 sc->stts_data[i].duration= sample_duration;
3533
3534 2944 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3535 sample_count, sample_duration);
3536
3537 /* STTS sample offsets are uint32 but some files store it as int32
3538 * with negative values used to correct DTS delays.
3539 There may be abnormally large values as well. */
3540
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2943 times.
2944 if (sample_duration > c->max_stts_delta) {
3541 // assume high delta is a correction if negative when cast as int32
3542 1 int32_t delta_magnitude = (int32_t)sample_duration;
3543 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",
3544 sample_duration, i, sample_count, st->index);
3545 1 sc->stts_data[i].duration = 1;
3546
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);
3547 } else {
3548 2943 corrected_dts += sample_duration * (uint64_t)sample_count;
3549 }
3550
3551 2944 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3552
3553
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2922 times.
2944 if (current_dts > corrected_dts) {
3554 22 int64_t drift = av_sat_sub64(current_dts, corrected_dts) / FFMAX(sample_count, 1);
3555
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;
3556 22 current_dts -= correction * (uint64_t)sample_count;
3557 22 sc->stts_data[i].duration -= correction;
3558 }
3559
3560 2944 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3561 2944 total_sample_count+=sc->stts_data[i].count;
3562 }
3563
3564 597 sc->stts_count = i;
3565
3566
2/2
✓ Branch 0 taken 581 times.
✓ Branch 1 taken 16 times.
597 if (duration > 0 &&
3567
1/2
✓ Branch 0 taken 581 times.
✗ Branch 1 not taken.
581 duration <= INT64_MAX - sc->duration_for_fps &&
3568
1/2
✓ Branch 0 taken 581 times.
✗ Branch 1 not taken.
581 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3569 581 sc->duration_for_fps += duration;
3570 581 sc->nb_frames_for_fps += total_sample_count;
3571 }
3572
3573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (pb->eof_reached) {
3574 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3575 return AVERROR_EOF;
3576 }
3577
3578 597 st->nb_frames= total_sample_count;
3579
2/2
✓ Branch 0 taken 581 times.
✓ Branch 1 taken 16 times.
597 if (duration)
3580 581 st->duration= FFMIN(st->duration, duration);
3581
3582 // All samples have zero duration. They have higher chance be chose by
3583 // mov_find_next_sample, which leads to seek again and again.
3584 //
3585 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3586 // So only mark data stream as discarded for safety.
3587
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 581 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
597 if (!duration && sc->stts_count &&
3588 st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3589 av_log(c->fc, AV_LOG_WARNING,
3590 "All samples in data stream index:id [%d:%d] have zero "
3591 "duration, stream set to be discarded by default. Override "
3592 "using AVStream->discard or -discard for ffmpeg command.\n",
3593 st->index, sc->id);
3594 st->discard = AVDISCARD_ALL;
3595 }
3596 597 sc->track_end = duration;
3597 597 return 0;
3598 }
3599
3600 44 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3601 {
3602 AVStream *st;
3603 MOVStreamContext *sc;
3604 int64_t i, entries;
3605
3606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (c->fc->nb_streams < 1)
3607 return 0;
3608 44 st = c->fc->streams[c->fc->nb_streams - 1];
3609 44 sc = st->priv_data;
3610
3611 44 avio_r8(pb); /* version */
3612 44 avio_rb24(pb); /* flags */
3613 44 entries = atom.size - 4;
3614
3615 44 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3616 44 c->fc->nb_streams - 1, entries);
3617
3618
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 36 times.
44 if (sc->sdtp_data)
3619 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3620 44 av_freep(&sc->sdtp_data);
3621 44 sc->sdtp_count = 0;
3622
3623 44 sc->sdtp_data = av_malloc(entries);
3624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (!sc->sdtp_data)
3625 return AVERROR(ENOMEM);
3626
3627
3/4
✓ Branch 0 taken 3807 times.
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 3807 times.
✗ Branch 3 not taken.
3851 for (i = 0; i < entries && !pb->eof_reached; i++)
3628 3807 sc->sdtp_data[i] = avio_r8(pb);
3629 44 sc->sdtp_count = i;
3630
3631 44 return 0;
3632 }
3633
3634 10827 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3635 {
3636
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 9691 times.
10827 if (duration < 0) {
3637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3638 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3639 duration++;
3640 }
3641 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3642 }
3643 10827 }
3644
3645 63 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3646 {
3647 AVStream *st;
3648 MOVStreamContext *sc;
3649 63 unsigned int i, entries, ctts_count = 0;
3650
3651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->trak_index < 0) {
3652 av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
3653 return 0;
3654 }
3655
3656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->fc->nb_streams < 1)
3657 return 0;
3658 63 st = c->fc->streams[c->fc->nb_streams-1];
3659 63 sc = st->priv_data;
3660
3661 63 avio_r8(pb); /* version */
3662 63 avio_rb24(pb); /* flags */
3663 63 entries = avio_rb32(pb);
3664
3665 63 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3666
3667
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 59 times.
63 if (!entries)
3668 4 return 0;
3669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
3670 return AVERROR_INVALIDDATA;
3671 59 av_freep(&sc->ctts_data);
3672 59 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
3673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->ctts_data)
3674 return AVERROR(ENOMEM);
3675
3676
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++) {
3677 MOVCtts *ctts_data;
3678 4874 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
3679 4874 const size_t requested_size =
3680 4874 min_size_needed > sc->ctts_allocated_size ?
3681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
3682 min_size_needed;
3683 4874 int count = avio_rb32(pb);
3684 4874 int duration = avio_rb32(pb);
3685
3686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (count <= 0) {
3687 av_log(c->fc, AV_LOG_TRACE,
3688 "ignoring CTTS entry with count=%d duration=%d\n",
3689 count, duration);
3690 continue;
3691 }
3692
3693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
3694 return AVERROR(ENOMEM);
3695
3696 4874 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
3697
3698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (!ctts_data)
3699 return AVERROR(ENOMEM);
3700
3701 4874 sc->ctts_data = ctts_data;
3702
3703 4874 ctts_data[ctts_count].count = count;
3704 4874 ctts_data[ctts_count].offset = duration;
3705 4874 ctts_count++;
3706
3707 4874 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
3708 count, duration);
3709
3710
2/2
✓ Branch 0 taken 4761 times.
✓ Branch 1 taken 113 times.
4874 if (i+2<entries)
3711 4761 mov_update_dts_shift(sc, duration, c->fc);
3712 }
3713
3714 59 sc->ctts_count = ctts_count;
3715
3716
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (pb->eof_reached) {
3717 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
3718 return AVERROR_EOF;
3719 }
3720
3721 59 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
3722
3723 59 return 0;
3724 }
3725
3726 28 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3727 {
3728 AVStream *st;
3729 MOVStreamContext *sc;
3730 uint8_t version;
3731 uint32_t grouping_type;
3732 uint32_t default_length;
3733 av_unused uint32_t default_group_description_index;
3734 uint32_t entry_count;
3735
3736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (c->fc->nb_streams < 1)
3737 return 0;
3738 28 st = c->fc->streams[c->fc->nb_streams - 1];
3739 28 sc = st->priv_data;
3740
3741 28 version = avio_r8(pb); /* version */
3742 28 avio_rb24(pb); /* flags */
3743 28 grouping_type = avio_rl32(pb);
3744
3745 /*
3746 * This function only supports "sync" boxes, but the code is able to parse
3747 * other boxes (such as "tscl", "tsas" and "stsa")
3748 */
3749
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 5 times.
28 if (grouping_type != MKTAG('s','y','n','c'))
3750 23 return 0;
3751
3752
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
3753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
3754 5 entry_count = avio_rb32(pb);
3755
3756 5 av_freep(&sc->sgpd_sync);
3757 5 sc->sgpd_sync_count = entry_count;
3758 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
3759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
3760 return AVERROR(ENOMEM);
3761
3762
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++) {
3763 8 uint32_t description_length = default_length;
3764
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)
3765 description_length = avio_rb32(pb);
3766
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
3767 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
3768 8 sc->sgpd_sync[i] = nal_unit_type;
3769 8 description_length -= 1;
3770 }
3771 8 avio_skip(pb, description_length);
3772 }
3773
3774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
3775 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
3776 return AVERROR_EOF;
3777 }
3778
3779 5 return 0;
3780 }
3781
3782 25 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3783 {
3784 AVStream *st;
3785 MOVStreamContext *sc;
3786 unsigned int i, entries;
3787 uint8_t version;
3788 uint32_t grouping_type;
3789 MOVSbgp *table, **tablep;
3790 int *table_count;
3791
3792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (c->fc->nb_streams < 1)
3793 return 0;
3794 25 st = c->fc->streams[c->fc->nb_streams-1];
3795 25 sc = st->priv_data;
3796
3797 25 version = avio_r8(pb); /* version */
3798 25 avio_rb24(pb); /* flags */
3799 25 grouping_type = avio_rl32(pb);
3800
3801
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 24 times.
25 if (grouping_type == MKTAG('r','a','p',' ')) {
3802 1 tablep = &sc->rap_group;
3803 1 table_count = &sc->rap_group_count;
3804
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19 times.
24 } else if (grouping_type == MKTAG('s','y','n','c')) {
3805 5 tablep = &sc->sync_group;
3806 5 table_count = &sc->sync_group_count;
3807 } else {
3808 19 return 0;
3809 }
3810
3811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
3812 avio_rb32(pb); /* grouping_type_parameter */
3813
3814 6 entries = avio_rb32(pb);
3815
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
3816 return 0;
3817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
3818 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
3819 6 av_freep(tablep);
3820 6 table = av_malloc_array(entries, sizeof(*table));
3821
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
3822 return AVERROR(ENOMEM);
3823 6 *tablep = table;
3824
3825
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++) {
3826 32 table[i].count = avio_rb32(pb); /* sample_count */
3827 32 table[i].index = avio_rb32(pb); /* group_description_index */
3828 }
3829
3830 6 *table_count = i;
3831
3832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
3833 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
3834 return AVERROR_EOF;
3835 }
3836
3837 6 return 0;
3838 }
3839
3840 /**
3841 * Get ith edit list entry (media time, duration).
3842 */
3843 907 static int get_edit_list_entry(MOVContext *mov,
3844 const MOVStreamContext *msc,
3845 unsigned int edit_list_index,
3846 int64_t *edit_list_media_time,
3847 int64_t *edit_list_duration,
3848 int64_t global_timescale)
3849 {
3850
2/2
✓ Branch 0 taken 440 times.
✓ Branch 1 taken 467 times.
907 if (edit_list_index == msc->elst_count) {
3851 440 return 0;
3852 }
3853 467 *edit_list_media_time = msc->elst_data[edit_list_index].time;
3854 467 *edit_list_duration = msc->elst_data[edit_list_index].duration;
3855
3856 /* duration is in global timescale units;convert to msc timescale */
3857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 467 times.
467 if (global_timescale == 0) {
3858 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
3859 return 0;
3860 }
3861 467 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
3862 global_timescale);
3863
3864
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 467 times.
467 if (*edit_list_duration + (uint64_t)*edit_list_media_time > INT64_MAX)
3865 *edit_list_duration = 0;
3866
3867 467 return 1;
3868 }
3869
3870 /**
3871 * Find the closest previous frame to the timestamp_pts, in e_old index
3872 * entries. Searching for just any frame / just key frames can be controlled by
3873 * last argument 'flag'.
3874 * Note that if ctts_data is not NULL, we will always search for a key frame
3875 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
3876 * return the first frame of the video.
3877 *
3878 * Here the timestamp_pts is considered to be a presentation timestamp and
3879 * the timestamp of index entries are considered to be decoding timestamps.
3880 *
3881 * Returns 0 if successful in finding a frame, else returns -1.
3882 * Places the found index corresponding output arg.
3883 *
3884 * If ctts_old is not NULL, then refines the searched entry by searching
3885 * backwards from the found timestamp, to find the frame with correct PTS.
3886 *
3887 * Places the found ctts_index and ctts_sample in corresponding output args.
3888 */
3889 466 static int find_prev_closest_index(AVStream *st,
3890 AVIndexEntry *e_old,
3891 int nb_old,
3892 MOVTimeToSample *tts_data,
3893 int64_t tts_count,
3894 int64_t timestamp_pts,
3895 int flag,
3896 int64_t* index,
3897 int64_t* tts_index,
3898 int64_t* tts_sample)
3899 {
3900 466 MOVStreamContext *msc = st->priv_data;
3901 466 FFStream *const sti = ffstream(st);
3902 466 AVIndexEntry *e_keep = sti->index_entries;
3903 466 int nb_keep = sti->nb_index_entries;
3904 466 int64_t i = 0;
3905
3906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 466 times.
466 av_assert0(index);
3907
3908 // If dts_shift > 0, then all the index timestamps will have to be offset by
3909 // at least dts_shift amount to obtain PTS.
3910 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
3911
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 457 times.
466 if (msc->dts_shift > 0) {
3912 9 timestamp_pts -= msc->dts_shift;
3913 }
3914
3915 466 sti->index_entries = e_old;
3916 466 sti->nb_index_entries = nb_old;
3917 466 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
3918
3919 // Keep going backwards in the index entries until the timestamp is the same.
3920
2/2
✓ Branch 0 taken 465 times.
✓ Branch 1 taken 1 times.
466 if (*index >= 0) {
3921
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 441 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
465 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
3922 i--) {
3923 if ((flag & AVSEEK_FLAG_ANY) ||
3924 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
3925 *index = i - 1;
3926 }
3927 }
3928 }
3929
3930 // If we have CTTS then refine the search, by searching backwards over PTS
3931 // computed by adding corresponding CTTS durations to index timestamps.
3932
4/4
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 402 times.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 1 times.
466 if (msc->ctts_count && *index >= 0) {
3933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(tts_index);
3934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(tts_sample);
3935 // Find out the ctts_index for the found frame.
3936 63 *tts_index = 0;
3937 63 *tts_sample = 0;
3938
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++) {
3939
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (*tts_index < tts_count) {
3940 175 (*tts_sample)++;
3941
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (tts_data[*tts_index].count == *tts_sample) {
3942 175 (*tts_index)++;
3943 175 *tts_sample = 0;
3944 }
3945 }
3946 }
3947
3948
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) {
3949 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
3950 // No need to add dts_shift to the timestamp here becase timestamp_pts has already been
3951 // compensated by dts_shift above.
3952
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 &&
3953
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 4 times.
62 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
3954 58 break;
3955 }
3956
3957 12 (*index)--;
3958
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (*tts_sample == 0) {
3959 12 (*tts_index)--;
3960
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 if (*tts_index >= 0)
3961 7 *tts_sample = tts_data[*tts_index].count - 1;
3962 } else {
3963 (*tts_sample)--;
3964 }
3965 }
3966 }
3967
3968 /* restore AVStream state*/
3969 466 sti->index_entries = e_keep;
3970 466 sti->nb_index_entries = nb_keep;
3971
2/2
✓ Branch 0 taken 460 times.
✓ Branch 1 taken 6 times.
466 return *index >= 0 ? 0 : -1;
3972 }
3973
3974 /**
3975 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
3976 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
3977 *
3978 * This function is similar to ff_add_index_entry in libavformat/utils.c
3979 * except that here we are always unconditionally adding an index entry to
3980 * the end, instead of searching the entries list and skipping the add if
3981 * there is an existing entry with the same timestamp.
3982 * This is needed because the mov_fix_index calls this func with the same
3983 * unincremented timestamp for successive discarded frames.
3984 */
3985 348550 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
3986 int size, int distance, int flags)
3987 {
3988 348550 FFStream *const sti = ffstream(st);
3989 AVIndexEntry *entries, *ie;
3990 348550 int64_t index = -1;
3991 348550 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
3992
3993 // Double the allocation each time, to lower memory fragmentation.
3994 // Another difference from ff_add_index_entry function.
3995 348550 const size_t requested_size =
3996 348550 min_size_needed > sti->index_entries_allocated_size ?
3997
2/2
✓ Branch 0 taken 1976 times.
✓ Branch 1 taken 346574 times.
348550 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
3998 min_size_needed;
3999
4000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348550 times.
348550 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
4001 return -1;
4002
4003 348550 entries = av_fast_realloc(sti->index_entries,
4004 &sti->index_entries_allocated_size,
4005 requested_size);
4006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348550 times.
348550 if (!entries)
4007 return -1;
4008
4009 348550 sti->index_entries = entries;
4010
4011 348550 index = sti->nb_index_entries++;
4012 348550 ie= &entries[index];
4013
4014 348550 ie->pos = pos;
4015 348550 ie->timestamp = timestamp;
4016 348550 ie->min_distance= distance;
4017 348550 ie->size= size;
4018 348550 ie->flags = flags;
4019 348550 return index;
4020 }
4021
4022 /**
4023 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4024 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4025 */
4026 27 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4027 int64_t* frame_duration_buffer,
4028 int frame_duration_buffer_size) {
4029 27 FFStream *const sti = ffstream(st);
4030 27 int i = 0;
4031
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);
4032
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 27 times.
164 for (i = 0; i < frame_duration_buffer_size; i++) {
4033 137 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4034 137 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4035 }
4036 27 }
4037
4038 186051 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4039 int count, int offset, unsigned int duration)
4040 {
4041 MOVTimeToSample *tts_buf_new;
4042 186051 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4043 186051 const size_t requested_size =
4044 186051 min_size_needed > *allocated_size ?
4045
2/2
✓ Branch 0 taken 1344 times.
✓ Branch 1 taken 184707 times.
186051 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4046 min_size_needed;
4047
4048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186051 times.
186051 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4049 return -1;
4050
4051 186051 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4052
4053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186051 times.
186051 if (!tts_buf_new)
4054 return -1;
4055
4056 186051 *tts_data = tts_buf_new;
4057
4058 186051 tts_buf_new[*tts_count].count = count;
4059 186051 tts_buf_new[*tts_count].offset = offset;
4060 186051 tts_buf_new[*tts_count].duration = duration;
4061
4062 186051 *tts_count = (*tts_count) + 1;
4063 186051 return 0;
4064 }
4065
4066 #define MAX_REORDER_DELAY 16
4067 606 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4068 {
4069 606 MOVStreamContext *msc = st->priv_data;
4070 606 FFStream *const sti = ffstream(st);
4071 606 int ctts_ind = 0;
4072 606 int ctts_sample = 0;
4073 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4074 606 int buf_start = 0;
4075 int j, r, num_swaps;
4076
4077
2/2
✓ Branch 0 taken 10302 times.
✓ Branch 1 taken 606 times.
10908 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4078 10302 pts_buf[j] = INT64_MIN;
4079
4080
3/4
✓ Branch 0 taken 606 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 547 times.
606 if (st->codecpar->video_delay <= 0 && msc->ctts_count &&
4081
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 16 times.
59 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4082 43 st->codecpar->video_delay = 0;
4083
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) {
4084 // Point j to the last elem of the buffer and insert the current pts there.
4085 138279 j = buf_start;
4086 138279 buf_start = (buf_start + 1);
4087
2/2
✓ Branch 0 taken 8111 times.
✓ Branch 1 taken 130168 times.
138279 if (buf_start == MAX_REORDER_DELAY + 1)
4088 8111 buf_start = 0;
4089
4090 138279 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4091
4092 // The timestamps that are already in the sorted buffer, and are greater than the
4093 // current pts, are exactly the timestamps that need to be buffered to output PTS
4094 // in correct sorted order.
4095 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4096 // can be computed as the maximum no. of swaps any particular timestamp needs to
4097 // go through, to keep this buffer in sorted order.
4098 138279 num_swaps = 0;
4099
2/2
✓ Branch 0 taken 142294 times.
✓ Branch 1 taken 4 times.
142298 while (j != buf_start) {
4100 142294 r = j - 1;
4101
2/2
✓ Branch 0 taken 8389 times.
✓ Branch 1 taken 133905 times.
142294 if (r < 0) r = MAX_REORDER_DELAY;
4102
2/2
✓ Branch 0 taken 4019 times.
✓ Branch 1 taken 138275 times.
142294 if (pts_buf[j] < pts_buf[r]) {
4103 4019 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4104 4019 ++num_swaps;
4105 } else {
4106 138275 break;
4107 }
4108 4019 j = r;
4109 }
4110 138279 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4111
4112 138279 ctts_sample++;
4113
1/2
✓ Branch 0 taken 138279 times.
✗ Branch 1 not taken.
138279 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4114 138279 ctts_ind++;
4115 138279 ctts_sample = 0;
4116 }
4117 }
4118 43 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4119 43 st->codecpar->video_delay, st->index);
4120 }
4121 606 }
4122
4123 103415 static void mov_current_sample_inc(MOVStreamContext *sc)
4124 {
4125 103415 sc->current_sample++;
4126 103415 sc->current_index++;
4127
2/2
✓ Branch 0 taken 61414 times.
✓ Branch 1 taken 42001 times.
103415 if (sc->index_ranges &&
4128
2/2
✓ Branch 0 taken 425 times.
✓ Branch 1 taken 60989 times.
61414 sc->current_index >= sc->current_index_range->end &&
4129
1/2
✓ Branch 0 taken 425 times.
✗ Branch 1 not taken.
425 sc->current_index_range->end) {
4130 425 sc->current_index_range++;
4131 425 sc->current_index = sc->current_index_range->start;
4132 }
4133 103415 }
4134
4135 static void mov_current_sample_dec(MOVStreamContext *sc)
4136 {
4137 sc->current_sample--;
4138 sc->current_index--;
4139 if (sc->index_ranges &&
4140 sc->current_index < sc->current_index_range->start &&
4141 sc->current_index_range > sc->index_ranges) {
4142 sc->current_index_range--;
4143 sc->current_index = sc->current_index_range->end - 1;
4144 }
4145 }
4146
4147 335 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4148 {
4149 int64_t range_size;
4150
4151 335 sc->current_sample = current_sample;
4152 335 sc->current_index = current_sample;
4153
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 309 times.
335 if (!sc->index_ranges) {
4154 26 return;
4155 }
4156
4157 309 for (sc->current_index_range = sc->index_ranges;
4158
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 sc->current_index_range->end;
4159 sc->current_index_range++) {
4160 309 range_size = sc->current_index_range->end - sc->current_index_range->start;
4161
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 if (range_size > current_sample) {
4162 309 sc->current_index = sc->current_index_range->start + current_sample;
4163 309 break;
4164 }
4165 current_sample -= range_size;
4166 }
4167 }
4168
4169 /**
4170 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4171 * which are needed to decode them) that fall in the edit list time ranges.
4172 * Also fixes the timestamps of the index entries to match the timeline
4173 * specified the edit lists.
4174 */
4175 606 static void mov_fix_index(MOVContext *mov, AVStream *st)
4176 {
4177 606 MOVStreamContext *msc = st->priv_data;
4178 606 FFStream *const sti = ffstream(st);
4179 606 AVIndexEntry *e_old = sti->index_entries;
4180 606 int nb_old = sti->nb_index_entries;
4181 606 const AVIndexEntry *e_old_end = e_old + nb_old;
4182 606 const AVIndexEntry *current = NULL;
4183 606 MOVTimeToSample *tts_data_old = msc->tts_data;
4184 606 int64_t tts_index_old = 0;
4185 606 int64_t tts_sample_old = 0;
4186 606 int64_t tts_count_old = msc->tts_count;
4187 606 int64_t edit_list_media_time = 0;
4188 606 int64_t edit_list_duration = 0;
4189 606 int64_t frame_duration = 0;
4190 606 int64_t edit_list_dts_counter = 0;
4191 606 int64_t edit_list_dts_entry_end = 0;
4192 606 int64_t edit_list_start_tts_sample = 0;
4193 int64_t curr_cts;
4194 606 int64_t curr_ctts = 0;
4195 606 int64_t empty_edits_sum_duration = 0;
4196 606 int64_t edit_list_index = 0;
4197 int64_t index;
4198 int flags;
4199 606 int64_t start_dts = 0;
4200 606 int64_t edit_list_start_encountered = 0;
4201 606 int64_t search_timestamp = 0;
4202 606 int64_t* frame_duration_buffer = NULL;
4203 606 int num_discarded_begin = 0;
4204 606 int first_non_zero_audio_edit = -1;
4205 606 int packet_skip_samples = 0;
4206 606 MOVIndexRange *current_index_range = NULL;
4207 606 int found_keyframe_after_edit = 0;
4208 606 int found_non_empty_edit = 0;
4209
4210
4/6
✓ Branch 0 taken 440 times.
✓ Branch 1 taken 166 times.
✓ Branch 2 taken 440 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 440 times.
606 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
4211 166 return;
4212 }
4213
4214 // allocate the index ranges array
4215 440 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4216 sizeof(msc->index_ranges[0]));
4217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 440 times.
440 if (!msc->index_ranges) {
4218 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4219 return;
4220 }
4221 440 msc->current_index_range = msc->index_ranges;
4222
4223 // Clean AVStream from traces of old index
4224 440 sti->index_entries = NULL;
4225 440 sti->index_entries_allocated_size = 0;
4226 440 sti->nb_index_entries = 0;
4227
4228 // Clean time to sample fields of MOVStreamContext
4229 440 msc->tts_data = NULL;
4230 440 msc->tts_count = 0;
4231 440 msc->tts_index = 0;
4232 440 msc->tts_sample = 0;
4233 440 msc->tts_allocated_size = 0;
4234
4235 // Reinitialize min_corrected_pts so that it can be computed again.
4236 440 msc->min_corrected_pts = -1;
4237
4238 // If the dts_shift is positive (in case of negative ctts values in mov),
4239 // then negate the DTS by dts_shift
4240
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 431 times.
440 if (msc->dts_shift > 0) {
4241 9 edit_list_dts_entry_end -= msc->dts_shift;
4242 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4243 }
4244
4245 440 start_dts = edit_list_dts_entry_end;
4246
4247
2/2
✓ Branch 0 taken 467 times.
✓ Branch 1 taken 440 times.
1347 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
4248 907 &edit_list_duration, mov->time_scale)) {
4249 467 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4250 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4251 467 edit_list_index++;
4252 467 edit_list_dts_counter = edit_list_dts_entry_end;
4253 467 edit_list_dts_entry_end += edit_list_duration;
4254 467 num_discarded_begin = 0;
4255
4/4
✓ Branch 0 taken 444 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 440 times.
467 if (!found_non_empty_edit && edit_list_media_time == -1) {
4256 4 empty_edits_sum_duration += edit_list_duration;
4257 4 continue;
4258 }
4259 463 found_non_empty_edit = 1;
4260
4261 // If we encounter a non-negative edit list reset the skip_samples/start_pad fields and set them
4262 // according to the edit list below.
4263
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 336 times.
463 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4264
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit < 0) {
4265 127 first_non_zero_audio_edit = 1;
4266 } else {
4267 first_non_zero_audio_edit = 0;
4268 }
4269
4270
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit > 0)
4271 127 sti->skip_samples = msc->start_pad = 0;
4272 }
4273
4274 // While reordering frame index according to edit list we must handle properly
4275 // the scenario when edit list entry starts from none key frame.
4276 // We find closest previous key frame and preserve it and consequent frames in index.
4277 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4278 463 search_timestamp = edit_list_media_time;
4279
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 336 times.
463 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4280 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4281 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4282 // edit_list_media_time to cover the decoder delay.
4283 127 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
4284 }
4285
4286
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 460 times.
463 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, 0,
4287 &index, &tts_index_old, &tts_sample_old) < 0) {
4288 3 av_log(mov->fc, AV_LOG_WARNING,
4289 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4290 st->index, edit_list_index, search_timestamp);
4291
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,
4292 &index, &tts_index_old, &tts_sample_old) < 0) {
4293 3 av_log(mov->fc, AV_LOG_WARNING,
4294 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4295 st->index, edit_list_index, search_timestamp);
4296 3 index = 0;
4297 3 tts_index_old = 0;
4298 3 tts_sample_old = 0;
4299 }
4300 }
4301 463 current = e_old + index;
4302 463 edit_list_start_tts_sample = tts_sample_old;
4303
4304 // Iterate over index and arrange it according to edit list
4305 463 edit_list_start_encountered = 0;
4306 463 found_keyframe_after_edit = 0;
4307
2/2
✓ Branch 0 taken 348550 times.
✓ Branch 1 taken 112 times.
348662 for (; current < e_old_end; current++, index++) {
4308 // check if frame outside edit list mark it for discard
4309 697100 frame_duration = (current + 1 < e_old_end) ?
4310
2/2
✓ Branch 0 taken 348114 times.
✓ Branch 1 taken 436 times.
348550 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4311
4312 348550 flags = current->flags;
4313
4314 // frames (pts) before or after edit list
4315 348550 curr_cts = current->timestamp + msc->dts_shift;
4316 348550 curr_ctts = 0;
4317
4318
4/4
✓ Branch 0 taken 186063 times.
✓ Branch 1 taken 162487 times.
✓ Branch 2 taken 186051 times.
✓ Branch 3 taken 12 times.
348550 if (tts_data_old && tts_index_old < tts_count_old) {
4319 186051 curr_ctts = tts_data_old[tts_index_old].offset;
4320 186051 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4321 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4322 186051 curr_cts += curr_ctts;
4323 186051 tts_sample_old++;
4324
1/2
✓ Branch 0 taken 186051 times.
✗ Branch 1 not taken.
186051 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186051 times.
186051 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4326 &msc->tts_allocated_size,
4327 186051 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4328 186051 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4329 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4330 tts_index_old,
4331 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4332 tts_data_old[tts_index_old].offset);
4333 break;
4334 }
4335 186051 tts_index_old++;
4336 186051 tts_sample_old = 0;
4337 186051 edit_list_start_tts_sample = 0;
4338 }
4339 }
4340
4341
4/4
✓ Branch 0 taken 348398 times.
✓ Branch 1 taken 152 times.
✓ Branch 2 taken 130 times.
✓ Branch 3 taken 348268 times.
348550 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
4342
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 &&
4343
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 &&
4344 first_non_zero_audio_edit > 0) {
4345 11 packet_skip_samples = edit_list_media_time - curr_cts;
4346 11 sti->skip_samples += packet_skip_samples;
4347
4348 // Shift the index entry timestamp by packet_skip_samples to be correct.
4349 11 edit_list_dts_counter -= packet_skip_samples;
4350
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (edit_list_start_encountered == 0) {
4351 11 edit_list_start_encountered = 1;
4352 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4353 // discarded packets.
4354
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 if (frame_duration_buffer) {
4355 6 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4356 frame_duration_buffer, num_discarded_begin);
4357 6 av_freep(&frame_duration_buffer);
4358 }
4359 }
4360
4361 11 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4362 } else {
4363 271 flags |= AVINDEX_DISCARD_FRAME;
4364 271 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4365
4366
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 132 times.
271 if (edit_list_start_encountered == 0) {
4367 139 num_discarded_begin++;
4368 139 frame_duration_buffer = av_realloc(frame_duration_buffer,
4369 num_discarded_begin * sizeof(int64_t));
4370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if (!frame_duration_buffer) {
4371 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4372 break;
4373 }
4374 139 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4375
4376 // Increment skip_samples for the first non-zero audio edit list
4377
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 &&
4378
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) {
4379 20 sti->skip_samples += frame_duration;
4380 }
4381 }
4382 }
4383 } else {
4384
2/2
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 347829 times.
348268 if (msc->min_corrected_pts < 0) {
4385 439 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4386 } else {
4387 347829 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4388 }
4389
2/2
✓ Branch 0 taken 450 times.
✓ Branch 1 taken 347818 times.
348268 if (edit_list_start_encountered == 0) {
4390 450 edit_list_start_encountered = 1;
4391 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4392 // discarded packets.
4393
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 429 times.
450 if (frame_duration_buffer) {
4394 21 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4395 frame_duration_buffer, num_discarded_begin);
4396 21 av_freep(&frame_duration_buffer);
4397 }
4398 }
4399 }
4400
4401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348550 times.
348550 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
4402 348550 current->min_distance, flags) == -1) {
4403 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4404 break;
4405 }
4406
4407 // Update the index ranges array
4408
4/4
✓ Branch 0 taken 348110 times.
✓ Branch 1 taken 440 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 348089 times.
348550 if (!current_index_range || index != current_index_range->end) {
4409 461 current_index_range = current_index_range ? current_index_range + 1
4410
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 440 times.
461 : msc->index_ranges;
4411 461 current_index_range->start = index;
4412 }
4413 348550 current_index_range->end = index + 1;
4414
4415 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4416
2/2
✓ Branch 0 taken 348411 times.
✓ Branch 1 taken 139 times.
348550 if (edit_list_start_encountered > 0) {
4417 348411 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4418 }
4419
4420 // Break when found first key frame after edit entry completion
4421
2/2
✓ Branch 0 taken 619 times.
✓ Branch 1 taken 347931 times.
348550 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
4422
3/4
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 363 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 256 times.
619 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
4423
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 342 times.
363 if (msc->ctts_count) {
4424 // If we have CTTS and this is the first keyframe after edit elist,
4425 // wait for one more, because there might be trailing B-frames after this I-frame
4426 // that do belong to the edit.
4427
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) {
4428 12 found_keyframe_after_edit = 1;
4429 12 continue;
4430 }
4431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (tts_sample_old != 0) {
4432 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4433 &msc->tts_allocated_size,
4434 tts_sample_old - edit_list_start_tts_sample,
4435 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4436 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4437 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4438 tts_data_old[tts_index_old].offset);
4439 break;
4440 }
4441 }
4442 }
4443 351 break;
4444 }
4445 }
4446 }
4447 // If there are empty edits, then msc->min_corrected_pts might be positive
4448 // intentionally. So we subtract the sum duration of emtpy edits here.
4449 440 msc->min_corrected_pts -= empty_edits_sum_duration;
4450
4451 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4452 // dts by that amount to make the first pts zero.
4453
2/2
✓ Branch 0 taken 271 times.
✓ Branch 1 taken 169 times.
440 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4454
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 230 times.
271 if (msc->min_corrected_pts > 0) {
4455 41 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4456
2/2
✓ Branch 0 taken 2829 times.
✓ Branch 1 taken 41 times.
2870 for (int i = 0; i < sti->nb_index_entries; ++i)
4457 2829 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4458 }
4459 }
4460 // Start time should be equal to zero or the duration of any empty edits.
4461 440 st->start_time = empty_edits_sum_duration;
4462
4463 // Update av stream length, if it ends up shorter than the track's media duration
4464 440 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4465 440 msc->start_pad = sti->skip_samples;
4466
4467 // Free the old index and the old CTTS structures
4468 440 av_free(e_old);
4469 440 av_free(tts_data_old);
4470 440 av_freep(&frame_duration_buffer);
4471
4472 // Null terminate the index ranges array
4473 440 current_index_range = current_index_range ? current_index_range + 1
4474
1/2
✓ Branch 0 taken 440 times.
✗ Branch 1 not taken.
440 : msc->index_ranges;
4475 440 current_index_range->start = 0;
4476 440 current_index_range->end = 0;
4477 440 msc->current_index = msc->index_ranges[0].start;
4478 }
4479
4480 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4481 {
4482
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4483
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == nal_unit_type)
4484 5 return i + 1;
4485 return 0;
4486 }
4487
4488 622 static int build_open_gop_key_points(AVStream *st)
4489 {
4490 int k;
4491 622 int sample_id = 0;
4492 uint32_t cra_index;
4493 622 MOVStreamContext *sc = st->priv_data;
4494
4495
4/4
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 583 times.
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 5 times.
622 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count)
4496 617 return 0;
4497
4498 /* Build an unrolled index of the samples */
4499 5 sc->sample_offsets_count = 0;
4500
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4502 return AVERROR(ENOMEM);
4503 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4504 }
4505 5 av_freep(&sc->sample_offsets);
4506 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4508 return AVERROR(ENOMEM);
4509 5 k = 0;
4510
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4511
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4512 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4513
4514 /* The following HEVC NAL type reveal the use of open GOP sync points
4515 * (TODO: BLA types may also be concerned) */
4516 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4518 return 0;
4519
4520 /* Build a list of open-GOP key samples */
4521 5 sc->open_key_samples_count = 0;
4522
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4523
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4524
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)
4525 return AVERROR(ENOMEM);
4526 11 sc->open_key_samples_count += sc->sync_group[i].count;
4527 }
4528 5 av_freep(&sc->open_key_samples);
4529 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4531 return AVERROR(ENOMEM);
4532 5 k = 0;
4533
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4534 28 const MOVSbgp *sg = &sc->sync_group[i];
4535
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4536
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4537 11 sc->open_key_samples[k++] = sample_id;
4538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4539 return AVERROR_PATCHWELCOME;
4540 28 sample_id += sg->count;
4541 }
4542
4543 /* Identify the minimal time step between samples */
4544 5 sc->min_sample_duration = UINT_MAX;
4545
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4546 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4547
4548 5 return 0;
4549 }
4550
4551 #define MOV_MERGE_CTTS 1
4552 #define MOV_MERGE_STTS 2
4553 /*
4554 * Merge stts and ctts arrays into a new combined array.
4555 * stts_count and ctts_count may be left untouched as they will be
4556 * used to check for the presence of either of them.
4557 */
4558 606 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4559 {
4560 606 MOVStreamContext *sc = st->priv_data;
4561
3/4
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 547 times.
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
606 int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS);
4562
3/4
✓ Branch 0 taken 606 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 540 times.
✓ Branch 3 taken 66 times.
606 int stts = sc->stts_data && (flags & MOV_MERGE_STTS);
4563 606 int idx = 0;
4564
4565
3/4
✓ Branch 0 taken 547 times.
✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 547 times.
606 if (!sc->ctts_data && !sc->stts_data)
4566 return 0;
4567 // Expand time to sample entries such that we have a 1-1 mapping with samples
4568
2/4
✓ Branch 0 taken 606 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 606 times.
606 if (!sc->sample_count || sc->sample_count >= UINT_MAX / sizeof(*sc->tts_data))
4569 return -1;
4570
4571
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 547 times.
606 if (ctts) {
4572 118 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4573 59 sc->sample_count * sizeof(*sc->tts_data));
4574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->tts_data)
4575 return -1;
4576
4577 59 memset(sc->tts_data, 0, sc->tts_allocated_size);
4578
4579
2/2
✓ Branch 0 taken 4874 times.
✓ Branch 1 taken 59 times.
4933 for (int i = 0; i < sc->ctts_count &&
4580
1/2
✓ Branch 0 taken 4874 times.
✗ Branch 1 not taken.
9748 idx < sc->sample_count; i++)
4581
2/2
✓ Branch 0 taken 139017 times.
✓ Branch 1 taken 4874 times.
143891 for (int j = 0; j < sc->ctts_data[i].count &&
4582
1/2
✓ Branch 0 taken 139017 times.
✗ Branch 1 not taken.
139017 idx < sc->sample_count; j++) {
4583 139017 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4584 139017 sc->tts_data[idx++].count = 1;
4585 }
4586
4587 59 sc->tts_count = idx;
4588 } else
4589 547 sc->ctts_count = 0;
4590 606 av_freep(&sc->ctts_data);
4591 606 sc->ctts_allocated_size = 0;
4592
4593 606 idx = 0;
4594
2/2
✓ Branch 0 taken 540 times.
✓ Branch 1 taken 66 times.
606 if (stts) {
4595 540 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4596 540 sc->sample_count * sizeof(*sc->tts_data));
4597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 540 times.
540 if (!tts_data)
4598 return -1;
4599
4600
2/2
✓ Branch 0 taken 481 times.
✓ Branch 1 taken 59 times.
540 if (!sc->tts_data)
4601 481 memset(tts_data, 0, sc->tts_allocated_size);
4602 540 sc->tts_data = tts_data;
4603
4604
2/2
✓ Branch 0 taken 2903 times.
✓ Branch 1 taken 540 times.
3443 for (int i = 0; i < sc->stts_count &&
4605
1/2
✓ Branch 0 taken 2903 times.
✗ Branch 1 not taken.
5806 idx < sc->sample_count; i++)
4606
2/2
✓ Branch 0 taken 235897 times.
✓ Branch 1 taken 2903 times.
238800 for (int j = 0; j < sc->stts_data[i].count &&
4607
1/2
✓ Branch 0 taken 235897 times.
✗ Branch 1 not taken.
235897 idx < sc->sample_count; j++) {
4608 235897 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4609 235897 sc->tts_data[idx++].count = 1;
4610 }
4611
4612 540 sc->tts_count = FFMAX(sc->tts_count, idx);
4613 } else
4614 66 sc->stts_count = 0;
4615 606 av_freep(&sc->stts_data);
4616 606 sc->stts_allocated_size = 0;
4617
4618 606 return 0;
4619 }
4620
4621 622 static void mov_build_index(MOVContext *mov, AVStream *st)
4622 {
4623 622 MOVStreamContext *sc = st->priv_data;
4624 622 FFStream *const sti = ffstream(st);
4625 int64_t current_offset;
4626 622 int64_t current_dts = 0;
4627 622 unsigned int stts_index = 0;
4628 622 unsigned int stsc_index = 0;
4629 622 unsigned int stss_index = 0;
4630 622 unsigned int stps_index = 0;
4631 unsigned int i, j;
4632 622 uint64_t stream_size = 0;
4633
4634 622 int ret = build_open_gop_key_points(st);
4635
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 622 times.
622 if (ret < 0)
4636 return;
4637
4638
2/2
✓ Branch 0 taken 442 times.
✓ Branch 1 taken 180 times.
622 if (sc->elst_count) {
4639 442 int i, edit_start_index = 0, multiple_edits = 0;
4640 442 int64_t empty_duration = 0; // empty duration of the first edit list entry
4641 442 int64_t start_time = 0; // start time of the media
4642
4643
2/2
✓ Branch 0 taken 469 times.
✓ Branch 1 taken 442 times.
911 for (i = 0; i < sc->elst_count; i++) {
4644 469 const MOVElst *e = &sc->elst_data[i];
4645
4/4
✓ Branch 0 taken 442 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 438 times.
469 if (i == 0 && e->time == -1) {
4646 /* if empty, the first entry is the start time of the stream
4647 * relative to the presentation itself */
4648 4 empty_duration = e->duration;
4649 4 edit_start_index = 1;
4650
3/4
✓ Branch 0 taken 442 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 442 times.
✗ Branch 3 not taken.
465 } else if (i == edit_start_index && e->time >= 0) {
4651 442 start_time = e->time;
4652 } else {
4653 23 multiple_edits = 1;
4654 }
4655 }
4656
4657
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 436 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
442 if (multiple_edits && !mov->advanced_editlist) {
4658 if (mov->advanced_editlist_autodisabled)
4659 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4660 "not supported in fragmented MP4 files\n");
4661 else
4662 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4663 "Use -advanced_editlist to correctly decode otherwise "
4664 "a/v desync might occur\n");
4665 }
4666
4667 /* adjust first dts according to edit list */
4668
5/6
✓ Branch 0 taken 438 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 369 times.
✓ Branch 4 taken 73 times.
✗ Branch 5 not taken.
442 if ((empty_duration || start_time) && mov->time_scale > 0) {
4669
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 69 times.
73 if (empty_duration)
4670 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
4671
4672
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)
4673 av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
4674
4675 73 sc->time_offset = start_time - (uint64_t)empty_duration;
4676 73 sc->min_corrected_pts = start_time;
4677
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 72 times.
73 if (!mov->advanced_editlist)
4678 1 current_dts = -sc->time_offset;
4679 }
4680
4681
4/4
✓ Branch 0 taken 436 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 434 times.
442 if (!multiple_edits && !mov->advanced_editlist &&
4682
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 st->codecpar->codec_id == AV_CODEC_ID_AAC && start_time > 0)
4683 sc->start_pad = start_time;
4684 }
4685
4686 /* only use old uncompressed audio chunk demuxing when stts specifies it */
4687
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 381 times.
622 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4688
5/6
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 187 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 121 times.
✓ Branch 5 taken 66 times.
781 sc->stts_count == 1 && sc->stts_data && sc->stts_data[0].duration == 1)) {
4689 556 unsigned int current_sample = 0;
4690 556 unsigned int stts_sample = 0;
4691 unsigned int sample_size;
4692 556 unsigned int distance = 0;
4693 556 unsigned int rap_group_index = 0;
4694 556 unsigned int rap_group_sample = 0;
4695
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 555 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
556 int rap_group_present = sc->rap_group_count && sc->rap_group;
4696
4/8
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 418 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 138 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 418 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
556 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
4697
4698 556 current_dts -= sc->dts_shift;
4699
4700
4/6
✓ Branch 0 taken 540 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 540 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 540 times.
556 if (!sc->sample_count || sti->nb_index_entries || sc->tts_count)
4701 16 return;
4702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 540 times.
540 if (sc->sample_count >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4703 return;
4704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 540 times.
540 if (av_reallocp_array(&sti->index_entries,
4705 540 sti->nb_index_entries + sc->sample_count,
4706 sizeof(*sti->index_entries)) < 0) {
4707 sti->nb_index_entries = 0;
4708 return;
4709 }
4710 540 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
4711
4712 540 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
4713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 540 times.
540 if (ret < 0)
4714 return;
4715
4716
2/2
✓ Branch 0 taken 173843 times.
✓ Branch 1 taken 540 times.
174383 for (i = 0; i < sc->chunk_count; i++) {
4717
2/2
✓ Branch 0 taken 173303 times.
✓ Branch 1 taken 540 times.
173843 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
4718 173843 current_offset = sc->chunk_offsets[i];
4719
2/2
✓ Branch 1 taken 8859 times.
✓ Branch 2 taken 167527 times.
176386 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4720
2/2
✓ Branch 0 taken 2543 times.
✓ Branch 1 taken 6316 times.
8859 i + 1 == sc->stsc_data[stsc_index + 1].first)
4721 2543 stsc_index++;
4722
4723
4/6
✓ Branch 0 taken 173843 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7349 times.
✓ Branch 3 taken 166494 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7349 times.
173843 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
4724 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
4725 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
4726 sc->stsz_sample_size = sc->sample_size;
4727 }
4728
3/4
✓ Branch 0 taken 7349 times.
✓ Branch 1 taken 166494 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7349 times.
173843 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
4729 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
4730 sc->stsz_sample_size = sc->sample_size;
4731 }
4732
4733
2/2
✓ Branch 0 taken 235897 times.
✓ Branch 1 taken 173843 times.
409740 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
4734 235897 int keyframe = 0;
4735
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235897 times.
235897 if (current_sample >= sc->sample_count) {
4736 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
4737 return;
4738 }
4739
4740
6/6
✓ Branch 0 taken 231141 times.
✓ Branch 1 taken 4756 times.
✓ Branch 2 taken 152644 times.
✓ Branch 3 taken 78497 times.
✓ Branch 4 taken 5706 times.
✓ Branch 5 taken 146938 times.
235897 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
4741 84203 keyframe = 1;
4742
2/2
✓ Branch 0 taken 5568 times.
✓ Branch 1 taken 78635 times.
84203 if (stss_index + 1 < sc->keyframe_count)
4743 5568 stss_index++;
4744
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 151694 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
151694 } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
4745 keyframe = 1;
4746 if (stps_index + 1 < sc->stps_count)
4747 stps_index++;
4748 }
4749
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 235709 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
235897 if (rap_group_present && rap_group_index < sc->rap_group_count) {
4750
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
4751 2 keyframe = 1;
4752
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
4753 4 rap_group_sample = 0;
4754 4 rap_group_index++;
4755 }
4756 }
4757
2/2
✓ Branch 0 taken 4756 times.
✓ Branch 1 taken 231141 times.
235897 if (sc->keyframe_absent
4758
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !sc->stps_count
4759
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !rap_group_present
4760
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)))
4761 3884 keyframe = 1;
4762
2/2
✓ Branch 0 taken 88087 times.
✓ Branch 1 taken 147810 times.
235897 if (keyframe)
4763 88087 distance = 0;
4764
2/2
✓ Branch 0 taken 8989 times.
✓ Branch 1 taken 226908 times.
235897 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
4765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235897 times.
235897 if (current_offset > INT64_MAX - sample_size) {
4766 av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
4767 current_offset,
4768 sample_size);
4769 return;
4770 }
4771
4772
2/2
✓ Branch 0 taken 235816 times.
✓ Branch 1 taken 81 times.
235897 if (sc->pseudo_stream_id == -1 ||
4773
1/2
✓ Branch 0 taken 235816 times.
✗ Branch 1 not taken.
235816 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
4774 AVIndexEntry *e;
4775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235897 times.
235897 if (sample_size > 0x3FFFFFFF) {
4776 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
4777 return;
4778 }
4779 235897 e = &sti->index_entries[sti->nb_index_entries++];
4780 235897 e->pos = current_offset;
4781 235897 e->timestamp = current_dts;
4782 235897 e->size = sample_size;
4783 235897 e->min_distance = distance;
4784 235897 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
4785 235897 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
4786 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
4787 current_offset, current_dts, sample_size, distance, keyframe);
4788
4/4
✓ Branch 0 taken 154997 times.
✓ Branch 1 taken 80900 times.
✓ Branch 2 taken 10364 times.
✓ Branch 3 taken 144633 times.
235897 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries < 100)
4789 10364 ff_rfps_add_frame(mov->fc, st, current_dts);
4790 }
4791
4792 235897 current_offset += sample_size;
4793 235897 stream_size += sample_size;
4794
4795 235897 current_dts += sc->tts_data[stts_index].duration;
4796
4797 235897 distance++;
4798 235897 stts_sample++;
4799 235897 current_sample++;
4800
3/4
✓ Branch 0 taken 235357 times.
✓ Branch 1 taken 540 times.
✓ Branch 2 taken 235357 times.
✗ Branch 3 not taken.
235897 if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) {
4801 235357 stts_sample = 0;
4802 235357 stts_index++;
4803 }
4804 }
4805 }
4806
2/2
✓ Branch 0 taken 515 times.
✓ Branch 1 taken 25 times.
540 if (st->duration > 0)
4807 515 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
4808 } else {
4809 66 unsigned chunk_samples, total = 0;
4810
4811
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)
4812 return;
4813
4814 66 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
4815
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
4816 return;
4817
4818 // compute total chunk count
4819
2/2
✓ Branch 0 taken 723 times.
✓ Branch 1 taken 66 times.
789 for (i = 0; i < sc->stsc_count; i++) {
4820 unsigned count, chunk_count;
4821
4822 723 chunk_samples = sc->stsc_data[i].count;
4823
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 66 times.
723 if (i != sc->stsc_count - 1 &&
4824
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) {
4825 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
4826 return;
4827 }
4828
4829
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 648 times.
723 if (sc->samples_per_frame >= 160) { // gsm
4830 75 count = chunk_samples / sc->samples_per_frame;
4831
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 117 times.
648 } else if (sc->samples_per_frame > 1) {
4832 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
4833 531 count = (chunk_samples+samples-1) / samples;
4834 } else {
4835 117 count = (chunk_samples+1023) / 1024;
4836 }
4837
4838
2/2
✓ Branch 1 taken 657 times.
✓ Branch 2 taken 66 times.
723 if (mov_stsc_index_valid(i, sc->stsc_count))
4839 657 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
4840 else
4841 66 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
4842 723 total += chunk_count * count;
4843 }
4844
4845 66 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
4846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4847 return;
4848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (av_reallocp_array(&sti->index_entries,
4849 66 sti->nb_index_entries + total,
4850 sizeof(*sti->index_entries)) < 0) {
4851 sti->nb_index_entries = 0;
4852 return;
4853 }
4854 66 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
4855
4856 // populate index
4857
2/2
✓ Branch 0 taken 5428 times.
✓ Branch 1 taken 66 times.
5494 for (i = 0; i < sc->chunk_count; i++) {
4858 5428 current_offset = sc->chunk_offsets[i];
4859
2/2
✓ Branch 1 taken 5287 times.
✓ Branch 2 taken 141 times.
5428 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4860
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 4630 times.
5287 i + 1 == sc->stsc_data[stsc_index + 1].first)
4861 657 stsc_index++;
4862 5428 chunk_samples = sc->stsc_data[stsc_index].count;
4863
4864
2/2
✓ Branch 0 taken 162532 times.
✓ Branch 1 taken 5428 times.
167960 while (chunk_samples > 0) {
4865 AVIndexEntry *e;
4866 unsigned size, samples;
4867
4868
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) {
4869 avpriv_request_sample(mov->fc,
4870 "Zero bytes per frame, but %d samples per frame",
4871 sc->samples_per_frame);
4872 return;
4873 }
4874
4875
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 148174 times.
162532 if (sc->samples_per_frame >= 160) { // gsm
4876 14358 samples = sc->samples_per_frame;
4877 14358 size = sc->bytes_per_frame;
4878 } else {
4879
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 138611 times.
148174 if (sc->samples_per_frame > 1) {
4880 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
4881 sc->samples_per_frame, chunk_samples);
4882 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
4883 } else {
4884 138611 samples = FFMIN(1024, chunk_samples);
4885 138611 size = samples * sc->sample_size;
4886 }
4887 }
4888
4889
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (sti->nb_index_entries >= total) {
4890 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
4891 return;
4892 }
4893
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (size > 0x3FFFFFFF) {
4894 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
4895 return;
4896 }
4897 162532 e = &sti->index_entries[sti->nb_index_entries++];
4898 162532 e->pos = current_offset;
4899 162532 e->timestamp = current_dts;
4900 162532 e->size = size;
4901 162532 e->min_distance = 0;
4902 162532 e->flags = AVINDEX_KEYFRAME;
4903 162532 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
4904 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
4905 size, samples);
4906
4907 162532 current_offset += size;
4908 162532 current_dts += samples;
4909 162532 chunk_samples -= samples;
4910 }
4911 }
4912 }
4913
4914
2/4
✓ Branch 0 taken 606 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 606 times.
✗ Branch 3 not taken.
606 if (!mov->ignore_editlist && mov->advanced_editlist) {
4915 // Fix index according to edit lists.
4916 606 mov_fix_index(mov, st);
4917 }
4918
4919 // Update start time of the stream.
4920
5/6
✓ Branch 0 taken 166 times.
✓ Branch 1 taken 440 times.
✓ Branch 2 taken 49 times.
✓ Branch 3 taken 117 times.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
606 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) {
4921 49 st->start_time = sti->index_entries[0].timestamp + sc->dts_shift;
4922
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 if (sc->tts_data) {
4923 49 st->start_time += sc->tts_data[0].offset;
4924 }
4925 }
4926
4927 606 mov_estimate_video_delay(mov, st);
4928 }
4929
4930 static int test_same_origin(const char *src, const char *ref) {
4931 char src_proto[64];
4932 char ref_proto[64];
4933 char src_auth[256];
4934 char ref_auth[256];
4935 char src_host[256];
4936 char ref_host[256];
4937 int src_port=-1;
4938 int ref_port=-1;
4939
4940 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
4941 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
4942
4943 if (strlen(src) == 0) {
4944 return -1;
4945 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
4946 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
4947 strlen(src_host) + 1 >= sizeof(src_host) ||
4948 strlen(ref_host) + 1 >= sizeof(ref_host)) {
4949 return 0;
4950 } else if (strcmp(src_proto, ref_proto) ||
4951 strcmp(src_auth, ref_auth) ||
4952 strcmp(src_host, ref_host) ||
4953 src_port != ref_port) {
4954 return 0;
4955 } else
4956 return 1;
4957 }
4958
4959 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
4960 {
4961 /* try relative path, we do not try the absolute because it can leak information about our
4962 system to an attacker */
4963 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
4964 char filename[1025];
4965 const char *src_path;
4966 int i, l;
4967
4968 /* find a source dir */
4969 src_path = strrchr(src, '/');
4970 if (src_path)
4971 src_path++;
4972 else
4973 src_path = src;
4974
4975 /* find a next level down to target */
4976 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
4977 if (ref->path[l] == '/') {
4978 if (i == ref->nlvl_to - 1)
4979 break;
4980 else
4981 i++;
4982 }
4983
4984 /* compose filename if next level down to target was found */
4985 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
4986 memcpy(filename, src, src_path - src);
4987 filename[src_path - src] = 0;
4988
4989 for (i = 1; i < ref->nlvl_from; i++)
4990 av_strlcat(filename, "../", sizeof(filename));
4991
4992 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
4993 if (!c->use_absolute_path) {
4994 int same_origin = test_same_origin(src, filename);
4995
4996 if (!same_origin) {
4997 av_log(c->fc, AV_LOG_ERROR,
4998 "Reference with mismatching origin, %s not tried for security reasons, "
4999 "set demuxer option use_absolute_path to allow it anyway\n",
5000 ref->path);
5001 return AVERROR(ENOENT);
5002 }
5003
5004 if (strstr(ref->path + l + 1, "..") ||
5005 strstr(ref->path + l + 1, ":") ||
5006 (ref->nlvl_from > 1 && same_origin < 0) ||
5007 (filename[0] == '/' && src_path == src))
5008 return AVERROR(ENOENT);
5009 }
5010
5011 if (strlen(filename) + 1 == sizeof(filename))
5012 return AVERROR(ENOENT);
5013 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5014 return 0;
5015 }
5016 } else if (c->use_absolute_path) {
5017 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5018 "this is a possible security issue\n");
5019 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5020 return 0;
5021 } else {
5022 av_log(c->fc, AV_LOG_ERROR,
5023 "Absolute path %s not tried for security reasons, "
5024 "set demuxer option use_absolute_path to allow absolute paths\n",
5025 ref->path);
5026 }
5027
5028 return AVERROR(ENOENT);
5029 }
5030
5031 1273 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5032 {
5033
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1259 times.
1273 if (sc->time_scale <= 0) {
5034 14 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5035 14 sc->time_scale = c->time_scale;
5036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (sc->time_scale <= 0)
5037 sc->time_scale = 1;
5038 }
5039 1273 }
5040
5041 #if CONFIG_IAMFDEC
5042 10 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5043 {
5044 10 const MOVStreamContext *sc = st->priv_data;
5045 10 const IAMFContext *iamf = &sc->iamf->iamf;
5046
5047
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5048 10 const AVStreamGroup *stg = NULL;
5049
5050
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5051
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)
5052 10 stg = c->fc->stream_groups[j];
5053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 av_assert0(stg);
5054
5055
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int j = 0; j < stg->nb_streams; j++) {
5056 50 const FFStream *sti = cffstream(st);
5057 50 AVStream *out = stg->streams[j];
5058 50 FFStream *out_sti = ffstream(stg->streams[j]);
5059
5060 50 out->codecpar->bit_rate = 0;
5061
5062
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 40 times.
50 if (out == st)
5063 10 continue;
5064
5065 40 out->time_base = st->time_base;
5066 40 out->start_time = st->start_time;
5067 40 out->duration = st->duration;
5068 40 out->nb_frames = st->nb_frames;
5069 40 out->discard = st->discard;
5070
5071
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 av_assert0(!out_sti->index_entries);
5072 40 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (!out_sti->index_entries)
5074 return AVERROR(ENOMEM);
5075
5076 40 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5077 40 out_sti->nb_index_entries = sti->nb_index_entries;
5078 40 out_sti->skip_samples = sti->skip_samples;
5079 40 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5080 }
5081 }
5082
5083 10 return 0;
5084 }
5085 #endif
5086
5087 622 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5088 {
5089
4/6
✓ Branch 0 taken 606 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 606 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 606 times.
✗ Branch 5 not taken.
622 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5090
3/4
✓ Branch 0 taken 405 times.
✓ Branch 1 taken 201 times.
✓ Branch 2 taken 405 times.
✗ Branch 3 not taken.
606 (!sc->sample_size && !sc->sample_count))) ||
5091
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 606 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
622 (!sc->chunk_count && sc->sample_count)) {
5092 av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5093 index);
5094 return 1;
5095 }
5096
5097
3/4
✓ Branch 0 taken 606 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 606 times.
622 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
5098 av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5099 index);
5100 return 2;
5101 }
5102 622 return 0;
5103 }
5104
5105 597 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5106 {
5107 AVStream *st;
5108 MOVStreamContext *sc;
5109 int ret;
5110
5111 597 st = avformat_new_stream(c->fc, NULL);
5112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (!st) return AVERROR(ENOMEM);
5113 597 st->id = -1;
5114 597 sc = av_mallocz(sizeof(MOVStreamContext));
5115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (!sc) return AVERROR(ENOMEM);
5116
5117 597 st->priv_data = sc;
5118 597 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5119 597 sc->ffindex = st->index;
5120 597 c->trak_index = st->index;
5121 597 sc->tref_flags = 0;
5122 597 sc->tref_id = -1;
5123 597 sc->refcount = 1;
5124
5125
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 597 times.
597 if ((ret = mov_read_default(c, pb, atom)) < 0)
5126 return ret;
5127
5128 597 c->trak_index = -1;
5129
5130 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5131 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5132
5/6
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 581 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 15 times.
597 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
5133 1 sc->stsc_count = 0;
5134 1 av_freep(&sc->stsc_data);
5135 }
5136
5137 597 ret = sanity_checks(c->fc, sc, st->index);
5138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (ret)
5139 return ret > 1 ? AVERROR_INVALIDDATA : 0;
5140
5141 597 fix_timescale(c, sc);
5142
5143 597 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5144
5145 /*
5146 * Advanced edit list support does not work with fragemented MP4s, which
5147 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5148 * In these files, trun atoms may be streamed in.
5149 */
5150
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 581 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 4 times.
597 if (!sc->stts_count && c->advanced_editlist) {
5151
5152 12 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5153 "MP4. disabling.\n");
5154 12 c->advanced_editlist = 0;
5155 12 c->advanced_editlist_autodisabled = 1;
5156 }
5157
5158 597 mov_build_index(c, st);
5159
5160 #if CONFIG_IAMFDEC
5161
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 587 times.
597 if (sc->iamf) {
5162 10 ret = mov_update_iamf_streams(c, st);
5163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
5164 return ret;
5165 }
5166 #endif
5167
5168
3/4
✓ Branch 0 taken 596 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 596 times.
597 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
5169 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5170 if (c->enable_drefs) {
5171 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5172 av_log(c->fc, AV_LOG_ERROR,
5173 "stream %d, error opening alias: path='%s', dir='%s', "
5174 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5175 st->index, dref->path, dref->dir, dref->filename,
5176 dref->volume, dref->nlvl_from, dref->nlvl_to);
5177 } else {
5178 av_log(c->fc, AV_LOG_WARNING,
5179 "Skipped opening external track: "
5180 "stream %d, alias: path='%s', dir='%s', "
5181 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5182 "Set enable_drefs to allow this.\n",
5183 st->index, dref->path, dref->dir, dref->filename,
5184 dref->volume, dref->nlvl_from, dref->nlvl_to);
5185 }
5186 } else {
5187 597 sc->pb = c->fc->pb;
5188 597 sc->pb_is_copied = 1;
5189 }
5190
5191
2/2
✓ Branch 0 taken 305 times.
✓ Branch 1 taken 292 times.
597 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5192
3/4
✓ Branch 0 taken 295 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 295 times.
✗ Branch 3 not taken.
305 int stts_constant = sc->stts_count && sc->tts_count;
5193
3/4
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 247 times.
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
305 if (sc->h_spacing && sc->v_spacing)
5194 58 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5195 58 sc->h_spacing, sc->v_spacing, INT_MAX);
5196
4/6
✓ Branch 0 taken 244 times.
✓ Branch 1 taken 61 times.
✓ Branch 2 taken 244 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 244 times.
✗ Branch 5 not taken.
305 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
5197
2/4
✓ Branch 0 taken 244 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 244 times.
✗ Branch 3 not taken.
244 sc->height && sc->width &&
5198
2/4
✓ Branch 0 taken 244 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 244 times.
244 (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
5199 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5200 (int64_t)st->codecpar->height * sc->width,
5201 (int64_t)st->codecpar->width * sc->height, INT_MAX);
5202 }
5203
5204 #if FF_API_R_FRAME_RATE
5205
4/4
✓ Branch 0 taken 154830 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 154535 times.
✓ Branch 3 taken 295 times.
154840 for (unsigned int i = 1; sc->stts_count && i + 1 < sc->tts_count; i++) {
5206
2/2
✓ Branch 0 taken 152108 times.
✓ Branch 1 taken 2427 times.
154535 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5207 152108 continue;
5208 2427 stts_constant = 0;
5209 }
5210
2/2
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 24 times.
305 if (stts_constant)
5211 281 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5212 281 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5213 #endif
5214 }
5215
5216 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
5217
3/4
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 331 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 266 times.
597 if (!st->codecpar->extradata_size && st->codecpar->codec_id == AV_CODEC_ID_H264 &&
5218 TAG_IS_AVCI(st->codecpar->codec_tag)) {
5219 ret = ff_generate_avci_extradata(st);
5220 if (ret < 0)
5221 return ret;
5222 }
5223
5224
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 573 times.
597 switch (st->codecpar->codec_id) {
5225 #if CONFIG_H261_DECODER
5226 24 case AV_CODEC_ID_H261:
5227 #endif
5228 #if CONFIG_H263_DECODER
5229 case AV_CODEC_ID_H263:
5230 #endif
5231 #if CONFIG_MPEG4_DECODER
5232 case AV_CODEC_ID_MPEG4:
5233 #endif
5234 24 st->codecpar->width = 0; /* let decoder init width/height */
5235 24 st->codecpar->height= 0;
5236 24 break;
5237 }
5238
5239 // If the duration of the mp3 packets is not constant, then they could need a parser
5240
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 596 times.
597 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5241
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 && sc->time_scale == st->codecpar->sample_rate) {
5242 1 int stts_constant = 1;
5243
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++) {
5244
1/2
✓ Branch 0 taken 287 times.
✗ Branch 1 not taken.
287 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5245 287 continue;
5246 stts_constant = 0;
5247 }
5248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!stts_constant)
5249 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5250 }
5251 /* Do not need those anymore. */
5252 597 av_freep(&sc->chunk_offsets);
5253 597 av_freep(&sc->sample_sizes);
5254 597 av_freep(&sc->keyframes);
5255 597 av_freep(&sc->stps_data);
5256 597 av_freep(&sc->elst_data);
5257 597 av_freep(&sc->rap_group);
5258 597 av_freep(&sc->sync_group);
5259 597 av_freep(&sc->sgpd_sync);
5260
5261 597 return 0;
5262 }
5263
5264 125 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5265 {
5266 int ret;
5267 125 c->itunes_metadata = 1;
5268 125 ret = mov_read_default(c, pb, atom);
5269 125 c->itunes_metadata = 0;
5270 125 return ret;
5271 }
5272
5273 11 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5274 {
5275 uint32_t count;
5276 uint32_t i;
5277
5278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
5279 return 0;
5280
5281 11 avio_skip(pb, 4);
5282 11 count = avio_rb32(pb);
5283 11 atom.size -= 8;
5284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (count >= UINT_MAX / sizeof(*c->meta_keys)) {
5285 av_log(c->fc, AV_LOG_ERROR,
5286 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5287 return AVERROR_INVALIDDATA;
5288 }
5289
5290 11 c->meta_keys_count = count + 1;
5291 11 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
5292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!c->meta_keys)
5293 return AVERROR(ENOMEM);
5294
5295
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i <= count; ++i) {
5296 58 uint32_t key_size = avio_rb32(pb);
5297 58 uint32_t type = avio_rl32(pb);
5298
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) {
5299 av_log(c->fc, AV_LOG_ERROR,
5300 "The key# %"PRIu32" in meta has invalid size:"
5301 "%"PRIu32"\n", i, key_size);
5302 return AVERROR_INVALIDDATA;
5303 }
5304 58 atom.size -= key_size;
5305 58 key_size -= 8;
5306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (type != MKTAG('m','d','t','a')) {
5307 avio_skip(pb, key_size);
5308 continue;
5309 }
5310 58 c->meta_keys[i] = av_mallocz(key_size + 1);
5311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!c->meta_keys[i])
5312 return AVERROR(ENOMEM);
5313 58 avio_read(pb, c->meta_keys[i], key_size);
5314 }
5315
5316 11 return 0;
5317 }
5318
5319 65 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5320 {
5321 65 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5322 65 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5323 int i;
5324 65 int ret = 0;
5325 AVStream *st;
5326 MOVStreamContext *sc;
5327
5328
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (c->fc->nb_streams < 1)
5329 return 0;
5330 65 st = c->fc->streams[c->fc->nb_streams-1];
5331 65 sc = st->priv_data;
5332
5333
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 65 times.
260 for (i = 0; i < 3; i++) {
5334 uint8_t **p;
5335 uint32_t len, tag;
5336
5337
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 195 times.
195 if (end - avio_tell(pb) <= 12)
5338 break;
5339
5340 195 len = avio_rb32(pb);
5341 195 tag = avio_rl32(pb);
5342 195 avio_skip(pb, 4); // flags
5343
5344
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))
5345 break;
5346 195 len -= 12;
5347
5348
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 130 times.
195 if (tag == MKTAG('m', 'e', 'a', 'n'))
5349 65 p = &mean;
5350
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 65 times.
130 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5351 65 p = &key;
5352
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) {
5353 65 avio_skip(pb, 4);
5354 65 len -= 4;
5355 65 p = &val;
5356 } else
5357 break;
5358
5359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (*p)
5360 break;
5361
5362 195 *p = av_malloc(len + 1);
5363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*p) {
5364 ret = AVERROR(ENOMEM);
5365 break;
5366 }
5367 195 ret = ffio_read_size(pb, *p, len);
5368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (ret < 0) {
5369 av_freep(p);
5370 break;
5371 }
5372 195 (*p)[len] = 0;
5373 }
5374
5375
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) {
5376
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 32 times.
65 if (strcmp(key, "iTunSMPB") == 0) {
5377 int priming, remainder, samples;
5378
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
5379
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)
5380 33 sc->start_pad = priming;
5381 }
5382 }
5383
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 10 times.
120 if (strcmp(key, "cdec") != 0) {
5384 55 av_dict_set(&c->fc->metadata, key, val,
5385 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5386 55 key = val = NULL;
5387 }
5388 } else {
5389 av_log(c->fc, AV_LOG_VERBOSE,
5390 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5391 }
5392
5393 65 avio_seek(pb, end, SEEK_SET);
5394 65 av_freep(&key);
5395 65 av_freep(&val);
5396 65 av_freep(&mean);
5397 65 return ret;
5398 }
5399
5400 25 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5401 {
5402 MOVStreamContext *sc;
5403 AVStream *st;
5404
5405 25 st = avformat_new_stream(c->fc, NULL);
5406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!st)
5407 return AVERROR(ENOMEM);
5408 25 sc = av_mallocz(sizeof(MOVStreamContext));
5409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!sc)
5410 return AVERROR(ENOMEM);
5411
5412 25 item->st = st;
5413 25 st->id = item->item_id;
5414 25 st->priv_data = sc;
5415 25 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5416 25 st->codecpar->codec_id = mov_codec_id(st, item->type);
5417 25 sc->id = st->id;
5418 25 sc->ffindex = st->index;
5419 25 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5420 25 st->time_base.num = st->time_base.den = 1;
5421 25 st->nb_frames = 1;
5422 25 sc->time_scale = 1;
5423 25 sc->pb = c->fc->pb;
5424 25 sc->pb_is_copied = 1;
5425 25 sc->refcount = 1;
5426
5427
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 if (item->name)
5428 25 av_dict_set(&st->metadata, "title", item->name, 0);
5429
5430 // Populate the necessary fields used by mov_build_index.
5431 25 sc->stsc_count = 1;
5432 25 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!sc->stsc_data)
5434 return AVERROR(ENOMEM);
5435 25 sc->stsc_data[0].first = 1;
5436 25 sc->stsc_data[0].count = 1;
5437 25 sc->stsc_data[0].id = 1;
5438 25 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!sc->chunk_offsets)
5440 return AVERROR(ENOMEM);
5441 25 sc->chunk_count = 1;
5442 25 sc->sample_sizes = av_malloc_array(1, sizeof(*sc->sample_sizes));
5443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!sc->sample_sizes)
5444 return AVERROR(ENOMEM);
5445 25 sc->sample_count = 1;
5446 25 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!sc->stts_data)
5448 return AVERROR(ENOMEM);
5449 25 sc->stts_count = 1;
5450 25 sc->stts_data[0].count = 1;
5451 // Not used for still images. But needed by mov_build_index.
5452 25 sc->stts_data[0].duration = 0;
5453
5454 25 return 0;
5455 }
5456
5457 140 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5458 {
5459
1/2
✓ Branch 0 taken 406 times.
✗ Branch 1 not taken.
406 while (atom.size > 8) {
5460 uint32_t tag;
5461
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 406 times.
406 if (avio_feof(pb))
5462 return AVERROR_EOF;
5463 406 tag = avio_rl32(pb);
5464 406 atom.size -= 4;
5465
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 266 times.
406 if (tag == MKTAG('h','d','l','r')) {
5466 140 avio_seek(pb, -8, SEEK_CUR);
5467 140 atom.size += 8;
5468 140 return mov_read_default(c, pb, atom);
5469 }
5470 }
5471 return 0;
5472 }
5473
5474 // return 1 when matrix is identity, 0 otherwise
5475 #define IS_MATRIX_IDENT(matrix) \
5476 ( (matrix)[0][0] == (1 << 16) && \
5477 (matrix)[1][1] == (1 << 16) && \
5478 (matrix)[2][2] == (1 << 30) && \
5479 !(matrix)[0][1] && !(matrix)[0][2] && \
5480 !(matrix)[1][0] && !(matrix)[1][2] && \
5481 !(matrix)[2][0] && !(matrix)[2][1])
5482
5483 597 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5484 {
5485 int i, j, e;
5486 int width;
5487 int height;
5488 int display_matrix[3][3];
5489 597 int res_display_matrix[3][3] = { { 0 } };
5490 AVStream *st;
5491 MOVStreamContext *sc;
5492 int version;
5493 int flags;
5494
5495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (c->fc->nb_streams < 1)
5496 return 0;
5497 597 st = c->fc->streams[c->fc->nb_streams-1];
5498 597 sc = st->priv_data;
5499
5500 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5501 // avoids corrupting AVStreams mapped to an earlier tkhd.
5502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 597 times.
597 if (st->id != -1)
5503 return AVERROR_INVALIDDATA;
5504
5505 597 version = avio_r8(pb);
5506 597 flags = avio_rb24(pb);
5507 597 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5508
5509
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 588 times.
597 if (version == 1) {
5510 9 avio_rb64(pb);
5511 9 avio_rb64(pb);
5512 } else {
5513 588 avio_rb32(pb); /* creation time */
5514 588 avio_rb32(pb); /* modification time */
5515 }
5516 597 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5517 597 sc->id = st->id;
5518 597 avio_rb32(pb); /* reserved */
5519
5520 /* highlevel (considering edits) duration in movie timebase */
5521
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 588 times.
597 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5522 597 avio_rb32(pb); /* reserved */
5523 597 avio_rb32(pb); /* reserved */
5524
5525 597 avio_rb16(pb); /* layer */
5526 597 avio_rb16(pb); /* alternate group */
5527 597 avio_rb16(pb); /* volume */
5528 597 avio_rb16(pb); /* reserved */
5529
5530 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
5531 // they're kept in fixed point format through all calculations
5532 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
5533 // side data, but the scale factor is not needed to calculate aspect ratio
5534
2/2
✓ Branch 0 taken 1791 times.
✓ Branch 1 taken 597 times.
2388 for (i = 0; i < 3; i++) {
5535 1791 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
5536 1791 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
5537 1791 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
5538 }
5539
5540 597 width = avio_rb32(pb); // 16.16 fixed point track width
5541 597 height = avio_rb32(pb); // 16.16 fixed point track height
5542 597 sc->width = width >> 16;
5543 597 sc->height = height >> 16;
5544
5545 // apply the moov display matrix (after the tkhd one)
5546
2/2
✓ Branch 0 taken 1791 times.
✓ Branch 1 taken 597 times.
2388 for (i = 0; i < 3; i++) {
5547 1791 const int sh[3] = { 16, 16, 30 };
5548
2/2
✓ Branch 0 taken 5373 times.
✓ Branch 1 taken 1791 times.
7164 for (j = 0; j < 3; j++) {
5549
2/2
✓ Branch 0 taken 16119 times.
✓ Branch 1 taken 5373 times.
21492 for (e = 0; e < 3; e++) {
5550 16119 res_display_matrix[i][j] +=
5551 16119 ((int64_t) display_matrix[i][e] *
5552 16119 c->movie_display_matrix[e][j]) >> sh[e];
5553 }
5554 }
5555 }
5556
5557 // save the matrix when it is not the default identity
5558
10/18
✓ Branch 0 taken 588 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 588 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 588 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 588 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 588 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 588 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 588 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 588 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 588 times.
597 if (!IS_MATRIX_IDENT(res_display_matrix)) {
5559 9 av_freep(&sc->display_matrix);
5560 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
5561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
5562 return AVERROR(ENOMEM);
5563
5564
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
5565
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
5566 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
5567 }
5568
5569 // transform the display width/height according to the matrix
5570 // to keep the same scale, use [width height 1<<16]
5571
5/6
✓ Branch 0 taken 315 times.
✓ Branch 1 taken 282 times.
✓ Branch 2 taken 315 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 307 times.
597 if (width && height && sc->display_matrix) {
5572 double disp_transform[2];
5573
5574
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
5575 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
5576 16 sc->display_matrix[3 + i]);
5577
5578
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 &&
5579
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) &&
5580
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
5581 3 st->sample_aspect_ratio = av_d2q(
5582 3 disp_transform[0] / disp_transform[1],
5583 INT_MAX);
5584 }
5585 597 return 0;
5586 }
5587
5588 388 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5589 {
5590 388 MOVFragment *frag = &c->fragment;
5591 388 MOVTrackExt *trex = NULL;
5592 int flags, track_id, i;
5593 MOVFragmentStreamInfo * frag_stream_info;
5594
5595 388 avio_r8(pb); /* version */
5596 388 flags = avio_rb24(pb);
5597
5598 388 track_id = avio_rb32(pb);
5599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!track_id)
5600 return AVERROR_INVALIDDATA;
5601
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < c->trex_count; i++)
5602
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (c->trex_data[i].track_id == track_id) {
5603 388 trex = &c->trex_data[i];
5604 388 break;
5605 }
5606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!trex) {
5607 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
5608 return 0;
5609 }
5610 388 c->fragment.found_tfhd = 1;
5611 388 frag->track_id = track_id;
5612 388 set_frag_stream(&c->frag_index, track_id);
5613
5614 776 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
5615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
776 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
5616
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 21 times.
388 frag->moof_offset : frag->implicit_offset;
5617
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 385 times.
388 frag->stsd_id = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id;
5618
5619 776 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
5620
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 383 times.
388 avio_rb32(pb) : trex->duration;
5621 776 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
5622
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 382 times.
388 avio_rb32(pb) : trex->size;
5623 776 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
5624
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 365 times.
388 avio_rb32(pb) : trex->flags;
5625 388 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
5626
5627 388 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5628
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5629 388 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
5630 388 frag_stream_info->stsd_id = frag->stsd_id;
5631 }
5632 388 return 0;
5633 }
5634
5635 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5636 {
5637 unsigned i, num;
5638 void *new_tracks;
5639
5640 2 num = atom.size / 4;
5641
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
5642 return AVERROR(ENOMEM);
5643
5644 2 av_free(c->chapter_tracks);
5645 2 c->chapter_tracks = new_tracks;
5646 2 c->nb_chapter_tracks = num;
5647
5648
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++)
5649 2 c->chapter_tracks[i] = avio_rb32(pb);
5650
5651 2 c->nb_chapter_tracks = i;
5652
5653 2 return 0;
5654 }
5655
5656 17 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5657 {
5658 MOVTrackExt *trex;
5659 int err;
5660
5661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if ((uint64_t)c->trex_count+1 >= UINT_MAX / sizeof(*c->trex_data))
5662 return AVERROR_INVALIDDATA;
5663
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
5664 sizeof(*c->trex_data))) < 0) {
5665 c->trex_count = 0;
5666 return err;
5667 }
5668
5669 17 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
5670
5671 17 trex = &c->trex_data[c->trex_count++];
5672 17 avio_r8(pb); /* version */
5673 17 avio_rb24(pb); /* flags */
5674 17 trex->track_id = avio_rb32(pb);
5675 17 trex->stsd_id = avio_rb32(pb);
5676 17 trex->duration = avio_rb32(pb);
5677 17 trex->size = avio_rb32(pb);
5678 17 trex->flags = avio_rb32(pb);
5679 17 return 0;
5680 }
5681
5682 367 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5683 {
5684 367 MOVFragment *frag = &c->fragment;
5685 367 AVStream *st = NULL;
5686 MOVStreamContext *sc;
5687 int version, i;
5688 MOVFragmentStreamInfo * frag_stream_info;
5689 int64_t base_media_decode_time;
5690
5691
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 for (i = 0; i < c->fc->nb_streams; i++) {
5692 367 sc = c->fc->streams[i]->priv_data;
5693
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 if (sc->id == frag->track_id) {
5694 367 st = c->fc->streams[i];
5695 367 break;
5696 }
5697 }
5698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367 times.
367 if (!st) {
5699 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5700 return 0;
5701 }
5702 367 sc = st->priv_data;
5703
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 365 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
367 if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1)
5704 return 0;
5705 367 version = avio_r8(pb);
5706 367 avio_rb24(pb); /* flags */
5707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367 times.
367 if (version) {
5708 base_media_decode_time = avio_rb64(pb);
5709 } else {
5710 367 base_media_decode_time = avio_rb32(pb);
5711 }
5712
5713 367 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5714
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 if (frag_stream_info)
5715 367 frag_stream_info->tfdt_dts = base_media_decode_time;
5716 367 sc->track_end = base_media_decode_time;
5717
5718 367 return 0;
5719 }
5720
5721 388 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5722 {
5723 388 MOVFragment *frag = &c->fragment;
5724 388 AVStream *st = NULL;
5725 388 FFStream *sti = NULL;
5726 MOVStreamContext *sc;
5727 MOVTimeToSample *tts_data;
5728 uint64_t offset;
5729 388 int64_t dts, pts = AV_NOPTS_VALUE;
5730 388 int data_offset = 0;
5731 388 unsigned entries, first_sample_flags = frag->flags;
5732 int flags, distance, i;
5733 388 int64_t prev_dts = AV_NOPTS_VALUE;
5734 388 int next_frag_index = -1, index_entry_pos;
5735 size_t requested_size;
5736 size_t old_allocated_size;
5737 AVIndexEntry *new_entries;
5738 MOVFragmentStreamInfo * frag_stream_info;
5739
5740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!frag->found_tfhd) {
5741 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
5742 return AVERROR_INVALIDDATA;
5743 }
5744
5745
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < c->fc->nb_streams; i++) {
5746 394 sc = c->fc->streams[i]->priv_data;
5747
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (sc->id == frag->track_id) {
5748 388 st = c->fc->streams[i];
5749 388 sti = ffstream(st);
5750 388 break;
5751 }
5752 }
5753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!st) {
5754 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5755 return 0;
5756 }
5757 388 sc = st->priv_data;
5758
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 386 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
388 if (sc->pseudo_stream_id+1 != frag->stsd_id && sc->pseudo_stream_id != -1)
5759 return 0;
5760
5761 // Find the next frag_index index that has a valid index_entry for
5762 // the current track_id.
5763 //
5764 // A valid index_entry means the trun for the fragment was read
5765 // and it's samples are in index_entries at the given position.
5766 // New index entries will be inserted before the index_entry found.
5767 388 index_entry_pos = sti->nb_index_entries;
5768
2/2
✓ Branch 0 taken 1621 times.
✓ Branch 1 taken 388 times.
2009 for (i = c->frag_index.current + 1; i < c->frag_index.nb_items; i++) {
5769 1621 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
5770
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) {
5771 next_frag_index = i;
5772 index_entry_pos = frag_stream_info->index_entry;
5773 break;
5774 }
5775 }
5776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 av_assert0(index_entry_pos <= sti->nb_index_entries);
5777
5778 388 avio_r8(pb); /* version */
5779 388 flags = avio_rb24(pb);
5780 388 entries = avio_rb32(pb);
5781 388 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
5782
5783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if ((uint64_t)entries+sc->tts_count >= UINT_MAX/sizeof(*sc->tts_data))
5784 return AVERROR_INVALIDDATA;
5785
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
5786
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 367 times.
388 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb);
5787
5788 388 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5789
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
5791 dts = frag_stream_info->next_trun_dts - sc->time_offset;
5792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5793 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
5794 pts = frag_stream_info->first_tfra_pts;
5795 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5796 ", using it for pts\n", pts);
5797
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5798 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
5799 dts = frag_stream_info->first_tfra_pts;
5800 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5801 ", using it for dts\n", pts);
5802 } else {
5803 388 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
5804 388 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
5805
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
388 int fallback_tfdt = !c->use_tfdt && !has_sidx && has_tfdt;
5806
4/6
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 367 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
388 int fallback_sidx = c->use_tfdt && !has_tfdt && has_sidx;
5807
5808
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (fallback_sidx) {
5809 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
5810 }
5811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (fallback_tfdt) {
5812 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
5813 }
5814
5815
4/6
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 367 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
388 if (has_tfdt && c->use_tfdt || fallback_tfdt) {
5816 367 dts = frag_stream_info->tfdt_dts - sc->time_offset;
5817 367 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
5818 ", using it for dts\n", dts);
5819
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
21 } else if (has_sidx && !c->use_tfdt || fallback_sidx) {
5820 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
5821 // pts = frag_stream_info->sidx_pts;
5822 dts = frag_stream_info->sidx_pts - sc->time_offset;
5823 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
5824 ", using it for dts\n", frag_stream_info->sidx_pts);
5825 } else {
5826 21 dts = sc->track_end - sc->time_offset;
5827 21 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5828 ", using it for dts\n", dts);
5829 }
5830 }
5831 } else {
5832 dts = sc->track_end - sc->time_offset;
5833 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5834 ", using it for dts\n", dts);
5835 }
5836 388 offset = frag->base_data_offset + data_offset;
5837 388 distance = 0;
5838 388 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
5839
5840 // realloc space for new index entries
5841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
5842 entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
5843 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
5844 }
5845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (entries == 0)
5846 return 0;
5847
5848 388 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
5849 388 new_entries = av_fast_realloc(sti->index_entries,
5850 &sti->index_entries_allocated_size,
5851 requested_size);
5852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!new_entries)
5853 return AVERROR(ENOMEM);
5854 388 sti->index_entries= new_entries;
5855
5856 388 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
5857 388 old_allocated_size = sc->tts_allocated_size;
5858 388 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
5859 requested_size);
5860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!tts_data)
5861 return AVERROR(ENOMEM);
5862 388 sc->tts_data = tts_data;
5863
5864 // In case there were samples without time to sample entries, ensure they get
5865 // zero valued entries. This ensures clips which mix boxes with and
5866 // without time to sample entries don't pickup uninitialized data.
5867 388 memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0,
5868 388 sc->tts_allocated_size - old_allocated_size);
5869
5870
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (index_entry_pos < sti->nb_index_entries) {
5871 // Make hole in index_entries and tts_data for new samples
5872 memmove(sti->index_entries + index_entry_pos + entries,
5873 sti->index_entries + index_entry_pos,
5874 sizeof(*sti->index_entries) *
5875 (sti->nb_index_entries - index_entry_pos));
5876 memmove(sc->tts_data + index_entry_pos + entries,
5877 sc->tts_data + index_entry_pos,
5878 sizeof(*sc->tts_data) * (sc->tts_count - index_entry_pos));
5879 if (index_entry_pos < sc->current_sample) {
5880 sc->current_sample += entries;
5881 }
5882 }
5883
5884 388 sti->nb_index_entries += entries;
5885 388 sc->tts_count = sti->nb_index_entries;
5886 388 sc->stts_count = sti->nb_index_entries;
5887
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 28 times.
388 if (flags & MOV_TRUN_SAMPLE_CTS)
5888 360 sc->ctts_count = sti->nb_index_entries;
5889
5890 // Record the index_entry position in frag_index of this fragment
5891
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5892 388 frag_stream_info->index_entry = index_entry_pos;
5893
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info->index_base < 0)
5894 388 frag_stream_info->index_base = index_entry_pos;
5895 }
5896
5897
2/2
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 14 times.
388 if (index_entry_pos > 0)
5898 374 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
5899
5900
3/4
✓ Branch 0 taken 6066 times.
✓ Branch 1 taken 388 times.
✓ Branch 2 taken 6066 times.
✗ Branch 3 not taken.
6454 for (i = 0; i < entries && !pb->eof_reached; i++) {
5901 6066 unsigned sample_size = frag->size;
5902
2/2
✓ Branch 0 taken 5678 times.
✓ Branch 1 taken 388 times.
6066 int sample_flags = i ? frag->flags : first_sample_flags;
5903 6066 unsigned sample_duration = frag->duration;
5904 6066 unsigned ctts_duration = 0;
5905 6066 int keyframe = 0;
5906 6066 int index_entry_flags = 0;
5907
5908
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 5594 times.
6066 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
5909
2/2
✓ Branch 0 taken 6034 times.
✓ Branch 1 taken 32 times.
6066 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
5910
2/2
✓ Branch 0 taken 933 times.
✓ Branch 1 taken 5133 times.
6066 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
5911
2/2
✓ Branch 0 taken 5400 times.
✓ Branch 1 taken 666 times.
6066 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
5912
5913 6066 mov_update_dts_shift(sc, ctts_duration, c->fc);
5914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6066 times.
6066 if (pts != AV_NOPTS_VALUE) {
5915 dts = pts - sc->dts_shift;
5916 if (flags & MOV_TRUN_SAMPLE_CTS) {
5917 dts -= ctts_duration;
5918 } else {
5919 dts -= sc->time_offset;
5920 }
5921 av_log(c->fc, AV_LOG_DEBUG,
5922 "pts %"PRId64" calculated dts %"PRId64
5923 " sc->dts_shift %d ctts.duration %d"
5924 " sc->time_offset %"PRId64
5925 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
5926 pts, dts,
5927 sc->dts_shift, ctts_duration,
5928 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
5929 pts = AV_NOPTS_VALUE;
5930 }
5931
5932 6066 keyframe =
5933 6066 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
5934 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
5935
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 5666 times.
6066 if (keyframe) {
5936 400 distance = 0;
5937 400 index_entry_flags |= AVINDEX_KEYFRAME;
5938 }
5939 // Fragments can overlap in time. Discard overlapping frames after
5940 // decoding.
5941
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6042 times.
6066 if (prev_dts >= dts)
5942 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
5943
5944 6066 sti->index_entries[index_entry_pos].pos = offset;
5945 6066 sti->index_entries[index_entry_pos].timestamp = dts;
5946 6066 sti->index_entries[index_entry_pos].size = sample_size;
5947 6066 sti->index_entries[index_entry_pos].min_distance = distance;
5948 6066 sti->index_entries[index_entry_pos].flags = index_entry_flags;
5949
5950 6066 sc->tts_data[index_entry_pos].count = 1;
5951 6066 sc->tts_data[index_entry_pos].offset = ctts_duration;
5952 6066 sc->tts_data[index_entry_pos].duration = sample_duration;
5953 6066 index_entry_pos++;
5954
5955 6066 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
5956 "size %u, distance %d, keyframe %d\n", st->index,
5957 index_entry_pos, offset, dts, sample_size, distance, keyframe);
5958 6066 distance++;
5959
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6066 times.
6066 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
5960 return AVERROR_INVALIDDATA;
5961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6066 times.
6066 if (!sample_size)
5962 return AVERROR_INVALIDDATA;
5963 6066 dts += sample_duration;
5964 6066 offset += sample_size;
5965 6066 sc->data_size += sample_size;
5966
5967
1/2
✓ Branch 0 taken 6066 times.
✗ Branch 1 not taken.
6066 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
5968
1/2
✓ Branch 0 taken 6066 times.
✗ Branch 1 not taken.
6066 1 <= INT_MAX - sc->nb_frames_for_fps
5969 ) {
5970 6066 sc->duration_for_fps += sample_duration;
5971 6066 sc->nb_frames_for_fps ++;
5972 }
5973 }
5974
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info)
5975 388 frag_stream_info->next_trun_dts = dts + sc->time_offset;
5976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (i < entries) {
5977 // EOF found before reading all entries. Fix the hole this would
5978 // leave in index_entries and tts_data
5979 int gap = entries - i;
5980 memmove(sti->index_entries + index_entry_pos,
5981 sti->index_entries + index_entry_pos + gap,
5982 sizeof(*sti->index_entries) *
5983 (sti->nb_index_entries - (index_entry_pos + gap)));
5984 memmove(sc->tts_data + index_entry_pos,
5985 sc->tts_data + index_entry_pos + gap,
5986 sizeof(*sc->tts_data) *
5987 (sc->tts_count - (index_entry_pos + gap)));
5988
5989 sti->nb_index_entries -= gap;
5990 sc->tts_count -= gap;
5991 if (index_entry_pos < sc->current_sample) {
5992 sc->current_sample -= gap;
5993 }
5994 entries = i;
5995 }
5996
5997 // The end of this new fragment may overlap in time with the start
5998 // of the next fragment in index_entries. Mark the samples in the next
5999 // fragment that overlap with AVINDEX_DISCARD_FRAME
6000 388 prev_dts = AV_NOPTS_VALUE;
6001
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (index_entry_pos > 0)
6002 388 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
6004 if (prev_dts < sti->index_entries[i].timestamp)
6005 break;
6006 sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6007 }
6008
6009 // If a hole was created to insert the new index_entries into,
6010 // the index_entry recorded for all subsequent moof must
6011 // be incremented by the number of entries inserted.
6012 388 fix_frag_index_entries(&c->frag_index, next_frag_index,
6013 388 frag->track_id, entries);
6014
6015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (pb->eof_reached) {
6016 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6017 return AVERROR_EOF;
6018 }
6019
6020 388 frag->implicit_offset = offset;
6021
6022 388 sc->track_end = dts + sc->time_offset;
6023
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 379 times.
388 if (st->duration < sc->track_end)
6024 9 st->duration = sc->track_end;
6025
6026 388 return 0;
6027 }
6028
6029 43 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6030 {
6031 43 int64_t stream_size = avio_size(pb);
6032 43 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6033 uint8_t version, is_complete;
6034 int64_t offadd;
6035 unsigned i, j, track_id, item_count;
6036 43 AVStream *st = NULL;
6037 43 AVStream *ref_st = NULL;
6038 43 MOVStreamContext *sc, *ref_sc = NULL;
6039 AVRational timescale;
6040
6041 43 version = avio_r8(pb);
6042
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (version > 1) {
6043 avpriv_request_sample(c->fc, "sidx version %u", version);
6044 return 0;
6045 }
6046
6047 43 avio_rb24(pb); // flags
6048
6049 43 track_id = avio_rb32(pb); // Reference ID
6050
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 for (i = 0; i < c->fc->nb_streams; i++) {
6051 43 sc = c->fc->streams[i]->priv_data;
6052
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (sc->id == track_id) {
6053 43 st = c->fc->streams[i];
6054 43 break;
6055 }
6056 }
6057
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st) {
6058 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6059 return 0;
6060 }
6061
6062 43 sc = st->priv_data;
6063
6064 43 timescale = av_make_q(1, avio_rb32(pb));
6065
6066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (timescale.den <= 0) {
6067 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6068 return AVERROR_INVALIDDATA;
6069 }
6070
6071
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (version == 0) {
6072 43 pts = avio_rb32(pb);
6073 43 offadd= avio_rb32(pb);
6074 } else {
6075 pts = avio_rb64(pb);
6076 offadd= avio_rb64(pb);
6077 }
6078
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6079 return AVERROR_INVALIDDATA;
6080
6081 43 offset += (uint64_t)offadd;
6082
6083 43 avio_rb16(pb); // reserved
6084
6085 43 item_count = avio_rb16(pb);
6086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (item_count == 0)
6087 return AVERROR_INVALIDDATA;
6088
6089
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 43 times.
411 for (i = 0; i < item_count; i++) {
6090 int index;
6091 MOVFragmentStreamInfo * frag_stream_info;
6092 368 uint32_t size = avio_rb32(pb);
6093 368 uint32_t duration = avio_rb32(pb);
6094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 368 times.
368 if (size & 0x80000000) {
6095 avpriv_request_sample(c->fc, "sidx reference_type 1");
6096 return AVERROR_PATCHWELCOME;
6097 }
6098 368 avio_rb32(pb); // sap_flags
6099 368 timestamp = av_rescale_q(pts, timescale, st->time_base);
6100
6101 368 index = update_frag_index(c, offset);
6102 368 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6103
1/2
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
368 if (frag_stream_info)
6104 368 frag_stream_info->sidx_pts = timestamp;
6105
6106
1/2
✓ Branch 1 taken 368 times.
✗ Branch 2 not taken.
368 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6107
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 368 times.
368 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6108 )
6109 return AVERROR_INVALIDDATA;
6110 368 offset += size;
6111 368 pts += duration;
6112 }
6113
6114 43 st->duration = sc->track_end = pts;
6115
6116 43 sc->has_sidx = 1;
6117
6118 // See if the remaining bytes are just an mfra which we can ignore.
6119 43 is_complete = offset == stream_size;
6120
4/6
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
43 if (!is_complete && (pb->seekable & AVIO_SEEKABLE_NORMAL) && stream_size > 0 ) {
6121 int64_t ret;
6122 38 int64_t original_pos = avio_tell(pb);
6123
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
38 if (!c->have_read_mfra_size) {
6124
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6125 return ret;
6126 3 c->mfra_size = avio_rb32(pb);
6127 3 c->have_read_mfra_size = 1;
6128
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6129 return ret;
6130 }
6131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (offset == stream_size - c->mfra_size)
6132 is_complete = 1;
6133 }
6134
6135
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 38 times.
43 if (is_complete) {
6136 // Find first entry in fragment index that came from an sidx.
6137 // This will pretty much always be the first entry.
6138
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 5 times.
373 for (i = 0; i < c->frag_index.nb_items; i++) {
6139 368 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6140
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++) {
6141 MOVFragmentStreamInfo * si;
6142 5 si = &item->stream_info[j];
6143
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (si->sidx_pts != AV_NOPTS_VALUE) {
6144 5 ref_st = c->fc->streams[j];
6145 5 ref_sc = ref_st->priv_data;
6146 5 break;
6147 }
6148 }
6149 }
6150
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++) {
6151 5 st = c->fc->streams[i];
6152 5 sc = st->priv_data;
6153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->has_sidx) {
6154 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6155 }
6156 }
6157
6158 5 c->frag_index.complete = 1;
6159 }
6160
6161 43 return 0;
6162 }
6163
6164 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6165 /* like the files created with Adobe Premiere 5.0, for samples see */
6166 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6167 269 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6168 {
6169 int err;
6170
6171
1/2
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
269 if (atom.size < 8)
6172 269 return 0; /* continue */
6173 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6174 avio_skip(pb, atom.size - 4);
6175 return 0;
6176 }
6177 atom.type = avio_rl32(pb);
6178 atom.size -= 8;
6179 if (atom.type != MKTAG('m','d','a','t')) {
6180 avio_skip(pb, atom.size);
6181 return 0;
6182 }
6183 err = mov_read_mdat(c, pb, atom);
6184 return err;
6185 }
6186
6187 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6188 {
6189 #if CONFIG_ZLIB
6190 FFIOContext ctx;
6191 uint8_t *cmov_data;
6192 uint8_t *moov_data; /* uncompressed data */
6193 long cmov_len, moov_len;
6194 3 int ret = -1;
6195
6196 3 avio_rb32(pb); /* dcom atom */
6197
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6198 return AVERROR_INVALIDDATA;
6199
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6200 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6201 return AVERROR_INVALIDDATA;
6202 }
6203 3 avio_rb32(pb); /* cmvd atom */
6204
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6205 return AVERROR_INVALIDDATA;
6206 3 moov_len = avio_rb32(pb); /* uncompressed size */
6207 3 cmov_len = atom.size - 6 * 4;
6208
6209 3 cmov_data = av_malloc(cmov_len);
6210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6211 return AVERROR(ENOMEM);
6212 3 moov_data = av_malloc(moov_len);
6213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6214 av_free(cmov_data);
6215 return AVERROR(ENOMEM);
6216 }
6217 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6219 goto free_and_return;
6220
6221 3 ret = AVERROR_INVALIDDATA;
6222
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)
6223 goto free_and_return;
6224 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6225 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6226 3 atom.type = MKTAG('m','o','o','v');
6227 3 atom.size = moov_len;
6228 3 ret = mov_read_default(c, &ctx.pub, atom);
6229 3 free_and_return:
6230 3 av_free(moov_data);
6231 3 av_free(cmov_data);
6232 3 return ret;
6233 #else
6234 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6235 return AVERROR(ENOSYS);
6236 #endif
6237 }
6238
6239 /* edit list atom */
6240 442 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6241 {
6242 MOVStreamContext *sc;
6243 int i, edit_count, version;
6244 int64_t elst_entry_size;
6245
6246
2/4
✓ Branch 0 taken 442 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 442 times.
442 if (c->fc->nb_streams < 1 || c->ignore_editlist)
6247 return 0;
6248 442 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6249
6250 442 version = avio_r8(pb); /* version */
6251 442 avio_rb24(pb); /* flags */
6252 442 edit_count = avio_rb32(pb); /* entries */
6253 442 atom.size -= 8;
6254
6255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 442 times.
442 elst_entry_size = version == 1 ? 20 : 12;
6256
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 441 times.
442 if (atom.size != edit_count * elst_entry_size) {
6257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6258 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6259 edit_count, atom.size + 8);
6260 return AVERROR_INVALIDDATA;
6261 } else {
6262 1 edit_count = atom.size / elst_entry_size;
6263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6264 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6265 }
6266 }
6267 }
6268
6269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 442 times.
442 if (!edit_count)
6270 return 0;
6271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 442 times.
442 if (sc->elst_data)
6272 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6273 442 av_free(sc->elst_data);
6274 442 sc->elst_count = 0;
6275 442 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 442 times.
442 if (!sc->elst_data)
6277 return AVERROR(ENOMEM);
6278
6279 442 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6280
4/6
✓ Branch 0 taken 469 times.
✓ Branch 1 taken 442 times.
✓ Branch 2 taken 469 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 469 times.
✗ Branch 5 not taken.
911 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
6281 469 MOVElst *e = &sc->elst_data[i];
6282
6283
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 469 times.
469 if (version == 1) {
6284 e->duration = avio_rb64(pb);
6285 e->time = avio_rb64(pb);
6286 atom.size -= 16;
6287 } else {
6288 469 e->duration = avio_rb32(pb); /* segment duration */
6289 469 e->time = (int32_t)avio_rb32(pb); /* media time */
6290 469 atom.size -= 8;
6291 }
6292 469 e->rate = avio_rb32(pb) / 65536.0;
6293 469 atom.size -= 4;
6294 469 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6295 469 e->duration, e->time, e->rate);
6296
6297
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 465 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
469 if (e->time < 0 && e->time != -1 &&
6298 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6299 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6300 c->fc->nb_streams-1, i, e->time);
6301 return AVERROR_INVALIDDATA;
6302 }
6303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 469 times.
469 if (e->duration < 0) {
6304 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list duration=%"PRId64"\n",
6305 c->fc->nb_streams-1, i, e->duration);
6306 return AVERROR_INVALIDDATA;
6307 }
6308 }
6309 442 sc->elst_count = i;
6310
6311 442 return 0;
6312 }
6313
6314 18 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6315 {
6316 MOVStreamContext *sc;
6317
6318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->fc->nb_streams < 1)
6319 return AVERROR_INVALIDDATA;
6320 18 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6321 18 sc->timecode_track = avio_rb32(pb);
6322 18 return 0;
6323 }
6324
6325 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6326 {
6327 AVStream *st;
6328 int version, color_range, color_primaries, color_trc, color_space;
6329
6330 if (c->fc->nb_streams < 1)
6331 return 0;
6332 st = c->fc->streams[c->fc->nb_streams - 1];
6333
6334 if (atom.size < 5) {
6335 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6336 return AVERROR_INVALIDDATA;
6337 }
6338
6339 version = avio_r8(pb);
6340 if (version != 1) {
6341 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6342 return 0;
6343 }
6344 avio_skip(pb, 3); /* flags */
6345
6346 avio_skip(pb, 2); /* profile + level */
6347 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6348 color_primaries = avio_r8(pb);
6349 color_trc = avio_r8(pb);
6350 color_space = avio_r8(pb);
6351 if (avio_rb16(pb)) /* codecIntializationDataSize */
6352 return AVERROR_INVALIDDATA;
6353
6354 if (!av_color_primaries_name(color_primaries))
6355 color_primaries = AVCOL_PRI_UNSPECIFIED;
6356 if (!av_color_transfer_name(color_trc))
6357 color_trc = AVCOL_TRC_UNSPECIFIED;
6358 if (!av_color_space_name(color_space))
6359 color_space = AVCOL_SPC_UNSPECIFIED;
6360
6361 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6362 st->codecpar->color_primaries = color_primaries;
6363 st->codecpar->color_trc = color_trc;
6364 st->codecpar->color_space = color_space;
6365
6366 return 0;
6367 }
6368
6369 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6370 {
6371 MOVStreamContext *sc;
6372 int i, version;
6373
6374 if (c->fc->nb_streams < 1)
6375 return AVERROR_INVALIDDATA;
6376
6377 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6378
6379 if (atom.size < 5) {
6380 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6381 return AVERROR_INVALIDDATA;
6382 }
6383
6384 version = avio_r8(pb);
6385 if (version) {
6386 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6387 return 0;
6388 }
6389 if (sc->mastering) {
6390 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6391 return 0;
6392 }
6393
6394 avio_skip(pb, 3); /* flags */
6395
6396 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6397 if (!sc->mastering)
6398 return AVERROR(ENOMEM);
6399
6400 for (i = 0; i < 3; i++) {
6401 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6402 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6403 }
6404 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6405 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6406
6407 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6408 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6409
6410 sc->mastering->has_primaries = 1;
6411 sc->mastering->has_luminance = 1;
6412
6413 return 0;
6414 }
6415
6416 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6417 {
6418 MOVStreamContext *sc;
6419 const int mapping[3] = {1, 2, 0};
6420 const int chroma_den = 50000;
6421 const int luma_den = 10000;
6422 int i;
6423
6424 if (c->fc->nb_streams < 1)
6425 return AVERROR_INVALIDDATA;
6426
6427 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6428
6429 if (atom.size < 24) {
6430 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6431 return AVERROR_INVALIDDATA;
6432 }
6433
6434 if (sc->mastering) {
6435 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6436 return 0;
6437 }
6438
6439 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6440 if (!sc->mastering)
6441 return AVERROR(ENOMEM);
6442
6443 for (i = 0; i < 3; i++) {
6444 const int j = mapping[i];
6445 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6446 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6447 }
6448 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6449 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6450
6451 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6452 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6453
6454 sc->mastering->has_luminance = 1;
6455 sc->mastering->has_primaries = 1;
6456
6457 return 0;
6458 }
6459
6460 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6461 {
6462 MOVStreamContext *sc;
6463 int version;
6464
6465 if (c->fc->nb_streams < 1)
6466 return AVERROR_INVALIDDATA;
6467
6468 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6469
6470 if (atom.size < 5) {
6471 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
6472 return AVERROR_INVALIDDATA;
6473 }
6474
6475 version = avio_r8(pb);
6476 if (version) {
6477 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
6478 return 0;
6479 }
6480 avio_skip(pb, 3); /* flags */
6481
6482 if (sc->coll){
6483 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
6484 return 0;
6485 }
6486
6487 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6488 if (!sc->coll)
6489 return AVERROR(ENOMEM);
6490
6491 sc->coll->MaxCLL = avio_rb16(pb);
6492 sc->coll->MaxFALL = avio_rb16(pb);
6493
6494 return 0;
6495 }
6496
6497 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6498 {
6499 MOVStreamContext *sc;
6500
6501 if (c->fc->nb_streams < 1)
6502 return AVERROR_INVALIDDATA;
6503
6504 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6505
6506 if (atom.size < 4) {
6507 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
6508 return AVERROR_INVALIDDATA;
6509 }
6510
6511 if (sc->coll){
6512 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
6513 return 0;
6514 }
6515
6516 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6517 if (!sc->coll)
6518 return AVERROR(ENOMEM);
6519
6520 sc->coll->MaxCLL = avio_rb16(pb);
6521 sc->coll->MaxFALL = avio_rb16(pb);
6522
6523 return 0;
6524 }
6525
6526 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6527 {
6528 MOVStreamContext *sc;
6529 4 const int illuminance_den = 10000;
6530 4 const int ambient_den = 50000;
6531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
6532 return AVERROR_INVALIDDATA;
6533 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
6535 av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
6536 return AVERROR_INVALIDDATA;
6537 }
6538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
6539 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
6540 return 0;
6541 }
6542 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
6543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
6544 return AVERROR(ENOMEM);
6545 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
6546 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
6547 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
6548 4 return 0;
6549 }
6550
6551 1 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6552 {
6553 AVStream *st;
6554 MOVStreamContext *sc;
6555 enum AVStereo3DType type;
6556 int mode;
6557
6558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6559 return 0;
6560
6561 1 st = c->fc->streams[c->fc->nb_streams - 1];
6562 1 sc = st->priv_data;
6563
6564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 5) {
6565 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
6566 return AVERROR_INVALIDDATA;
6567 }
6568
6569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sc->stereo3d)
6570 return AVERROR_INVALIDDATA;
6571
6572 1 avio_skip(pb, 4); /* version + flags */
6573
6574 1 mode = avio_r8(pb);
6575
1/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 switch (mode) {
6576 1 case 0:
6577 1 type = AV_STEREO3D_2D;
6578 1 break;
6579 case 1:
6580 type = AV_STEREO3D_TOPBOTTOM;
6581 break;
6582 case 2:
6583 type = AV_STEREO3D_SIDEBYSIDE;
6584 break;
6585 default:
6586 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
6587 return 0;
6588 }
6589
6590 1 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->stereo3d)
6592 return AVERROR(ENOMEM);
6593
6594 1 sc->stereo3d->type = type;
6595 1 return 0;
6596 }
6597
6598 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6599 {
6600 AVStream *st;
6601 MOVStreamContext *sc;
6602 int size, version, layout;
6603 int32_t yaw, pitch, roll;
6604 1 uint32_t l = 0, t = 0, r = 0, b = 0;
6605 1 uint32_t tag, padding = 0;
6606 enum AVSphericalProjection projection;
6607
6608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6609 return 0;
6610
6611 1 st = c->fc->streams[c->fc->nb_streams - 1];
6612 1 sc = st->priv_data;
6613
6614
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
6615 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
6616 return AVERROR_INVALIDDATA;
6617 }
6618
6619 1 size = avio_rb32(pb);
6620
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)
6621 return AVERROR_INVALIDDATA;
6622
6623 1 tag = avio_rl32(pb);
6624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
6625 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
6626 return 0;
6627 }
6628 1 version = avio_r8(pb);
6629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6630 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6631 version);
6632 return 0;
6633 }
6634 1 avio_skip(pb, 3); /* flags */
6635 1 avio_skip(pb, size - 12); /* metadata_source */
6636
6637 1 size = avio_rb32(pb);
6638
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6639 return AVERROR_INVALIDDATA;
6640
6641 1 tag = avio_rl32(pb);
6642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
6643 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
6644 return 0;
6645 }
6646
6647 1 size = avio_rb32(pb);
6648
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6649 return AVERROR_INVALIDDATA;
6650
6651 1 tag = avio_rl32(pb);
6652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
6653 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
6654 return 0;
6655 }
6656 1 version = avio_r8(pb);
6657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6658 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6659 version);
6660 return 0;
6661 }
6662 1 avio_skip(pb, 3); /* flags */
6663
6664 /* 16.16 fixed point */
6665 1 yaw = avio_rb32(pb);
6666 1 pitch = avio_rb32(pb);
6667 1 roll = avio_rb32(pb);
6668
6669 1 size = avio_rb32(pb);
6670
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6671 return AVERROR_INVALIDDATA;
6672
6673 1 tag = avio_rl32(pb);
6674 1 version = avio_r8(pb);
6675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6676 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6677 version);
6678 return 0;
6679 }
6680 1 avio_skip(pb, 3); /* flags */
6681
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
6682 case MKTAG('c','b','m','p'):
6683 layout = avio_rb32(pb);
6684 if (layout) {
6685 av_log(c->fc, AV_LOG_WARNING,
6686 "Unsupported cubemap layout %d\n", layout);
6687 return 0;
6688 }
6689 projection = AV_SPHERICAL_CUBEMAP;
6690 padding = avio_rb32(pb);
6691 break;
6692 1 case MKTAG('e','q','u','i'):
6693 1 t = avio_rb32(pb);
6694 1 b = avio_rb32(pb);
6695 1 l = avio_rb32(pb);
6696 1 r = avio_rb32(pb);
6697
6698
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) {
6699 av_log(c->fc, AV_LOG_ERROR,
6700 "Invalid bounding rectangle coordinates "
6701 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
6702 return AVERROR_INVALIDDATA;
6703 }
6704
6705
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)
6706 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
6707 else
6708 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6709 1 break;
6710 default:
6711 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
6712 return 0;
6713 }
6714
6715 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6716
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
6717 return AVERROR(ENOMEM);
6718
6719 1 sc->spherical->projection = projection;
6720
6721 1 sc->spherical->yaw = yaw;
6722 1 sc->spherical->pitch = pitch;
6723 1 sc->spherical->roll = roll;
6724
6725 1 sc->spherical->padding = padding;
6726
6727 1 sc->spherical->bound_left = l;
6728 1 sc->spherical->bound_top = t;
6729 1 sc->spherical->bound_right = r;
6730 1 sc->spherical->bound_bottom = b;
6731
6732 1 return 0;
6733 }
6734
6735 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6736 {
6737 AVStream *st;
6738 MOVStreamContext *sc;
6739 int size;
6740 uint32_t tag;
6741 enum AVSphericalProjection projection;
6742
6743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6744 return 0;
6745
6746 3 st = c->fc->streams[c->fc->nb_streams - 1];
6747 3 sc = st->priv_data;
6748
6749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 16) {
6750 av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
6751 return AVERROR_INVALIDDATA;
6752 }
6753
6754 3 size = avio_rb32(pb);
6755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 16) {
6756 av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
6757 return AVERROR_INVALIDDATA;
6758 }
6759
6760 3 tag = avio_rl32(pb);
6761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
6762 av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: 0x%08X\n", tag);
6763 return AVERROR_INVALIDDATA;
6764 }
6765
6766 3 avio_skip(pb, 1); // version
6767 3 avio_skip(pb, 3); // flags
6768
6769 3 tag = avio_rl32(pb);
6770
1/5
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
3 switch (tag) {
6771 3 case MKTAG('r','e','c','t'):
6772 3 projection = AV_SPHERICAL_RECTILINEAR;
6773 3 break;
6774 case MKTAG('e','q','u','i'):
6775 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6776 break;
6777 case MKTAG('h','e','q','u'):
6778 projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
6779 break;
6780 case MKTAG('f','i','s','h'):
6781 projection = AV_SPHERICAL_FISHEYE;
6782 break;
6783 default:
6784 av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: 0x%08X\n", tag);
6785 return AVERROR_INVALIDDATA;
6786 }
6787
6788 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
6790 return AVERROR(ENOMEM);
6791
6792 3 sc->spherical->projection = projection;
6793
6794 3 return 0;
6795 }
6796
6797 3 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6798 {
6799 AVStream *st;
6800 MOVStreamContext *sc;
6801 3 int size, flags = 0;
6802 int64_t remaining;
6803 3 uint32_t tag, baseline = 0;
6804 3 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
6805 3 enum AVStereo3DType type = AV_STEREO3D_2D;
6806 3 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
6807 3 AVRational horizontal_disparity_adjustment = { 0, 1 };
6808
6809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6810 return 0;
6811
6812 3 st = c->fc->streams[c->fc->nb_streams - 1];
6813 3 sc = st->priv_data;
6814
6815 3 remaining = atom.size;
6816
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 while (remaining > 0) {
6817 9 size = avio_rb32(pb);
6818
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 ) {
6819 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
6820 return AVERROR_INVALIDDATA;
6821 }
6822
6823 9 tag = avio_rl32(pb);
6824
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) {
6825 3 case MKTAG('s','t','r','i'): {
6826 int has_right, has_left;
6827 uint8_t tmp;
6828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 13) {
6829 av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
6830 return AVERROR_INVALIDDATA;
6831 }
6832 3 avio_skip(pb, 1); // version
6833 3 avio_skip(pb, 3); // flags
6834
6835 3 tmp = avio_r8(pb);
6836
6837 // eye_views_reversed
6838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tmp & 8) {
6839 flags |= AV_STEREO3D_FLAG_INVERT;
6840 }
6841 // has_additional_views
6842 3 if (tmp & 4) {
6843 // skip...
6844 }
6845
6846 3 has_right = tmp & 2; // has_right_eye_view
6847 3 has_left = tmp & 1; // has_left_eye_view
6848
6849
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)
6850 3 view = AV_STEREO3D_VIEW_PACKED;
6851 else if (has_left)
6852 view = AV_STEREO3D_VIEW_LEFT;
6853 else if (has_right)
6854 view = AV_STEREO3D_VIEW_RIGHT;
6855
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)
6856 3 type = AV_STEREO3D_UNSPEC;
6857
6858 3 break;
6859 }
6860 case MKTAG('h','e','r','o'): {
6861 int tmp;
6862 if (size != 13) {
6863 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
6864 return AVERROR_INVALIDDATA;
6865 }
6866 avio_skip(pb, 1); // version
6867 avio_skip(pb, 3); // flags
6868
6869 tmp = avio_r8(pb);
6870 if (tmp == 0)
6871 primary_eye = AV_PRIMARY_EYE_NONE;
6872 else if (tmp == 1)
6873 primary_eye = AV_PRIMARY_EYE_LEFT;
6874 else if (tmp == 2)
6875 primary_eye = AV_PRIMARY_EYE_RIGHT;
6876 else
6877 av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
6878
6879 break;
6880 }
6881 3 case MKTAG('c','a','m','s'): {
6882 uint32_t subtag;
6883 int subsize;
6884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
6885 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
6886 return AVERROR_INVALIDDATA;
6887 }
6888
6889 3 subsize = avio_rb32(pb);
6890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
6891 av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
6892 return AVERROR_INVALIDDATA;
6893 }
6894
6895 3 subtag = avio_rl32(pb);
6896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
6897 av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got 0x%08X\n", subtag);
6898 return AVERROR_INVALIDDATA;
6899 }
6900
6901 3 avio_skip(pb, 1); // version
6902 3 avio_skip(pb, 3); // flags
6903
6904 3 baseline = avio_rb32(pb);
6905
6906 3 break;
6907 }
6908 3 case MKTAG('c','m','f','y'): {
6909 uint32_t subtag;
6910 int subsize;
6911 int32_t adjustment;
6912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
6913 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
6914 return AVERROR_INVALIDDATA;
6915 }
6916
6917 3 subsize = avio_rb32(pb);
6918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
6919 av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
6920 return AVERROR_INVALIDDATA;
6921 }
6922
6923 3 subtag = avio_rl32(pb);
6924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
6925 av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got 0x%08X\n", subtag);
6926 return AVERROR_INVALIDDATA;
6927 }
6928
6929 3 avio_skip(pb, 1); // version
6930 3 avio_skip(pb, 3); // flags
6931
6932 3 adjustment = (int32_t) avio_rb32(pb);
6933
6934 3 horizontal_disparity_adjustment.num = (int) adjustment;
6935 3 horizontal_disparity_adjustment.den = 10000;
6936
6937 3 break;
6938 }
6939 default:
6940 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: 0x%08X\n", tag);
6941 avio_skip(pb, size - 8);
6942 break;
6943 }
6944 9 remaining -= size;
6945 }
6946
6947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
6948 av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
6949 return AVERROR_INVALIDDATA;
6950 }
6951
6952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (type == AV_STEREO3D_2D)
6953 return 0;
6954
6955
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->stereo3d) {
6956 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
6958 return AVERROR(ENOMEM);
6959 }
6960
6961 3 sc->stereo3d->flags = flags;
6962 3 sc->stereo3d->type = type;
6963 3 sc->stereo3d->view = view;
6964 3 sc->stereo3d->primary_eye = primary_eye;
6965 3 sc->stereo3d->baseline = baseline;
6966 3 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
6967
6968 3 return 0;
6969 }
6970
6971 3 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6972 {
6973 int size;
6974 int64_t remaining;
6975 uint32_t tag;
6976
6977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6978 return 0;
6979
6980
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8) {
6981 av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
6982 return AVERROR_INVALIDDATA;
6983 }
6984
6985 3 remaining = atom.size;
6986
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 while (remaining > 0) {
6987 6 size = avio_rb32(pb);
6988
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 ) {
6989 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
6990 return AVERROR_INVALIDDATA;
6991 }
6992
6993 6 tag = avio_rl32(pb);
6994
2/3
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 switch (tag) {
6995 3 case MKTAG('p','r','o','j'): {
6996 3 MOVAtom proj = { tag, size - 8 };
6997 3 int ret = mov_read_vexu_proj(c, pb, proj);
6998
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6999 return ret;
7000 3 break;
7001 }
7002 3 case MKTAG('e','y','e','s'): {
7003 3 MOVAtom eyes = { tag, size - 8 };
7004 3 int ret = mov_read_eyes(c, pb, eyes);
7005
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7006 return ret;
7007 3 break;
7008 }
7009 default:
7010 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: 0x%08X\n", tag);
7011 avio_skip(pb, size - 8);
7012 break;
7013 }
7014 6 remaining -= size;
7015 }
7016
7017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7018 av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7019 return AVERROR_INVALIDDATA;
7020 }
7021
7022 3 return 0;
7023 }
7024
7025 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7026 {
7027 AVStream *st;
7028 MOVStreamContext *sc;
7029
7030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7031 return 0;
7032
7033 3 st = c->fc->streams[c->fc->nb_streams - 1];
7034 3 sc = st->priv_data;
7035
7036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7037 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7038 return AVERROR_INVALIDDATA;
7039 }
7040
7041
7042
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7043 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7044 if (!sc->stereo3d)
7045 return AVERROR(ENOMEM);
7046 }
7047
7048 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7049 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7050
7051 3 return 0;
7052 }
7053
7054 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7055 {
7056 int ret = 0;
7057 uint8_t *buffer = av_malloc(len + 1);
7058 const char *val;
7059
7060 if (!buffer)
7061 return AVERROR(ENOMEM);
7062 buffer[len] = '\0';
7063
7064 ret = ffio_read_size(pb, buffer, len);
7065 if (ret < 0)
7066 goto out;
7067
7068 /* Check for mandatory keys and values, try to support XML as best-effort */
7069 if (!sc->spherical &&
7070 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7071 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7072 av_stristr(val, "true") &&
7073 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7074 av_stristr(val, "true") &&
7075 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7076 av_stristr(val, "equirectangular")) {
7077 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7078 if (!sc->spherical)
7079 goto out;
7080
7081 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7082
7083 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7084 enum AVStereo3DType mode;
7085
7086 if (av_stristr(buffer, "left-right"))
7087 mode = AV_STEREO3D_SIDEBYSIDE;
7088 else if (av_stristr(buffer, "top-bottom"))
7089 mode = AV_STEREO3D_TOPBOTTOM;
7090 else
7091 mode = AV_STEREO3D_2D;
7092
7093 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7094 if (!sc->stereo3d)
7095 goto out;
7096
7097 sc->stereo3d->type = mode;
7098 }
7099
7100 /* orientation */
7101 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7102 if (val)
7103 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7104 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7105 if (val)
7106 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7107 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7108 if (val)
7109 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7110 }
7111
7112 out:
7113 av_free(buffer);
7114 return ret;
7115 }
7116
7117 15 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7118 {
7119 AVStream *st;
7120 MOVStreamContext *sc;
7121 int64_t ret;
7122 AVUUID uuid;
7123 static const AVUUID uuid_isml_manifest = {
7124 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7125 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7126 };
7127 static const AVUUID uuid_xmp = {
7128 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7129 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7130 };
7131 static const AVUUID uuid_spherical = {
7132 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7133 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7134 };
7135
7136
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 if (atom.size < AV_UUID_LEN || atom.size >= FFMIN(INT_MAX, SIZE_MAX))
7137 return AVERROR_INVALIDDATA;
7138
7139
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 14 times.
15 if (c->fc->nb_streams < 1)
7140 1 return 0;
7141 14 st = c->fc->streams[c->fc->nb_streams - 1];
7142 14 sc = st->priv_data;
7143
7144 14 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0)
7146 return ret;
7147
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7148 uint8_t *buffer, *ptr;
7149 char *endptr;
7150 size_t len = atom.size - AV_UUID_LEN;
7151
7152 if (len < 4) {
7153 return AVERROR_INVALIDDATA;
7154 }
7155 ret = avio_skip(pb, 4); // zeroes
7156 len -= 4;
7157
7158 buffer = av_mallocz(len + 1);
7159 if (!buffer) {
7160 return AVERROR(ENOMEM);
7161 }
7162 ret = ffio_read_size(pb, buffer, len);
7163 if (ret < 0) {
7164 av_free(buffer);
7165 return ret;
7166 }
7167
7168 ptr = buffer;
7169 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7170 ptr += sizeof("systemBitrate=\"") - 1;
7171 c->bitrates_count++;
7172 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7173 if (!c->bitrates) {
7174 c->bitrates_count = 0;
7175 av_free(buffer);
7176 return AVERROR(ENOMEM);
7177 }
7178 errno = 0;
7179 ret = strtol(ptr, &endptr, 10);
7180 if (ret < 0 || errno || *endptr != '"') {
7181 c->bitrates[c->bitrates_count - 1] = 0;
7182 } else {
7183 c->bitrates[c->bitrates_count - 1] = ret;
7184 }
7185 }
7186
7187 av_free(buffer);
7188
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7189 uint8_t *buffer;
7190 size_t len = atom.size - AV_UUID_LEN;
7191 if (c->export_xmp) {
7192 buffer = av_mallocz(len + 1);
7193 if (!buffer) {
7194 return AVERROR(ENOMEM);
7195 }
7196 ret = ffio_read_size(pb, buffer, len);
7197 if (ret < 0) {
7198 av_free(buffer);
7199 return ret;
7200 }
7201 buffer[len] = '\0';
7202 av_dict_set(&c->fc->metadata, "xmp",
7203 buffer, AV_DICT_DONT_STRDUP_VAL);
7204 } else {
7205 // skip all uuid atom, which makes it fast for long uuid-xmp file
7206 ret = avio_skip(pb, len);
7207 if (ret < 0)
7208 return ret;
7209 }
7210
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7211 size_t len = atom.size - AV_UUID_LEN;
7212 ret = mov_parse_uuid_spherical(sc, pb, len);
7213 if (ret < 0)
7214 return ret;
7215 if (!sc->spherical)
7216 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7217 }
7218
7219 14 return 0;
7220 }
7221
7222 188 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7223 {
7224 int ret;
7225 uint8_t content[16];
7226
7227
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 96 times.
188 if (atom.size < 8)
7228 92 return 0;
7229
7230 96 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (ret < 0)
7232 return ret;
7233
7234
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 55 times.
96 if ( !c->found_moov
7235
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 23 times.
41 && !c->found_mdat
7236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 && !memcmp(content, "Anevia\x1A\x1A", 8)
7237 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7238 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7239 }
7240
7241 96 return 0;
7242 }
7243
7244 35 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7245 {
7246 35 uint32_t format = avio_rl32(pb);
7247 MOVStreamContext *sc;
7248 enum AVCodecID id;
7249 AVStream *st;
7250
7251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (c->fc->nb_streams < 1)
7252 return 0;
7253 35 st = c->fc->streams[c->fc->nb_streams - 1];
7254 35 sc = st->priv_data;
7255
7256
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 32 times.
35 switch (sc->format)
7257 {
7258 3 case MKTAG('e','n','c','v'): // encrypted video
7259 case MKTAG('e','n','c','a'): // encrypted audio
7260 3 id = mov_codec_id(st, format);
7261
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7262 st->codecpar->codec_id != id) {
7263 av_log(c->fc, AV_LOG_WARNING,
7264 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7265 (char*)&format, st->codecpar->codec_id);
7266 break;
7267 }
7268
7269 3 st->codecpar->codec_id = id;
7270 3 sc->format = format;
7271 3 break;
7272
7273 32 default:
7274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (format != sc->format) {
7275 av_log(c->fc, AV_LOG_WARNING,
7276 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7277 (char*)&format, (char*)&sc->format);
7278 }
7279 32 break;
7280 }
7281
7282 35 return 0;
7283 }
7284
7285 /**
7286 * Gets the current encryption info and associated current stream context. If
7287 * we are parsing a track fragment, this will return the specific encryption
7288 * info for this fragment; otherwise this will return the global encryption
7289 * info for the current stream.
7290 */
7291 6 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7292 {
7293 MOVFragmentStreamInfo *frag_stream_info;
7294 AVStream *st;
7295 int i;
7296
7297 6 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7298
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (frag_stream_info) {
7299
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 for (i = 0; i < c->fc->nb_streams; i++) {
7300 3 *sc = c->fc->streams[i]->priv_data;
7301
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if ((*sc)->id == frag_stream_info->id) {
7302 3 st = c->fc->streams[i];
7303 3 break;
7304 }
7305 }
7306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (i == c->fc->nb_streams)
7307 return 0;
7308 3 *sc = st->priv_data;
7309
7310
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!frag_stream_info->encryption_index) {
7311 // If this stream isn't encrypted, don't create the index.
7312
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!(*sc)->cenc.default_encrypted_sample)
7313 return 0;
7314 1 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!frag_stream_info->encryption_index)
7316 return AVERROR(ENOMEM);
7317 }
7318 3 *encryption_index = frag_stream_info->encryption_index;
7319 3 return 1;
7320 } else {
7321 // No current track fragment, using stream level encryption info.
7322
7323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7324 return 0;
7325 3 st = c->fc->streams[c->fc->nb_streams - 1];
7326 3 *sc = st->priv_data;
7327
7328
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!(*sc)->cenc.encryption_index) {
7329 // If this stream isn't encrypted, don't create the index.
7330 if (!(*sc)->cenc.default_encrypted_sample)
7331 return 0;
7332 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7333 if (!(*sc)->cenc.encryption_index)
7334 return AVERROR(ENOMEM);
7335 }
7336
7337 3 *encryption_index = (*sc)->cenc.encryption_index;
7338 3 return 1;
7339 }
7340 }
7341
7342 72 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7343 {
7344 int i, ret;
7345 unsigned int subsample_count;
7346 AVSubsampleEncryptionInfo *subsamples;
7347
7348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!sc->cenc.default_encrypted_sample) {
7349 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7350 return AVERROR_INVALIDDATA;
7351 }
7352
7353
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) {
7354 72 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!*sample)
7356 return AVERROR(ENOMEM);
7357 } else
7358 *sample = NULL;
7359
7360
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (sc->cenc.per_sample_iv_size != 0) {
7361
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) {
7362 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
7363 av_encryption_info_free(*sample);
7364 *sample = NULL;
7365 return ret;
7366 }
7367 }
7368
7369
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (use_subsamples) {
7370 72 subsample_count = avio_rb16(pb);
7371 72 av_free((*sample)->subsamples);
7372 72 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
7373
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!(*sample)->subsamples) {
7374 av_encryption_info_free(*sample);
7375 *sample = NULL;
7376 return AVERROR(ENOMEM);
7377 }
7378
7379
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++) {
7380 72 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
7381 72 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
7382 }
7383
7384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (pb->eof_reached) {
7385 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
7386 av_encryption_info_free(*sample);
7387 *sample = NULL;
7388 return AVERROR_INVALIDDATA;
7389 }
7390 72 (*sample)->subsample_count = subsample_count;
7391 }
7392
7393 72 return 0;
7394 }
7395
7396 2 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7397 {
7398 AVEncryptionInfo **encrypted_samples;
7399 MOVEncryptionIndex *encryption_index;
7400 MOVStreamContext *sc;
7401 int use_subsamples, ret;
7402 2 unsigned int sample_count, i, alloc_size = 0;
7403
7404 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7406 return ret;
7407
7408
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7409 // This can happen if we have both saio/saiz and senc atoms.
7410 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
7411 1 return 0;
7412 }
7413
7414 1 avio_r8(pb); /* version */
7415 1 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
7416
7417 1 sample_count = avio_rb32(pb);
7418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7419 return AVERROR(ENOMEM);
7420
7421
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1 times.
49 for (i = 0; i < sample_count; i++) {
7422 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7423 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7424 min_samples * sizeof(*encrypted_samples));
7425
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (encrypted_samples) {
7426 48 encryption_index->encrypted_samples = encrypted_samples;
7427
7428 48 ret = mov_read_sample_encryption_info(
7429 48 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
7430 } else {
7431 ret = AVERROR(ENOMEM);
7432 }
7433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (pb->eof_reached) {
7434 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
7435 if (ret >= 0)
7436 av_encryption_info_free(encryption_index->encrypted_samples[i]);
7437 ret = AVERROR_INVALIDDATA;
7438 }
7439
7440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0) {
7441 for (; i > 0; i--)
7442 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7443 av_freep(&encryption_index->encrypted_samples);
7444 return ret;
7445 }
7446 }
7447 1 encryption_index->nb_encrypted_samples = sample_count;
7448
7449 1 return 0;
7450 }
7451
7452 1 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
7453 {
7454 AVEncryptionInfo **sample, **encrypted_samples;
7455 int64_t prev_pos;
7456 size_t sample_count, sample_info_size, i;
7457 1 int ret = 0;
7458 1 unsigned int alloc_size = 0;
7459
7460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->nb_encrypted_samples)
7461 return 0;
7462 1 sample_count = encryption_index->auxiliary_info_sample_count;
7463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count != 1) {
7464 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
7465 return AVERROR_PATCHWELCOME;
7466 }
7467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7468 return AVERROR(ENOMEM);
7469
7470 1 prev_pos = avio_tell(pb);
7471
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
7472
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]) {
7473 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
7474 goto finish;
7475 }
7476
7477
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++) {
7478 24 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7479 24 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7480 min_samples * sizeof(*encrypted_samples));
7481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!encrypted_samples) {
7482 ret = AVERROR(ENOMEM);
7483 goto finish;
7484 }
7485 24 encryption_index->encrypted_samples = encrypted_samples;
7486
7487 24 sample = &encryption_index->encrypted_samples[i];
7488 48 sample_info_size = encryption_index->auxiliary_info_default_size
7489 24 ? encryption_index->auxiliary_info_default_size
7490
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 : encryption_index->auxiliary_info_sizes[i];
7491
7492 24 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
7493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (ret < 0)
7494 goto finish;
7495 }
7496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7497 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
7498 ret = AVERROR_INVALIDDATA;
7499 } else {
7500 1 encryption_index->nb_encrypted_samples = sample_count;
7501 }
7502
7503 1 finish:
7504 1 avio_seek(pb, prev_pos, SEEK_SET);
7505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
7506 for (; i > 0; i--) {
7507 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7508 }
7509 av_freep(&encryption_index->encrypted_samples);
7510 }
7511 1 return ret;
7512 }
7513
7514 2 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7515 {
7516 MOVEncryptionIndex *encryption_index;
7517 MOVStreamContext *sc;
7518 int ret;
7519 unsigned int sample_count, aux_info_type, aux_info_param;
7520
7521 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7523 return ret;
7524
7525
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7526 // This can happen if we have both saio/saiz and senc atoms.
7527 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
7528 1 return 0;
7529 }
7530
7531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_sample_count) {
7532 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
7533 return AVERROR_INVALIDDATA;
7534 }
7535
7536 1 avio_r8(pb); /* version */
7537
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7538 aux_info_type = avio_rb32(pb);
7539 aux_info_param = avio_rb32(pb);
7540 if (sc->cenc.default_encrypted_sample) {
7541 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7542 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
7543 return 0;
7544 }
7545 if (aux_info_param != 0) {
7546 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
7547 return 0;
7548 }
7549 } else {
7550 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7551 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7552 aux_info_type == MKBETAG('c','e','n','s') ||
7553 aux_info_type == MKBETAG('c','b','c','1') ||
7554 aux_info_type == MKBETAG('c','b','c','s')) &&
7555 aux_info_param == 0) {
7556 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
7557 return AVERROR_INVALIDDATA;
7558 } else {
7559 return 0;
7560 }
7561 }
7562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7563 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7564 return 0;
7565 }
7566
7567 1 encryption_index->auxiliary_info_default_size = avio_r8(pb);
7568 1 sample_count = avio_rb32(pb);
7569
7570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_default_size == 0) {
7571 if (sample_count == 0)
7572 return AVERROR_INVALIDDATA;
7573
7574 encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
7575 if (!encryption_index->auxiliary_info_sizes)
7576 return AVERROR(ENOMEM);
7577
7578 ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
7579 if (ret != sample_count) {
7580 av_freep(&encryption_index->auxiliary_info_sizes);
7581
7582 if (ret >= 0)
7583 ret = AVERROR_INVALIDDATA;
7584 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
7585 av_err2str(ret));
7586 return ret;
7587 }
7588 }
7589 1 encryption_index->auxiliary_info_sample_count = sample_count;
7590
7591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7592 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7593 }
7594
7595 1 return 0;
7596 }
7597
7598 2 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7599 {
7600 uint64_t *auxiliary_offsets;
7601 MOVEncryptionIndex *encryption_index;
7602 MOVStreamContext *sc;
7603 int i, ret;
7604 unsigned int version, entry_count, aux_info_type, aux_info_param;
7605 2 unsigned int alloc_size = 0;
7606
7607 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7609 return ret;
7610
7611
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7612 // This can happen if we have both saio/saiz and senc atoms.
7613 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
7614 1 return 0;
7615 }
7616
7617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7618 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
7619 return AVERROR_INVALIDDATA;
7620 }
7621
7622 1 version = avio_r8(pb); /* version */
7623
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7624 aux_info_type = avio_rb32(pb);
7625 aux_info_param = avio_rb32(pb);
7626 if (sc->cenc.default_encrypted_sample) {
7627 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7628 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
7629 return 0;
7630 }
7631 if (aux_info_param != 0) {
7632 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
7633 return 0;
7634 }
7635 } else {
7636 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7637 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7638 aux_info_type == MKBETAG('c','e','n','s') ||
7639 aux_info_type == MKBETAG('c','b','c','1') ||
7640 aux_info_type == MKBETAG('c','b','c','s')) &&
7641 aux_info_param == 0) {
7642 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
7643 return AVERROR_INVALIDDATA;
7644 } else {
7645 return 0;
7646 }
7647 }
7648
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7649 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7650 return 0;
7651 }
7652
7653 1 entry_count = avio_rb32(pb);
7654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
7655 return AVERROR(ENOMEM);
7656
7657
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++) {
7658
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);
7659 1 auxiliary_offsets = av_fast_realloc(
7660 1 encryption_index->auxiliary_offsets, &alloc_size,
7661 min_offsets * sizeof(*auxiliary_offsets));
7662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!auxiliary_offsets) {
7663 av_freep(&encryption_index->auxiliary_offsets);
7664 return AVERROR(ENOMEM);
7665 }
7666 1 encryption_index->auxiliary_offsets = auxiliary_offsets;
7667
7668
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (version == 0) {
7669 1 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
7670 } else {
7671 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
7672 }
7673
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (c->frag_index.current >= 0) {
7674 1 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
7675 }
7676 }
7677
7678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7679 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
7680 av_freep(&encryption_index->auxiliary_offsets);
7681 return AVERROR_INVALIDDATA;
7682 }
7683
7684 1 encryption_index->auxiliary_offsets_count = entry_count;
7685
7686
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (encryption_index->auxiliary_info_sample_count) {
7687 1 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7688 }
7689
7690 return 0;
7691 }
7692
7693 2 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7694 {
7695 AVEncryptionInitInfo *info, *old_init_info;
7696 uint8_t **key_ids;
7697 AVStream *st;
7698 const AVPacketSideData *old_side_data;
7699 uint8_t *side_data, *extra_data;
7700 size_t side_data_size;
7701 2 int ret = 0;
7702 2 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
7703
7704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
7705 return 0;
7706 2 st = c->fc->streams[c->fc->nb_streams-1];
7707
7708 2 version = avio_r8(pb); /* version */
7709 2 avio_rb24(pb); /* flags */
7710
7711 2 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
7712 /* key_id_size */ 16, /* data_size */ 0);
7713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info)
7714 return AVERROR(ENOMEM);
7715
7716
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
7717 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
7718 goto finish;
7719 }
7720
7721
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version > 0) {
7722 2 kid_count = avio_rb32(pb);
7723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
7724 ret = AVERROR(ENOMEM);
7725 goto finish;
7726 }
7727
7728
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++) {
7729 2 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
7730 2 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
7731 min_kid_count * sizeof(*key_ids));
7732
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!key_ids) {
7733 ret = AVERROR(ENOMEM);
7734 goto finish;
7735 }
7736 2 info->key_ids = key_ids;
7737
7738 2 info->key_ids[i] = av_mallocz(16);
7739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info->key_ids[i]) {
7740 ret = AVERROR(ENOMEM);
7741 goto finish;
7742 }
7743 2 info->num_key_ids = i + 1;
7744
7745
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
7746 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
7747 goto finish;
7748 }
7749 }
7750
7751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
7752 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
7753 ret = AVERROR_INVALIDDATA;
7754 goto finish;
7755 }
7756 }
7757
7758 2 extra_data_size = avio_rb32(pb);
7759 2 extra_data = av_malloc(extra_data_size);
7760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!extra_data) {
7761 ret = AVERROR(ENOMEM);
7762 goto finish;
7763 }
7764 2 ret = avio_read(pb, extra_data, extra_data_size);
7765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != extra_data_size) {
7766 av_free(extra_data);
7767
7768 if (ret >= 0)
7769 ret = AVERROR_INVALIDDATA;
7770 goto finish;
7771 }
7772
7773 2 av_freep(&info->data); // malloc(0) may still allocate something.
7774 2 info->data = extra_data;
7775 2 info->data_size = extra_data_size;
7776
7777 // If there is existing initialization data, append to the list.
7778 2 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
7779 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
7780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (old_side_data) {
7781 old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
7782 if (old_init_info) {
7783 // Append to the end of the list.
7784 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
7785 if (!cur->next) {
7786 cur->next = info;
7787 break;
7788 }
7789 }
7790 info = old_init_info;
7791 } else {
7792 // Assume existing side-data will be valid, so the only error we could get is OOM.
7793 ret = AVERROR(ENOMEM);
7794 goto finish;
7795 }
7796 }
7797
7798 2 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
7799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!side_data) {
7800 ret = AVERROR(ENOMEM);
7801 goto finish;
7802 }
7803
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
7804 2 &st->codecpar->nb_coded_side_data,
7805 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
7806 side_data, side_data_size, 0))
7807 av_free(side_data);
7808
7809 2 finish:
7810 2 av_encryption_init_info_free(info);
7811 2 return ret;
7812 }
7813
7814 3 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7815 {
7816 AVStream *st;
7817 MOVStreamContext *sc;
7818
7819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7820 return 0;
7821 3 st = c->fc->streams[c->fc->nb_streams-1];
7822 3 sc = st->priv_data;
7823
7824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7825 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
7826 return AVERROR_PATCHWELCOME;
7827 }
7828
7829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8)
7830 return AVERROR_INVALIDDATA;
7831
7832 3 avio_rb32(pb); /* version and flags */
7833
7834
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->cenc.default_encrypted_sample) {
7835 3 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7837 return AVERROR(ENOMEM);
7838 }
7839 }
7840
7841 3 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
7842 3 return 0;
7843 }
7844
7845 3 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7846 {
7847 AVStream *st;
7848 MOVStreamContext *sc;
7849 unsigned int version, pattern, is_protected, iv_size;
7850
7851
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7852 return 0;
7853 3 st = c->fc->streams[c->fc->nb_streams-1];
7854 3 sc = st->priv_data;
7855
7856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7857 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
7858 return AVERROR_PATCHWELCOME;
7859 }
7860
7861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7862 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7863 if (!sc->cenc.default_encrypted_sample) {
7864 return AVERROR(ENOMEM);
7865 }
7866 }
7867
7868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 20)
7869 return AVERROR_INVALIDDATA;
7870
7871 3 version = avio_r8(pb); /* version */
7872 3 avio_rb24(pb); /* flags */
7873
7874 3 avio_r8(pb); /* reserved */
7875 3 pattern = avio_r8(pb);
7876
7877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (version > 0) {
7878 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
7879 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
7880 }
7881
7882 3 is_protected = avio_r8(pb);
7883
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) {
7884 // The whole stream should be by-default encrypted.
7885 3 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
7886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.encryption_index)
7887 return AVERROR(ENOMEM);
7888 }
7889 3 sc->cenc.per_sample_iv_size = avio_r8(pb);
7890
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 &&
7891 sc->cenc.per_sample_iv_size != 16) {
7892 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
7893 return AVERROR_INVALIDDATA;
7894 }
7895
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) {
7896 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
7897 return AVERROR_INVALIDDATA;
7898 }
7899
7900
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) {
7901 1 iv_size = avio_r8(pb);
7902
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) {
7903 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
7904 return AVERROR_INVALIDDATA;
7905 }
7906
7907
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) {
7908 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
7909 return AVERROR_INVALIDDATA;
7910 }
7911 }
7912
7913 3 return 0;
7914 }
7915
7916 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7917 {
7918 AVStream *st;
7919 int last, type, size, ret;
7920 uint8_t buf[4];
7921
7922 if (c->fc->nb_streams < 1)
7923 return 0;
7924 st = c->fc->streams[c->fc->nb_streams-1];
7925
7926 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
7927 return AVERROR_INVALIDDATA;
7928
7929 /* Check FlacSpecificBox version. */
7930 if (avio_r8(pb) != 0)
7931 return AVERROR_INVALIDDATA;
7932
7933 avio_rb24(pb); /* Flags */
7934
7935 if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
7936 av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
7937 return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
7938 }
7939 flac_parse_block_header(buf, &last, &type, &size);
7940
7941 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
7942 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
7943 return AVERROR_INVALIDDATA;
7944 }
7945
7946 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
7947 if (ret < 0)
7948 return ret;
7949
7950 if (!last)
7951 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
7952
7953 return 0;
7954 }
7955
7956 146 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
7957 {
7958 int i, ret;
7959 int bytes_of_protected_data;
7960
7961
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 143 times.
146 if (!sc->cenc.aes_ctr) {
7962 /* initialize the cipher */
7963 3 sc->cenc.aes_ctr = av_aes_ctr_alloc();
7964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.aes_ctr) {
7965 return AVERROR(ENOMEM);
7966 }
7967
7968 3 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
7969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
7970 return ret;
7971 }
7972 }
7973
7974 146 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
7975
7976
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!sample->subsample_count) {
7977 /* decrypt the whole packet */
7978 48 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
7979 48 return 0;
7980 }
7981
7982
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 98 times.
196 for (i = 0; i < sample->subsample_count; i++) {
7983
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) {
7984 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
7985 return AVERROR_INVALIDDATA;
7986 }
7987
7988 /* skip the clear bytes */
7989 98 input += sample->subsamples[i].bytes_of_clear_data;
7990 98 size -= sample->subsamples[i].bytes_of_clear_data;
7991
7992 /* decrypt the encrypted bytes */
7993
7994 98 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
7995 98 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
7996
7997 98 input += bytes_of_protected_data;
7998 98 size -= bytes_of_protected_data;
7999 }
8000
8001
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (size > 0) {
8002 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8003 return AVERROR_INVALIDDATA;
8004 }
8005
8006 98 return 0;
8007 }
8008
8009 static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8010 {
8011 int i, ret;
8012 int num_of_encrypted_blocks;
8013 uint8_t iv[16];
8014
8015 if (!sc->cenc.aes_ctx) {
8016 /* initialize the cipher */
8017 sc->cenc.aes_ctx = av_aes_alloc();
8018 if (!sc->cenc.aes_ctx) {
8019 return AVERROR(ENOMEM);
8020 }
8021
8022 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8023 if (ret < 0) {
8024 return ret;
8025 }
8026 }
8027
8028 memcpy(iv, sample->iv, 16);
8029
8030 /* whole-block full sample encryption */
8031 if (!sample->subsample_count) {
8032 /* decrypt the whole packet */
8033 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8034 return 0;
8035 }
8036
8037 for (i = 0; i < sample->subsample_count; i++) {
8038 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8039 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8040 return AVERROR_INVALIDDATA;
8041 }
8042
8043 if (sample->subsamples[i].bytes_of_protected_data % 16) {
8044 av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8045 return AVERROR_INVALIDDATA;
8046 }
8047
8048 /* skip the clear bytes */
8049 input += sample->subsamples[i].bytes_of_clear_data;
8050 size -= sample->subsamples[i].bytes_of_clear_data;
8051
8052 /* decrypt the encrypted bytes */
8053 num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8054 if (num_of_encrypted_blocks > 0) {
8055 av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8056 }
8057 input += sample->subsamples[i].bytes_of_protected_data;
8058 size -= sample->subsamples[i].bytes_of_protected_data;
8059 }
8060
8061 if (size > 0) {
8062 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8063 return AVERROR_INVALIDDATA;
8064 }
8065
8066 return 0;
8067 }
8068
8069 static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8070 {
8071 int i, ret, rem_bytes;
8072 uint8_t *data;
8073
8074 if (!sc->cenc.aes_ctr) {
8075 /* initialize the cipher */
8076 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8077 if (!sc->cenc.aes_ctr) {
8078 return AVERROR(ENOMEM);
8079 }
8080
8081 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
8082 if (ret < 0) {
8083 return ret;
8084 }
8085 }
8086
8087 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8088
8089 /* whole-block full sample encryption */
8090 if (!sample->subsample_count) {
8091 /* decrypt the whole packet */
8092 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8093 return 0;
8094 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8095 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8096 return AVERROR_INVALIDDATA;
8097 }
8098
8099 for (i = 0; i < sample->subsample_count; i++) {
8100 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8101 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8102 return AVERROR_INVALIDDATA;
8103 }
8104
8105 /* skip the clear bytes */
8106 input += sample->subsamples[i].bytes_of_clear_data;
8107 size -= sample->subsamples[i].bytes_of_clear_data;
8108
8109 /* decrypt the encrypted bytes */
8110 data = input;
8111 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8112 while (rem_bytes > 0) {
8113 if (rem_bytes < 16*sample->crypt_byte_block) {
8114 break;
8115 }
8116 av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8117 data += 16*sample->crypt_byte_block;
8118 rem_bytes -= 16*sample->crypt_byte_block;
8119 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8120 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8121 }
8122 input += sample->subsamples[i].bytes_of_protected_data;
8123 size -= sample->subsamples[i].bytes_of_protected_data;
8124 }
8125
8126 if (size > 0) {
8127 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8128 return AVERROR_INVALIDDATA;
8129 }
8130
8131 return 0;
8132 }
8133
8134 static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8135 {
8136 int i, ret, rem_bytes;
8137 uint8_t iv[16];
8138 uint8_t *data;
8139
8140 if (!sc->cenc.aes_ctx) {
8141 /* initialize the cipher */
8142 sc->cenc.aes_ctx = av_aes_alloc();
8143 if (!sc->cenc.aes_ctx) {
8144 return AVERROR(ENOMEM);
8145 }
8146
8147 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8148 if (ret < 0) {
8149 return ret;
8150 }
8151 }
8152
8153 /* whole-block full sample encryption */
8154 if (!sample->subsample_count) {
8155 /* decrypt the whole packet */
8156 memcpy(iv, sample->iv, 16);
8157 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8158 return 0;
8159 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8160 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8161 return AVERROR_INVALIDDATA;
8162 }
8163
8164 for (i = 0; i < sample->subsample_count; i++) {
8165 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8166 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8167 return AVERROR_INVALIDDATA;
8168 }
8169
8170 /* skip the clear bytes */
8171 input += sample->subsamples[i].bytes_of_clear_data;
8172 size -= sample->subsamples[i].bytes_of_clear_data;
8173
8174 /* decrypt the encrypted bytes */
8175 memcpy(iv, sample->iv, 16);
8176 data = input;
8177 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8178 while (rem_bytes > 0) {
8179 if (rem_bytes < 16*sample->crypt_byte_block) {
8180 break;
8181 }
8182 av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8183 data += 16*sample->crypt_byte_block;
8184 rem_bytes -= 16*sample->crypt_byte_block;
8185 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8186 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8187 }
8188 input += sample->subsamples[i].bytes_of_protected_data;
8189 size -= sample->subsamples[i].bytes_of_protected_data;
8190 }
8191
8192 if (size > 0) {
8193 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8194 return AVERROR_INVALIDDATA;
8195 }
8196
8197 return 0;
8198 }
8199
8200 146 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8201 {
8202
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) {
8203 146 return cenc_scheme_decrypt(c, sc, sample, input, size);
8204 } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8205 return cbc1_scheme_decrypt(c, sc, sample, input, size);
8206 } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8207 return cens_scheme_decrypt(c, sc, sample, input, size);
8208 } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8209 return cbcs_scheme_decrypt(c, sc, sample, input, size);
8210 } else {
8211 av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8212 return AVERROR_INVALIDDATA;
8213 }
8214 }
8215
8216 96528 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8217 {
8218 96528 int current = frag_index->current;
8219
8220
2/2
✓ Branch 0 taken 95867 times.
✓ Branch 1 taken 661 times.
96528 if (!frag_index->nb_items)
8221 95867 return NULL;
8222
8223 // Check frag_index->current is the right one for pkt. It can out of sync.
8224
2/4
✓ Branch 0 taken 661 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 661 times.
✗ Branch 3 not taken.
661 if (current >= 0 && current < frag_index->nb_items) {
8225
2/2
✓ Branch 0 taken 639 times.
✓ Branch 1 taken 22 times.
661 if (frag_index->item[current].moof_offset < pkt->pos &&
8226
2/2
✓ Branch 0 taken 413 times.
✓ Branch 1 taken 226 times.
639 (current + 1 == frag_index->nb_items ||
8227
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 25 times.
413 frag_index->item[current + 1].moof_offset > pkt->pos))
8228 614 return get_frag_stream_info(frag_index, current, id);
8229 }
8230
8231
8232
2/2
✓ Branch 0 taken 3955 times.
✓ Branch 1 taken 4 times.
3959 for (int i = 0; i < frag_index->nb_items; i++) {
8233
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 3912 times.
3955 if (frag_index->item[i].moof_offset > pkt->pos)
8234 43 break;
8235 3912 current = i;
8236 }
8237 47 frag_index->current = current;
8238 47 return get_frag_stream_info(frag_index, current, id);
8239 }
8240
8241 96528 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8242 {
8243 MOVFragmentStreamInfo *frag_stream_info;
8244 MOVEncryptionIndex *encryption_index;
8245 AVEncryptionInfo *encrypted_sample;
8246 int encrypted_index, ret;
8247
8248 96528 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8249 96528 encrypted_index = current_index;
8250 96528 encryption_index = NULL;
8251
2/2
✓ Branch 0 taken 661 times.
✓ Branch 1 taken 95867 times.
96528 if (frag_stream_info) {
8252 // Note this only supports encryption info in the first sample descriptor.
8253
2/2
✓ Branch 0 taken 637 times.
✓ Branch 1 taken 24 times.
661 if (frag_stream_info->stsd_id == 1) {
8254
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 613 times.
637 if (frag_stream_info->encryption_index) {
8255 24 encrypted_index = current_index - frag_stream_info->index_base;
8256 24 encryption_index = frag_stream_info->encryption_index;
8257 } else {
8258 613 encryption_index = sc->cenc.encryption_index;
8259 }
8260 }
8261 } else {
8262 95867 encryption_index = sc->cenc.encryption_index;
8263 }
8264
8265
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 96382 times.
96528 if (encryption_index) {
8266
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_info_sample_count &&
8267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8268 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8269 return AVERROR_INVALIDDATA;
8270 }
8271
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_offsets_count &&
8272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8273 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8274 return AVERROR_INVALIDDATA;
8275 }
8276
8277 146 encrypted_sample = NULL;
8278
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!encryption_index->nb_encrypted_samples) {
8279 // Full-sample encryption with default settings.
8280 48 encrypted_sample = sc->cenc.default_encrypted_sample;
8281
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) {
8282 // Per-sample setting override.
8283 98 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (!encrypted_sample) {
8285 encrypted_sample = sc->cenc.default_encrypted_sample;
8286 }
8287 }
8288
8289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (!encrypted_sample) {
8290 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8291 return AVERROR_INVALIDDATA;
8292 }
8293
8294
1/2
✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
146 if (mov->decryption_key) {
8295 146 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
8296 } else {
8297 size_t size;
8298 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
8299 if (!side_data)
8300 return AVERROR(ENOMEM);
8301 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
8302 if (ret < 0)
8303 av_free(side_data);
8304 return ret;
8305 }
8306 }
8307
8308 96382 return 0;
8309 }
8310
8311 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8312 {
8313 const int OPUS_SEEK_PREROLL_MS = 80;
8314 int ret;
8315 AVStream *st;
8316 size_t size;
8317 uint16_t pre_skip;
8318
8319 if (c->fc->nb_streams < 1)
8320 return 0;
8321 st = c->fc->streams[c->fc->nb_streams-1];
8322
8323 if ((uint64_t)atom.size > (1<<30) || atom.size < 11)
8324 return AVERROR_INVALIDDATA;
8325
8326 /* Check OpusSpecificBox version. */
8327 if (avio_r8(pb) != 0) {
8328 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
8329 return AVERROR_INVALIDDATA;
8330 }
8331
8332 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
8333 size = atom.size + 8;
8334
8335 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
8336 return ret;
8337
8338 AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
8339 AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
8340 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
8341 avio_read(pb, st->codecpar->extradata + 9, size - 9);
8342
8343 /* OpusSpecificBox is stored in big-endian, but OpusHead is
8344 little-endian; aside from the preceeding magic and version they're
8345 otherwise currently identical. Data after output gain at offset 16
8346 doesn't need to be bytewapped. */
8347 pre_skip = AV_RB16A(st->codecpar->extradata + 10);
8348 AV_WL16A(st->codecpar->extradata + 10, pre_skip);
8349 AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
8350 AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
8351
8352 st->codecpar->initial_padding = pre_skip;
8353 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
8354 (AVRational){1, 1000},
8355 (AVRational){1, 48000});
8356
8357 return 0;
8358 }
8359
8360 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8361 {
8362 AVStream *st;
8363 unsigned format_info;
8364 int channel_assignment, channel_assignment1, channel_assignment2;
8365 int ratebits;
8366 uint64_t chmask;
8367
8368 if (c->fc->nb_streams < 1)
8369 return 0;
8370 st = c->fc->streams[c->fc->nb_streams-1];
8371
8372 if (atom.size < 10)
8373 return AVERROR_INVALIDDATA;
8374
8375 format_info = avio_rb32(pb);
8376
8377 ratebits = (format_info >> 28) & 0xF;
8378 channel_assignment1 = (format_info >> 15) & 0x1F;
8379 channel_assignment2 = format_info & 0x1FFF;
8380 if (channel_assignment2)
8381 channel_assignment = channel_assignment2;
8382 else
8383 channel_assignment = channel_assignment1;
8384
8385 st->codecpar->frame_size = 40 << (ratebits & 0x7);
8386 st->codecpar->sample_rate = mlp_samplerate(ratebits);
8387
8388 av_channel_layout_uninit(&st->codecpar->ch_layout);
8389 chmask = truehd_layout(channel_assignment);
8390 av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
8391
8392 return 0;
8393 }
8394
8395 4 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8396 {
8397 AVStream *st;
8398 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
8399 int ret;
8400 4 int64_t read_size = atom.size;
8401
8402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8403 return 0;
8404 4 st = c->fc->streams[c->fc->nb_streams-1];
8405
8406 // At most 24 bytes
8407 4 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
8408
8409
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
8410 return ret;
8411
8412 4 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
8413 }
8414
8415 3 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8416 {
8417 AVStream *st;
8418 uint8_t *buf;
8419 int ret, old_size, num_arrays;
8420
8421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
8422 return 0;
8423 3 st = c->fc->streams[c->fc->nb_streams-1];
8424
8425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata_size)
8426 // TODO: handle lhvC when present before hvcC
8427 return 0;
8428
8429
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)
8430 return AVERROR_INVALIDDATA;
8431
8432 3 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
8433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!buf)
8434 return AVERROR(ENOMEM);
8435 3 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8436
8437 3 ret = ffio_read_size(pb, buf, atom.size);
8438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8439 av_free(buf);
8440 av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
8441 return 0;
8442 }
8443
8444 3 num_arrays = buf[5];
8445 3 old_size = st->codecpar->extradata_size;
8446 3 atom.size -= 8 /* account for mov_realloc_extradata offseting */
8447 + 6 /* lhvC bytes before the arrays*/;
8448
8449 3 ret = mov_realloc_extradata(st->codecpar, atom);
8450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8451 av_free(buf);
8452 return ret;
8453 }
8454
8455 3 st->codecpar->extradata[22] += num_arrays;
8456 3 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
8457
8458 3 st->disposition |= AV_DISPOSITION_MULTILAYER;
8459
8460 3 av_free(buf);
8461 3 return 0;
8462 }
8463
8464 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8465 {
8466 4 AVFormatContext *ctx = c->fc;
8467 4 AVStream *st = NULL;
8468 AVBPrint scheme_buf, value_buf;
8469 4 int64_t scheme_str_len = 0, value_str_len = 0;
8470 4 int version, flags, ret = AVERROR_BUG;
8471 4 int64_t size = atom.size;
8472
8473
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
8474 // 4 bytes for version + flags, 2x 1 byte for null
8475 return AVERROR_INVALIDDATA;
8476
8477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8478 return 0;
8479 4 st = c->fc->streams[c->fc->nb_streams-1];
8480
8481 4 version = avio_r8(pb);
8482 4 flags = avio_rb24(pb);
8483 4 size -= 4;
8484
8485
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) {
8486 av_log(ctx, AV_LOG_ERROR,
8487 "Unsupported 'kind' box with version %d, flags: %x",
8488 version, flags);
8489 return AVERROR_INVALIDDATA;
8490 }
8491
8492 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8493 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8494
8495
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,
8496 size)) < 0) {
8497 ret = scheme_str_len;
8498 goto cleanup;
8499 }
8500
8501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
8502 // we need to have another string, even if nullptr.
8503 // we check with + 1 since we expect that if size was not hit,
8504 // an additional null was read.
8505 ret = AVERROR_INVALIDDATA;
8506 goto cleanup;
8507 }
8508
8509 4 size -= scheme_str_len + 1;
8510
8511
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,
8512 size)) < 0) {
8513 ret = value_str_len;
8514 goto cleanup;
8515 }
8516
8517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
8518 // in case of no trailing null, box is not valid.
8519 ret = AVERROR_INVALIDDATA;
8520 goto cleanup;
8521 }
8522
8523 4 av_log(ctx, AV_LOG_TRACE,
8524 "%s stream %d KindBox(scheme: %s, value: %s)\n",
8525 4 av_get_media_type_string(st->codecpar->codec_type),
8526 st->index,
8527 scheme_buf.str, value_buf.str);
8528
8529
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++) {
8530 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
8531
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
8532 continue;
8533
8534
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
8535 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
8536
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
8537 16 continue;
8538
8539 4 st->disposition |= value_map.disposition;
8540 }
8541 }
8542
8543 4 ret = 0;
8544
8545 4 cleanup:
8546
8547 4 av_bprint_finalize(&scheme_buf, NULL);
8548 4 av_bprint_finalize(&value_buf, NULL);
8549
8550 4 return ret;
8551 }
8552
8553 static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8554 {
8555 AVStream *st;
8556 AVChannelLayout ch_layout = { 0 };
8557 int ret, i, version, type;
8558 int ambisonic_order, channel_order, normalization, channel_count;
8559 int ambi_channels, non_diegetic_channels;
8560
8561 if (c->fc->nb_streams < 1)
8562 return 0;
8563
8564 st = c->fc->streams[c->fc->nb_streams - 1];
8565
8566 if (atom.size < 16) {
8567 av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
8568 return AVERROR_INVALIDDATA;
8569 }
8570
8571 version = avio_r8(pb);
8572 if (version) {
8573 av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
8574 return 0;
8575 }
8576
8577 type = avio_r8(pb);
8578 if (type & 0x7f) {
8579 av_log(c->fc, AV_LOG_WARNING,
8580 "Unsupported ambisonic type %d\n", type & 0x7f);
8581 return 0;
8582 }
8583 non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
8584
8585 ambisonic_order = avio_rb32(pb);
8586
8587 channel_order = avio_r8(pb);
8588 if (channel_order) {
8589 av_log(c->fc, AV_LOG_WARNING,
8590 "Unsupported channel_order %d\n", channel_order);
8591 return 0;
8592 }
8593
8594 normalization = avio_r8(pb);
8595 if (normalization) {
8596 av_log(c->fc, AV_LOG_WARNING,
8597 "Unsupported normalization %d\n", normalization);
8598 return 0;
8599 }
8600
8601 channel_count = avio_rb32(pb);
8602 if (ambisonic_order < 0 || ambisonic_order > 31 ||
8603 channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
8604 non_diegetic_channels)) {
8605 av_log(c->fc, AV_LOG_ERROR,
8606 "Invalid number of channels (%d / %d)\n",
8607 channel_count, ambisonic_order);
8608 return 0;
8609 }
8610 ambi_channels = channel_count - non_diegetic_channels;
8611
8612 ret = av_channel_layout_custom_init(&ch_layout, channel_count);
8613 if (ret < 0)
8614 return 0;
8615
8616 for (i = 0; i < channel_count; i++) {
8617 unsigned channel = avio_rb32(pb);
8618
8619 if (channel >= channel_count) {
8620 av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
8621 channel, ambisonic_order);
8622 av_channel_layout_uninit(&ch_layout);
8623 return 0;
8624 }
8625 if (channel >= ambi_channels)
8626 ch_layout.u.map[i].id = channel - ambi_channels;
8627 else
8628 ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
8629 }
8630
8631 ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
8632 if (ret < 0) {
8633 av_channel_layout_uninit(&ch_layout);
8634 return 0;
8635 }
8636
8637 av_channel_layout_uninit(&st->codecpar->ch_layout);
8638 st->codecpar->ch_layout = ch_layout;
8639
8640 return 0;
8641 }
8642
8643 static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8644 {
8645 AVStream *st;
8646 int version;
8647
8648 if (c->fc->nb_streams < 1)
8649 return 0;
8650
8651 st = c->fc->streams[c->fc->nb_streams - 1];
8652
8653 if (atom.size < 5) {
8654 av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
8655 return AVERROR_INVALIDDATA;
8656 }
8657
8658 version = avio_r8(pb);
8659 if (version) {
8660 av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
8661 return 0;
8662 }
8663
8664 st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
8665
8666 return 0;
8667 }
8668
8669 96 static int rb_size(AVIOContext *pb, int64_t *value, int size)
8670 {
8671
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 95 times.
96 if (size == 0)
8672 1 *value = 0;
8673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
95 else if (size == 1)
8674 *value = avio_r8(pb);
8675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
95 else if (size == 2)
8676 *value = avio_rb16(pb);
8677
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 else if (size == 4)
8678 95 *value = avio_rb32(pb);
8679 else if (size == 8) {
8680 *value = avio_rb64(pb);
8681 if (*value < 0)
8682 return -1;
8683 } else
8684 return -1;
8685 96 return size;
8686 }
8687
8688 13 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8689 {
8690 13 avio_rb32(pb); // version & flags.
8691 13 c->primary_item_id = avio_rb16(pb);
8692 13 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
8693 13 return atom.size;
8694 }
8695
8696 6 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8697 {
8698 6 c->idat_offset = avio_tell(pb);
8699 6 return 0;
8700 }
8701
8702 13 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8703 {
8704 HEIFItem **heif_item;
8705 int version, offset_size, length_size, base_offset_size, index_size;
8706 int item_count, extent_count;
8707 int64_t base_offset, extent_offset, extent_length;
8708 uint8_t value;
8709
8710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (c->found_iloc) {
8711 av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
8712 return 0;
8713 }
8714
8715 13 version = avio_r8(pb);
8716 13 avio_rb24(pb); // flags.
8717
8718 13 value = avio_r8(pb);
8719 13 offset_size = (value >> 4) & 0xF;
8720 13 length_size = value & 0xF;
8721 13 value = avio_r8(pb);
8722 13 base_offset_size = (value >> 4) & 0xF;
8723
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 7 times.
13 index_size = !version ? 0 : (value & 0xF);
8724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (index_size) {
8725 avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
8726 return AVERROR_PATCHWELCOME;
8727 }
8728
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8729
8730 13 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
8731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!heif_item)
8732 return AVERROR(ENOMEM);
8733 13 c->heif_item = heif_item;
8734
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (item_count > c->nb_heif_item)
8735 13 memset(&c->heif_item[c->nb_heif_item], 0,
8736 13 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
8737 13 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
8738
8739 13 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
8740
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 13 times.
45 for (int i = 0; i < item_count; i++) {
8741 32 HEIFItem *item = c->heif_item[i];
8742
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8743
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 12 times.
32 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
8744
8745
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if (avio_feof(pb))
8746 return AVERROR_INVALIDDATA;
8747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (offset_type > 1) {
8748 avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
8749 return AVERROR_PATCHWELCOME;
8750 }
8751
8752 32 avio_rb16(pb); // data_reference_index.
8753
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if (rb_size(pb, &base_offset, base_offset_size) < 0)
8754 return AVERROR_INVALIDDATA;
8755 32 extent_count = avio_rb16(pb);
8756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (extent_count > 1) {
8757 // For still AVIF images, we only support one extent item.
8758 avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
8759 return AVERROR_PATCHWELCOME;
8760 }
8761
8762
2/4
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
64 if (rb_size(pb, &extent_offset, offset_size) < 0 ||
8763 32 rb_size(pb, &extent_length, length_size) < 0 ||
8764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 base_offset > INT64_MAX - extent_offset)
8765 return AVERROR_INVALIDDATA;
8766
8767
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (!item)
8768 32 item = c->heif_item[i] = av_mallocz(sizeof(*item));
8769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!item)
8770 return AVERROR(ENOMEM);
8771
8772 32 item->item_id = item_id;
8773
8774
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 26 times.
32 if (offset_type == 1)
8775 6 item->is_idat_relative = 1;
8776 32 item->extent_length = extent_length;
8777 32 item->extent_offset = base_offset + extent_offset;
8778 32 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, offset_type %d, "
8779 "extent_offset %"PRId64", extent_length %"PRId64"\n",
8780 i, offset_type, item->extent_offset, item->extent_length);
8781 }
8782
8783 13 c->found_iloc = 1;
8784 13 return atom.size;
8785 }
8786
8787 32 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom, int idx)
8788 {
8789 HEIFItem *item;
8790 AVBPrint item_name;
8791 32 int64_t size = atom.size;
8792 uint32_t item_type;
8793 int item_id;
8794 int version, ret;
8795
8796 32 version = avio_r8(pb);
8797 32 avio_rb24(pb); // flags.
8798 32 size -= 4;
8799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (size < 0)
8800 return AVERROR_INVALIDDATA;
8801
8802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (version < 2) {
8803 avpriv_report_missing_feature(c->fc, "infe version < 2");
8804 avio_skip(pb, size);
8805 return 1;
8806 }
8807
8808
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
8809 32 avio_rb16(pb); // item_protection_index
8810 32 item_type = avio_rl32(pb);
8811 32 size -= 8;
8812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (size < 1)
8813 return AVERROR_INVALIDDATA;
8814
8815 32 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
8816 32 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
8817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (ret < 0) {
8818 av_bprint_finalize(&item_name, NULL);
8819 return ret;
8820 }
8821
8822 32 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
8823 32 item_id, av_fourcc2str(item_type), item_name.str);
8824
8825 32 size -= ret + 1;
8826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (size > 0)
8827 avio_skip(pb, size);
8828
8829 32 item = c->heif_item[idx];
8830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!item)
8831 item = c->heif_item[idx] = av_mallocz(sizeof(*item));
8832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!item)
8833 return AVERROR(ENOMEM);
8834
8835
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 1 times.
32 if (ret)
8836 31 av_bprint_finalize(&item_name, &c->heif_item[idx]->name);
8837 32 c->heif_item[idx]->item_id = item_id;
8838 32 c->heif_item[idx]->type = item_type;
8839
8840
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 7 times.
32 switch (item_type) {
8841 25 case MKTAG('a','v','0','1'):
8842 case MKTAG('h','v','c','1'):
8843 25 ret = heif_add_stream(c, c->heif_item[idx]);
8844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (ret < 0)
8845 return ret;
8846 25 break;
8847 }
8848
8849 32 return 0;
8850 }
8851
8852 13 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8853 {
8854 HEIFItem **heif_item;
8855 int entry_count;
8856 13 int version, got_stream = 0, ret, i;
8857
8858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (c->found_iinf) {
8859 av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
8860 return 0;
8861 }
8862
8863 13 version = avio_r8(pb);
8864 13 avio_rb24(pb); // flags.
8865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
8866
8867 13 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
8868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!heif_item)
8869 return AVERROR(ENOMEM);
8870 13 c->heif_item = heif_item;
8871
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (entry_count > c->nb_heif_item)
8872 memset(&c->heif_item[c->nb_heif_item], 0,
8873 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
8874 13 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
8875
8876
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 13 times.
45 for (i = 0; i < entry_count; i++) {
8877 MOVAtom infe;
8878
8879 32 infe.size = avio_rb32(pb) - 8;
8880 32 infe.type = avio_rl32(pb);
8881
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if (avio_feof(pb)) {
8882 ret = AVERROR_INVALIDDATA;
8883 goto fail;
8884 }
8885 32 ret = mov_read_infe(c, pb, infe, i);
8886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (ret < 0)
8887 goto fail;
8888
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (!ret)
8889 32 got_stream = 1;
8890 }
8891
8892 13 c->found_iinf = got_stream;
8893 13 return 0;
8894 fail:
8895 for (; i >= 0; i--) {
8896 HEIFItem *item = c->heif_item[i];
8897
8898 if (!item)
8899 continue;
8900
8901 av_freep(&item->name);
8902 if (!item->st)
8903 continue;
8904
8905 mov_free_stream_context(c->fc, item->st);
8906 ff_remove_stream(c->fc, item->st);
8907 item->st = NULL;
8908 }
8909 return ret;
8910 }
8911
8912 6 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
8913 {
8914 6 HEIFItem *item = NULL;
8915 HEIFGrid *grid;
8916 int entries, i;
8917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8918
8919
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 for (int i = 0; i < c->nb_heif_grid; i++) {
8920 if (c->heif_grid[i].item->item_id == from_item_id) {
8921 av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
8922 "referencing the same Derived Image item\n");
8923 return AVERROR_INVALIDDATA;
8924 }
8925 }
8926
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 for (int i = 0; i < c->nb_heif_item; i++) {
8927
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)
8928 14 continue;
8929 6 item = c->heif_item[i];
8930
8931
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 switch (item->type) {
8932 6 case MKTAG('g','r','i','d'):
8933 case MKTAG('i','o','v','l'):
8934 6 break;
8935 default:
8936 avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
8937 av_fourcc2str(item->type));
8938 return 0;
8939 }
8940 6 break;
8941 }
8942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!item) {
8943 av_log(c->fc, AV_LOG_ERROR, "Missing grid information\n");
8944 return AVERROR_INVALIDDATA;
8945 }
8946
8947 6 grid = av_realloc_array(c->heif_grid, c->nb_heif_grid + 1U,
8948 sizeof(*c->heif_grid));
8949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!grid)
8950 return AVERROR(ENOMEM);
8951 6 c->heif_grid = grid;
8952 6 grid = &grid[c->nb_heif_grid++];
8953
8954 6 entries = avio_rb16(pb);
8955 6 grid->tile_id_list = av_malloc_array(entries, sizeof(*grid->tile_id_list));
8956 6 grid->tile_idx_list = av_calloc(entries, sizeof(*grid->tile_idx_list));
8957 6 grid->tile_item_list = av_calloc(entries, sizeof(*grid->tile_item_list));
8958
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)
8959 return AVERROR(ENOMEM);
8960 /* 'to' item ids */
8961
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (i = 0; i < entries; i++)
8962
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 grid->tile_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
8963 6 grid->nb_tiles = entries;
8964 6 grid->item = item;
8965
8966 6 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
8967 from_item_id, entries);
8968
8969 6 return 0;
8970 }
8971
8972 3 static int mov_read_iref_thmb(MOVContext *c, AVIOContext *pb, int version)
8973 {
8974 int entries;
8975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 int to_item_id, from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8976
8977 3 entries = avio_rb16(pb);
8978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (entries > 1) {
8979 avpriv_request_sample(c->fc, "thmb in iref referencing several items");
8980 return AVERROR_PATCHWELCOME;
8981 }
8982 /* 'to' item ids */
8983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 to_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8984
8985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (to_item_id != c->primary_item_id)
8986 return 0;
8987
8988 3 c->thmb_item_id = from_item_id;
8989
8990 3 av_log(c->fc, AV_LOG_TRACE, "thmb: from_item_id %d, entries %d\n",
8991 from_item_id, entries);
8992
8993 3 return 0;
8994 }
8995
8996 9 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8997 {
8998 9 int version = avio_r8(pb);
8999 9 avio_rb24(pb); // flags
9000 9 atom.size -= 4;
9001
9002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (version > 1) {
9003 av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
9004 return 0;
9005 }
9006
9007
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 while (atom.size) {
9008 9 uint32_t type, size = avio_rb32(pb);
9009 9 int64_t next = avio_tell(pb);
9010
9011
3/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
9 if (size < 14 || next < 0 || next > INT64_MAX - size)
9012 return AVERROR_INVALIDDATA;
9013
9014 9 next += size - 4;
9015 9 type = avio_rl32(pb);
9016
2/3
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
9 switch (type) {
9017 6 case MKTAG('d','i','m','g'):
9018 6 mov_read_iref_dimg(c, pb, version);
9019 9 break;
9020 3 case MKTAG('t','h','m','b'):
9021 3 mov_read_iref_thmb(c, pb, version);
9022 3 break;
9023 default:
9024 av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
9025 av_fourcc2str(type), size);
9026 }
9027
9028 9 atom.size -= size;
9029 9 avio_seek(pb, next, SEEK_SET);
9030 }
9031 9 return 0;
9032 }
9033
9034 31 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9035 {
9036 HEIFItem *item;
9037 uint32_t width, height;
9038
9039 31 avio_r8(pb); /* version */
9040 31 avio_rb24(pb); /* flags */
9041 31 width = avio_rb32(pb);
9042 31 height = avio_rb32(pb);
9043
9044 31 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %u, height %u\n",
9045 c->cur_item_id, width, height);
9046
9047 31 item = heif_cur_item(c);
9048
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 if (item) {
9049 31 item->width = width;
9050 31 item->height = height;
9051 }
9052
9053 31 return 0;
9054 }
9055
9056 6 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9057 {
9058 HEIFItem *item;
9059 int angle;
9060
9061 6 angle = avio_r8(pb) & 0x3;
9062
9063 6 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
9064 c->cur_item_id, angle);
9065
9066 6 item = heif_cur_item(c);
9067
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
9068 // angle * 90 specifies the angle (in anti-clockwise direction)
9069 // in units of degrees.
9070 6 item->rotation = angle * 90;
9071 }
9072
9073 6 return 0;
9074 }
9075
9076 6 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9077 {
9078 HEIFItem *item;
9079 int axis;
9080
9081 6 axis = avio_r8(pb) & 0x1;
9082
9083 6 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
9084 c->cur_item_id, axis);
9085
9086 6 item = heif_cur_item(c);
9087
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
9088 6 item->hflip = axis;
9089 6 item->vflip = !axis;
9090 }
9091
9092 6 return 0;
9093 }
9094
9095 13 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9096 {
9097 typedef struct MOVAtoms {
9098 FFIOContext b;
9099 uint32_t type;
9100 int64_t size;
9101 uint8_t *data;
9102 } MOVAtoms;
9103 13 MOVAtoms *atoms = NULL;
9104 MOVAtom a;
9105 unsigned count;
9106 13 int nb_atoms = 0;
9107 int version, flags;
9108 int ret;
9109
9110 13 a.size = avio_rb32(pb);
9111 13 a.type = avio_rl32(pb);
9112
9113
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
13 if (a.size < 8 || a.type != MKTAG('i','p','c','o'))
9114 return AVERROR_INVALIDDATA;
9115
9116 13 a.size -= 8;
9117
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 13 times.
70 while (a.size >= 8) {
9118 57 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
9119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!ref) {
9120 ret = AVERROR(ENOMEM);
9121 goto fail;
9122 }
9123 57 ref->data = NULL;
9124 57 ref->size = avio_rb32(pb);
9125 57 ref->type = avio_rl32(pb);
9126
2/4
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
57 if (ref->size > a.size || ref->size < 8)
9127 break;
9128 57 ref->data = av_malloc(ref->size);
9129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!ref->data) {
9130 ret = AVERROR_INVALIDDATA;
9131 goto fail;
9132 }
9133 57 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
9134 57 avio_seek(pb, -8, SEEK_CUR);
9135
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (avio_read(pb, ref->data, ref->size) != ref->size) {
9136 ret = AVERROR_INVALIDDATA;
9137 goto fail;
9138 }
9139 57 ffio_init_read_context(&ref->b, ref->data, ref->size);
9140 57 a.size -= ref->size;
9141 }
9142
9143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (a.size) {
9144 ret = AVERROR_INVALIDDATA;
9145 goto fail;
9146 }
9147
9148 13 a.size = avio_rb32(pb);
9149 13 a.type = avio_rl32(pb);
9150
9151
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
13 if (a.size < 8 || a.type != MKTAG('i','p','m','a')) {
9152 ret = AVERROR_INVALIDDATA;
9153 goto fail;
9154 }
9155
9156 13 version = avio_r8(pb);
9157 13 flags = avio_rb24(pb);
9158 13 count = avio_rb32(pb);
9159
9160
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 13 times.
44 for (int i = 0; i < count; i++) {
9161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9162 31 int assoc_count = avio_r8(pb);
9163
9164
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 if (avio_feof(pb)) {
9165 ret = AVERROR_INVALIDDATA;
9166 goto fail;
9167 }
9168
9169
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 31 times.
115 for (int j = 0; j < assoc_count; j++) {
9170 MOVAtoms *ref;
9171 84 int index = avio_r8(pb) & 0x7f;
9172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (flags & 1) {
9173 index <<= 8;
9174 index |= avio_r8(pb);
9175 }
9176
2/4
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 84 times.
84 if (index > nb_atoms || index <= 0) {
9177 ret = AVERROR_INVALIDDATA;
9178 goto fail;
9179 }
9180 84 ref = &atoms[--index];
9181
9182 84 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
9183 84 index + 1, item_id, av_fourcc2str(ref->type));
9184
9185 84 c->cur_item_id = item_id;
9186
9187 84 ret = mov_read_default(c, &ref->b.pub,
9188 84 (MOVAtom) { .size = ref->size,
9189 .type = MKTAG('i','p','c','o') });
9190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (ret < 0)
9191 goto fail;
9192 84 ffio_init_read_context(&ref->b, ref->data, ref->size);
9193 }
9194 }
9195
9196 13 ret = 0;
9197 13 fail:
9198 13 c->cur_item_id = -1;
9199
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 13 times.
70 for (int i = 0; i < nb_atoms; i++)
9200 57 av_free(atoms[i].data);
9201 13 av_free(atoms);
9202
9203 13 return ret;
9204 }
9205
9206 static const MOVParseTableEntry mov_default_parse_table[] = {
9207 { MKTAG('A','C','L','R'), mov_read_aclr },
9208 { MKTAG('A','P','R','G'), mov_read_avid },
9209 { MKTAG('A','A','L','P'), mov_read_avid },
9210 { MKTAG('A','R','E','S'), mov_read_ares },
9211 { MKTAG('a','v','s','s'), mov_read_avss },
9212 { MKTAG('a','v','1','C'), mov_read_glbl },
9213 { MKTAG('c','h','p','l'), mov_read_chpl },
9214 { MKTAG('c','o','6','4'), mov_read_stco },
9215 { MKTAG('c','o','l','r'), mov_read_colr },
9216 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
9217 { MKTAG('d','i','n','f'), mov_read_default },
9218 { MKTAG('D','p','x','E'), mov_read_dpxe },
9219 { MKTAG('d','r','e','f'), mov_read_dref },
9220 { MKTAG('e','d','t','s'), mov_read_default },
9221 { MKTAG('e','l','s','t'), mov_read_elst },
9222 { MKTAG('e','n','d','a'), mov_read_enda },
9223 { MKTAG('f','i','e','l'), mov_read_fiel },
9224 { MKTAG('a','d','r','m'), mov_read_adrm },
9225 { MKTAG('f','t','y','p'), mov_read_ftyp },
9226 { MKTAG('g','l','b','l'), mov_read_glbl },
9227 { MKTAG('h','d','l','r'), mov_read_hdlr },
9228 { MKTAG('i','l','s','t'), mov_read_ilst },
9229 { MKTAG('j','p','2','h'), mov_read_jp2h },
9230 { MKTAG('m','d','a','t'), mov_read_mdat },
9231 { MKTAG('m','d','h','d'), mov_read_mdhd },
9232 { MKTAG('m','d','i','a'), mov_read_default },
9233 { MKTAG('m','e','t','a'), mov_read_meta },
9234 { MKTAG('m','i','n','f'), mov_read_default },
9235 { MKTAG('m','o','o','f'), mov_read_moof },
9236 { MKTAG('m','o','o','v'), mov_read_moov },
9237 { MKTAG('m','v','e','x'), mov_read_default },
9238 { MKTAG('m','v','h','d'), mov_read_mvhd },
9239 { MKTAG('S','M','I',' '), mov_read_svq3 },
9240 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
9241 { MKTAG('a','v','c','C'), mov_read_glbl },
9242 { MKTAG('p','a','s','p'), mov_read_pasp },
9243 { MKTAG('c','l','a','p'), mov_read_clap },
9244 { MKTAG('s','b','a','s'), mov_read_sbas },
9245 { MKTAG('s','i','d','x'), mov_read_sidx },
9246 { MKTAG('s','t','b','l'), mov_read_default },
9247 { MKTAG('s','t','c','o'), mov_read_stco },
9248 { MKTAG('s','t','p','s'), mov_read_stps },
9249 { MKTAG('s','t','r','f'), mov_read_strf },
9250 { MKTAG('s','t','s','c'), mov_read_stsc },
9251 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
9252 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
9253 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
9254 { MKTAG('s','t','t','s'), mov_read_stts },
9255 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
9256 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
9257 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
9258 { MKTAG('t','f','d','t'), mov_read_tfdt },
9259 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
9260 { MKTAG('t','r','a','k'), mov_read_trak },
9261 { MKTAG('t','r','a','f'), mov_read_default },
9262 { MKTAG('t','r','e','f'), mov_read_default },
9263 { MKTAG('t','m','c','d'), mov_read_tmcd },
9264 { MKTAG('c','h','a','p'), mov_read_chap },
9265 { MKTAG('t','r','e','x'), mov_read_trex },
9266 { MKTAG('t','r','u','n'), mov_read_trun },
9267 { MKTAG('u','d','t','a'), mov_read_default },
9268 { MKTAG('w','a','v','e'), mov_read_wave },
9269 { MKTAG('e','s','d','s'), mov_read_esds },
9270 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
9271 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
9272 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
9273 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
9274 { MKTAG('w','f','e','x'), mov_read_wfex },
9275 { MKTAG('c','m','o','v'), mov_read_cmov },
9276 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
9277 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
9278 { MKTAG('d','v','c','1'), mov_read_dvc1 },
9279 { MKTAG('s','g','p','d'), mov_read_sgpd },
9280 { MKTAG('s','b','g','p'), mov_read_sbgp },
9281 { MKTAG('h','v','c','C'), mov_read_glbl },
9282 { MKTAG('v','v','c','C'), mov_read_glbl },
9283 { MKTAG('u','u','i','d'), mov_read_uuid },
9284 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
9285 { MKTAG('f','r','e','e'), mov_read_free },
9286 { MKTAG('-','-','-','-'), mov_read_custom },
9287 { MKTAG('s','i','n','f'), mov_read_default },
9288 { MKTAG('f','r','m','a'), mov_read_frma },
9289 { MKTAG('s','e','n','c'), mov_read_senc },
9290 { MKTAG('s','a','i','z'), mov_read_saiz },
9291 { MKTAG('s','a','i','o'), mov_read_saio },
9292 { MKTAG('p','s','s','h'), mov_read_pssh },
9293 { MKTAG('s','c','h','m'), mov_read_schm },
9294 { MKTAG('s','c','h','i'), mov_read_default },
9295 { MKTAG('t','e','n','c'), mov_read_tenc },
9296 { MKTAG('d','f','L','a'), mov_read_dfla },
9297 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
9298 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
9299 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
9300 { MKTAG('h','f','o','v'), mov_read_hfov },
9301 { MKTAG('d','O','p','s'), mov_read_dops },
9302 { MKTAG('d','m','l','p'), mov_read_dmlp },
9303 { MKTAG('S','m','D','m'), mov_read_smdm },
9304 { MKTAG('C','o','L','L'), mov_read_coll },
9305 { MKTAG('v','p','c','C'), mov_read_vpcc },
9306 { MKTAG('m','d','c','v'), mov_read_mdcv },
9307 { MKTAG('c','l','l','i'), mov_read_clli },
9308 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
9309 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
9310 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
9311 { MKTAG('k','i','n','d'), mov_read_kind },
9312 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
9313 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
9314 { MKTAG('i','l','o','c'), mov_read_iloc },
9315 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
9316 { MKTAG('p','i','t','m'), mov_read_pitm },
9317 { MKTAG('e','v','c','C'), mov_read_glbl },
9318 { MKTAG('i','d','a','t'), mov_read_idat },
9319 { MKTAG('i','m','i','r'), mov_read_imir },
9320 { MKTAG('i','r','e','f'), mov_read_iref },
9321 { MKTAG('i','s','p','e'), mov_read_ispe },
9322 { MKTAG('i','r','o','t'), mov_read_irot },
9323 { MKTAG('i','p','r','p'), mov_read_iprp },
9324 { MKTAG('i','i','n','f'), mov_read_iinf },
9325 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
9326 { MKTAG('l','h','v','C'), mov_read_lhvc },
9327 { MKTAG('l','v','c','C'), mov_read_glbl },
9328 #if CONFIG_IAMFDEC
9329 { MKTAG('i','a','c','b'), mov_read_iacb },
9330 #endif
9331 { 0, NULL }
9332 };
9333
9334 6357 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9335 {
9336 6357 int64_t total_size = 0;
9337 MOVAtom a;
9338 int i;
9339
9340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6357 times.
6357 if (c->atom_depth > 10) {
9341 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
9342 return AVERROR_INVALIDDATA;
9343 }
9344 6357 c->atom_depth ++;
9345
9346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6357 times.
6357 if (atom.size < 0)
9347 atom.size = INT64_MAX;
9348
2/2
✓ Branch 0 taken 18210 times.
✓ Branch 1 taken 5874 times.
24084 while (total_size <= atom.size - 8) {
9349 18210 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
9350 18210 a.size = avio_rb32(pb);
9351 18210 a.type = avio_rl32(pb);
9352
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 18206 times.
18210 if (avio_feof(pb))
9353 4 break;
9354
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 18018 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
18206 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
9355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18206 times.
18206 a.type == MKTAG('h','o','o','v')) &&
9356 a.size >= 8 &&
9357 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
9358 uint32_t type;
9359 avio_skip(pb, 4);
9360 type = avio_rl32(pb);
9361 if (avio_feof(pb))
9362 break;
9363 avio_seek(pb, -8, SEEK_CUR);
9364 if (type == MKTAG('m','v','h','d') ||
9365 type == MKTAG('c','m','o','v')) {
9366 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
9367 a.type = MKTAG('m','o','o','v');
9368 }
9369 }
9370
2/2
✓ Branch 0 taken 15505 times.
✓ Branch 1 taken 2701 times.
18206 if (atom.type != MKTAG('r','o','o','t') &&
9371
2/2
✓ Branch 0 taken 14099 times.
✓ Branch 1 taken 1406 times.
15505 atom.type != MKTAG('m','o','o','v')) {
9372
1/2
✓ Branch 0 taken 14099 times.
✗ Branch 1 not taken.
14099 if (a.type == MKTAG('t','r','a','k') ||
9373
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14099 times.
14099 a.type == MKTAG('m','d','a','t')) {
9374 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
9375 avio_skip(pb, -8);
9376 c->atom_depth --;
9377 479 return 0;
9378 }
9379 }
9380 18206 total_size += 8;
9381
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 18182 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
18206 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
9382 24 a.size = avio_rb64(pb) - 8;
9383 24 total_size += 8;
9384 }
9385 18206 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
9386 18206 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
9387
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 18201 times.
18206 if (a.size == 0) {
9388 5 a.size = atom.size - total_size + 8;
9389 }
9390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18206 times.
18206 if (a.size < 0)
9391 break;
9392 18206 a.size -= 8;
9393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18206 times.
18206 if (a.size < 0)
9394 break;
9395 18206 a.size = FFMIN(a.size, atom.size - total_size);
9396
9397
2/2
✓ Branch 0 taken 828887 times.
✓ Branch 1 taken 1847 times.
830734 for (i = 0; mov_default_parse_table[i].type; i++)
9398
2/2
✓ Branch 0 taken 16359 times.
✓ Branch 1 taken 812528 times.
828887 if (mov_default_parse_table[i].type == a.type) {
9399 16359 parse = mov_default_parse_table[i].parse;
9400 16359 break;
9401 }
9402
9403 // container is user data
9404
4/4
✓ Branch 0 taken 1847 times.
✓ Branch 1 taken 16359 times.
✓ Branch 2 taken 1672 times.
✓ Branch 3 taken 175 times.
18206 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
9405
2/2
✓ Branch 0 taken 298 times.
✓ Branch 1 taken 1374 times.
1672 atom.type == MKTAG('i','l','s','t')))
9406 473 parse = mov_read_udta_string;
9407
9408 // Supports parsing the QuickTime Metadata Keys.
9409 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
9410
4/4
✓ Branch 0 taken 1374 times.
✓ Branch 1 taken 16832 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 1363 times.
18206 if (!parse && c->found_hdlr_mdta &&
9411
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 atom.type == MKTAG('m','e','t','a') &&
9412
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 a.type == MKTAG('k','e','y','s') &&
9413
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 c->meta_keys_count == 0) {
9414 11 parse = mov_read_keys;
9415 }
9416
9417
2/2
✓ Branch 0 taken 1363 times.
✓ Branch 1 taken 16843 times.
18206 if (!parse) { /* skip leaf atoms data */
9418 1363 avio_skip(pb, a.size);
9419 } else {
9420 16843 int64_t start_pos = avio_tell(pb);
9421 int64_t left;
9422 16843 int err = parse(c, pb, a);
9423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16843 times.
16843 if (err < 0) {
9424 c->atom_depth --;
9425 return err;
9426 }
9427
5/6
✓ Branch 0 taken 3081 times.
✓ Branch 1 taken 13762 times.
✓ Branch 2 taken 2783 times.
✓ Branch 3 taken 298 times.
✓ Branch 4 taken 2783 times.
✗ Branch 5 not taken.
16843 if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos &&
9428
6/8
✓ Branch 0 taken 2783 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2783 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2775 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 471 times.
✓ Branch 7 taken 2304 times.
5558 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
9429 2775 start_pos + a.size == avio_size(pb))) {
9430
4/6
✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 479 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 471 times.
479 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
9431 8 c->next_root_atom = start_pos + a.size;
9432 479 c->atom_depth --;
9433 479 return 0;
9434 }
9435 16364 left = a.size - avio_tell(pb) + start_pos;
9436
2/2
✓ Branch 0 taken 1307 times.
✓ Branch 1 taken 15057 times.
16364 if (left > 0) /* skip garbage at atom end */
9437 1307 avio_skip(pb, left);
9438
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 15055 times.
15057 else if (left < 0) {
9439 2 av_log(c->fc, AV_LOG_WARNING,
9440 "overread end of atom '%s' by %"PRId64" bytes\n",
9441 2 av_fourcc2str(a.type), -left);
9442 2 avio_seek(pb, left, SEEK_CUR);
9443 }
9444 }
9445
9446 17727 total_size += a.size;
9447 }
9448
9449
4/4
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 5772 times.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 4 times.
5878 if (total_size < atom.size && atom.size < 0x7ffff)
9450 102 avio_skip(pb, atom.size - total_size);
9451
9452 5878 c->atom_depth --;
9453 5878 return 0;
9454 }
9455
9456 7236 static int mov_probe(const AVProbeData *p)
9457 {
9458 int64_t offset;
9459 uint32_t tag;
9460 7236 int score = 0;
9461 7236 int moov_offset = -1;
9462
9463 /* check file header */
9464 7236 offset = 0;
9465 8911 for (;;) {
9466 int64_t size;
9467 16147 int minsize = 8;
9468 /* ignore invalid offset */
9469
2/2
✓ Branch 0 taken 7236 times.
✓ Branch 1 taken 8911 times.
16147 if ((offset + 8ULL) > (unsigned int)p->buf_size)
9470 7236 break;
9471 8911 size = AV_RB32(p->buf + offset);
9472
3/4
✓ Branch 0 taken 521 times.
✓ Branch 1 taken 8390 times.
✓ Branch 2 taken 521 times.
✗ Branch 3 not taken.
8911 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
9473 521 size = AV_RB64(p->buf+offset + 8);
9474 521 minsize = 16;
9475
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 8335 times.
8390 } else if (size == 0) {
9476 55 size = p->buf_size - offset;
9477 }
9478
2/2
✓ Branch 0 taken 399 times.
✓ Branch 1 taken 8512 times.
8911 if (size < minsize) {
9479 399 offset += 4;
9480 399 continue;
9481 }
9482 8512 tag = AV_RL32(p->buf + offset + 4);
9483
5/6
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 832 times.
✓ Branch 2 taken 354 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7202 times.
8512 switch(tag) {
9484 /* check for obvious tags */
9485 123 case MKTAG('m','o','o','v'):
9486 123 moov_offset = offset + 4;
9487 955 case MKTAG('m','d','a','t'):
9488 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
9489 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
9490 case MKTAG('f','t','y','p'):
9491
2/2
✓ Branch 0 taken 434 times.
✓ Branch 1 taken 521 times.
955 if (tag == MKTAG('f','t','y','p') &&
9492
1/2
✓ Branch 0 taken 434 times.
✗ Branch 1 not taken.
434 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
9493
1/2
✓ Branch 0 taken 434 times.
✗ Branch 1 not taken.
434 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
9494
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 428 times.
434 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
9495 )) {
9496 6 score = FFMAX(score, 5);
9497 } else {
9498 949 score = AVPROBE_SCORE_MAX;
9499 }
9500 955 break;
9501 /* those are more common words, so rate then a bit less */
9502 354 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
9503 case MKTAG('w','i','d','e'):
9504 case MKTAG('f','r','e','e'):
9505 case MKTAG('j','u','n','k'):
9506 case MKTAG('p','i','c','t'):
9507 354 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
9508 354 break;
9509 case MKTAG(0x82,0x82,0x7f,0x7d):
9510 score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
9511 break;
9512 1 case MKTAG('s','k','i','p'):
9513 case MKTAG('u','u','i','d'):
9514 case MKTAG('p','r','f','l'):
9515 /* if we only find those cause probedata is too small at least rate them */
9516 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
9517 1 break;
9518 }
9519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8512 times.
8512 if (size > INT64_MAX - offset)
9520 break;
9521 8512 offset += size;
9522 }
9523
4/4
✓ Branch 0 taken 465 times.
✓ Branch 1 taken 6771 times.
✓ Branch 2 taken 123 times.
✓ Branch 3 taken 342 times.
7236 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
9524 /* moov atom in the header - we should make sure that this is not a
9525 * MOV-packed MPEG-PS */
9526 123 offset = moov_offset;
9527
9528
2/2
✓ Branch 0 taken 120608 times.
✓ Branch 1 taken 123 times.
120731 while (offset < (p->buf_size - 16)) { /* Sufficient space */
9529 /* We found an actual hdlr atom */
9530
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 120476 times.
120608 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
9531
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 111 times.
132 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
9532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
9533 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
9534 /* We found a media handler reference atom describing an
9535 * MPEG-PS-in-MOV, return a
9536 * low score to force expanding the probe window until
9537 * mpegps_probe finds what it needs */
9538 return 5;
9539 } else {
9540 /* Keep looking */
9541 120608 offset += 2;
9542 }
9543 }
9544 }
9545
9546 7236 return score;
9547 }
9548
9549 // must be done after parsing all trak because there's no order requirement
9550 2 static void mov_read_chapters(AVFormatContext *s)
9551 {
9552 2 MOVContext *mov = s->priv_data;
9553 MOVStreamContext *sc;
9554 int64_t cur_pos;
9555 int i, j;
9556 int chapter_track;
9557
9558
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
9559 2 AVStream *st = NULL;
9560 2 FFStream *sti = NULL;
9561 2 chapter_track = mov->chapter_tracks[j];
9562
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
9563 4 sc = mov->fc->streams[i]->priv_data;
9564
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
9565 2 st = s->streams[i];
9566 2 break;
9567 }
9568 }
9569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
9570 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
9571 continue;
9572 }
9573 2 sti = ffstream(st);
9574
9575 2 sc = st->priv_data;
9576 2 cur_pos = avio_tell(sc->pb);
9577
9578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
9579 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
9580 if (!st->attached_pic.data && sti->nb_index_entries) {
9581 // Retrieve the first frame, if possible
9582 AVIndexEntry *sample = &sti->index_entries[0];
9583 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9584 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
9585 goto finish;
9586 }
9587
9588 if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
9589 goto finish;
9590 }
9591 } else {
9592 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
9593 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
9594 2 st->discard = AVDISCARD_ALL;
9595
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
9596 8 AVIndexEntry *sample = &sti->index_entries[i];
9597
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;
9598 uint8_t *title;
9599 uint16_t ch;
9600 int len, title_len;
9601
9602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
9603 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
9604 end = AV_NOPTS_VALUE;
9605 }
9606
9607
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9608 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
9609 goto finish;
9610 }
9611
9612 // the first two bytes are the length of the title
9613 8 len = avio_rb16(sc->pb);
9614
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
9615 continue;
9616 8 title_len = 2*len + 1;
9617
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
9618 goto finish;
9619
9620 // The samples could theoretically be in any encoding if there's an encd
9621 // atom following, but in practice are only utf-8 or utf-16, distinguished
9622 // instead by the presence of a BOM
9623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
9624 title[0] = 0;
9625 } else {
9626 8 ch = avio_rb16(sc->pb);
9627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
9628 avio_get_str16be(sc->pb, len, title, title_len);
9629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
9630 avio_get_str16le(sc->pb, len, title, title_len);
9631 else {
9632 8 AV_WB16(title, ch);
9633
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)
9634 title[len] = 0;
9635 else
9636 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
9637 }
9638 }
9639
9640 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
9641 8 av_freep(&title);
9642 }
9643 }
9644 2 finish:
9645 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
9646 }
9647 2 }
9648
9649 19 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
9650 int64_t value, int flags)
9651 {
9652 AVTimecode tc;
9653 char buf[AV_TIMECODE_STR_SIZE];
9654 19 AVRational rate = st->avg_frame_rate;
9655 19 int ret = av_timecode_init(&tc, rate, flags, 0, s);
9656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
9657 return ret;
9658 19 av_dict_set(&st->metadata, "timecode",
9659 19 av_timecode_make_string(&tc, buf, value), 0);
9660 19 return 0;
9661 }
9662
9663 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
9664 {
9665 MOVStreamContext *sc = st->priv_data;
9666 FFStream *const sti = ffstream(st);
9667 char buf[AV_TIMECODE_STR_SIZE];
9668 int64_t cur_pos = avio_tell(sc->pb);
9669 int hh, mm, ss, ff, drop;
9670
9671 if (!sti->nb_index_entries)
9672 return -1;
9673
9674 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9675 avio_skip(s->pb, 13);
9676 hh = avio_r8(s->pb);
9677 mm = avio_r8(s->pb);
9678 ss = avio_r8(s->pb);
9679 drop = avio_r8(s->pb);
9680 ff = avio_r8(s->pb);
9681 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
9682 hh, mm, ss, drop ? ';' : ':', ff);
9683 av_dict_set(&st->metadata, "timecode", buf, 0);
9684
9685 avio_seek(sc->pb, cur_pos, SEEK_SET);
9686 return 0;
9687 }
9688
9689 19 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
9690 {
9691 19 MOVStreamContext *sc = st->priv_data;
9692 19 FFStream *const sti = ffstream(st);
9693 19 int flags = 0;
9694 19 int64_t cur_pos = avio_tell(sc->pb);
9695 int64_t value;
9696 19 AVRational tc_rate = st->avg_frame_rate;
9697 19 int tmcd_nb_frames = sc->tmcd_nb_frames;
9698 int rounded_tc_rate;
9699
9700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!sti->nb_index_entries)
9701 return -1;
9702
9703
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)
9704 return -1;
9705
9706 19 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9707 19 value = avio_rb32(s->pb);
9708
9709
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13 times.
19 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
9710
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
9711
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
9712
9713 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
9714 * not the case) and thus assume "frame number format" instead of QT one.
9715 * No sample with tmcd track can be found with a QT timecode at the moment,
9716 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
9717 * format). */
9718
9719 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
9720 * we multiply the frame number with the quotient.
9721 * See tickets #9492, #9710. */
9722 19 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
9723 /* Work around files where tmcd_nb_frames is rounded down from frame rate
9724 * instead of up. See ticket #5978. */
9725
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
9726
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
9727 10 tmcd_nb_frames = rounded_tc_rate;
9728 19 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
9729
9730 19 parse_timecode_in_framenum_format(s, st, value, flags);
9731
9732 19 avio_seek(sc->pb, cur_pos, SEEK_SET);
9733 19 return 0;
9734 }
9735
9736 1043 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
9737 int i;
9738
3/4
✓ Branch 0 taken 1043 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1039 times.
✓ Branch 3 taken 4 times.
1043 if (!index || !*index) return;
9739
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 4 times.
76 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
9740 72 av_encryption_info_free((*index)->encrypted_samples[i]);
9741 }
9742 4 av_freep(&(*index)->encrypted_samples);
9743 4 av_freep(&(*index)->auxiliary_info_sizes);
9744 4 av_freep(&(*index)->auxiliary_offsets);
9745 4 av_freep(index);
9746 }
9747
9748 676 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
9749 {
9750 676 MOVStreamContext *sc = st->priv_data;
9751
9752
3/4
✓ Branch 0 taken 676 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 636 times.
676 if (!sc || --sc->refcount) {
9753 40 st->priv_data = NULL;
9754 40 return;
9755 }
9756
9757 636 av_freep(&sc->tts_data);
9758
2/2
✓ Branch 0 taken 597 times.
✓ Branch 1 taken 636 times.
1233 for (int i = 0; i < sc->drefs_count; i++) {
9759 597 av_freep(&sc->drefs[i].path);
9760 597 av_freep(&sc->drefs[i].dir);
9761 }
9762 636 av_freep(&sc->drefs);
9763
9764 636 sc->drefs_count = 0;
9765
9766
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 622 times.
636 if (!sc->pb_is_copied)
9767 14 ff_format_io_close(s, &sc->pb);
9768
9769 636 sc->pb = NULL;
9770 636 av_freep(&sc->chunk_offsets);
9771 636 av_freep(&sc->stsc_data);
9772 636 av_freep(&sc->sample_sizes);
9773 636 av_freep(&sc->keyframes);
9774 636 av_freep(&sc->ctts_data);
9775 636 av_freep(&sc->stts_data);
9776 636 av_freep(&sc->sdtp_data);
9777 636 av_freep(&sc->stps_data);
9778 636 av_freep(&sc->elst_data);
9779 636 av_freep(&sc->rap_group);
9780 636 av_freep(&sc->sync_group);
9781 636 av_freep(&sc->sgpd_sync);
9782 636 av_freep(&sc->sample_offsets);
9783 636 av_freep(&sc->open_key_samples);
9784 636 av_freep(&sc->display_matrix);
9785 636 av_freep(&sc->index_ranges);
9786
9787
2/2
✓ Branch 0 taken 597 times.
✓ Branch 1 taken 39 times.
636 if (sc->extradata)
9788
2/2
✓ Branch 0 taken 608 times.
✓ Branch 1 taken 597 times.
1205 for (int i = 0; i < sc->stsd_count; i++)
9789 608 av_free(sc->extradata[i]);
9790 636 av_freep(&sc->extradata);
9791 636 av_freep(&sc->extradata_size);
9792
9793 636 mov_free_encryption_index(&sc->cenc.encryption_index);
9794 636 av_encryption_info_free(sc->cenc.default_encrypted_sample);
9795 636 av_aes_ctr_free(sc->cenc.aes_ctr);
9796
9797 636 av_freep(&sc->stereo3d);
9798 636 av_freep(&sc->spherical);
9799 636 av_freep(&sc->mastering);
9800 636 av_freep(&sc->coll);
9801 636 av_freep(&sc->ambient);
9802
9803 #if CONFIG_IAMFDEC
9804
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 626 times.
636 if (sc->iamf)
9805 10 ff_iamf_read_deinit(sc->iamf);
9806 #endif
9807 636 av_freep(&sc->iamf);
9808 }
9809
9810 496 static int mov_read_close(AVFormatContext *s)
9811 {
9812 496 MOVContext *mov = s->priv_data;
9813 int i, j;
9814
9815
2/2
✓ Branch 0 taken 676 times.
✓ Branch 1 taken 496 times.
1172 for (i = 0; i < s->nb_streams; i++) {
9816 676 AVStream *st = s->streams[i];
9817
9818 676 mov_free_stream_context(s, st);
9819 }
9820
9821 496 av_freep(&mov->dv_demux);
9822 496 avformat_free_context(mov->dv_fctx);
9823 496 mov->dv_fctx = NULL;
9824
9825
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 485 times.
496 if (mov->meta_keys) {
9826
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i < mov->meta_keys_count; i++) {
9827 58 av_freep(&mov->meta_keys[i]);
9828 }
9829 11 av_freep(&mov->meta_keys);
9830 }
9831
9832 496 av_freep(&mov->trex_data);
9833 496 av_freep(&mov->bitrates);
9834
9835
2/2
✓ Branch 0 taken 389 times.
✓ Branch 1 taken 496 times.
885 for (i = 0; i < mov->frag_index.nb_items; i++) {
9836 389 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
9837
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 389 times.
796 for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) {
9838 407 mov_free_encryption_index(&frag[j].encryption_index);
9839 }
9840 389 av_freep(&mov->frag_index.item[i].stream_info);
9841 }
9842 496 av_freep(&mov->frag_index.item);
9843
9844 496 av_freep(&mov->aes_decrypt);
9845 496 av_freep(&mov->chapter_tracks);
9846
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 496 times.
528 for (i = 0; i < mov->nb_heif_item; i++) {
9847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!mov->heif_item[i])
9848 continue;
9849 32 av_freep(&mov->heif_item[i]->name);
9850 32 av_freep(&mov->heif_item[i]->icc_profile);
9851 32 av_freep(&mov->heif_item[i]);
9852 }
9853 496 av_freep(&mov->heif_item);
9854
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 496 times.
502 for (i = 0; i < mov->nb_heif_grid; i++) {
9855 6 av_freep(&mov->heif_grid[i].tile_id_list);
9856 6 av_freep(&mov->heif_grid[i].tile_idx_list);
9857 6 av_freep(&mov->heif_grid[i].tile_item_list);
9858 }
9859 496 av_freep(&mov->heif_grid);
9860
9861 496 return 0;
9862 }
9863
9864 16 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
9865 {
9866 int i;
9867
9868
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 for (i = 0; i < s->nb_streams; i++) {
9869 24 AVStream *st = s->streams[i];
9870 24 MOVStreamContext *sc = st->priv_data;
9871
9872
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
9873
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 sc->timecode_track == tmcd_id)
9874 14 return 1;
9875 }
9876 2 return 0;
9877 }
9878
9879 /* look for a tmcd track not referenced by any video track, and export it globally */
9880 496 static void export_orphan_timecode(AVFormatContext *s)
9881 {
9882 int i;
9883
9884
2/2
✓ Branch 0 taken 673 times.
✓ Branch 1 taken 494 times.
1167 for (i = 0; i < s->nb_streams; i++) {
9885 673 AVStream *st = s->streams[i];
9886
9887
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 657 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 14 times.
689 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
9888 16 !tmcd_is_referenced(s, i + 1)) {
9889 2 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
9890
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (tcr) {
9891 2 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
9892 2 break;
9893 }
9894 }
9895 }
9896 496 }
9897
9898 static int read_tfra(MOVContext *mov, AVIOContext *f)
9899 {
9900 int version, fieldlength, i, j;
9901 int64_t pos = avio_tell(f);
9902 uint32_t size = avio_rb32(f);
9903 unsigned track_id, item_count;
9904
9905 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
9906 return 1;
9907 }
9908 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
9909
9910 version = avio_r8(f);
9911 avio_rb24(f);
9912 track_id = avio_rb32(f);
9913 fieldlength = avio_rb32(f);
9914 item_count = avio_rb32(f);
9915 for (i = 0; i < item_count; i++) {
9916 int64_t time, offset;
9917 int index;
9918 MOVFragmentStreamInfo * frag_stream_info;
9919
9920 if (avio_feof(f)) {
9921 return AVERROR_INVALIDDATA;
9922 }
9923
9924 if (version == 1) {
9925 time = avio_rb64(f);
9926 offset = avio_rb64(f);
9927 } else {
9928 time = avio_rb32(f);
9929 offset = avio_rb32(f);
9930 }
9931
9932 // The first sample of each stream in a fragment is always a random
9933 // access sample. So it's entry in the tfra can be used as the
9934 // initial PTS of the fragment.
9935 index = update_frag_index(mov, offset);
9936 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
9937 if (frag_stream_info &&
9938 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
9939 frag_stream_info->first_tfra_pts = time;
9940
9941 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
9942 avio_r8(f);
9943 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
9944 avio_r8(f);
9945 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
9946 avio_r8(f);
9947 }
9948
9949 avio_seek(f, pos + size, SEEK_SET);
9950 return 0;
9951 }
9952
9953 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
9954 {
9955 int64_t stream_size = avio_size(f);
9956 int64_t original_pos = avio_tell(f);
9957 int64_t seek_ret;
9958 int ret = -1;
9959 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
9960 ret = seek_ret;
9961 goto fail;
9962 }
9963 c->mfra_size = avio_rb32(f);
9964 c->have_read_mfra_size = 1;
9965 if (!c->mfra_size || c->mfra_size > stream_size) {
9966 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
9967 goto fail;
9968 }
9969 if ((seek_ret = avio_seek(f, -((int64_t) c->mfra_size), SEEK_CUR)) < 0) {
9970 ret = seek_ret;
9971 goto fail;
9972 }
9973 if (avio_rb32(f) != c->mfra_size) {
9974 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
9975 goto fail;
9976 }
9977 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
9978 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
9979 goto fail;
9980 }
9981 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
9982 do {
9983 ret = read_tfra(c, f);
9984 if (ret < 0)
9985 goto fail;
9986 } while (!ret);
9987 ret = 0;
9988 c->frag_index.complete = 1;
9989 fail:
9990 seek_ret = avio_seek(f, original_pos, SEEK_SET);
9991 if (seek_ret < 0) {
9992 av_log(c->fc, AV_LOG_ERROR,
9993 "failed to seek back after looking for mfra\n");
9994 ret = seek_ret;
9995 }
9996 return ret;
9997 }
9998
9999 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10000 const HEIFItem *item)
10001 {
10002 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
10003 AV_PKT_DATA_ICC_PROFILE,
10004 item->icc_profile_size, 0);
10005 if (!sd)
10006 return AVERROR(ENOMEM);
10007
10008 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
10009
10010 return 0;
10011 }
10012
10013 6 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10014 const HEIFItem *item)
10015 {
10016 int32_t *matrix;
10017 6 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data,
10018 nb_coded_side_data,
10019 AV_PKT_DATA_DISPLAYMATRIX,
10020 9 * sizeof(*matrix), 0);
10021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sd)
10022 return AVERROR(ENOMEM);
10023
10024 6 matrix = (int32_t*)sd->data;
10025 /* rotation is in the counter-clockwise direction whereas
10026 * av_display_rotation_set() expects its argument to be
10027 * oriented clockwise, so we need to negate it. */
10028 6 av_display_rotation_set(matrix, -item->rotation);
10029 6 av_display_matrix_flip(matrix, item->hflip, item->vflip);
10030
10031 6 return 0;
10032 }
10033
10034 2 static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid,
10035 AVStreamGroupTileGrid *tile_grid)
10036 {
10037 2 MOVContext *c = s->priv_data;
10038 2 const HEIFItem *item = grid->item;
10039 2 int64_t offset = 0, pos = avio_tell(s->pb);
10040 2 int x = 0, y = 0, i = 0;
10041 int tile_rows, tile_cols;
10042 int flags, size;
10043
10044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10045 av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
10046 return AVERROR_PATCHWELCOME;
10047 }
10048
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (item->is_idat_relative) {
10049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!c->idat_offset) {
10050 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
10051 return AVERROR_INVALIDDATA;
10052 }
10053 2 offset = c->idat_offset;
10054 }
10055
10056 2 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10057
10058 2 avio_r8(s->pb); /* version */
10059 2 flags = avio_r8(s->pb);
10060
10061 2 tile_rows = avio_r8(s->pb) + 1;
10062 2 tile_cols = avio_r8(s->pb) + 1;
10063 /* actual width and height of output image */
10064
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);
10065
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);
10066
10067 /* ICC profile */
10068
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (item->icc_profile_size) {
10069 int ret = set_icc_profile_from_item(&tile_grid->coded_side_data,
10070 &tile_grid->nb_coded_side_data, item);
10071 if (ret < 0)
10072 return ret;
10073 }
10074 /* rotation */
10075
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 if (item->rotation || item->hflip || item->vflip) {
10076 int ret = set_display_matrix_from_item(&tile_grid->coded_side_data,
10077 &tile_grid->nb_coded_side_data, item);
10078 if (ret < 0)
10079 return ret;
10080 }
10081
10082 2 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
10083 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
10084
10085 2 avio_seek(s->pb, pos, SEEK_SET);
10086
10087 2 size = tile_rows * tile_cols;
10088 2 tile_grid->nb_tiles = grid->nb_tiles;
10089
10090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tile_grid->nb_tiles != size)
10091 return AVERROR_INVALIDDATA;
10092
10093
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < tile_cols; i++)
10094 4 tile_grid->coded_width += grid->tile_item_list[i]->width;
10095
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < size; i += tile_cols)
10096 4 tile_grid->coded_height += grid->tile_item_list[i]->height;
10097
10098 2 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!tile_grid->offsets)
10100 return AVERROR(ENOMEM);
10101
10102
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 while (y < tile_grid->coded_height) {
10103 4 int left_col = i;
10104
10105
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 while (x < tile_grid->coded_width) {
10106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (i == tile_grid->nb_tiles)
10107 return AVERROR_INVALIDDATA;
10108
10109 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10110 8 tile_grid->offsets[i].horizontal = x;
10111 8 tile_grid->offsets[i].vertical = y;
10112
10113 8 x += grid->tile_item_list[i++]->width;
10114 }
10115
10116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (x > tile_grid->coded_width) {
10117 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10118 return AVERROR_INVALIDDATA;
10119 }
10120
10121 4 x = 0;
10122 4 y += grid->tile_item_list[left_col]->height;
10123 }
10124
10125
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) {
10126 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10127 return AVERROR_INVALIDDATA;
10128 }
10129
10130 2 return 0;
10131 }
10132
10133 4 static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid,
10134 AVStreamGroupTileGrid *tile_grid)
10135 {
10136 4 MOVContext *c = s->priv_data;
10137 4 const HEIFItem *item = grid->item;
10138 uint16_t canvas_fill_value[4];
10139 4 int64_t offset = 0, pos = avio_tell(s->pb);
10140 4 int ret = 0, flags;
10141
10142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10143 av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
10144 return AVERROR_PATCHWELCOME;
10145 }
10146
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
10147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
10148 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
10149 return AVERROR_INVALIDDATA;
10150 }
10151 4 offset = c->idat_offset;
10152 }
10153
10154 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10155
10156 4 avio_r8(s->pb); /* version */
10157 4 flags = avio_r8(s->pb);
10158
10159
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10160 16 canvas_fill_value[i] = avio_rb16(s->pb);
10161 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
10162 4 canvas_fill_value[0], canvas_fill_value[1],
10163 4 canvas_fill_value[2], canvas_fill_value[3]);
10164
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10165 16 tile_grid->background[i] = canvas_fill_value[i];
10166
10167 /* actual width and height of output image */
10168 4 tile_grid->width =
10169
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);
10170 4 tile_grid->height =
10171
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);
10172
10173 /* rotation */
10174
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
4 if (item->rotation || item->hflip || item->vflip) {
10175 int ret = set_display_matrix_from_item(&tile_grid->coded_side_data,
10176 &tile_grid->nb_coded_side_data, item);
10177 if (ret < 0)
10178 return ret;
10179 }
10180
10181 /* ICC profile */
10182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (item->icc_profile_size) {
10183 int ret = set_icc_profile_from_item(&tile_grid->coded_side_data,
10184 &tile_grid->nb_coded_side_data, item);
10185 if (ret < 0)
10186 return ret;
10187 }
10188
10189 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
10190 tile_grid->width, tile_grid->height);
10191
10192 4 tile_grid->nb_tiles = grid->nb_tiles;
10193 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
10195 ret = AVERROR(ENOMEM);
10196 goto fail;
10197 }
10198
10199
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
10200 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10201
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);
10202
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);
10203 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
10204 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
10205 8 i, tile_grid->offsets[i].idx,
10206 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
10207 }
10208
10209 4 fail:
10210 4 avio_seek(s->pb, pos, SEEK_SET);
10211
10212 4 return ret;
10213 }
10214
10215 6 static int mov_parse_tiles(AVFormatContext *s)
10216 {
10217 6 MOVContext *mov = s->priv_data;
10218
10219
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (int i = 0; i < mov->nb_heif_grid; i++) {
10220 6 AVStreamGroup *stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
10221 AVStreamGroupTileGrid *tile_grid;
10222 6 const HEIFGrid *grid = &mov->heif_grid[i];
10223 6 int err, loop = 1;
10224
10225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!stg)
10226 return AVERROR(ENOMEM);
10227
10228 6 stg->id = grid->item->item_id;
10229 6 tile_grid = stg->params.tile_grid;
10230
10231
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (int j = 0; j < grid->nb_tiles; j++) {
10232 16 int tile_id = grid->tile_id_list[j];
10233 int k;
10234
10235
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 for (k = 0; k < mov->nb_heif_item; k++) {
10236 30 HEIFItem *item = mov->heif_item[k];
10237 AVStream *st;
10238
10239
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)
10240 14 continue;
10241 16 st = item->st;
10242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!st) {
10243 av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
10244 "reference a stream\n",
10245 tile_id, grid->item->item_id);
10246 ff_remove_stream_group(s, stg);
10247 loop = 0;
10248 break;
10249 }
10250
10251 16 grid->tile_item_list[j] = item;
10252 16 grid->tile_idx_list[j] = stg->nb_streams;
10253
10254 16 err = avformat_stream_group_add_stream(stg, st);
10255
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (err < 0) {
10256 int l;
10257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
10258 return err;
10259
10260
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_streams; l++)
10261
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->streams[l]->index == st->index)
10262 2 break;
10263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_streams);
10264 2 grid->tile_idx_list[j] = l;
10265 }
10266
10267
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
16 if (item->item_id != mov->primary_item_id)
10268 10 st->disposition |= AV_DISPOSITION_DEPENDENT;
10269 16 break;
10270 }
10271
10272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (k == mov->nb_heif_item) {
10273 av_assert0(loop);
10274 av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
10275 "exist\n",
10276 tile_id, grid->item->item_id);
10277 ff_remove_stream_group(s, stg);
10278 loop = 0;
10279 }
10280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!loop)
10281 break;
10282 }
10283
10284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!loop)
10285 continue;
10286
10287
2/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
6 switch (grid->item->type) {
10288 2 case MKTAG('g','r','i','d'):
10289 2 err = read_image_grid(s, grid, tile_grid);
10290 2 break;
10291 4 case MKTAG('i','o','v','l'):
10292 4 err = read_image_iovl(s, grid, tile_grid);
10293 4 break;
10294 default:
10295 av_assert0(0);
10296 }
10297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10298 return err;
10299
10300
10301
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (grid->item->name)
10302 6 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
10303
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (grid->item->item_id == mov->primary_item_id)
10304 2 stg->disposition |= AV_DISPOSITION_DEFAULT;
10305 }
10306
10307 6 return 0;
10308 }
10309
10310 13 static int mov_parse_heif_items(AVFormatContext *s)
10311 {
10312 13 MOVContext *mov = s->priv_data;
10313 int err;
10314
10315
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 13 times.
45 for (int i = 0; i < mov->nb_heif_item; i++) {
10316 32 HEIFItem *item = mov->heif_item[i];
10317 MOVStreamContext *sc;
10318 AVStream *st;
10319 32 int64_t offset = 0;
10320
10321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!item)
10322 continue;
10323
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 25 times.
32 if (!item->st) {
10324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (item->item_id == mov->thmb_item_id) {
10325 av_log(s, AV_LOG_ERROR, "HEIF thumbnail doesn't reference a stream\n");
10326 return AVERROR_INVALIDDATA;
10327 }
10328 7 continue;
10329 }
10330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (item->is_idat_relative) {
10331 if (!mov->idat_offset) {
10332 av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
10333 return AVERROR_INVALIDDATA;
10334 }
10335 offset = mov->idat_offset;
10336 }
10337
10338 25 st = item->st;
10339 25 sc = st->priv_data;
10340 25 st->codecpar->width = item->width;
10341 25 st->codecpar->height = item->height;
10342
10343 25 err = sanity_checks(s, sc, item->item_id);
10344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (err)
10345 return AVERROR_INVALIDDATA;
10346
10347 25 sc->sample_sizes[0] = item->extent_length;
10348 25 sc->chunk_offsets[0] = item->extent_offset + offset;
10349
10350
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 14 times.
25 if (item->item_id == mov->primary_item_id)
10351 11 st->disposition |= AV_DISPOSITION_DEFAULT;
10352
10353
4/6
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 19 times.
25 if (item->rotation || item->hflip || item->vflip) {
10354 6 err = set_display_matrix_from_item(&st->codecpar->coded_side_data,
10355 6 &st->codecpar->nb_coded_side_data, item);
10356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10357 return err;
10358 }
10359
10360 25 mov_build_index(mov, st);
10361 }
10362
10363
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 7 times.
13 if (mov->nb_heif_grid) {
10364 6 err = mov_parse_tiles(s);
10365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10366 return err;
10367 }
10368
10369 13 return 0;
10370 }
10371
10372 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
10373 int first_index)
10374 {
10375 MOVStreamContext *sc = st->priv_data;
10376
10377 if (sc->tref_id < 0)
10378 return NULL;
10379
10380 for (int i = first_index; i < s->nb_streams; i++)
10381 if (s->streams[i]->id == sc->tref_id)
10382 return s->streams[i];
10383
10384 return NULL;
10385 }
10386
10387 496 static int mov_parse_lcevc_streams(AVFormatContext *s)
10388 {
10389 int err;
10390
10391
2/2
✓ Branch 0 taken 676 times.
✓ Branch 1 taken 496 times.
1172 for (int i = 0; i < s->nb_streams; i++) {
10392 AVStreamGroup *stg;
10393 676 AVStream *st = s->streams[i];
10394 AVStream *st_base;
10395 676 MOVStreamContext *sc = st->priv_data;
10396 676 int j = 0;
10397
10398 /* Find an enhancement stream. */
10399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 676 times.
676 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC ||
10400 !(sc->tref_flags & MOV_TREF_FLAG_ENHANCEMENT))
10401 676 continue;
10402
10403 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10404
10405 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
10406 if (!stg)
10407 return AVERROR(ENOMEM);
10408
10409 stg->id = st->id;
10410 stg->params.lcevc->width = st->codecpar->width;
10411 stg->params.lcevc->height = st->codecpar->height;
10412 st->codecpar->width = 0;
10413 st->codecpar->height = 0;
10414
10415 while (st_base = mov_find_reference_track(s, st, j)) {
10416 err = avformat_stream_group_add_stream(stg, st_base);
10417 if (err < 0)
10418 return err;
10419
10420 j = st_base->index + 1;
10421 }
10422 if (!j) {
10423 av_log(s, AV_LOG_ERROR, "Failed to find base stream for enhancement stream\n");
10424 return AVERROR_INVALIDDATA;
10425 }
10426
10427 err = avformat_stream_group_add_stream(stg, st);
10428 if (err < 0)
10429 return err;
10430
10431 stg->params.lcevc->lcevc_index = stg->nb_streams - 1;
10432 }
10433
10434 496 return 0;
10435 }
10436
10437 496 static void fix_stream_ids(AVFormatContext *s)
10438 {
10439 496 int highest_id = 0;
10440
10441
2/2
✓ Branch 0 taken 676 times.
✓ Branch 1 taken 496 times.
1172 for (int i = 0; i < s->nb_streams; i++) {
10442 676 const AVStream *st = s->streams[i];
10443 676 const MOVStreamContext *sc = st->priv_data;
10444
2/2
✓ Branch 0 taken 626 times.
✓ Branch 1 taken 50 times.
676 if (!sc->iamf)
10445 626 highest_id = FFMAX(highest_id, st->id);
10446 }
10447 496 highest_id += !highest_id;
10448
4/4
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 410 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 86 times.
506 for (int i = 0; highest_id > 1 && i < s->nb_stream_groups; i++) {
10449 10 AVStreamGroup *stg = s->stream_groups[i];
10450
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
10451 8 continue;
10452
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_streams; j++) {
10453 14 AVStream *st = stg->streams[j];
10454 14 MOVStreamContext *sc = st->priv_data;
10455 14 st->id += highest_id;
10456 14 sc->iamf_stream_offset = highest_id;
10457 }
10458 }
10459 496 }
10460
10461 496 static int mov_read_header(AVFormatContext *s)
10462 {
10463 496 MOVContext *mov = s->priv_data;
10464 496 AVIOContext *pb = s->pb;
10465 int j, err;
10466 496 MOVAtom atom = { AV_RL32("root") };
10467 int i;
10468
10469
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 493 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
496 if (mov->decryption_key_len != 0 && mov->decryption_key_len != AES_CTR_KEY_SIZE) {
10470 av_log(s, AV_LOG_ERROR, "Invalid decryption key len %d expected %d\n",
10471 mov->decryption_key_len, AES_CTR_KEY_SIZE);
10472 return AVERROR(EINVAL);
10473 }
10474
10475 496 mov->fc = s;
10476 496 mov->trak_index = -1;
10477 496 mov->thmb_item_id = -1;
10478 496 mov->primary_item_id = -1;
10479 496 mov->cur_item_id = -1;
10480 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
10481
1/2
✓ Branch 0 taken 496 times.
✗ Branch 1 not taken.
496 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
10482 496 atom.size = avio_size(pb);
10483 else
10484 atom.size = INT64_MAX;
10485
10486 /* check MOV header */
10487 do {
10488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 if (mov->moov_retry)
10489 avio_seek(pb, 0, SEEK_SET);
10490
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 496 times.
496 if ((err = mov_read_default(mov, pb, atom)) < 0) {
10491 av_log(s, AV_LOG_ERROR, "error reading header\n");
10492 return err;
10493 }
10494 992 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10495
5/10
✓ Branch 0 taken 496 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 483 times.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 13 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
496 !mov->found_moov && (!mov->found_iloc || !mov->found_iinf) && !mov->moov_retry++);
10496
3/6
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 483 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
496 if (!mov->found_moov && !mov->found_iloc && !mov->found_iinf) {
10497 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
10498 return AVERROR_INVALIDDATA;
10499 }
10500 496 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
10501
10502
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 483 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
496 if (mov->found_iloc && mov->found_iinf) {
10503 13 err = mov_parse_heif_items(s);
10504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (err < 0)
10505 return err;
10506 }
10507 // prevent iloc and iinf boxes from being parsed while reading packets.
10508 // this is needed because an iinf box may have been parsed but ignored
10509 // for having old infe boxes which create no streams.
10510 496 mov->found_iloc = mov->found_iinf = 1;
10511
10512
1/2
✓ Branch 0 taken 496 times.
✗ Branch 1 not taken.
496 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
10513
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 494 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
496 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
10514 2 mov_read_chapters(s);
10515
2/2
✓ Branch 0 taken 676 times.
✓ Branch 1 taken 496 times.
1172 for (i = 0; i < s->nb_streams; i++)
10516
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 657 times.
676 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
10517 19 mov_read_timecode_track(s, s->streams[i]);
10518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 657 times.
657 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
10519 mov_read_rtmd_track(s, s->streams[i]);
10520 }
10521 }
10522
10523 /* copy timecode metadata from tmcd tracks to the related video streams */
10524
2/2
✓ Branch 0 taken 676 times.
✓ Branch 1 taken 496 times.
1172 for (i = 0; i < s->nb_streams; i++) {
10525 676 AVStream *st = s->streams[i];
10526 676 MOVStreamContext *sc = st->priv_data;
10527
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 658 times.
676 if (sc->timecode_track > 0) {
10528 AVDictionaryEntry *tcr;
10529 18 int tmcd_st_id = -1;
10530
10531
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 18 times.
66 for (j = 0; j < s->nb_streams; j++) {
10532 48 MOVStreamContext *sc2 = s->streams[j]->priv_data;
10533
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 30 times.
48 if (sc2->id == sc->timecode_track)
10534 18 tmcd_st_id = j;
10535 }
10536
10537
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)
10538 continue;
10539 18 tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
10540
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 if (tcr)
10541 16 av_dict_set(&st->metadata, "timecode", tcr->value, 0);
10542 }
10543 }
10544 496 export_orphan_timecode(s);
10545
10546 /* Create LCEVC stream groups. */
10547 496 err = mov_parse_lcevc_streams(s);
10548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 if (err < 0)
10549 return err;
10550
10551
2/2
✓ Branch 0 taken 676 times.
✓ Branch 1 taken 496 times.
1172 for (i = 0; i < s->nb_streams; i++) {
10552 676 AVStream *st = s->streams[i];
10553 676 FFStream *const sti = ffstream(st);
10554 676 MOVStreamContext *sc = st->priv_data;
10555 676 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
10556 676 fix_timescale(mov, sc);
10557
2/2
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 395 times.
676 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
10558
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 165 times.
281 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
10559 116 sti->skip_samples = sc->start_pad;
10560 }
10561
5/6
✓ Branch 0 taken 344 times.
✓ Branch 1 taken 332 times.
✓ Branch 2 taken 305 times.
✓ Branch 3 taken 39 times.
✓ Branch 4 taken 305 times.
✗ Branch 5 not taken.
676 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
10562 305 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
10563 305 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
10564
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 668 times.
676 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
10565
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
8 if (st->codecpar->width <= 0 || st->codecpar->height <= 0) {
10566 4 st->codecpar->width = sc->width;
10567 4 st->codecpar->height = sc->height;
10568 }
10569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
10570 st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
10571
10572 for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
10573 dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
10574
10575 err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
10576 if (err < 0)
10577 return err;
10578
10579 av_freep(&st->codecpar->extradata);
10580 st->codecpar->extradata_size = 0;
10581
10582 err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
10583 st->codecpar);
10584 if (err < 0)
10585 return err;
10586 }
10587 }
10588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 676 times.
676 if (mov->handbrake_version &&
10589 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
10590 st->codecpar->codec_id == AV_CODEC_ID_MP3) {
10591 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
10592 sti->need_parsing = AVSTREAM_PARSE_FULL;
10593 }
10594 }
10595
10596
3/4
✓ Branch 0 taken 484 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 484 times.
496 if (mov->trex_data || mov->use_mfra_for > 0) {
10597
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 12 times.
29 for (i = 0; i < s->nb_streams; i++) {
10598 17 AVStream *st = s->streams[i];
10599 17 MOVStreamContext *sc = st->priv_data;
10600
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 3 times.
17 if (sc->duration_for_fps > 0) {
10601 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
10602 14 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
10603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (st->codecpar->bit_rate == INT64_MIN) {
10604 av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
10605 sc->data_size, sc->time_scale);
10606 st->codecpar->bit_rate = 0;
10607 if (s->error_recognition & AV_EF_EXPLODE)
10608 return AVERROR_INVALIDDATA;
10609 }
10610 }
10611 }
10612 }
10613
10614
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
496 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
10615 if (mov->bitrates[i]) {
10616 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
10617 }
10618 }
10619
10620 496 ff_rfps_calculate(s);
10621
10622
2/2
✓ Branch 0 taken 676 times.
✓ Branch 1 taken 496 times.
1172 for (i = 0; i < s->nb_streams; i++) {
10623 676 AVStream *st = s->streams[i];
10624 676 MOVStreamContext *sc = st->priv_data;
10625
10626
3/3
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 344 times.
✓ Branch 2 taken 51 times.
676 switch (st->codecpar->codec_type) {
10627 281 case AVMEDIA_TYPE_AUDIO:
10628 281 err = ff_replaygain_export(st, s->metadata);
10629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 281 times.
281 if (err < 0)
10630 return err;
10631 281 break;
10632 344 case AVMEDIA_TYPE_VIDEO:
10633
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 336 times.
344 if (sc->display_matrix) {
10634
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,
10635 AV_PKT_DATA_DISPLAYMATRIX,
10636 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
10637 return AVERROR(ENOMEM);
10638
10639 8 sc->display_matrix = NULL;
10640 }
10641
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 340 times.
344 if (sc->stereo3d) {
10642
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,
10643 AV_PKT_DATA_STEREO3D,
10644 4 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
10645 return AVERROR(ENOMEM);
10646
10647 4 sc->stereo3d = NULL;
10648 }
10649
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 340 times.
344 if (sc->spherical) {
10650
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,
10651 AV_PKT_DATA_SPHERICAL,
10652 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
10653 return AVERROR(ENOMEM);
10654
10655 4 sc->spherical = NULL;
10656 }
10657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 344 times.
344 if (sc->mastering) {
10658 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10659 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
10660 (uint8_t *)sc->mastering, sc->mastering_size, 0))
10661 return AVERROR(ENOMEM);
10662
10663 sc->mastering = NULL;
10664 }
10665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 344 times.
344 if (sc->coll) {
10666 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10667 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
10668 (uint8_t *)sc->coll, sc->coll_size, 0))
10669 return AVERROR(ENOMEM);
10670
10671 sc->coll = NULL;
10672 }
10673
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 340 times.
344 if (sc->ambient) {
10674
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,
10675 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
10676 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
10677 return AVERROR(ENOMEM);
10678
10679 4 sc->ambient = NULL;
10680 }
10681 344 break;
10682 }
10683 }
10684
10685 496 fix_stream_ids(s);
10686
10687 496 ff_configure_buffers_for_index(s, AV_TIME_BASE);
10688
10689
2/2
✓ Branch 0 taken 389 times.
✓ Branch 1 taken 496 times.
885 for (i = 0; i < mov->frag_index.nb_items; i++)
10690
2/2
✓ Branch 0 taken 385 times.
✓ Branch 1 taken 4 times.
389 if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset)
10691 385 mov->frag_index.item[i].headers_read = 1;
10692
10693 496 return 0;
10694 }
10695
10696 103943 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
10697 {
10698 103943 AVIndexEntry *sample = NULL;
10699 103943 int64_t best_dts = INT64_MAX;
10700 int i;
10701 103943 MOVContext *mov = s->priv_data;
10702
2/4
✓ Branch 0 taken 103943 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 103943 times.
103943 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
10703
2/2
✓ Branch 0 taken 133746 times.
✓ Branch 1 taken 103943 times.
237689 for (i = 0; i < s->nb_streams; i++) {
10704 133746 AVStream *avst = s->streams[i];
10705 133746 FFStream *const avsti = ffstream(avst);
10706 133746 MOVStreamContext *msc = avst->priv_data;
10707
4/4
✓ Branch 0 taken 125508 times.
✓ Branch 1 taken 8238 times.
✓ Branch 2 taken 122220 times.
✓ Branch 3 taken 3288 times.
133746 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
10708 122220 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
10709 122220 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
10710
2/2
✓ Branch 0 taken 108564 times.
✓ Branch 1 taken 13656 times.
122220 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
10711 122220 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
10712
3/6
✓ Branch 0 taken 18770 times.
✓ Branch 1 taken 103450 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18770 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
122220 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
10713
1/2
✓ Branch 0 taken 18770 times.
✗ Branch 1 not taken.
18770 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10714
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 18770 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 18770 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18770 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 16642 times.
✓ Branch 9 taken 2128 times.
18770 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
10715
4/4
✓ Branch 0 taken 8536 times.
✓ Branch 1 taken 8106 times.
✓ Branch 2 taken 2128 times.
✓ Branch 3 taken 8536 times.
18770 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
10716
3/4
✓ Branch 0 taken 715 times.
✓ Branch 1 taken 1413 times.
✓ Branch 2 taken 715 times.
✗ Branch 3 not taken.
2128 (dtsdiff > AV_TIME_BASE && dts < best_dts && mov->interleaved_read)))))) {
10717 112271 sample = current_sample;
10718 112271 best_dts = dts;
10719 112271 *st = avst;
10720 }
10721 }
10722 }
10723 103943 return sample;
10724 }
10725
10726 9 static int should_retry(AVIOContext *pb, int error_code) {
10727
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))
10728 9 return 0;
10729
10730 return 1;
10731 }
10732
10733 42 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
10734 {
10735 int ret;
10736 42 MOVContext *mov = s->priv_data;
10737
10738
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
42 if (index >= 0 && index < mov->frag_index.nb_items)
10739 target = mov->frag_index.item[index].moof_offset;
10740
2/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 42 times.
42 if (target >= 0 && avio_seek(s->pb, target, SEEK_SET) != target) {
10741 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
10742 return AVERROR_INVALIDDATA;
10743 }
10744
10745 42 mov->next_root_atom = 0;
10746
2/6
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 42 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
42 if ((index < 0 && target >= 0) || index >= mov->frag_index.nb_items)
10747 42 index = search_frag_moof_offset(&mov->frag_index, target);
10748
3/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 4 times.
42 if (index >= 0 && index < mov->frag_index.nb_items &&
10749
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 mov->frag_index.item[index].moof_offset == target) {
10750
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (index + 1 < mov->frag_index.nb_items)
10751 35 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
10752
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (mov->frag_index.item[index].headers_read)
10753 35 return 0;
10754 3 mov->frag_index.item[index].headers_read = 1;
10755 }
10756
10757 7 mov->found_mdat = 0;
10758
10759 7 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
10760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
10761 return ret;
10762
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 3 times.
7 if (avio_feof(s->pb))
10763 4 return AVERROR_EOF;
10764 3 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
10765
10766 3 return 1;
10767 }
10768
10769 16 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
10770 {
10771 16 MOVStreamContext *sc = st->priv_data;
10772 uint8_t *side, *extradata;
10773 int extradata_size;
10774
10775 /* Save the current index. */
10776 16 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
10777
10778 /* Notify the decoder that extradata changed. */
10779 16 extradata_size = sc->extradata_size[sc->last_stsd_index];
10780 16 extradata = sc->extradata[sc->last_stsd_index];
10781
4/6
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
16 if (st->discard != AVDISCARD_ALL && extradata_size > 0 && extradata) {
10782 13 side = av_packet_new_side_data(pkt,
10783 AV_PKT_DATA_NEW_EXTRADATA,
10784 extradata_size);
10785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!side)
10786 return AVERROR(ENOMEM);
10787 13 memcpy(side, extradata, extradata_size);
10788 }
10789
10790 16 return 0;
10791 }
10792
10793 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
10794 {
10795 /* We can't make assumptions about the structure of the payload,
10796 because it may include multiple cdat and cdt2 samples. */
10797 const uint32_t cdat = AV_RB32("cdat");
10798 const uint32_t cdt2 = AV_RB32("cdt2");
10799 int ret, out_size = 0;
10800
10801 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
10802 if (src_size < 10)
10803 return AVERROR_INVALIDDATA;
10804
10805 /* avoid an int overflow: */
10806 if ((src_size - 8) / 2 >= INT_MAX / 3)
10807 return AVERROR_INVALIDDATA;
10808
10809 ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
10810 if (ret < 0)
10811 return ret;
10812
10813 /* parse and re-format the c608 payload in one pass. */
10814 while (src_size >= 10) {
10815 const uint32_t atom_size = avio_rb32(pb);
10816 const uint32_t atom_type = avio_rb32(pb);
10817 const uint32_t data_size = atom_size - 8;
10818 const uint8_t cc_field =
10819 atom_type == cdat ? 1 :
10820 atom_type == cdt2 ? 2 :
10821 0;
10822
10823 /* account for bytes consumed for atom size and type. */
10824 src_size -= 8;
10825
10826 /* make sure the data size stays within the buffer boundaries. */
10827 if (data_size < 2 || data_size > src_size) {
10828 ret = AVERROR_INVALIDDATA;
10829 break;
10830 }
10831
10832 /* make sure the data size is consistent with N byte pairs. */
10833 if (data_size % 2 != 0) {
10834 ret = AVERROR_INVALIDDATA;
10835 break;
10836 }
10837
10838 if (!cc_field) {
10839 /* neither cdat or cdt2 ... skip it */
10840 avio_skip(pb, data_size);
10841 src_size -= data_size;
10842 continue;
10843 }
10844
10845 for (uint32_t i = 0; i < data_size; i += 2) {
10846 pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
10847 pkt->data[out_size + 1] = avio_r8(pb);
10848 pkt->data[out_size + 2] = avio_r8(pb);
10849 out_size += 3;
10850 src_size -= 2;
10851 }
10852 }
10853
10854 if (src_size > 0)
10855 /* skip any remaining unread portion of the input payload */
10856 avio_skip(pb, src_size);
10857
10858 av_shrink_packet(pkt, out_size);
10859 return ret;
10860 }
10861
10862 103406 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
10863 int64_t current_index, AVPacket *pkt)
10864 {
10865 103406 MOVStreamContext *sc = st->priv_data;
10866
10867 103406 pkt->stream_index = sc->ffindex;
10868 103406 pkt->dts = sample->timestamp;
10869
2/2
✓ Branch 0 taken 237 times.
✓ Branch 1 taken 103169 times.
103406 if (sample->flags & AVINDEX_DISCARD_FRAME) {
10870 237 pkt->flags |= AV_PKT_FLAG_DISCARD;
10871 }
10872
4/4
✓ Branch 0 taken 83550 times.
✓ Branch 1 taken 19856 times.
✓ Branch 2 taken 83538 times.
✓ Branch 3 taken 12 times.
103406 if (sc->stts_count && sc->tts_index < sc->tts_count)
10873 83538 pkt->duration = sc->tts_data[sc->tts_index].duration;
10874
3/4
✓ Branch 0 taken 3022 times.
✓ Branch 1 taken 100384 times.
✓ Branch 2 taken 3022 times.
✗ Branch 3 not taken.
103406 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
10875 3022 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
10876 } else {
10877
2/2
✓ Branch 0 taken 15775 times.
✓ Branch 1 taken 84609 times.
100384 if (pkt->duration == 0) {
10878 15775 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
10879
2/2
✓ Branch 0 taken 15700 times.
✓ Branch 1 taken 75 times.
15775 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
10880
2/2
✓ Branch 0 taken 15747 times.
✓ Branch 1 taken 28 times.
15775 if (next_dts >= pkt->dts)
10881 15747 pkt->duration = next_dts - pkt->dts;
10882 }
10883 100384 pkt->pts = pkt->dts;
10884 }
10885
10886
4/4
✓ Branch 0 taken 83550 times.
✓ Branch 1 taken 19856 times.
✓ Branch 2 taken 83538 times.
✓ Branch 3 taken 12 times.
103406 if (sc->tts_data && sc->tts_index < sc->tts_count) {
10887 /* update tts context */
10888 83538 sc->tts_sample++;
10889
1/2
✓ Branch 0 taken 83538 times.
✗ Branch 1 not taken.
83538 if (sc->tts_index < sc->tts_count &&
10890
1/2
✓ Branch 0 taken 83538 times.
✗ Branch 1 not taken.
83538 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
10891 83538 sc->tts_index++;
10892 83538 sc->tts_sample = 0;
10893 }
10894 }
10895
10896
4/4
✓ Branch 0 taken 1044 times.
✓ Branch 1 taken 102362 times.
✓ Branch 2 taken 912 times.
✓ Branch 3 taken 132 times.
103406 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
10897 912 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
10898 912 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
10899
2/2
✓ Branch 0 taken 317 times.
✓ Branch 1 taken 595 times.
912 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
10900 }
10901 103406 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
10902 103406 pkt->pos = sample->pos;
10903
10904 /* Multiple stsd handling. */
10905
2/2
✓ Branch 0 taken 102615 times.
✓ Branch 1 taken 791 times.
103406 if (sc->stsc_data) {
10906
1/2
✓ Branch 0 taken 102615 times.
✗ Branch 1 not taken.
102615 if (sc->stsc_data[sc->stsc_index].id > 0 &&
10907
2/2
✓ Branch 0 taken 102590 times.
✓ Branch 1 taken 25 times.
102615 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
10908
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 102574 times.
102590 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
10909 16 int ret = mov_change_extradata(st, pkt);
10910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0)
10911 return ret;
10912 }
10913
10914 /* Update the stsc index for the next sample */
10915 102615 sc->stsc_sample++;
10916
2/2
✓ Branch 1 taken 55152 times.
✓ Branch 2 taken 47463 times.
102615 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
10917
2/2
✓ Branch 1 taken 1191 times.
✓ Branch 2 taken 53961 times.
55152 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
10918 1191 sc->stsc_index++;
10919 1191 sc->stsc_sample = 0;
10920 }
10921 }
10922
10923 103406 return 0;
10924 }
10925
10926 97082 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
10927 {
10928 97082 MOVContext *mov = s->priv_data;
10929 MOVStreamContext *sc;
10930 AVIndexEntry *sample;
10931 97082 AVStream *st = NULL;
10932 97082 FFStream *avsti = NULL;
10933 int64_t current_index;
10934 int ret;
10935 int i;
10936 97082 mov->fc = s;
10937 6861 retry:
10938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103943 times.
103943 if (s->pb->pos == 0) {
10939
10940 // Discard current fragment index
10941 if (mov->frag_index.allocated_size > 0) {
10942 for(int i = 0; i < mov->frag_index.nb_items; i++) {
10943 av_freep(&mov->frag_index.item[i].stream_info);
10944 }
10945 av_freep(&mov->frag_index.item);
10946 mov->frag_index.nb_items = 0;
10947 mov->frag_index.allocated_size = 0;
10948 mov->frag_index.current = -1;
10949 mov->frag_index.complete = 0;
10950 }
10951
10952 for (i = 0; i < s->nb_streams; i++) {
10953 AVStream *avst = s->streams[i];
10954 MOVStreamContext *msc = avst->priv_data;
10955
10956 // Clear current sample
10957 mov_current_sample_set(msc, 0);
10958 msc->tts_index = 0;
10959
10960 // Discard current index entries
10961 avsti = ffstream(avst);
10962 if (avsti->index_entries_allocated_size > 0) {
10963 av_freep(&avsti->index_entries);
10964 avsti->index_entries_allocated_size = 0;
10965 avsti->nb_index_entries = 0;
10966 }
10967 }
10968
10969 if ((ret = mov_switch_root(s, -1, -1)) < 0)
10970 return ret;
10971 }
10972 103943 sample = mov_find_next_sample(s, &st);
10973
6/6
✓ Branch 0 taken 103450 times.
✓ Branch 1 taken 493 times.
✓ Branch 2 taken 472 times.
✓ Branch 3 taken 102978 times.
✓ Branch 4 taken 35 times.
✓ Branch 5 taken 437 times.
103943 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
10974
2/2
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 42 times.
528 if (!mov->next_root_atom)
10975 486 return AVERROR_EOF;
10976
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 38 times.
42 if ((ret = mov_switch_root(s, mov->next_root_atom, -1)) < 0)
10977 4 return ret;
10978 38 goto retry;
10979 }
10980 103415 sc = st->priv_data;
10981 /* must be done just before reading, to avoid infinite loop on sample */
10982 103415 current_index = sc->current_index;
10983 103415 mov_current_sample_inc(sc);
10984
10985
2/2
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 102978 times.
103415 if (mov->next_root_atom) {
10986 437 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
10987 437 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
10988 }
10989
10990
2/2
✓ Branch 0 taken 96592 times.
✓ Branch 1 taken 6823 times.
103415 if (st->discard != AVDISCARD_ALL) {
10991 96592 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
10992
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 96585 times.
96592 if (ret64 != sample->pos) {
10993 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
10994 sc->ffindex, sample->pos);
10995
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
10996 mov_current_sample_dec(sc);
10997
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
10998 7 return (int)ret64;
10999 }
11000 return AVERROR_INVALIDDATA;
11001 }
11002
11003
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96585 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96585 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
11004 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
11005 goto retry;
11006 }
11007
11008
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96585 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96585 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
11009 ret = get_eia608_packet(sc->pb, pkt, sample->size);
11010 #if CONFIG_IAMFDEC
11011
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 96530 times.
96585 else if (sc->iamf) {
11012 int64_t pts, dts, pos, duration;
11013 55 int flags, size = sample->size;
11014 55 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11015 55 pts = pkt->pts; dts = pkt->dts;
11016 55 pos = pkt->pos; flags = pkt->flags;
11017 55 duration = pkt->duration;
11018
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) {
11019 275 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
11020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
275 if (ret < 0) {
11021 if (should_retry(sc->pb, ret))
11022 mov_current_sample_dec(sc);
11023 return ret;
11024 }
11025 275 size -= ret;
11026 275 pkt->pts = pts; pkt->dts = dts;
11027 275 pkt->pos = pos; pkt->flags |= flags;
11028 275 pkt->duration = duration;
11029 275 ret = ff_buffer_packet(s, pkt);
11030 }
11031
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 if (!ret)
11032 55 return FFERROR_REDO;
11033 }
11034 #endif
11035 else
11036 96530 ret = av_get_packet(sc->pb, pkt, sample->size);
11037
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 96528 times.
96530 if (ret < 0) {
11038
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (should_retry(sc->pb, ret)) {
11039 mov_current_sample_dec(sc);
11040 }
11041 2 return ret;
11042 }
11043 #if CONFIG_DV_DEMUXER
11044
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96528 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96528 if (mov->dv_demux && sc->dv_audio_container) {
11045 ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
11046 av_packet_unref(pkt);
11047 if (ret < 0)
11048 return ret;
11049 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
11050 if (ret < 0)
11051 return ret;
11052 }
11053 #endif
11054
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 96510 times.
96528 if (sc->has_palette) {
11055 uint8_t *pal;
11056
11057 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
11058
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
11059 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
11060 } else {
11061 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
11062 18 sc->has_palette = 0;
11063 }
11064 }
11065
4/6
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 96240 times.
✓ Branch 3 taken 288 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 288 times.
✗ Branch 6 not taken.
96528 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
11066
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 288 times.
288 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
11067 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
11068 }
11069 }
11070
11071 103351 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11072
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103351 times.
103351 if (ret < 0)
11073 return ret;
11074
11075
2/2
✓ Branch 0 taken 6823 times.
✓ Branch 1 taken 96528 times.
103351 if (st->discard == AVDISCARD_ALL)
11076 6823 goto retry;
11077
11078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96528 times.
96528 if (mov->aax_mode)
11079 aax_filter(pkt->data, pkt->size, mov);
11080
11081 96528 ret = cenc_filter(mov, st, sc, pkt, current_index);
11082
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96528 times.
96528 if (ret < 0) {
11083 return ret;
11084 }
11085
11086 96528 return 0;
11087 }
11088
11089 361 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
11090 {
11091 361 MOVContext *mov = s->priv_data;
11092 int index;
11093
11094
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 26 times.
361 if (!mov->frag_index.complete)
11095 335 return 0;
11096
11097 26 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
11098
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 22 times.
26 if (index < 0)
11099 4 index = 0;
11100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (!mov->frag_index.item[index].headers_read)
11101 return mov_switch_root(s, -1, index);
11102
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (index + 1 < mov->frag_index.nb_items)
11103 26 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11104
11105 26 return 0;
11106 }
11107
11108 static int is_open_key_sample(const MOVStreamContext *sc, int sample)
11109 {
11110 // TODO: a bisect search would scale much better
11111 for (int i = 0; i < sc->open_key_samples_count; i++) {
11112 const int oks = sc->open_key_samples[i];
11113 if (oks == sample)
11114 return 1;
11115 if (oks > sample) /* list is monotically increasing so we can stop early */
11116 break;
11117 }
11118 return 0;
11119 }
11120
11121 /*
11122 * Some key sample may be key frames but not IDR frames, so a random access to
11123 * them may not be allowed.
11124 */
11125 229 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
11126 {
11127 229 MOVStreamContext *sc = st->priv_data;
11128 229 FFStream *const sti = ffstream(st);
11129 int64_t key_sample_dts, key_sample_pts;
11130
11131
1/2
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
229 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
11132 229 return 1;
11133
11134 if (sample >= sc->sample_offsets_count)
11135 return 1;
11136
11137 key_sample_dts = sti->index_entries[sample].timestamp;
11138 key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
11139
11140 /*
11141 * If the sample needs to be presented before an open key sample, they may
11142 * not be decodable properly, even though they come after in decoding
11143 * order.
11144 */
11145 if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
11146 return 0;
11147
11148 return 1;
11149 }
11150
11151 361 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
11152 {
11153 361 MOVStreamContext *sc = st->priv_data;
11154 361 FFStream *const sti = ffstream(st);
11155 int sample, time_sample, ret, next_ts, requested_sample;
11156 unsigned int i;
11157
11158 // Here we consider timestamp to be PTS, hence try to offset it so that we
11159 // can search over the DTS timeline.
11160 361 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
11161
11162 361 ret = mov_seek_fragment(s, st, timestamp);
11163
1/2
✓ Branch 0 taken 361 times.
✗ Branch 1 not taken.
361 if (ret < 0)
11164 return ret;
11165
11166 for (;;) {
11167 361 sample = av_index_search_timestamp(st, timestamp, flags);
11168 361 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
11169
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)
11170 43 sample = 0;
11171
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 335 times.
361 if (sample < 0) /* not sure what to do */
11172 26 return AVERROR_INVALIDDATA;
11173
11174
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))
11175 break;
11176
11177 next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
11178 requested_sample = av_index_search_timestamp(st, next_ts, flags);
11179
11180 // If we've reached a different sample trying to find a good pts to
11181 // seek to, give up searching because we'll end up seeking back to
11182 // sample 0 on every seek.
11183 if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
11184 break;
11185
11186 timestamp = next_ts;
11187 }
11188
11189 335 mov_current_sample_set(sc, sample);
11190 335 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
11191 /* adjust time to sample index */
11192
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 125 times.
335 if (sc->tts_data) {
11193 210 time_sample = 0;
11194
1/2
✓ Branch 0 taken 60235 times.
✗ Branch 1 not taken.
60235 for (i = 0; i < sc->tts_count; i++) {
11195 60235 int next = time_sample + sc->tts_data[i].count;
11196
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 60025 times.
60235 if (next > sc->current_sample) {
11197 210 sc->tts_index = i;
11198 210 sc->tts_sample = sc->current_sample - time_sample;
11199 210 break;
11200 }
11201 60025 time_sample = next;
11202 }
11203 }
11204
11205 /* adjust stsd index */
11206
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 26 times.
335 if (sc->chunk_count) {
11207 309 time_sample = 0;
11208
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
381 for (i = 0; i < sc->stsc_count; i++) {
11209 381 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
11210
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 72 times.
381 if (next > sc->current_sample) {
11211 309 sc->stsc_index = i;
11212 309 sc->stsc_sample = sc->current_sample - time_sample;
11213 309 break;
11214 }
11215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
11216 72 time_sample = next;
11217 }
11218 }
11219
11220 335 return sample;
11221 }
11222
11223 335 static int64_t mov_get_skip_samples(AVStream *st, int sample)
11224 {
11225 335 MOVStreamContext *sc = st->priv_data;
11226 335 FFStream *const sti = ffstream(st);
11227 335 int64_t first_ts = sti->index_entries[0].timestamp;
11228 335 int64_t ts = sti->index_entries[sample].timestamp;
11229 int64_t off;
11230
11231
2/2
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 151 times.
335 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
11232 184 return 0;
11233
11234 /* compute skip samples according to stream start_pad, seek ts and first ts */
11235 151 off = av_rescale_q(ts - first_ts, st->time_base,
11236 151 (AVRational){1, st->codecpar->sample_rate});
11237 151 return FFMAX(sc->start_pad - off, 0);
11238 }
11239
11240 340 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
11241 {
11242 340 MOVContext *mc = s->priv_data;
11243 AVStream *st;
11244 FFStream *sti;
11245 int sample;
11246 int i;
11247
11248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 340 times.
340 if (stream_index >= s->nb_streams)
11249 return AVERROR_INVALIDDATA;
11250
11251 340 st = s->streams[stream_index];
11252 340 sti = ffstream(st);
11253 340 sample = mov_seek_stream(s, st, sample_time, flags);
11254
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 314 times.
340 if (sample < 0)
11255 26 return sample;
11256
11257
1/2
✓ Branch 0 taken 314 times.
✗ Branch 1 not taken.
314 if (mc->seek_individually) {
11258 /* adjust seek timestamp to found sample timestamp */
11259 314 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
11260 314 sti->skip_samples = mov_get_skip_samples(st, sample);
11261
11262
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 314 times.
649 for (i = 0; i < s->nb_streams; i++) {
11263 335 AVStream *const st = s->streams[i];
11264 335 FFStream *const sti = ffstream(st);
11265 int64_t timestamp;
11266
11267
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 21 times.
335 if (stream_index == i)
11268 314 continue;
11269
11270 21 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
11271 21 sample = mov_seek_stream(s, st, timestamp, flags);
11272
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (sample >= 0)
11273 21 sti->skip_samples = mov_get_skip_samples(st, sample);
11274 }
11275 } else {
11276 for (i = 0; i < s->nb_streams; i++) {
11277 MOVStreamContext *sc;
11278 st = s->streams[i];
11279 sc = st->priv_data;
11280 mov_current_sample_set(sc, 0);
11281 }
11282 while (1) {
11283 MOVStreamContext *sc;
11284 AVIndexEntry *entry = mov_find_next_sample(s, &st);
11285 if (!entry)
11286 return AVERROR_INVALIDDATA;
11287 sc = st->priv_data;
11288 if (sc->ffindex == stream_index && sc->current_sample == sample)
11289 break;
11290 mov_current_sample_inc(sc);
11291 }
11292 }
11293 314 return 0;
11294 }
11295
11296 #define OFFSET(x) offsetof(MOVContext, x)
11297 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
11298 static const AVOption mov_options[] = {
11299 {"use_absolute_path",
11300 "allow using absolute path when opening alias, this is a possible security issue",
11301 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
11302 0, 1, FLAGS},
11303 {"seek_streams_individually",
11304 "Seek each stream individually to the closest point",
11305 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
11306 0, 1, FLAGS},
11307 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
11308 0, 1, FLAGS},
11309 {"advanced_editlist",
11310 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
11311 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
11312 0, 1, FLAGS},
11313 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
11314 0, 1, FLAGS},
11315 {"use_mfra_for",
11316 "use mfra for fragment timestamps",
11317 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
11318 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
11319 .unit = "use_mfra_for"},
11320 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
11321 FLAGS, .unit = "use_mfra_for" },
11322 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
11323 FLAGS, .unit = "use_mfra_for" },
11324 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
11325 FLAGS, .unit = "use_mfra_for" },
11326 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
11327 0, 1, FLAGS},
11328 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
11329 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11330 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
11331 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11332 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
11333 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11334 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
11335 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11336 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
11337 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11338 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
11339 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
11340 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
11341 .flags = AV_OPT_FLAG_DECODING_PARAM },
11342 { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11343 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
11344 {.i64 = 0}, 0, 1, FLAGS },
11345 { "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 },
11346 { "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 },
11347
11348 { NULL },
11349 };
11350
11351 static const AVClass mov_class = {
11352 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
11353 .item_name = av_default_item_name,
11354 .option = mov_options,
11355 .version = LIBAVUTIL_VERSION_INT,
11356 };
11357
11358 const FFInputFormat ff_mov_demuxer = {
11359 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
11360 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
11361 .p.priv_class = &mov_class,
11362 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v,avif,heic,heif",
11363 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
11364 .priv_data_size = sizeof(MOVContext),
11365 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
11366 .read_probe = mov_probe,
11367 .read_header = mov_read_header,
11368 .read_packet = mov_read_packet,
11369 .read_close = mov_read_close,
11370 .read_seek = mov_read_seek,
11371 };
11372