FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2025-04-25 22:50:00
Exec Total Coverage
Lines: 4279 6778 63.1%
Functions: 173 212 81.6%
Branches: 2407 4552 52.9%

Line Branch Exec Source
1 /*
2 * MOV demuxer
3 * Copyright (c) 2001 Fabrice Bellard
4 * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
5 *
6 * first version by Francois Revol <revol@free.fr>
7 * seek function by Gael Chardon <gael.dev@4now.net>
8 *
9 * This file is part of FFmpeg.
10 *
11 * FFmpeg is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * FFmpeg is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with FFmpeg; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #include "config_components.h"
27
28 #include <inttypes.h>
29 #include <limits.h>
30 #include <stdint.h>
31
32 #include "libavutil/attributes.h"
33 #include "libavutil/bprint.h"
34 #include "libavutil/channel_layout.h"
35 #include "libavutil/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 326 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
169 char *dst, int dstlen)
170 {
171 326 char *p = dst;
172 326 char *end = dst+dstlen-1;
173 int i;
174
175
2/2
✓ Branch 0 taken 2889 times.
✓ Branch 1 taken 326 times.
3215 for (i = 0; i < len; i++) {
176 2889 uint8_t t, c = avio_r8(pb);
177
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2889 times.
2889 if (p >= end)
179 continue;
180
181
2/2
✓ Branch 0 taken 2886 times.
✓ Branch 1 taken 3 times.
2889 if (c < 0x80)
182 2886 *p++ = c;
183
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 else if (p < end)
184
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 3 times.
6 PUT_UTF8(mac_to_unicode[c-0x80], t, if (p < end) *p++ = t;);
185 }
186 326 *p = 0;
187 326 return p - dst;
188 }
189
190 /**
191 * Get the current item in the parsing process.
192 */
193 82 static HEIFItem *heif_cur_item(MOVContext *c)
194 {
195 82 HEIFItem *item = NULL;
196
197
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 12 times.
138 for (int i = 0; i < c->nb_heif_item; i++) {
198
3/4
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✓ Branch 3 taken 70 times.
126 if (!c->heif_item[i] || c->heif_item[i]->item_id != c->cur_item_id)
199 56 continue;
200
201 70 item = c->heif_item[i];
202 70 break;
203 }
204
205 82 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 198 static AVStream *get_curr_st(MOVContext *c)
213 {
214 198 AVStream *st = NULL;
215 HEIFItem *item;
216
217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 if (c->fc->nb_streams < 1)
218 return NULL;
219
220
2/2
✓ Branch 0 taken 169 times.
✓ Branch 1 taken 29 times.
198 if (c->cur_item_id == -1)
221 169 return c->fc->streams[c->fc->nb_streams-1];
222
223 29 item = heif_cur_item(c);
224
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (item)
225 29 st = item->st;
226
227 29 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 472 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
345 {
346 472 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
347 472 char key2[32], language[4] = {0};
348 472 char *str = NULL;
349 472 const char *key = NULL;
350 472 uint16_t langcode = 0;
351 472 uint32_t data_type = 0, str_size_alloc;
352 uint64_t str_size;
353 472 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
354 472 int raw = 0;
355 472 int num = 0;
356 AVDictionary **metadata;
357
358
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 443 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
472 if (c->trak_index >= 0 && c->trak_index < c->fc->nb_streams)
359 29 metadata = &c->fc->streams[c->trak_index]->metadata;
360 else
361 443 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 58 times.
✓ Branch 68 taken 50 times.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✓ Branch 72 taken 1 times.
✓ Branch 73 taken 5 times.
472 switch (atom.type) {
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 58 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 174 times.
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
760 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 156 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 105 times.
✓ Branch 3 taken 51 times.
✓ Branch 4 taken 105 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 99 times.
✓ Branch 7 taken 6 times.
174 } else if (atom.size > 4 && key && !c->itunes_metadata && !raw) {
488 99 str_size = avio_rb16(pb); // string length
489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 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 99 langcode = avio_rb16(pb);
496 99 ff_mov_lang_to_iso639(langcode, language);
497 99 atom.size -= 4;
498 } else
499 75 str_size = atom.size;
500
501
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 460 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
460 if (c->export_all && !key) {
502 key = av_fourcc_make_string(tmp_key, atom.type);
503 }
504
505
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 371 times.
460 if (!key)
506 89 return 0;
507
2/4
✓ Branch 0 taken 371 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 371 times.
371 if (atom.size < 0 || str_size >= INT_MAX/2)
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 330 times.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
371 num = (data_type >= 21 && data_type <= 23);
513
4/4
✓ Branch 0 taken 330 times.
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 324 times.
✓ Branch 3 taken 6 times.
371 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
514 371 str = av_mallocz(str_size_alloc);
515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 371 times.
371 if (!str)
516 return AVERROR(ENOMEM);
517
518
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 311 times.
371 if (parse)
519 60 parse(c, pb, str_size, key);
520 else {
521
8/10
✓ Branch 0 taken 305 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 305 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 100 times.
✓ Branch 5 taken 205 times.
✓ Branch 6 taken 86 times.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 86 times.
311 if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
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 295 times.
297 } 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 295 times.
295 } 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 282 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
308 } 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 282 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
282 } 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 282 int ret = ffio_read_size(pb, str, str_size);
573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 282 times.
282 if (ret < 0) {
574 av_free(str);
575 return ret;
576 }
577 282 str[str_size] = 0;
578 }
579 311 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
580 311 av_dict_set(metadata, key, str, 0);
581
4/4
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 212 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 62 times.
311 if (*language && strcmp(language, "und")) {
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 110 times.
✓ Branch 1 taken 201 times.
311 if (!strcmp(key, "encoder")) {
586 int major, minor, micro;
587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
110 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 371 av_freep(&str);
594 371 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 594 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 594 times.
594 if (c->fc->nb_streams < 1)
643 return 0;
644 594 st = c->fc->streams[c->fc->nb_streams-1];
645 594 sc = st->priv_data;
646
647 594 avio_rb32(pb); // version + flags
648 594 entries = avio_rb32(pb);
649
1/2
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
594 if (!entries ||
650
1/2
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
594 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 entries >= UINT_MAX / sizeof(*sc->drefs))
652 return AVERROR_INVALIDDATA;
653
654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 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 594 av_free(sc->drefs);
660 594 sc->drefs_count = 0;
661 594 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (!sc->drefs)
663 return AVERROR(ENOMEM);
664 594 sc->drefs_count = entries;
665
666
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 594 times.
1188 for (i = 0; i < entries; i++) {
667 594 MOVDref *dref = &sc->drefs[i];
668 594 uint32_t size = avio_rb32(pb);
669 594 int64_t next = avio_tell(pb);
670
671
3/6
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 594 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 594 times.
594 if (size < 12 || next < 0 || next > INT64_MAX - size)
672 return AVERROR_INVALIDDATA;
673
674 594 next += size - 4;
675
676 594 dref->type = avio_rl32(pb);
677 594 avio_rb32(pb); // version + flags
678
679
3/4
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 476 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 118 times.
594 if (dref->type == MKTAG('a','l','i','s') && size > 150) {
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 594 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
771 dref->type, size);
772 594 entries--;
773 594 i--;
774 }
775 594 avio_seek(pb, next, SEEK_SET);
776 }
777 594 return 0;
778 }
779
780 1087 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 1087 avio_r8(pb); /* version */
790 1087 avio_rb24(pb); /* flags */
791
792 /* component type */
793 1087 ctype = avio_rl32(pb);
794 1087 type = avio_rl32(pb); /* component subtype */
795
796 1087 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
797 1087 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
798
799
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 951 times.
1087 if (c->trak_index < 0) { // meta not inside a trak
800
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 125 times.
136 if (type == MKTAG('m','d','t','a')) {
801 11 c->found_hdlr_mdta = 1;
802 }
803 136 return 0;
804 }
805
806 951 st = c->fc->streams[c->fc->nb_streams-1];
807
808
2/2
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 649 times.
951 if (type == MKTAG('v','i','d','e'))
809 302 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
810
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 408 times.
649 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 408 times.
408 else if (type == MKTAG('m','1','a',' '))
813 st->codecpar->codec_id = AV_CODEC_ID_MP2;
814
2/4
✓ Branch 0 taken 408 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 408 times.
408 else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
815 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
816
817 951 avio_rb32(pb); /* component manufacture */
818 951 avio_rb32(pb); /* component flags */
819 951 avio_rb32(pb); /* component flags mask */
820
821 951 title_size = atom.size - 24;
822
2/2
✓ Branch 0 taken 948 times.
✓ Branch 1 taken 3 times.
951 if (title_size > 0) {
823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 948 times.
948 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
824 return AVERROR_INVALIDDATA;
825 948 title_str = av_malloc(title_size + 1); /* Add null terminator */
826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 948 times.
948 if (!title_str)
827 return AVERROR(ENOMEM);
828
829 948 ret = ffio_read_size(pb, title_str, title_size);
830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 948 times.
948 if (ret < 0) {
831 av_freep(&title_str);
832 return ret;
833 }
834 948 title_str[title_size] = 0;
835
2/2
✓ Branch 0 taken 897 times.
✓ Branch 1 taken 51 times.
948 if (title_str[0]) {
836
4/4
✓ Branch 0 taken 690 times.
✓ Branch 1 taken 207 times.
✓ Branch 2 taken 688 times.
✓ Branch 3 taken 2 times.
897 int off = (!c->isom && title_str[0] == title_size - 1);
837 // flag added so as to not set stream handler name if already set from mdia->hdlr
838 897 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
839 }
840 948 av_freep(&title_str);
841 }
842
843 951 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 16 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1239 {
1240 AVStream *st;
1241 HEIFItem *item;
1242 AVPacketSideData *sd;
1243 16 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 16 item = heif_cur_item(c);
1249 16 st = get_curr_st(c);
1250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!st)
1251 return 0;
1252
1253 16 width = st->codecpar->width;
1254 16 height = st->codecpar->height;
1255
4/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
16 if ((!width || !height) && item) {
1256 4 width = item->width;
1257 4 height = item->height;
1258 }
1259
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
16 if (!width || !height) {
1260 err = AVERROR_INVALIDDATA;
1261 goto fail;
1262 }
1263
1264 16 aperture_width.num = avio_rb32(pb);
1265 16 aperture_width.den = avio_rb32(pb);
1266 16 aperture_height.num = avio_rb32(pb);
1267 16 aperture_height.den = avio_rb32(pb);
1268
1269 16 horiz_off.num = avio_rb32(pb);
1270 16 horiz_off.den = avio_rb32(pb);
1271 16 vert_off.num = avio_rb32(pb);
1272 16 vert_off.den = avio_rb32(pb);
1273
1274
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 if (aperture_width.num < 0 || aperture_width.den < 0 ||
1275
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 aperture_height.num < 0 || aperture_height.den < 0 ||
1276
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
16 horiz_off.den < 0 || vert_off.den < 0) {
1277 err = AVERROR_INVALIDDATA;
1278 goto fail;
1279 }
1280 16 av_log(c->fc, AV_LOG_TRACE, "clap: apertureWidth %d/%d, apertureHeight %d/%d "
1281 "horizOff %d/%d vertOff %d/%d\n",
1282 aperture_width.num, aperture_width.den, aperture_height.num, aperture_height.den,
1283 horiz_off.num, horiz_off.den, vert_off.num, vert_off.den);
1284
1285 16 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1286 16 pc_x = av_add_q(pc_x, horiz_off);
1287 16 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1288 16 pc_y = av_add_q(pc_y, vert_off);
1289
1290 16 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1291 16 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1292 16 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1293 16 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1294
1295 16 left = av_q2d(av_sub_q(pc_x, aperture_width));
1296 16 right = av_q2d(av_add_q(pc_x, aperture_width));
1297 16 top = av_q2d(av_sub_q(pc_y, aperture_height));
1298 16 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1299
1300
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 if (bottom > (height - 1) ||
1301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 right > (width - 1)) {
1302 2 err = AVERROR_INVALIDDATA;
1303 2 goto fail;
1304 }
1305
1306 14 bottom = height - 1 - bottom;
1307 14 right = width - 1 - right;
1308
1309
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
14 if (!(left | right | top | bottom))
1310 6 return 0;
1311
1312
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if ((left + right) >= width ||
1313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 (top + bottom) >= height) {
1314 err = AVERROR_INVALIDDATA;
1315 goto fail;
1316 }
1317
1318 8 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1319 8 &st->codecpar->nb_coded_side_data,
1320 AV_PKT_DATA_FRAME_CROPPING,
1321 sizeof(uint32_t) * 4, 0);
1322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!sd)
1323 return AVERROR(ENOMEM);
1324
1325 8 AV_WL32A(sd->data, top);
1326 8 AV_WL32A(sd->data + 4, bottom);
1327 8 AV_WL32A(sd->data + 8, left);
1328 8 AV_WL32A(sd->data + 12, right);
1329
1330 10 fail:
1331
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (err < 0) {
1332 2 int explode = !!(c->fc->error_recognition & AV_EF_EXPLODE);
1333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_log(c->fc, explode ? AV_LOG_ERROR : AV_LOG_WARNING, "Invalid clap box\n");
1334
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!explode)
1335 2 err = 0;
1336 }
1337
1338 10 return err;
1339 }
1340
1341 /* This atom overrides any previously set aspect ratio */
1342 66 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1343 {
1344 66 const int num = avio_rb32(pb);
1345 66 const int den = avio_rb32(pb);
1346 AVStream *st;
1347 MOVStreamContext *sc;
1348
1349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (c->fc->nb_streams < 1)
1350 return 0;
1351 66 st = c->fc->streams[c->fc->nb_streams-1];
1352 66 sc = st->priv_data;
1353
1354 66 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1355
1356
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 2 times.
66 if (den != 0) {
1357 64 sc->h_spacing = num;
1358 64 sc->v_spacing = den;
1359 }
1360 66 return 0;
1361 }
1362
1363 /* this atom contains actual media data */
1364 873 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1365 {
1366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 873 times.
873 if (atom.size == 0) /* wrong one (MP4) */
1367 return 0;
1368 873 c->found_mdat=1;
1369 873 return 0; /* now go for moov */
1370 }
1371
1372 #define DRM_BLOB_SIZE 56
1373
1374 static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1375 {
1376 uint8_t intermediate_key[20];
1377 uint8_t intermediate_iv[20];
1378 uint8_t input[64];
1379 uint8_t output[64];
1380 uint8_t file_checksum[20];
1381 uint8_t calculated_checksum[20];
1382 char checksum_string[2 * sizeof(file_checksum) + 1];
1383 struct AVSHA *sha;
1384 int i;
1385 int ret = 0;
1386 uint8_t *activation_bytes = c->activation_bytes;
1387 uint8_t *fixed_key = c->audible_fixed_key;
1388
1389 c->aax_mode = 1;
1390
1391 sha = av_sha_alloc();
1392 if (!sha)
1393 return AVERROR(ENOMEM);
1394 av_free(c->aes_decrypt);
1395 c->aes_decrypt = av_aes_alloc();
1396 if (!c->aes_decrypt) {
1397 ret = AVERROR(ENOMEM);
1398 goto fail;
1399 }
1400
1401 /* drm blob processing */
1402 avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1403 avio_read(pb, input, DRM_BLOB_SIZE);
1404 avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1405 avio_read(pb, file_checksum, 20);
1406
1407 // required by external tools
1408 ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1);
1409 av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string);
1410
1411 /* verify activation data */
1412 if (!activation_bytes) {
1413 av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1414 ret = 0; /* allow ffprobe to continue working on .aax files */
1415 goto fail;
1416 }
1417 if (c->activation_bytes_size != 4) {
1418 av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1419 ret = AVERROR(EINVAL);
1420 goto fail;
1421 }
1422
1423 /* verify fixed key */
1424 if (c->audible_fixed_key_size != 16) {
1425 av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1426 ret = AVERROR(EINVAL);
1427 goto fail;
1428 }
1429
1430 /* AAX (and AAX+) key derivation */
1431 av_sha_init(sha, 160);
1432 av_sha_update(sha, fixed_key, 16);
1433 av_sha_update(sha, activation_bytes, 4);
1434 av_sha_final(sha, intermediate_key);
1435 av_sha_init(sha, 160);
1436 av_sha_update(sha, fixed_key, 16);
1437 av_sha_update(sha, intermediate_key, 20);
1438 av_sha_update(sha, activation_bytes, 4);
1439 av_sha_final(sha, intermediate_iv);
1440 av_sha_init(sha, 160);
1441 av_sha_update(sha, intermediate_key, 16);
1442 av_sha_update(sha, intermediate_iv, 16);
1443 av_sha_final(sha, calculated_checksum);
1444 if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1445 av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1446 ret = AVERROR_INVALIDDATA;
1447 goto fail;
1448 }
1449 av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1450 av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1451 for (i = 0; i < 4; i++) {
1452 // file data (in output) is stored in big-endian mode
1453 if (activation_bytes[i] != output[3 - i]) { // critical error
1454 av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1455 ret = AVERROR_INVALIDDATA;
1456 goto fail;
1457 }
1458 }
1459 memcpy(c->file_key, output + 8, 16);
1460 memcpy(input, output + 26, 16);
1461 av_sha_init(sha, 160);
1462 av_sha_update(sha, input, 16);
1463 av_sha_update(sha, c->file_key, 16);
1464 av_sha_update(sha, fixed_key, 16);
1465 av_sha_final(sha, c->file_iv);
1466
1467 fail:
1468 av_free(sha);
1469
1470 return ret;
1471 }
1472
1473 static int mov_aaxc_crypto(MOVContext *c)
1474 {
1475 if (c->audible_key_size != 16) {
1476 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n");
1477 return AVERROR(EINVAL);
1478 }
1479
1480 if (c->audible_iv_size != 16) {
1481 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n");
1482 return AVERROR(EINVAL);
1483 }
1484
1485 c->aes_decrypt = av_aes_alloc();
1486 if (!c->aes_decrypt) {
1487 return AVERROR(ENOMEM);
1488 }
1489
1490 memcpy(c->file_key, c->audible_key, 16);
1491 memcpy(c->file_iv, c->audible_iv, 16);
1492 c->aax_mode = 1;
1493
1494 return 0;
1495 }
1496
1497 // Audible AAX (and AAX+) bytestream decryption
1498 static int aax_filter(uint8_t *input, int size, MOVContext *c)
1499 {
1500 int blocks = 0;
1501 unsigned char iv[16];
1502
1503 memcpy(iv, c->file_iv, 16); // iv is overwritten
1504 blocks = size >> 4; // trailing bytes are not encrypted!
1505 av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1506 av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1507
1508 return 0;
1509 }
1510
1511 /* read major brand, minor version and compatible brands and store them as metadata */
1512 452 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1513 {
1514 uint32_t minor_ver;
1515 int comp_brand_size;
1516 char* comp_brands_str;
1517 452 uint8_t type[5] = {0};
1518 452 int ret = ffio_read_size(pb, type, 4);
1519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 452 times.
452 if (ret < 0)
1520 return ret;
1521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 452 times.
452 if (c->fc->nb_streams) {
1522 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1523 return AVERROR_INVALIDDATA;
1524 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate FTYP\n");
1525 return 0;
1526 }
1527
1528
2/2
✓ Branch 0 taken 220 times.
✓ Branch 1 taken 232 times.
452 if (strcmp(type, "qt "))
1529 220 c->isom = 1;
1530 452 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1531 452 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1532 452 minor_ver = avio_rb32(pb); /* minor version */
1533 452 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1534
1535 452 comp_brand_size = atom.size - 8;
1536
2/4
✓ Branch 0 taken 452 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 452 times.
452 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1537 return AVERROR_INVALIDDATA;
1538 452 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 452 times.
452 if (!comp_brands_str)
1540 return AVERROR(ENOMEM);
1541
1542 452 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 452 times.
452 if (ret < 0) {
1544 av_freep(&comp_brands_str);
1545 return ret;
1546 }
1547 452 comp_brands_str[comp_brand_size] = 0;
1548 452 av_dict_set(&c->fc->metadata, "compatible_brands",
1549 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1550
1551 // Logic for handling Audible's .aaxc files
1552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 452 times.
452 if (!strcmp(type, "aaxc")) {
1553 mov_aaxc_crypto(c);
1554 }
1555
1556 452 return 0;
1557 }
1558
1559 /* this atom should contain all header atoms */
1560 484 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1561 {
1562 int ret;
1563
1564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
484 if (c->found_moov) {
1565 av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1566 avio_skip(pb, atom.size);
1567 return 0;
1568 }
1569
1570
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 484 times.
484 if ((ret = mov_read_default(c, pb, atom)) < 0)
1571 return ret;
1572 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1573 /* so we don't parse the whole file if over a network */
1574 484 c->found_moov=1;
1575 484 return 0; /* now go for mdat */
1576 }
1577
1578 2869 static MOVFragmentStreamInfo * get_frag_stream_info(
1579 MOVFragmentIndex *frag_index,
1580 int index,
1581 int id)
1582 {
1583 int i;
1584 MOVFragmentIndexItem * item;
1585
1586
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)
1587 return NULL;
1588 2869 item = &frag_index->item[index];
1589
1/2
✓ Branch 0 taken 2993 times.
✗ Branch 1 not taken.
2993 for (i = 0; i < item->nb_stream_info; i++)
1590
2/2
✓ Branch 0 taken 2869 times.
✓ Branch 1 taken 124 times.
2993 if (item->stream_info[i].id == id)
1591 2869 return &item->stream_info[i];
1592
1593 // This shouldn't happen
1594 return NULL;
1595 }
1596
1597 388 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1598 {
1599 int i;
1600 MOVFragmentIndexItem * item;
1601
1602
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_index->current < 0 ||
1603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 frag_index->current >= frag_index->nb_items)
1604 return;
1605
1606 388 item = &frag_index->item[frag_index->current];
1607
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < item->nb_stream_info; i++)
1608
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (item->stream_info[i].id == id) {
1609 388 item->current = i;
1610 388 return;
1611 }
1612
1613 // id not found. This shouldn't happen.
1614 item->current = -1;
1615 }
1616
1617 1149 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1618 MOVFragmentIndex *frag_index)
1619 {
1620 MOVFragmentIndexItem *item;
1621
1/2
✓ Branch 0 taken 1149 times.
✗ Branch 1 not taken.
1149 if (frag_index->current < 0 ||
1622
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1146 times.
1149 frag_index->current >= frag_index->nb_items)
1623 3 return NULL;
1624
1625 1146 item = &frag_index->item[frag_index->current];
1626
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)
1627 1146 return &item->stream_info[item->current];
1628
1629 // This shouldn't happen
1630 return NULL;
1631 }
1632
1633 798 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1634 {
1635 int a, b, m;
1636 int64_t moof_offset;
1637
1638 // Optimize for appending new entries
1639
2/2
✓ Branch 0 taken 788 times.
✓ Branch 1 taken 10 times.
798 if (!frag_index->nb_items ||
1640
2/2
✓ Branch 0 taken 383 times.
✓ Branch 1 taken 405 times.
788 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1641 393 return frag_index->nb_items;
1642
1643 405 a = -1;
1644 405 b = frag_index->nb_items;
1645
1646
2/2
✓ Branch 0 taken 2655 times.
✓ Branch 1 taken 405 times.
3060 while (b - a > 1) {
1647 2655 m = (a + b) >> 1;
1648 2655 moof_offset = frag_index->item[m].moof_offset;
1649
2/2
✓ Branch 0 taken 732 times.
✓ Branch 1 taken 1923 times.
2655 if (moof_offset >= offset)
1650 732 b = m;
1651
2/2
✓ Branch 0 taken 2328 times.
✓ Branch 1 taken 327 times.
2655 if (moof_offset <= offset)
1652 2328 a = m;
1653 }
1654 405 return b;
1655 }
1656
1657 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1658 {
1659 av_assert0(frag_stream_info);
1660 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1661 return frag_stream_info->sidx_pts;
1662 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1663 return frag_stream_info->first_tfra_pts;
1664 return frag_stream_info->tfdt_dts;
1665 }
1666
1667 219 static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1668 MOVFragmentIndex *frag_index, int index)
1669 {
1670 MOVFragmentStreamInfo * frag_stream_info;
1671 219 MOVStreamContext *sc = dst_st->priv_data;
1672 int64_t timestamp;
1673 int i, j;
1674
1675 // If the stream is referenced by any sidx, limit the search
1676 // to fragments that referenced this stream in the sidx
1677
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (sc->has_sidx) {
1678 219 frag_stream_info = get_frag_stream_info(frag_index, index, sc->id);
1679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!frag_stream_info)
1680 return AV_NOPTS_VALUE;
1681
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1682 219 return frag_stream_info->sidx_pts;
1683 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1684 return frag_stream_info->first_tfra_pts;
1685 return frag_stream_info->sidx_pts;
1686 }
1687
1688 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
1689 AVStream *frag_stream = NULL;
1690 frag_stream_info = &frag_index->item[index].stream_info[i];
1691 for (j = 0; j < s->nb_streams; j++) {
1692 MOVStreamContext *sc2 = s->streams[j]->priv_data;
1693 if (sc2->id == frag_stream_info->id)
1694 frag_stream = s->streams[j];
1695 }
1696 if (!frag_stream) {
1697 av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1698 continue;
1699 }
1700 timestamp = get_stream_info_time(frag_stream_info);
1701 if (timestamp != AV_NOPTS_VALUE)
1702 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1703 }
1704 return AV_NOPTS_VALUE;
1705 }
1706
1707 26 static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1708 AVStream *st, int64_t timestamp)
1709 {
1710 int a, b, m, m0;
1711 int64_t frag_time;
1712
1713 26 a = -1;
1714 26 b = frag_index->nb_items;
1715
1716
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 26 times.
245 while (b - a > 1) {
1717 219 m0 = m = (a + b) >> 1;
1718
1719
2/4
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 219 times.
438 while (m < b &&
1720 219 (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
1721 m++;
1722
1723
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)
1724 93 a = m;
1725 else
1726 126 b = m0;
1727 }
1728
1729 26 return a;
1730 }
1731
1732 756 static int update_frag_index(MOVContext *c, int64_t offset)
1733 {
1734 int index, i;
1735 MOVFragmentIndexItem * item;
1736 MOVFragmentStreamInfo * frag_stream_info;
1737
1738 // If moof_offset already exists in frag_index, return index to it
1739 756 index = search_frag_moof_offset(&c->frag_index, offset);
1740
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 389 times.
756 if (index < c->frag_index.nb_items &&
1741
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 c->frag_index.item[index].moof_offset == offset)
1742 367 return index;
1743
1744 // offset is not yet in frag index.
1745 // Insert new item at index (sorted by moof offset)
1746 389 item = av_fast_realloc(c->frag_index.item,
1747 389 &c->frag_index.allocated_size,
1748 389 (c->frag_index.nb_items + 1) *
1749 sizeof(*c->frag_index.item));
1750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (!item)
1751 return -1;
1752 389 c->frag_index.item = item;
1753
1754 389 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1755 sizeof(*item->stream_info));
1756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (!frag_stream_info)
1757 return -1;
1758
1759
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 389 times.
796 for (i = 0; i < c->fc->nb_streams; i++) {
1760 // Avoid building frag index if streams lack track id.
1761 407 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 407 times.
407 if (sc->id < 0) {
1763 av_free(frag_stream_info);
1764 return AVERROR_INVALIDDATA;
1765 }
1766
1767 407 frag_stream_info[i].id = sc->id;
1768 407 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1769 407 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1770 407 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1771 407 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1772 407 frag_stream_info[i].index_base = -1;
1773 407 frag_stream_info[i].index_entry = -1;
1774 407 frag_stream_info[i].encryption_index = NULL;
1775 407 frag_stream_info[i].stsd_id = -1;
1776 }
1777
1778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (index < c->frag_index.nb_items)
1779 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1780 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1781
1782 389 item = &c->frag_index.item[index];
1783 389 item->headers_read = 0;
1784 389 item->current = 0;
1785 389 item->nb_stream_info = c->fc->nb_streams;
1786 389 item->moof_offset = offset;
1787 389 item->stream_info = frag_stream_info;
1788 389 c->frag_index.nb_items++;
1789
1790 389 return index;
1791 }
1792
1793 388 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1794 int id, int entries)
1795 {
1796 int i;
1797 MOVFragmentStreamInfo * frag_stream_info;
1798
1799
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (index < 0)
1800 388 return;
1801 for (i = index; i < frag_index->nb_items; i++) {
1802 frag_stream_info = get_frag_stream_info(frag_index, i, id);
1803 if (frag_stream_info && frag_stream_info->index_entry >= 0)
1804 frag_stream_info->index_entry += entries;
1805 }
1806 }
1807
1808 388 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1809 {
1810 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1811 388 c->fragment.found_tfhd = 0;
1812
1813
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) {
1814 c->has_looked_for_mfra = 1;
1815 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1816 int ret;
1817 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1818 "for a mfra\n");
1819 if ((ret = mov_read_mfra(c, pb)) < 0) {
1820 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1821 "read the mfra (may be a live ismv)\n");
1822 }
1823 } else {
1824 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1825 "seekable, can not look for mfra\n");
1826 }
1827 }
1828 388 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1829 388 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1830 388 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1831 388 return mov_read_default(c, pb, atom);
1832 }
1833
1834 1075 static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version)
1835 {
1836 int64_t time;
1837
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1064 times.
1075 if (version == 1) {
1838 11 time = avio_rb64(pb);
1839 11 avio_rb64(pb);
1840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (time < 0) {
1841 av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n");
1842 return;
1843 }
1844 } else {
1845 1064 time = avio_rb32(pb);
1846 1064 avio_rb32(pb); /* modification time */
1847
4/4
✓ Branch 0 taken 519 times.
✓ Branch 1 taken 545 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 471 times.
1064 if (time > 0 && time < 2082844800) {
1848 48 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1849 48 time += 2082844800;
1850 }
1851 }
1852
2/2
✓ Branch 0 taken 525 times.
✓ Branch 1 taken 550 times.
1075 if (time) {
1853 525 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1854
1855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 525 times.
525 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1856 av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n");
1857 return;
1858 }
1859
1860 525 ff_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1861 }
1862 }
1863
1864 594 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1865 {
1866 AVStream *st;
1867 MOVStreamContext *sc;
1868 int version;
1869 594 char language[4] = {0};
1870 unsigned lang;
1871
1872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
1873 return 0;
1874 594 st = c->fc->streams[c->fc->nb_streams-1];
1875 594 sc = st->priv_data;
1876
1877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (sc->time_scale) {
1878 av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
1879 return AVERROR_INVALIDDATA;
1880 }
1881
1882 594 version = avio_r8(pb);
1883
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (version > 1) {
1884 avpriv_request_sample(c->fc, "Version %d", version);
1885 return AVERROR_PATCHWELCOME;
1886 }
1887 594 avio_rb24(pb); /* flags */
1888 594 mov_metadata_creation_time(c, pb, &st->metadata, version);
1889
1890 594 sc->time_scale = avio_rb32(pb);
1891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (sc->time_scale <= 0) {
1892 av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
1893 sc->time_scale = 1;
1894 }
1895
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 585 times.
594 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1896
1897
6/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 585 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 585 times.
✓ Branch 5 taken 4 times.
594 if ((version == 1 && st->duration == UINT64_MAX) ||
1898
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 585 times.
585 (version != 1 && st->duration == UINT32_MAX)) {
1899 5 st->duration = 0;
1900 }
1901
1902 594 lang = avio_rb16(pb); /* language */
1903
2/2
✓ Branch 1 taken 422 times.
✓ Branch 2 taken 172 times.
594 if (ff_mov_lang_to_iso639(lang, language))
1904 422 av_dict_set(&st->metadata, "language", language, 0);
1905 594 avio_rb16(pb); /* quality */
1906
1907 594 return 0;
1908 }
1909
1910 481 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1911 {
1912 int i;
1913 481 int version = avio_r8(pb); /* version */
1914 481 avio_rb24(pb); /* flags */
1915
1916 481 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
1917 481 c->time_scale = avio_rb32(pb); /* time scale */
1918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 481 times.
481 if (c->time_scale <= 0) {
1919 av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
1920 c->time_scale = 1;
1921 }
1922 481 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
1923
1924
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 479 times.
481 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1925 481 avio_rb32(pb); /* preferred scale */
1926
1927 481 avio_rb16(pb); /* preferred volume */
1928
1929 481 avio_skip(pb, 10); /* reserved */
1930
1931 /* movie display matrix, store it in main context and use it later on */
1932
2/2
✓ Branch 0 taken 1443 times.
✓ Branch 1 taken 481 times.
1924 for (i = 0; i < 3; i++) {
1933 1443 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
1934 1443 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
1935 1443 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
1936 }
1937
1938 481 avio_rb32(pb); /* preview time */
1939 481 avio_rb32(pb); /* preview duration */
1940 481 avio_rb32(pb); /* poster time */
1941 481 avio_rb32(pb); /* selection time */
1942 481 avio_rb32(pb); /* selection duration */
1943 481 avio_rb32(pb); /* current time */
1944 481 avio_rb32(pb); /* next track ID */
1945
1946 481 return 0;
1947 }
1948
1949 7 static void set_last_stream_little_endian(AVFormatContext *fc)
1950 {
1951 AVStream *st;
1952
1953
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (fc->nb_streams < 1)
1954 return;
1955 7 st = fc->streams[fc->nb_streams-1];
1956
1957
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) {
1958 5 case AV_CODEC_ID_PCM_S16BE:
1959 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
1960 5 break;
1961 1 case AV_CODEC_ID_PCM_S24BE:
1962 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
1963 1 break;
1964 case AV_CODEC_ID_PCM_S32BE:
1965 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
1966 break;
1967 1 case AV_CODEC_ID_PCM_F32BE:
1968 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
1969 1 break;
1970 case AV_CODEC_ID_PCM_F64BE:
1971 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
1972 break;
1973 default:
1974 break;
1975 }
1976 }
1977
1978 5 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1979 {
1980 5 int little_endian = avio_rb16(pb) & 0xFF;
1981 5 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
1982
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (little_endian == 1)
1983 1 set_last_stream_little_endian(c->fc);
1984 5 return 0;
1985 }
1986
1987 6 static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1988 {
1989 int format_flags;
1990 int version, flags;
1991 int pcm_sample_size;
1992 6 AVFormatContext *fc = c->fc;
1993 AVStream *st;
1994 MOVStreamContext *sc;
1995
1996
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 6) {
1997 av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n");
1998 return AVERROR_INVALIDDATA;
1999 }
2000
2001 6 version = avio_r8(pb);
2002 6 flags = avio_rb24(pb);
2003
2004
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) {
2005 av_log(c->fc, AV_LOG_ERROR,
2006 "Unsupported 'pcmC' box with version %d, flags: %x",
2007 version, flags);
2008 return AVERROR_INVALIDDATA;
2009 }
2010
2011 6 format_flags = avio_r8(pb);
2012 6 pcm_sample_size = avio_r8(pb);
2013
2014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fc->nb_streams < 1)
2015 return AVERROR_INVALIDDATA;
2016
2017 6 st = fc->streams[fc->nb_streams - 1];
2018 6 sc = st->priv_data;
2019
2020
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (sc->format == MOV_MP4_FPCM_TAG) {
2021
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (pcm_sample_size) {
2022 1 case 32:
2023 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE;
2024 1 break;
2025 case 64:
2026 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE;
2027 break;
2028 default:
2029 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2030 pcm_sample_size,
2031 av_fourcc2str(sc->format));
2032 return AVERROR_INVALIDDATA;
2033 }
2034
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (sc->format == MOV_MP4_IPCM_TAG) {
2035
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 switch (pcm_sample_size) {
2036 5 case 16:
2037 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2038 5 break;
2039 case 24:
2040 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
2041 break;
2042 case 32:
2043 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
2044 break;
2045 default:
2046 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2047 pcm_sample_size,
2048 av_fourcc2str(sc->format));
2049 return AVERROR_INVALIDDATA;
2050 }
2051 } else {
2052 av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n",
2053 av_fourcc2str(sc->format));
2054 return AVERROR_INVALIDDATA;
2055 }
2056
2057
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
2058 6 set_last_stream_little_endian(c->fc);
2059 6 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2060
2061 6 return 0;
2062 }
2063
2064 43 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2065 {
2066 AVStream *st;
2067 43 HEIFItem *item = NULL;
2068 43 char color_parameter_type[5] = { 0 };
2069 uint16_t color_primaries, color_trc, color_matrix;
2070 int ret;
2071
2072 43 st = get_curr_st(c);
2073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st) {
2074 item = heif_cur_item(c);
2075 if (!item)
2076 return 0;
2077 }
2078
2079 43 ret = ffio_read_size(pb, color_parameter_type, 4);
2080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
2081 return ret;
2082
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 10 times.
43 if (strncmp(color_parameter_type, "nclx", 4) &&
2083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 strncmp(color_parameter_type, "nclc", 4) &&
2084 strncmp(color_parameter_type, "prof", 4)) {
2085 av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
2086 color_parameter_type);
2087 return 0;
2088 }
2089
2090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!strncmp(color_parameter_type, "prof", 4)) {
2091 AVPacketSideData *sd;
2092 uint8_t *icc_profile;
2093 if (st) {
2094 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
2095 &st->codecpar->nb_coded_side_data,
2096 AV_PKT_DATA_ICC_PROFILE,
2097 atom.size - 4, 0);
2098 if (!sd)
2099 return AVERROR(ENOMEM);
2100 icc_profile = sd->data;
2101 } else {
2102 av_freep(&item->icc_profile);
2103 icc_profile = item->icc_profile = av_malloc(atom.size - 4);
2104 if (!icc_profile) {
2105 item->icc_profile_size = 0;
2106 return AVERROR(ENOMEM);
2107 }
2108 item->icc_profile_size = atom.size - 4;
2109 }
2110 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
2111 if (ret < 0)
2112 return ret;
2113
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 } else if (st) {
2114 43 color_primaries = avio_rb16(pb);
2115 43 color_trc = avio_rb16(pb);
2116 43 color_matrix = avio_rb16(pb);
2117
2118 43 av_log(c->fc, AV_LOG_TRACE,
2119 "%s: pri %d trc %d matrix %d",
2120 color_parameter_type, color_primaries, color_trc, color_matrix);
2121
2122
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 33 times.
43 if (!strncmp(color_parameter_type, "nclx", 4)) {
2123 10 uint8_t color_range = avio_r8(pb) >> 7;
2124 10 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (color_range)
2126 st->codecpar->color_range = AVCOL_RANGE_JPEG;
2127 else
2128 10 st->codecpar->color_range = AVCOL_RANGE_MPEG;
2129 }
2130
2131
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_primaries_name(color_primaries))
2132 color_primaries = AVCOL_PRI_UNSPECIFIED;
2133
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_transfer_name(color_trc))
2134 color_trc = AVCOL_TRC_UNSPECIFIED;
2135
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_space_name(color_matrix))
2136 color_matrix = AVCOL_SPC_UNSPECIFIED;
2137
2138 43 st->codecpar->color_primaries = color_primaries;
2139 43 st->codecpar->color_trc = color_trc;
2140 43 st->codecpar->color_space = color_matrix;
2141 43 av_log(c->fc, AV_LOG_TRACE, "\n");
2142 }
2143 43 return 0;
2144 }
2145
2146 112 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2147 {
2148 AVStream *st;
2149 unsigned mov_field_order;
2150 112 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2151
2152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (c->fc->nb_streams < 1) // will happen with jp2 files
2153 return 0;
2154 112 st = c->fc->streams[c->fc->nb_streams-1];
2155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (atom.size < 2)
2156 return AVERROR_INVALIDDATA;
2157 112 mov_field_order = avio_rb16(pb);
2158
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 20 times.
112 if ((mov_field_order & 0xFF00) == 0x0100)
2159 92 decoded_field_order = AV_FIELD_PROGRESSIVE;
2160
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 else if ((mov_field_order & 0xFF00) == 0x0200) {
2161
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) {
2162 1 case 0x01: decoded_field_order = AV_FIELD_TT;
2163 1 break;
2164 case 0x06: decoded_field_order = AV_FIELD_BB;
2165 break;
2166 1 case 0x09: decoded_field_order = AV_FIELD_TB;
2167 1 break;
2168 18 case 0x0E: decoded_field_order = AV_FIELD_BT;
2169 18 break;
2170 }
2171 }
2172
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) {
2173 av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
2174 }
2175 112 st->codecpar->field_order = decoded_field_order;
2176
2177 112 return 0;
2178 }
2179
2180 68 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
2181 {
2182 68 int err = 0;
2183 68 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
2184
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)
2185 return AVERROR_INVALIDDATA;
2186
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
68 if ((err = av_reallocp(&par->extradata, size)) < 0) {
2187 par->extradata_size = 0;
2188 return err;
2189 }
2190 68 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
2191 68 return 0;
2192 }
2193
2194 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
2195 65 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2196 AVCodecParameters *par, uint8_t *buf)
2197 {
2198 65 int64_t result = atom.size;
2199 int err;
2200
2201 65 AV_WB32(buf , atom.size + 8);
2202 65 AV_WL32(buf + 4, atom.type);
2203 65 err = ffio_read_size(pb, buf + 8, atom.size);
2204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (err < 0) {
2205 par->extradata_size -= atom.size;
2206 return err;
2207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 } else if (err < atom.size) {
2208 av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
2209 par->extradata_size -= atom.size - err;
2210 result = err;
2211 }
2212 65 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2213 65 return result;
2214 }
2215
2216 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
2217 58 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2218 enum AVCodecID codec_id)
2219 {
2220 AVStream *st;
2221 uint64_t original_size;
2222 int err;
2223
2224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (c->fc->nb_streams < 1) // will happen with jp2 files
2225 return 0;
2226 58 st = c->fc->streams[c->fc->nb_streams-1];
2227
2228
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
58 if (st->codecpar->codec_id != codec_id)
2229 19 return 0; /* unexpected codec_id - don't mess with extradata */
2230
2231 39 original_size = st->codecpar->extradata_size;
2232 39 err = mov_realloc_extradata(st->codecpar, atom);
2233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err)
2234 return err;
2235
2236 39 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
2237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err < 0)
2238 return err;
2239 39 return 0; // Note: this is the original behavior to ignore truncation.
2240 }
2241
2242 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
2243 16 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2244 {
2245 16 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
2246 }
2247
2248 static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2249 {
2250 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS);
2251 }
2252
2253 static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2254 {
2255 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
2256 }
2257
2258 static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2259 {
2260 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
2261 }
2262
2263 19 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2264 {
2265 19 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
2266
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!ret)
2267 19 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
2268 19 return ret;
2269 }
2270
2271 static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2272 {
2273 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
2274
2275 if (!ret && c->fc->nb_streams >= 1) {
2276 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2277 if (par->extradata_size >= 40) {
2278 par->height = AV_RB16(&par->extradata[36]);
2279 par->width = AV_RB16(&par->extradata[38]);
2280 }
2281 }
2282 return ret;
2283 }
2284
2285 16 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2286 {
2287
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (c->fc->nb_streams >= 1) {
2288 16 AVStream *const st = c->fc->streams[c->fc->nb_streams - 1];
2289 16 FFStream *const sti = ffstream(st);
2290 16 AVCodecParameters *par = st->codecpar;
2291
2292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
2293 par->codec_id == AV_CODEC_ID_H264 &&
2294 atom.size > 11) {
2295 int cid;
2296 avio_skip(pb, 10);
2297 cid = avio_rb16(pb);
2298 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
2299 if (cid == 0xd4d || cid == 0xd4e)
2300 par->width = 1440;
2301 return 0;
2302
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
2303
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
2304
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
2305
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 atom.size >= 24) {
2306 int num, den;
2307 13 avio_skip(pb, 12);
2308 13 num = avio_rb32(pb);
2309 13 den = avio_rb32(pb);
2310
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)
2311 return 0;
2312
2/3
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
13 switch (avio_rb32(pb)) {
2313 12 case 2:
2314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (den >= INT_MAX / 2)
2315 return 0;
2316 12 den *= 2;
2317 13 case 1:
2318 13 sti->display_aspect_ratio = (AVRational){ num, den };
2319 13 default:
2320 13 return 0;
2321 }
2322 }
2323 }
2324
2325 3 return mov_read_avid(c, pb, atom);
2326 }
2327
2328 26 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2329 {
2330 26 int ret = 0;
2331 26 int length = 0;
2332 uint64_t original_size;
2333
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (c->fc->nb_streams >= 1) {
2334 26 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (par->codec_id == AV_CODEC_ID_H264)
2336 return 0;
2337
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (atom.size == 16) {
2338 26 original_size = par->extradata_size;
2339 26 ret = mov_realloc_extradata(par, atom);
2340
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!ret) {
2341 26 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
2342
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (length == atom.size) {
2343 26 const uint8_t range_value = par->extradata[original_size + 19];
2344
1/3
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
26 switch (range_value) {
2345 26 case 1:
2346 26 par->color_range = AVCOL_RANGE_MPEG;
2347 26 break;
2348 case 2:
2349 par->color_range = AVCOL_RANGE_JPEG;
2350 break;
2351 default:
2352 av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
2353 break;
2354 }
2355 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
2356 } else {
2357 /* For some reason the whole atom was not added to the extradata */
2358 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
2359 }
2360 } else {
2361 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
2362 }
2363 } else {
2364 av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
2365 }
2366 }
2367
2368 26 return ret;
2369 }
2370
2371 4 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2372 {
2373 4 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
2374 }
2375
2376 34 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2377 {
2378 AVStream *st;
2379 int ret;
2380
2381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (c->fc->nb_streams < 1)
2382 return 0;
2383 34 st = c->fc->streams[c->fc->nb_streams-1];
2384
2385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if ((uint64_t)atom.size > (1<<30))
2386 return AVERROR_INVALIDDATA;
2387
2388
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2 times.
34 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2389
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
2391 // pass all frma atom to codec, needed at least for QDMC and QDM2
2392 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2394 return ret;
2395
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 } else if (atom.size > 8) { /* to read frma, esds atoms */
2396
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) {
2397 uint64_t buffer;
2398 10 ret = ffio_ensure_seekback(pb, 8);
2399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2400 return ret;
2401 10 buffer = avio_rb64(pb);
2402 10 atom.size -= 8;
2403
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
2404
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 <= atom.size
2405
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 >= 8) {
2406 10 avio_skip(pb, -8);
2407 10 atom.size += 8;
2408 } else if (!st->codecpar->extradata_size) {
2409 #define ALAC_EXTRADATA_SIZE 36
2410 st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
2411 if (!st->codecpar->extradata)
2412 return AVERROR(ENOMEM);
2413 st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
2414 AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
2415 AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
2416 AV_WB64(st->codecpar->extradata + 12, buffer);
2417 avio_read(pb, st->codecpar->extradata + 20, 16);
2418 avio_skip(pb, atom.size - 24);
2419 return 0;
2420 }
2421 }
2422
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if ((ret = mov_read_default(c, pb, atom)) < 0)
2423 return ret;
2424 } else
2425 avio_skip(pb, atom.size);
2426 34 return 0;
2427 }
2428
2429 /**
2430 * This function reads atom content and puts data in extradata without tag
2431 * nor size unlike mov_read_extradata.
2432 */
2433 139 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2434 {
2435 AVStream *st;
2436 int ret;
2437
2438 139 st = get_curr_st(c);
2439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if (!st)
2440 return 0;
2441
2442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if ((uint64_t)atom.size > (1<<30))
2443 return AVERROR_INVALIDDATA;
2444
2445
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 138 times.
139 if (atom.type == MKTAG('v','v','c','C')) {
2446 1 avio_skip(pb, 4);
2447 1 atom.size -= 4;
2448 }
2449
2450
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 4 times.
139 if (atom.size >= 10) {
2451 // Broken files created by legacy versions of libavformat will
2452 // wrap a whole fiel atom inside of a glbl atom.
2453 135 unsigned size = avio_rb32(pb);
2454 135 unsigned type = avio_rl32(pb);
2455
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 135 times.
135 if (avio_feof(pb))
2456 return AVERROR_INVALIDDATA;
2457 135 avio_seek(pb, -8, SEEK_CUR);
2458
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 127 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
135 if (type == MKTAG('f','i','e','l') && size == atom.size)
2459 8 return mov_read_default(c, pb, atom);
2460 }
2461
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 131 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
131 if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
2462 av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
2463 return 0;
2464 }
2465 131 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2466
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 131 times.
131 if (ret < 0)
2467 return ret;
2468
3/4
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 39 times.
131 if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
2469 /* HEVC-based Dolby Vision derived from hvc1.
2470 Happens to match with an identifier
2471 previously utilized for DV. Thus, if we have
2472 the hvcC extradata box available as specified,
2473 set codec to HEVC */
2474 st->codecpar->codec_id = AV_CODEC_ID_HEVC;
2475
2476 131 return 0;
2477 }
2478
2479 2 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2480 {
2481 AVStream *st;
2482 uint8_t profile_level;
2483 int ret;
2484
2485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
2486 return 0;
2487 2 st = c->fc->streams[c->fc->nb_streams-1];
2488
2489
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)
2490 return AVERROR_INVALIDDATA;
2491
2492 2 profile_level = avio_r8(pb);
2493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((profile_level & 0xf0) != 0xc0)
2494 return 0;
2495
2496 2 avio_seek(pb, 6, SEEK_CUR);
2497 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
2498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2499 return ret;
2500
2501 2 return 0;
2502 }
2503
2504 static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2505 {
2506 AVStream* st;
2507 MOVStreamContext* sc;
2508
2509 if (c->fc->nb_streams < 1)
2510 return 0;
2511
2512 /* For SBAS this should be fine - though beware if someone implements a
2513 * tref atom processor that doesn't drop down to default then this may
2514 * be lost. */
2515 if (atom.size > 4) {
2516 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2517 return AVERROR_PATCHWELCOME;
2518 }
2519
2520 st = c->fc->streams[c->fc->nb_streams - 1];
2521 sc = st->priv_data;
2522 sc->tref_id = avio_rb32(pb);
2523 sc->tref_flags |= MOV_TREF_FLAG_ENHANCEMENT;
2524
2525 return 0;
2526 }
2527
2528 /**
2529 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2530 * but can have extradata appended at the end after the 40 bytes belonging
2531 * to the struct.
2532 */
2533 static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2534 {
2535 AVStream *st;
2536 int ret;
2537
2538 if (c->fc->nb_streams < 1)
2539 return 0;
2540 if (atom.size <= 40)
2541 return 0;
2542 st = c->fc->streams[c->fc->nb_streams-1];
2543
2544 if ((uint64_t)atom.size > (1<<30))
2545 return AVERROR_INVALIDDATA;
2546
2547 avio_skip(pb, 40);
2548 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
2549 if (ret < 0)
2550 return ret;
2551
2552 return 0;
2553 }
2554
2555 594 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2556 {
2557 AVStream *st;
2558 MOVStreamContext *sc;
2559 unsigned int i, entries;
2560
2561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->trak_index < 0) {
2562 av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
2563 return 0;
2564 }
2565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
2566 return 0;
2567 594 st = c->fc->streams[c->fc->nb_streams-1];
2568 594 sc = st->priv_data;
2569
2570 594 avio_r8(pb); /* version */
2571 594 avio_rb24(pb); /* flags */
2572
2573 // Clamp allocation size for `chunk_offsets` -- don't throw an error for an
2574 // invalid count since the EOF path doesn't throw either.
2575 594 entries = avio_rb32(pb);
2576 594 entries =
2577
2/2
✓ Branch 0 taken 589 times.
✓ Branch 1 taken 5 times.
594 FFMIN(entries,
2578 FFMAX(0, (atom.size - 8) /
2579 (atom.type == MKTAG('s', 't', 'c', 'o') ? 4 : 8)));
2580
2581
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 578 times.
594 if (!entries)
2582 16 return 0;
2583
2584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (sc->chunk_offsets) {
2585 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2586 return 0;
2587 }
2588
2589 578 av_free(sc->chunk_offsets);
2590 578 sc->chunk_count = 0;
2591 578 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (!sc->chunk_offsets)
2593 return AVERROR(ENOMEM);
2594 578 sc->chunk_count = entries;
2595
2596
2/2
✓ Branch 0 taken 574 times.
✓ Branch 1 taken 4 times.
578 if (atom.type == MKTAG('s','t','c','o'))
2597
3/4
✓ Branch 0 taken 42907 times.
✓ Branch 1 taken 574 times.
✓ Branch 2 taken 42907 times.
✗ Branch 3 not taken.
43481 for (i = 0; i < entries && !pb->eof_reached; i++)
2598 42907 sc->chunk_offsets[i] = avio_rb32(pb);
2599
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (atom.type == MKTAG('c','o','6','4'))
2600
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++) {
2601 136336 sc->chunk_offsets[i] = avio_rb64(pb);
2602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136336 times.
136336 if (sc->chunk_offsets[i] < 0) {
2603 av_log(c->fc, AV_LOG_WARNING, "Impossible chunk_offset\n");
2604 sc->chunk_offsets[i] = 0;
2605 }
2606 }
2607 else
2608 return AVERROR_INVALIDDATA;
2609
2610 578 sc->chunk_count = i;
2611
2612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (pb->eof_reached) {
2613 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2614 return AVERROR_EOF;
2615 }
2616
2617 578 return 0;
2618 }
2619
2620 631 static int mov_codec_id(AVStream *st, uint32_t format)
2621 {
2622 631 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2623
2624
2/2
✓ Branch 0 taken 411 times.
✓ Branch 1 taken 220 times.
631 if (id <= 0 &&
2625
2/2
✓ Branch 0 taken 408 times.
✓ Branch 1 taken 3 times.
411 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 408 times.
408 (format & 0xFFFF) == 'T' + ('S' << 8)))
2627 3 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2628
2629
4/4
✓ Branch 0 taken 293 times.
✓ Branch 1 taken 338 times.
✓ Branch 2 taken 223 times.
✓ Branch 3 taken 70 times.
631 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2630 223 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2631
3/4
✓ Branch 0 taken 390 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 390 times.
✗ Branch 3 not taken.
408 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2632 /* skip old ASF MPEG-4 tag */
2633
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 4 times.
390 format && format != MKTAG('m','p','4','s')) {
2634 386 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2635
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 331 times.
386 if (id <= 0)
2636 55 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2637
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 51 times.
386 if (id > 0)
2638 335 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2639
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 47 times.
51 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2640
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2642 47 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2643
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6 times.
47 if (id <= 0) {
2644
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 2 times.
80 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2645
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 2 times.
80 AV_CODEC_ID_TTML : id;
2646 }
2647
2648
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 37 times.
47 if (id > 0)
2649 10 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2650 else
2651 37 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2652 }
2653 }
2654
2655 631 st->codecpar->codec_tag = format;
2656
2657 631 return id;
2658 }
2659
2660 312 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2661 AVStream *st, MOVStreamContext *sc)
2662 {
2663 312 uint8_t codec_name[32] = { 0 };
2664 int64_t stsd_start;
2665 unsigned int len;
2666 312 uint32_t id = 0;
2667
2668 /* The first 16 bytes of the video sample description are already
2669 * read in ff_mov_read_stsd_entries() */
2670 312 stsd_start = avio_tell(pb) - 16;
2671
2672 312 avio_rb16(pb); /* version */
2673 312 avio_rb16(pb); /* revision level */
2674 312 id = avio_rl32(pb); /* vendor */
2675 312 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2676 312 avio_rb32(pb); /* temporal quality */
2677 312 avio_rb32(pb); /* spatial quality */
2678
2679 312 st->codecpar->width = avio_rb16(pb); /* width */
2680 312 st->codecpar->height = avio_rb16(pb); /* height */
2681
2682 312 avio_rb32(pb); /* horiz resolution */
2683 312 avio_rb32(pb); /* vert resolution */
2684 312 avio_rb32(pb); /* data size, always 0 */
2685 312 avio_rb16(pb); /* frames per samples */
2686
2687 312 len = avio_r8(pb); /* codec name, pascal string */
2688
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 311 times.
312 if (len > 31)
2689 1 len = 31;
2690 312 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2691
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 3 times.
312 if (len < 31)
2692 309 avio_skip(pb, 31 - len);
2693
2694
2/2
✓ Branch 0 taken 250 times.
✓ Branch 1 taken 62 times.
312 if (codec_name[0])
2695 250 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2696
2697 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 312 times.
312 if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2699 st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2700 st->codecpar->width &= ~1;
2701 st->codecpar->height &= ~1;
2702 }
2703 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 312 times.
312 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2705 !strncmp(codec_name, "Sorenson H263", 13))
2706 st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2707
2708 312 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2709
2710 312 avio_seek(pb, stsd_start, SEEK_SET);
2711
2712
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 294 times.
312 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2713 18 st->codecpar->bits_per_coded_sample &= 0x1F;
2714 18 sc->has_palette = 1;
2715 }
2716 312 }
2717
2718 241 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2719 AVStream *st, MOVStreamContext *sc)
2720 {
2721 int bits_per_sample, flags;
2722 241 uint16_t version = avio_rb16(pb);
2723 241 uint32_t id = 0;
2724 241 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2725 int channel_count;
2726
2727 241 avio_rb16(pb); /* revision level */
2728 241 id = avio_rl32(pb); /* vendor */
2729 241 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2730
2731 241 channel_count = avio_rb16(pb);
2732
2733 241 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2734 241 st->codecpar->ch_layout.nb_channels = channel_count;
2735 241 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
2736 241 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
2737
2738 241 sc->audio_cid = avio_rb16(pb);
2739 241 avio_rb16(pb); /* packet size = 0 */
2740
2741 241 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
2742
2743 // Read QT version 1 fields. In version 0 these do not exist.
2744 241 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
2745
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 ||
2746
1/2
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
155 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
2747
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)) {
2748
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 40 times.
90 if (version == 1) {
2749 50 sc->samples_per_frame = avio_rb32(pb);
2750 50 avio_rb32(pb); /* bytes per packet */
2751 50 sc->bytes_per_frame = avio_rb32(pb);
2752 50 avio_rb32(pb); /* bytes per sample */
2753
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
40 } else if (version == 2) {
2754 4 avio_rb32(pb); /* sizeof struct only */
2755 4 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
2756 4 channel_count = avio_rb32(pb);
2757 4 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2758 4 st->codecpar->ch_layout.nb_channels = channel_count;
2759 4 avio_rb32(pb); /* always 0x7F000000 */
2760 4 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
2761
2762 4 flags = avio_rb32(pb); /* lpcm format specific flag */
2763 4 sc->bytes_per_frame = avio_rb32(pb);
2764 4 sc->samples_per_frame = avio_rb32(pb);
2765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
2766 st->codecpar->codec_id =
2767 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
2768 flags);
2769 }
2770
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)) {
2771 /* can't correctly handle variable sized packet as audio unit */
2772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 switch (st->codecpar->codec_id) {
2773 case AV_CODEC_ID_MP2:
2774 case AV_CODEC_ID_MP3:
2775 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
2776 break;
2777 }
2778 }
2779 }
2780
2781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (sc->format == 0) {
2782 if (st->codecpar->bits_per_coded_sample == 8)
2783 st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
2784 else if (st->codecpar->bits_per_coded_sample == 16)
2785 st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
2786 }
2787
2788
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) {
2789 7 case AV_CODEC_ID_PCM_S8:
2790 case AV_CODEC_ID_PCM_U8:
2791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
2792 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2793 7 break;
2794 19 case AV_CODEC_ID_PCM_S16LE:
2795 case AV_CODEC_ID_PCM_S16BE:
2796
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
19 if (st->codecpar->bits_per_coded_sample == 8)
2797 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
2798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 24)
2799 st->codecpar->codec_id =
2800 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2801 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
2802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 32)
2803 st->codecpar->codec_id =
2804 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2805 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
2806 19 break;
2807 /* set values for old format before stsd version 1 appeared */
2808 2 case AV_CODEC_ID_MACE3:
2809 2 sc->samples_per_frame = 6;
2810 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
2811 2 break;
2812 8 case AV_CODEC_ID_MACE6:
2813 8 sc->samples_per_frame = 6;
2814 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
2815 8 break;
2816 5 case AV_CODEC_ID_ADPCM_IMA_QT:
2817 5 sc->samples_per_frame = 64;
2818 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
2819 5 break;
2820 1 case AV_CODEC_ID_GSM:
2821 1 sc->samples_per_frame = 160;
2822 1 sc->bytes_per_frame = 33;
2823 1 break;
2824 199 default:
2825 199 break;
2826 }
2827
2828 241 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2829
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) {
2830 48 st->codecpar->bits_per_coded_sample = bits_per_sample;
2831 48 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
2832 }
2833 241 }
2834
2835 11 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
2836 AVStream *st, MOVStreamContext *sc,
2837 int64_t size)
2838 {
2839 // ttxt stsd contains display flags, justification, background
2840 // color, fonts, and default styles, so fake an atom to read it
2841 11 MOVAtom fake_atom = { .size = size };
2842 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
2843 // in extradata unlike stpp MP4 TTML.
2844
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
2845
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
2846 9 mov_read_glbl(c, pb, fake_atom);
2847 11 st->codecpar->width = sc->width;
2848 11 st->codecpar->height = sc->height;
2849 11 }
2850
2851 41 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
2852 AVStream *st, MOVStreamContext *sc,
2853 int64_t size)
2854 {
2855 int ret;
2856
2857
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 22 times.
41 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
2858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if ((int)size != size)
2859 return AVERROR(ENOMEM);
2860
2861 19 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
2862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
2863 return ret;
2864
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (size > 16) {
2865 19 MOVStreamContext *tmcd_ctx = st->priv_data;
2866 int val;
2867 19 val = AV_RB32(st->codecpar->extradata + 4);
2868 19 tmcd_ctx->tmcd_flags = val;
2869 19 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
2870 19 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
2871 19 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
2872
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (size > 30) {
2873 4 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
2874 4 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
2875
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) {
2876 4 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
2877
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 &&
2878
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 st->codecpar->extradata[30] /* Don't add empty string */) {
2879 4 char *reel_name = av_malloc(str_size + 1);
2880
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!reel_name)
2881 return AVERROR(ENOMEM);
2882 4 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
2883 4 reel_name[str_size] = 0; /* Add null terminator */
2884 4 av_dict_set(&st->metadata, "reel_name", reel_name,
2885 AV_DICT_DONT_STRDUP_VAL);
2886 }
2887 }
2888 }
2889 }
2890 } else {
2891 /* other codec type, just skip (rtp, mp4s ...) */
2892 22 avio_skip(pb, size);
2893 }
2894 41 return 0;
2895 }
2896
2897 594 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
2898 AVStream *st, MOVStreamContext *sc)
2899 {
2900 594 FFStream *const sti = ffstream(st);
2901
2902
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 353 times.
594 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
2903
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)
2904 st->codecpar->sample_rate = sc->time_scale;
2905
2906 /* special codec parameters handling */
2907
7/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 15 times.
✓ Branch 6 taken 16 times.
✓ Branch 7 taken 10 times.
✓ Branch 8 taken 66 times.
✓ Branch 9 taken 475 times.
594 switch (st->codecpar->codec_id) {
2908 #if CONFIG_DV_DEMUXER
2909 case AV_CODEC_ID_DVAUDIO:
2910 if (c->dv_fctx) {
2911 avpriv_request_sample(c->fc, "multiple DV audio streams");
2912 return AVERROR(ENOSYS);
2913 }
2914
2915 c->dv_fctx = avformat_alloc_context();
2916 if (!c->dv_fctx) {
2917 av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
2918 return AVERROR(ENOMEM);
2919 }
2920 c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
2921 if (!c->dv_demux) {
2922 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
2923 return AVERROR(ENOMEM);
2924 }
2925 sc->dv_audio_container = 1;
2926 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2927 break;
2928 #endif
2929 /* no ifdef since parameters are always those */
2930 case AV_CODEC_ID_QCELP:
2931 av_channel_layout_uninit(&st->codecpar->ch_layout);
2932 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2933 // force sample rate for qcelp when not stored in mov
2934 if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
2935 st->codecpar->sample_rate = 8000;
2936 // FIXME: Why is the following needed for some files?
2937 sc->samples_per_frame = 160;
2938 if (!sc->bytes_per_frame)
2939 sc->bytes_per_frame = 35;
2940 break;
2941 case AV_CODEC_ID_AMR_NB:
2942 av_channel_layout_uninit(&st->codecpar->ch_layout);
2943 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2944 /* force sample rate for amr, stsd in 3gp does not store sample rate */
2945 st->codecpar->sample_rate = 8000;
2946 break;
2947 11 case AV_CODEC_ID_AMR_WB:
2948 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
2949 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2950 11 st->codecpar->sample_rate = 16000;
2951 11 break;
2952 1 case AV_CODEC_ID_MP2:
2953 case AV_CODEC_ID_MP3:
2954 /* force type after stsd for m1a hdlr */
2955 1 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2956 1 break;
2957 15 case AV_CODEC_ID_GSM:
2958 case AV_CODEC_ID_ADPCM_MS:
2959 case AV_CODEC_ID_ADPCM_IMA_WAV:
2960 case AV_CODEC_ID_ILBC:
2961 case AV_CODEC_ID_MACE3:
2962 case AV_CODEC_ID_MACE6:
2963 case AV_CODEC_ID_QDM2:
2964 15 st->codecpar->block_align = sc->bytes_per_frame;
2965 15 break;
2966 16 case AV_CODEC_ID_ALAC:
2967
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
2968 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
2969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
2970 av_channel_layout_uninit(&st->codecpar->ch_layout);
2971 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2972 st->codecpar->ch_layout.nb_channels = channel_count;
2973 }
2974 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
2975 }
2976 16 break;
2977 10 case AV_CODEC_ID_AC3:
2978 case AV_CODEC_ID_EAC3:
2979 case AV_CODEC_ID_MPEG1VIDEO:
2980 case AV_CODEC_ID_VC1:
2981 case AV_CODEC_ID_VP8:
2982 case AV_CODEC_ID_VP9:
2983 10 sti->need_parsing = AVSTREAM_PARSE_FULL;
2984 10 break;
2985 66 case AV_CODEC_ID_EVC:
2986 case AV_CODEC_ID_AV1:
2987 /* field_order detection of H264 requires parsing */
2988 case AV_CODEC_ID_H264:
2989 66 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
2990 66 break;
2991 475 default:
2992 475 break;
2993 }
2994 594 return 0;
2995 }
2996
2997 605 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
2998 int codec_tag, int format,
2999 int64_t size)
3000 {
3001
3/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 594 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
605 if (codec_tag &&
3002 (codec_tag != format &&
3003 // AVID 1:1 samples with differing data format and codec tag exist
3004 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
3005 // prores is allowed to have differing data format and codec tag
3006 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
3007 // so is dv (sigh)
3008 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
3009 (c->fc->video_codec_id ? ff_codec_get_id(ff_codec_movvideo_tags, format) != c->fc->video_codec_id
3010 : codec_tag != MKTAG('j','p','e','g')))) {
3011 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3012 * export it as a separate AVStream but this needs a few changes
3013 * in the MOV demuxer, patch welcome. */
3014
3015 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3016 avio_skip(pb, size);
3017 return 1;
3018 }
3019
3020 605 return 0;
3021 }
3022
3023 594 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3024 {
3025 AVStream *st;
3026 MOVStreamContext *sc;
3027 int pseudo_stream_id;
3028
3029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 av_assert0 (c->fc->nb_streams >= 1);
3030 594 st = c->fc->streams[c->fc->nb_streams-1];
3031 594 sc = st->priv_data;
3032
3033 594 for (pseudo_stream_id = 0;
3034
3/4
✓ Branch 0 taken 605 times.
✓ Branch 1 taken 594 times.
✓ Branch 2 taken 605 times.
✗ Branch 3 not taken.
1199 pseudo_stream_id < entries && !pb->eof_reached;
3035 605 pseudo_stream_id++) {
3036 //Parsing Sample description table
3037 enum AVCodecID id;
3038 605 int ret, dref_id = 1;
3039 605 MOVAtom a = { AV_RL32("stsd") };
3040 605 int64_t start_pos = avio_tell(pb);
3041 605 int64_t size = avio_rb32(pb); /* size */
3042 605 uint32_t format = avio_rl32(pb); /* data format */
3043
3044
1/2
✓ Branch 0 taken 605 times.
✗ Branch 1 not taken.
605 if (size >= 16) {
3045 605 avio_rb32(pb); /* reserved */
3046 605 avio_rb16(pb); /* reserved */
3047 605 dref_id = avio_rb16(pb);
3048 } else if (size <= 7) {
3049 av_log(c->fc, AV_LOG_ERROR,
3050 "invalid size %"PRId64" in stsd\n", size);
3051 return AVERROR_INVALIDDATA;
3052 }
3053
3054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 605 times.
605 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3055 605 size - (avio_tell(pb) - start_pos))) {
3056 sc->stsd_count++;
3057 continue;
3058 }
3059
3060
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 11 times.
605 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
3061 605 sc->dref_id= dref_id;
3062 605 sc->format = format;
3063
3064 605 id = mov_codec_id(st, format);
3065
3066 605 av_log(c->fc, AV_LOG_TRACE,
3067 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3068 605 av_fourcc2str(format), st->codecpar->codec_type);
3069
3070 605 st->codecpar->codec_id = id;
3071
2/2
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 293 times.
605 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3072 312 mov_parse_stsd_video(c, pb, st, sc);
3073
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 52 times.
293 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3074 241 mov_parse_stsd_audio(c, pb, st, sc);
3075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (st->codecpar->sample_rate < 0) {
3076 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3077 return AVERROR_INVALIDDATA;
3078 }
3079
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (st->codecpar->ch_layout.nb_channels < 0) {
3080 av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3081 return AVERROR_INVALIDDATA;
3082 }
3083
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 41 times.
52 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3084 11 mov_parse_stsd_subtitle(c, pb, st, sc,
3085 11 size - (avio_tell(pb) - start_pos));
3086 } else {
3087 41 ret = mov_parse_stsd_data(c, pb, st, sc,
3088 41 size - (avio_tell(pb) - start_pos));
3089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ret < 0)
3090 return ret;
3091 }
3092 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3093 605 a.size = size - (avio_tell(pb) - start_pos);
3094
2/2
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 128 times.
605 if (a.size > 8) {
3095
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 477 times.
477 if ((ret = mov_read_default(c, pb, a)) < 0)
3096 return ret;
3097
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 127 times.
128 } else if (a.size > 0)
3098 1 avio_skip(pb, a.size);
3099
3100
3/4
✓ Branch 0 taken 605 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 341 times.
✓ Branch 3 taken 264 times.
605 if (sc->extradata && st->codecpar->extradata) {
3101 341 int extra_size = st->codecpar->extradata_size;
3102
3103 /* Move the current stream extradata to the stream context one. */
3104 341 sc->extradata_size[pseudo_stream_id] = extra_size;
3105 341 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3106 341 st->codecpar->extradata = NULL;
3107 341 st->codecpar->extradata_size = 0;
3108 }
3109 605 sc->stsd_count++;
3110 }
3111
3112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (pb->eof_reached) {
3113 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3114 return AVERROR_EOF;
3115 }
3116
3117 594 return 0;
3118 }
3119
3120 594 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3121 {
3122 AVStream *st;
3123 MOVStreamContext *sc;
3124 int ret, entries;
3125
3126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
3127 return 0;
3128 594 st = c->fc->streams[c->fc->nb_streams - 1];
3129 594 sc = st->priv_data;
3130
3131 594 sc->stsd_version = avio_r8(pb);
3132 594 avio_rb24(pb); /* flags */
3133 594 entries = avio_rb32(pb);
3134
3135 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3136
3/6
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 594 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 594 times.
594 if (entries <= 0 || entries > atom.size / 8 || entries > 1024) {
3137 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3138 return AVERROR_INVALIDDATA;
3139 }
3140
3141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (sc->extradata) {
3142 av_log(c->fc, AV_LOG_ERROR,
3143 "Duplicate stsd found in this track.\n");
3144 return AVERROR_INVALIDDATA;
3145 }
3146
3147 /* Prepare space for hosting multiple extradata. */
3148 594 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (!sc->extradata)
3150 return AVERROR(ENOMEM);
3151
3152 594 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (!sc->extradata_size) {
3154 ret = AVERROR(ENOMEM);
3155 goto fail;
3156 }
3157
3158 594 ret = ff_mov_read_stsd_entries(c, pb, entries);
3159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (ret < 0)
3160 goto fail;
3161
3162 /* Restore back the primary extradata. */
3163 594 av_freep(&st->codecpar->extradata);
3164 594 st->codecpar->extradata_size = sc->extradata_size[0];
3165
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 263 times.
594 if (sc->extradata_size[0]) {
3166 331 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 331 times.
331 if (!st->codecpar->extradata)
3168 return AVERROR(ENOMEM);
3169 331 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3170 }
3171
3172 594 return mov_finalize_stsd_codec(c, pb, st, sc);
3173 fail:
3174 if (sc->extradata) {
3175 int j;
3176 for (j = 0; j < sc->stsd_count; j++)
3177 av_freep(&sc->extradata[j]);
3178 }
3179
3180 av_freep(&sc->extradata);
3181 av_freep(&sc->extradata_size);
3182 return ret;
3183 }
3184
3185 594 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3186 {
3187 AVStream *st;
3188 MOVStreamContext *sc;
3189 unsigned int i, entries;
3190
3191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->trak_index < 0) {
3192 av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3193 return 0;
3194 }
3195
3196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
3197 return 0;
3198 594 st = c->fc->streams[c->fc->nb_streams-1];
3199 594 sc = st->priv_data;
3200
3201 594 avio_r8(pb); /* version */
3202 594 avio_rb24(pb); /* flags */
3203
3204 594 entries = avio_rb32(pb);
3205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if ((uint64_t)entries * 12 + 4 > atom.size)
3206 return AVERROR_INVALIDDATA;
3207
3208 594 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3209
3210
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 579 times.
594 if (!entries)
3211 15 return 0;
3212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 579 times.
579 if (sc->stsc_data) {
3213 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3214 return 0;
3215 }
3216 579 av_free(sc->stsc_data);
3217 579 sc->stsc_count = 0;
3218 579 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 579 times.
579 if (!sc->stsc_data)
3220 return AVERROR(ENOMEM);
3221
3222
3/4
✓ Branch 0 taken 3779 times.
✓ Branch 1 taken 579 times.
✓ Branch 2 taken 3779 times.
✗ Branch 3 not taken.
4358 for (i = 0; i < entries && !pb->eof_reached; i++) {
3223 3779 sc->stsc_data[i].first = avio_rb32(pb);
3224 3779 sc->stsc_data[i].count = avio_rb32(pb);
3225 3779 sc->stsc_data[i].id = avio_rb32(pb);
3226 }
3227
3228 579 sc->stsc_count = i;
3229
2/2
✓ Branch 0 taken 3779 times.
✓ Branch 1 taken 579 times.
4358 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3230 3779 int64_t first_min = i + 1;
3231
5/6
✓ Branch 0 taken 3200 times.
✓ Branch 1 taken 579 times.
✓ Branch 2 taken 3200 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3200 times.
✓ Branch 5 taken 579 times.
3779 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
3232
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) ||
3233
1/2
✓ Branch 0 taken 3779 times.
✗ Branch 1 not taken.
3779 sc->stsc_data[i].first < first_min ||
3234
1/2
✓ Branch 0 taken 3779 times.
✗ Branch 1 not taken.
3779 sc->stsc_data[i].count < 1 ||
3235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3779 times.
3779 sc->stsc_data[i].id < 1) {
3236 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);
3237 if (i+1 >= sc->stsc_count) {
3238 if (sc->stsc_data[i].count == 0 && i > 0) {
3239 sc->stsc_count --;
3240 continue;
3241 }
3242 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3243 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3244 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3245 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3246 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3247 continue;
3248 }
3249 av_assert0(sc->stsc_data[i+1].first >= 2);
3250 // We replace this entry by the next valid
3251 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3252 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3253 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3254 }
3255 }
3256
3257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 579 times.
579 if (pb->eof_reached) {
3258 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3259 return AVERROR_EOF;
3260 }
3261
3262 579 return 0;
3263 }
3264
3265 340680 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3266 {
3267 340680 return index < count - 1;
3268 }
3269
3270 /* Compute the samples value for the stsc entry at the given index. */
3271 55539 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3272 {
3273 int chunk_count;
3274
3275
2/2
✓ Branch 1 taken 55343 times.
✓ Branch 2 taken 196 times.
55539 if (mov_stsc_index_valid(index, sc->stsc_count))
3276 55343 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3277 else {
3278 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3280 196 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3281 }
3282
3283 55539 return sc->stsc_data[index].count * (int64_t)chunk_count;
3284 }
3285
3286 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3287 {
3288 AVStream *st;
3289 MOVStreamContext *sc;
3290 unsigned i, entries;
3291
3292 if (c->trak_index < 0) {
3293 av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3294 return 0;
3295 }
3296
3297 if (c->fc->nb_streams < 1)
3298 return 0;
3299 st = c->fc->streams[c->fc->nb_streams-1];
3300 sc = st->priv_data;
3301
3302 avio_rb32(pb); // version + flags
3303
3304 entries = avio_rb32(pb);
3305 if (sc->stps_data)
3306 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3307 av_free(sc->stps_data);
3308 sc->stps_count = 0;
3309 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3310 if (!sc->stps_data)
3311 return AVERROR(ENOMEM);
3312
3313 for (i = 0; i < entries && !pb->eof_reached; i++) {
3314 sc->stps_data[i] = avio_rb32(pb);
3315 }
3316
3317 sc->stps_count = i;
3318
3319 if (pb->eof_reached) {
3320 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3321 return AVERROR_EOF;
3322 }
3323
3324 return 0;
3325 }
3326
3327 144 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3328 {
3329 AVStream *st;
3330 FFStream *sti;
3331 MOVStreamContext *sc;
3332 unsigned int i, entries;
3333
3334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (c->trak_index < 0) {
3335 av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3336 return 0;
3337 }
3338
3339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (c->fc->nb_streams < 1)
3340 return 0;
3341 144 st = c->fc->streams[c->fc->nb_streams-1];
3342 144 sti = ffstream(st);
3343 144 sc = st->priv_data;
3344
3345 144 avio_r8(pb); /* version */
3346 144 avio_rb24(pb); /* flags */
3347
3348 144 entries = avio_rb32(pb);
3349
3350 144 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3351
3352
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 138 times.
144 if (!entries) {
3353 6 sc->keyframe_absent = 1;
3354
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)
3355 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3356 6 return 0;
3357 }
3358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (sc->keyframes)
3359 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (entries >= UINT_MAX / sizeof(int))
3361 return AVERROR_INVALIDDATA;
3362 138 av_freep(&sc->keyframes);
3363 138 sc->keyframe_count = 0;
3364 138 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (!sc->keyframes)
3366 return AVERROR(ENOMEM);
3367
3368
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++) {
3369 5706 sc->keyframes[i] = avio_rb32(pb);
3370 }
3371
3372 138 sc->keyframe_count = i;
3373
3374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (pb->eof_reached) {
3375 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3376 return AVERROR_EOF;
3377 }
3378
3379 138 return 0;
3380 }
3381
3382 594 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3383 {
3384 AVStream *st;
3385 MOVStreamContext *sc;
3386 unsigned int i, entries, sample_size, field_size, num_bytes;
3387 GetBitContext gb;
3388 unsigned char* buf;
3389 int ret;
3390
3391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->trak_index < 0) {
3392 av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3393 return 0;
3394 }
3395
3396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
3397 return 0;
3398 594 st = c->fc->streams[c->fc->nb_streams-1];
3399 594 sc = st->priv_data;
3400
3401 594 avio_r8(pb); /* version */
3402 594 avio_rb24(pb); /* flags */
3403
3404
1/2
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
594 if (atom.type == MKTAG('s','t','s','z')) {
3405 594 sample_size = avio_rb32(pb);
3406
2/2
✓ Branch 0 taken 553 times.
✓ Branch 1 taken 41 times.
594 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3407 553 sc->sample_size = sample_size;
3408 594 sc->stsz_sample_size = sample_size;
3409 594 field_size = 32;
3410 } else {
3411 sample_size = 0;
3412 avio_rb24(pb); /* reserved */
3413 field_size = avio_r8(pb);
3414 }
3415 594 entries = avio_rb32(pb);
3416
3417 594 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3418
3419 594 sc->sample_count = entries;
3420
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 396 times.
594 if (sample_size)
3421 198 return 0;
3422
3423
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) {
3424 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3425 return AVERROR_INVALIDDATA;
3426 }
3427
3428
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 380 times.
396 if (!entries)
3429 16 return 0;
3430
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)
3431 return AVERROR_INVALIDDATA;
3432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (sc->sample_sizes)
3433 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3434 380 av_free(sc->sample_sizes);
3435 380 sc->sample_count = 0;
3436 380 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (!sc->sample_sizes)
3438 return AVERROR(ENOMEM);
3439
3440 380 num_bytes = (entries*field_size+4)>>3;
3441
3442 380 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (!buf) {
3444 av_freep(&sc->sample_sizes);
3445 return AVERROR(ENOMEM);
3446 }
3447
3448 380 ret = ffio_read_size(pb, buf, num_bytes);
3449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (ret < 0) {
3450 av_freep(&sc->sample_sizes);
3451 av_free(buf);
3452 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3453 return 0;
3454 }
3455
3456 380 init_get_bits(&gb, buf, 8*num_bytes);
3457
3458
2/2
✓ Branch 0 taken 226883 times.
✓ Branch 1 taken 380 times.
227263 for (i = 0; i < entries; i++) {
3459 226883 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 226883 times.
226883 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3461 av_free(buf);
3462 av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3463 return AVERROR_INVALIDDATA;
3464 }
3465 226883 sc->data_size += sc->sample_sizes[i];
3466 }
3467
3468 380 sc->sample_count = i;
3469
3470 380 av_free(buf);
3471
3472 380 return 0;
3473 }
3474
3475 594 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3476 {
3477 AVStream *st;
3478 MOVStreamContext *sc;
3479 unsigned int i, entries;
3480 594 int64_t duration = 0;
3481 594 int64_t total_sample_count = 0;
3482 594 int64_t current_dts = 0;
3483 594 int64_t corrected_dts = 0;
3484
3485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->trak_index < 0) {
3486 av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3487 return 0;
3488 }
3489
3490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
3491 return 0;
3492 594 st = c->fc->streams[c->fc->nb_streams-1];
3493 594 sc = st->priv_data;
3494
3495 594 avio_r8(pb); /* version */
3496 594 avio_rb24(pb); /* flags */
3497 594 entries = avio_rb32(pb);
3498
3499 594 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3500 594 c->fc->nb_streams-1, entries);
3501
3502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (sc->stts_data)
3503 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3504 594 av_freep(&sc->stts_data);
3505 594 sc->stts_count = 0;
3506
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3507 return AVERROR(ENOMEM);
3508
3509
3/4
✓ Branch 0 taken 2941 times.
✓ Branch 1 taken 594 times.
✓ Branch 2 taken 2941 times.
✗ Branch 3 not taken.
3535 for (i = 0; i < entries && !pb->eof_reached; i++) {
3510 unsigned int sample_duration;
3511 unsigned int sample_count;
3512 2941 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3513 2941 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3514 min_entries * sizeof(*sc->stts_data));
3515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2941 times.
2941 if (!stts_data) {
3516 av_freep(&sc->stts_data);
3517 sc->stts_count = 0;
3518 return AVERROR(ENOMEM);
3519 }
3520 2941 sc->stts_count = min_entries;
3521 2941 sc->stts_data = stts_data;
3522
3523 2941 sample_count = avio_rb32(pb);
3524 2941 sample_duration = avio_rb32(pb);
3525
3526 2941 sc->stts_data[i].count= sample_count;
3527 2941 sc->stts_data[i].duration= sample_duration;
3528
3529 2941 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3530 sample_count, sample_duration);
3531
3532 /* STTS sample offsets are uint32 but some files store it as int32
3533 * with negative values used to correct DTS delays.
3534 There may be abnormally large values as well. */
3535
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2940 times.
2941 if (sample_duration > c->max_stts_delta) {
3536 // assume high delta is a correction if negative when cast as int32
3537 1 int32_t delta_magnitude = (int32_t)sample_duration;
3538 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",
3539 sample_duration, i, sample_count, st->index);
3540 1 sc->stts_data[i].duration = 1;
3541
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);
3542 } else {
3543 2940 corrected_dts += sample_duration * (uint64_t)sample_count;
3544 }
3545
3546 2941 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3547
3548
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2919 times.
2941 if (current_dts > corrected_dts) {
3549 22 int64_t drift = av_sat_sub64(current_dts, corrected_dts) / FFMAX(sample_count, 1);
3550
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;
3551 22 current_dts -= correction * (uint64_t)sample_count;
3552 22 sc->stts_data[i].duration -= correction;
3553 }
3554
3555 2941 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3556 2941 total_sample_count+=sc->stts_data[i].count;
3557 }
3558
3559 594 sc->stts_count = i;
3560
3561
2/2
✓ Branch 0 taken 578 times.
✓ Branch 1 taken 16 times.
594 if (duration > 0 &&
3562
1/2
✓ Branch 0 taken 578 times.
✗ Branch 1 not taken.
578 duration <= INT64_MAX - sc->duration_for_fps &&
3563
1/2
✓ Branch 0 taken 578 times.
✗ Branch 1 not taken.
578 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3564 578 sc->duration_for_fps += duration;
3565 578 sc->nb_frames_for_fps += total_sample_count;
3566 }
3567
3568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (pb->eof_reached) {
3569 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3570 return AVERROR_EOF;
3571 }
3572
3573 594 st->nb_frames= total_sample_count;
3574
2/2
✓ Branch 0 taken 578 times.
✓ Branch 1 taken 16 times.
594 if (duration)
3575 578 st->duration= FFMIN(st->duration, duration);
3576
3577 // All samples have zero duration. They have higher chance be chose by
3578 // mov_find_next_sample, which leads to seek again and again.
3579 //
3580 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3581 // So only mark data stream as discarded for safety.
3582
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 578 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
594 if (!duration && sc->stts_count &&
3583 st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3584 av_log(c->fc, AV_LOG_WARNING,
3585 "All samples in data stream index:id [%d:%d] have zero "
3586 "duration, stream set to be discarded by default. Override "
3587 "using AVStream->discard or -discard for ffmpeg command.\n",
3588 st->index, sc->id);
3589 st->discard = AVDISCARD_ALL;
3590 }
3591 594 sc->track_end = duration;
3592 594 return 0;
3593 }
3594
3595 44 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3596 {
3597 AVStream *st;
3598 MOVStreamContext *sc;
3599 int64_t i, entries;
3600
3601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (c->fc->nb_streams < 1)
3602 return 0;
3603 44 st = c->fc->streams[c->fc->nb_streams - 1];
3604 44 sc = st->priv_data;
3605
3606 44 avio_r8(pb); /* version */
3607 44 avio_rb24(pb); /* flags */
3608 44 entries = atom.size - 4;
3609
3610 44 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3611 44 c->fc->nb_streams - 1, entries);
3612
3613
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 36 times.
44 if (sc->sdtp_data)
3614 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3615 44 av_freep(&sc->sdtp_data);
3616 44 sc->sdtp_count = 0;
3617
3618 44 sc->sdtp_data = av_malloc(entries);
3619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (!sc->sdtp_data)
3620 return AVERROR(ENOMEM);
3621
3622
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++)
3623 3807 sc->sdtp_data[i] = avio_r8(pb);
3624 44 sc->sdtp_count = i;
3625
3626 44 return 0;
3627 }
3628
3629 10827 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3630 {
3631
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 9691 times.
10827 if (duration < 0) {
3632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3633 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3634 duration++;
3635 }
3636 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3637 }
3638 10827 }
3639
3640 63 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3641 {
3642 AVStream *st;
3643 MOVStreamContext *sc;
3644 63 unsigned int i, entries, ctts_count = 0;
3645
3646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->trak_index < 0) {
3647 av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
3648 return 0;
3649 }
3650
3651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->fc->nb_streams < 1)
3652 return 0;
3653 63 st = c->fc->streams[c->fc->nb_streams-1];
3654 63 sc = st->priv_data;
3655
3656 63 avio_r8(pb); /* version */
3657 63 avio_rb24(pb); /* flags */
3658 63 entries = avio_rb32(pb);
3659
3660 63 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3661
3662
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 59 times.
63 if (!entries)
3663 4 return 0;
3664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
3665 return AVERROR_INVALIDDATA;
3666 59 av_freep(&sc->ctts_data);
3667 59 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
3668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->ctts_data)
3669 return AVERROR(ENOMEM);
3670
3671
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++) {
3672 MOVCtts *ctts_data;
3673 4874 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
3674 4874 const size_t requested_size =
3675 4874 min_size_needed > sc->ctts_allocated_size ?
3676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
3677 min_size_needed;
3678 4874 int count = avio_rb32(pb);
3679 4874 int duration = avio_rb32(pb);
3680
3681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (count <= 0) {
3682 av_log(c->fc, AV_LOG_TRACE,
3683 "ignoring CTTS entry with count=%d duration=%d\n",
3684 count, duration);
3685 continue;
3686 }
3687
3688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
3689 return AVERROR(ENOMEM);
3690
3691 4874 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
3692
3693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (!ctts_data)
3694 return AVERROR(ENOMEM);
3695
3696 4874 sc->ctts_data = ctts_data;
3697
3698 4874 ctts_data[ctts_count].count = count;
3699 4874 ctts_data[ctts_count].offset = duration;
3700 4874 ctts_count++;
3701
3702 4874 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
3703 count, duration);
3704
3705
2/2
✓ Branch 0 taken 4761 times.
✓ Branch 1 taken 113 times.
4874 if (i+2<entries)
3706 4761 mov_update_dts_shift(sc, duration, c->fc);
3707 }
3708
3709 59 sc->ctts_count = ctts_count;
3710
3711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (pb->eof_reached) {
3712 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
3713 return AVERROR_EOF;
3714 }
3715
3716 59 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
3717
3718 59 return 0;
3719 }
3720
3721 28 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3722 {
3723 AVStream *st;
3724 MOVStreamContext *sc;
3725 uint8_t version;
3726 uint32_t grouping_type;
3727 uint32_t default_length;
3728 av_unused uint32_t default_group_description_index;
3729 uint32_t entry_count;
3730
3731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (c->fc->nb_streams < 1)
3732 return 0;
3733 28 st = c->fc->streams[c->fc->nb_streams - 1];
3734 28 sc = st->priv_data;
3735
3736 28 version = avio_r8(pb); /* version */
3737 28 avio_rb24(pb); /* flags */
3738 28 grouping_type = avio_rl32(pb);
3739
3740 /*
3741 * This function only supports "sync" boxes, but the code is able to parse
3742 * other boxes (such as "tscl", "tsas" and "stsa")
3743 */
3744
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 5 times.
28 if (grouping_type != MKTAG('s','y','n','c'))
3745 23 return 0;
3746
3747
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
3748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
3749 5 entry_count = avio_rb32(pb);
3750
3751 5 av_freep(&sc->sgpd_sync);
3752 5 sc->sgpd_sync_count = entry_count;
3753 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
3754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
3755 return AVERROR(ENOMEM);
3756
3757
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++) {
3758 8 uint32_t description_length = default_length;
3759
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)
3760 description_length = avio_rb32(pb);
3761
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
3762 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
3763 8 sc->sgpd_sync[i] = nal_unit_type;
3764 8 description_length -= 1;
3765 }
3766 8 avio_skip(pb, description_length);
3767 }
3768
3769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
3770 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
3771 return AVERROR_EOF;
3772 }
3773
3774 5 return 0;
3775 }
3776
3777 25 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3778 {
3779 AVStream *st;
3780 MOVStreamContext *sc;
3781 unsigned int i, entries;
3782 uint8_t version;
3783 uint32_t grouping_type;
3784 MOVSbgp *table, **tablep;
3785 int *table_count;
3786
3787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (c->fc->nb_streams < 1)
3788 return 0;
3789 25 st = c->fc->streams[c->fc->nb_streams-1];
3790 25 sc = st->priv_data;
3791
3792 25 version = avio_r8(pb); /* version */
3793 25 avio_rb24(pb); /* flags */
3794 25 grouping_type = avio_rl32(pb);
3795
3796
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 24 times.
25 if (grouping_type == MKTAG('r','a','p',' ')) {
3797 1 tablep = &sc->rap_group;
3798 1 table_count = &sc->rap_group_count;
3799
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19 times.
24 } else if (grouping_type == MKTAG('s','y','n','c')) {
3800 5 tablep = &sc->sync_group;
3801 5 table_count = &sc->sync_group_count;
3802 } else {
3803 19 return 0;
3804 }
3805
3806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
3807 avio_rb32(pb); /* grouping_type_parameter */
3808
3809 6 entries = avio_rb32(pb);
3810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
3811 return 0;
3812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
3813 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
3814 6 av_freep(tablep);
3815 6 table = av_malloc_array(entries, sizeof(*table));
3816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
3817 return AVERROR(ENOMEM);
3818 6 *tablep = table;
3819
3820
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++) {
3821 32 table[i].count = avio_rb32(pb); /* sample_count */
3822 32 table[i].index = avio_rb32(pb); /* group_description_index */
3823 }
3824
3825 6 *table_count = i;
3826
3827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
3828 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
3829 return AVERROR_EOF;
3830 }
3831
3832 6 return 0;
3833 }
3834
3835 /**
3836 * Get ith edit list entry (media time, duration).
3837 */
3838 901 static int get_edit_list_entry(MOVContext *mov,
3839 const MOVStreamContext *msc,
3840 unsigned int edit_list_index,
3841 int64_t *edit_list_media_time,
3842 int64_t *edit_list_duration,
3843 int64_t global_timescale)
3844 {
3845
2/2
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 464 times.
901 if (edit_list_index == msc->elst_count) {
3846 437 return 0;
3847 }
3848 464 *edit_list_media_time = msc->elst_data[edit_list_index].time;
3849 464 *edit_list_duration = msc->elst_data[edit_list_index].duration;
3850
3851 /* duration is in global timescale units;convert to msc timescale */
3852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 464 times.
464 if (global_timescale == 0) {
3853 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
3854 return 0;
3855 }
3856 464 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
3857 global_timescale);
3858
3859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 464 times.
464 if (*edit_list_duration + (uint64_t)*edit_list_media_time > INT64_MAX)
3860 *edit_list_duration = 0;
3861
3862 464 return 1;
3863 }
3864
3865 /**
3866 * Find the closest previous frame to the timestamp_pts, in e_old index
3867 * entries. Searching for just any frame / just key frames can be controlled by
3868 * last argument 'flag'.
3869 * Note that if ctts_data is not NULL, we will always search for a key frame
3870 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
3871 * return the first frame of the video.
3872 *
3873 * Here the timestamp_pts is considered to be a presentation timestamp and
3874 * the timestamp of index entries are considered to be decoding timestamps.
3875 *
3876 * Returns 0 if successful in finding a frame, else returns -1.
3877 * Places the found index corresponding output arg.
3878 *
3879 * If ctts_old is not NULL, then refines the searched entry by searching
3880 * backwards from the found timestamp, to find the frame with correct PTS.
3881 *
3882 * Places the found ctts_index and ctts_sample in corresponding output args.
3883 */
3884 463 static int find_prev_closest_index(AVStream *st,
3885 AVIndexEntry *e_old,
3886 int nb_old,
3887 MOVTimeToSample *tts_data,
3888 int64_t tts_count,
3889 int64_t timestamp_pts,
3890 int flag,
3891 int64_t* index,
3892 int64_t* tts_index,
3893 int64_t* tts_sample)
3894 {
3895 463 MOVStreamContext *msc = st->priv_data;
3896 463 FFStream *const sti = ffstream(st);
3897 463 AVIndexEntry *e_keep = sti->index_entries;
3898 463 int nb_keep = sti->nb_index_entries;
3899 463 int64_t i = 0;
3900
3901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 463 times.
463 av_assert0(index);
3902
3903 // If dts_shift > 0, then all the index timestamps will have to be offset by
3904 // at least dts_shift amount to obtain PTS.
3905 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
3906
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 454 times.
463 if (msc->dts_shift > 0) {
3907 9 timestamp_pts -= msc->dts_shift;
3908 }
3909
3910 463 sti->index_entries = e_old;
3911 463 sti->nb_index_entries = nb_old;
3912 463 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
3913
3914 // Keep going backwards in the index entries until the timestamp is the same.
3915
2/2
✓ Branch 0 taken 462 times.
✓ Branch 1 taken 1 times.
463 if (*index >= 0) {
3916
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 438 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
462 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
3917 i--) {
3918 if ((flag & AVSEEK_FLAG_ANY) ||
3919 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
3920 *index = i - 1;
3921 }
3922 }
3923 }
3924
3925 // If we have CTTS then refine the search, by searching backwards over PTS
3926 // computed by adding corresponding CTTS durations to index timestamps.
3927
4/4
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 399 times.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 1 times.
463 if (msc->ctts_count && *index >= 0) {
3928
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(tts_index);
3929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(tts_sample);
3930 // Find out the ctts_index for the found frame.
3931 63 *tts_index = 0;
3932 63 *tts_sample = 0;
3933
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++) {
3934
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (*tts_index < tts_count) {
3935 175 (*tts_sample)++;
3936
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (tts_data[*tts_index].count == *tts_sample) {
3937 175 (*tts_index)++;
3938 175 *tts_sample = 0;
3939 }
3940 }
3941 }
3942
3943
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) {
3944 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
3945 // No need to add dts_shift to the timestamp here becase timestamp_pts has already been
3946 // compensated by dts_shift above.
3947
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 &&
3948
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 4 times.
62 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
3949 58 break;
3950 }
3951
3952 12 (*index)--;
3953
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (*tts_sample == 0) {
3954 12 (*tts_index)--;
3955
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 if (*tts_index >= 0)
3956 7 *tts_sample = tts_data[*tts_index].count - 1;
3957 } else {
3958 (*tts_sample)--;
3959 }
3960 }
3961 }
3962
3963 /* restore AVStream state*/
3964 463 sti->index_entries = e_keep;
3965 463 sti->nb_index_entries = nb_keep;
3966
2/2
✓ Branch 0 taken 457 times.
✓ Branch 1 taken 6 times.
463 return *index >= 0 ? 0 : -1;
3967 }
3968
3969 /**
3970 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
3971 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
3972 *
3973 * This function is similar to ff_add_index_entry in libavformat/utils.c
3974 * except that here we are always unconditionally adding an index entry to
3975 * the end, instead of searching the entries list and skipping the add if
3976 * there is an existing entry with the same timestamp.
3977 * This is needed because the mov_fix_index calls this func with the same
3978 * unincremented timestamp for successive discarded frames.
3979 */
3980 348547 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
3981 int size, int distance, int flags)
3982 {
3983 348547 FFStream *const sti = ffstream(st);
3984 AVIndexEntry *entries, *ie;
3985 348547 int64_t index = -1;
3986 348547 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
3987
3988 // Double the allocation each time, to lower memory fragmentation.
3989 // Another difference from ff_add_index_entry function.
3990 348547 const size_t requested_size =
3991 348547 min_size_needed > sti->index_entries_allocated_size ?
3992
2/2
✓ Branch 0 taken 1973 times.
✓ Branch 1 taken 346574 times.
348547 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
3993 min_size_needed;
3994
3995
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348547 times.
348547 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
3996 return -1;
3997
3998 348547 entries = av_fast_realloc(sti->index_entries,
3999 &sti->index_entries_allocated_size,
4000 requested_size);
4001
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348547 times.
348547 if (!entries)
4002 return -1;
4003
4004 348547 sti->index_entries = entries;
4005
4006 348547 index = sti->nb_index_entries++;
4007 348547 ie= &entries[index];
4008
4009 348547 ie->pos = pos;
4010 348547 ie->timestamp = timestamp;
4011 348547 ie->min_distance= distance;
4012 348547 ie->size= size;
4013 348547 ie->flags = flags;
4014 348547 return index;
4015 }
4016
4017 /**
4018 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4019 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4020 */
4021 27 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4022 int64_t* frame_duration_buffer,
4023 int frame_duration_buffer_size) {
4024 27 FFStream *const sti = ffstream(st);
4025 27 int i = 0;
4026
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);
4027
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 27 times.
164 for (i = 0; i < frame_duration_buffer_size; i++) {
4028 137 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4029 137 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4030 }
4031 27 }
4032
4033 186048 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4034 int count, int offset, unsigned int duration)
4035 {
4036 MOVTimeToSample *tts_buf_new;
4037 186048 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4038 186048 const size_t requested_size =
4039 186048 min_size_needed > *allocated_size ?
4040
2/2
✓ Branch 0 taken 1341 times.
✓ Branch 1 taken 184707 times.
186048 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4041 min_size_needed;
4042
4043
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186048 times.
186048 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4044 return -1;
4045
4046 186048 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4047
4048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186048 times.
186048 if (!tts_buf_new)
4049 return -1;
4050
4051 186048 *tts_data = tts_buf_new;
4052
4053 186048 tts_buf_new[*tts_count].count = count;
4054 186048 tts_buf_new[*tts_count].offset = offset;
4055 186048 tts_buf_new[*tts_count].duration = duration;
4056
4057 186048 *tts_count = (*tts_count) + 1;
4058 186048 return 0;
4059 }
4060
4061 #define MAX_REORDER_DELAY 16
4062 601 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4063 {
4064 601 MOVStreamContext *msc = st->priv_data;
4065 601 FFStream *const sti = ffstream(st);
4066 601 int ctts_ind = 0;
4067 601 int ctts_sample = 0;
4068 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4069 601 int buf_start = 0;
4070 int j, r, num_swaps;
4071
4072
2/2
✓ Branch 0 taken 10217 times.
✓ Branch 1 taken 601 times.
10818 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4073 10217 pts_buf[j] = INT64_MIN;
4074
4075
3/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 542 times.
601 if (st->codecpar->video_delay <= 0 && msc->ctts_count &&
4076
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 16 times.
59 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4077 43 st->codecpar->video_delay = 0;
4078
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) {
4079 // Point j to the last elem of the buffer and insert the current pts there.
4080 138279 j = buf_start;
4081 138279 buf_start = (buf_start + 1);
4082
2/2
✓ Branch 0 taken 8111 times.
✓ Branch 1 taken 130168 times.
138279 if (buf_start == MAX_REORDER_DELAY + 1)
4083 8111 buf_start = 0;
4084
4085 138279 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4086
4087 // The timestamps that are already in the sorted buffer, and are greater than the
4088 // current pts, are exactly the timestamps that need to be buffered to output PTS
4089 // in correct sorted order.
4090 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4091 // can be computed as the maximum no. of swaps any particular timestamp needs to
4092 // go through, to keep this buffer in sorted order.
4093 138279 num_swaps = 0;
4094
2/2
✓ Branch 0 taken 142294 times.
✓ Branch 1 taken 4 times.
142298 while (j != buf_start) {
4095 142294 r = j - 1;
4096
2/2
✓ Branch 0 taken 8389 times.
✓ Branch 1 taken 133905 times.
142294 if (r < 0) r = MAX_REORDER_DELAY;
4097
2/2
✓ Branch 0 taken 4019 times.
✓ Branch 1 taken 138275 times.
142294 if (pts_buf[j] < pts_buf[r]) {
4098 4019 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4099 4019 ++num_swaps;
4100 } else {
4101 138275 break;
4102 }
4103 4019 j = r;
4104 }
4105 138279 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4106
4107 138279 ctts_sample++;
4108
1/2
✓ Branch 0 taken 138279 times.
✗ Branch 1 not taken.
138279 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4109 138279 ctts_ind++;
4110 138279 ctts_sample = 0;
4111 }
4112 }
4113 43 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4114 43 st->codecpar->video_delay, st->index);
4115 }
4116 601 }
4117
4118 103409 static void mov_current_sample_inc(MOVStreamContext *sc)
4119 {
4120 103409 sc->current_sample++;
4121 103409 sc->current_index++;
4122
2/2
✓ Branch 0 taken 61410 times.
✓ Branch 1 taken 41999 times.
103409 if (sc->index_ranges &&
4123
2/2
✓ Branch 0 taken 421 times.
✓ Branch 1 taken 60989 times.
61410 sc->current_index >= sc->current_index_range->end &&
4124
1/2
✓ Branch 0 taken 421 times.
✗ Branch 1 not taken.
421 sc->current_index_range->end) {
4125 421 sc->current_index_range++;
4126 421 sc->current_index = sc->current_index_range->start;
4127 }
4128 103409 }
4129
4130 static void mov_current_sample_dec(MOVStreamContext *sc)
4131 {
4132 sc->current_sample--;
4133 sc->current_index--;
4134 if (sc->index_ranges &&
4135 sc->current_index < sc->current_index_range->start &&
4136 sc->current_index_range > sc->index_ranges) {
4137 sc->current_index_range--;
4138 sc->current_index = sc->current_index_range->end - 1;
4139 }
4140 }
4141
4142 335 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4143 {
4144 int64_t range_size;
4145
4146 335 sc->current_sample = current_sample;
4147 335 sc->current_index = current_sample;
4148
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 309 times.
335 if (!sc->index_ranges) {
4149 26 return;
4150 }
4151
4152 309 for (sc->current_index_range = sc->index_ranges;
4153
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 sc->current_index_range->end;
4154 sc->current_index_range++) {
4155 309 range_size = sc->current_index_range->end - sc->current_index_range->start;
4156
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 if (range_size > current_sample) {
4157 309 sc->current_index = sc->current_index_range->start + current_sample;
4158 309 break;
4159 }
4160 current_sample -= range_size;
4161 }
4162 }
4163
4164 /**
4165 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4166 * which are needed to decode them) that fall in the edit list time ranges.
4167 * Also fixes the timestamps of the index entries to match the timeline
4168 * specified the edit lists.
4169 */
4170 601 static void mov_fix_index(MOVContext *mov, AVStream *st)
4171 {
4172 601 MOVStreamContext *msc = st->priv_data;
4173 601 FFStream *const sti = ffstream(st);
4174 601 AVIndexEntry *e_old = sti->index_entries;
4175 601 int nb_old = sti->nb_index_entries;
4176 601 const AVIndexEntry *e_old_end = e_old + nb_old;
4177 601 const AVIndexEntry *current = NULL;
4178 601 MOVTimeToSample *tts_data_old = msc->tts_data;
4179 601 int64_t tts_index_old = 0;
4180 601 int64_t tts_sample_old = 0;
4181 601 int64_t tts_count_old = msc->tts_count;
4182 601 int64_t edit_list_media_time = 0;
4183 601 int64_t edit_list_duration = 0;
4184 601 int64_t frame_duration = 0;
4185 601 int64_t edit_list_dts_counter = 0;
4186 601 int64_t edit_list_dts_entry_end = 0;
4187 601 int64_t edit_list_start_tts_sample = 0;
4188 int64_t curr_cts;
4189 601 int64_t curr_ctts = 0;
4190 601 int64_t empty_edits_sum_duration = 0;
4191 601 int64_t edit_list_index = 0;
4192 int64_t index;
4193 int flags;
4194 601 int64_t start_dts = 0;
4195 601 int64_t edit_list_start_encountered = 0;
4196 601 int64_t search_timestamp = 0;
4197 601 int64_t* frame_duration_buffer = NULL;
4198 601 int num_discarded_begin = 0;
4199 601 int first_non_zero_audio_edit = -1;
4200 601 int packet_skip_samples = 0;
4201 601 MOVIndexRange *current_index_range = NULL;
4202 601 int found_keyframe_after_edit = 0;
4203 601 int found_non_empty_edit = 0;
4204
4205
4/6
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 164 times.
✓ Branch 2 taken 437 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 437 times.
601 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
4206 164 return;
4207 }
4208
4209 // allocate the index ranges array
4210 437 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4211 sizeof(msc->index_ranges[0]));
4212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 437 times.
437 if (!msc->index_ranges) {
4213 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4214 return;
4215 }
4216 437 msc->current_index_range = msc->index_ranges;
4217
4218 // Clean AVStream from traces of old index
4219 437 sti->index_entries = NULL;
4220 437 sti->index_entries_allocated_size = 0;
4221 437 sti->nb_index_entries = 0;
4222
4223 // Clean time to sample fields of MOVStreamContext
4224 437 msc->tts_data = NULL;
4225 437 msc->tts_count = 0;
4226 437 msc->tts_index = 0;
4227 437 msc->tts_sample = 0;
4228 437 msc->tts_allocated_size = 0;
4229
4230 // Reinitialize min_corrected_pts so that it can be computed again.
4231 437 msc->min_corrected_pts = -1;
4232
4233 // If the dts_shift is positive (in case of negative ctts values in mov),
4234 // then negate the DTS by dts_shift
4235
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 428 times.
437 if (msc->dts_shift > 0) {
4236 9 edit_list_dts_entry_end -= msc->dts_shift;
4237 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4238 }
4239
4240 437 start_dts = edit_list_dts_entry_end;
4241
4242
2/2
✓ Branch 0 taken 464 times.
✓ Branch 1 taken 437 times.
1338 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
4243 901 &edit_list_duration, mov->time_scale)) {
4244 464 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4245 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4246 464 edit_list_index++;
4247 464 edit_list_dts_counter = edit_list_dts_entry_end;
4248 464 edit_list_dts_entry_end += edit_list_duration;
4249 464 num_discarded_begin = 0;
4250
4/4
✓ Branch 0 taken 441 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 437 times.
464 if (!found_non_empty_edit && edit_list_media_time == -1) {
4251 4 empty_edits_sum_duration += edit_list_duration;
4252 4 continue;
4253 }
4254 460 found_non_empty_edit = 1;
4255
4256 // If we encounter a non-negative edit list reset the skip_samples/start_pad fields and set them
4257 // according to the edit list below.
4258
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 333 times.
460 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4259
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit < 0) {
4260 127 first_non_zero_audio_edit = 1;
4261 } else {
4262 first_non_zero_audio_edit = 0;
4263 }
4264
4265
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit > 0)
4266 127 sti->skip_samples = msc->start_pad = 0;
4267 }
4268
4269 // While reordering frame index according to edit list we must handle properly
4270 // the scenario when edit list entry starts from none key frame.
4271 // We find closest previous key frame and preserve it and consequent frames in index.
4272 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4273 460 search_timestamp = edit_list_media_time;
4274
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 333 times.
460 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4275 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4276 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4277 // edit_list_media_time to cover the decoder delay.
4278 127 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
4279 }
4280
4281
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 457 times.
460 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, 0,
4282 &index, &tts_index_old, &tts_sample_old) < 0) {
4283 3 av_log(mov->fc, AV_LOG_WARNING,
4284 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4285 st->index, edit_list_index, search_timestamp);
4286
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,
4287 &index, &tts_index_old, &tts_sample_old) < 0) {
4288 3 av_log(mov->fc, AV_LOG_WARNING,
4289 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4290 st->index, edit_list_index, search_timestamp);
4291 3 index = 0;
4292 3 tts_index_old = 0;
4293 3 tts_sample_old = 0;
4294 }
4295 }
4296 460 current = e_old + index;
4297 460 edit_list_start_tts_sample = tts_sample_old;
4298
4299 // Iterate over index and arrange it according to edit list
4300 460 edit_list_start_encountered = 0;
4301 460 found_keyframe_after_edit = 0;
4302
2/2
✓ Branch 0 taken 348547 times.
✓ Branch 1 taken 112 times.
348659 for (; current < e_old_end; current++, index++) {
4303 // check if frame outside edit list mark it for discard
4304 697094 frame_duration = (current + 1 < e_old_end) ?
4305
2/2
✓ Branch 0 taken 348114 times.
✓ Branch 1 taken 433 times.
348547 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4306
4307 348547 flags = current->flags;
4308
4309 // frames (pts) before or after edit list
4310 348547 curr_cts = current->timestamp + msc->dts_shift;
4311 348547 curr_ctts = 0;
4312
4313
4/4
✓ Branch 0 taken 186060 times.
✓ Branch 1 taken 162487 times.
✓ Branch 2 taken 186048 times.
✓ Branch 3 taken 12 times.
348547 if (tts_data_old && tts_index_old < tts_count_old) {
4314 186048 curr_ctts = tts_data_old[tts_index_old].offset;
4315 186048 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4316 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4317 186048 curr_cts += curr_ctts;
4318 186048 tts_sample_old++;
4319
1/2
✓ Branch 0 taken 186048 times.
✗ Branch 1 not taken.
186048 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186048 times.
186048 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4321 &msc->tts_allocated_size,
4322 186048 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4323 186048 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4324 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4325 tts_index_old,
4326 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4327 tts_data_old[tts_index_old].offset);
4328 break;
4329 }
4330 186048 tts_index_old++;
4331 186048 tts_sample_old = 0;
4332 186048 edit_list_start_tts_sample = 0;
4333 }
4334 }
4335
4336
4/4
✓ Branch 0 taken 348395 times.
✓ Branch 1 taken 152 times.
✓ Branch 2 taken 130 times.
✓ Branch 3 taken 348265 times.
348547 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
4337
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 &&
4338
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 &&
4339 first_non_zero_audio_edit > 0) {
4340 11 packet_skip_samples = edit_list_media_time - curr_cts;
4341 11 sti->skip_samples += packet_skip_samples;
4342
4343 // Shift the index entry timestamp by packet_skip_samples to be correct.
4344 11 edit_list_dts_counter -= packet_skip_samples;
4345
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (edit_list_start_encountered == 0) {
4346 11 edit_list_start_encountered = 1;
4347 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4348 // discarded packets.
4349
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 if (frame_duration_buffer) {
4350 6 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4351 frame_duration_buffer, num_discarded_begin);
4352 6 av_freep(&frame_duration_buffer);
4353 }
4354 }
4355
4356 11 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4357 } else {
4358 271 flags |= AVINDEX_DISCARD_FRAME;
4359 271 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4360
4361
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 132 times.
271 if (edit_list_start_encountered == 0) {
4362 139 num_discarded_begin++;
4363 139 frame_duration_buffer = av_realloc(frame_duration_buffer,
4364 num_discarded_begin * sizeof(int64_t));
4365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if (!frame_duration_buffer) {
4366 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4367 break;
4368 }
4369 139 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4370
4371 // Increment skip_samples for the first non-zero audio edit list
4372
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 &&
4373
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) {
4374 20 sti->skip_samples += frame_duration;
4375 }
4376 }
4377 }
4378 } else {
4379
2/2
✓ Branch 0 taken 436 times.
✓ Branch 1 taken 347829 times.
348265 if (msc->min_corrected_pts < 0) {
4380 436 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4381 } else {
4382 347829 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4383 }
4384
2/2
✓ Branch 0 taken 447 times.
✓ Branch 1 taken 347818 times.
348265 if (edit_list_start_encountered == 0) {
4385 447 edit_list_start_encountered = 1;
4386 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4387 // discarded packets.
4388
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 426 times.
447 if (frame_duration_buffer) {
4389 21 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4390 frame_duration_buffer, num_discarded_begin);
4391 21 av_freep(&frame_duration_buffer);
4392 }
4393 }
4394 }
4395
4396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348547 times.
348547 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
4397 348547 current->min_distance, flags) == -1) {
4398 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4399 break;
4400 }
4401
4402 // Update the index ranges array
4403
4/4
✓ Branch 0 taken 348110 times.
✓ Branch 1 taken 437 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 348089 times.
348547 if (!current_index_range || index != current_index_range->end) {
4404 458 current_index_range = current_index_range ? current_index_range + 1
4405
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 437 times.
458 : msc->index_ranges;
4406 458 current_index_range->start = index;
4407 }
4408 348547 current_index_range->end = index + 1;
4409
4410 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4411
2/2
✓ Branch 0 taken 348408 times.
✓ Branch 1 taken 139 times.
348547 if (edit_list_start_encountered > 0) {
4412 348408 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4413 }
4414
4415 // Break when found first key frame after edit entry completion
4416
2/2
✓ Branch 0 taken 616 times.
✓ Branch 1 taken 347931 times.
348547 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
4417
3/4
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 256 times.
616 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
4418
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 339 times.
360 if (msc->ctts_count) {
4419 // If we have CTTS and this is the first keyframe after edit elist,
4420 // wait for one more, because there might be trailing B-frames after this I-frame
4421 // that do belong to the edit.
4422
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) {
4423 12 found_keyframe_after_edit = 1;
4424 12 continue;
4425 }
4426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (tts_sample_old != 0) {
4427 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4428 &msc->tts_allocated_size,
4429 tts_sample_old - edit_list_start_tts_sample,
4430 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4431 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4432 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4433 tts_data_old[tts_index_old].offset);
4434 break;
4435 }
4436 }
4437 }
4438 348 break;
4439 }
4440 }
4441 }
4442 // If there are empty edits, then msc->min_corrected_pts might be positive
4443 // intentionally. So we subtract the sum duration of emtpy edits here.
4444 437 msc->min_corrected_pts -= empty_edits_sum_duration;
4445
4446 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4447 // dts by that amount to make the first pts zero.
4448
2/2
✓ Branch 0 taken 268 times.
✓ Branch 1 taken 169 times.
437 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4449
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 227 times.
268 if (msc->min_corrected_pts > 0) {
4450 41 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4451
2/2
✓ Branch 0 taken 2829 times.
✓ Branch 1 taken 41 times.
2870 for (int i = 0; i < sti->nb_index_entries; ++i)
4452 2829 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4453 }
4454 }
4455 // Start time should be equal to zero or the duration of any empty edits.
4456 437 st->start_time = empty_edits_sum_duration;
4457
4458 // Update av stream length, if it ends up shorter than the track's media duration
4459 437 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4460 437 msc->start_pad = sti->skip_samples;
4461
4462 // Free the old index and the old CTTS structures
4463 437 av_free(e_old);
4464 437 av_free(tts_data_old);
4465 437 av_freep(&frame_duration_buffer);
4466
4467 // Null terminate the index ranges array
4468 437 current_index_range = current_index_range ? current_index_range + 1
4469
1/2
✓ Branch 0 taken 437 times.
✗ Branch 1 not taken.
437 : msc->index_ranges;
4470 437 current_index_range->start = 0;
4471 437 current_index_range->end = 0;
4472 437 msc->current_index = msc->index_ranges[0].start;
4473 }
4474
4475 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4476 {
4477
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4478
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == nal_unit_type)
4479 5 return i + 1;
4480 return 0;
4481 }
4482
4483 617 static int build_open_gop_key_points(AVStream *st)
4484 {
4485 int k;
4486 617 int sample_id = 0;
4487 uint32_t cra_index;
4488 617 MOVStreamContext *sc = st->priv_data;
4489
4490
4/4
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 580 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 5 times.
617 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count)
4491 612 return 0;
4492
4493 /* Build an unrolled index of the samples */
4494 5 sc->sample_offsets_count = 0;
4495
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4497 return AVERROR(ENOMEM);
4498 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4499 }
4500 5 av_freep(&sc->sample_offsets);
4501 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4503 return AVERROR(ENOMEM);
4504 5 k = 0;
4505
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4506
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4507 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4508
4509 /* The following HEVC NAL type reveal the use of open GOP sync points
4510 * (TODO: BLA types may also be concerned) */
4511 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4513 return 0;
4514
4515 /* Build a list of open-GOP key samples */
4516 5 sc->open_key_samples_count = 0;
4517
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4518
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4519
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)
4520 return AVERROR(ENOMEM);
4521 11 sc->open_key_samples_count += sc->sync_group[i].count;
4522 }
4523 5 av_freep(&sc->open_key_samples);
4524 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4526 return AVERROR(ENOMEM);
4527 5 k = 0;
4528
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4529 28 const MOVSbgp *sg = &sc->sync_group[i];
4530
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4531
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4532 11 sc->open_key_samples[k++] = sample_id;
4533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4534 return AVERROR_PATCHWELCOME;
4535 28 sample_id += sg->count;
4536 }
4537
4538 /* Identify the minimal time step between samples */
4539 5 sc->min_sample_duration = UINT_MAX;
4540
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4541 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4542
4543 5 return 0;
4544 }
4545
4546 #define MOV_MERGE_CTTS 1
4547 #define MOV_MERGE_STTS 2
4548 /*
4549 * Merge stts and ctts arrays into a new combined array.
4550 * stts_count and ctts_count may be left untouched as they will be
4551 * used to check for the presence of either of them.
4552 */
4553 601 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4554 {
4555 601 MOVStreamContext *sc = st->priv_data;
4556
3/4
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 542 times.
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
601 int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS);
4557
3/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 535 times.
✓ Branch 3 taken 66 times.
601 int stts = sc->stts_data && (flags & MOV_MERGE_STTS);
4558 601 int idx = 0;
4559
4560
3/4
✓ Branch 0 taken 542 times.
✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 542 times.
601 if (!sc->ctts_data && !sc->stts_data)
4561 return 0;
4562 // Expand time to sample entries such that we have a 1-1 mapping with samples
4563
2/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 601 times.
601 if (!sc->sample_count || sc->sample_count >= UINT_MAX / sizeof(*sc->tts_data))
4564 return -1;
4565
4566
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 542 times.
601 if (ctts) {
4567 118 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4568 59 sc->sample_count * sizeof(*sc->tts_data));
4569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->tts_data)
4570 return -1;
4571
4572 59 memset(sc->tts_data, 0, sc->tts_allocated_size);
4573
4574
2/2
✓ Branch 0 taken 4874 times.
✓ Branch 1 taken 59 times.
4933 for (int i = 0; i < sc->ctts_count &&
4575
1/2
✓ Branch 0 taken 4874 times.
✗ Branch 1 not taken.
9748 idx < sc->sample_count; i++)
4576
2/2
✓ Branch 0 taken 139017 times.
✓ Branch 1 taken 4874 times.
143891 for (int j = 0; j < sc->ctts_data[i].count &&
4577
1/2
✓ Branch 0 taken 139017 times.
✗ Branch 1 not taken.
139017 idx < sc->sample_count; j++) {
4578 139017 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4579 139017 sc->tts_data[idx++].count = 1;
4580 }
4581
4582 59 sc->tts_count = idx;
4583 } else
4584 542 sc->ctts_count = 0;
4585 601 av_freep(&sc->ctts_data);
4586 601 sc->ctts_allocated_size = 0;
4587
4588 601 idx = 0;
4589
2/2
✓ Branch 0 taken 535 times.
✓ Branch 1 taken 66 times.
601 if (stts) {
4590 535 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4591 535 sc->sample_count * sizeof(*sc->tts_data));
4592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
535 if (!tts_data)
4593 return -1;
4594
4595
2/2
✓ Branch 0 taken 476 times.
✓ Branch 1 taken 59 times.
535 if (!sc->tts_data)
4596 476 memset(tts_data, 0, sc->tts_allocated_size);
4597 535 sc->tts_data = tts_data;
4598
4599
2/2
✓ Branch 0 taken 2898 times.
✓ Branch 1 taken 535 times.
3433 for (int i = 0; i < sc->stts_count &&
4600
1/2
✓ Branch 0 taken 2898 times.
✗ Branch 1 not taken.
5796 idx < sc->sample_count; i++)
4601
2/2
✓ Branch 0 taken 235892 times.
✓ Branch 1 taken 2898 times.
238790 for (int j = 0; j < sc->stts_data[i].count &&
4602
1/2
✓ Branch 0 taken 235892 times.
✗ Branch 1 not taken.
235892 idx < sc->sample_count; j++) {
4603 235892 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4604 235892 sc->tts_data[idx++].count = 1;
4605 }
4606
4607 535 sc->tts_count = FFMAX(sc->tts_count, idx);
4608 } else
4609 66 sc->stts_count = 0;
4610 601 av_freep(&sc->stts_data);
4611 601 sc->stts_allocated_size = 0;
4612
4613 601 return 0;
4614 }
4615
4616 617 static void mov_build_index(MOVContext *mov, AVStream *st)
4617 {
4618 617 MOVStreamContext *sc = st->priv_data;
4619 617 FFStream *const sti = ffstream(st);
4620 int64_t current_offset;
4621 617 int64_t current_dts = 0;
4622 617 unsigned int stts_index = 0;
4623 617 unsigned int stsc_index = 0;
4624 617 unsigned int stss_index = 0;
4625 617 unsigned int stps_index = 0;
4626 unsigned int i, j;
4627 617 uint64_t stream_size = 0;
4628
4629 617 int ret = build_open_gop_key_points(st);
4630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 617 times.
617 if (ret < 0)
4631 return;
4632
4633
2/2
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 178 times.
617 if (sc->elst_count) {
4634 439 int i, edit_start_index = 0, multiple_edits = 0;
4635 439 int64_t empty_duration = 0; // empty duration of the first edit list entry
4636 439 int64_t start_time = 0; // start time of the media
4637
4638
2/2
✓ Branch 0 taken 466 times.
✓ Branch 1 taken 439 times.
905 for (i = 0; i < sc->elst_count; i++) {
4639 466 const MOVElst *e = &sc->elst_data[i];
4640
4/4
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 435 times.
466 if (i == 0 && e->time == -1) {
4641 /* if empty, the first entry is the start time of the stream
4642 * relative to the presentation itself */
4643 4 empty_duration = e->duration;
4644 4 edit_start_index = 1;
4645
3/4
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 439 times.
✗ Branch 3 not taken.
462 } else if (i == edit_start_index && e->time >= 0) {
4646 439 start_time = e->time;
4647 } else {
4648 23 multiple_edits = 1;
4649 }
4650 }
4651
4652
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 433 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
439 if (multiple_edits && !mov->advanced_editlist) {
4653 if (mov->advanced_editlist_autodisabled)
4654 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4655 "not supported in fragmented MP4 files\n");
4656 else
4657 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4658 "Use -advanced_editlist to correctly decode otherwise "
4659 "a/v desync might occur\n");
4660 }
4661
4662 /* adjust first dts according to edit list */
4663
5/6
✓ Branch 0 taken 435 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 366 times.
✓ Branch 4 taken 73 times.
✗ Branch 5 not taken.
439 if ((empty_duration || start_time) && mov->time_scale > 0) {
4664
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 69 times.
73 if (empty_duration)
4665 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
4666
4667
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)
4668 av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
4669
4670 73 sc->time_offset = start_time - (uint64_t)empty_duration;
4671 73 sc->min_corrected_pts = start_time;
4672
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 72 times.
73 if (!mov->advanced_editlist)
4673 1 current_dts = -sc->time_offset;
4674 }
4675
4676
4/4
✓ Branch 0 taken 433 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 431 times.
439 if (!multiple_edits && !mov->advanced_editlist &&
4677
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)
4678 sc->start_pad = start_time;
4679 }
4680
4681 /* only use old uncompressed audio chunk demuxing when stts specifies it */
4682
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 376 times.
617 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4683
5/6
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 187 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 121 times.
✓ Branch 5 taken 66 times.
776 sc->stts_count == 1 && sc->stts_data && sc->stts_data[0].duration == 1)) {
4684 551 unsigned int current_sample = 0;
4685 551 unsigned int stts_sample = 0;
4686 unsigned int sample_size;
4687 551 unsigned int distance = 0;
4688 551 unsigned int rap_group_index = 0;
4689 551 unsigned int rap_group_sample = 0;
4690
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 550 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
551 int rap_group_present = sc->rap_group_count && sc->rap_group;
4691
4/8
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 413 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 138 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 413 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
551 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
4692
4693 551 current_dts -= sc->dts_shift;
4694
4695
4/6
✓ Branch 0 taken 535 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 535 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 535 times.
551 if (!sc->sample_count || sti->nb_index_entries || sc->tts_count)
4696 16 return;
4697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
535 if (sc->sample_count >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4698 return;
4699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
535 if (av_reallocp_array(&sti->index_entries,
4700 535 sti->nb_index_entries + sc->sample_count,
4701 sizeof(*sti->index_entries)) < 0) {
4702 sti->nb_index_entries = 0;
4703 return;
4704 }
4705 535 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
4706
4707 535 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
4708
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
535 if (ret < 0)
4709 return;
4710
4711
2/2
✓ Branch 0 taken 173838 times.
✓ Branch 1 taken 535 times.
174373 for (i = 0; i < sc->chunk_count; i++) {
4712
2/2
✓ Branch 0 taken 173303 times.
✓ Branch 1 taken 535 times.
173838 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
4713 173838 current_offset = sc->chunk_offsets[i];
4714
2/2
✓ Branch 1 taken 8859 times.
✓ Branch 2 taken 167522 times.
176381 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4715
2/2
✓ Branch 0 taken 2543 times.
✓ Branch 1 taken 6316 times.
8859 i + 1 == sc->stsc_data[stsc_index + 1].first)
4716 2543 stsc_index++;
4717
4718
4/6
✓ Branch 0 taken 173838 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7346 times.
✓ Branch 3 taken 166492 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7346 times.
173838 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
4719 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
4720 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
4721 sc->stsz_sample_size = sc->sample_size;
4722 }
4723
3/4
✓ Branch 0 taken 7346 times.
✓ Branch 1 taken 166492 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7346 times.
173838 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
4724 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
4725 sc->stsz_sample_size = sc->sample_size;
4726 }
4727
4728
2/2
✓ Branch 0 taken 235892 times.
✓ Branch 1 taken 173838 times.
409730 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
4729 235892 int keyframe = 0;
4730
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235892 times.
235892 if (current_sample >= sc->sample_count) {
4731 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
4732 return;
4733 }
4734
4735
6/6
✓ Branch 0 taken 231136 times.
✓ Branch 1 taken 4756 times.
✓ Branch 2 taken 152644 times.
✓ Branch 3 taken 78492 times.
✓ Branch 4 taken 5706 times.
✓ Branch 5 taken 146938 times.
235892 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
4736 84198 keyframe = 1;
4737
2/2
✓ Branch 0 taken 5568 times.
✓ Branch 1 taken 78630 times.
84198 if (stss_index + 1 < sc->keyframe_count)
4738 5568 stss_index++;
4739
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]) {
4740 keyframe = 1;
4741 if (stps_index + 1 < sc->stps_count)
4742 stps_index++;
4743 }
4744
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 235704 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
235892 if (rap_group_present && rap_group_index < sc->rap_group_count) {
4745
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
4746 2 keyframe = 1;
4747
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
4748 4 rap_group_sample = 0;
4749 4 rap_group_index++;
4750 }
4751 }
4752
2/2
✓ Branch 0 taken 4756 times.
✓ Branch 1 taken 231136 times.
235892 if (sc->keyframe_absent
4753
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !sc->stps_count
4754
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !rap_group_present
4755
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)))
4756 3884 keyframe = 1;
4757
2/2
✓ Branch 0 taken 88082 times.
✓ Branch 1 taken 147810 times.
235892 if (keyframe)
4758 88082 distance = 0;
4759
2/2
✓ Branch 0 taken 8986 times.
✓ Branch 1 taken 226906 times.
235892 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
4760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235892 times.
235892 if (current_offset > INT64_MAX - sample_size) {
4761 av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
4762 current_offset,
4763 sample_size);
4764 return;
4765 }
4766
4767
2/2
✓ Branch 0 taken 235811 times.
✓ Branch 1 taken 81 times.
235892 if (sc->pseudo_stream_id == -1 ||
4768
1/2
✓ Branch 0 taken 235811 times.
✗ Branch 1 not taken.
235811 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
4769 AVIndexEntry *e;
4770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235892 times.
235892 if (sample_size > 0x3FFFFFFF) {
4771 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
4772 return;
4773 }
4774 235892 e = &sti->index_entries[sti->nb_index_entries++];
4775 235892 e->pos = current_offset;
4776 235892 e->timestamp = current_dts;
4777 235892 e->size = sample_size;
4778 235892 e->min_distance = distance;
4779 235892 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
4780 235892 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
4781 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
4782 current_offset, current_dts, sample_size, distance, keyframe);
4783
4/4
✓ Branch 0 taken 154992 times.
✓ Branch 1 taken 80900 times.
✓ Branch 2 taken 10359 times.
✓ Branch 3 taken 144633 times.
235892 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries < 100)
4784 10359 ff_rfps_add_frame(mov->fc, st, current_dts);
4785 }
4786
4787 235892 current_offset += sample_size;
4788 235892 stream_size += sample_size;
4789
4790 235892 current_dts += sc->tts_data[stts_index].duration;
4791
4792 235892 distance++;
4793 235892 stts_sample++;
4794 235892 current_sample++;
4795
3/4
✓ Branch 0 taken 235357 times.
✓ Branch 1 taken 535 times.
✓ Branch 2 taken 235357 times.
✗ Branch 3 not taken.
235892 if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) {
4796 235357 stts_sample = 0;
4797 235357 stts_index++;
4798 }
4799 }
4800 }
4801
2/2
✓ Branch 0 taken 512 times.
✓ Branch 1 taken 23 times.
535 if (st->duration > 0)
4802 512 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
4803 } else {
4804 66 unsigned chunk_samples, total = 0;
4805
4806
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)
4807 return;
4808
4809 66 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
4810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
4811 return;
4812
4813 // compute total chunk count
4814
2/2
✓ Branch 0 taken 723 times.
✓ Branch 1 taken 66 times.
789 for (i = 0; i < sc->stsc_count; i++) {
4815 unsigned count, chunk_count;
4816
4817 723 chunk_samples = sc->stsc_data[i].count;
4818
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 66 times.
723 if (i != sc->stsc_count - 1 &&
4819
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) {
4820 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
4821 return;
4822 }
4823
4824
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 648 times.
723 if (sc->samples_per_frame >= 160) { // gsm
4825 75 count = chunk_samples / sc->samples_per_frame;
4826
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 117 times.
648 } else if (sc->samples_per_frame > 1) {
4827 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
4828 531 count = (chunk_samples+samples-1) / samples;
4829 } else {
4830 117 count = (chunk_samples+1023) / 1024;
4831 }
4832
4833
2/2
✓ Branch 1 taken 657 times.
✓ Branch 2 taken 66 times.
723 if (mov_stsc_index_valid(i, sc->stsc_count))
4834 657 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
4835 else
4836 66 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
4837 723 total += chunk_count * count;
4838 }
4839
4840 66 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
4841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4842 return;
4843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (av_reallocp_array(&sti->index_entries,
4844 66 sti->nb_index_entries + total,
4845 sizeof(*sti->index_entries)) < 0) {
4846 sti->nb_index_entries = 0;
4847 return;
4848 }
4849 66 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
4850
4851 // populate index
4852
2/2
✓ Branch 0 taken 5428 times.
✓ Branch 1 taken 66 times.
5494 for (i = 0; i < sc->chunk_count; i++) {
4853 5428 current_offset = sc->chunk_offsets[i];
4854
2/2
✓ Branch 1 taken 5287 times.
✓ Branch 2 taken 141 times.
5428 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4855
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 4630 times.
5287 i + 1 == sc->stsc_data[stsc_index + 1].first)
4856 657 stsc_index++;
4857 5428 chunk_samples = sc->stsc_data[stsc_index].count;
4858
4859
2/2
✓ Branch 0 taken 162532 times.
✓ Branch 1 taken 5428 times.
167960 while (chunk_samples > 0) {
4860 AVIndexEntry *e;
4861 unsigned size, samples;
4862
4863
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) {
4864 avpriv_request_sample(mov->fc,
4865 "Zero bytes per frame, but %d samples per frame",
4866 sc->samples_per_frame);
4867 return;
4868 }
4869
4870
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 148174 times.
162532 if (sc->samples_per_frame >= 160) { // gsm
4871 14358 samples = sc->samples_per_frame;
4872 14358 size = sc->bytes_per_frame;
4873 } else {
4874
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 138611 times.
148174 if (sc->samples_per_frame > 1) {
4875 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
4876 sc->samples_per_frame, chunk_samples);
4877 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
4878 } else {
4879 138611 samples = FFMIN(1024, chunk_samples);
4880 138611 size = samples * sc->sample_size;
4881 }
4882 }
4883
4884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (sti->nb_index_entries >= total) {
4885 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
4886 return;
4887 }
4888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (size > 0x3FFFFFFF) {
4889 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
4890 return;
4891 }
4892 162532 e = &sti->index_entries[sti->nb_index_entries++];
4893 162532 e->pos = current_offset;
4894 162532 e->timestamp = current_dts;
4895 162532 e->size = size;
4896 162532 e->min_distance = 0;
4897 162532 e->flags = AVINDEX_KEYFRAME;
4898 162532 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
4899 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
4900 size, samples);
4901
4902 162532 current_offset += size;
4903 162532 current_dts += samples;
4904 162532 chunk_samples -= samples;
4905 }
4906 }
4907 }
4908
4909
2/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
601 if (!mov->ignore_editlist && mov->advanced_editlist) {
4910 // Fix index according to edit lists.
4911 601 mov_fix_index(mov, st);
4912 }
4913
4914 // Update start time of the stream.
4915
5/6
✓ Branch 0 taken 164 times.
✓ Branch 1 taken 437 times.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 117 times.
✓ Branch 4 taken 47 times.
✗ Branch 5 not taken.
601 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) {
4916 47 st->start_time = sti->index_entries[0].timestamp + sc->dts_shift;
4917
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 if (sc->tts_data) {
4918 47 st->start_time += sc->tts_data[0].offset;
4919 }
4920 }
4921
4922 601 mov_estimate_video_delay(mov, st);
4923 }
4924
4925 static int test_same_origin(const char *src, const char *ref) {
4926 char src_proto[64];
4927 char ref_proto[64];
4928 char src_auth[256];
4929 char ref_auth[256];
4930 char src_host[256];
4931 char ref_host[256];
4932 int src_port=-1;
4933 int ref_port=-1;
4934
4935 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
4936 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
4937
4938 if (strlen(src) == 0) {
4939 return -1;
4940 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
4941 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
4942 strlen(src_host) + 1 >= sizeof(src_host) ||
4943 strlen(ref_host) + 1 >= sizeof(ref_host)) {
4944 return 0;
4945 } else if (strcmp(src_proto, ref_proto) ||
4946 strcmp(src_auth, ref_auth) ||
4947 strcmp(src_host, ref_host) ||
4948 src_port != ref_port) {
4949 return 0;
4950 } else
4951 return 1;
4952 }
4953
4954 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
4955 {
4956 /* try relative path, we do not try the absolute because it can leak information about our
4957 system to an attacker */
4958 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
4959 char filename[1025];
4960 const char *src_path;
4961 int i, l;
4962
4963 /* find a source dir */
4964 src_path = strrchr(src, '/');
4965 if (src_path)
4966 src_path++;
4967 else
4968 src_path = src;
4969
4970 /* find a next level down to target */
4971 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
4972 if (ref->path[l] == '/') {
4973 if (i == ref->nlvl_to - 1)
4974 break;
4975 else
4976 i++;
4977 }
4978
4979 /* compose filename if next level down to target was found */
4980 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
4981 memcpy(filename, src, src_path - src);
4982 filename[src_path - src] = 0;
4983
4984 for (i = 1; i < ref->nlvl_from; i++)
4985 av_strlcat(filename, "../", sizeof(filename));
4986
4987 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
4988 if (!c->use_absolute_path) {
4989 int same_origin = test_same_origin(src, filename);
4990
4991 if (!same_origin) {
4992 av_log(c->fc, AV_LOG_ERROR,
4993 "Reference with mismatching origin, %s not tried for security reasons, "
4994 "set demuxer option use_absolute_path to allow it anyway\n",
4995 ref->path);
4996 return AVERROR(ENOENT);
4997 }
4998
4999 if (strstr(ref->path + l + 1, "..") ||
5000 strstr(ref->path + l + 1, ":") ||
5001 (ref->nlvl_from > 1 && same_origin < 0) ||
5002 (filename[0] == '/' && src_path == src))
5003 return AVERROR(ENOENT);
5004 }
5005
5006 if (strlen(filename) + 1 == sizeof(filename))
5007 return AVERROR(ENOENT);
5008 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5009 return 0;
5010 }
5011 } else if (c->use_absolute_path) {
5012 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5013 "this is a possible security issue\n");
5014 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5015 return 0;
5016 } else {
5017 av_log(c->fc, AV_LOG_ERROR,
5018 "Absolute path %s not tried for security reasons, "
5019 "set demuxer option use_absolute_path to allow absolute paths\n",
5020 ref->path);
5021 }
5022
5023 return AVERROR(ENOENT);
5024 }
5025
5026 1265 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5027 {
5028
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1251 times.
1265 if (sc->time_scale <= 0) {
5029 14 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5030 14 sc->time_scale = c->time_scale;
5031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (sc->time_scale <= 0)
5032 sc->time_scale = 1;
5033 }
5034 1265 }
5035
5036 #if CONFIG_IAMFDEC
5037 10 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5038 {
5039 10 const MOVStreamContext *sc = st->priv_data;
5040 10 const IAMFContext *iamf = &sc->iamf->iamf;
5041
5042
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5043 10 const AVStreamGroup *stg = NULL;
5044
5045
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5046
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)
5047 10 stg = c->fc->stream_groups[j];
5048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 av_assert0(stg);
5049
5050
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int j = 0; j < stg->nb_streams; j++) {
5051 50 const FFStream *sti = cffstream(st);
5052 50 AVStream *out = stg->streams[j];
5053 50 FFStream *out_sti = ffstream(stg->streams[j]);
5054
5055 50 out->codecpar->bit_rate = 0;
5056
5057
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 40 times.
50 if (out == st)
5058 10 continue;
5059
5060 40 out->time_base = st->time_base;
5061 40 out->start_time = st->start_time;
5062 40 out->duration = st->duration;
5063 40 out->nb_frames = st->nb_frames;
5064 40 out->discard = st->discard;
5065
5066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 av_assert0(!out_sti->index_entries);
5067 40 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5068
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (!out_sti->index_entries)
5069 return AVERROR(ENOMEM);
5070
5071 40 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5072 40 out_sti->nb_index_entries = sti->nb_index_entries;
5073 40 out_sti->skip_samples = sti->skip_samples;
5074 40 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5075 }
5076 }
5077
5078 10 return 0;
5079 }
5080 #endif
5081
5082 617 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5083 {
5084
4/6
✓ Branch 0 taken 601 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 601 times.
✗ Branch 5 not taken.
617 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5085
3/4
✓ Branch 0 taken 403 times.
✓ Branch 1 taken 198 times.
✓ Branch 2 taken 403 times.
✗ Branch 3 not taken.
601 (!sc->sample_size && !sc->sample_count))) ||
5086
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 601 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
617 (!sc->chunk_count && sc->sample_count)) {
5087 av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5088 index);
5089 return 1;
5090 }
5091
5092
3/4
✓ Branch 0 taken 601 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 601 times.
617 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
5093 av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5094 index);
5095 return 2;
5096 }
5097 617 return 0;
5098 }
5099
5100 594 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5101 {
5102 AVStream *st;
5103 MOVStreamContext *sc;
5104 int ret;
5105
5106 594 st = avformat_new_stream(c->fc, NULL);
5107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (!st) return AVERROR(ENOMEM);
5108 594 st->id = -1;
5109 594 sc = av_mallocz(sizeof(MOVStreamContext));
5110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (!sc) return AVERROR(ENOMEM);
5111
5112 594 st->priv_data = sc;
5113 594 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5114 594 sc->ffindex = st->index;
5115 594 c->trak_index = st->index;
5116 594 sc->tref_flags = 0;
5117 594 sc->tref_id = -1;
5118 594 sc->refcount = 1;
5119
5120
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 594 times.
594 if ((ret = mov_read_default(c, pb, atom)) < 0)
5121 return ret;
5122
5123 594 c->trak_index = -1;
5124
5125 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5126 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5127
5/6
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 578 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 15 times.
594 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
5128 1 sc->stsc_count = 0;
5129 1 av_freep(&sc->stsc_data);
5130 }
5131
5132 594 ret = sanity_checks(c->fc, sc, st->index);
5133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (ret)
5134 return ret > 1 ? AVERROR_INVALIDDATA : 0;
5135
5136 594 fix_timescale(c, sc);
5137
5138 594 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5139
5140 /*
5141 * Advanced edit list support does not work with fragemented MP4s, which
5142 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5143 * In these files, trun atoms may be streamed in.
5144 */
5145
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 578 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 4 times.
594 if (!sc->stts_count && c->advanced_editlist) {
5146
5147 12 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5148 "MP4. disabling.\n");
5149 12 c->advanced_editlist = 0;
5150 12 c->advanced_editlist_autodisabled = 1;
5151 }
5152
5153 594 mov_build_index(c, st);
5154
5155 #if CONFIG_IAMFDEC
5156
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 584 times.
594 if (sc->iamf) {
5157 10 ret = mov_update_iamf_streams(c, st);
5158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
5159 return ret;
5160 }
5161 #endif
5162
5163
3/4
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 593 times.
594 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
5164 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5165 if (c->enable_drefs) {
5166 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5167 av_log(c->fc, AV_LOG_ERROR,
5168 "stream %d, error opening alias: path='%s', dir='%s', "
5169 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5170 st->index, dref->path, dref->dir, dref->filename,
5171 dref->volume, dref->nlvl_from, dref->nlvl_to);
5172 } else {
5173 av_log(c->fc, AV_LOG_WARNING,
5174 "Skipped opening external track: "
5175 "stream %d, alias: path='%s', dir='%s', "
5176 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5177 "Set enable_drefs to allow this.\n",
5178 st->index, dref->path, dref->dir, dref->filename,
5179 dref->volume, dref->nlvl_from, dref->nlvl_to);
5180 }
5181 } else {
5182 594 sc->pb = c->fc->pb;
5183 594 sc->pb_is_copied = 1;
5184 }
5185
5186
2/2
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 292 times.
594 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5187
3/4
✓ Branch 0 taken 292 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 292 times.
✗ Branch 3 not taken.
302 int stts_constant = sc->stts_count && sc->tts_count;
5188
3/4
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 244 times.
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
302 if (sc->h_spacing && sc->v_spacing)
5189 58 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5190 58 sc->h_spacing, sc->v_spacing, INT_MAX);
5191
4/6
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 61 times.
✓ Branch 2 taken 241 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 241 times.
✗ Branch 5 not taken.
302 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
5192
2/4
✓ Branch 0 taken 241 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241 times.
✗ Branch 3 not taken.
241 sc->height && sc->width &&
5193
2/4
✓ Branch 0 taken 241 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 241 times.
241 (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
5194 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5195 (int64_t)st->codecpar->height * sc->width,
5196 (int64_t)st->codecpar->width * sc->height, INT_MAX);
5197 }
5198
5199 #if FF_API_R_FRAME_RATE
5200
4/4
✓ Branch 0 taken 154827 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 154535 times.
✓ Branch 3 taken 292 times.
154837 for (unsigned int i = 1; sc->stts_count && i + 1 < sc->tts_count; i++) {
5201
2/2
✓ Branch 0 taken 152108 times.
✓ Branch 1 taken 2427 times.
154535 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5202 152108 continue;
5203 2427 stts_constant = 0;
5204 }
5205
2/2
✓ Branch 0 taken 278 times.
✓ Branch 1 taken 24 times.
302 if (stts_constant)
5206 278 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5207 278 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5208 #endif
5209 }
5210
5211 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
5212
3/4
✓ Branch 0 taken 263 times.
✓ Branch 1 taken 331 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 263 times.
594 if (!st->codecpar->extradata_size && st->codecpar->codec_id == AV_CODEC_ID_H264 &&
5213 TAG_IS_AVCI(st->codecpar->codec_tag)) {
5214 ret = ff_generate_avci_extradata(st);
5215 if (ret < 0)
5216 return ret;
5217 }
5218
5219
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 570 times.
594 switch (st->codecpar->codec_id) {
5220 #if CONFIG_H261_DECODER
5221 24 case AV_CODEC_ID_H261:
5222 #endif
5223 #if CONFIG_H263_DECODER
5224 case AV_CODEC_ID_H263:
5225 #endif
5226 #if CONFIG_MPEG4_DECODER
5227 case AV_CODEC_ID_MPEG4:
5228 #endif
5229 24 st->codecpar->width = 0; /* let decoder init width/height */
5230 24 st->codecpar->height= 0;
5231 24 break;
5232 }
5233
5234 // If the duration of the mp3 packets is not constant, then they could need a parser
5235
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 593 times.
594 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5236
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 && sc->time_scale == st->codecpar->sample_rate) {
5237 1 int stts_constant = 1;
5238
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++) {
5239
1/2
✓ Branch 0 taken 287 times.
✗ Branch 1 not taken.
287 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5240 287 continue;
5241 stts_constant = 0;
5242 }
5243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!stts_constant)
5244 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5245 }
5246 /* Do not need those anymore. */
5247 594 av_freep(&sc->chunk_offsets);
5248 594 av_freep(&sc->sample_sizes);
5249 594 av_freep(&sc->keyframes);
5250 594 av_freep(&sc->stps_data);
5251 594 av_freep(&sc->elst_data);
5252 594 av_freep(&sc->rap_group);
5253 594 av_freep(&sc->sync_group);
5254 594 av_freep(&sc->sgpd_sync);
5255
5256 594 return 0;
5257 }
5258
5259 125 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5260 {
5261 int ret;
5262 125 c->itunes_metadata = 1;
5263 125 ret = mov_read_default(c, pb, atom);
5264 125 c->itunes_metadata = 0;
5265 125 return ret;
5266 }
5267
5268 11 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5269 {
5270 uint32_t count;
5271 uint32_t i;
5272
5273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
5274 return 0;
5275
5276 11 avio_skip(pb, 4);
5277 11 count = avio_rb32(pb);
5278 11 atom.size -= 8;
5279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (count >= UINT_MAX / sizeof(*c->meta_keys)) {
5280 av_log(c->fc, AV_LOG_ERROR,
5281 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5282 return AVERROR_INVALIDDATA;
5283 }
5284
5285 11 c->meta_keys_count = count + 1;
5286 11 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
5287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!c->meta_keys)
5288 return AVERROR(ENOMEM);
5289
5290
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i <= count; ++i) {
5291 58 uint32_t key_size = avio_rb32(pb);
5292 58 uint32_t type = avio_rl32(pb);
5293
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) {
5294 av_log(c->fc, AV_LOG_ERROR,
5295 "The key# %"PRIu32" in meta has invalid size:"
5296 "%"PRIu32"\n", i, key_size);
5297 return AVERROR_INVALIDDATA;
5298 }
5299 58 atom.size -= key_size;
5300 58 key_size -= 8;
5301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (type != MKTAG('m','d','t','a')) {
5302 avio_skip(pb, key_size);
5303 continue;
5304 }
5305 58 c->meta_keys[i] = av_mallocz(key_size + 1);
5306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!c->meta_keys[i])
5307 return AVERROR(ENOMEM);
5308 58 avio_read(pb, c->meta_keys[i], key_size);
5309 }
5310
5311 11 return 0;
5312 }
5313
5314 65 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5315 {
5316 65 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5317 65 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5318 int i;
5319 65 int ret = 0;
5320 AVStream *st;
5321 MOVStreamContext *sc;
5322
5323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (c->fc->nb_streams < 1)
5324 return 0;
5325 65 st = c->fc->streams[c->fc->nb_streams-1];
5326 65 sc = st->priv_data;
5327
5328
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 65 times.
260 for (i = 0; i < 3; i++) {
5329 uint8_t **p;
5330 uint32_t len, tag;
5331
5332
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 195 times.
195 if (end - avio_tell(pb) <= 12)
5333 break;
5334
5335 195 len = avio_rb32(pb);
5336 195 tag = avio_rl32(pb);
5337 195 avio_skip(pb, 4); // flags
5338
5339
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))
5340 break;
5341 195 len -= 12;
5342
5343
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 130 times.
195 if (tag == MKTAG('m', 'e', 'a', 'n'))
5344 65 p = &mean;
5345
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 65 times.
130 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5346 65 p = &key;
5347
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) {
5348 65 avio_skip(pb, 4);
5349 65 len -= 4;
5350 65 p = &val;
5351 } else
5352 break;
5353
5354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (*p)
5355 break;
5356
5357 195 *p = av_malloc(len + 1);
5358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*p) {
5359 ret = AVERROR(ENOMEM);
5360 break;
5361 }
5362 195 ret = ffio_read_size(pb, *p, len);
5363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (ret < 0) {
5364 av_freep(p);
5365 break;
5366 }
5367 195 (*p)[len] = 0;
5368 }
5369
5370
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) {
5371
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 32 times.
65 if (strcmp(key, "iTunSMPB") == 0) {
5372 int priming, remainder, samples;
5373
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
5374
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)
5375 33 sc->start_pad = priming;
5376 }
5377 }
5378
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 10 times.
120 if (strcmp(key, "cdec") != 0) {
5379 55 av_dict_set(&c->fc->metadata, key, val,
5380 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5381 55 key = val = NULL;
5382 }
5383 } else {
5384 av_log(c->fc, AV_LOG_VERBOSE,
5385 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5386 }
5387
5388 65 avio_seek(pb, end, SEEK_SET);
5389 65 av_freep(&key);
5390 65 av_freep(&val);
5391 65 av_freep(&mean);
5392 65 return ret;
5393 }
5394
5395 23 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5396 {
5397 MOVStreamContext *sc;
5398 AVStream *st;
5399
5400 23 st = avformat_new_stream(c->fc, NULL);
5401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!st)
5402 return AVERROR(ENOMEM);
5403 23 sc = av_mallocz(sizeof(MOVStreamContext));
5404
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc)
5405 return AVERROR(ENOMEM);
5406
5407 23 item->st = st;
5408 23 st->id = item->item_id;
5409 23 st->priv_data = sc;
5410 23 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5411 23 st->codecpar->codec_id = mov_codec_id(st, item->type);
5412 23 sc->id = st->id;
5413 23 sc->ffindex = st->index;
5414 23 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5415 23 st->time_base.num = st->time_base.den = 1;
5416 23 st->nb_frames = 1;
5417 23 sc->time_scale = 1;
5418 23 sc->pb = c->fc->pb;
5419 23 sc->pb_is_copied = 1;
5420 23 sc->refcount = 1;
5421
5422
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 if (item->name)
5423 23 av_dict_set(&st->metadata, "title", item->name, 0);
5424
5425 // Populate the necessary fields used by mov_build_index.
5426 23 sc->stsc_count = 1;
5427 23 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc->stsc_data)
5429 return AVERROR(ENOMEM);
5430 23 sc->stsc_data[0].first = 1;
5431 23 sc->stsc_data[0].count = 1;
5432 23 sc->stsc_data[0].id = 1;
5433 23 sc->chunk_count = 1;
5434 23 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc->chunk_offsets)
5436 return AVERROR(ENOMEM);
5437 23 sc->sample_count = 1;
5438 23 sc->sample_sizes = av_malloc_array(1, sizeof(*sc->sample_sizes));
5439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc->sample_sizes)
5440 return AVERROR(ENOMEM);
5441 23 sc->stts_count = 1;
5442 23 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc->stts_data)
5444 return AVERROR(ENOMEM);
5445 23 sc->stts_data[0].count = 1;
5446 // Not used for still images. But needed by mov_build_index.
5447 23 sc->stts_data[0].duration = 0;
5448
5449 23 return 0;
5450 }
5451
5452 139 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5453 {
5454
1/2
✓ Branch 0 taken 403 times.
✗ Branch 1 not taken.
403 while (atom.size > 8) {
5455 uint32_t tag;
5456
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 403 times.
403 if (avio_feof(pb))
5457 return AVERROR_EOF;
5458 403 tag = avio_rl32(pb);
5459 403 atom.size -= 4;
5460
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 264 times.
403 if (tag == MKTAG('h','d','l','r')) {
5461 139 avio_seek(pb, -8, SEEK_CUR);
5462 139 atom.size += 8;
5463 139 return mov_read_default(c, pb, atom);
5464 }
5465 }
5466 return 0;
5467 }
5468
5469 // return 1 when matrix is identity, 0 otherwise
5470 #define IS_MATRIX_IDENT(matrix) \
5471 ( (matrix)[0][0] == (1 << 16) && \
5472 (matrix)[1][1] == (1 << 16) && \
5473 (matrix)[2][2] == (1 << 30) && \
5474 !(matrix)[0][1] && !(matrix)[0][2] && \
5475 !(matrix)[1][0] && !(matrix)[1][2] && \
5476 !(matrix)[2][0] && !(matrix)[2][1])
5477
5478 594 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5479 {
5480 int i, j, e;
5481 int width;
5482 int height;
5483 int display_matrix[3][3];
5484 594 int res_display_matrix[3][3] = { { 0 } };
5485 AVStream *st;
5486 MOVStreamContext *sc;
5487 int version;
5488 int flags;
5489
5490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
5491 return 0;
5492 594 st = c->fc->streams[c->fc->nb_streams-1];
5493 594 sc = st->priv_data;
5494
5495 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5496 // avoids corrupting AVStreams mapped to an earlier tkhd.
5497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (st->id != -1)
5498 return AVERROR_INVALIDDATA;
5499
5500 594 version = avio_r8(pb);
5501 594 flags = avio_rb24(pb);
5502 594 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5503
5504
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 585 times.
594 if (version == 1) {
5505 9 avio_rb64(pb);
5506 9 avio_rb64(pb);
5507 } else {
5508 585 avio_rb32(pb); /* creation time */
5509 585 avio_rb32(pb); /* modification time */
5510 }
5511 594 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5512 594 sc->id = st->id;
5513 594 avio_rb32(pb); /* reserved */
5514
5515 /* highlevel (considering edits) duration in movie timebase */
5516
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 585 times.
594 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5517 594 avio_rb32(pb); /* reserved */
5518 594 avio_rb32(pb); /* reserved */
5519
5520 594 avio_rb16(pb); /* layer */
5521 594 avio_rb16(pb); /* alternate group */
5522 594 avio_rb16(pb); /* volume */
5523 594 avio_rb16(pb); /* reserved */
5524
5525 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
5526 // they're kept in fixed point format through all calculations
5527 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
5528 // side data, but the scale factor is not needed to calculate aspect ratio
5529
2/2
✓ Branch 0 taken 1782 times.
✓ Branch 1 taken 594 times.
2376 for (i = 0; i < 3; i++) {
5530 1782 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
5531 1782 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
5532 1782 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
5533 }
5534
5535 594 width = avio_rb32(pb); // 16.16 fixed point track width
5536 594 height = avio_rb32(pb); // 16.16 fixed point track height
5537 594 sc->width = width >> 16;
5538 594 sc->height = height >> 16;
5539
5540 // apply the moov display matrix (after the tkhd one)
5541
2/2
✓ Branch 0 taken 1782 times.
✓ Branch 1 taken 594 times.
2376 for (i = 0; i < 3; i++) {
5542 1782 const int sh[3] = { 16, 16, 30 };
5543
2/2
✓ Branch 0 taken 5346 times.
✓ Branch 1 taken 1782 times.
7128 for (j = 0; j < 3; j++) {
5544
2/2
✓ Branch 0 taken 16038 times.
✓ Branch 1 taken 5346 times.
21384 for (e = 0; e < 3; e++) {
5545 16038 res_display_matrix[i][j] +=
5546 16038 ((int64_t) display_matrix[i][e] *
5547 16038 c->movie_display_matrix[e][j]) >> sh[e];
5548 }
5549 }
5550 }
5551
5552 // save the matrix when it is not the default identity
5553
10/18
✓ Branch 0 taken 585 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 585 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 585 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 585 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 585 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 585 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 585 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 585 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 585 times.
594 if (!IS_MATRIX_IDENT(res_display_matrix)) {
5554 9 av_freep(&sc->display_matrix);
5555 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
5556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
5557 return AVERROR(ENOMEM);
5558
5559
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
5560
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
5561 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
5562 }
5563
5564 // transform the display width/height according to the matrix
5565 // to keep the same scale, use [width height 1<<16]
5566
5/6
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 282 times.
✓ Branch 2 taken 312 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 304 times.
594 if (width && height && sc->display_matrix) {
5567 double disp_transform[2];
5568
5569
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
5570 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
5571 16 sc->display_matrix[3 + i]);
5572
5573
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 &&
5574
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) &&
5575
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
5576 3 st->sample_aspect_ratio = av_d2q(
5577 3 disp_transform[0] / disp_transform[1],
5578 INT_MAX);
5579 }
5580 594 return 0;
5581 }
5582
5583 388 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5584 {
5585 388 MOVFragment *frag = &c->fragment;
5586 388 MOVTrackExt *trex = NULL;
5587 int flags, track_id, i;
5588 MOVFragmentStreamInfo * frag_stream_info;
5589
5590 388 avio_r8(pb); /* version */
5591 388 flags = avio_rb24(pb);
5592
5593 388 track_id = avio_rb32(pb);
5594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!track_id)
5595 return AVERROR_INVALIDDATA;
5596
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < c->trex_count; i++)
5597
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (c->trex_data[i].track_id == track_id) {
5598 388 trex = &c->trex_data[i];
5599 388 break;
5600 }
5601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!trex) {
5602 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
5603 return 0;
5604 }
5605 388 c->fragment.found_tfhd = 1;
5606 388 frag->track_id = track_id;
5607 388 set_frag_stream(&c->frag_index, track_id);
5608
5609 776 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
5610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
776 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
5611
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 21 times.
388 frag->moof_offset : frag->implicit_offset;
5612
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;
5613
5614 776 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
5615
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 383 times.
388 avio_rb32(pb) : trex->duration;
5616 776 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
5617
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 382 times.
388 avio_rb32(pb) : trex->size;
5618 776 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
5619
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 365 times.
388 avio_rb32(pb) : trex->flags;
5620 388 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
5621
5622 388 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5623
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5624 388 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
5625 388 frag_stream_info->stsd_id = frag->stsd_id;
5626 }
5627 388 return 0;
5628 }
5629
5630 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5631 {
5632 unsigned i, num;
5633 void *new_tracks;
5634
5635 2 num = atom.size / 4;
5636
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
5637 return AVERROR(ENOMEM);
5638
5639 2 av_free(c->chapter_tracks);
5640 2 c->chapter_tracks = new_tracks;
5641 2 c->nb_chapter_tracks = num;
5642
5643
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++)
5644 2 c->chapter_tracks[i] = avio_rb32(pb);
5645
5646 2 c->nb_chapter_tracks = i;
5647
5648 2 return 0;
5649 }
5650
5651 17 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5652 {
5653 MOVTrackExt *trex;
5654 int err;
5655
5656
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))
5657 return AVERROR_INVALIDDATA;
5658
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
5659 sizeof(*c->trex_data))) < 0) {
5660 c->trex_count = 0;
5661 return err;
5662 }
5663
5664 17 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
5665
5666 17 trex = &c->trex_data[c->trex_count++];
5667 17 avio_r8(pb); /* version */
5668 17 avio_rb24(pb); /* flags */
5669 17 trex->track_id = avio_rb32(pb);
5670 17 trex->stsd_id = avio_rb32(pb);
5671 17 trex->duration = avio_rb32(pb);
5672 17 trex->size = avio_rb32(pb);
5673 17 trex->flags = avio_rb32(pb);
5674 17 return 0;
5675 }
5676
5677 367 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5678 {
5679 367 MOVFragment *frag = &c->fragment;
5680 367 AVStream *st = NULL;
5681 MOVStreamContext *sc;
5682 int version, i;
5683 MOVFragmentStreamInfo * frag_stream_info;
5684 int64_t base_media_decode_time;
5685
5686
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 for (i = 0; i < c->fc->nb_streams; i++) {
5687 367 sc = c->fc->streams[i]->priv_data;
5688
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 if (sc->id == frag->track_id) {
5689 367 st = c->fc->streams[i];
5690 367 break;
5691 }
5692 }
5693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367 times.
367 if (!st) {
5694 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5695 return 0;
5696 }
5697 367 sc = st->priv_data;
5698
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)
5699 return 0;
5700 367 version = avio_r8(pb);
5701 367 avio_rb24(pb); /* flags */
5702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367 times.
367 if (version) {
5703 base_media_decode_time = avio_rb64(pb);
5704 } else {
5705 367 base_media_decode_time = avio_rb32(pb);
5706 }
5707
5708 367 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5709
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 if (frag_stream_info)
5710 367 frag_stream_info->tfdt_dts = base_media_decode_time;
5711 367 sc->track_end = base_media_decode_time;
5712
5713 367 return 0;
5714 }
5715
5716 388 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5717 {
5718 388 MOVFragment *frag = &c->fragment;
5719 388 AVStream *st = NULL;
5720 388 FFStream *sti = NULL;
5721 MOVStreamContext *sc;
5722 MOVTimeToSample *tts_data;
5723 uint64_t offset;
5724 388 int64_t dts, pts = AV_NOPTS_VALUE;
5725 388 int data_offset = 0;
5726 388 unsigned entries, first_sample_flags = frag->flags;
5727 int flags, distance, i;
5728 388 int64_t prev_dts = AV_NOPTS_VALUE;
5729 388 int next_frag_index = -1, index_entry_pos;
5730 size_t requested_size;
5731 size_t old_allocated_size;
5732 AVIndexEntry *new_entries;
5733 MOVFragmentStreamInfo * frag_stream_info;
5734
5735
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!frag->found_tfhd) {
5736 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
5737 return AVERROR_INVALIDDATA;
5738 }
5739
5740
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < c->fc->nb_streams; i++) {
5741 394 sc = c->fc->streams[i]->priv_data;
5742
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (sc->id == frag->track_id) {
5743 388 st = c->fc->streams[i];
5744 388 sti = ffstream(st);
5745 388 break;
5746 }
5747 }
5748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!st) {
5749 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5750 return 0;
5751 }
5752 388 sc = st->priv_data;
5753
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)
5754 return 0;
5755
5756 // Find the next frag_index index that has a valid index_entry for
5757 // the current track_id.
5758 //
5759 // A valid index_entry means the trun for the fragment was read
5760 // and it's samples are in index_entries at the given position.
5761 // New index entries will be inserted before the index_entry found.
5762 388 index_entry_pos = sti->nb_index_entries;
5763
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++) {
5764 1621 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
5765
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) {
5766 next_frag_index = i;
5767 index_entry_pos = frag_stream_info->index_entry;
5768 break;
5769 }
5770 }
5771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 av_assert0(index_entry_pos <= sti->nb_index_entries);
5772
5773 388 avio_r8(pb); /* version */
5774 388 flags = avio_rb24(pb);
5775 388 entries = avio_rb32(pb);
5776 388 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
5777
5778
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))
5779 return AVERROR_INVALIDDATA;
5780
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
5781
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);
5782
5783 388 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5784
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
5786 dts = frag_stream_info->next_trun_dts - sc->time_offset;
5787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5788 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
5789 pts = frag_stream_info->first_tfra_pts;
5790 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5791 ", using it for pts\n", pts);
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_DTS) {
5794 dts = frag_stream_info->first_tfra_pts;
5795 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5796 ", using it for dts\n", pts);
5797 } else {
5798 388 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
5799 388 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
5800
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;
5801
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;
5802
5803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (fallback_sidx) {
5804 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
5805 }
5806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (fallback_tfdt) {
5807 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
5808 }
5809
5810
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) {
5811 367 dts = frag_stream_info->tfdt_dts - sc->time_offset;
5812 367 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
5813 ", using it for dts\n", dts);
5814
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) {
5815 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
5816 // pts = frag_stream_info->sidx_pts;
5817 dts = frag_stream_info->sidx_pts - sc->time_offset;
5818 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
5819 ", using it for dts\n", frag_stream_info->sidx_pts);
5820 } else {
5821 21 dts = sc->track_end - sc->time_offset;
5822 21 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5823 ", using it for dts\n", dts);
5824 }
5825 }
5826 } else {
5827 dts = sc->track_end - sc->time_offset;
5828 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5829 ", using it for dts\n", dts);
5830 }
5831 388 offset = frag->base_data_offset + data_offset;
5832 388 distance = 0;
5833 388 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
5834
5835 // realloc space for new index entries
5836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
5837 entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
5838 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
5839 }
5840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (entries == 0)
5841 return 0;
5842
5843 388 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
5844 388 new_entries = av_fast_realloc(sti->index_entries,
5845 &sti->index_entries_allocated_size,
5846 requested_size);
5847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!new_entries)
5848 return AVERROR(ENOMEM);
5849 388 sti->index_entries= new_entries;
5850
5851 388 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
5852 388 old_allocated_size = sc->tts_allocated_size;
5853 388 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
5854 requested_size);
5855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!tts_data)
5856 return AVERROR(ENOMEM);
5857 388 sc->tts_data = tts_data;
5858
5859 // In case there were samples without time to sample entries, ensure they get
5860 // zero valued entries. This ensures clips which mix boxes with and
5861 // without time to sample entries don't pickup uninitialized data.
5862 388 memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0,
5863 388 sc->tts_allocated_size - old_allocated_size);
5864
5865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (index_entry_pos < sti->nb_index_entries) {
5866 // Make hole in index_entries and tts_data for new samples
5867 memmove(sti->index_entries + index_entry_pos + entries,
5868 sti->index_entries + index_entry_pos,
5869 sizeof(*sti->index_entries) *
5870 (sti->nb_index_entries - index_entry_pos));
5871 memmove(sc->tts_data + index_entry_pos + entries,
5872 sc->tts_data + index_entry_pos,
5873 sizeof(*sc->tts_data) * (sc->tts_count - index_entry_pos));
5874 if (index_entry_pos < sc->current_sample) {
5875 sc->current_sample += entries;
5876 }
5877 }
5878
5879 388 sti->nb_index_entries += entries;
5880 388 sc->tts_count = sti->nb_index_entries;
5881 388 sc->stts_count = sti->nb_index_entries;
5882
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 28 times.
388 if (flags & MOV_TRUN_SAMPLE_CTS)
5883 360 sc->ctts_count = sti->nb_index_entries;
5884
5885 // Record the index_entry position in frag_index of this fragment
5886
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5887 388 frag_stream_info->index_entry = index_entry_pos;
5888
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info->index_base < 0)
5889 388 frag_stream_info->index_base = index_entry_pos;
5890 }
5891
5892
2/2
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 14 times.
388 if (index_entry_pos > 0)
5893 374 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
5894
5895
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++) {
5896 6066 unsigned sample_size = frag->size;
5897
2/2
✓ Branch 0 taken 5678 times.
✓ Branch 1 taken 388 times.
6066 int sample_flags = i ? frag->flags : first_sample_flags;
5898 6066 unsigned sample_duration = frag->duration;
5899 6066 unsigned ctts_duration = 0;
5900 6066 int keyframe = 0;
5901 6066 int index_entry_flags = 0;
5902
5903
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 5594 times.
6066 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
5904
2/2
✓ Branch 0 taken 6034 times.
✓ Branch 1 taken 32 times.
6066 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
5905
2/2
✓ Branch 0 taken 933 times.
✓ Branch 1 taken 5133 times.
6066 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
5906
2/2
✓ Branch 0 taken 5400 times.
✓ Branch 1 taken 666 times.
6066 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
5907
5908 6066 mov_update_dts_shift(sc, ctts_duration, c->fc);
5909
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6066 times.
6066 if (pts != AV_NOPTS_VALUE) {
5910 dts = pts - sc->dts_shift;
5911 if (flags & MOV_TRUN_SAMPLE_CTS) {
5912 dts -= ctts_duration;
5913 } else {
5914 dts -= sc->time_offset;
5915 }
5916 av_log(c->fc, AV_LOG_DEBUG,
5917 "pts %"PRId64" calculated dts %"PRId64
5918 " sc->dts_shift %d ctts.duration %d"
5919 " sc->time_offset %"PRId64
5920 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
5921 pts, dts,
5922 sc->dts_shift, ctts_duration,
5923 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
5924 pts = AV_NOPTS_VALUE;
5925 }
5926
5927 6066 keyframe =
5928 6066 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
5929 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
5930
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 5666 times.
6066 if (keyframe) {
5931 400 distance = 0;
5932 400 index_entry_flags |= AVINDEX_KEYFRAME;
5933 }
5934 // Fragments can overlap in time. Discard overlapping frames after
5935 // decoding.
5936
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6042 times.
6066 if (prev_dts >= dts)
5937 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
5938
5939 6066 sti->index_entries[index_entry_pos].pos = offset;
5940 6066 sti->index_entries[index_entry_pos].timestamp = dts;
5941 6066 sti->index_entries[index_entry_pos].size = sample_size;
5942 6066 sti->index_entries[index_entry_pos].min_distance = distance;
5943 6066 sti->index_entries[index_entry_pos].flags = index_entry_flags;
5944
5945 6066 sc->tts_data[index_entry_pos].count = 1;
5946 6066 sc->tts_data[index_entry_pos].offset = ctts_duration;
5947 6066 sc->tts_data[index_entry_pos].duration = sample_duration;
5948 6066 index_entry_pos++;
5949
5950 6066 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
5951 "size %u, distance %d, keyframe %d\n", st->index,
5952 index_entry_pos, offset, dts, sample_size, distance, keyframe);
5953 6066 distance++;
5954
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6066 times.
6066 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
5955 return AVERROR_INVALIDDATA;
5956
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6066 times.
6066 if (!sample_size)
5957 return AVERROR_INVALIDDATA;
5958 6066 dts += sample_duration;
5959 6066 offset += sample_size;
5960 6066 sc->data_size += sample_size;
5961
5962
1/2
✓ Branch 0 taken 6066 times.
✗ Branch 1 not taken.
6066 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
5963
1/2
✓ Branch 0 taken 6066 times.
✗ Branch 1 not taken.
6066 1 <= INT_MAX - sc->nb_frames_for_fps
5964 ) {
5965 6066 sc->duration_for_fps += sample_duration;
5966 6066 sc->nb_frames_for_fps ++;
5967 }
5968 }
5969
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info)
5970 388 frag_stream_info->next_trun_dts = dts + sc->time_offset;
5971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (i < entries) {
5972 // EOF found before reading all entries. Fix the hole this would
5973 // leave in index_entries and tts_data
5974 int gap = entries - i;
5975 memmove(sti->index_entries + index_entry_pos,
5976 sti->index_entries + index_entry_pos + gap,
5977 sizeof(*sti->index_entries) *
5978 (sti->nb_index_entries - (index_entry_pos + gap)));
5979 memmove(sc->tts_data + index_entry_pos,
5980 sc->tts_data + index_entry_pos + gap,
5981 sizeof(*sc->tts_data) *
5982 (sc->tts_count - (index_entry_pos + gap)));
5983
5984 sti->nb_index_entries -= gap;
5985 sc->tts_count -= gap;
5986 if (index_entry_pos < sc->current_sample) {
5987 sc->current_sample -= gap;
5988 }
5989 entries = i;
5990 }
5991
5992 // The end of this new fragment may overlap in time with the start
5993 // of the next fragment in index_entries. Mark the samples in the next
5994 // fragment that overlap with AVINDEX_DISCARD_FRAME
5995 388 prev_dts = AV_NOPTS_VALUE;
5996
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (index_entry_pos > 0)
5997 388 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
5998
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
5999 if (prev_dts < sti->index_entries[i].timestamp)
6000 break;
6001 sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6002 }
6003
6004 // If a hole was created to insert the new index_entries into,
6005 // the index_entry recorded for all subsequent moof must
6006 // be incremented by the number of entries inserted.
6007 388 fix_frag_index_entries(&c->frag_index, next_frag_index,
6008 388 frag->track_id, entries);
6009
6010
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (pb->eof_reached) {
6011 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6012 return AVERROR_EOF;
6013 }
6014
6015 388 frag->implicit_offset = offset;
6016
6017 388 sc->track_end = dts + sc->time_offset;
6018
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 379 times.
388 if (st->duration < sc->track_end)
6019 9 st->duration = sc->track_end;
6020
6021 388 return 0;
6022 }
6023
6024 43 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6025 {
6026 43 int64_t stream_size = avio_size(pb);
6027 43 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6028 uint8_t version, is_complete;
6029 int64_t offadd;
6030 unsigned i, j, track_id, item_count;
6031 43 AVStream *st = NULL;
6032 43 AVStream *ref_st = NULL;
6033 43 MOVStreamContext *sc, *ref_sc = NULL;
6034 AVRational timescale;
6035
6036 43 version = avio_r8(pb);
6037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (version > 1) {
6038 avpriv_request_sample(c->fc, "sidx version %u", version);
6039 return 0;
6040 }
6041
6042 43 avio_rb24(pb); // flags
6043
6044 43 track_id = avio_rb32(pb); // Reference ID
6045
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 for (i = 0; i < c->fc->nb_streams; i++) {
6046 43 sc = c->fc->streams[i]->priv_data;
6047
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (sc->id == track_id) {
6048 43 st = c->fc->streams[i];
6049 43 break;
6050 }
6051 }
6052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st) {
6053 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6054 return 0;
6055 }
6056
6057 43 sc = st->priv_data;
6058
6059 43 timescale = av_make_q(1, avio_rb32(pb));
6060
6061
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (timescale.den <= 0) {
6062 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6063 return AVERROR_INVALIDDATA;
6064 }
6065
6066
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (version == 0) {
6067 43 pts = avio_rb32(pb);
6068 43 offadd= avio_rb32(pb);
6069 } else {
6070 pts = avio_rb64(pb);
6071 offadd= avio_rb64(pb);
6072 }
6073
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6074 return AVERROR_INVALIDDATA;
6075
6076 43 offset += (uint64_t)offadd;
6077
6078 43 avio_rb16(pb); // reserved
6079
6080 43 item_count = avio_rb16(pb);
6081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (item_count == 0)
6082 return AVERROR_INVALIDDATA;
6083
6084
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 43 times.
411 for (i = 0; i < item_count; i++) {
6085 int index;
6086 MOVFragmentStreamInfo * frag_stream_info;
6087 368 uint32_t size = avio_rb32(pb);
6088 368 uint32_t duration = avio_rb32(pb);
6089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 368 times.
368 if (size & 0x80000000) {
6090 avpriv_request_sample(c->fc, "sidx reference_type 1");
6091 return AVERROR_PATCHWELCOME;
6092 }
6093 368 avio_rb32(pb); // sap_flags
6094 368 timestamp = av_rescale_q(pts, timescale, st->time_base);
6095
6096 368 index = update_frag_index(c, offset);
6097 368 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6098
1/2
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
368 if (frag_stream_info)
6099 368 frag_stream_info->sidx_pts = timestamp;
6100
6101
1/2
✓ Branch 1 taken 368 times.
✗ Branch 2 not taken.
368 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6102
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 368 times.
368 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6103 )
6104 return AVERROR_INVALIDDATA;
6105 368 offset += size;
6106 368 pts += duration;
6107 }
6108
6109 43 st->duration = sc->track_end = pts;
6110
6111 43 sc->has_sidx = 1;
6112
6113 // See if the remaining bytes are just an mfra which we can ignore.
6114 43 is_complete = offset == stream_size;
6115
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 ) {
6116 int64_t ret;
6117 38 int64_t original_pos = avio_tell(pb);
6118
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
38 if (!c->have_read_mfra_size) {
6119
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6120 return ret;
6121 3 c->mfra_size = avio_rb32(pb);
6122 3 c->have_read_mfra_size = 1;
6123
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6124 return ret;
6125 }
6126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (offset == stream_size - c->mfra_size)
6127 is_complete = 1;
6128 }
6129
6130
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 38 times.
43 if (is_complete) {
6131 // Find first entry in fragment index that came from an sidx.
6132 // This will pretty much always be the first entry.
6133
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 5 times.
373 for (i = 0; i < c->frag_index.nb_items; i++) {
6134 368 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6135
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++) {
6136 MOVFragmentStreamInfo * si;
6137 5 si = &item->stream_info[j];
6138
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (si->sidx_pts != AV_NOPTS_VALUE) {
6139 5 ref_st = c->fc->streams[j];
6140 5 ref_sc = ref_st->priv_data;
6141 5 break;
6142 }
6143 }
6144 }
6145
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++) {
6146 5 st = c->fc->streams[i];
6147 5 sc = st->priv_data;
6148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->has_sidx) {
6149 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6150 }
6151 }
6152
6153 5 c->frag_index.complete = 1;
6154 }
6155
6156 43 return 0;
6157 }
6158
6159 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6160 /* like the files created with Adobe Premiere 5.0, for samples see */
6161 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6162 267 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6163 {
6164 int err;
6165
6166
1/2
✓ Branch 0 taken 267 times.
✗ Branch 1 not taken.
267 if (atom.size < 8)
6167 267 return 0; /* continue */
6168 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6169 avio_skip(pb, atom.size - 4);
6170 return 0;
6171 }
6172 atom.type = avio_rl32(pb);
6173 atom.size -= 8;
6174 if (atom.type != MKTAG('m','d','a','t')) {
6175 avio_skip(pb, atom.size);
6176 return 0;
6177 }
6178 err = mov_read_mdat(c, pb, atom);
6179 return err;
6180 }
6181
6182 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6183 {
6184 #if CONFIG_ZLIB
6185 FFIOContext ctx;
6186 uint8_t *cmov_data;
6187 uint8_t *moov_data; /* uncompressed data */
6188 long cmov_len, moov_len;
6189 3 int ret = -1;
6190
6191 3 avio_rb32(pb); /* dcom atom */
6192
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6193 return AVERROR_INVALIDDATA;
6194
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6195 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6196 return AVERROR_INVALIDDATA;
6197 }
6198 3 avio_rb32(pb); /* cmvd atom */
6199
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6200 return AVERROR_INVALIDDATA;
6201 3 moov_len = avio_rb32(pb); /* uncompressed size */
6202 3 cmov_len = atom.size - 6 * 4;
6203
6204 3 cmov_data = av_malloc(cmov_len);
6205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6206 return AVERROR(ENOMEM);
6207 3 moov_data = av_malloc(moov_len);
6208
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6209 av_free(cmov_data);
6210 return AVERROR(ENOMEM);
6211 }
6212 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6214 goto free_and_return;
6215
6216 3 ret = AVERROR_INVALIDDATA;
6217
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)
6218 goto free_and_return;
6219 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6220 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6221 3 atom.type = MKTAG('m','o','o','v');
6222 3 atom.size = moov_len;
6223 3 ret = mov_read_default(c, &ctx.pub, atom);
6224 3 free_and_return:
6225 3 av_free(moov_data);
6226 3 av_free(cmov_data);
6227 3 return ret;
6228 #else
6229 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6230 return AVERROR(ENOSYS);
6231 #endif
6232 }
6233
6234 /* edit list atom */
6235 439 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6236 {
6237 MOVStreamContext *sc;
6238 int i, edit_count, version;
6239 int64_t elst_entry_size;
6240
6241
2/4
✓ Branch 0 taken 439 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 439 times.
439 if (c->fc->nb_streams < 1 || c->ignore_editlist)
6242 return 0;
6243 439 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6244
6245 439 version = avio_r8(pb); /* version */
6246 439 avio_rb24(pb); /* flags */
6247 439 edit_count = avio_rb32(pb); /* entries */
6248 439 atom.size -= 8;
6249
6250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
439 elst_entry_size = version == 1 ? 20 : 12;
6251
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 438 times.
439 if (atom.size != edit_count * elst_entry_size) {
6252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6253 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6254 edit_count, atom.size + 8);
6255 return AVERROR_INVALIDDATA;
6256 } else {
6257 1 edit_count = atom.size / elst_entry_size;
6258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6259 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6260 }
6261 }
6262 }
6263
6264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
439 if (!edit_count)
6265 return 0;
6266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
439 if (sc->elst_data)
6267 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6268 439 av_free(sc->elst_data);
6269 439 sc->elst_count = 0;
6270 439 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
439 if (!sc->elst_data)
6272 return AVERROR(ENOMEM);
6273
6274 439 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6275
4/6
✓ Branch 0 taken 466 times.
✓ Branch 1 taken 439 times.
✓ Branch 2 taken 466 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 466 times.
✗ Branch 5 not taken.
905 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
6276 466 MOVElst *e = &sc->elst_data[i];
6277
6278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 466 times.
466 if (version == 1) {
6279 e->duration = avio_rb64(pb);
6280 e->time = avio_rb64(pb);
6281 atom.size -= 16;
6282 } else {
6283 466 e->duration = avio_rb32(pb); /* segment duration */
6284 466 e->time = (int32_t)avio_rb32(pb); /* media time */
6285 466 atom.size -= 8;
6286 }
6287 466 e->rate = avio_rb32(pb) / 65536.0;
6288 466 atom.size -= 4;
6289 466 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6290 466 e->duration, e->time, e->rate);
6291
6292
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 462 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
466 if (e->time < 0 && e->time != -1 &&
6293 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6294 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6295 c->fc->nb_streams-1, i, e->time);
6296 return AVERROR_INVALIDDATA;
6297 }
6298 }
6299 439 sc->elst_count = i;
6300
6301 439 return 0;
6302 }
6303
6304 18 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6305 {
6306 MOVStreamContext *sc;
6307
6308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->fc->nb_streams < 1)
6309 return AVERROR_INVALIDDATA;
6310 18 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6311 18 sc->timecode_track = avio_rb32(pb);
6312 18 return 0;
6313 }
6314
6315 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6316 {
6317 AVStream *st;
6318 int version, color_range, color_primaries, color_trc, color_space;
6319
6320 if (c->fc->nb_streams < 1)
6321 return 0;
6322 st = c->fc->streams[c->fc->nb_streams - 1];
6323
6324 if (atom.size < 5) {
6325 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6326 return AVERROR_INVALIDDATA;
6327 }
6328
6329 version = avio_r8(pb);
6330 if (version != 1) {
6331 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6332 return 0;
6333 }
6334 avio_skip(pb, 3); /* flags */
6335
6336 avio_skip(pb, 2); /* profile + level */
6337 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6338 color_primaries = avio_r8(pb);
6339 color_trc = avio_r8(pb);
6340 color_space = avio_r8(pb);
6341 if (avio_rb16(pb)) /* codecIntializationDataSize */
6342 return AVERROR_INVALIDDATA;
6343
6344 if (!av_color_primaries_name(color_primaries))
6345 color_primaries = AVCOL_PRI_UNSPECIFIED;
6346 if (!av_color_transfer_name(color_trc))
6347 color_trc = AVCOL_TRC_UNSPECIFIED;
6348 if (!av_color_space_name(color_space))
6349 color_space = AVCOL_SPC_UNSPECIFIED;
6350
6351 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6352 st->codecpar->color_primaries = color_primaries;
6353 st->codecpar->color_trc = color_trc;
6354 st->codecpar->color_space = color_space;
6355
6356 return 0;
6357 }
6358
6359 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6360 {
6361 MOVStreamContext *sc;
6362 int i, version;
6363
6364 if (c->fc->nb_streams < 1)
6365 return AVERROR_INVALIDDATA;
6366
6367 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6368
6369 if (atom.size < 5) {
6370 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6371 return AVERROR_INVALIDDATA;
6372 }
6373
6374 version = avio_r8(pb);
6375 if (version) {
6376 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6377 return 0;
6378 }
6379 if (sc->mastering) {
6380 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6381 return 0;
6382 }
6383
6384 avio_skip(pb, 3); /* flags */
6385
6386 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6387 if (!sc->mastering)
6388 return AVERROR(ENOMEM);
6389
6390 for (i = 0; i < 3; i++) {
6391 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6392 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6393 }
6394 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6395 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6396
6397 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6398 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6399
6400 sc->mastering->has_primaries = 1;
6401 sc->mastering->has_luminance = 1;
6402
6403 return 0;
6404 }
6405
6406 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6407 {
6408 MOVStreamContext *sc;
6409 const int mapping[3] = {1, 2, 0};
6410 const int chroma_den = 50000;
6411 const int luma_den = 10000;
6412 int i;
6413
6414 if (c->fc->nb_streams < 1)
6415 return AVERROR_INVALIDDATA;
6416
6417 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6418
6419 if (atom.size < 24) {
6420 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6421 return AVERROR_INVALIDDATA;
6422 }
6423
6424 if (sc->mastering) {
6425 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6426 return 0;
6427 }
6428
6429 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6430 if (!sc->mastering)
6431 return AVERROR(ENOMEM);
6432
6433 for (i = 0; i < 3; i++) {
6434 const int j = mapping[i];
6435 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6436 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6437 }
6438 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6439 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6440
6441 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6442 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6443
6444 sc->mastering->has_luminance = 1;
6445 sc->mastering->has_primaries = 1;
6446
6447 return 0;
6448 }
6449
6450 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6451 {
6452 MOVStreamContext *sc;
6453 int version;
6454
6455 if (c->fc->nb_streams < 1)
6456 return AVERROR_INVALIDDATA;
6457
6458 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6459
6460 if (atom.size < 5) {
6461 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
6462 return AVERROR_INVALIDDATA;
6463 }
6464
6465 version = avio_r8(pb);
6466 if (version) {
6467 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
6468 return 0;
6469 }
6470 avio_skip(pb, 3); /* flags */
6471
6472 if (sc->coll){
6473 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
6474 return 0;
6475 }
6476
6477 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6478 if (!sc->coll)
6479 return AVERROR(ENOMEM);
6480
6481 sc->coll->MaxCLL = avio_rb16(pb);
6482 sc->coll->MaxFALL = avio_rb16(pb);
6483
6484 return 0;
6485 }
6486
6487 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6488 {
6489 MOVStreamContext *sc;
6490
6491 if (c->fc->nb_streams < 1)
6492 return AVERROR_INVALIDDATA;
6493
6494 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6495
6496 if (atom.size < 4) {
6497 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
6498 return AVERROR_INVALIDDATA;
6499 }
6500
6501 if (sc->coll){
6502 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
6503 return 0;
6504 }
6505
6506 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6507 if (!sc->coll)
6508 return AVERROR(ENOMEM);
6509
6510 sc->coll->MaxCLL = avio_rb16(pb);
6511 sc->coll->MaxFALL = avio_rb16(pb);
6512
6513 return 0;
6514 }
6515
6516 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6517 {
6518 MOVStreamContext *sc;
6519 4 const int illuminance_den = 10000;
6520 4 const int ambient_den = 50000;
6521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
6522 return AVERROR_INVALIDDATA;
6523 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
6525 av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
6526 return AVERROR_INVALIDDATA;
6527 }
6528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
6529 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
6530 return 0;
6531 }
6532 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
6533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
6534 return AVERROR(ENOMEM);
6535 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
6536 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
6537 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
6538 4 return 0;
6539 }
6540
6541 1 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6542 {
6543 AVStream *st;
6544 MOVStreamContext *sc;
6545 enum AVStereo3DType type;
6546 int mode;
6547
6548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6549 return 0;
6550
6551 1 st = c->fc->streams[c->fc->nb_streams - 1];
6552 1 sc = st->priv_data;
6553
6554
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 5) {
6555 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
6556 return AVERROR_INVALIDDATA;
6557 }
6558
6559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sc->stereo3d)
6560 return AVERROR_INVALIDDATA;
6561
6562 1 avio_skip(pb, 4); /* version + flags */
6563
6564 1 mode = avio_r8(pb);
6565
1/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 switch (mode) {
6566 1 case 0:
6567 1 type = AV_STEREO3D_2D;
6568 1 break;
6569 case 1:
6570 type = AV_STEREO3D_TOPBOTTOM;
6571 break;
6572 case 2:
6573 type = AV_STEREO3D_SIDEBYSIDE;
6574 break;
6575 default:
6576 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
6577 return 0;
6578 }
6579
6580 1 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->stereo3d)
6582 return AVERROR(ENOMEM);
6583
6584 1 sc->stereo3d->type = type;
6585 1 return 0;
6586 }
6587
6588 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6589 {
6590 AVStream *st;
6591 MOVStreamContext *sc;
6592 int size, version, layout;
6593 int32_t yaw, pitch, roll;
6594 1 uint32_t l = 0, t = 0, r = 0, b = 0;
6595 1 uint32_t tag, padding = 0;
6596 enum AVSphericalProjection projection;
6597
6598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6599 return 0;
6600
6601 1 st = c->fc->streams[c->fc->nb_streams - 1];
6602 1 sc = st->priv_data;
6603
6604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
6605 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
6606 return AVERROR_INVALIDDATA;
6607 }
6608
6609 1 size = avio_rb32(pb);
6610
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)
6611 return AVERROR_INVALIDDATA;
6612
6613 1 tag = avio_rl32(pb);
6614
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
6615 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
6616 return 0;
6617 }
6618 1 version = avio_r8(pb);
6619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6620 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6621 version);
6622 return 0;
6623 }
6624 1 avio_skip(pb, 3); /* flags */
6625 1 avio_skip(pb, size - 12); /* metadata_source */
6626
6627 1 size = avio_rb32(pb);
6628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6629 return AVERROR_INVALIDDATA;
6630
6631 1 tag = avio_rl32(pb);
6632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
6633 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
6634 return 0;
6635 }
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','h','d')) {
6643 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
6644 return 0;
6645 }
6646 1 version = avio_r8(pb);
6647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6648 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6649 version);
6650 return 0;
6651 }
6652 1 avio_skip(pb, 3); /* flags */
6653
6654 /* 16.16 fixed point */
6655 1 yaw = avio_rb32(pb);
6656 1 pitch = avio_rb32(pb);
6657 1 roll = avio_rb32(pb);
6658
6659 1 size = avio_rb32(pb);
6660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6661 return AVERROR_INVALIDDATA;
6662
6663 1 tag = avio_rl32(pb);
6664 1 version = avio_r8(pb);
6665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6666 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6667 version);
6668 return 0;
6669 }
6670 1 avio_skip(pb, 3); /* flags */
6671
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
6672 case MKTAG('c','b','m','p'):
6673 layout = avio_rb32(pb);
6674 if (layout) {
6675 av_log(c->fc, AV_LOG_WARNING,
6676 "Unsupported cubemap layout %d\n", layout);
6677 return 0;
6678 }
6679 projection = AV_SPHERICAL_CUBEMAP;
6680 padding = avio_rb32(pb);
6681 break;
6682 1 case MKTAG('e','q','u','i'):
6683 1 t = avio_rb32(pb);
6684 1 b = avio_rb32(pb);
6685 1 l = avio_rb32(pb);
6686 1 r = avio_rb32(pb);
6687
6688
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) {
6689 av_log(c->fc, AV_LOG_ERROR,
6690 "Invalid bounding rectangle coordinates "
6691 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
6692 return AVERROR_INVALIDDATA;
6693 }
6694
6695
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)
6696 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
6697 else
6698 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6699 1 break;
6700 default:
6701 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
6702 return 0;
6703 }
6704
6705 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
6707 return AVERROR(ENOMEM);
6708
6709 1 sc->spherical->projection = projection;
6710
6711 1 sc->spherical->yaw = yaw;
6712 1 sc->spherical->pitch = pitch;
6713 1 sc->spherical->roll = roll;
6714
6715 1 sc->spherical->padding = padding;
6716
6717 1 sc->spherical->bound_left = l;
6718 1 sc->spherical->bound_top = t;
6719 1 sc->spherical->bound_right = r;
6720 1 sc->spherical->bound_bottom = b;
6721
6722 1 return 0;
6723 }
6724
6725 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6726 {
6727 AVStream *st;
6728 MOVStreamContext *sc;
6729 int size;
6730 uint32_t tag;
6731 enum AVSphericalProjection projection;
6732
6733
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6734 return 0;
6735
6736 3 st = c->fc->streams[c->fc->nb_streams - 1];
6737 3 sc = st->priv_data;
6738
6739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 16) {
6740 av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
6741 return AVERROR_INVALIDDATA;
6742 }
6743
6744 3 size = avio_rb32(pb);
6745
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 16) {
6746 av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
6747 return AVERROR_INVALIDDATA;
6748 }
6749
6750 3 tag = avio_rl32(pb);
6751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
6752 av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: 0x%08X\n", tag);
6753 return AVERROR_INVALIDDATA;
6754 }
6755
6756 3 avio_skip(pb, 1); // version
6757 3 avio_skip(pb, 3); // flags
6758
6759 3 tag = avio_rl32(pb);
6760
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) {
6761 3 case MKTAG('r','e','c','t'):
6762 3 projection = AV_SPHERICAL_RECTILINEAR;
6763 3 break;
6764 case MKTAG('e','q','u','i'):
6765 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6766 break;
6767 case MKTAG('h','e','q','u'):
6768 projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
6769 break;
6770 case MKTAG('f','i','s','h'):
6771 projection = AV_SPHERICAL_FISHEYE;
6772 break;
6773 default:
6774 av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: 0x%08X\n", tag);
6775 return AVERROR_INVALIDDATA;
6776 }
6777
6778 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
6780 return AVERROR(ENOMEM);
6781
6782 3 sc->spherical->projection = projection;
6783
6784 3 return 0;
6785 }
6786
6787 3 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6788 {
6789 AVStream *st;
6790 MOVStreamContext *sc;
6791 3 int size, flags = 0;
6792 int64_t remaining;
6793 3 uint32_t tag, baseline = 0;
6794 3 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
6795 3 enum AVStereo3DType type = AV_STEREO3D_2D;
6796 3 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
6797 3 AVRational horizontal_disparity_adjustment = { 0, 1 };
6798
6799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6800 return 0;
6801
6802 3 st = c->fc->streams[c->fc->nb_streams - 1];
6803 3 sc = st->priv_data;
6804
6805 3 remaining = atom.size;
6806
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 while (remaining > 0) {
6807 9 size = avio_rb32(pb);
6808
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 ) {
6809 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
6810 return AVERROR_INVALIDDATA;
6811 }
6812
6813 9 tag = avio_rl32(pb);
6814
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) {
6815 3 case MKTAG('s','t','r','i'): {
6816 int has_right, has_left;
6817 uint8_t tmp;
6818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 13) {
6819 av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
6820 return AVERROR_INVALIDDATA;
6821 }
6822 3 avio_skip(pb, 1); // version
6823 3 avio_skip(pb, 3); // flags
6824
6825 3 tmp = avio_r8(pb);
6826
6827 // eye_views_reversed
6828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tmp & 8) {
6829 flags |= AV_STEREO3D_FLAG_INVERT;
6830 }
6831 // has_additional_views
6832 3 if (tmp & 4) {
6833 // skip...
6834 }
6835
6836 3 has_right = tmp & 2; // has_right_eye_view
6837 3 has_left = tmp & 1; // has_left_eye_view
6838
6839
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)
6840 3 view = AV_STEREO3D_VIEW_PACKED;
6841 else if (has_left)
6842 view = AV_STEREO3D_VIEW_LEFT;
6843 else if (has_right)
6844 view = AV_STEREO3D_VIEW_RIGHT;
6845
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)
6846 3 type = AV_STEREO3D_UNSPEC;
6847
6848 3 break;
6849 }
6850 case MKTAG('h','e','r','o'): {
6851 int tmp;
6852 if (size != 13) {
6853 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
6854 return AVERROR_INVALIDDATA;
6855 }
6856 avio_skip(pb, 1); // version
6857 avio_skip(pb, 3); // flags
6858
6859 tmp = avio_r8(pb);
6860 if (tmp == 0)
6861 primary_eye = AV_PRIMARY_EYE_NONE;
6862 else if (tmp == 1)
6863 primary_eye = AV_PRIMARY_EYE_LEFT;
6864 else if (tmp == 2)
6865 primary_eye = AV_PRIMARY_EYE_RIGHT;
6866 else
6867 av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
6868
6869 break;
6870 }
6871 3 case MKTAG('c','a','m','s'): {
6872 uint32_t subtag;
6873 int subsize;
6874
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
6875 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
6876 return AVERROR_INVALIDDATA;
6877 }
6878
6879 3 subsize = avio_rb32(pb);
6880
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
6881 av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
6882 return AVERROR_INVALIDDATA;
6883 }
6884
6885 3 subtag = avio_rl32(pb);
6886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
6887 av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got 0x%08X\n", subtag);
6888 return AVERROR_INVALIDDATA;
6889 }
6890
6891 3 avio_skip(pb, 1); // version
6892 3 avio_skip(pb, 3); // flags
6893
6894 3 baseline = avio_rb32(pb);
6895
6896 3 break;
6897 }
6898 3 case MKTAG('c','m','f','y'): {
6899 uint32_t subtag;
6900 int subsize;
6901 int32_t adjustment;
6902
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
6903 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
6904 return AVERROR_INVALIDDATA;
6905 }
6906
6907 3 subsize = avio_rb32(pb);
6908
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
6909 av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
6910 return AVERROR_INVALIDDATA;
6911 }
6912
6913 3 subtag = avio_rl32(pb);
6914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
6915 av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got 0x%08X\n", subtag);
6916 return AVERROR_INVALIDDATA;
6917 }
6918
6919 3 avio_skip(pb, 1); // version
6920 3 avio_skip(pb, 3); // flags
6921
6922 3 adjustment = (int32_t) avio_rb32(pb);
6923
6924 3 horizontal_disparity_adjustment.num = (int) adjustment;
6925 3 horizontal_disparity_adjustment.den = 10000;
6926
6927 3 break;
6928 }
6929 default:
6930 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: 0x%08X\n", tag);
6931 avio_skip(pb, size - 8);
6932 break;
6933 }
6934 9 remaining -= size;
6935 }
6936
6937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
6938 av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
6939 return AVERROR_INVALIDDATA;
6940 }
6941
6942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (type == AV_STEREO3D_2D)
6943 return 0;
6944
6945
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->stereo3d) {
6946 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
6948 return AVERROR(ENOMEM);
6949 }
6950
6951 3 sc->stereo3d->flags = flags;
6952 3 sc->stereo3d->type = type;
6953 3 sc->stereo3d->view = view;
6954 3 sc->stereo3d->primary_eye = primary_eye;
6955 3 sc->stereo3d->baseline = baseline;
6956 3 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
6957
6958 3 return 0;
6959 }
6960
6961 3 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6962 {
6963 int size;
6964 int64_t remaining;
6965 uint32_t tag;
6966
6967
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6968 return 0;
6969
6970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8) {
6971 av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
6972 return AVERROR_INVALIDDATA;
6973 }
6974
6975 3 remaining = atom.size;
6976
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 while (remaining > 0) {
6977 6 size = avio_rb32(pb);
6978
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 ) {
6979 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
6980 return AVERROR_INVALIDDATA;
6981 }
6982
6983 6 tag = avio_rl32(pb);
6984
2/3
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 switch (tag) {
6985 3 case MKTAG('p','r','o','j'): {
6986 3 MOVAtom proj = { tag, size - 8 };
6987 3 int ret = mov_read_vexu_proj(c, pb, proj);
6988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6989 return ret;
6990 3 break;
6991 }
6992 3 case MKTAG('e','y','e','s'): {
6993 3 MOVAtom eyes = { tag, size - 8 };
6994 3 int ret = mov_read_eyes(c, pb, eyes);
6995
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6996 return ret;
6997 3 break;
6998 }
6999 default:
7000 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: 0x%08X\n", tag);
7001 avio_skip(pb, size - 8);
7002 break;
7003 }
7004 6 remaining -= size;
7005 }
7006
7007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7008 av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7009 return AVERROR_INVALIDDATA;
7010 }
7011
7012 3 return 0;
7013 }
7014
7015 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7016 {
7017 AVStream *st;
7018 MOVStreamContext *sc;
7019
7020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7021 return 0;
7022
7023 3 st = c->fc->streams[c->fc->nb_streams - 1];
7024 3 sc = st->priv_data;
7025
7026
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7027 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7028 return AVERROR_INVALIDDATA;
7029 }
7030
7031
7032
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7033 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7034 if (!sc->stereo3d)
7035 return AVERROR(ENOMEM);
7036 }
7037
7038 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7039 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7040
7041 3 return 0;
7042 }
7043
7044 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7045 {
7046 int ret = 0;
7047 uint8_t *buffer = av_malloc(len + 1);
7048 const char *val;
7049
7050 if (!buffer)
7051 return AVERROR(ENOMEM);
7052 buffer[len] = '\0';
7053
7054 ret = ffio_read_size(pb, buffer, len);
7055 if (ret < 0)
7056 goto out;
7057
7058 /* Check for mandatory keys and values, try to support XML as best-effort */
7059 if (!sc->spherical &&
7060 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7061 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7062 av_stristr(val, "true") &&
7063 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7064 av_stristr(val, "true") &&
7065 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7066 av_stristr(val, "equirectangular")) {
7067 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7068 if (!sc->spherical)
7069 goto out;
7070
7071 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7072
7073 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7074 enum AVStereo3DType mode;
7075
7076 if (av_stristr(buffer, "left-right"))
7077 mode = AV_STEREO3D_SIDEBYSIDE;
7078 else if (av_stristr(buffer, "top-bottom"))
7079 mode = AV_STEREO3D_TOPBOTTOM;
7080 else
7081 mode = AV_STEREO3D_2D;
7082
7083 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7084 if (!sc->stereo3d)
7085 goto out;
7086
7087 sc->stereo3d->type = mode;
7088 }
7089
7090 /* orientation */
7091 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7092 if (val)
7093 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7094 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7095 if (val)
7096 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7097 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7098 if (val)
7099 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7100 }
7101
7102 out:
7103 av_free(buffer);
7104 return ret;
7105 }
7106
7107 15 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7108 {
7109 AVStream *st;
7110 MOVStreamContext *sc;
7111 int64_t ret;
7112 AVUUID uuid;
7113 static const AVUUID uuid_isml_manifest = {
7114 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7115 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7116 };
7117 static const AVUUID uuid_xmp = {
7118 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7119 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7120 };
7121 static const AVUUID uuid_spherical = {
7122 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7123 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7124 };
7125
7126
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))
7127 return AVERROR_INVALIDDATA;
7128
7129
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 14 times.
15 if (c->fc->nb_streams < 1)
7130 1 return 0;
7131 14 st = c->fc->streams[c->fc->nb_streams - 1];
7132 14 sc = st->priv_data;
7133
7134 14 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0)
7136 return ret;
7137
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7138 uint8_t *buffer, *ptr;
7139 char *endptr;
7140 size_t len = atom.size - AV_UUID_LEN;
7141
7142 if (len < 4) {
7143 return AVERROR_INVALIDDATA;
7144 }
7145 ret = avio_skip(pb, 4); // zeroes
7146 len -= 4;
7147
7148 buffer = av_mallocz(len + 1);
7149 if (!buffer) {
7150 return AVERROR(ENOMEM);
7151 }
7152 ret = ffio_read_size(pb, buffer, len);
7153 if (ret < 0) {
7154 av_free(buffer);
7155 return ret;
7156 }
7157
7158 ptr = buffer;
7159 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7160 ptr += sizeof("systemBitrate=\"") - 1;
7161 c->bitrates_count++;
7162 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7163 if (!c->bitrates) {
7164 c->bitrates_count = 0;
7165 av_free(buffer);
7166 return AVERROR(ENOMEM);
7167 }
7168 errno = 0;
7169 ret = strtol(ptr, &endptr, 10);
7170 if (ret < 0 || errno || *endptr != '"') {
7171 c->bitrates[c->bitrates_count - 1] = 0;
7172 } else {
7173 c->bitrates[c->bitrates_count - 1] = ret;
7174 }
7175 }
7176
7177 av_free(buffer);
7178
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7179 uint8_t *buffer;
7180 size_t len = atom.size - AV_UUID_LEN;
7181 if (c->export_xmp) {
7182 buffer = av_mallocz(len + 1);
7183 if (!buffer) {
7184 return AVERROR(ENOMEM);
7185 }
7186 ret = ffio_read_size(pb, buffer, len);
7187 if (ret < 0) {
7188 av_free(buffer);
7189 return ret;
7190 }
7191 buffer[len] = '\0';
7192 av_dict_set(&c->fc->metadata, "xmp",
7193 buffer, AV_DICT_DONT_STRDUP_VAL);
7194 } else {
7195 // skip all uuid atom, which makes it fast for long uuid-xmp file
7196 ret = avio_skip(pb, len);
7197 if (ret < 0)
7198 return ret;
7199 }
7200
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7201 size_t len = atom.size - AV_UUID_LEN;
7202 ret = mov_parse_uuid_spherical(sc, pb, len);
7203 if (ret < 0)
7204 return ret;
7205 if (!sc->spherical)
7206 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7207 }
7208
7209 14 return 0;
7210 }
7211
7212 188 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7213 {
7214 int ret;
7215 uint8_t content[16];
7216
7217
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 96 times.
188 if (atom.size < 8)
7218 92 return 0;
7219
7220 96 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (ret < 0)
7222 return ret;
7223
7224
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 55 times.
96 if ( !c->found_moov
7225
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 23 times.
41 && !c->found_mdat
7226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 && !memcmp(content, "Anevia\x1A\x1A", 8)
7227 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7228 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7229 }
7230
7231 96 return 0;
7232 }
7233
7234 35 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7235 {
7236 35 uint32_t format = avio_rl32(pb);
7237 MOVStreamContext *sc;
7238 enum AVCodecID id;
7239 AVStream *st;
7240
7241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (c->fc->nb_streams < 1)
7242 return 0;
7243 35 st = c->fc->streams[c->fc->nb_streams - 1];
7244 35 sc = st->priv_data;
7245
7246
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 32 times.
35 switch (sc->format)
7247 {
7248 3 case MKTAG('e','n','c','v'): // encrypted video
7249 case MKTAG('e','n','c','a'): // encrypted audio
7250 3 id = mov_codec_id(st, format);
7251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7252 st->codecpar->codec_id != id) {
7253 av_log(c->fc, AV_LOG_WARNING,
7254 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7255 (char*)&format, st->codecpar->codec_id);
7256 break;
7257 }
7258
7259 3 st->codecpar->codec_id = id;
7260 3 sc->format = format;
7261 3 break;
7262
7263 32 default:
7264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (format != sc->format) {
7265 av_log(c->fc, AV_LOG_WARNING,
7266 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7267 (char*)&format, (char*)&sc->format);
7268 }
7269 32 break;
7270 }
7271
7272 35 return 0;
7273 }
7274
7275 /**
7276 * Gets the current encryption info and associated current stream context. If
7277 * we are parsing a track fragment, this will return the specific encryption
7278 * info for this fragment; otherwise this will return the global encryption
7279 * info for the current stream.
7280 */
7281 6 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7282 {
7283 MOVFragmentStreamInfo *frag_stream_info;
7284 AVStream *st;
7285 int i;
7286
7287 6 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7288
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (frag_stream_info) {
7289
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 for (i = 0; i < c->fc->nb_streams; i++) {
7290 3 *sc = c->fc->streams[i]->priv_data;
7291
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if ((*sc)->id == frag_stream_info->id) {
7292 3 st = c->fc->streams[i];
7293 3 break;
7294 }
7295 }
7296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (i == c->fc->nb_streams)
7297 return 0;
7298 3 *sc = st->priv_data;
7299
7300
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!frag_stream_info->encryption_index) {
7301 // If this stream isn't encrypted, don't create the index.
7302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!(*sc)->cenc.default_encrypted_sample)
7303 return 0;
7304 1 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!frag_stream_info->encryption_index)
7306 return AVERROR(ENOMEM);
7307 }
7308 3 *encryption_index = frag_stream_info->encryption_index;
7309 3 return 1;
7310 } else {
7311 // No current track fragment, using stream level encryption info.
7312
7313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7314 return 0;
7315 3 st = c->fc->streams[c->fc->nb_streams - 1];
7316 3 *sc = st->priv_data;
7317
7318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!(*sc)->cenc.encryption_index) {
7319 // If this stream isn't encrypted, don't create the index.
7320 if (!(*sc)->cenc.default_encrypted_sample)
7321 return 0;
7322 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7323 if (!(*sc)->cenc.encryption_index)
7324 return AVERROR(ENOMEM);
7325 }
7326
7327 3 *encryption_index = (*sc)->cenc.encryption_index;
7328 3 return 1;
7329 }
7330 }
7331
7332 72 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7333 {
7334 int i, ret;
7335 unsigned int subsample_count;
7336 AVSubsampleEncryptionInfo *subsamples;
7337
7338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!sc->cenc.default_encrypted_sample) {
7339 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7340 return AVERROR_INVALIDDATA;
7341 }
7342
7343
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) {
7344 72 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!*sample)
7346 return AVERROR(ENOMEM);
7347 } else
7348 *sample = NULL;
7349
7350
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (sc->cenc.per_sample_iv_size != 0) {
7351
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) {
7352 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
7353 av_encryption_info_free(*sample);
7354 *sample = NULL;
7355 return ret;
7356 }
7357 }
7358
7359
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (use_subsamples) {
7360 72 subsample_count = avio_rb16(pb);
7361 72 av_free((*sample)->subsamples);
7362 72 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
7363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!(*sample)->subsamples) {
7364 av_encryption_info_free(*sample);
7365 *sample = NULL;
7366 return AVERROR(ENOMEM);
7367 }
7368
7369
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++) {
7370 72 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
7371 72 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
7372 }
7373
7374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (pb->eof_reached) {
7375 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
7376 av_encryption_info_free(*sample);
7377 *sample = NULL;
7378 return AVERROR_INVALIDDATA;
7379 }
7380 72 (*sample)->subsample_count = subsample_count;
7381 }
7382
7383 72 return 0;
7384 }
7385
7386 2 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7387 {
7388 AVEncryptionInfo **encrypted_samples;
7389 MOVEncryptionIndex *encryption_index;
7390 MOVStreamContext *sc;
7391 int use_subsamples, ret;
7392 2 unsigned int sample_count, i, alloc_size = 0;
7393
7394 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7396 return ret;
7397
7398
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7399 // This can happen if we have both saio/saiz and senc atoms.
7400 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
7401 1 return 0;
7402 }
7403
7404 1 avio_r8(pb); /* version */
7405 1 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
7406
7407 1 sample_count = avio_rb32(pb);
7408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7409 return AVERROR(ENOMEM);
7410
7411
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1 times.
49 for (i = 0; i < sample_count; i++) {
7412 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7413 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7414 min_samples * sizeof(*encrypted_samples));
7415
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (encrypted_samples) {
7416 48 encryption_index->encrypted_samples = encrypted_samples;
7417
7418 48 ret = mov_read_sample_encryption_info(
7419 48 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
7420 } else {
7421 ret = AVERROR(ENOMEM);
7422 }
7423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (pb->eof_reached) {
7424 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
7425 if (ret >= 0)
7426 av_encryption_info_free(encryption_index->encrypted_samples[i]);
7427 ret = AVERROR_INVALIDDATA;
7428 }
7429
7430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0) {
7431 for (; i > 0; i--)
7432 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7433 av_freep(&encryption_index->encrypted_samples);
7434 return ret;
7435 }
7436 }
7437 1 encryption_index->nb_encrypted_samples = sample_count;
7438
7439 1 return 0;
7440 }
7441
7442 1 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
7443 {
7444 AVEncryptionInfo **sample, **encrypted_samples;
7445 int64_t prev_pos;
7446 size_t sample_count, sample_info_size, i;
7447 1 int ret = 0;
7448 1 unsigned int alloc_size = 0;
7449
7450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->nb_encrypted_samples)
7451 return 0;
7452 1 sample_count = encryption_index->auxiliary_info_sample_count;
7453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count != 1) {
7454 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
7455 return AVERROR_PATCHWELCOME;
7456 }
7457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7458 return AVERROR(ENOMEM);
7459
7460 1 prev_pos = avio_tell(pb);
7461
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
7462
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]) {
7463 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
7464 goto finish;
7465 }
7466
7467
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++) {
7468 24 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7469 24 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7470 min_samples * sizeof(*encrypted_samples));
7471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!encrypted_samples) {
7472 ret = AVERROR(ENOMEM);
7473 goto finish;
7474 }
7475 24 encryption_index->encrypted_samples = encrypted_samples;
7476
7477 24 sample = &encryption_index->encrypted_samples[i];
7478 48 sample_info_size = encryption_index->auxiliary_info_default_size
7479 24 ? encryption_index->auxiliary_info_default_size
7480
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 : encryption_index->auxiliary_info_sizes[i];
7481
7482 24 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
7483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (ret < 0)
7484 goto finish;
7485 }
7486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7487 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
7488 ret = AVERROR_INVALIDDATA;
7489 } else {
7490 1 encryption_index->nb_encrypted_samples = sample_count;
7491 }
7492
7493 1 finish:
7494 1 avio_seek(pb, prev_pos, SEEK_SET);
7495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
7496 for (; i > 0; i--) {
7497 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7498 }
7499 av_freep(&encryption_index->encrypted_samples);
7500 }
7501 1 return ret;
7502 }
7503
7504 2 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7505 {
7506 MOVEncryptionIndex *encryption_index;
7507 MOVStreamContext *sc;
7508 int ret;
7509 unsigned int sample_count, aux_info_type, aux_info_param;
7510
7511 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7513 return ret;
7514
7515
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7516 // This can happen if we have both saio/saiz and senc atoms.
7517 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
7518 1 return 0;
7519 }
7520
7521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_sample_count) {
7522 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
7523 return AVERROR_INVALIDDATA;
7524 }
7525
7526 1 avio_r8(pb); /* version */
7527
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7528 aux_info_type = avio_rb32(pb);
7529 aux_info_param = avio_rb32(pb);
7530 if (sc->cenc.default_encrypted_sample) {
7531 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7532 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
7533 return 0;
7534 }
7535 if (aux_info_param != 0) {
7536 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
7537 return 0;
7538 }
7539 } else {
7540 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7541 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7542 aux_info_type == MKBETAG('c','e','n','s') ||
7543 aux_info_type == MKBETAG('c','b','c','1') ||
7544 aux_info_type == MKBETAG('c','b','c','s')) &&
7545 aux_info_param == 0) {
7546 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
7547 return AVERROR_INVALIDDATA;
7548 } else {
7549 return 0;
7550 }
7551 }
7552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7553 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7554 return 0;
7555 }
7556
7557 1 encryption_index->auxiliary_info_default_size = avio_r8(pb);
7558 1 sample_count = avio_rb32(pb);
7559
7560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_default_size == 0) {
7561 if (sample_count == 0)
7562 return AVERROR_INVALIDDATA;
7563
7564 encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
7565 if (!encryption_index->auxiliary_info_sizes)
7566 return AVERROR(ENOMEM);
7567
7568 ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
7569 if (ret != sample_count) {
7570 av_freep(&encryption_index->auxiliary_info_sizes);
7571
7572 if (ret >= 0)
7573 ret = AVERROR_INVALIDDATA;
7574 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
7575 av_err2str(ret));
7576 return ret;
7577 }
7578 }
7579 1 encryption_index->auxiliary_info_sample_count = sample_count;
7580
7581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7582 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7583 }
7584
7585 1 return 0;
7586 }
7587
7588 2 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7589 {
7590 uint64_t *auxiliary_offsets;
7591 MOVEncryptionIndex *encryption_index;
7592 MOVStreamContext *sc;
7593 int i, ret;
7594 unsigned int version, entry_count, aux_info_type, aux_info_param;
7595 2 unsigned int alloc_size = 0;
7596
7597 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7599 return ret;
7600
7601
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7602 // This can happen if we have both saio/saiz and senc atoms.
7603 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
7604 1 return 0;
7605 }
7606
7607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7608 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
7609 return AVERROR_INVALIDDATA;
7610 }
7611
7612 1 version = avio_r8(pb); /* version */
7613
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7614 aux_info_type = avio_rb32(pb);
7615 aux_info_param = avio_rb32(pb);
7616 if (sc->cenc.default_encrypted_sample) {
7617 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7618 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
7619 return 0;
7620 }
7621 if (aux_info_param != 0) {
7622 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
7623 return 0;
7624 }
7625 } else {
7626 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7627 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7628 aux_info_type == MKBETAG('c','e','n','s') ||
7629 aux_info_type == MKBETAG('c','b','c','1') ||
7630 aux_info_type == MKBETAG('c','b','c','s')) &&
7631 aux_info_param == 0) {
7632 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
7633 return AVERROR_INVALIDDATA;
7634 } else {
7635 return 0;
7636 }
7637 }
7638
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7639 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7640 return 0;
7641 }
7642
7643 1 entry_count = avio_rb32(pb);
7644
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
7645 return AVERROR(ENOMEM);
7646
7647
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++) {
7648
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);
7649 1 auxiliary_offsets = av_fast_realloc(
7650 1 encryption_index->auxiliary_offsets, &alloc_size,
7651 min_offsets * sizeof(*auxiliary_offsets));
7652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!auxiliary_offsets) {
7653 av_freep(&encryption_index->auxiliary_offsets);
7654 return AVERROR(ENOMEM);
7655 }
7656 1 encryption_index->auxiliary_offsets = auxiliary_offsets;
7657
7658
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (version == 0) {
7659 1 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
7660 } else {
7661 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
7662 }
7663
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (c->frag_index.current >= 0) {
7664 1 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
7665 }
7666 }
7667
7668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7669 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
7670 av_freep(&encryption_index->auxiliary_offsets);
7671 return AVERROR_INVALIDDATA;
7672 }
7673
7674 1 encryption_index->auxiliary_offsets_count = entry_count;
7675
7676
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (encryption_index->auxiliary_info_sample_count) {
7677 1 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7678 }
7679
7680 return 0;
7681 }
7682
7683 2 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7684 {
7685 AVEncryptionInitInfo *info, *old_init_info;
7686 uint8_t **key_ids;
7687 AVStream *st;
7688 const AVPacketSideData *old_side_data;
7689 uint8_t *side_data, *extra_data;
7690 size_t side_data_size;
7691 2 int ret = 0;
7692 2 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
7693
7694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
7695 return 0;
7696 2 st = c->fc->streams[c->fc->nb_streams-1];
7697
7698 2 version = avio_r8(pb); /* version */
7699 2 avio_rb24(pb); /* flags */
7700
7701 2 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
7702 /* key_id_size */ 16, /* data_size */ 0);
7703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info)
7704 return AVERROR(ENOMEM);
7705
7706
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
7707 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
7708 goto finish;
7709 }
7710
7711
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version > 0) {
7712 2 kid_count = avio_rb32(pb);
7713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
7714 ret = AVERROR(ENOMEM);
7715 goto finish;
7716 }
7717
7718
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++) {
7719 2 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
7720 2 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
7721 min_kid_count * sizeof(*key_ids));
7722
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!key_ids) {
7723 ret = AVERROR(ENOMEM);
7724 goto finish;
7725 }
7726 2 info->key_ids = key_ids;
7727
7728 2 info->key_ids[i] = av_mallocz(16);
7729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info->key_ids[i]) {
7730 ret = AVERROR(ENOMEM);
7731 goto finish;
7732 }
7733 2 info->num_key_ids = i + 1;
7734
7735
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
7736 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
7737 goto finish;
7738 }
7739 }
7740
7741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
7742 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
7743 ret = AVERROR_INVALIDDATA;
7744 goto finish;
7745 }
7746 }
7747
7748 2 extra_data_size = avio_rb32(pb);
7749 2 extra_data = av_malloc(extra_data_size);
7750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!extra_data) {
7751 ret = AVERROR(ENOMEM);
7752 goto finish;
7753 }
7754 2 ret = avio_read(pb, extra_data, extra_data_size);
7755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != extra_data_size) {
7756 av_free(extra_data);
7757
7758 if (ret >= 0)
7759 ret = AVERROR_INVALIDDATA;
7760 goto finish;
7761 }
7762
7763 2 av_freep(&info->data); // malloc(0) may still allocate something.
7764 2 info->data = extra_data;
7765 2 info->data_size = extra_data_size;
7766
7767 // If there is existing initialization data, append to the list.
7768 2 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
7769 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
7770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (old_side_data) {
7771 old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
7772 if (old_init_info) {
7773 // Append to the end of the list.
7774 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
7775 if (!cur->next) {
7776 cur->next = info;
7777 break;
7778 }
7779 }
7780 info = old_init_info;
7781 } else {
7782 // Assume existing side-data will be valid, so the only error we could get is OOM.
7783 ret = AVERROR(ENOMEM);
7784 goto finish;
7785 }
7786 }
7787
7788 2 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
7789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!side_data) {
7790 ret = AVERROR(ENOMEM);
7791 goto finish;
7792 }
7793
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
7794 2 &st->codecpar->nb_coded_side_data,
7795 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
7796 side_data, side_data_size, 0))
7797 av_free(side_data);
7798
7799 2 finish:
7800 2 av_encryption_init_info_free(info);
7801 2 return ret;
7802 }
7803
7804 3 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7805 {
7806 AVStream *st;
7807 MOVStreamContext *sc;
7808
7809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7810 return 0;
7811 3 st = c->fc->streams[c->fc->nb_streams-1];
7812 3 sc = st->priv_data;
7813
7814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7815 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
7816 return AVERROR_PATCHWELCOME;
7817 }
7818
7819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8)
7820 return AVERROR_INVALIDDATA;
7821
7822 3 avio_rb32(pb); /* version and flags */
7823
7824
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->cenc.default_encrypted_sample) {
7825 3 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7827 return AVERROR(ENOMEM);
7828 }
7829 }
7830
7831 3 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
7832 3 return 0;
7833 }
7834
7835 3 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7836 {
7837 AVStream *st;
7838 MOVStreamContext *sc;
7839 unsigned int version, pattern, is_protected, iv_size;
7840
7841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7842 return 0;
7843 3 st = c->fc->streams[c->fc->nb_streams-1];
7844 3 sc = st->priv_data;
7845
7846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7847 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
7848 return AVERROR_PATCHWELCOME;
7849 }
7850
7851
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7852 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7853 if (!sc->cenc.default_encrypted_sample) {
7854 return AVERROR(ENOMEM);
7855 }
7856 }
7857
7858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 20)
7859 return AVERROR_INVALIDDATA;
7860
7861 3 version = avio_r8(pb); /* version */
7862 3 avio_rb24(pb); /* flags */
7863
7864 3 avio_r8(pb); /* reserved */
7865 3 pattern = avio_r8(pb);
7866
7867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (version > 0) {
7868 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
7869 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
7870 }
7871
7872 3 is_protected = avio_r8(pb);
7873
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) {
7874 // The whole stream should be by-default encrypted.
7875 3 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
7876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.encryption_index)
7877 return AVERROR(ENOMEM);
7878 }
7879 3 sc->cenc.per_sample_iv_size = avio_r8(pb);
7880
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 &&
7881 sc->cenc.per_sample_iv_size != 16) {
7882 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
7883 return AVERROR_INVALIDDATA;
7884 }
7885
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) {
7886 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
7887 return AVERROR_INVALIDDATA;
7888 }
7889
7890
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) {
7891 1 iv_size = avio_r8(pb);
7892
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) {
7893 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
7894 return AVERROR_INVALIDDATA;
7895 }
7896
7897
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) {
7898 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
7899 return AVERROR_INVALIDDATA;
7900 }
7901 }
7902
7903 3 return 0;
7904 }
7905
7906 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7907 {
7908 AVStream *st;
7909 int last, type, size, ret;
7910 uint8_t buf[4];
7911
7912 if (c->fc->nb_streams < 1)
7913 return 0;
7914 st = c->fc->streams[c->fc->nb_streams-1];
7915
7916 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
7917 return AVERROR_INVALIDDATA;
7918
7919 /* Check FlacSpecificBox version. */
7920 if (avio_r8(pb) != 0)
7921 return AVERROR_INVALIDDATA;
7922
7923 avio_rb24(pb); /* Flags */
7924
7925 if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
7926 av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
7927 return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
7928 }
7929 flac_parse_block_header(buf, &last, &type, &size);
7930
7931 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
7932 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
7933 return AVERROR_INVALIDDATA;
7934 }
7935
7936 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
7937 if (ret < 0)
7938 return ret;
7939
7940 if (!last)
7941 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
7942
7943 return 0;
7944 }
7945
7946 146 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
7947 {
7948 int i, ret;
7949 int bytes_of_protected_data;
7950
7951
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 143 times.
146 if (!sc->cenc.aes_ctr) {
7952 /* initialize the cipher */
7953 3 sc->cenc.aes_ctr = av_aes_ctr_alloc();
7954
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.aes_ctr) {
7955 return AVERROR(ENOMEM);
7956 }
7957
7958 3 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
7959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
7960 return ret;
7961 }
7962 }
7963
7964 146 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
7965
7966
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!sample->subsample_count) {
7967 /* decrypt the whole packet */
7968 48 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
7969 48 return 0;
7970 }
7971
7972
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 98 times.
196 for (i = 0; i < sample->subsample_count; i++) {
7973
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) {
7974 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
7975 return AVERROR_INVALIDDATA;
7976 }
7977
7978 /* skip the clear bytes */
7979 98 input += sample->subsamples[i].bytes_of_clear_data;
7980 98 size -= sample->subsamples[i].bytes_of_clear_data;
7981
7982 /* decrypt the encrypted bytes */
7983
7984 98 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
7985 98 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
7986
7987 98 input += bytes_of_protected_data;
7988 98 size -= bytes_of_protected_data;
7989 }
7990
7991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (size > 0) {
7992 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
7993 return AVERROR_INVALIDDATA;
7994 }
7995
7996 98 return 0;
7997 }
7998
7999 static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8000 {
8001 int i, ret;
8002 int num_of_encrypted_blocks;
8003 uint8_t iv[16];
8004
8005 if (!sc->cenc.aes_ctx) {
8006 /* initialize the cipher */
8007 sc->cenc.aes_ctx = av_aes_alloc();
8008 if (!sc->cenc.aes_ctx) {
8009 return AVERROR(ENOMEM);
8010 }
8011
8012 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8013 if (ret < 0) {
8014 return ret;
8015 }
8016 }
8017
8018 memcpy(iv, sample->iv, 16);
8019
8020 /* whole-block full sample encryption */
8021 if (!sample->subsample_count) {
8022 /* decrypt the whole packet */
8023 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8024 return 0;
8025 }
8026
8027 for (i = 0; i < sample->subsample_count; i++) {
8028 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8029 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8030 return AVERROR_INVALIDDATA;
8031 }
8032
8033 if (sample->subsamples[i].bytes_of_protected_data % 16) {
8034 av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8035 return AVERROR_INVALIDDATA;
8036 }
8037
8038 /* skip the clear bytes */
8039 input += sample->subsamples[i].bytes_of_clear_data;
8040 size -= sample->subsamples[i].bytes_of_clear_data;
8041
8042 /* decrypt the encrypted bytes */
8043 num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8044 if (num_of_encrypted_blocks > 0) {
8045 av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8046 }
8047 input += sample->subsamples[i].bytes_of_protected_data;
8048 size -= sample->subsamples[i].bytes_of_protected_data;
8049 }
8050
8051 if (size > 0) {
8052 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8053 return AVERROR_INVALIDDATA;
8054 }
8055
8056 return 0;
8057 }
8058
8059 static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8060 {
8061 int i, ret, rem_bytes;
8062 uint8_t *data;
8063
8064 if (!sc->cenc.aes_ctr) {
8065 /* initialize the cipher */
8066 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8067 if (!sc->cenc.aes_ctr) {
8068 return AVERROR(ENOMEM);
8069 }
8070
8071 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
8072 if (ret < 0) {
8073 return ret;
8074 }
8075 }
8076
8077 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8078
8079 /* whole-block full sample encryption */
8080 if (!sample->subsample_count) {
8081 /* decrypt the whole packet */
8082 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8083 return 0;
8084 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8085 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8086 return AVERROR_INVALIDDATA;
8087 }
8088
8089 for (i = 0; i < sample->subsample_count; i++) {
8090 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8091 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8092 return AVERROR_INVALIDDATA;
8093 }
8094
8095 /* skip the clear bytes */
8096 input += sample->subsamples[i].bytes_of_clear_data;
8097 size -= sample->subsamples[i].bytes_of_clear_data;
8098
8099 /* decrypt the encrypted bytes */
8100 data = input;
8101 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8102 while (rem_bytes > 0) {
8103 if (rem_bytes < 16*sample->crypt_byte_block) {
8104 break;
8105 }
8106 av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8107 data += 16*sample->crypt_byte_block;
8108 rem_bytes -= 16*sample->crypt_byte_block;
8109 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8110 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8111 }
8112 input += sample->subsamples[i].bytes_of_protected_data;
8113 size -= sample->subsamples[i].bytes_of_protected_data;
8114 }
8115
8116 if (size > 0) {
8117 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8118 return AVERROR_INVALIDDATA;
8119 }
8120
8121 return 0;
8122 }
8123
8124 static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8125 {
8126 int i, ret, rem_bytes;
8127 uint8_t iv[16];
8128 uint8_t *data;
8129
8130 if (!sc->cenc.aes_ctx) {
8131 /* initialize the cipher */
8132 sc->cenc.aes_ctx = av_aes_alloc();
8133 if (!sc->cenc.aes_ctx) {
8134 return AVERROR(ENOMEM);
8135 }
8136
8137 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8138 if (ret < 0) {
8139 return ret;
8140 }
8141 }
8142
8143 /* whole-block full sample encryption */
8144 if (!sample->subsample_count) {
8145 /* decrypt the whole packet */
8146 memcpy(iv, sample->iv, 16);
8147 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8148 return 0;
8149 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8150 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8151 return AVERROR_INVALIDDATA;
8152 }
8153
8154 for (i = 0; i < sample->subsample_count; i++) {
8155 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8156 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8157 return AVERROR_INVALIDDATA;
8158 }
8159
8160 /* skip the clear bytes */
8161 input += sample->subsamples[i].bytes_of_clear_data;
8162 size -= sample->subsamples[i].bytes_of_clear_data;
8163
8164 /* decrypt the encrypted bytes */
8165 memcpy(iv, sample->iv, 16);
8166 data = input;
8167 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8168 while (rem_bytes > 0) {
8169 if (rem_bytes < 16*sample->crypt_byte_block) {
8170 break;
8171 }
8172 av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8173 data += 16*sample->crypt_byte_block;
8174 rem_bytes -= 16*sample->crypt_byte_block;
8175 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8176 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8177 }
8178 input += sample->subsamples[i].bytes_of_protected_data;
8179 size -= sample->subsamples[i].bytes_of_protected_data;
8180 }
8181
8182 if (size > 0) {
8183 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8184 return AVERROR_INVALIDDATA;
8185 }
8186
8187 return 0;
8188 }
8189
8190 146 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8191 {
8192
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) {
8193 146 return cenc_scheme_decrypt(c, sc, sample, input, size);
8194 } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8195 return cbc1_scheme_decrypt(c, sc, sample, input, size);
8196 } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8197 return cens_scheme_decrypt(c, sc, sample, input, size);
8198 } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8199 return cbcs_scheme_decrypt(c, sc, sample, input, size);
8200 } else {
8201 av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8202 return AVERROR_INVALIDDATA;
8203 }
8204 }
8205
8206 96523 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8207 {
8208 96523 int current = frag_index->current;
8209
8210
2/2
✓ Branch 0 taken 95862 times.
✓ Branch 1 taken 661 times.
96523 if (!frag_index->nb_items)
8211 95862 return NULL;
8212
8213 // Check frag_index->current is the right one for pkt. It can out of sync.
8214
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) {
8215
2/2
✓ Branch 0 taken 639 times.
✓ Branch 1 taken 22 times.
661 if (frag_index->item[current].moof_offset < pkt->pos &&
8216
2/2
✓ Branch 0 taken 413 times.
✓ Branch 1 taken 226 times.
639 (current + 1 == frag_index->nb_items ||
8217
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 25 times.
413 frag_index->item[current + 1].moof_offset > pkt->pos))
8218 614 return get_frag_stream_info(frag_index, current, id);
8219 }
8220
8221
8222
2/2
✓ Branch 0 taken 3955 times.
✓ Branch 1 taken 4 times.
3959 for (int i = 0; i < frag_index->nb_items; i++) {
8223
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 3912 times.
3955 if (frag_index->item[i].moof_offset > pkt->pos)
8224 43 break;
8225 3912 current = i;
8226 }
8227 47 frag_index->current = current;
8228 47 return get_frag_stream_info(frag_index, current, id);
8229 }
8230
8231 96523 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8232 {
8233 MOVFragmentStreamInfo *frag_stream_info;
8234 MOVEncryptionIndex *encryption_index;
8235 AVEncryptionInfo *encrypted_sample;
8236 int encrypted_index, ret;
8237
8238 96523 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8239 96523 encrypted_index = current_index;
8240 96523 encryption_index = NULL;
8241
2/2
✓ Branch 0 taken 661 times.
✓ Branch 1 taken 95862 times.
96523 if (frag_stream_info) {
8242 // Note this only supports encryption info in the first sample descriptor.
8243
2/2
✓ Branch 0 taken 637 times.
✓ Branch 1 taken 24 times.
661 if (frag_stream_info->stsd_id == 1) {
8244
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 613 times.
637 if (frag_stream_info->encryption_index) {
8245 24 encrypted_index = current_index - frag_stream_info->index_base;
8246 24 encryption_index = frag_stream_info->encryption_index;
8247 } else {
8248 613 encryption_index = sc->cenc.encryption_index;
8249 }
8250 }
8251 } else {
8252 95862 encryption_index = sc->cenc.encryption_index;
8253 }
8254
8255
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 96377 times.
96523 if (encryption_index) {
8256
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_info_sample_count &&
8257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8258 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8259 return AVERROR_INVALIDDATA;
8260 }
8261
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_offsets_count &&
8262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8263 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8264 return AVERROR_INVALIDDATA;
8265 }
8266
8267 146 encrypted_sample = NULL;
8268
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!encryption_index->nb_encrypted_samples) {
8269 // Full-sample encryption with default settings.
8270 48 encrypted_sample = sc->cenc.default_encrypted_sample;
8271
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) {
8272 // Per-sample setting override.
8273 98 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (!encrypted_sample) {
8275 encrypted_sample = sc->cenc.default_encrypted_sample;
8276 }
8277 }
8278
8279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (!encrypted_sample) {
8280 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8281 return AVERROR_INVALIDDATA;
8282 }
8283
8284
1/2
✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
146 if (mov->decryption_key) {
8285 146 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
8286 } else {
8287 size_t size;
8288 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
8289 if (!side_data)
8290 return AVERROR(ENOMEM);
8291 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
8292 if (ret < 0)
8293 av_free(side_data);
8294 return ret;
8295 }
8296 }
8297
8298 96377 return 0;
8299 }
8300
8301 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8302 {
8303 const int OPUS_SEEK_PREROLL_MS = 80;
8304 int ret;
8305 AVStream *st;
8306 size_t size;
8307 uint16_t pre_skip;
8308
8309 if (c->fc->nb_streams < 1)
8310 return 0;
8311 st = c->fc->streams[c->fc->nb_streams-1];
8312
8313 if ((uint64_t)atom.size > (1<<30) || atom.size < 11)
8314 return AVERROR_INVALIDDATA;
8315
8316 /* Check OpusSpecificBox version. */
8317 if (avio_r8(pb) != 0) {
8318 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
8319 return AVERROR_INVALIDDATA;
8320 }
8321
8322 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
8323 size = atom.size + 8;
8324
8325 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
8326 return ret;
8327
8328 AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
8329 AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
8330 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
8331 avio_read(pb, st->codecpar->extradata + 9, size - 9);
8332
8333 /* OpusSpecificBox is stored in big-endian, but OpusHead is
8334 little-endian; aside from the preceeding magic and version they're
8335 otherwise currently identical. Data after output gain at offset 16
8336 doesn't need to be bytewapped. */
8337 pre_skip = AV_RB16A(st->codecpar->extradata + 10);
8338 AV_WL16A(st->codecpar->extradata + 10, pre_skip);
8339 AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
8340 AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
8341
8342 st->codecpar->initial_padding = pre_skip;
8343 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
8344 (AVRational){1, 1000},
8345 (AVRational){1, 48000});
8346
8347 return 0;
8348 }
8349
8350 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8351 {
8352 AVStream *st;
8353 unsigned format_info;
8354 int channel_assignment, channel_assignment1, channel_assignment2;
8355 int ratebits;
8356 uint64_t chmask;
8357
8358 if (c->fc->nb_streams < 1)
8359 return 0;
8360 st = c->fc->streams[c->fc->nb_streams-1];
8361
8362 if (atom.size < 10)
8363 return AVERROR_INVALIDDATA;
8364
8365 format_info = avio_rb32(pb);
8366
8367 ratebits = (format_info >> 28) & 0xF;
8368 channel_assignment1 = (format_info >> 15) & 0x1F;
8369 channel_assignment2 = format_info & 0x1FFF;
8370 if (channel_assignment2)
8371 channel_assignment = channel_assignment2;
8372 else
8373 channel_assignment = channel_assignment1;
8374
8375 st->codecpar->frame_size = 40 << (ratebits & 0x7);
8376 st->codecpar->sample_rate = mlp_samplerate(ratebits);
8377
8378 av_channel_layout_uninit(&st->codecpar->ch_layout);
8379 chmask = truehd_layout(channel_assignment);
8380 av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
8381
8382 return 0;
8383 }
8384
8385 4 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8386 {
8387 AVStream *st;
8388 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
8389 int ret;
8390 4 int64_t read_size = atom.size;
8391
8392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8393 return 0;
8394 4 st = c->fc->streams[c->fc->nb_streams-1];
8395
8396 // At most 24 bytes
8397 4 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
8398
8399
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
8400 return ret;
8401
8402 4 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
8403 }
8404
8405 3 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8406 {
8407 AVStream *st;
8408 uint8_t *buf;
8409 int ret, old_size, num_arrays;
8410
8411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
8412 return 0;
8413 3 st = c->fc->streams[c->fc->nb_streams-1];
8414
8415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata_size)
8416 // TODO: handle lhvC when present before hvcC
8417 return 0;
8418
8419
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)
8420 return AVERROR_INVALIDDATA;
8421
8422 3 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
8423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!buf)
8424 return AVERROR(ENOMEM);
8425 3 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8426
8427 3 ret = ffio_read_size(pb, buf, atom.size);
8428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8429 av_free(buf);
8430 av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
8431 return 0;
8432 }
8433
8434 3 num_arrays = buf[5];
8435 3 old_size = st->codecpar->extradata_size;
8436 3 atom.size -= 8 /* account for mov_realloc_extradata offseting */
8437 + 6 /* lhvC bytes before the arrays*/;
8438
8439 3 ret = mov_realloc_extradata(st->codecpar, atom);
8440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8441 av_free(buf);
8442 return ret;
8443 }
8444
8445 3 st->codecpar->extradata[22] += num_arrays;
8446 3 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
8447
8448 3 st->disposition |= AV_DISPOSITION_MULTILAYER;
8449
8450 3 av_free(buf);
8451 3 return 0;
8452 }
8453
8454 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8455 {
8456 4 AVFormatContext *ctx = c->fc;
8457 4 AVStream *st = NULL;
8458 AVBPrint scheme_buf, value_buf;
8459 4 int64_t scheme_str_len = 0, value_str_len = 0;
8460 4 int version, flags, ret = AVERROR_BUG;
8461 4 int64_t size = atom.size;
8462
8463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
8464 // 4 bytes for version + flags, 2x 1 byte for null
8465 return AVERROR_INVALIDDATA;
8466
8467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8468 return 0;
8469 4 st = c->fc->streams[c->fc->nb_streams-1];
8470
8471 4 version = avio_r8(pb);
8472 4 flags = avio_rb24(pb);
8473 4 size -= 4;
8474
8475
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) {
8476 av_log(ctx, AV_LOG_ERROR,
8477 "Unsupported 'kind' box with version %d, flags: %x",
8478 version, flags);
8479 return AVERROR_INVALIDDATA;
8480 }
8481
8482 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8483 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8484
8485
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,
8486 size)) < 0) {
8487 ret = scheme_str_len;
8488 goto cleanup;
8489 }
8490
8491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
8492 // we need to have another string, even if nullptr.
8493 // we check with + 1 since we expect that if size was not hit,
8494 // an additional null was read.
8495 ret = AVERROR_INVALIDDATA;
8496 goto cleanup;
8497 }
8498
8499 4 size -= scheme_str_len + 1;
8500
8501
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,
8502 size)) < 0) {
8503 ret = value_str_len;
8504 goto cleanup;
8505 }
8506
8507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
8508 // in case of no trailing null, box is not valid.
8509 ret = AVERROR_INVALIDDATA;
8510 goto cleanup;
8511 }
8512
8513 4 av_log(ctx, AV_LOG_TRACE,
8514 "%s stream %d KindBox(scheme: %s, value: %s)\n",
8515 4 av_get_media_type_string(st->codecpar->codec_type),
8516 st->index,
8517 scheme_buf.str, value_buf.str);
8518
8519
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++) {
8520 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
8521
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
8522 continue;
8523
8524
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
8525 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
8526
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
8527 16 continue;
8528
8529 4 st->disposition |= value_map.disposition;
8530 }
8531 }
8532
8533 4 ret = 0;
8534
8535 4 cleanup:
8536
8537 4 av_bprint_finalize(&scheme_buf, NULL);
8538 4 av_bprint_finalize(&value_buf, NULL);
8539
8540 4 return ret;
8541 }
8542
8543 static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8544 {
8545 AVStream *st;
8546 AVChannelLayout ch_layout = { 0 };
8547 int ret, i, version, type;
8548 int ambisonic_order, channel_order, normalization, channel_count;
8549 int ambi_channels, non_diegetic_channels;
8550
8551 if (c->fc->nb_streams < 1)
8552 return 0;
8553
8554 st = c->fc->streams[c->fc->nb_streams - 1];
8555
8556 if (atom.size < 16) {
8557 av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
8558 return AVERROR_INVALIDDATA;
8559 }
8560
8561 version = avio_r8(pb);
8562 if (version) {
8563 av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
8564 return 0;
8565 }
8566
8567 type = avio_r8(pb);
8568 if (type & 0x7f) {
8569 av_log(c->fc, AV_LOG_WARNING,
8570 "Unsupported ambisonic type %d\n", type & 0x7f);
8571 return 0;
8572 }
8573 non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
8574
8575 ambisonic_order = avio_rb32(pb);
8576
8577 channel_order = avio_r8(pb);
8578 if (channel_order) {
8579 av_log(c->fc, AV_LOG_WARNING,
8580 "Unsupported channel_order %d\n", channel_order);
8581 return 0;
8582 }
8583
8584 normalization = avio_r8(pb);
8585 if (normalization) {
8586 av_log(c->fc, AV_LOG_WARNING,
8587 "Unsupported normalization %d\n", normalization);
8588 return 0;
8589 }
8590
8591 channel_count = avio_rb32(pb);
8592 if (ambisonic_order < 0 || ambisonic_order > 31 ||
8593 channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
8594 non_diegetic_channels)) {
8595 av_log(c->fc, AV_LOG_ERROR,
8596 "Invalid number of channels (%d / %d)\n",
8597 channel_count, ambisonic_order);
8598 return 0;
8599 }
8600 ambi_channels = channel_count - non_diegetic_channels;
8601
8602 ret = av_channel_layout_custom_init(&ch_layout, channel_count);
8603 if (ret < 0)
8604 return 0;
8605
8606 for (i = 0; i < channel_count; i++) {
8607 unsigned channel = avio_rb32(pb);
8608
8609 if (channel >= channel_count) {
8610 av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
8611 channel, ambisonic_order);
8612 av_channel_layout_uninit(&ch_layout);
8613 return 0;
8614 }
8615 if (channel >= ambi_channels)
8616 ch_layout.u.map[i].id = channel - ambi_channels;
8617 else
8618 ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
8619 }
8620
8621 ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
8622 if (ret < 0) {
8623 av_channel_layout_uninit(&ch_layout);
8624 return 0;
8625 }
8626
8627 av_channel_layout_uninit(&st->codecpar->ch_layout);
8628 st->codecpar->ch_layout = ch_layout;
8629
8630 return 0;
8631 }
8632
8633 static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8634 {
8635 AVStream *st;
8636 int version;
8637
8638 if (c->fc->nb_streams < 1)
8639 return 0;
8640
8641 st = c->fc->streams[c->fc->nb_streams - 1];
8642
8643 if (atom.size < 5) {
8644 av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
8645 return AVERROR_INVALIDDATA;
8646 }
8647
8648 version = avio_r8(pb);
8649 if (version) {
8650 av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
8651 return 0;
8652 }
8653
8654 st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
8655
8656 return 0;
8657 }
8658
8659 90 static int rb_size(AVIOContext *pb, int64_t *value, int size)
8660 {
8661
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 89 times.
90 if (size == 0)
8662 1 *value = 0;
8663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
89 else if (size == 1)
8664 *value = avio_r8(pb);
8665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
89 else if (size == 2)
8666 *value = avio_rb16(pb);
8667
1/2
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
89 else if (size == 4)
8668 89 *value = avio_rb32(pb);
8669 else if (size == 8) {
8670 *value = avio_rb64(pb);
8671 if (*value < 0)
8672 return -1;
8673 } else
8674 return -1;
8675 90 return size;
8676 }
8677
8678 12 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8679 {
8680 12 avio_rb32(pb); // version & flags.
8681 12 c->primary_item_id = avio_rb16(pb);
8682 12 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
8683 12 return atom.size;
8684 }
8685
8686 6 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8687 {
8688 6 c->idat_offset = avio_tell(pb);
8689 6 return 0;
8690 }
8691
8692 12 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8693 {
8694 HEIFItem **heif_item;
8695 int version, offset_size, length_size, base_offset_size, index_size;
8696 int item_count, extent_count;
8697 int64_t base_offset, extent_offset, extent_length;
8698 uint8_t value;
8699
8700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->found_iloc) {
8701 av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
8702 return 0;
8703 }
8704
8705 12 version = avio_r8(pb);
8706 12 avio_rb24(pb); // flags.
8707
8708 12 value = avio_r8(pb);
8709 12 offset_size = (value >> 4) & 0xF;
8710 12 length_size = value & 0xF;
8711 12 value = avio_r8(pb);
8712 12 base_offset_size = (value >> 4) & 0xF;
8713
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 index_size = !version ? 0 : (value & 0xF);
8714
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (index_size) {
8715 avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
8716 return AVERROR_PATCHWELCOME;
8717 }
8718
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8719
8720 12 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
8721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!heif_item)
8722 return AVERROR(ENOMEM);
8723 12 c->heif_item = heif_item;
8724
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (item_count > c->nb_heif_item)
8725 12 memset(&c->heif_item[c->nb_heif_item], 0,
8726 12 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
8727 12 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
8728
8729 12 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
8730
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 for (int i = 0; i < item_count; i++) {
8731 30 HEIFItem *item = c->heif_item[i];
8732
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8733
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
8734
8735
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (avio_feof(pb))
8736 return AVERROR_INVALIDDATA;
8737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (offset_type > 1) {
8738 avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
8739 return AVERROR_PATCHWELCOME;
8740 }
8741
8742 30 avio_rb16(pb); // data_reference_index.
8743
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (rb_size(pb, &base_offset, base_offset_size) < 0)
8744 return AVERROR_INVALIDDATA;
8745 30 extent_count = avio_rb16(pb);
8746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (extent_count > 1) {
8747 // For still AVIF images, we only support one extent item.
8748 avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
8749 return AVERROR_PATCHWELCOME;
8750 }
8751
8752
2/4
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
✗ Branch 4 not taken.
60 if (rb_size(pb, &extent_offset, offset_size) < 0 ||
8753 30 rb_size(pb, &extent_length, length_size) < 0 ||
8754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 base_offset > INT64_MAX - extent_offset)
8755 return AVERROR_INVALIDDATA;
8756
8757
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if (!item)
8758 30 item = c->heif_item[i] = av_mallocz(sizeof(*item));
8759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!item)
8760 return AVERROR(ENOMEM);
8761
8762 30 item->item_id = item_id;
8763
8764
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 24 times.
30 if (offset_type == 1)
8765 6 item->is_idat_relative = 1;
8766 30 item->extent_length = extent_length;
8767 30 item->extent_offset = base_offset + extent_offset;
8768 30 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, offset_type %d, "
8769 "extent_offset %"PRId64", extent_length %"PRId64"\n",
8770 i, offset_type, item->extent_offset, item->extent_length);
8771 }
8772
8773 12 c->found_iloc = 1;
8774 12 return atom.size;
8775 }
8776
8777 30 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom, int idx)
8778 {
8779 HEIFItem *item;
8780 AVBPrint item_name;
8781 30 int64_t size = atom.size;
8782 uint32_t item_type;
8783 int item_id;
8784 int version, ret;
8785
8786 30 version = avio_r8(pb);
8787 30 avio_rb24(pb); // flags.
8788 30 size -= 4;
8789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (size < 0)
8790 return AVERROR_INVALIDDATA;
8791
8792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (version < 2) {
8793 avpriv_report_missing_feature(c->fc, "infe version < 2");
8794 avio_skip(pb, size);
8795 return 1;
8796 }
8797
8798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
8799 30 avio_rb16(pb); // item_protection_index
8800 30 item_type = avio_rl32(pb);
8801 30 size -= 8;
8802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (size < 1)
8803 return AVERROR_INVALIDDATA;
8804
8805 30 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
8806 30 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
8807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (ret < 0) {
8808 av_bprint_finalize(&item_name, NULL);
8809 return ret;
8810 }
8811
8812 30 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
8813 30 item_id, av_fourcc2str(item_type), item_name.str);
8814
8815 30 size -= ret + 1;
8816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (size > 0)
8817 avio_skip(pb, size);
8818
8819 30 item = c->heif_item[idx];
8820
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!item)
8821 item = c->heif_item[idx] = av_mallocz(sizeof(*item));
8822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!item)
8823 return AVERROR(ENOMEM);
8824
8825
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 1 times.
30 if (ret)
8826 29 av_bprint_finalize(&item_name, &c->heif_item[idx]->name);
8827 30 c->heif_item[idx]->item_id = item_id;
8828 30 c->heif_item[idx]->type = item_type;
8829
8830
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 7 times.
30 switch (item_type) {
8831 23 case MKTAG('a','v','0','1'):
8832 case MKTAG('h','v','c','1'):
8833 23 ret = heif_add_stream(c, c->heif_item[idx]);
8834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (ret < 0)
8835 return ret;
8836 23 break;
8837 }
8838
8839 30 return 0;
8840 }
8841
8842 12 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8843 {
8844 HEIFItem **heif_item;
8845 int entry_count;
8846 12 int version, got_stream = 0, ret, i;
8847
8848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->found_iinf) {
8849 av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
8850 return 0;
8851 }
8852
8853 12 version = avio_r8(pb);
8854 12 avio_rb24(pb); // flags.
8855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
8856
8857 12 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
8858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!heif_item)
8859 return AVERROR(ENOMEM);
8860 12 c->heif_item = heif_item;
8861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (entry_count > c->nb_heif_item)
8862 memset(&c->heif_item[c->nb_heif_item], 0,
8863 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
8864 12 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
8865
8866
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 for (i = 0; i < entry_count; i++) {
8867 MOVAtom infe;
8868
8869 30 infe.size = avio_rb32(pb) - 8;
8870 30 infe.type = avio_rl32(pb);
8871
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (avio_feof(pb)) {
8872 ret = AVERROR_INVALIDDATA;
8873 goto fail;
8874 }
8875 30 ret = mov_read_infe(c, pb, infe, i);
8876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (ret < 0)
8877 goto fail;
8878
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if (!ret)
8879 30 got_stream = 1;
8880 }
8881
8882 12 c->found_iinf = got_stream;
8883 12 return 0;
8884 fail:
8885 for (; i >= 0; i--) {
8886 HEIFItem *item = c->heif_item[i];
8887
8888 if (!item)
8889 continue;
8890
8891 av_freep(&item->name);
8892 if (!item->st)
8893 continue;
8894
8895 mov_free_stream_context(c->fc, item->st);
8896 ff_remove_stream(c->fc, item->st);
8897 item->st = NULL;
8898 }
8899 return ret;
8900 }
8901
8902 6 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
8903 {
8904 6 HEIFItem *item = NULL;
8905 HEIFGrid *grid;
8906 int entries, i;
8907
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8908
8909
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 for (int i = 0; i < c->nb_heif_grid; i++) {
8910 if (c->heif_grid[i].item->item_id == from_item_id) {
8911 av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
8912 "referencing the same Derived Image item\n");
8913 return AVERROR_INVALIDDATA;
8914 }
8915 }
8916
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 for (int i = 0; i < c->nb_heif_item; i++) {
8917
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)
8918 14 continue;
8919 6 item = c->heif_item[i];
8920
8921
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 switch (item->type) {
8922 6 case MKTAG('g','r','i','d'):
8923 case MKTAG('i','o','v','l'):
8924 6 break;
8925 default:
8926 avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
8927 av_fourcc2str(item->type));
8928 return 0;
8929 }
8930 6 break;
8931 }
8932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!item) {
8933 av_log(c->fc, AV_LOG_ERROR, "Missing grid information\n");
8934 return AVERROR_INVALIDDATA;
8935 }
8936
8937 6 grid = av_realloc_array(c->heif_grid, c->nb_heif_grid + 1U,
8938 sizeof(*c->heif_grid));
8939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!grid)
8940 return AVERROR(ENOMEM);
8941 6 c->heif_grid = grid;
8942 6 grid = &grid[c->nb_heif_grid++];
8943
8944 6 entries = avio_rb16(pb);
8945 6 grid->tile_id_list = av_malloc_array(entries, sizeof(*grid->tile_id_list));
8946 6 grid->tile_idx_list = av_calloc(entries, sizeof(*grid->tile_idx_list));
8947 6 grid->tile_item_list = av_calloc(entries, sizeof(*grid->tile_item_list));
8948
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)
8949 return AVERROR(ENOMEM);
8950 /* 'to' item ids */
8951
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (i = 0; i < entries; i++)
8952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 grid->tile_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
8953 6 grid->nb_tiles = entries;
8954 6 grid->item = item;
8955
8956 6 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
8957 from_item_id, entries);
8958
8959 6 return 0;
8960 }
8961
8962 2 static int mov_read_iref_thmb(MOVContext *c, AVIOContext *pb, int version)
8963 {
8964 int entries;
8965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 int to_item_id, from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8966
8967 2 entries = avio_rb16(pb);
8968
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (entries > 1) {
8969 avpriv_request_sample(c->fc, "thmb in iref referencing several items");
8970 return AVERROR_PATCHWELCOME;
8971 }
8972 /* 'to' item ids */
8973
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 to_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8974
8975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (to_item_id != c->primary_item_id)
8976 return 0;
8977
8978 2 c->thmb_item_id = from_item_id;
8979
8980 2 av_log(c->fc, AV_LOG_TRACE, "thmb: from_item_id %d, entries %d\n",
8981 from_item_id, entries);
8982
8983 2 return 0;
8984 }
8985
8986 8 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8987 {
8988 8 int version = avio_r8(pb);
8989 8 avio_rb24(pb); // flags
8990 8 atom.size -= 4;
8991
8992
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (version > 1) {
8993 av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
8994 return 0;
8995 }
8996
8997
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 while (atom.size) {
8998 8 uint32_t type, size = avio_rb32(pb);
8999 8 int64_t next = avio_tell(pb);
9000
9001
3/6
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
8 if (size < 14 || next < 0 || next > INT64_MAX - size)
9002 return AVERROR_INVALIDDATA;
9003
9004 8 next += size - 4;
9005 8 type = avio_rl32(pb);
9006
2/3
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
8 switch (type) {
9007 6 case MKTAG('d','i','m','g'):
9008 6 mov_read_iref_dimg(c, pb, version);
9009 8 break;
9010 2 case MKTAG('t','h','m','b'):
9011 2 mov_read_iref_thmb(c, pb, version);
9012 2 break;
9013 default:
9014 av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
9015 av_fourcc2str(type), size);
9016 }
9017
9018 8 atom.size -= size;
9019 8 avio_seek(pb, next, SEEK_SET);
9020 }
9021 8 return 0;
9022 }
9023
9024 29 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9025 {
9026 HEIFItem *item;
9027 uint32_t width, height;
9028
9029 29 avio_r8(pb); /* version */
9030 29 avio_rb24(pb); /* flags */
9031 29 width = avio_rb32(pb);
9032 29 height = avio_rb32(pb);
9033
9034 29 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %u, height %u\n",
9035 c->cur_item_id, width, height);
9036
9037 29 item = heif_cur_item(c);
9038
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (item) {
9039 29 item->width = width;
9040 29 item->height = height;
9041 }
9042
9043 29 return 0;
9044 }
9045
9046 4 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9047 {
9048 HEIFItem *item;
9049 int angle;
9050
9051 4 angle = avio_r8(pb) & 0x3;
9052
9053 4 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
9054 c->cur_item_id, angle);
9055
9056 4 item = heif_cur_item(c);
9057
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item) {
9058 // angle * 90 specifies the angle (in anti-clockwise direction)
9059 // in units of degrees.
9060 4 item->rotation = angle * 90;
9061 }
9062
9063 4 return 0;
9064 }
9065
9066 4 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9067 {
9068 HEIFItem *item;
9069 int axis;
9070
9071 4 axis = avio_r8(pb) & 0x1;
9072
9073 4 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
9074 c->cur_item_id, axis);
9075
9076 4 item = heif_cur_item(c);
9077
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item) {
9078 4 item->hflip = axis;
9079 4 item->vflip = !axis;
9080 }
9081
9082 4 return 0;
9083 }
9084
9085 12 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9086 {
9087 typedef struct MOVAtoms {
9088 FFIOContext b;
9089 uint32_t type;
9090 int64_t size;
9091 uint8_t *data;
9092 } MOVAtoms;
9093 12 MOVAtoms *atoms = NULL;
9094 MOVAtom a;
9095 unsigned count;
9096 12 int nb_atoms = 0;
9097 int version, flags;
9098 int ret;
9099
9100 12 a.size = avio_rb32(pb);
9101 12 a.type = avio_rl32(pb);
9102
9103
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (a.size < 8 || a.type != MKTAG('i','p','c','o'))
9104 return AVERROR_INVALIDDATA;
9105
9106 12 a.size -= 8;
9107
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 12 times.
61 while (a.size >= 8) {
9108 49 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
9109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if (!ref) {
9110 ret = AVERROR(ENOMEM);
9111 goto fail;
9112 }
9113 49 ref->data = NULL;
9114 49 ref->size = avio_rb32(pb);
9115 49 ref->type = avio_rl32(pb);
9116
2/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
49 if (ref->size > a.size || ref->size < 8)
9117 break;
9118 49 ref->data = av_malloc(ref->size);
9119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if (!ref->data) {
9120 ret = AVERROR_INVALIDDATA;
9121 goto fail;
9122 }
9123 49 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
9124 49 avio_seek(pb, -8, SEEK_CUR);
9125
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
49 if (avio_read(pb, ref->data, ref->size) != ref->size) {
9126 ret = AVERROR_INVALIDDATA;
9127 goto fail;
9128 }
9129 49 ffio_init_read_context(&ref->b, ref->data, ref->size);
9130 49 a.size -= ref->size;
9131 }
9132
9133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (a.size) {
9134 ret = AVERROR_INVALIDDATA;
9135 goto fail;
9136 }
9137
9138 12 a.size = avio_rb32(pb);
9139 12 a.type = avio_rl32(pb);
9140
9141
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (a.size < 8 || a.type != MKTAG('i','p','m','a')) {
9142 ret = AVERROR_INVALIDDATA;
9143 goto fail;
9144 }
9145
9146 12 version = avio_r8(pb);
9147 12 flags = avio_rb24(pb);
9148 12 count = avio_rb32(pb);
9149
9150
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 12 times.
41 for (int i = 0; i < count; i++) {
9151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9152 29 int assoc_count = avio_r8(pb);
9153
9154
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 if (avio_feof(pb)) {
9155 ret = AVERROR_INVALIDDATA;
9156 goto fail;
9157 }
9158
9159
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 29 times.
101 for (int j = 0; j < assoc_count; j++) {
9160 MOVAtoms *ref;
9161 72 int index = avio_r8(pb) & 0x7f;
9162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (flags & 1) {
9163 index <<= 8;
9164 index |= avio_r8(pb);
9165 }
9166
2/4
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 72 times.
72 if (index > nb_atoms || index <= 0) {
9167 ret = AVERROR_INVALIDDATA;
9168 goto fail;
9169 }
9170 72 ref = &atoms[--index];
9171
9172 72 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
9173 72 index + 1, item_id, av_fourcc2str(ref->type));
9174
9175 72 c->cur_item_id = item_id;
9176
9177 72 ret = mov_read_default(c, &ref->b.pub,
9178 72 (MOVAtom) { .size = ref->size,
9179 .type = MKTAG('i','p','c','o') });
9180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (ret < 0)
9181 goto fail;
9182 72 ffio_init_read_context(&ref->b, ref->data, ref->size);
9183 }
9184 }
9185
9186 12 ret = 0;
9187 12 fail:
9188 12 c->cur_item_id = -1;
9189
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 12 times.
61 for (int i = 0; i < nb_atoms; i++)
9190 49 av_free(atoms[i].data);
9191 12 av_free(atoms);
9192
9193 12 return ret;
9194 }
9195
9196 static const MOVParseTableEntry mov_default_parse_table[] = {
9197 { MKTAG('A','C','L','R'), mov_read_aclr },
9198 { MKTAG('A','P','R','G'), mov_read_avid },
9199 { MKTAG('A','A','L','P'), mov_read_avid },
9200 { MKTAG('A','R','E','S'), mov_read_ares },
9201 { MKTAG('a','v','s','s'), mov_read_avss },
9202 { MKTAG('a','v','1','C'), mov_read_glbl },
9203 { MKTAG('c','h','p','l'), mov_read_chpl },
9204 { MKTAG('c','o','6','4'), mov_read_stco },
9205 { MKTAG('c','o','l','r'), mov_read_colr },
9206 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
9207 { MKTAG('d','i','n','f'), mov_read_default },
9208 { MKTAG('D','p','x','E'), mov_read_dpxe },
9209 { MKTAG('d','r','e','f'), mov_read_dref },
9210 { MKTAG('e','d','t','s'), mov_read_default },
9211 { MKTAG('e','l','s','t'), mov_read_elst },
9212 { MKTAG('e','n','d','a'), mov_read_enda },
9213 { MKTAG('f','i','e','l'), mov_read_fiel },
9214 { MKTAG('a','d','r','m'), mov_read_adrm },
9215 { MKTAG('f','t','y','p'), mov_read_ftyp },
9216 { MKTAG('g','l','b','l'), mov_read_glbl },
9217 { MKTAG('h','d','l','r'), mov_read_hdlr },
9218 { MKTAG('i','l','s','t'), mov_read_ilst },
9219 { MKTAG('j','p','2','h'), mov_read_jp2h },
9220 { MKTAG('m','d','a','t'), mov_read_mdat },
9221 { MKTAG('m','d','h','d'), mov_read_mdhd },
9222 { MKTAG('m','d','i','a'), mov_read_default },
9223 { MKTAG('m','e','t','a'), mov_read_meta },
9224 { MKTAG('m','i','n','f'), mov_read_default },
9225 { MKTAG('m','o','o','f'), mov_read_moof },
9226 { MKTAG('m','o','o','v'), mov_read_moov },
9227 { MKTAG('m','v','e','x'), mov_read_default },
9228 { MKTAG('m','v','h','d'), mov_read_mvhd },
9229 { MKTAG('S','M','I',' '), mov_read_svq3 },
9230 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
9231 { MKTAG('a','v','c','C'), mov_read_glbl },
9232 { MKTAG('p','a','s','p'), mov_read_pasp },
9233 { MKTAG('c','l','a','p'), mov_read_clap },
9234 { MKTAG('s','b','a','s'), mov_read_sbas },
9235 { MKTAG('s','i','d','x'), mov_read_sidx },
9236 { MKTAG('s','t','b','l'), mov_read_default },
9237 { MKTAG('s','t','c','o'), mov_read_stco },
9238 { MKTAG('s','t','p','s'), mov_read_stps },
9239 { MKTAG('s','t','r','f'), mov_read_strf },
9240 { MKTAG('s','t','s','c'), mov_read_stsc },
9241 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
9242 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
9243 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
9244 { MKTAG('s','t','t','s'), mov_read_stts },
9245 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
9246 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
9247 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
9248 { MKTAG('t','f','d','t'), mov_read_tfdt },
9249 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
9250 { MKTAG('t','r','a','k'), mov_read_trak },
9251 { MKTAG('t','r','a','f'), mov_read_default },
9252 { MKTAG('t','r','e','f'), mov_read_default },
9253 { MKTAG('t','m','c','d'), mov_read_tmcd },
9254 { MKTAG('c','h','a','p'), mov_read_chap },
9255 { MKTAG('t','r','e','x'), mov_read_trex },
9256 { MKTAG('t','r','u','n'), mov_read_trun },
9257 { MKTAG('u','d','t','a'), mov_read_default },
9258 { MKTAG('w','a','v','e'), mov_read_wave },
9259 { MKTAG('e','s','d','s'), mov_read_esds },
9260 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
9261 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
9262 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
9263 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
9264 { MKTAG('w','f','e','x'), mov_read_wfex },
9265 { MKTAG('c','m','o','v'), mov_read_cmov },
9266 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
9267 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
9268 { MKTAG('d','v','c','1'), mov_read_dvc1 },
9269 { MKTAG('s','g','p','d'), mov_read_sgpd },
9270 { MKTAG('s','b','g','p'), mov_read_sbgp },
9271 { MKTAG('h','v','c','C'), mov_read_glbl },
9272 { MKTAG('v','v','c','C'), mov_read_glbl },
9273 { MKTAG('u','u','i','d'), mov_read_uuid },
9274 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
9275 { MKTAG('f','r','e','e'), mov_read_free },
9276 { MKTAG('-','-','-','-'), mov_read_custom },
9277 { MKTAG('s','i','n','f'), mov_read_default },
9278 { MKTAG('f','r','m','a'), mov_read_frma },
9279 { MKTAG('s','e','n','c'), mov_read_senc },
9280 { MKTAG('s','a','i','z'), mov_read_saiz },
9281 { MKTAG('s','a','i','o'), mov_read_saio },
9282 { MKTAG('p','s','s','h'), mov_read_pssh },
9283 { MKTAG('s','c','h','m'), mov_read_schm },
9284 { MKTAG('s','c','h','i'), mov_read_default },
9285 { MKTAG('t','e','n','c'), mov_read_tenc },
9286 { MKTAG('d','f','L','a'), mov_read_dfla },
9287 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
9288 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
9289 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
9290 { MKTAG('h','f','o','v'), mov_read_hfov },
9291 { MKTAG('d','O','p','s'), mov_read_dops },
9292 { MKTAG('d','m','l','p'), mov_read_dmlp },
9293 { MKTAG('S','m','D','m'), mov_read_smdm },
9294 { MKTAG('C','o','L','L'), mov_read_coll },
9295 { MKTAG('v','p','c','C'), mov_read_vpcc },
9296 { MKTAG('m','d','c','v'), mov_read_mdcv },
9297 { MKTAG('c','l','l','i'), mov_read_clli },
9298 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
9299 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
9300 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
9301 { MKTAG('k','i','n','d'), mov_read_kind },
9302 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
9303 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
9304 { MKTAG('i','l','o','c'), mov_read_iloc },
9305 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
9306 { MKTAG('p','i','t','m'), mov_read_pitm },
9307 { MKTAG('e','v','c','C'), mov_read_glbl },
9308 { MKTAG('i','d','a','t'), mov_read_idat },
9309 { MKTAG('i','m','i','r'), mov_read_imir },
9310 { MKTAG('i','r','e','f'), mov_read_iref },
9311 { MKTAG('i','s','p','e'), mov_read_ispe },
9312 { MKTAG('i','r','o','t'), mov_read_irot },
9313 { MKTAG('i','p','r','p'), mov_read_iprp },
9314 { MKTAG('i','i','n','f'), mov_read_iinf },
9315 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
9316 { MKTAG('l','h','v','C'), mov_read_lhvc },
9317 { MKTAG('l','v','c','C'), mov_read_glbl },
9318 #if CONFIG_IAMFDEC
9319 { MKTAG('i','a','c','b'), mov_read_iacb },
9320 #endif
9321 { 0, NULL }
9322 };
9323
9324 6320 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9325 {
9326 6320 int64_t total_size = 0;
9327 MOVAtom a;
9328 int i;
9329
9330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6320 times.
6320 if (c->atom_depth > 10) {
9331 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
9332 return AVERROR_INVALIDDATA;
9333 }
9334 6320 c->atom_depth ++;
9335
9336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6320 times.
6320 if (atom.size < 0)
9337 atom.size = INT64_MAX;
9338
2/2
✓ Branch 0 taken 18123 times.
✓ Branch 1 taken 5839 times.
23962 while (total_size <= atom.size - 8) {
9339 18123 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
9340 18123 a.size = avio_rb32(pb);
9341 18123 a.type = avio_rl32(pb);
9342
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 18119 times.
18123 if (avio_feof(pb))
9343 4 break;
9344
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 17931 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
18119 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
9345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18119 times.
18119 a.type == MKTAG('h','o','o','v')) &&
9346 a.size >= 8 &&
9347 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
9348 uint32_t type;
9349 avio_skip(pb, 4);
9350 type = avio_rl32(pb);
9351 if (avio_feof(pb))
9352 break;
9353 avio_seek(pb, -8, SEEK_CUR);
9354 if (type == MKTAG('m','v','h','d') ||
9355 type == MKTAG('c','m','o','v')) {
9356 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
9357 a.type = MKTAG('m','o','o','v');
9358 }
9359 }
9360
2/2
✓ Branch 0 taken 15429 times.
✓ Branch 1 taken 2690 times.
18119 if (atom.type != MKTAG('r','o','o','t') &&
9361
2/2
✓ Branch 0 taken 14029 times.
✓ Branch 1 taken 1400 times.
15429 atom.type != MKTAG('m','o','o','v')) {
9362
1/2
✓ Branch 0 taken 14029 times.
✗ Branch 1 not taken.
14029 if (a.type == MKTAG('t','r','a','k') ||
9363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14029 times.
14029 a.type == MKTAG('m','d','a','t')) {
9364 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
9365 avio_skip(pb, -8);
9366 c->atom_depth --;
9367 477 return 0;
9368 }
9369 }
9370 18119 total_size += 8;
9371
3/4
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 18096 times.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
18119 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
9372 23 a.size = avio_rb64(pb) - 8;
9373 23 total_size += 8;
9374 }
9375 18119 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
9376 18119 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
9377
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 18114 times.
18119 if (a.size == 0) {
9378 5 a.size = atom.size - total_size + 8;
9379 }
9380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18119 times.
18119 if (a.size < 0)
9381 break;
9382 18119 a.size -= 8;
9383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18119 times.
18119 if (a.size < 0)
9384 break;
9385 18119 a.size = FFMIN(a.size, atom.size - total_size);
9386
9387
2/2
✓ Branch 0 taken 824548 times.
✓ Branch 1 taken 1841 times.
826389 for (i = 0; mov_default_parse_table[i].type; i++)
9388
2/2
✓ Branch 0 taken 16278 times.
✓ Branch 1 taken 808270 times.
824548 if (mov_default_parse_table[i].type == a.type) {
9389 16278 parse = mov_default_parse_table[i].parse;
9390 16278 break;
9391 }
9392
9393 // container is user data
9394
4/4
✓ Branch 0 taken 1841 times.
✓ Branch 1 taken 16278 times.
✓ Branch 2 taken 1667 times.
✓ Branch 3 taken 174 times.
18119 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
9395
2/2
✓ Branch 0 taken 298 times.
✓ Branch 1 taken 1369 times.
1667 atom.type == MKTAG('i','l','s','t')))
9396 472 parse = mov_read_udta_string;
9397
9398 // Supports parsing the QuickTime Metadata Keys.
9399 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
9400
4/4
✓ Branch 0 taken 1369 times.
✓ Branch 1 taken 16750 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 1358 times.
18119 if (!parse && c->found_hdlr_mdta &&
9401
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 atom.type == MKTAG('m','e','t','a') &&
9402
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 a.type == MKTAG('k','e','y','s') &&
9403
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 c->meta_keys_count == 0) {
9404 11 parse = mov_read_keys;
9405 }
9406
9407
2/2
✓ Branch 0 taken 1358 times.
✓ Branch 1 taken 16761 times.
18119 if (!parse) { /* skip leaf atoms data */
9408 1358 avio_skip(pb, a.size);
9409 } else {
9410 16761 int64_t start_pos = avio_tell(pb);
9411 int64_t left;
9412 16761 int err = parse(c, pb, a);
9413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16761 times.
16761 if (err < 0) {
9414 c->atom_depth --;
9415 return err;
9416 }
9417
5/6
✓ Branch 0 taken 3079 times.
✓ Branch 1 taken 13682 times.
✓ Branch 2 taken 2781 times.
✓ Branch 3 taken 298 times.
✓ Branch 4 taken 2781 times.
✗ Branch 5 not taken.
16761 if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos &&
9418
6/8
✓ Branch 0 taken 2781 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2781 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2773 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 469 times.
✓ Branch 7 taken 2304 times.
5554 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
9419 2773 start_pos + a.size == avio_size(pb))) {
9420
4/6
✓ Branch 0 taken 477 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 477 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 469 times.
477 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
9421 8 c->next_root_atom = start_pos + a.size;
9422 477 c->atom_depth --;
9423 477 return 0;
9424 }
9425 16284 left = a.size - avio_tell(pb) + start_pos;
9426
2/2
✓ Branch 0 taken 1304 times.
✓ Branch 1 taken 14980 times.
16284 if (left > 0) /* skip garbage at atom end */
9427 1304 avio_skip(pb, left);
9428
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14978 times.
14980 else if (left < 0) {
9429 2 av_log(c->fc, AV_LOG_WARNING,
9430 "overread end of atom '%s' by %"PRId64" bytes\n",
9431 2 av_fourcc2str(a.type), -left);
9432 2 avio_seek(pb, left, SEEK_CUR);
9433 }
9434 }
9435
9436 17642 total_size += a.size;
9437 }
9438
9439
4/4
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 5737 times.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 4 times.
5843 if (total_size < atom.size && atom.size < 0x7ffff)
9440 102 avio_skip(pb, atom.size - total_size);
9441
9442 5843 c->atom_depth --;
9443 5843 return 0;
9444 }
9445
9446 7211 static int mov_probe(const AVProbeData *p)
9447 {
9448 int64_t offset;
9449 uint32_t tag;
9450 7211 int score = 0;
9451 7211 int moov_offset = -1;
9452
9453 /* check file header */
9454 7211 offset = 0;
9455 8882 for (;;) {
9456 int64_t size;
9457 16093 int minsize = 8;
9458 /* ignore invalid offset */
9459
2/2
✓ Branch 0 taken 7211 times.
✓ Branch 1 taken 8882 times.
16093 if ((offset + 8ULL) > (unsigned int)p->buf_size)
9460 7211 break;
9461 8882 size = AV_RB32(p->buf + offset);
9462
3/4
✓ Branch 0 taken 519 times.
✓ Branch 1 taken 8363 times.
✓ Branch 2 taken 519 times.
✗ Branch 3 not taken.
8882 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
9463 519 size = AV_RB64(p->buf+offset + 8);
9464 519 minsize = 16;
9465
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 8308 times.
8363 } else if (size == 0) {
9466 55 size = p->buf_size - offset;
9467 }
9468
2/2
✓ Branch 0 taken 397 times.
✓ Branch 1 taken 8485 times.
8882 if (size < minsize) {
9469 397 offset += 4;
9470 397 continue;
9471 }
9472 8485 tag = AV_RL32(p->buf + offset + 4);
9473
5/6
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 830 times.
✓ Branch 2 taken 353 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7178 times.
8485 switch(tag) {
9474 /* check for obvious tags */
9475 123 case MKTAG('m','o','o','v'):
9476 123 moov_offset = offset + 4;
9477 953 case MKTAG('m','d','a','t'):
9478 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
9479 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
9480 case MKTAG('f','t','y','p'):
9481
2/2
✓ Branch 0 taken 433 times.
✓ Branch 1 taken 520 times.
953 if (tag == MKTAG('f','t','y','p') &&
9482
1/2
✓ Branch 0 taken 433 times.
✗ Branch 1 not taken.
433 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
9483
1/2
✓ Branch 0 taken 433 times.
✗ Branch 1 not taken.
433 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
9484
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 427 times.
433 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
9485 )) {
9486 6 score = FFMAX(score, 5);
9487 } else {
9488 947 score = AVPROBE_SCORE_MAX;
9489 }
9490 953 break;
9491 /* those are more common words, so rate then a bit less */
9492 353 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
9493 case MKTAG('w','i','d','e'):
9494 case MKTAG('f','r','e','e'):
9495 case MKTAG('j','u','n','k'):
9496 case MKTAG('p','i','c','t'):
9497 353 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
9498 353 break;
9499 case MKTAG(0x82,0x82,0x7f,0x7d):
9500 score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
9501 break;
9502 1 case MKTAG('s','k','i','p'):
9503 case MKTAG('u','u','i','d'):
9504 case MKTAG('p','r','f','l'):
9505 /* if we only find those cause probedata is too small at least rate them */
9506 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
9507 1 break;
9508 }
9509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8485 times.
8485 if (size > INT64_MAX - offset)
9510 break;
9511 8485 offset += size;
9512 }
9513
4/4
✓ Branch 0 taken 464 times.
✓ Branch 1 taken 6747 times.
✓ Branch 2 taken 123 times.
✓ Branch 3 taken 341 times.
7211 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
9514 /* moov atom in the header - we should make sure that this is not a
9515 * MOV-packed MPEG-PS */
9516 123 offset = moov_offset;
9517
9518
2/2
✓ Branch 0 taken 120608 times.
✓ Branch 1 taken 123 times.
120731 while (offset < (p->buf_size - 16)) { /* Sufficient space */
9519 /* We found an actual hdlr atom */
9520
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 120476 times.
120608 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
9521
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 111 times.
132 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
9522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
9523 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
9524 /* We found a media handler reference atom describing an
9525 * MPEG-PS-in-MOV, return a
9526 * low score to force expanding the probe window until
9527 * mpegps_probe finds what it needs */
9528 return 5;
9529 } else {
9530 /* Keep looking */
9531 120608 offset += 2;
9532 }
9533 }
9534 }
9535
9536 7211 return score;
9537 }
9538
9539 // must be done after parsing all trak because there's no order requirement
9540 2 static void mov_read_chapters(AVFormatContext *s)
9541 {
9542 2 MOVContext *mov = s->priv_data;
9543 MOVStreamContext *sc;
9544 int64_t cur_pos;
9545 int i, j;
9546 int chapter_track;
9547
9548
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
9549 2 AVStream *st = NULL;
9550 2 FFStream *sti = NULL;
9551 2 chapter_track = mov->chapter_tracks[j];
9552
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
9553 4 sc = mov->fc->streams[i]->priv_data;
9554
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
9555 2 st = s->streams[i];
9556 2 break;
9557 }
9558 }
9559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
9560 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
9561 continue;
9562 }
9563 2 sti = ffstream(st);
9564
9565 2 sc = st->priv_data;
9566 2 cur_pos = avio_tell(sc->pb);
9567
9568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
9569 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
9570 if (!st->attached_pic.data && sti->nb_index_entries) {
9571 // Retrieve the first frame, if possible
9572 AVIndexEntry *sample = &sti->index_entries[0];
9573 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9574 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
9575 goto finish;
9576 }
9577
9578 if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
9579 goto finish;
9580 }
9581 } else {
9582 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
9583 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
9584 2 st->discard = AVDISCARD_ALL;
9585
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
9586 8 AVIndexEntry *sample = &sti->index_entries[i];
9587
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;
9588 uint8_t *title;
9589 uint16_t ch;
9590 int len, title_len;
9591
9592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
9593 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
9594 end = AV_NOPTS_VALUE;
9595 }
9596
9597
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9598 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
9599 goto finish;
9600 }
9601
9602 // the first two bytes are the length of the title
9603 8 len = avio_rb16(sc->pb);
9604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
9605 continue;
9606 8 title_len = 2*len + 1;
9607
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
9608 goto finish;
9609
9610 // The samples could theoretically be in any encoding if there's an encd
9611 // atom following, but in practice are only utf-8 or utf-16, distinguished
9612 // instead by the presence of a BOM
9613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
9614 title[0] = 0;
9615 } else {
9616 8 ch = avio_rb16(sc->pb);
9617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
9618 avio_get_str16be(sc->pb, len, title, title_len);
9619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
9620 avio_get_str16le(sc->pb, len, title, title_len);
9621 else {
9622 8 AV_WB16(title, ch);
9623
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)
9624 title[len] = 0;
9625 else
9626 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
9627 }
9628 }
9629
9630 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
9631 8 av_freep(&title);
9632 }
9633 }
9634 2 finish:
9635 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
9636 }
9637 2 }
9638
9639 19 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
9640 int64_t value, int flags)
9641 {
9642 AVTimecode tc;
9643 char buf[AV_TIMECODE_STR_SIZE];
9644 19 AVRational rate = st->avg_frame_rate;
9645 19 int ret = av_timecode_init(&tc, rate, flags, 0, s);
9646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
9647 return ret;
9648 19 av_dict_set(&st->metadata, "timecode",
9649 19 av_timecode_make_string(&tc, buf, value), 0);
9650 19 return 0;
9651 }
9652
9653 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
9654 {
9655 MOVStreamContext *sc = st->priv_data;
9656 FFStream *const sti = ffstream(st);
9657 char buf[AV_TIMECODE_STR_SIZE];
9658 int64_t cur_pos = avio_tell(sc->pb);
9659 int hh, mm, ss, ff, drop;
9660
9661 if (!sti->nb_index_entries)
9662 return -1;
9663
9664 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9665 avio_skip(s->pb, 13);
9666 hh = avio_r8(s->pb);
9667 mm = avio_r8(s->pb);
9668 ss = avio_r8(s->pb);
9669 drop = avio_r8(s->pb);
9670 ff = avio_r8(s->pb);
9671 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
9672 hh, mm, ss, drop ? ';' : ':', ff);
9673 av_dict_set(&st->metadata, "timecode", buf, 0);
9674
9675 avio_seek(sc->pb, cur_pos, SEEK_SET);
9676 return 0;
9677 }
9678
9679 19 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
9680 {
9681 19 MOVStreamContext *sc = st->priv_data;
9682 19 FFStream *const sti = ffstream(st);
9683 19 int flags = 0;
9684 19 int64_t cur_pos = avio_tell(sc->pb);
9685 int64_t value;
9686 19 AVRational tc_rate = st->avg_frame_rate;
9687 19 int tmcd_nb_frames = sc->tmcd_nb_frames;
9688 int rounded_tc_rate;
9689
9690
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!sti->nb_index_entries)
9691 return -1;
9692
9693
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)
9694 return -1;
9695
9696 19 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9697 19 value = avio_rb32(s->pb);
9698
9699
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13 times.
19 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
9700
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
9701
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
9702
9703 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
9704 * not the case) and thus assume "frame number format" instead of QT one.
9705 * No sample with tmcd track can be found with a QT timecode at the moment,
9706 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
9707 * format). */
9708
9709 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
9710 * we multiply the frame number with the quotient.
9711 * See tickets #9492, #9710. */
9712 19 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
9713 /* Work around files where tmcd_nb_frames is rounded down from frame rate
9714 * instead of up. See ticket #5978. */
9715
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
9716
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
9717 10 tmcd_nb_frames = rounded_tc_rate;
9718 19 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
9719
9720 19 parse_timecode_in_framenum_format(s, st, value, flags);
9721
9722 19 avio_seek(sc->pb, cur_pos, SEEK_SET);
9723 19 return 0;
9724 }
9725
9726 1038 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
9727 int i;
9728
3/4
✓ Branch 0 taken 1038 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1034 times.
✓ Branch 3 taken 4 times.
1038 if (!index || !*index) return;
9729
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 4 times.
76 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
9730 72 av_encryption_info_free((*index)->encrypted_samples[i]);
9731 }
9732 4 av_freep(&(*index)->encrypted_samples);
9733 4 av_freep(&(*index)->auxiliary_info_sizes);
9734 4 av_freep(&(*index)->auxiliary_offsets);
9735 4 av_freep(index);
9736 }
9737
9738 671 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
9739 {
9740 671 MOVStreamContext *sc = st->priv_data;
9741
9742
3/4
✓ Branch 0 taken 671 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 631 times.
671 if (!sc || --sc->refcount) {
9743 40 st->priv_data = NULL;
9744 40 return;
9745 }
9746
9747 631 av_freep(&sc->tts_data);
9748
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 631 times.
1225 for (int i = 0; i < sc->drefs_count; i++) {
9749 594 av_freep(&sc->drefs[i].path);
9750 594 av_freep(&sc->drefs[i].dir);
9751 }
9752 631 av_freep(&sc->drefs);
9753
9754 631 sc->drefs_count = 0;
9755
9756
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 617 times.
631 if (!sc->pb_is_copied)
9757 14 ff_format_io_close(s, &sc->pb);
9758
9759 631 sc->pb = NULL;
9760 631 av_freep(&sc->chunk_offsets);
9761 631 av_freep(&sc->stsc_data);
9762 631 av_freep(&sc->sample_sizes);
9763 631 av_freep(&sc->keyframes);
9764 631 av_freep(&sc->ctts_data);
9765 631 av_freep(&sc->stts_data);
9766 631 av_freep(&sc->sdtp_data);
9767 631 av_freep(&sc->stps_data);
9768 631 av_freep(&sc->elst_data);
9769 631 av_freep(&sc->rap_group);
9770 631 av_freep(&sc->sync_group);
9771 631 av_freep(&sc->sgpd_sync);
9772 631 av_freep(&sc->sample_offsets);
9773 631 av_freep(&sc->open_key_samples);
9774 631 av_freep(&sc->display_matrix);
9775 631 av_freep(&sc->index_ranges);
9776
9777
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 37 times.
631 if (sc->extradata)
9778
2/2
✓ Branch 0 taken 605 times.
✓ Branch 1 taken 594 times.
1199 for (int i = 0; i < sc->stsd_count; i++)
9779 605 av_free(sc->extradata[i]);
9780 631 av_freep(&sc->extradata);
9781 631 av_freep(&sc->extradata_size);
9782
9783 631 mov_free_encryption_index(&sc->cenc.encryption_index);
9784 631 av_encryption_info_free(sc->cenc.default_encrypted_sample);
9785 631 av_aes_ctr_free(sc->cenc.aes_ctr);
9786
9787 631 av_freep(&sc->stereo3d);
9788 631 av_freep(&sc->spherical);
9789 631 av_freep(&sc->mastering);
9790 631 av_freep(&sc->coll);
9791 631 av_freep(&sc->ambient);
9792
9793 #if CONFIG_IAMFDEC
9794
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 621 times.
631 if (sc->iamf)
9795 10 ff_iamf_read_deinit(sc->iamf);
9796 #endif
9797 631 av_freep(&sc->iamf);
9798 }
9799
9800 493 static int mov_read_close(AVFormatContext *s)
9801 {
9802 493 MOVContext *mov = s->priv_data;
9803 int i, j;
9804
9805
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 493 times.
1164 for (i = 0; i < s->nb_streams; i++) {
9806 671 AVStream *st = s->streams[i];
9807
9808 671 mov_free_stream_context(s, st);
9809 }
9810
9811 493 av_freep(&mov->dv_demux);
9812 493 avformat_free_context(mov->dv_fctx);
9813 493 mov->dv_fctx = NULL;
9814
9815
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 482 times.
493 if (mov->meta_keys) {
9816
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i < mov->meta_keys_count; i++) {
9817 58 av_freep(&mov->meta_keys[i]);
9818 }
9819 11 av_freep(&mov->meta_keys);
9820 }
9821
9822 493 av_freep(&mov->trex_data);
9823 493 av_freep(&mov->bitrates);
9824
9825
2/2
✓ Branch 0 taken 389 times.
✓ Branch 1 taken 493 times.
882 for (i = 0; i < mov->frag_index.nb_items; i++) {
9826 389 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
9827
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++) {
9828 407 mov_free_encryption_index(&frag[j].encryption_index);
9829 }
9830 389 av_freep(&mov->frag_index.item[i].stream_info);
9831 }
9832 493 av_freep(&mov->frag_index.item);
9833
9834 493 av_freep(&mov->aes_decrypt);
9835 493 av_freep(&mov->chapter_tracks);
9836
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 493 times.
523 for (i = 0; i < mov->nb_heif_item; i++) {
9837
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!mov->heif_item[i])
9838 continue;
9839 30 av_freep(&mov->heif_item[i]->name);
9840 30 av_freep(&mov->heif_item[i]->icc_profile);
9841 30 av_freep(&mov->heif_item[i]);
9842 }
9843 493 av_freep(&mov->heif_item);
9844
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 493 times.
499 for (i = 0; i < mov->nb_heif_grid; i++) {
9845 6 av_freep(&mov->heif_grid[i].tile_id_list);
9846 6 av_freep(&mov->heif_grid[i].tile_idx_list);
9847 6 av_freep(&mov->heif_grid[i].tile_item_list);
9848 }
9849 493 av_freep(&mov->heif_grid);
9850
9851 493 return 0;
9852 }
9853
9854 16 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
9855 {
9856 int i;
9857
9858
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 for (i = 0; i < s->nb_streams; i++) {
9859 24 AVStream *st = s->streams[i];
9860 24 MOVStreamContext *sc = st->priv_data;
9861
9862
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
9863
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 sc->timecode_track == tmcd_id)
9864 14 return 1;
9865 }
9866 2 return 0;
9867 }
9868
9869 /* look for a tmcd track not referenced by any video track, and export it globally */
9870 493 static void export_orphan_timecode(AVFormatContext *s)
9871 {
9872 int i;
9873
9874
2/2
✓ Branch 0 taken 668 times.
✓ Branch 1 taken 491 times.
1159 for (i = 0; i < s->nb_streams; i++) {
9875 668 AVStream *st = s->streams[i];
9876
9877
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 652 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 14 times.
684 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
9878 16 !tmcd_is_referenced(s, i + 1)) {
9879 2 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
9880
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (tcr) {
9881 2 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
9882 2 break;
9883 }
9884 }
9885 }
9886 493 }
9887
9888 static int read_tfra(MOVContext *mov, AVIOContext *f)
9889 {
9890 int version, fieldlength, i, j;
9891 int64_t pos = avio_tell(f);
9892 uint32_t size = avio_rb32(f);
9893 unsigned track_id, item_count;
9894
9895 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
9896 return 1;
9897 }
9898 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
9899
9900 version = avio_r8(f);
9901 avio_rb24(f);
9902 track_id = avio_rb32(f);
9903 fieldlength = avio_rb32(f);
9904 item_count = avio_rb32(f);
9905 for (i = 0; i < item_count; i++) {
9906 int64_t time, offset;
9907 int index;
9908 MOVFragmentStreamInfo * frag_stream_info;
9909
9910 if (avio_feof(f)) {
9911 return AVERROR_INVALIDDATA;
9912 }
9913
9914 if (version == 1) {
9915 time = avio_rb64(f);
9916 offset = avio_rb64(f);
9917 } else {
9918 time = avio_rb32(f);
9919 offset = avio_rb32(f);
9920 }
9921
9922 // The first sample of each stream in a fragment is always a random
9923 // access sample. So it's entry in the tfra can be used as the
9924 // initial PTS of the fragment.
9925 index = update_frag_index(mov, offset);
9926 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
9927 if (frag_stream_info &&
9928 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
9929 frag_stream_info->first_tfra_pts = time;
9930
9931 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
9932 avio_r8(f);
9933 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
9934 avio_r8(f);
9935 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
9936 avio_r8(f);
9937 }
9938
9939 avio_seek(f, pos + size, SEEK_SET);
9940 return 0;
9941 }
9942
9943 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
9944 {
9945 int64_t stream_size = avio_size(f);
9946 int64_t original_pos = avio_tell(f);
9947 int64_t seek_ret;
9948 int ret = -1;
9949 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
9950 ret = seek_ret;
9951 goto fail;
9952 }
9953 c->mfra_size = avio_rb32(f);
9954 c->have_read_mfra_size = 1;
9955 if (!c->mfra_size || c->mfra_size > stream_size) {
9956 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
9957 goto fail;
9958 }
9959 if ((seek_ret = avio_seek(f, -((int64_t) c->mfra_size), SEEK_CUR)) < 0) {
9960 ret = seek_ret;
9961 goto fail;
9962 }
9963 if (avio_rb32(f) != c->mfra_size) {
9964 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
9965 goto fail;
9966 }
9967 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
9968 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
9969 goto fail;
9970 }
9971 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
9972 do {
9973 ret = read_tfra(c, f);
9974 if (ret < 0)
9975 goto fail;
9976 } while (!ret);
9977 ret = 0;
9978 c->frag_index.complete = 1;
9979 fail:
9980 seek_ret = avio_seek(f, original_pos, SEEK_SET);
9981 if (seek_ret < 0) {
9982 av_log(c->fc, AV_LOG_ERROR,
9983 "failed to seek back after looking for mfra\n");
9984 ret = seek_ret;
9985 }
9986 return ret;
9987 }
9988
9989 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
9990 const HEIFItem *item)
9991 {
9992 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
9993 AV_PKT_DATA_ICC_PROFILE,
9994 item->icc_profile_size, 0);
9995 if (!sd)
9996 return AVERROR(ENOMEM);
9997
9998 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
9999
10000 return 0;
10001 }
10002
10003 4 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10004 const HEIFItem *item)
10005 {
10006 int32_t *matrix;
10007 4 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data,
10008 nb_coded_side_data,
10009 AV_PKT_DATA_DISPLAYMATRIX,
10010 9 * sizeof(*matrix), 0);
10011
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sd)
10012 return AVERROR(ENOMEM);
10013
10014 4 matrix = (int32_t*)sd->data;
10015 /* rotation is in the counter-clockwise direction whereas
10016 * av_display_rotation_set() expects its argument to be
10017 * oriented clockwise, so we need to negate it. */
10018 4 av_display_rotation_set(matrix, -item->rotation);
10019 4 av_display_matrix_flip(matrix, item->hflip, item->vflip);
10020
10021 4 return 0;
10022 }
10023
10024 2 static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid,
10025 AVStreamGroupTileGrid *tile_grid)
10026 {
10027 2 MOVContext *c = s->priv_data;
10028 2 const HEIFItem *item = grid->item;
10029 2 int64_t offset = 0, pos = avio_tell(s->pb);
10030 2 int x = 0, y = 0, i = 0;
10031 int tile_rows, tile_cols;
10032 int flags, size;
10033
10034
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10035 av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
10036 return AVERROR_PATCHWELCOME;
10037 }
10038
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (item->is_idat_relative) {
10039
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!c->idat_offset) {
10040 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
10041 return AVERROR_INVALIDDATA;
10042 }
10043 2 offset = c->idat_offset;
10044 }
10045
10046 2 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10047
10048 2 avio_r8(s->pb); /* version */
10049 2 flags = avio_r8(s->pb);
10050
10051 2 tile_rows = avio_r8(s->pb) + 1;
10052 2 tile_cols = avio_r8(s->pb) + 1;
10053 /* actual width and height of output image */
10054
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);
10055
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);
10056
10057 /* ICC profile */
10058
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (item->icc_profile_size) {
10059 int ret = set_icc_profile_from_item(&tile_grid->coded_side_data,
10060 &tile_grid->nb_coded_side_data, item);
10061 if (ret < 0)
10062 return ret;
10063 }
10064 /* rotation */
10065
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) {
10066 int ret = set_display_matrix_from_item(&tile_grid->coded_side_data,
10067 &tile_grid->nb_coded_side_data, item);
10068 if (ret < 0)
10069 return ret;
10070 }
10071
10072 2 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
10073 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
10074
10075 2 avio_seek(s->pb, pos, SEEK_SET);
10076
10077 2 size = tile_rows * tile_cols;
10078 2 tile_grid->nb_tiles = grid->nb_tiles;
10079
10080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tile_grid->nb_tiles != size)
10081 return AVERROR_INVALIDDATA;
10082
10083
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < tile_cols; i++)
10084 4 tile_grid->coded_width += grid->tile_item_list[i]->width;
10085
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < size; i += tile_cols)
10086 4 tile_grid->coded_height += grid->tile_item_list[i]->height;
10087
10088 2 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!tile_grid->offsets)
10090 return AVERROR(ENOMEM);
10091
10092
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 while (y < tile_grid->coded_height) {
10093 4 int left_col = i;
10094
10095
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 while (x < tile_grid->coded_width) {
10096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (i == tile_grid->nb_tiles)
10097 return AVERROR_INVALIDDATA;
10098
10099 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10100 8 tile_grid->offsets[i].horizontal = x;
10101 8 tile_grid->offsets[i].vertical = y;
10102
10103 8 x += grid->tile_item_list[i++]->width;
10104 }
10105
10106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (x > tile_grid->coded_width) {
10107 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10108 return AVERROR_INVALIDDATA;
10109 }
10110
10111 4 x = 0;
10112 4 y += grid->tile_item_list[left_col]->height;
10113 }
10114
10115
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) {
10116 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10117 return AVERROR_INVALIDDATA;
10118 }
10119
10120 2 return 0;
10121 }
10122
10123 4 static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid,
10124 AVStreamGroupTileGrid *tile_grid)
10125 {
10126 4 MOVContext *c = s->priv_data;
10127 4 const HEIFItem *item = grid->item;
10128 uint16_t canvas_fill_value[4];
10129 4 int64_t offset = 0, pos = avio_tell(s->pb);
10130 4 int ret = 0, flags;
10131
10132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10133 av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
10134 return AVERROR_PATCHWELCOME;
10135 }
10136
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
10137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
10138 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
10139 return AVERROR_INVALIDDATA;
10140 }
10141 4 offset = c->idat_offset;
10142 }
10143
10144 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10145
10146 4 avio_r8(s->pb); /* version */
10147 4 flags = avio_r8(s->pb);
10148
10149
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10150 16 canvas_fill_value[i] = avio_rb16(s->pb);
10151 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
10152 4 canvas_fill_value[0], canvas_fill_value[1],
10153 4 canvas_fill_value[2], canvas_fill_value[3]);
10154
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10155 16 tile_grid->background[i] = canvas_fill_value[i];
10156
10157 /* actual width and height of output image */
10158 4 tile_grid->width =
10159
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);
10160 4 tile_grid->height =
10161
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);
10162
10163 /* rotation */
10164
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) {
10165 int ret = set_display_matrix_from_item(&tile_grid->coded_side_data,
10166 &tile_grid->nb_coded_side_data, item);
10167 if (ret < 0)
10168 return ret;
10169 }
10170
10171 /* ICC profile */
10172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (item->icc_profile_size) {
10173 int ret = set_icc_profile_from_item(&tile_grid->coded_side_data,
10174 &tile_grid->nb_coded_side_data, item);
10175 if (ret < 0)
10176 return ret;
10177 }
10178
10179 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
10180 tile_grid->width, tile_grid->height);
10181
10182 4 tile_grid->nb_tiles = grid->nb_tiles;
10183 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
10185 ret = AVERROR(ENOMEM);
10186 goto fail;
10187 }
10188
10189
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
10190 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10191
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);
10192
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);
10193 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
10194 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
10195 8 i, tile_grid->offsets[i].idx,
10196 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
10197 }
10198
10199 4 fail:
10200 4 avio_seek(s->pb, pos, SEEK_SET);
10201
10202 4 return ret;
10203 }
10204
10205 6 static int mov_parse_tiles(AVFormatContext *s)
10206 {
10207 6 MOVContext *mov = s->priv_data;
10208
10209
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (int i = 0; i < mov->nb_heif_grid; i++) {
10210 6 AVStreamGroup *stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
10211 AVStreamGroupTileGrid *tile_grid;
10212 6 const HEIFGrid *grid = &mov->heif_grid[i];
10213 6 int err, loop = 1;
10214
10215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!stg)
10216 return AVERROR(ENOMEM);
10217
10218 6 stg->id = grid->item->item_id;
10219 6 tile_grid = stg->params.tile_grid;
10220
10221
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (int j = 0; j < grid->nb_tiles; j++) {
10222 16 int tile_id = grid->tile_id_list[j];
10223 int k;
10224
10225
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 for (k = 0; k < mov->nb_heif_item; k++) {
10226 30 HEIFItem *item = mov->heif_item[k];
10227 AVStream *st;
10228
10229
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)
10230 14 continue;
10231 16 st = item->st;
10232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!st) {
10233 av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
10234 "reference a stream\n",
10235 tile_id, grid->item->item_id);
10236 ff_remove_stream_group(s, stg);
10237 loop = 0;
10238 break;
10239 }
10240
10241 16 grid->tile_item_list[j] = item;
10242 16 grid->tile_idx_list[j] = stg->nb_streams;
10243
10244 16 err = avformat_stream_group_add_stream(stg, st);
10245
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (err < 0) {
10246 int l;
10247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
10248 return err;
10249
10250
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_streams; l++)
10251
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->streams[l]->index == st->index)
10252 2 break;
10253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_streams);
10254 2 grid->tile_idx_list[j] = l;
10255 }
10256
10257
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
16 if (item->item_id != mov->primary_item_id)
10258 10 st->disposition |= AV_DISPOSITION_DEPENDENT;
10259 16 break;
10260 }
10261
10262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (k == mov->nb_heif_item) {
10263 av_assert0(loop);
10264 av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
10265 "exist\n",
10266 tile_id, grid->item->item_id);
10267 ff_remove_stream_group(s, stg);
10268 loop = 0;
10269 }
10270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!loop)
10271 break;
10272 }
10273
10274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!loop)
10275 continue;
10276
10277
2/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
6 switch (grid->item->type) {
10278 2 case MKTAG('g','r','i','d'):
10279 2 err = read_image_grid(s, grid, tile_grid);
10280 2 break;
10281 4 case MKTAG('i','o','v','l'):
10282 4 err = read_image_iovl(s, grid, tile_grid);
10283 4 break;
10284 default:
10285 av_assert0(0);
10286 }
10287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10288 return err;
10289
10290
10291
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (grid->item->name)
10292 6 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
10293
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (grid->item->item_id == mov->primary_item_id)
10294 2 stg->disposition |= AV_DISPOSITION_DEFAULT;
10295 }
10296
10297 6 return 0;
10298 }
10299
10300 12 static int mov_parse_heif_items(AVFormatContext *s)
10301 {
10302 12 MOVContext *mov = s->priv_data;
10303 int err;
10304
10305
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 for (int i = 0; i < mov->nb_heif_item; i++) {
10306 30 HEIFItem *item = mov->heif_item[i];
10307 MOVStreamContext *sc;
10308 AVStream *st;
10309 30 int64_t offset = 0;
10310
10311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!item)
10312 continue;
10313
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 23 times.
30 if (!item->st) {
10314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (item->item_id == mov->thmb_item_id) {
10315 av_log(s, AV_LOG_ERROR, "HEIF thumbnail doesn't reference a stream\n");
10316 return AVERROR_INVALIDDATA;
10317 }
10318 7 continue;
10319 }
10320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (item->is_idat_relative) {
10321 if (!mov->idat_offset) {
10322 av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
10323 return AVERROR_INVALIDDATA;
10324 }
10325 offset = mov->idat_offset;
10326 }
10327
10328 23 st = item->st;
10329 23 sc = st->priv_data;
10330 23 st->codecpar->width = item->width;
10331 23 st->codecpar->height = item->height;
10332
10333 23 err = sanity_checks(s, sc, item->item_id);
10334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (err)
10335 return AVERROR_INVALIDDATA;
10336
10337 23 sc->sample_sizes[0] = item->extent_length;
10338 23 sc->chunk_offsets[0] = item->extent_offset + offset;
10339
10340
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 13 times.
23 if (item->item_id == mov->primary_item_id)
10341 10 st->disposition |= AV_DISPOSITION_DEFAULT;
10342
10343
4/6
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 19 times.
23 if (item->rotation || item->hflip || item->vflip) {
10344 4 err = set_display_matrix_from_item(&st->codecpar->coded_side_data,
10345 4 &st->codecpar->nb_coded_side_data, item);
10346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
10347 return err;
10348 }
10349
10350 23 mov_build_index(mov, st);
10351 }
10352
10353
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (mov->nb_heif_grid) {
10354 6 err = mov_parse_tiles(s);
10355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10356 return err;
10357 }
10358
10359 12 return 0;
10360 }
10361
10362 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
10363 int first_index)
10364 {
10365 MOVStreamContext *sc = st->priv_data;
10366
10367 if (sc->tref_id < 0)
10368 return NULL;
10369
10370 for (int i = first_index; i < s->nb_streams; i++)
10371 if (s->streams[i]->id == sc->tref_id)
10372 return s->streams[i];
10373
10374 return NULL;
10375 }
10376
10377 493 static int mov_parse_lcevc_streams(AVFormatContext *s)
10378 {
10379 int err;
10380
10381
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 493 times.
1164 for (int i = 0; i < s->nb_streams; i++) {
10382 AVStreamGroup *stg;
10383 671 AVStream *st = s->streams[i];
10384 AVStream *st_base;
10385 671 MOVStreamContext *sc = st->priv_data;
10386 671 int j = 0;
10387
10388 /* Find an enhancement stream. */
10389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 671 times.
671 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC ||
10390 !(sc->tref_flags & MOV_TREF_FLAG_ENHANCEMENT))
10391 671 continue;
10392
10393 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10394
10395 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
10396 if (!stg)
10397 return AVERROR(ENOMEM);
10398
10399 stg->id = st->id;
10400 stg->params.lcevc->width = st->codecpar->width;
10401 stg->params.lcevc->height = st->codecpar->height;
10402 st->codecpar->width = 0;
10403 st->codecpar->height = 0;
10404
10405 while (st_base = mov_find_reference_track(s, st, j)) {
10406 err = avformat_stream_group_add_stream(stg, st_base);
10407 if (err < 0)
10408 return err;
10409
10410 j = st_base->index + 1;
10411 }
10412 if (!j) {
10413 av_log(s, AV_LOG_ERROR, "Failed to find base stream for enhancement stream\n");
10414 return AVERROR_INVALIDDATA;
10415 }
10416
10417 err = avformat_stream_group_add_stream(stg, st);
10418 if (err < 0)
10419 return err;
10420
10421 stg->params.lcevc->lcevc_index = stg->nb_streams - 1;
10422 }
10423
10424 493 return 0;
10425 }
10426
10427 493 static void fix_stream_ids(AVFormatContext *s)
10428 {
10429 493 int highest_id = 0;
10430
10431
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 493 times.
1164 for (int i = 0; i < s->nb_streams; i++) {
10432 671 const AVStream *st = s->streams[i];
10433 671 const MOVStreamContext *sc = st->priv_data;
10434
2/2
✓ Branch 0 taken 621 times.
✓ Branch 1 taken 50 times.
671 if (!sc->iamf)
10435 621 highest_id = FFMAX(highest_id, st->id);
10436 }
10437 493 highest_id += !highest_id;
10438
4/4
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 409 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 84 times.
503 for (int i = 0; highest_id > 1 && i < s->nb_stream_groups; i++) {
10439 10 AVStreamGroup *stg = s->stream_groups[i];
10440
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
10441 8 continue;
10442
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_streams; j++) {
10443 14 AVStream *st = stg->streams[j];
10444 14 MOVStreamContext *sc = st->priv_data;
10445 14 st->id += highest_id;
10446 14 sc->iamf_stream_offset = highest_id;
10447 }
10448 }
10449 493 }
10450
10451 493 static int mov_read_header(AVFormatContext *s)
10452 {
10453 493 MOVContext *mov = s->priv_data;
10454 493 AVIOContext *pb = s->pb;
10455 int j, err;
10456 493 MOVAtom atom = { AV_RL32("root") };
10457 int i;
10458
10459
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 490 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
493 if (mov->decryption_key_len != 0 && mov->decryption_key_len != AES_CTR_KEY_SIZE) {
10460 av_log(s, AV_LOG_ERROR, "Invalid decryption key len %d expected %d\n",
10461 mov->decryption_key_len, AES_CTR_KEY_SIZE);
10462 return AVERROR(EINVAL);
10463 }
10464
10465 493 mov->fc = s;
10466 493 mov->trak_index = -1;
10467 493 mov->thmb_item_id = -1;
10468 493 mov->primary_item_id = -1;
10469 493 mov->cur_item_id = -1;
10470 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
10471
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
10472 493 atom.size = avio_size(pb);
10473 else
10474 atom.size = INT64_MAX;
10475
10476 /* check MOV header */
10477 do {
10478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (mov->moov_retry)
10479 avio_seek(pb, 0, SEEK_SET);
10480
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 493 times.
493 if ((err = mov_read_default(mov, pb, atom)) < 0) {
10481 av_log(s, AV_LOG_ERROR, "error reading header\n");
10482 return err;
10483 }
10484 986 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10485
5/10
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 481 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
493 !mov->found_moov && (!mov->found_iloc || !mov->found_iinf) && !mov->moov_retry++);
10486
3/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 481 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
493 if (!mov->found_moov && !mov->found_iloc && !mov->found_iinf) {
10487 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
10488 return AVERROR_INVALIDDATA;
10489 }
10490 493 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
10491
10492
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 481 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
493 if (mov->found_iloc && mov->found_iinf) {
10493 12 err = mov_parse_heif_items(s);
10494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (err < 0)
10495 return err;
10496 }
10497 // prevent iloc and iinf boxes from being parsed while reading packets.
10498 // this is needed because an iinf box may have been parsed but ignored
10499 // for having old infe boxes which create no streams.
10500 493 mov->found_iloc = mov->found_iinf = 1;
10501
10502
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
10503
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 491 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
493 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
10504 2 mov_read_chapters(s);
10505
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 493 times.
1164 for (i = 0; i < s->nb_streams; i++)
10506
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 652 times.
671 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
10507 19 mov_read_timecode_track(s, s->streams[i]);
10508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 652 times.
652 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
10509 mov_read_rtmd_track(s, s->streams[i]);
10510 }
10511 }
10512
10513 /* copy timecode metadata from tmcd tracks to the related video streams */
10514
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 493 times.
1164 for (i = 0; i < s->nb_streams; i++) {
10515 671 AVStream *st = s->streams[i];
10516 671 MOVStreamContext *sc = st->priv_data;
10517
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 653 times.
671 if (sc->timecode_track > 0) {
10518 AVDictionaryEntry *tcr;
10519 18 int tmcd_st_id = -1;
10520
10521
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 18 times.
66 for (j = 0; j < s->nb_streams; j++) {
10522 48 MOVStreamContext *sc2 = s->streams[j]->priv_data;
10523
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 30 times.
48 if (sc2->id == sc->timecode_track)
10524 18 tmcd_st_id = j;
10525 }
10526
10527
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)
10528 continue;
10529 18 tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
10530
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 if (tcr)
10531 16 av_dict_set(&st->metadata, "timecode", tcr->value, 0);
10532 }
10533 }
10534 493 export_orphan_timecode(s);
10535
10536 /* Create LCEVC stream groups. */
10537 493 err = mov_parse_lcevc_streams(s);
10538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (err < 0)
10539 return err;
10540
10541
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 493 times.
1164 for (i = 0; i < s->nb_streams; i++) {
10542 671 AVStream *st = s->streams[i];
10543 671 FFStream *const sti = ffstream(st);
10544 671 MOVStreamContext *sc = st->priv_data;
10545 671 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
10546 671 fix_timescale(mov, sc);
10547
2/2
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 390 times.
671 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
10548
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 165 times.
281 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
10549 116 sti->skip_samples = sc->start_pad;
10550 }
10551
5/6
✓ Branch 0 taken 339 times.
✓ Branch 1 taken 332 times.
✓ Branch 2 taken 302 times.
✓ Branch 3 taken 37 times.
✓ Branch 4 taken 302 times.
✗ Branch 5 not taken.
671 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
10552 302 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
10553 302 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
10554
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 663 times.
671 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
10555
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) {
10556 4 st->codecpar->width = sc->width;
10557 4 st->codecpar->height = sc->height;
10558 }
10559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
10560 st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
10561
10562 for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
10563 dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
10564
10565 err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
10566 if (err < 0)
10567 return err;
10568
10569 av_freep(&st->codecpar->extradata);
10570 st->codecpar->extradata_size = 0;
10571
10572 err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
10573 st->codecpar);
10574 if (err < 0)
10575 return err;
10576 }
10577 }
10578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 671 times.
671 if (mov->handbrake_version &&
10579 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
10580 st->codecpar->codec_id == AV_CODEC_ID_MP3) {
10581 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
10582 sti->need_parsing = AVSTREAM_PARSE_FULL;
10583 }
10584 }
10585
10586
3/4
✓ Branch 0 taken 481 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 481 times.
493 if (mov->trex_data || mov->use_mfra_for > 0) {
10587
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 12 times.
29 for (i = 0; i < s->nb_streams; i++) {
10588 17 AVStream *st = s->streams[i];
10589 17 MOVStreamContext *sc = st->priv_data;
10590
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 3 times.
17 if (sc->duration_for_fps > 0) {
10591 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
10592 14 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
10593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (st->codecpar->bit_rate == INT64_MIN) {
10594 av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
10595 sc->data_size, sc->time_scale);
10596 st->codecpar->bit_rate = 0;
10597 if (s->error_recognition & AV_EF_EXPLODE)
10598 return AVERROR_INVALIDDATA;
10599 }
10600 }
10601 }
10602 }
10603
10604
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
493 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
10605 if (mov->bitrates[i]) {
10606 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
10607 }
10608 }
10609
10610 493 ff_rfps_calculate(s);
10611
10612
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 493 times.
1164 for (i = 0; i < s->nb_streams; i++) {
10613 671 AVStream *st = s->streams[i];
10614 671 MOVStreamContext *sc = st->priv_data;
10615
10616
3/3
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 339 times.
✓ Branch 2 taken 51 times.
671 switch (st->codecpar->codec_type) {
10617 281 case AVMEDIA_TYPE_AUDIO:
10618 281 err = ff_replaygain_export(st, s->metadata);
10619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 281 times.
281 if (err < 0)
10620 return err;
10621 281 break;
10622 339 case AVMEDIA_TYPE_VIDEO:
10623
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 331 times.
339 if (sc->display_matrix) {
10624
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,
10625 AV_PKT_DATA_DISPLAYMATRIX,
10626 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
10627 return AVERROR(ENOMEM);
10628
10629 8 sc->display_matrix = NULL;
10630 }
10631
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 335 times.
339 if (sc->stereo3d) {
10632
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,
10633 AV_PKT_DATA_STEREO3D,
10634 4 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
10635 return AVERROR(ENOMEM);
10636
10637 4 sc->stereo3d = NULL;
10638 }
10639
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 335 times.
339 if (sc->spherical) {
10640
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,
10641 AV_PKT_DATA_SPHERICAL,
10642 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
10643 return AVERROR(ENOMEM);
10644
10645 4 sc->spherical = NULL;
10646 }
10647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 339 times.
339 if (sc->mastering) {
10648 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10649 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
10650 (uint8_t *)sc->mastering, sc->mastering_size, 0))
10651 return AVERROR(ENOMEM);
10652
10653 sc->mastering = NULL;
10654 }
10655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 339 times.
339 if (sc->coll) {
10656 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10657 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
10658 (uint8_t *)sc->coll, sc->coll_size, 0))
10659 return AVERROR(ENOMEM);
10660
10661 sc->coll = NULL;
10662 }
10663
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 335 times.
339 if (sc->ambient) {
10664
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,
10665 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
10666 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
10667 return AVERROR(ENOMEM);
10668
10669 4 sc->ambient = NULL;
10670 }
10671 339 break;
10672 }
10673 }
10674
10675 493 fix_stream_ids(s);
10676
10677 493 ff_configure_buffers_for_index(s, AV_TIME_BASE);
10678
10679
2/2
✓ Branch 0 taken 389 times.
✓ Branch 1 taken 493 times.
882 for (i = 0; i < mov->frag_index.nb_items; i++)
10680
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)
10681 385 mov->frag_index.item[i].headers_read = 1;
10682
10683 493 return 0;
10684 }
10685
10686 103932 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
10687 {
10688 103932 AVIndexEntry *sample = NULL;
10689 103932 int64_t best_dts = INT64_MAX;
10690 int i;
10691 103932 MOVContext *mov = s->priv_data;
10692
2/4
✓ Branch 0 taken 103932 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 103932 times.
103932 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
10693
2/2
✓ Branch 0 taken 133841 times.
✓ Branch 1 taken 103932 times.
237773 for (i = 0; i < s->nb_streams; i++) {
10694 133841 AVStream *avst = s->streams[i];
10695 133841 FFStream *const avsti = ffstream(avst);
10696 133841 MOVStreamContext *msc = avst->priv_data;
10697
4/4
✓ Branch 0 taken 125603 times.
✓ Branch 1 taken 8238 times.
✓ Branch 2 taken 122325 times.
✓ Branch 3 taken 3278 times.
133841 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
10698 122325 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
10699 122325 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
10700
2/2
✓ Branch 0 taken 108614 times.
✓ Branch 1 taken 13711 times.
122325 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
10701 122325 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
10702
3/6
✓ Branch 0 taken 18881 times.
✓ Branch 1 taken 103444 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18881 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
122325 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
10703
1/2
✓ Branch 0 taken 18881 times.
✗ Branch 1 not taken.
18881 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10704
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 18881 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 18881 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18881 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 16770 times.
✓ Branch 9 taken 2111 times.
18881 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
10705
4/4
✓ Branch 0 taken 8645 times.
✓ Branch 1 taken 8125 times.
✓ Branch 2 taken 2111 times.
✓ Branch 3 taken 8645 times.
18881 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
10706
2/2
✓ Branch 0 taken 714 times.
✓ Branch 1 taken 1397 times.
2111 (dtsdiff > AV_TIME_BASE && dts < best_dts)))))) {
10707 112283 sample = current_sample;
10708 112283 best_dts = dts;
10709 112283 *st = avst;
10710 }
10711 }
10712 }
10713 103932 return sample;
10714 }
10715
10716 9 static int should_retry(AVIOContext *pb, int error_code) {
10717
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))
10718 9 return 0;
10719
10720 return 1;
10721 }
10722
10723 42 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
10724 {
10725 int ret;
10726 42 MOVContext *mov = s->priv_data;
10727
10728
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)
10729 target = mov->frag_index.item[index].moof_offset;
10730
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) {
10731 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
10732 return AVERROR_INVALIDDATA;
10733 }
10734
10735 42 mov->next_root_atom = 0;
10736
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)
10737 42 index = search_frag_moof_offset(&mov->frag_index, target);
10738
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 &&
10739
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 mov->frag_index.item[index].moof_offset == target) {
10740
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (index + 1 < mov->frag_index.nb_items)
10741 35 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
10742
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (mov->frag_index.item[index].headers_read)
10743 35 return 0;
10744 3 mov->frag_index.item[index].headers_read = 1;
10745 }
10746
10747 7 mov->found_mdat = 0;
10748
10749 7 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
10750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
10751 return ret;
10752
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 3 times.
7 if (avio_feof(s->pb))
10753 4 return AVERROR_EOF;
10754 3 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
10755
10756 3 return 1;
10757 }
10758
10759 16 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
10760 {
10761 16 MOVStreamContext *sc = st->priv_data;
10762 uint8_t *side, *extradata;
10763 int extradata_size;
10764
10765 /* Save the current index. */
10766 16 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
10767
10768 /* Notify the decoder that extradata changed. */
10769 16 extradata_size = sc->extradata_size[sc->last_stsd_index];
10770 16 extradata = sc->extradata[sc->last_stsd_index];
10771
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) {
10772 13 side = av_packet_new_side_data(pkt,
10773 AV_PKT_DATA_NEW_EXTRADATA,
10774 extradata_size);
10775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!side)
10776 return AVERROR(ENOMEM);
10777 13 memcpy(side, extradata, extradata_size);
10778 }
10779
10780 16 return 0;
10781 }
10782
10783 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
10784 {
10785 /* We can't make assumptions about the structure of the payload,
10786 because it may include multiple cdat and cdt2 samples. */
10787 const uint32_t cdat = AV_RB32("cdat");
10788 const uint32_t cdt2 = AV_RB32("cdt2");
10789 int ret, out_size = 0;
10790
10791 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
10792 if (src_size < 10)
10793 return AVERROR_INVALIDDATA;
10794
10795 /* avoid an int overflow: */
10796 if ((src_size - 8) / 2 >= INT_MAX / 3)
10797 return AVERROR_INVALIDDATA;
10798
10799 ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
10800 if (ret < 0)
10801 return ret;
10802
10803 /* parse and re-format the c608 payload in one pass. */
10804 while (src_size >= 10) {
10805 const uint32_t atom_size = avio_rb32(pb);
10806 const uint32_t atom_type = avio_rb32(pb);
10807 const uint32_t data_size = atom_size - 8;
10808 const uint8_t cc_field =
10809 atom_type == cdat ? 1 :
10810 atom_type == cdt2 ? 2 :
10811 0;
10812
10813 /* account for bytes consumed for atom size and type. */
10814 src_size -= 8;
10815
10816 /* make sure the data size stays within the buffer boundaries. */
10817 if (data_size < 2 || data_size > src_size) {
10818 ret = AVERROR_INVALIDDATA;
10819 break;
10820 }
10821
10822 /* make sure the data size is consistent with N byte pairs. */
10823 if (data_size % 2 != 0) {
10824 ret = AVERROR_INVALIDDATA;
10825 break;
10826 }
10827
10828 if (!cc_field) {
10829 /* neither cdat or cdt2 ... skip it */
10830 avio_skip(pb, data_size);
10831 src_size -= data_size;
10832 continue;
10833 }
10834
10835 for (uint32_t i = 0; i < data_size; i += 2) {
10836 pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
10837 pkt->data[out_size + 1] = avio_r8(pb);
10838 pkt->data[out_size + 2] = avio_r8(pb);
10839 out_size += 3;
10840 src_size -= 2;
10841 }
10842 }
10843
10844 if (src_size > 0)
10845 /* skip any remaining unread portion of the input payload */
10846 avio_skip(pb, src_size);
10847
10848 av_shrink_packet(pkt, out_size);
10849 return ret;
10850 }
10851
10852 103400 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
10853 int64_t current_index, AVPacket *pkt)
10854 {
10855 103400 MOVStreamContext *sc = st->priv_data;
10856
10857 103400 pkt->stream_index = sc->ffindex;
10858 103400 pkt->dts = sample->timestamp;
10859
2/2
✓ Branch 0 taken 237 times.
✓ Branch 1 taken 103163 times.
103400 if (sample->flags & AVINDEX_DISCARD_FRAME) {
10860 237 pkt->flags |= AV_PKT_FLAG_DISCARD;
10861 }
10862
4/4
✓ Branch 0 taken 83531 times.
✓ Branch 1 taken 19869 times.
✓ Branch 2 taken 83519 times.
✓ Branch 3 taken 12 times.
103400 if (sc->stts_count && sc->tts_index < sc->tts_count)
10863 83519 pkt->duration = sc->tts_data[sc->tts_index].duration;
10864
3/4
✓ Branch 0 taken 3010 times.
✓ Branch 1 taken 100390 times.
✓ Branch 2 taken 3010 times.
✗ Branch 3 not taken.
103400 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
10865 3010 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
10866 } else {
10867
2/2
✓ Branch 0 taken 15786 times.
✓ Branch 1 taken 84604 times.
100390 if (pkt->duration == 0) {
10868 15786 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
10869
2/2
✓ Branch 0 taken 15713 times.
✓ Branch 1 taken 73 times.
15786 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
10870
2/2
✓ Branch 0 taken 15760 times.
✓ Branch 1 taken 26 times.
15786 if (next_dts >= pkt->dts)
10871 15760 pkt->duration = next_dts - pkt->dts;
10872 }
10873 100390 pkt->pts = pkt->dts;
10874 }
10875
10876
4/4
✓ Branch 0 taken 83531 times.
✓ Branch 1 taken 19869 times.
✓ Branch 2 taken 83519 times.
✓ Branch 3 taken 12 times.
103400 if (sc->tts_data && sc->tts_index < sc->tts_count) {
10877 /* update tts context */
10878 83519 sc->tts_sample++;
10879
1/2
✓ Branch 0 taken 83519 times.
✗ Branch 1 not taken.
83519 if (sc->tts_index < sc->tts_count &&
10880
1/2
✓ Branch 0 taken 83519 times.
✗ Branch 1 not taken.
83519 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
10881 83519 sc->tts_index++;
10882 83519 sc->tts_sample = 0;
10883 }
10884 }
10885
10886
4/4
✓ Branch 0 taken 1037 times.
✓ Branch 1 taken 102363 times.
✓ Branch 2 taken 905 times.
✓ Branch 3 taken 132 times.
103400 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
10887 905 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
10888 905 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
10889
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 591 times.
905 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
10890 }
10891 103400 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
10892 103400 pkt->pos = sample->pos;
10893
10894 /* Multiple stsd handling. */
10895
2/2
✓ Branch 0 taken 102609 times.
✓ Branch 1 taken 791 times.
103400 if (sc->stsc_data) {
10896
1/2
✓ Branch 0 taken 102609 times.
✗ Branch 1 not taken.
102609 if (sc->stsc_data[sc->stsc_index].id > 0 &&
10897
2/2
✓ Branch 0 taken 102586 times.
✓ Branch 1 taken 23 times.
102609 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
10898
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 102570 times.
102586 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
10899 16 int ret = mov_change_extradata(st, pkt);
10900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0)
10901 return ret;
10902 }
10903
10904 /* Update the stsc index for the next sample */
10905 102609 sc->stsc_sample++;
10906
2/2
✓ Branch 1 taken 55158 times.
✓ Branch 2 taken 47451 times.
102609 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
10907
2/2
✓ Branch 1 taken 1190 times.
✓ Branch 2 taken 53968 times.
55158 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
10908 1190 sc->stsc_index++;
10909 1190 sc->stsc_sample = 0;
10910 }
10911 }
10912
10913 103400 return 0;
10914 }
10915
10916 97072 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
10917 {
10918 97072 MOVContext *mov = s->priv_data;
10919 MOVStreamContext *sc;
10920 AVIndexEntry *sample;
10921 97072 AVStream *st = NULL;
10922 97072 FFStream *avsti = NULL;
10923 int64_t current_index;
10924 int ret;
10925 int i;
10926 97072 mov->fc = s;
10927 6860 retry:
10928
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103932 times.
103932 if (s->pb->pos == 0) {
10929
10930 // Discard current fragment index
10931 if (mov->frag_index.allocated_size > 0) {
10932 for(int i = 0; i < mov->frag_index.nb_items; i++) {
10933 av_freep(&mov->frag_index.item[i].stream_info);
10934 }
10935 av_freep(&mov->frag_index.item);
10936 mov->frag_index.nb_items = 0;
10937 mov->frag_index.allocated_size = 0;
10938 mov->frag_index.current = -1;
10939 mov->frag_index.complete = 0;
10940 }
10941
10942 for (i = 0; i < s->nb_streams; i++) {
10943 AVStream *avst = s->streams[i];
10944 MOVStreamContext *msc = avst->priv_data;
10945
10946 // Clear current sample
10947 mov_current_sample_set(msc, 0);
10948 msc->tts_index = 0;
10949
10950 // Discard current index entries
10951 avsti = ffstream(avst);
10952 if (avsti->index_entries_allocated_size > 0) {
10953 av_freep(&avsti->index_entries);
10954 avsti->index_entries_allocated_size = 0;
10955 avsti->nb_index_entries = 0;
10956 }
10957 }
10958
10959 if ((ret = mov_switch_root(s, -1, -1)) < 0)
10960 return ret;
10961 }
10962 103932 sample = mov_find_next_sample(s, &st);
10963
6/6
✓ Branch 0 taken 103444 times.
✓ Branch 1 taken 488 times.
✓ Branch 2 taken 472 times.
✓ Branch 3 taken 102972 times.
✓ Branch 4 taken 35 times.
✓ Branch 5 taken 437 times.
103932 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
10964
2/2
✓ Branch 0 taken 481 times.
✓ Branch 1 taken 42 times.
523 if (!mov->next_root_atom)
10965 481 return AVERROR_EOF;
10966
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)
10967 4 return ret;
10968 38 goto retry;
10969 }
10970 103409 sc = st->priv_data;
10971 /* must be done just before reading, to avoid infinite loop on sample */
10972 103409 current_index = sc->current_index;
10973 103409 mov_current_sample_inc(sc);
10974
10975
2/2
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 102972 times.
103409 if (mov->next_root_atom) {
10976 437 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
10977 437 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
10978 }
10979
10980
2/2
✓ Branch 0 taken 96587 times.
✓ Branch 1 taken 6822 times.
103409 if (st->discard != AVDISCARD_ALL) {
10981 96587 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
10982
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 96580 times.
96587 if (ret64 != sample->pos) {
10983 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
10984 sc->ffindex, sample->pos);
10985
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
10986 mov_current_sample_dec(sc);
10987
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
10988 7 return (int)ret64;
10989 }
10990 return AVERROR_INVALIDDATA;
10991 }
10992
10993
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96580 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96580 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
10994 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
10995 goto retry;
10996 }
10997
10998
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96580 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96580 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
10999 ret = get_eia608_packet(sc->pb, pkt, sample->size);
11000 #if CONFIG_IAMFDEC
11001
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 96525 times.
96580 else if (sc->iamf) {
11002 int64_t pts, dts, pos, duration;
11003 55 int flags, size = sample->size;
11004 55 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11005 55 pts = pkt->pts; dts = pkt->dts;
11006 55 pos = pkt->pos; flags = pkt->flags;
11007 55 duration = pkt->duration;
11008
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) {
11009 275 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
11010
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
275 if (ret < 0) {
11011 if (should_retry(sc->pb, ret))
11012 mov_current_sample_dec(sc);
11013 return ret;
11014 }
11015 275 size -= ret;
11016 275 pkt->pts = pts; pkt->dts = dts;
11017 275 pkt->pos = pos; pkt->flags |= flags;
11018 275 pkt->duration = duration;
11019 275 ret = ff_buffer_packet(s, pkt);
11020 }
11021
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 if (!ret)
11022 55 return FFERROR_REDO;
11023 }
11024 #endif
11025 else
11026 96525 ret = av_get_packet(sc->pb, pkt, sample->size);
11027
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 96523 times.
96525 if (ret < 0) {
11028
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (should_retry(sc->pb, ret)) {
11029 mov_current_sample_dec(sc);
11030 }
11031 2 return ret;
11032 }
11033 #if CONFIG_DV_DEMUXER
11034
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96523 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96523 if (mov->dv_demux && sc->dv_audio_container) {
11035 ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
11036 av_packet_unref(pkt);
11037 if (ret < 0)
11038 return ret;
11039 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
11040 if (ret < 0)
11041 return ret;
11042 }
11043 #endif
11044
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 96505 times.
96523 if (sc->has_palette) {
11045 uint8_t *pal;
11046
11047 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
11048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
11049 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
11050 } else {
11051 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
11052 18 sc->has_palette = 0;
11053 }
11054 }
11055
4/6
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 96235 times.
✓ Branch 3 taken 288 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 288 times.
✗ Branch 6 not taken.
96523 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
11056
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 288 times.
288 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
11057 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
11058 }
11059 }
11060
11061 103345 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103345 times.
103345 if (ret < 0)
11063 return ret;
11064
11065
2/2
✓ Branch 0 taken 6822 times.
✓ Branch 1 taken 96523 times.
103345 if (st->discard == AVDISCARD_ALL)
11066 6822 goto retry;
11067
11068
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96523 times.
96523 if (mov->aax_mode)
11069 aax_filter(pkt->data, pkt->size, mov);
11070
11071 96523 ret = cenc_filter(mov, st, sc, pkt, current_index);
11072
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96523 times.
96523 if (ret < 0) {
11073 return ret;
11074 }
11075
11076 96523 return 0;
11077 }
11078
11079 361 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
11080 {
11081 361 MOVContext *mov = s->priv_data;
11082 int index;
11083
11084
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 26 times.
361 if (!mov->frag_index.complete)
11085 335 return 0;
11086
11087 26 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
11088
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 22 times.
26 if (index < 0)
11089 4 index = 0;
11090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (!mov->frag_index.item[index].headers_read)
11091 return mov_switch_root(s, -1, index);
11092
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (index + 1 < mov->frag_index.nb_items)
11093 26 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11094
11095 26 return 0;
11096 }
11097
11098 static int is_open_key_sample(const MOVStreamContext *sc, int sample)
11099 {
11100 // TODO: a bisect search would scale much better
11101 for (int i = 0; i < sc->open_key_samples_count; i++) {
11102 const int oks = sc->open_key_samples[i];
11103 if (oks == sample)
11104 return 1;
11105 if (oks > sample) /* list is monotically increasing so we can stop early */
11106 break;
11107 }
11108 return 0;
11109 }
11110
11111 /*
11112 * Some key sample may be key frames but not IDR frames, so a random access to
11113 * them may not be allowed.
11114 */
11115 229 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
11116 {
11117 229 MOVStreamContext *sc = st->priv_data;
11118 229 FFStream *const sti = ffstream(st);
11119 int64_t key_sample_dts, key_sample_pts;
11120
11121
1/2
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
229 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
11122 229 return 1;
11123
11124 if (sample >= sc->sample_offsets_count)
11125 return 1;
11126
11127 key_sample_dts = sti->index_entries[sample].timestamp;
11128 key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
11129
11130 /*
11131 * If the sample needs to be presented before an open key sample, they may
11132 * not be decodable properly, even though they come after in decoding
11133 * order.
11134 */
11135 if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
11136 return 0;
11137
11138 return 1;
11139 }
11140
11141 361 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
11142 {
11143 361 MOVStreamContext *sc = st->priv_data;
11144 361 FFStream *const sti = ffstream(st);
11145 int sample, time_sample, ret, next_ts, requested_sample;
11146 unsigned int i;
11147
11148 // Here we consider timestamp to be PTS, hence try to offset it so that we
11149 // can search over the DTS timeline.
11150 361 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
11151
11152 361 ret = mov_seek_fragment(s, st, timestamp);
11153
1/2
✓ Branch 0 taken 361 times.
✗ Branch 1 not taken.
361 if (ret < 0)
11154 return ret;
11155
11156 for (;;) {
11157 361 sample = av_index_search_timestamp(st, timestamp, flags);
11158 361 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
11159
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)
11160 43 sample = 0;
11161
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 335 times.
361 if (sample < 0) /* not sure what to do */
11162 26 return AVERROR_INVALIDDATA;
11163
11164
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))
11165 break;
11166
11167 next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
11168 requested_sample = av_index_search_timestamp(st, next_ts, flags);
11169
11170 // If we've reached a different sample trying to find a good pts to
11171 // seek to, give up searching because we'll end up seeking back to
11172 // sample 0 on every seek.
11173 if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
11174 break;
11175
11176 timestamp = next_ts;
11177 }
11178
11179 335 mov_current_sample_set(sc, sample);
11180 335 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
11181 /* adjust time to sample index */
11182
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 125 times.
335 if (sc->tts_data) {
11183 210 time_sample = 0;
11184
1/2
✓ Branch 0 taken 60235 times.
✗ Branch 1 not taken.
60235 for (i = 0; i < sc->tts_count; i++) {
11185 60235 int next = time_sample + sc->tts_data[i].count;
11186
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 60025 times.
60235 if (next > sc->current_sample) {
11187 210 sc->tts_index = i;
11188 210 sc->tts_sample = sc->current_sample - time_sample;
11189 210 break;
11190 }
11191 60025 time_sample = next;
11192 }
11193 }
11194
11195 /* adjust stsd index */
11196
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 26 times.
335 if (sc->chunk_count) {
11197 309 time_sample = 0;
11198
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
381 for (i = 0; i < sc->stsc_count; i++) {
11199 381 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
11200
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 72 times.
381 if (next > sc->current_sample) {
11201 309 sc->stsc_index = i;
11202 309 sc->stsc_sample = sc->current_sample - time_sample;
11203 309 break;
11204 }
11205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
11206 72 time_sample = next;
11207 }
11208 }
11209
11210 335 return sample;
11211 }
11212
11213 335 static int64_t mov_get_skip_samples(AVStream *st, int sample)
11214 {
11215 335 MOVStreamContext *sc = st->priv_data;
11216 335 FFStream *const sti = ffstream(st);
11217 335 int64_t first_ts = sti->index_entries[0].timestamp;
11218 335 int64_t ts = sti->index_entries[sample].timestamp;
11219 int64_t off;
11220
11221
2/2
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 151 times.
335 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
11222 184 return 0;
11223
11224 /* compute skip samples according to stream start_pad, seek ts and first ts */
11225 151 off = av_rescale_q(ts - first_ts, st->time_base,
11226 151 (AVRational){1, st->codecpar->sample_rate});
11227 151 return FFMAX(sc->start_pad - off, 0);
11228 }
11229
11230 340 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
11231 {
11232 340 MOVContext *mc = s->priv_data;
11233 AVStream *st;
11234 FFStream *sti;
11235 int sample;
11236 int i;
11237
11238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 340 times.
340 if (stream_index >= s->nb_streams)
11239 return AVERROR_INVALIDDATA;
11240
11241 340 st = s->streams[stream_index];
11242 340 sti = ffstream(st);
11243 340 sample = mov_seek_stream(s, st, sample_time, flags);
11244
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 314 times.
340 if (sample < 0)
11245 26 return sample;
11246
11247
1/2
✓ Branch 0 taken 314 times.
✗ Branch 1 not taken.
314 if (mc->seek_individually) {
11248 /* adjust seek timestamp to found sample timestamp */
11249 314 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
11250 314 sti->skip_samples = mov_get_skip_samples(st, sample);
11251
11252
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 314 times.
649 for (i = 0; i < s->nb_streams; i++) {
11253 335 AVStream *const st = s->streams[i];
11254 335 FFStream *const sti = ffstream(st);
11255 int64_t timestamp;
11256
11257
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 21 times.
335 if (stream_index == i)
11258 314 continue;
11259
11260 21 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
11261 21 sample = mov_seek_stream(s, st, timestamp, flags);
11262
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (sample >= 0)
11263 21 sti->skip_samples = mov_get_skip_samples(st, sample);
11264 }
11265 } else {
11266 for (i = 0; i < s->nb_streams; i++) {
11267 MOVStreamContext *sc;
11268 st = s->streams[i];
11269 sc = st->priv_data;
11270 mov_current_sample_set(sc, 0);
11271 }
11272 while (1) {
11273 MOVStreamContext *sc;
11274 AVIndexEntry *entry = mov_find_next_sample(s, &st);
11275 if (!entry)
11276 return AVERROR_INVALIDDATA;
11277 sc = st->priv_data;
11278 if (sc->ffindex == stream_index && sc->current_sample == sample)
11279 break;
11280 mov_current_sample_inc(sc);
11281 }
11282 }
11283 314 return 0;
11284 }
11285
11286 #define OFFSET(x) offsetof(MOVContext, x)
11287 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
11288 static const AVOption mov_options[] = {
11289 {"use_absolute_path",
11290 "allow using absolute path when opening alias, this is a possible security issue",
11291 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
11292 0, 1, FLAGS},
11293 {"seek_streams_individually",
11294 "Seek each stream individually to the closest point",
11295 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
11296 0, 1, FLAGS},
11297 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
11298 0, 1, FLAGS},
11299 {"advanced_editlist",
11300 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
11301 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
11302 0, 1, FLAGS},
11303 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
11304 0, 1, FLAGS},
11305 {"use_mfra_for",
11306 "use mfra for fragment timestamps",
11307 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
11308 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
11309 .unit = "use_mfra_for"},
11310 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
11311 FLAGS, .unit = "use_mfra_for" },
11312 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
11313 FLAGS, .unit = "use_mfra_for" },
11314 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
11315 FLAGS, .unit = "use_mfra_for" },
11316 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
11317 0, 1, FLAGS},
11318 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
11319 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11320 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
11321 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11322 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
11323 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11324 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
11325 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11326 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
11327 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11328 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
11329 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
11330 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
11331 .flags = AV_OPT_FLAG_DECODING_PARAM },
11332 { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11333 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
11334 {.i64 = 0}, 0, 1, FLAGS },
11335 { "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 },
11336 { "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 },
11337
11338 { NULL },
11339 };
11340
11341 static const AVClass mov_class = {
11342 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
11343 .item_name = av_default_item_name,
11344 .option = mov_options,
11345 .version = LIBAVUTIL_VERSION_INT,
11346 };
11347
11348 const FFInputFormat ff_mov_demuxer = {
11349 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
11350 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
11351 .p.priv_class = &mov_class,
11352 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v,avif,heic,heif",
11353 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
11354 .priv_data_size = sizeof(MOVContext),
11355 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
11356 .read_probe = mov_probe,
11357 .read_header = mov_read_header,
11358 .read_packet = mov_read_packet,
11359 .read_close = mov_read_close,
11360 .read_seek = mov_read_seek,
11361 };
11362