FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 4187 6678 62.7%
Functions: 170 211 80.6%
Branches: 2339 4452 52.5%

Line Branch Exec Source
1 /*
2 * MOV demuxer
3 * Copyright (c) 2001 Fabrice Bellard
4 * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
5 *
6 * first version by Francois Revol <revol@free.fr>
7 * seek function by Gael Chardon <gael.dev@4now.net>
8 *
9 * This file is part of FFmpeg.
10 *
11 * FFmpeg is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * FFmpeg is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with FFmpeg; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #include "config_components.h"
27
28 #include <inttypes.h>
29 #include <limits.h>
30 #include <stdint.h>
31
32 #include "libavutil/attributes.h"
33 #include "libavutil/bprint.h"
34 #include "libavutil/channel_layout.h"
35 #include "libavutil/dict_internal.h"
36 #include "libavutil/internal.h"
37 #include "libavutil/intreadwrite.h"
38 #include "libavutil/intfloat.h"
39 #include "libavutil/mathematics.h"
40 #include "libavutil/avassert.h"
41 #include "libavutil/avstring.h"
42 #include "libavutil/dict.h"
43 #include "libavutil/display.h"
44 #include "libavutil/mem.h"
45 #include "libavutil/opt.h"
46 #include "libavutil/aes.h"
47 #include "libavutil/aes_ctr.h"
48 #include "libavutil/pixdesc.h"
49 #include "libavutil/sha.h"
50 #include "libavutil/spherical.h"
51 #include "libavutil/stereo3d.h"
52 #include "libavutil/timecode.h"
53 #include "libavutil/uuid.h"
54 #include "libavcodec/ac3tab.h"
55 #include "libavcodec/flac.h"
56 #include "libavcodec/hevc/hevc.h"
57 #include "libavcodec/mpegaudiodecheader.h"
58 #include "libavcodec/mlp_parse.h"
59 #include "avformat.h"
60 #include "internal.h"
61 #include "avio_internal.h"
62 #include "demux.h"
63 #include "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 static int64_t add_ctts_entry(MOVCtts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size,
90 int count, int duration);
91
92 24 static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
93 unsigned len, const char *key)
94 {
95 char buf[16];
96
97 24 short current, total = 0;
98 24 avio_rb16(pb); // unknown
99 24 current = avio_rb16(pb);
100
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (len >= 6)
101 24 total = avio_rb16(pb);
102
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19 times.
24 if (!total)
103 5 snprintf(buf, sizeof(buf), "%d", current);
104 else
105 19 snprintf(buf, sizeof(buf), "%d/%d", current, total);
106 24 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
107 24 av_dict_set(&c->fc->metadata, key, buf, 0);
108
109 24 return 0;
110 }
111
112 static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
113 unsigned len, const char *key)
114 {
115 /* bypass padding bytes */
116 avio_r8(pb);
117 avio_r8(pb);
118 avio_r8(pb);
119
120 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
121 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
122
123 return 0;
124 }
125
126 26 static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
127 unsigned len, const char *key)
128 {
129 26 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
130 26 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
131
132 26 return 0;
133 }
134
135 10 static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
136 unsigned len, const char *key)
137 {
138 short genre;
139
140 10 avio_r8(pb); // unknown
141
142 10 genre = avio_r8(pb);
143
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)
144 return 0;
145 10 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
146 10 av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
147
148 10 return 0;
149 }
150
151 static const uint32_t mac_to_unicode[128] = {
152 0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
153 0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
154 0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,
155 0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,
156 0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,
157 0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,
158 0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,
159 0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,
160 0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,
161 0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,
162 0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,
163 0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,
164 0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,
165 0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,
166 0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,
167 0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7,
168 };
169
170 325 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
171 char *dst, int dstlen)
172 {
173 325 char *p = dst;
174 325 char *end = dst+dstlen-1;
175 int i;
176
177
2/2
✓ Branch 0 taken 2858 times.
✓ Branch 1 taken 325 times.
3183 for (i = 0; i < len; i++) {
178 2858 uint8_t t, c = avio_r8(pb);
179
180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2858 times.
2858 if (p >= end)
181 continue;
182
183
2/2
✓ Branch 0 taken 2855 times.
✓ Branch 1 taken 3 times.
2858 if (c < 0x80)
184 2855 *p++ = c;
185
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 else if (p < end)
186
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;);
187 }
188 325 *p = 0;
189 325 return p - dst;
190 }
191
192 /**
193 * Get the current item in the parsing process.
194 */
195 82 static HEIFItem *heif_cur_item(MOVContext *c)
196 {
197 82 HEIFItem *item = NULL;
198
199
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 12 times.
138 for (int i = 0; i < c->nb_heif_item; i++) {
200
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)
201 56 continue;
202
203 70 item = c->heif_item[i];
204 70 break;
205 }
206
207 82 return item;
208 }
209
210 /**
211 * Get the current stream in the parsing process. This can either be the
212 * latest stream added to the context, or the stream referenced by an item.
213 */
214 197 static AVStream *get_curr_st(MOVContext *c)
215 {
216 197 AVStream *st = NULL;
217 HEIFItem *item;
218
219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
197 if (c->fc->nb_streams < 1)
220 return NULL;
221
222
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 29 times.
197 if (c->cur_item_id == -1)
223 168 return c->fc->streams[c->fc->nb_streams-1];
224
225 29 item = heif_cur_item(c);
226
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (item)
227 29 st = item->st;
228
229 29 return st;
230 }
231
232 14 static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
233 {
234 AVStream *st;
235 MOVStreamContext *sc;
236 enum AVCodecID id;
237 int ret;
238
239
2/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
14 switch (type) {
240 7 case 0xd: id = AV_CODEC_ID_MJPEG; break;
241 7 case 0xe: id = AV_CODEC_ID_PNG; break;
242 case 0x1b: id = AV_CODEC_ID_BMP; break;
243 default:
244 av_log(c->fc, AV_LOG_WARNING, "Unknown cover type: 0x%x.\n", type);
245 avio_skip(pb, len);
246 return 0;
247 }
248
249 14 sc = av_mallocz(sizeof(*sc));
250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!sc)
251 return AVERROR(ENOMEM);
252 14 ret = ff_add_attached_pic(c->fc, NULL, pb, NULL, len);
253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0) {
254 av_free(sc);
255 return ret;
256 }
257 14 st = c->fc->streams[c->fc->nb_streams - 1];
258 14 st->priv_data = sc;
259 14 sc->id = st->id;
260 14 sc->refcount = 1;
261
262
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) {
263
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
264 7 id = AV_CODEC_ID_PNG;
265 } else {
266 7 id = AV_CODEC_ID_MJPEG;
267 }
268 }
269 14 st->codecpar->codec_id = id;
270
271 14 return 0;
272 }
273
274 // 3GPP TS 26.244
275 static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
276 {
277 char language[4] = { 0 };
278 char buf[200], place[100];
279 uint16_t langcode = 0;
280 double longitude, latitude, altitude;
281 const char *key = "location";
282
283 if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) {
284 av_log(c->fc, AV_LOG_ERROR, "loci too short\n");
285 return AVERROR_INVALIDDATA;
286 }
287
288 avio_skip(pb, 4); // version+flags
289 langcode = avio_rb16(pb);
290 ff_mov_lang_to_iso639(langcode, language);
291 len -= 6;
292
293 len -= avio_get_str(pb, len, place, sizeof(place));
294 if (len < 1) {
295 av_log(c->fc, AV_LOG_ERROR, "place name too long\n");
296 return AVERROR_INVALIDDATA;
297 }
298 avio_skip(pb, 1); // role
299 len -= 1;
300
301 if (len < 12) {
302 av_log(c->fc, AV_LOG_ERROR,
303 "loci too short (%u bytes left, need at least %d)\n", len, 12);
304 return AVERROR_INVALIDDATA;
305 }
306 longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
307 latitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
308 altitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
309
310 // Try to output in the same format as the ?xyz field
311 snprintf(buf, sizeof(buf), "%+08.4f%+09.4f", latitude, longitude);
312 if (altitude)
313 av_strlcatf(buf, sizeof(buf), "%+f", altitude);
314 av_strlcatf(buf, sizeof(buf), "/%s", place);
315
316 if (*language && strcmp(language, "und")) {
317 char key2[16];
318 snprintf(key2, sizeof(key2), "%s-%s", key, language);
319 av_dict_set(&c->fc->metadata, key2, buf, 0);
320 }
321 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
322 return av_dict_set(&c->fc->metadata, key, buf, 0);
323 }
324
325 static int mov_metadata_hmmt(MOVContext *c, AVIOContext *pb, unsigned len)
326 {
327 int i, n_hmmt;
328
329 if (len < 2)
330 return 0;
331 if (c->ignore_chapters)
332 return 0;
333
334 n_hmmt = avio_rb32(pb);
335 if (n_hmmt > len / 4)
336 return AVERROR_INVALIDDATA;
337 for (i = 0; i < n_hmmt && !pb->eof_reached; i++) {
338 int moment_time = avio_rb32(pb);
339 avpriv_new_chapter(c->fc, i, av_make_q(1, 1000), moment_time, AV_NOPTS_VALUE, NULL);
340 }
341 if (avio_feof(pb))
342 return AVERROR_INVALIDDATA;
343 return 0;
344 }
345
346 466 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
347 {
348 466 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
349 466 char key2[32], language[4] = {0};
350 466 char *str = NULL;
351 466 const char *key = NULL;
352 466 uint16_t langcode = 0;
353 466 uint32_t data_type = 0, str_size_alloc;
354 uint64_t str_size;
355 466 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
356 466 int raw = 0;
357 466 int num = 0;
358
359
24/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 16 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 16 times.
✓ Branch 42 taken 3 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 7 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 2 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 40 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 49 times.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✓ Branch 73 taken 5 times.
466 switch (atom.type) {
360 3 case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break;
361 3 case MKTAG( '@','P','R','Q'): key = "quicktime_version"; raw = 1; break;
362 2 case MKTAG( 'X','M','P','_'):
363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->export_xmp) { key = "xmp"; raw = 1; } break;
364 12 case MKTAG( 'a','A','R','T'): key = "album_artist"; break;
365 case MKTAG( 'a','k','I','D'): key = "account_type";
366 parse = mov_metadata_int8_no_padding; break;
367 case MKTAG( 'a','p','I','D'): key = "account_id"; break;
368 case MKTAG( 'c','a','t','g'): key = "category"; break;
369 13 case MKTAG( 'c','p','i','l'): key = "compilation";
370 13 parse = mov_metadata_int8_no_padding; break;
371 case MKTAG( 'c','p','r','t'): key = "copyright"; break;
372 case MKTAG( 'd','e','s','c'): key = "description"; break;
373 12 case MKTAG( 'd','i','s','k'): key = "disc";
374 12 parse = mov_metadata_track_or_disc_number; break;
375 case MKTAG( 'e','g','i','d'): key = "episode_uid";
376 parse = mov_metadata_int8_no_padding; break;
377 case MKTAG( 'F','I','R','M'): key = "firmware"; raw = 1; break;
378 10 case MKTAG( 'g','n','r','e'): key = "genre";
379 10 parse = mov_metadata_gnre; break;
380 case MKTAG( 'h','d','v','d'): key = "hd_video";
381 parse = mov_metadata_int8_no_padding; break;
382 case MKTAG( 'H','M','M','T'):
383 return mov_metadata_hmmt(c, pb, atom.size);
384 case MKTAG( 'k','e','y','w'): key = "keywords"; break;
385 case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
386 case MKTAG( 'l','o','c','i'):
387 return mov_metadata_loci(c, pb, atom.size);
388 case MKTAG( 'm','a','n','u'): key = "make"; break;
389 case MKTAG( 'm','o','d','l'): key = "model"; break;
390 case MKTAG( 'p','c','s','t'): key = "podcast";
391 parse = mov_metadata_int8_no_padding; break;
392 13 case MKTAG( 'p','g','a','p'): key = "gapless_playback";
393 13 parse = mov_metadata_int8_no_padding; break;
394 case MKTAG( 'p','u','r','d'): key = "purchase_date"; break;
395 case MKTAG( 'r','t','n','g'): key = "rating";
396 parse = mov_metadata_int8_no_padding; break;
397 case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break;
398 case MKTAG( 's','o','a','l'): key = "sort_album"; break;
399 case MKTAG( 's','o','a','r'): key = "sort_artist"; break;
400 case MKTAG( 's','o','c','o'): key = "sort_composer"; break;
401 case MKTAG( 's','o','n','m'): key = "sort_name"; break;
402 case MKTAG( 's','o','s','n'): key = "sort_show"; break;
403 case MKTAG( 's','t','i','k'): key = "media_type";
404 parse = mov_metadata_int8_no_padding; break;
405 12 case MKTAG( 't','r','k','n'): key = "track";
406 12 parse = mov_metadata_track_or_disc_number; break;
407 case MKTAG( 't','v','e','n'): key = "episode_id"; break;
408 case MKTAG( 't','v','e','s'): key = "episode_sort";
409 parse = mov_metadata_int8_bypass_padding; break;
410 case MKTAG( 't','v','n','n'): key = "network"; break;
411 case MKTAG( 't','v','s','h'): key = "show"; break;
412 case MKTAG( 't','v','s','n'): key = "season_number";
413 parse = mov_metadata_int8_bypass_padding; break;
414 16 case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
415 case MKTAG(0xa9,'P','R','D'): key = "producer"; break;
416 16 case MKTAG(0xa9,'a','l','b'): key = "album"; break;
417 3 case MKTAG(0xa9,'a','u','t'): key = "artist"; break;
418 case MKTAG(0xa9,'c','h','p'): key = "chapter"; break;
419 7 case MKTAG(0xa9,'c','m','t'): key = "comment"; break;
420 case MKTAG(0xa9,'c','o','m'): key = "composer"; break;
421 4 case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
422 16 case MKTAG(0xa9,'d','a','y'): key = "date"; break;
423 case MKTAG(0xa9,'d','i','r'): key = "director"; break;
424 case MKTAG(0xa9,'d','i','s'): key = "disclaimer"; break;
425 case MKTAG(0xa9,'e','d','1'): key = "edit_date"; break;
426 2 case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
427 case MKTAG(0xa9,'f','m','t'): key = "original_format"; break;
428 2 case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
429 case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
430 case MKTAG(0xa9,'h','s','t'): key = "host_computer"; break;
431 case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
432 case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
433 5 case MKTAG(0xa9,'m','a','k'): key = "make"; break;
434 5 case MKTAG(0xa9,'m','o','d'): key = "model"; break;
435 40 case MKTAG(0xa9,'n','a','m'): key = "title"; break;
436 case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break;
437 case MKTAG(0xa9,'p','r','d'): key = "producer"; break;
438 case MKTAG(0xa9,'p','r','f'): key = "performers"; break;
439 case MKTAG(0xa9,'r','e','q'): key = "playback_requirements"; break;
440 case MKTAG(0xa9,'s','r','c'): key = "original_source"; break;
441 case MKTAG(0xa9,'s','t','3'): key = "subtitle"; break;
442 58 case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
443 49 case MKTAG(0xa9,'t','o','o'): key = "encoder"; break;
444 case MKTAG(0xa9,'t','r','k'): key = "track"; break;
445 case MKTAG(0xa9,'u','r','l'): key = "URL"; break;
446 case MKTAG(0xa9,'w','r','n'): key = "warning"; break;
447 case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
448 5 case MKTAG(0xa9,'x','y','z'): key = "location"; break;
449 }
450 2 retry:
451
3/4
✓ Branch 0 taken 294 times.
✓ Branch 1 taken 174 times.
✓ Branch 2 taken 294 times.
✗ Branch 3 not taken.
748 if (c->itunes_metadata && atom.size > 8) {
452 294 int data_size = avio_rb32(pb);
453 294 int tag = avio_rl32(pb);
454
3/6
✓ Branch 0 taken 294 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 294 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 294 times.
✗ Branch 5 not taken.
294 if (tag == MKTAG('d','a','t','a') && data_size <= atom.size && data_size >= 16) {
455 294 data_type = avio_rb32(pb); // type
456 294 avio_rb32(pb); // unknown
457 294 str_size = data_size - 16;
458 294 atom.size -= 16;
459
460
5/6
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 201 times.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 34 times.
✓ Branch 4 taken 59 times.
✗ Branch 5 not taken.
294 if (!key && c->found_hdlr_mdta && c->meta_keys) {
461 59 uint32_t index = av_bswap32(atom.type); // BE number has been read as LE
462
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) {
463 59 key = c->meta_keys[index];
464 } else if (atom.type != MKTAG('c', 'o', 'v', 'r')) {
465 av_log(c->fc, AV_LOG_WARNING,
466 "The index of 'data' is out of range: %"PRId32" < 1 or >= %d.\n",
467 index, c->meta_keys_count);
468 }
469 }
470
4/4
✓ Branch 0 taken 280 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 260 times.
✓ Branch 3 taken 20 times.
294 if (atom.type == MKTAG('c', 'o', 'v', 'r') ||
471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 260 times.
260 (key && !strcmp(key, "com.apple.quicktime.artwork"))) {
472 14 int ret = mov_read_covr(c, pb, data_type, str_size);
473
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0) {
474 av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
475 return ret;
476 }
477 14 atom.size -= str_size;
478
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (atom.size > 8)
479 2 goto retry;
480 12 return ret;
481 }
482 } else return 0;
483
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) {
484 99 str_size = avio_rb16(pb); // string length
485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (str_size > atom.size) {
486 raw = 1;
487 avio_seek(pb, -2, SEEK_CUR);
488 av_log(c->fc, AV_LOG_WARNING, "UDTA parsing failed retrying raw\n");
489 goto retry;
490 }
491 99 langcode = avio_rb16(pb);
492 99 ff_mov_lang_to_iso639(langcode, language);
493 99 atom.size -= 4;
494 } else
495 75 str_size = atom.size;
496
497
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 454 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
454 if (c->export_all && !key) {
498 key = av_fourcc_make_string(tmp_key, atom.type);
499 }
500
501
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 365 times.
454 if (!key)
502 89 return 0;
503
2/4
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 365 times.
365 if (atom.size < 0 || str_size >= INT_MAX/2)
504 return AVERROR_INVALIDDATA;
505
506 // Allocates enough space if data_type is a int32 or float32 number, otherwise
507 // worst-case requirement for output string in case of utf8 coded input
508
3/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 324 times.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
365 num = (data_type >= 21 && data_type <= 23);
509
4/4
✓ Branch 0 taken 324 times.
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 318 times.
✓ Branch 3 taken 6 times.
365 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
510 365 str = av_mallocz(str_size_alloc);
511
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 365 times.
365 if (!str)
512 return AVERROR(ENOMEM);
513
514
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 305 times.
365 if (parse)
515 60 parse(c, pb, str_size, key);
516 else {
517
8/10
✓ Branch 0 taken 299 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 299 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 100 times.
✓ Branch 5 taken 199 times.
✓ Branch 6 taken 86 times.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 86 times.
305 if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
518 14 mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
519
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 289 times.
291 } else if (data_type == 21) { // BE signed integer, variable size
520 2 int val = 0;
521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (str_size == 1)
522 val = (int8_t)avio_r8(pb);
523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 2)
524 val = (int16_t)avio_rb16(pb);
525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 3)
526 val = ((int32_t)(avio_rb24(pb)<<8))>>8;
527
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (str_size == 4)
528 2 val = (int32_t)avio_rb32(pb);
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
530 av_log(c->fc, AV_LOG_ERROR,
531 "Failed to store the number (%d) in string.\n", val);
532 av_free(str);
533 return AVERROR_INVALIDDATA;
534 }
535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 289 times.
289 } else if (data_type == 22) { // BE unsigned integer, variable size
536 unsigned int val = 0;
537 if (str_size == 1)
538 val = avio_r8(pb);
539 else if (str_size == 2)
540 val = avio_rb16(pb);
541 else if (str_size == 3)
542 val = avio_rb24(pb);
543 else if (str_size == 4)
544 val = avio_rb32(pb);
545 if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
546 av_log(c->fc, AV_LOG_ERROR,
547 "Failed to store the number (%u) in string.\n", val);
548 av_free(str);
549 return AVERROR_INVALIDDATA;
550 }
551
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 276 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
302 } else if (data_type == 23 && str_size >= 4) { // BE float32
552 13 float val = av_int2float(avio_rb32(pb));
553
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
554 av_log(c->fc, AV_LOG_ERROR,
555 "Failed to store the float32 number (%f) in string.\n", val);
556 av_free(str);
557 return AVERROR_INVALIDDATA;
558 }
559
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 276 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
276 } else if (data_type > 1 && data_type != 4) {
560 // data_type can be 0 if not set at all above. data_type 1 means
561 // UTF8 and 4 means "UTF8 sort". For any other type (UTF16 or e.g.
562 // a picture), don't return it blindly in a string that is supposed
563 // to be UTF8 text.
564 av_log(c->fc, AV_LOG_WARNING, "Skipping unhandled metadata %s of type %d\n", key, data_type);
565 av_free(str);
566 return 0;
567 } else {
568 276 int ret = ffio_read_size(pb, str, str_size);
569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 276 times.
276 if (ret < 0) {
570 av_free(str);
571 return ret;
572 }
573 276 str[str_size] = 0;
574 }
575 305 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
576 305 av_dict_set(&c->fc->metadata, key, str, 0);
577
4/4
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 206 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 62 times.
305 if (*language && strcmp(language, "und")) {
578 37 snprintf(key2, sizeof(key2), "%s-%s", key, language);
579 37 av_dict_set(&c->fc->metadata, key2, str, 0);
580 }
581
2/2
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 196 times.
305 if (!strcmp(key, "encoder")) {
582 int major, minor, micro;
583
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 109 times.
109 if (sscanf(str, "HandBrake %d.%d.%d", &major, &minor, &micro) == 3) {
584 c->handbrake_version = 1000000*major + 1000*minor + micro;
585 }
586 }
587 }
588
589 365 av_freep(&str);
590 365 return 0;
591 }
592
593 12 static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
594 {
595 int64_t start;
596 int i, nb_chapters, str_len, version;
597 char str[256+1];
598 int ret;
599
600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->ignore_chapters)
601 return 0;
602
603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if ((atom.size -= 5) < 0)
604 return 0;
605
606 12 version = avio_r8(pb);
607 12 avio_rb24(pb);
608
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (version)
609 12 avio_rb32(pb); // ???
610 12 nb_chapters = avio_r8(pb);
611
612
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
30 for (i = 0; i < nb_chapters; i++) {
613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size < 9)
614 return 0;
615
616 18 start = avio_rb64(pb);
617 18 str_len = avio_r8(pb);
618
619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if ((atom.size -= 9+str_len) < 0)
620 return 0;
621
622 18 ret = ffio_read_size(pb, str, str_len);
623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (ret < 0)
624 return ret;
625 18 str[str_len] = 0;
626 18 avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
627 }
628 12 return 0;
629 }
630
631 #define MIN_DATA_ENTRY_BOX_SIZE 12
632 593 static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
633 {
634 AVStream *st;
635 MOVStreamContext *sc;
636 int entries, i, j;
637
638
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->fc->nb_streams < 1)
639 return 0;
640 593 st = c->fc->streams[c->fc->nb_streams-1];
641 593 sc = st->priv_data;
642
643 593 avio_rb32(pb); // version + flags
644 593 entries = avio_rb32(pb);
645
1/2
✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
593 if (!entries ||
646
1/2
✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
593 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 entries >= UINT_MAX / sizeof(*sc->drefs))
648 return AVERROR_INVALIDDATA;
649
650
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 for (i = 0; i < sc->drefs_count; i++) {
651 MOVDref *dref = &sc->drefs[i];
652 av_freep(&dref->path);
653 av_freep(&dref->dir);
654 }
655 593 av_free(sc->drefs);
656 593 sc->drefs_count = 0;
657 593 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (!sc->drefs)
659 return AVERROR(ENOMEM);
660 593 sc->drefs_count = entries;
661
662
2/2
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 593 times.
1186 for (i = 0; i < entries; i++) {
663 593 MOVDref *dref = &sc->drefs[i];
664 593 uint32_t size = avio_rb32(pb);
665 593 int64_t next = avio_tell(pb);
666
667
3/6
✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 593 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 593 times.
593 if (size < 12 || next < 0 || next > INT64_MAX - size)
668 return AVERROR_INVALIDDATA;
669
670 593 next += size - 4;
671
672 593 dref->type = avio_rl32(pb);
673 593 avio_rb32(pb); // version + flags
674
675
3/4
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 475 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 118 times.
593 if (dref->type == MKTAG('a','l','i','s') && size > 150) {
676 /* macintosh alias record */
677 uint16_t volume_len, len;
678 int16_t type;
679 int ret;
680
681 avio_skip(pb, 10);
682
683 volume_len = avio_r8(pb);
684 volume_len = FFMIN(volume_len, 27);
685 ret = ffio_read_size(pb, dref->volume, 27);
686 if (ret < 0)
687 return ret;
688 dref->volume[volume_len] = 0;
689 av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
690
691 avio_skip(pb, 12);
692
693 len = avio_r8(pb);
694 len = FFMIN(len, 63);
695 ret = ffio_read_size(pb, dref->filename, 63);
696 if (ret < 0)
697 return ret;
698 dref->filename[len] = 0;
699 av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
700
701 avio_skip(pb, 16);
702
703 /* read next level up_from_alias/down_to_target */
704 dref->nlvl_from = avio_rb16(pb);
705 dref->nlvl_to = avio_rb16(pb);
706 av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
707 dref->nlvl_from, dref->nlvl_to);
708
709 avio_skip(pb, 16);
710
711 for (type = 0; type != -1 && avio_tell(pb) < next; ) {
712 if (avio_feof(pb))
713 return AVERROR_EOF;
714 type = avio_rb16(pb);
715 len = avio_rb16(pb);
716 av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
717 if (len&1)
718 len += 1;
719 if (type == 2) { // absolute path
720 av_free(dref->path);
721 dref->path = av_mallocz(len+1);
722 if (!dref->path)
723 return AVERROR(ENOMEM);
724
725 ret = ffio_read_size(pb, dref->path, len);
726 if (ret < 0) {
727 av_freep(&dref->path);
728 return ret;
729 }
730 if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
731 len -= volume_len;
732 memmove(dref->path, dref->path+volume_len, len);
733 dref->path[len] = 0;
734 }
735 // trim string of any ending zeros
736 for (j = len - 1; j >= 0; j--) {
737 if (dref->path[j] == 0)
738 len--;
739 else
740 break;
741 }
742 for (j = 0; j < len; j++)
743 if (dref->path[j] == ':' || dref->path[j] == 0)
744 dref->path[j] = '/';
745 av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
746 } else if (type == 0) { // directory name
747 av_free(dref->dir);
748 dref->dir = av_malloc(len+1);
749 if (!dref->dir)
750 return AVERROR(ENOMEM);
751
752 ret = ffio_read_size(pb, dref->dir, len);
753 if (ret < 0) {
754 av_freep(&dref->dir);
755 return ret;
756 }
757 dref->dir[len] = 0;
758 for (j = 0; j < len; j++)
759 if (dref->dir[j] == ':')
760 dref->dir[j] = '/';
761 av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
762 } else
763 avio_skip(pb, len);
764 }
765 } else {
766 593 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
767 dref->type, size);
768 593 entries--;
769 593 i--;
770 }
771 593 avio_seek(pb, next, SEEK_SET);
772 }
773 593 return 0;
774 }
775
776 1085 static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
777 {
778 AVStream *st;
779 uint32_t type;
780 uint32_t ctype;
781 int64_t title_size;
782 char *title_str;
783 int ret;
784
785 1085 avio_r8(pb); /* version */
786 1085 avio_rb24(pb); /* flags */
787
788 /* component type */
789 1085 ctype = avio_rl32(pb);
790 1085 type = avio_rl32(pb); /* component subtype */
791
792 1085 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
793 1085 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
794
795
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 950 times.
1085 if (c->trak_index < 0) { // meta not inside a trak
796
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 124 times.
135 if (type == MKTAG('m','d','t','a')) {
797 11 c->found_hdlr_mdta = 1;
798 }
799 135 return 0;
800 }
801
802 950 st = c->fc->streams[c->fc->nb_streams-1];
803
804
2/2
✓ Branch 0 taken 301 times.
✓ Branch 1 taken 649 times.
950 if (type == MKTAG('v','i','d','e'))
805 301 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
806
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 408 times.
649 else if (type == MKTAG('s','o','u','n'))
807 241 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
808
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 408 times.
408 else if (type == MKTAG('m','1','a',' '))
809 st->codecpar->codec_id = AV_CODEC_ID_MP2;
810
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')))
811 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
812
813 950 avio_rb32(pb); /* component manufacture */
814 950 avio_rb32(pb); /* component flags */
815 950 avio_rb32(pb); /* component flags mask */
816
817 950 title_size = atom.size - 24;
818
2/2
✓ Branch 0 taken 947 times.
✓ Branch 1 taken 3 times.
950 if (title_size > 0) {
819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 947 times.
947 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
820 return AVERROR_INVALIDDATA;
821 947 title_str = av_malloc(title_size + 1); /* Add null terminator */
822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 947 times.
947 if (!title_str)
823 return AVERROR(ENOMEM);
824
825 947 ret = ffio_read_size(pb, title_str, title_size);
826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 947 times.
947 if (ret < 0) {
827 av_freep(&title_str);
828 return ret;
829 }
830 947 title_str[title_size] = 0;
831
2/2
✓ Branch 0 taken 896 times.
✓ Branch 1 taken 51 times.
947 if (title_str[0]) {
832
4/4
✓ Branch 0 taken 690 times.
✓ Branch 1 taken 206 times.
✓ Branch 2 taken 688 times.
✓ Branch 3 taken 2 times.
896 int off = (!c->isom && title_str[0] == title_size - 1);
833 // flag added so as to not set stream handler name if already set from mdia->hdlr
834 896 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
835 }
836 947 av_freep(&title_str);
837 }
838
839 950 return 0;
840 }
841
842 150 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
843 {
844 150 return ff_mov_read_esds(c->fc, pb);
845 }
846
847 7 static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
848 {
849 AVStream *st;
850 AVPacketSideData *sd;
851 enum AVAudioServiceType *ast;
852 int ac3info, acmod, lfeon, bsmod;
853 uint64_t mask;
854
855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (c->fc->nb_streams < 1)
856 return 0;
857 7 st = c->fc->streams[c->fc->nb_streams-1];
858
859 7 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
860 7 &st->codecpar->nb_coded_side_data,
861 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
862 sizeof(*ast), 0);
863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sd)
864 return AVERROR(ENOMEM);
865
866 7 ast = (enum AVAudioServiceType*)sd->data;
867 7 ac3info = avio_rb24(pb);
868 7 bsmod = (ac3info >> 14) & 0x7;
869 7 acmod = (ac3info >> 11) & 0x7;
870 7 lfeon = (ac3info >> 10) & 0x1;
871
872 7 mask = ff_ac3_channel_layout_tab[acmod];
873
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (lfeon)
874 1 mask |= AV_CH_LOW_FREQUENCY;
875 7 av_channel_layout_uninit(&st->codecpar->ch_layout);
876 7 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
877
878 7 *ast = bsmod;
879
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)
880 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
881
882 7 return 0;
883 }
884
885 #if CONFIG_IAMFDEC
886 10 static int mov_read_iacb(MOVContext *c, AVIOContext *pb, MOVAtom atom)
887 {
888 AVStream *st;
889 MOVStreamContext *sc;
890 FFIOContext b;
891 AVIOContext *descriptor_pb;
892 AVDictionary *metadata;
893 IAMFContext *iamf;
894 int64_t start_time, duration;
895 unsigned descriptors_size;
896 int nb_frames, disposition;
897 int version, ret;
898
899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (atom.size < 5)
900 return AVERROR_INVALIDDATA;
901
902
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (c->fc->nb_streams < 1)
903 return 0;
904
905 10 version = avio_r8(pb);
906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (version != 1) {
907 av_log(c->fc, AV_LOG_ERROR, "%s configurationVersion %d",
908 version < 1 ? "invalid" : "unsupported", version);
909 return AVERROR_INVALIDDATA;
910 }
911
912 10 descriptors_size = ffio_read_leb(pb);
913
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)
914 return AVERROR_INVALIDDATA;
915
916 10 st = c->fc->streams[c->fc->nb_streams - 1];
917 10 sc = st->priv_data;
918
919
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (st->codecpar->extradata) {
920 av_log(c->fc, AV_LOG_WARNING, "ignoring iacb\n");
921 return 0;
922 }
923
924 10 sc->iamf = av_mallocz(sizeof(*sc->iamf));
925
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!sc->iamf)
926 return AVERROR(ENOMEM);
927 10 iamf = &sc->iamf->iamf;
928
929 10 st->codecpar->extradata = av_malloc(descriptors_size);
930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!st->codecpar->extradata)
931 return AVERROR(ENOMEM);
932 10 st->codecpar->extradata_size = descriptors_size;
933
934 10 ret = avio_read(pb, st->codecpar->extradata, descriptors_size);
935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret != descriptors_size)
936 return ret < 0 ? ret : AVERROR_INVALIDDATA;
937
938 10 ffio_init_read_context(&b, st->codecpar->extradata, descriptors_size);
939 10 descriptor_pb = &b.pub;
940
941 10 ret = ff_iamfdec_read_descriptors(iamf, descriptor_pb, descriptors_size, c->fc);
942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
943 return ret;
944
945 10 metadata = st->metadata;
946 10 st->metadata = NULL;
947 10 start_time = st->start_time;
948 10 nb_frames = st->nb_frames;
949 10 duration = st->duration;
950 10 disposition = st->disposition;
951
952
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_audio_elements; i++) {
953 10 IAMFAudioElement *audio_element = iamf->audio_elements[i];
954 const AVIAMFAudioElement *element;
955 AVStreamGroup *stg =
956 10 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, NULL);
957
958
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!stg) {
959 ret = AVERROR(ENOMEM);
960 goto fail;
961 }
962
963 10 av_iamf_audio_element_free(&stg->params.iamf_audio_element);
964 10 stg->id = audio_element->audio_element_id;
965 /* Transfer ownership */
966 10 element = stg->params.iamf_audio_element = audio_element->element;
967 10 audio_element->element = NULL;
968
969
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int j = 0; j < audio_element->nb_substreams; j++) {
970 50 IAMFSubStream *substream = &audio_element->substreams[j];
971 AVStream *stream;
972
973
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) {
974
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (audio_element->layers[0].substream_count != 1)
975 2 disposition &= ~AV_DISPOSITION_DEFAULT;
976 10 stream = st;
977 } else
978 40 stream = avformat_new_stream(c->fc, NULL);
979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (!stream) {
980 ret = AVERROR(ENOMEM);
981 goto fail;
982 }
983
984 50 stream->start_time = start_time;
985 50 stream->nb_frames = nb_frames;
986 50 stream->duration = duration;
987 50 stream->disposition = disposition;
988
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 10 times.
50 if (stream != st) {
989 40 stream->priv_data = sc;
990 40 sc->refcount++;
991 }
992
993
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 42 times.
50 if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
994 8 stream->disposition |= AV_DISPOSITION_DEPENDENT;
995
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) {
996 40 stream->disposition |= AV_DISPOSITION_DEPENDENT;
997
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 6 times.
40 if (audio_element->layers[0].substream_count == 1)
998 34 stream->disposition &= ~AV_DISPOSITION_DEFAULT;
999 }
1000
1001 50 ret = avcodec_parameters_copy(stream->codecpar, substream->codecpar);
1002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (ret < 0)
1003 goto fail;
1004
1005 50 stream->id = substream->audio_substream_id;
1006
1007 50 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
1008
1009 50 ret = avformat_stream_group_add_stream(stg, stream);
1010
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (ret < 0)
1011 goto fail;
1012 }
1013
1014 10 ret = av_dict_copy(&stg->metadata, metadata, 0);
1015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
1016 goto fail;
1017 }
1018
1019
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1020 10 IAMFMixPresentation *mix_presentation = iamf->mix_presentations[i];
1021 10 const AVIAMFMixPresentation *mix = mix_presentation->cmix;
1022 AVStreamGroup *stg =
1023 10 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, NULL);
1024
1025
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!stg) {
1026 ret = AVERROR(ENOMEM);
1027 goto fail;
1028 }
1029
1030 10 av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
1031 10 stg->id = mix_presentation->mix_presentation_id;
1032 /* Transfer ownership */
1033 10 stg->params.iamf_mix_presentation = mix_presentation->mix;
1034 10 mix_presentation->mix = NULL;
1035
1036
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 10 times.
22 for (int j = 0; j < mix->nb_submixes; j++) {
1037 12 const AVIAMFSubmix *submix = mix->submixes[j];
1038
1039
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int k = 0; k < submix->nb_elements; k++) {
1040 12 const AVIAMFSubmixElement *submix_element = submix->elements[k];
1041 12 const AVStreamGroup *audio_element = NULL;
1042
1043
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 for (int l = 0; l < c->fc->nb_stream_groups; l++)
1044
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 &&
1045
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 c->fc->stream_groups[l]->id == submix_element->audio_element_id) {
1046 12 audio_element = c->fc->stream_groups[l];
1047 12 break;
1048 }
1049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 av_assert0(audio_element);
1050
1051
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 12 times.
64 for (int l = 0; l < audio_element->nb_streams; l++) {
1052 52 ret = avformat_stream_group_add_stream(stg, audio_element->streams[l]);
1053
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))
1054 goto fail;
1055 }
1056 }
1057 }
1058
1059 10 ret = av_dict_copy(&stg->metadata, metadata, 0);
1060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
1061 goto fail;
1062 }
1063
1064 10 ret = 0;
1065 10 fail:
1066 10 av_dict_free(&metadata);
1067
1068 10 return ret;
1069 }
1070 #endif
1071
1072 1 static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1073 {
1074 AVStream *st;
1075 AVPacketSideData *sd;
1076 enum AVAudioServiceType *ast;
1077 int eac3info, acmod, lfeon, bsmod;
1078 uint64_t mask;
1079
1080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
1081 return 0;
1082 1 st = c->fc->streams[c->fc->nb_streams-1];
1083
1084 1 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1085 1 &st->codecpar->nb_coded_side_data,
1086 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
1087 sizeof(*ast), 0);
1088
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sd)
1089 return AVERROR(ENOMEM);
1090
1091 1 ast = (enum AVAudioServiceType*)sd->data;
1092
1093 /* No need to parse fields for additional independent substreams and its
1094 * associated dependent substreams since libavcodec's E-AC-3 decoder
1095 * does not support them yet. */
1096 1 avio_rb16(pb); /* data_rate and num_ind_sub */
1097 1 eac3info = avio_rb24(pb);
1098 1 bsmod = (eac3info >> 12) & 0x1f;
1099 1 acmod = (eac3info >> 9) & 0x7;
1100 1 lfeon = (eac3info >> 8) & 0x1;
1101
1102 1 mask = ff_ac3_channel_layout_tab[acmod];
1103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (lfeon)
1104 mask |= AV_CH_LOW_FREQUENCY;
1105 1 av_channel_layout_uninit(&st->codecpar->ch_layout);
1106 1 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
1107
1108 1 *ast = bsmod;
1109
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)
1110 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
1111
1112 1 return 0;
1113 }
1114
1115 static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1116 {
1117 #define DDTS_SIZE 20
1118 uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
1119 AVStream *st = NULL;
1120 uint32_t frame_duration_code = 0;
1121 uint32_t channel_layout_code = 0;
1122 GetBitContext gb;
1123 int ret;
1124
1125 if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
1126 return ret;
1127
1128 init_get_bits(&gb, buf, 8 * DDTS_SIZE);
1129
1130 if (c->fc->nb_streams < 1) {
1131 return 0;
1132 }
1133 st = c->fc->streams[c->fc->nb_streams-1];
1134
1135 st->codecpar->sample_rate = get_bits_long(&gb, 32);
1136 if (st->codecpar->sample_rate <= 0) {
1137 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
1138 return AVERROR_INVALIDDATA;
1139 }
1140 skip_bits_long(&gb, 32); /* max bitrate */
1141 st->codecpar->bit_rate = get_bits_long(&gb, 32);
1142 st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
1143 frame_duration_code = get_bits(&gb, 2);
1144 skip_bits(&gb, 30); /* various fields */
1145 channel_layout_code = get_bits(&gb, 16);
1146
1147 st->codecpar->frame_size =
1148 (frame_duration_code == 0) ? 512 :
1149 (frame_duration_code == 1) ? 1024 :
1150 (frame_duration_code == 2) ? 2048 :
1151 (frame_duration_code == 3) ? 4096 : 0;
1152
1153 if (channel_layout_code > 0xff) {
1154 av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout\n");
1155 }
1156 av_channel_layout_uninit(&st->codecpar->ch_layout);
1157 av_channel_layout_from_mask(&st->codecpar->ch_layout,
1158 ((channel_layout_code & 0x1) ? AV_CH_FRONT_CENTER : 0) |
1159 ((channel_layout_code & 0x2) ? AV_CH_FRONT_LEFT : 0) |
1160 ((channel_layout_code & 0x2) ? AV_CH_FRONT_RIGHT : 0) |
1161 ((channel_layout_code & 0x4) ? AV_CH_SIDE_LEFT : 0) |
1162 ((channel_layout_code & 0x4) ? AV_CH_SIDE_RIGHT : 0) |
1163 ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0));
1164
1165 return 0;
1166 }
1167
1168 51 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1169 {
1170 AVStream *st;
1171
1172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (c->fc->nb_streams < 1)
1173 return 0;
1174 51 st = c->fc->streams[c->fc->nb_streams-1];
1175
1176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (atom.size < 16)
1177 return 0;
1178
1179 /* skip version and flags */
1180 51 avio_skip(pb, 4);
1181
1182 51 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
1183
1184 51 return 0;
1185 }
1186
1187 5 static int mov_read_chnl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1188 {
1189 5 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
1190 int version, flags;
1191 int ret;
1192 AVStream *st;
1193
1194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
1195 return 0;
1196 5 st = c->fc->streams[c->fc->nb_streams-1];
1197
1198 5 version = avio_r8(pb);
1199 5 flags = avio_rb24(pb);
1200
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) {
1201 av_log(c->fc, AV_LOG_ERROR,
1202 "Unsupported 'chnl' box with version %d, flags: %#x",
1203 version, flags);
1204 return AVERROR_INVALIDDATA;
1205 }
1206
1207 5 ret = ff_mov_read_chnl(c->fc, pb, st);
1208
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
1209 return ret;
1210
1211
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_tell(pb) != end) {
1212 av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data inside chnl\n",
1213 end - avio_tell(pb));
1214 avio_seek(pb, end, SEEK_SET);
1215 }
1216 5 return ret;
1217 }
1218
1219 2 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1220 {
1221 AVStream *st;
1222 int ret;
1223
1224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
1225 return 0;
1226 2 st = c->fc->streams[c->fc->nb_streams-1];
1227
1228
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)
1229 av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
1230
1231 2 return ret;
1232 }
1233
1234 16 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1235 {
1236 AVStream *st;
1237 HEIFItem *item;
1238 AVPacketSideData *sd;
1239 16 int width, height, err = 0;
1240 AVRational aperture_width, aperture_height, horiz_off, vert_off;
1241 AVRational pc_x, pc_y;
1242 uint64_t top, bottom, left, right;
1243
1244 16 item = heif_cur_item(c);
1245 16 st = get_curr_st(c);
1246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!st)
1247 return 0;
1248
1249 16 width = st->codecpar->width;
1250 16 height = st->codecpar->height;
1251
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) {
1252 4 width = item->width;
1253 4 height = item->height;
1254 }
1255
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
16 if (!width || !height) {
1256 err = AVERROR_INVALIDDATA;
1257 goto fail;
1258 }
1259
1260 16 aperture_width.num = avio_rb32(pb);
1261 16 aperture_width.den = avio_rb32(pb);
1262 16 aperture_height.num = avio_rb32(pb);
1263 16 aperture_height.den = avio_rb32(pb);
1264
1265 16 horiz_off.num = avio_rb32(pb);
1266 16 horiz_off.den = avio_rb32(pb);
1267 16 vert_off.num = avio_rb32(pb);
1268 16 vert_off.den = avio_rb32(pb);
1269
1270
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 ||
1271
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 ||
1272
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) {
1273 err = AVERROR_INVALIDDATA;
1274 goto fail;
1275 }
1276 16 av_log(c->fc, AV_LOG_TRACE, "clap: apertureWidth %d/%d, apertureHeight %d/%d "
1277 "horizOff %d/%d vertOff %d/%d\n",
1278 aperture_width.num, aperture_width.den, aperture_height.num, aperture_height.den,
1279 horiz_off.num, horiz_off.den, vert_off.num, vert_off.den);
1280
1281 16 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1282 16 pc_x = av_add_q(pc_x, horiz_off);
1283 16 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1284 16 pc_y = av_add_q(pc_y, vert_off);
1285
1286 16 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1287 16 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1288 16 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1289 16 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1290
1291 16 left = av_q2d(av_sub_q(pc_x, aperture_width));
1292 16 right = av_q2d(av_add_q(pc_x, aperture_width));
1293 16 top = av_q2d(av_sub_q(pc_y, aperture_height));
1294 16 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1295
1296
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 if (bottom > (height - 1) ||
1297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 right > (width - 1)) {
1298 2 err = AVERROR_INVALIDDATA;
1299 2 goto fail;
1300 }
1301
1302 14 bottom = height - 1 - bottom;
1303 14 right = width - 1 - right;
1304
1305
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
14 if (!(left | right | top | bottom))
1306 6 return 0;
1307
1308
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if ((left + right) >= width ||
1309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 (top + bottom) >= height) {
1310 err = AVERROR_INVALIDDATA;
1311 goto fail;
1312 }
1313
1314 8 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1315 8 &st->codecpar->nb_coded_side_data,
1316 AV_PKT_DATA_FRAME_CROPPING,
1317 sizeof(uint32_t) * 4, 0);
1318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!sd)
1319 return AVERROR(ENOMEM);
1320
1321 8 AV_WL32A(sd->data, top);
1322 8 AV_WL32A(sd->data + 4, bottom);
1323 8 AV_WL32A(sd->data + 8, left);
1324 8 AV_WL32A(sd->data + 12, right);
1325
1326 10 fail:
1327
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (err < 0) {
1328 2 int explode = !!(c->fc->error_recognition & AV_EF_EXPLODE);
1329
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");
1330
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!explode)
1331 2 err = 0;
1332 }
1333
1334 10 return err;
1335 }
1336
1337 /* This atom overrides any previously set aspect ratio */
1338 65 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1339 {
1340 65 const int num = avio_rb32(pb);
1341 65 const int den = avio_rb32(pb);
1342 AVStream *st;
1343 MOVStreamContext *sc;
1344
1345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (c->fc->nb_streams < 1)
1346 return 0;
1347 65 st = c->fc->streams[c->fc->nb_streams-1];
1348 65 sc = st->priv_data;
1349
1350 65 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1351
1352
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 2 times.
65 if (den != 0) {
1353 63 sc->h_spacing = num;
1354 63 sc->v_spacing = den;
1355 }
1356 65 return 0;
1357 }
1358
1359 /* this atom contains actual media data */
1360 872 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1361 {
1362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 872 times.
872 if (atom.size == 0) /* wrong one (MP4) */
1363 return 0;
1364 872 c->found_mdat=1;
1365 872 return 0; /* now go for moov */
1366 }
1367
1368 #define DRM_BLOB_SIZE 56
1369
1370 static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1371 {
1372 uint8_t intermediate_key[20];
1373 uint8_t intermediate_iv[20];
1374 uint8_t input[64];
1375 uint8_t output[64];
1376 uint8_t file_checksum[20];
1377 uint8_t calculated_checksum[20];
1378 char checksum_string[2 * sizeof(file_checksum) + 1];
1379 struct AVSHA *sha;
1380 int i;
1381 int ret = 0;
1382 uint8_t *activation_bytes = c->activation_bytes;
1383 uint8_t *fixed_key = c->audible_fixed_key;
1384
1385 c->aax_mode = 1;
1386
1387 sha = av_sha_alloc();
1388 if (!sha)
1389 return AVERROR(ENOMEM);
1390 av_free(c->aes_decrypt);
1391 c->aes_decrypt = av_aes_alloc();
1392 if (!c->aes_decrypt) {
1393 ret = AVERROR(ENOMEM);
1394 goto fail;
1395 }
1396
1397 /* drm blob processing */
1398 avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1399 avio_read(pb, input, DRM_BLOB_SIZE);
1400 avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1401 avio_read(pb, file_checksum, 20);
1402
1403 // required by external tools
1404 ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1);
1405 av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string);
1406
1407 /* verify activation data */
1408 if (!activation_bytes) {
1409 av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1410 ret = 0; /* allow ffprobe to continue working on .aax files */
1411 goto fail;
1412 }
1413 if (c->activation_bytes_size != 4) {
1414 av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1415 ret = AVERROR(EINVAL);
1416 goto fail;
1417 }
1418
1419 /* verify fixed key */
1420 if (c->audible_fixed_key_size != 16) {
1421 av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1422 ret = AVERROR(EINVAL);
1423 goto fail;
1424 }
1425
1426 /* AAX (and AAX+) key derivation */
1427 av_sha_init(sha, 160);
1428 av_sha_update(sha, fixed_key, 16);
1429 av_sha_update(sha, activation_bytes, 4);
1430 av_sha_final(sha, intermediate_key);
1431 av_sha_init(sha, 160);
1432 av_sha_update(sha, fixed_key, 16);
1433 av_sha_update(sha, intermediate_key, 20);
1434 av_sha_update(sha, activation_bytes, 4);
1435 av_sha_final(sha, intermediate_iv);
1436 av_sha_init(sha, 160);
1437 av_sha_update(sha, intermediate_key, 16);
1438 av_sha_update(sha, intermediate_iv, 16);
1439 av_sha_final(sha, calculated_checksum);
1440 if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1441 av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1442 ret = AVERROR_INVALIDDATA;
1443 goto fail;
1444 }
1445 av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1446 av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1447 for (i = 0; i < 4; i++) {
1448 // file data (in output) is stored in big-endian mode
1449 if (activation_bytes[i] != output[3 - i]) { // critical error
1450 av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1451 ret = AVERROR_INVALIDDATA;
1452 goto fail;
1453 }
1454 }
1455 memcpy(c->file_key, output + 8, 16);
1456 memcpy(input, output + 26, 16);
1457 av_sha_init(sha, 160);
1458 av_sha_update(sha, input, 16);
1459 av_sha_update(sha, c->file_key, 16);
1460 av_sha_update(sha, fixed_key, 16);
1461 av_sha_final(sha, c->file_iv);
1462
1463 fail:
1464 av_free(sha);
1465
1466 return ret;
1467 }
1468
1469 static int mov_aaxc_crypto(MOVContext *c)
1470 {
1471 if (c->audible_key_size != 16) {
1472 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n");
1473 return AVERROR(EINVAL);
1474 }
1475
1476 if (c->audible_iv_size != 16) {
1477 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n");
1478 return AVERROR(EINVAL);
1479 }
1480
1481 c->aes_decrypt = av_aes_alloc();
1482 if (!c->aes_decrypt) {
1483 return AVERROR(ENOMEM);
1484 }
1485
1486 memcpy(c->file_key, c->audible_key, 16);
1487 memcpy(c->file_iv, c->audible_iv, 16);
1488 c->aax_mode = 1;
1489
1490 return 0;
1491 }
1492
1493 // Audible AAX (and AAX+) bytestream decryption
1494 static int aax_filter(uint8_t *input, int size, MOVContext *c)
1495 {
1496 int blocks = 0;
1497 unsigned char iv[16];
1498
1499 memcpy(iv, c->file_iv, 16); // iv is overwritten
1500 blocks = size >> 4; // trailing bytes are not encrypted!
1501 av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1502 av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1503
1504 return 0;
1505 }
1506
1507 /* read major brand, minor version and compatible brands and store them as metadata */
1508 451 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1509 {
1510 uint32_t minor_ver;
1511 int comp_brand_size;
1512 char* comp_brands_str;
1513 451 uint8_t type[5] = {0};
1514 451 int ret = ffio_read_size(pb, type, 4);
1515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 451 times.
451 if (ret < 0)
1516 return ret;
1517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 451 times.
451 if (c->fc->nb_streams) {
1518 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1519 return AVERROR_INVALIDDATA;
1520 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate FTYP\n");
1521 return 0;
1522 }
1523
1524
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 232 times.
451 if (strcmp(type, "qt "))
1525 219 c->isom = 1;
1526 451 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1527 451 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1528 451 minor_ver = avio_rb32(pb); /* minor version */
1529 451 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1530
1531 451 comp_brand_size = atom.size - 8;
1532
2/4
✓ Branch 0 taken 451 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 451 times.
451 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1533 return AVERROR_INVALIDDATA;
1534 451 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 451 times.
451 if (!comp_brands_str)
1536 return AVERROR(ENOMEM);
1537
1538 451 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 451 times.
451 if (ret < 0) {
1540 av_freep(&comp_brands_str);
1541 return ret;
1542 }
1543 451 comp_brands_str[comp_brand_size] = 0;
1544 451 av_dict_set(&c->fc->metadata, "compatible_brands",
1545 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1546
1547 // Logic for handling Audible's .aaxc files
1548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 451 times.
451 if (!strcmp(type, "aaxc")) {
1549 mov_aaxc_crypto(c);
1550 }
1551
1552 451 return 0;
1553 }
1554
1555 /* this atom should contain all header atoms */
1556 483 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1557 {
1558 int ret;
1559
1560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
483 if (c->found_moov) {
1561 av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1562 avio_skip(pb, atom.size);
1563 return 0;
1564 }
1565
1566
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 483 times.
483 if ((ret = mov_read_default(c, pb, atom)) < 0)
1567 return ret;
1568 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1569 /* so we don't parse the whole file if over a network */
1570 483 c->found_moov=1;
1571 483 return 0; /* now go for mdat */
1572 }
1573
1574 2869 static MOVFragmentStreamInfo * get_frag_stream_info(
1575 MOVFragmentIndex *frag_index,
1576 int index,
1577 int id)
1578 {
1579 int i;
1580 MOVFragmentIndexItem * item;
1581
1582
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)
1583 return NULL;
1584 2869 item = &frag_index->item[index];
1585
1/2
✓ Branch 0 taken 2993 times.
✗ Branch 1 not taken.
2993 for (i = 0; i < item->nb_stream_info; i++)
1586
2/2
✓ Branch 0 taken 2869 times.
✓ Branch 1 taken 124 times.
2993 if (item->stream_info[i].id == id)
1587 2869 return &item->stream_info[i];
1588
1589 // This shouldn't happen
1590 return NULL;
1591 }
1592
1593 388 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1594 {
1595 int i;
1596 MOVFragmentIndexItem * item;
1597
1598
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_index->current < 0 ||
1599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 frag_index->current >= frag_index->nb_items)
1600 return;
1601
1602 388 item = &frag_index->item[frag_index->current];
1603
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < item->nb_stream_info; i++)
1604
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (item->stream_info[i].id == id) {
1605 388 item->current = i;
1606 388 return;
1607 }
1608
1609 // id not found. This shouldn't happen.
1610 item->current = -1;
1611 }
1612
1613 1149 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1614 MOVFragmentIndex *frag_index)
1615 {
1616 MOVFragmentIndexItem *item;
1617
1/2
✓ Branch 0 taken 1149 times.
✗ Branch 1 not taken.
1149 if (frag_index->current < 0 ||
1618
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1146 times.
1149 frag_index->current >= frag_index->nb_items)
1619 3 return NULL;
1620
1621 1146 item = &frag_index->item[frag_index->current];
1622
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)
1623 1146 return &item->stream_info[item->current];
1624
1625 // This shouldn't happen
1626 return NULL;
1627 }
1628
1629 798 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1630 {
1631 int a, b, m;
1632 int64_t moof_offset;
1633
1634 // Optimize for appending new entries
1635
2/2
✓ Branch 0 taken 788 times.
✓ Branch 1 taken 10 times.
798 if (!frag_index->nb_items ||
1636
2/2
✓ Branch 0 taken 383 times.
✓ Branch 1 taken 405 times.
788 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1637 393 return frag_index->nb_items;
1638
1639 405 a = -1;
1640 405 b = frag_index->nb_items;
1641
1642
2/2
✓ Branch 0 taken 2655 times.
✓ Branch 1 taken 405 times.
3060 while (b - a > 1) {
1643 2655 m = (a + b) >> 1;
1644 2655 moof_offset = frag_index->item[m].moof_offset;
1645
2/2
✓ Branch 0 taken 732 times.
✓ Branch 1 taken 1923 times.
2655 if (moof_offset >= offset)
1646 732 b = m;
1647
2/2
✓ Branch 0 taken 2328 times.
✓ Branch 1 taken 327 times.
2655 if (moof_offset <= offset)
1648 2328 a = m;
1649 }
1650 405 return b;
1651 }
1652
1653 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1654 {
1655 av_assert0(frag_stream_info);
1656 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1657 return frag_stream_info->sidx_pts;
1658 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1659 return frag_stream_info->first_tfra_pts;
1660 return frag_stream_info->tfdt_dts;
1661 }
1662
1663 219 static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1664 MOVFragmentIndex *frag_index, int index)
1665 {
1666 MOVFragmentStreamInfo * frag_stream_info;
1667 219 MOVStreamContext *sc = dst_st->priv_data;
1668 int64_t timestamp;
1669 int i, j;
1670
1671 // If the stream is referenced by any sidx, limit the search
1672 // to fragments that referenced this stream in the sidx
1673
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (sc->has_sidx) {
1674 219 frag_stream_info = get_frag_stream_info(frag_index, index, sc->id);
1675
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1676 219 return frag_stream_info->sidx_pts;
1677 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1678 return frag_stream_info->first_tfra_pts;
1679 return frag_stream_info->sidx_pts;
1680 }
1681
1682 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
1683 AVStream *frag_stream = NULL;
1684 frag_stream_info = &frag_index->item[index].stream_info[i];
1685 for (j = 0; j < s->nb_streams; j++) {
1686 MOVStreamContext *sc2 = s->streams[j]->priv_data;
1687 if (sc2->id == frag_stream_info->id)
1688 frag_stream = s->streams[j];
1689 }
1690 if (!frag_stream) {
1691 av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1692 continue;
1693 }
1694 timestamp = get_stream_info_time(frag_stream_info);
1695 if (timestamp != AV_NOPTS_VALUE)
1696 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1697 }
1698 return AV_NOPTS_VALUE;
1699 }
1700
1701 26 static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1702 AVStream *st, int64_t timestamp)
1703 {
1704 int a, b, m, m0;
1705 int64_t frag_time;
1706
1707 26 a = -1;
1708 26 b = frag_index->nb_items;
1709
1710
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 26 times.
245 while (b - a > 1) {
1711 219 m0 = m = (a + b) >> 1;
1712
1713
2/4
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 219 times.
438 while (m < b &&
1714 219 (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
1715 m++;
1716
1717
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)
1718 93 a = m;
1719 else
1720 126 b = m0;
1721 }
1722
1723 26 return a;
1724 }
1725
1726 756 static int update_frag_index(MOVContext *c, int64_t offset)
1727 {
1728 int index, i;
1729 MOVFragmentIndexItem * item;
1730 MOVFragmentStreamInfo * frag_stream_info;
1731
1732 // If moof_offset already exists in frag_index, return index to it
1733 756 index = search_frag_moof_offset(&c->frag_index, offset);
1734
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 389 times.
756 if (index < c->frag_index.nb_items &&
1735
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 c->frag_index.item[index].moof_offset == offset)
1736 367 return index;
1737
1738 // offset is not yet in frag index.
1739 // Insert new item at index (sorted by moof offset)
1740 389 item = av_fast_realloc(c->frag_index.item,
1741 389 &c->frag_index.allocated_size,
1742 389 (c->frag_index.nb_items + 1) *
1743 sizeof(*c->frag_index.item));
1744
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (!item)
1745 return -1;
1746 389 c->frag_index.item = item;
1747
1748 389 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1749 sizeof(*item->stream_info));
1750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (!frag_stream_info)
1751 return -1;
1752
1753
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 389 times.
796 for (i = 0; i < c->fc->nb_streams; i++) {
1754 // Avoid building frag index if streams lack track id.
1755 407 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 407 times.
407 if (sc->id < 0) {
1757 av_free(frag_stream_info);
1758 return AVERROR_INVALIDDATA;
1759 }
1760
1761 407 frag_stream_info[i].id = sc->id;
1762 407 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1763 407 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1764 407 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1765 407 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1766 407 frag_stream_info[i].index_base = -1;
1767 407 frag_stream_info[i].index_entry = -1;
1768 407 frag_stream_info[i].encryption_index = NULL;
1769 407 frag_stream_info[i].stsd_id = -1;
1770 }
1771
1772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (index < c->frag_index.nb_items)
1773 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1774 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1775
1776 389 item = &c->frag_index.item[index];
1777 389 item->headers_read = 0;
1778 389 item->current = 0;
1779 389 item->nb_stream_info = c->fc->nb_streams;
1780 389 item->moof_offset = offset;
1781 389 item->stream_info = frag_stream_info;
1782 389 c->frag_index.nb_items++;
1783
1784 389 return index;
1785 }
1786
1787 388 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1788 int id, int entries)
1789 {
1790 int i;
1791 MOVFragmentStreamInfo * frag_stream_info;
1792
1793
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (index < 0)
1794 388 return;
1795 for (i = index; i < frag_index->nb_items; i++) {
1796 frag_stream_info = get_frag_stream_info(frag_index, i, id);
1797 if (frag_stream_info && frag_stream_info->index_entry >= 0)
1798 frag_stream_info->index_entry += entries;
1799 }
1800 }
1801
1802 388 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1803 {
1804 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1805 388 c->fragment.found_tfhd = 0;
1806
1807
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) {
1808 c->has_looked_for_mfra = 1;
1809 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1810 int ret;
1811 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1812 "for a mfra\n");
1813 if ((ret = mov_read_mfra(c, pb)) < 0) {
1814 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1815 "read the mfra (may be a live ismv)\n");
1816 }
1817 } else {
1818 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1819 "seekable, can not look for mfra\n");
1820 }
1821 }
1822 388 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1823 388 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1824 388 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1825 388 return mov_read_default(c, pb, atom);
1826 }
1827
1828 1073 static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version)
1829 {
1830 int64_t time;
1831
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1062 times.
1073 if (version == 1) {
1832 11 time = avio_rb64(pb);
1833 11 avio_rb64(pb);
1834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (time < 0) {
1835 av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n");
1836 return;
1837 }
1838 } else {
1839 1062 time = avio_rb32(pb);
1840 1062 avio_rb32(pb); /* modification time */
1841
4/4
✓ Branch 0 taken 519 times.
✓ Branch 1 taken 543 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 471 times.
1062 if (time > 0 && time < 2082844800) {
1842 48 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1843 48 time += 2082844800;
1844 }
1845 }
1846
2/2
✓ Branch 0 taken 525 times.
✓ Branch 1 taken 548 times.
1073 if (time) {
1847 525 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1848
1849
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 525 times.
525 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1850 av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n");
1851 return;
1852 }
1853
1854 525 avpriv_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1855 }
1856 }
1857
1858 593 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1859 {
1860 AVStream *st;
1861 MOVStreamContext *sc;
1862 int version;
1863 593 char language[4] = {0};
1864 unsigned lang;
1865
1866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->fc->nb_streams < 1)
1867 return 0;
1868 593 st = c->fc->streams[c->fc->nb_streams-1];
1869 593 sc = st->priv_data;
1870
1871
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (sc->time_scale) {
1872 av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
1873 return AVERROR_INVALIDDATA;
1874 }
1875
1876 593 version = avio_r8(pb);
1877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (version > 1) {
1878 avpriv_request_sample(c->fc, "Version %d", version);
1879 return AVERROR_PATCHWELCOME;
1880 }
1881 593 avio_rb24(pb); /* flags */
1882 593 mov_metadata_creation_time(c, pb, &st->metadata, version);
1883
1884 593 sc->time_scale = avio_rb32(pb);
1885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (sc->time_scale <= 0) {
1886 av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
1887 sc->time_scale = 1;
1888 }
1889
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 584 times.
593 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1890
1891
6/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 584 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 584 times.
✓ Branch 5 taken 4 times.
593 if ((version == 1 && st->duration == UINT64_MAX) ||
1892
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 584 times.
584 (version != 1 && st->duration == UINT32_MAX)) {
1893 5 st->duration = 0;
1894 }
1895
1896 593 lang = avio_rb16(pb); /* language */
1897
2/2
✓ Branch 1 taken 421 times.
✓ Branch 2 taken 172 times.
593 if (ff_mov_lang_to_iso639(lang, language))
1898 421 av_dict_set(&st->metadata, "language", language, 0);
1899 593 avio_rb16(pb); /* quality */
1900
1901 593 return 0;
1902 }
1903
1904 480 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1905 {
1906 int i;
1907 480 int version = avio_r8(pb); /* version */
1908 480 avio_rb24(pb); /* flags */
1909
1910 480 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
1911 480 c->time_scale = avio_rb32(pb); /* time scale */
1912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 480 times.
480 if (c->time_scale <= 0) {
1913 av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
1914 c->time_scale = 1;
1915 }
1916 480 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
1917
1918
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 478 times.
480 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1919 480 avio_rb32(pb); /* preferred scale */
1920
1921 480 avio_rb16(pb); /* preferred volume */
1922
1923 480 avio_skip(pb, 10); /* reserved */
1924
1925 /* movie display matrix, store it in main context and use it later on */
1926
2/2
✓ Branch 0 taken 1440 times.
✓ Branch 1 taken 480 times.
1920 for (i = 0; i < 3; i++) {
1927 1440 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
1928 1440 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
1929 1440 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
1930 }
1931
1932 480 avio_rb32(pb); /* preview time */
1933 480 avio_rb32(pb); /* preview duration */
1934 480 avio_rb32(pb); /* poster time */
1935 480 avio_rb32(pb); /* selection time */
1936 480 avio_rb32(pb); /* selection duration */
1937 480 avio_rb32(pb); /* current time */
1938 480 avio_rb32(pb); /* next track ID */
1939
1940 480 return 0;
1941 }
1942
1943 7 static void set_last_stream_little_endian(AVFormatContext *fc)
1944 {
1945 AVStream *st;
1946
1947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (fc->nb_streams < 1)
1948 return;
1949 7 st = fc->streams[fc->nb_streams-1];
1950
1951
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) {
1952 5 case AV_CODEC_ID_PCM_S16BE:
1953 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
1954 5 break;
1955 1 case AV_CODEC_ID_PCM_S24BE:
1956 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
1957 1 break;
1958 case AV_CODEC_ID_PCM_S32BE:
1959 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
1960 break;
1961 1 case AV_CODEC_ID_PCM_F32BE:
1962 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
1963 1 break;
1964 case AV_CODEC_ID_PCM_F64BE:
1965 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
1966 break;
1967 default:
1968 break;
1969 }
1970 }
1971
1972 5 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1973 {
1974 5 int little_endian = avio_rb16(pb) & 0xFF;
1975 5 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
1976
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (little_endian == 1)
1977 1 set_last_stream_little_endian(c->fc);
1978 5 return 0;
1979 }
1980
1981 6 static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1982 {
1983 int format_flags;
1984 int version, flags;
1985 int pcm_sample_size;
1986 6 AVFormatContext *fc = c->fc;
1987 AVStream *st;
1988 MOVStreamContext *sc;
1989
1990
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 6) {
1991 av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n");
1992 return AVERROR_INVALIDDATA;
1993 }
1994
1995 6 version = avio_r8(pb);
1996 6 flags = avio_rb24(pb);
1997
1998
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) {
1999 av_log(c->fc, AV_LOG_ERROR,
2000 "Unsupported 'pcmC' box with version %d, flags: %x",
2001 version, flags);
2002 return AVERROR_INVALIDDATA;
2003 }
2004
2005 6 format_flags = avio_r8(pb);
2006 6 pcm_sample_size = avio_r8(pb);
2007
2008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fc->nb_streams < 1)
2009 return AVERROR_INVALIDDATA;
2010
2011 6 st = fc->streams[fc->nb_streams - 1];
2012 6 sc = st->priv_data;
2013
2014
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (sc->format == MOV_MP4_FPCM_TAG) {
2015
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (pcm_sample_size) {
2016 1 case 32:
2017 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE;
2018 1 break;
2019 case 64:
2020 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE;
2021 break;
2022 default:
2023 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2024 pcm_sample_size,
2025 av_fourcc2str(sc->format));
2026 return AVERROR_INVALIDDATA;
2027 }
2028
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (sc->format == MOV_MP4_IPCM_TAG) {
2029
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 switch (pcm_sample_size) {
2030 5 case 16:
2031 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2032 5 break;
2033 case 24:
2034 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
2035 break;
2036 case 32:
2037 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
2038 break;
2039 default:
2040 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2041 pcm_sample_size,
2042 av_fourcc2str(sc->format));
2043 return AVERROR_INVALIDDATA;
2044 }
2045 } else {
2046 av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n",
2047 av_fourcc2str(sc->format));
2048 return AVERROR_INVALIDDATA;
2049 }
2050
2051
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
2052 6 set_last_stream_little_endian(c->fc);
2053 6 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2054
2055 6 return 0;
2056 }
2057
2058 43 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2059 {
2060 AVStream *st;
2061 43 HEIFItem *item = NULL;
2062 43 char color_parameter_type[5] = { 0 };
2063 uint16_t color_primaries, color_trc, color_matrix;
2064 int ret;
2065
2066 43 st = get_curr_st(c);
2067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st) {
2068 item = heif_cur_item(c);
2069 if (!item)
2070 return 0;
2071 }
2072
2073 43 ret = ffio_read_size(pb, color_parameter_type, 4);
2074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
2075 return ret;
2076
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 10 times.
43 if (strncmp(color_parameter_type, "nclx", 4) &&
2077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 strncmp(color_parameter_type, "nclc", 4) &&
2078 strncmp(color_parameter_type, "prof", 4)) {
2079 av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
2080 color_parameter_type);
2081 return 0;
2082 }
2083
2084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!strncmp(color_parameter_type, "prof", 4)) {
2085 AVPacketSideData *sd;
2086 uint8_t *icc_profile;
2087 if (st) {
2088 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
2089 &st->codecpar->nb_coded_side_data,
2090 AV_PKT_DATA_ICC_PROFILE,
2091 atom.size - 4, 0);
2092 if (!sd)
2093 return AVERROR(ENOMEM);
2094 icc_profile = sd->data;
2095 } else {
2096 av_freep(&item->icc_profile);
2097 icc_profile = item->icc_profile = av_malloc(atom.size - 4);
2098 if (!icc_profile) {
2099 item->icc_profile_size = 0;
2100 return AVERROR(ENOMEM);
2101 }
2102 item->icc_profile_size = atom.size - 4;
2103 }
2104 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
2105 if (ret < 0)
2106 return ret;
2107
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 } else if (st) {
2108 43 color_primaries = avio_rb16(pb);
2109 43 color_trc = avio_rb16(pb);
2110 43 color_matrix = avio_rb16(pb);
2111
2112 43 av_log(c->fc, AV_LOG_TRACE,
2113 "%s: pri %d trc %d matrix %d",
2114 color_parameter_type, color_primaries, color_trc, color_matrix);
2115
2116
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 33 times.
43 if (!strncmp(color_parameter_type, "nclx", 4)) {
2117 10 uint8_t color_range = avio_r8(pb) >> 7;
2118 10 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (color_range)
2120 st->codecpar->color_range = AVCOL_RANGE_JPEG;
2121 else
2122 10 st->codecpar->color_range = AVCOL_RANGE_MPEG;
2123 }
2124
2125
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_primaries_name(color_primaries))
2126 color_primaries = AVCOL_PRI_UNSPECIFIED;
2127
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_transfer_name(color_trc))
2128 color_trc = AVCOL_TRC_UNSPECIFIED;
2129
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_space_name(color_matrix))
2130 color_matrix = AVCOL_SPC_UNSPECIFIED;
2131
2132 43 st->codecpar->color_primaries = color_primaries;
2133 43 st->codecpar->color_trc = color_trc;
2134 43 st->codecpar->color_space = color_matrix;
2135 43 av_log(c->fc, AV_LOG_TRACE, "\n");
2136 }
2137 43 return 0;
2138 }
2139
2140 111 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2141 {
2142 AVStream *st;
2143 unsigned mov_field_order;
2144 111 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2145
2146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111 times.
111 if (c->fc->nb_streams < 1) // will happen with jp2 files
2147 return 0;
2148 111 st = c->fc->streams[c->fc->nb_streams-1];
2149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111 times.
111 if (atom.size < 2)
2150 return AVERROR_INVALIDDATA;
2151 111 mov_field_order = avio_rb16(pb);
2152
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 20 times.
111 if ((mov_field_order & 0xFF00) == 0x0100)
2153 91 decoded_field_order = AV_FIELD_PROGRESSIVE;
2154
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 else if ((mov_field_order & 0xFF00) == 0x0200) {
2155
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) {
2156 1 case 0x01: decoded_field_order = AV_FIELD_TT;
2157 1 break;
2158 case 0x06: decoded_field_order = AV_FIELD_BB;
2159 break;
2160 1 case 0x09: decoded_field_order = AV_FIELD_TB;
2161 1 break;
2162 18 case 0x0E: decoded_field_order = AV_FIELD_BT;
2163 18 break;
2164 }
2165 }
2166
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 111 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
111 if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) {
2167 av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
2168 }
2169 111 st->codecpar->field_order = decoded_field_order;
2170
2171 111 return 0;
2172 }
2173
2174 68 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
2175 {
2176 68 int err = 0;
2177 68 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
2178
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)
2179 return AVERROR_INVALIDDATA;
2180
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
68 if ((err = av_reallocp(&par->extradata, size)) < 0) {
2181 par->extradata_size = 0;
2182 return err;
2183 }
2184 68 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
2185 68 return 0;
2186 }
2187
2188 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
2189 65 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2190 AVCodecParameters *par, uint8_t *buf)
2191 {
2192 65 int64_t result = atom.size;
2193 int err;
2194
2195 65 AV_WB32(buf , atom.size + 8);
2196 65 AV_WL32(buf + 4, atom.type);
2197 65 err = ffio_read_size(pb, buf + 8, atom.size);
2198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (err < 0) {
2199 par->extradata_size -= atom.size;
2200 return err;
2201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 } else if (err < atom.size) {
2202 av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
2203 par->extradata_size -= atom.size - err;
2204 result = err;
2205 }
2206 65 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2207 65 return result;
2208 }
2209
2210 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
2211 58 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2212 enum AVCodecID codec_id)
2213 {
2214 AVStream *st;
2215 uint64_t original_size;
2216 int err;
2217
2218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (c->fc->nb_streams < 1) // will happen with jp2 files
2219 return 0;
2220 58 st = c->fc->streams[c->fc->nb_streams-1];
2221
2222
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
58 if (st->codecpar->codec_id != codec_id)
2223 19 return 0; /* unexpected codec_id - don't mess with extradata */
2224
2225 39 original_size = st->codecpar->extradata_size;
2226 39 err = mov_realloc_extradata(st->codecpar, atom);
2227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err)
2228 return err;
2229
2230 39 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
2231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err < 0)
2232 return err;
2233 39 return 0; // Note: this is the original behavior to ignore truncation.
2234 }
2235
2236 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
2237 16 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2238 {
2239 16 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
2240 }
2241
2242 static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2243 {
2244 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS);
2245 }
2246
2247 static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2248 {
2249 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
2250 }
2251
2252 static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2253 {
2254 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
2255 }
2256
2257 19 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2258 {
2259 19 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
2260
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!ret)
2261 19 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
2262 19 return ret;
2263 }
2264
2265 static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2266 {
2267 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
2268
2269 if (!ret && c->fc->nb_streams >= 1) {
2270 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2271 if (par->extradata_size >= 40) {
2272 par->height = AV_RB16(&par->extradata[36]);
2273 par->width = AV_RB16(&par->extradata[38]);
2274 }
2275 }
2276 return ret;
2277 }
2278
2279 16 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2280 {
2281
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (c->fc->nb_streams >= 1) {
2282 16 AVStream *const st = c->fc->streams[c->fc->nb_streams - 1];
2283 16 FFStream *const sti = ffstream(st);
2284 16 AVCodecParameters *par = st->codecpar;
2285
2286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
2287 par->codec_id == AV_CODEC_ID_H264 &&
2288 atom.size > 11) {
2289 int cid;
2290 avio_skip(pb, 10);
2291 cid = avio_rb16(pb);
2292 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
2293 if (cid == 0xd4d || cid == 0xd4e)
2294 par->width = 1440;
2295 return 0;
2296
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
2297
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
2298
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
2299
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 atom.size >= 24) {
2300 int num, den;
2301 13 avio_skip(pb, 12);
2302 13 num = avio_rb32(pb);
2303 13 den = avio_rb32(pb);
2304
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)
2305 return 0;
2306
2/3
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
13 switch (avio_rb32(pb)) {
2307 12 case 2:
2308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (den >= INT_MAX / 2)
2309 return 0;
2310 12 den *= 2;
2311 13 case 1:
2312 13 sti->display_aspect_ratio = (AVRational){ num, den };
2313 13 default:
2314 13 return 0;
2315 }
2316 }
2317 }
2318
2319 3 return mov_read_avid(c, pb, atom);
2320 }
2321
2322 26 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2323 {
2324 26 int ret = 0;
2325 26 int length = 0;
2326 uint64_t original_size;
2327
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (c->fc->nb_streams >= 1) {
2328 26 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (par->codec_id == AV_CODEC_ID_H264)
2330 return 0;
2331
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (atom.size == 16) {
2332 26 original_size = par->extradata_size;
2333 26 ret = mov_realloc_extradata(par, atom);
2334
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!ret) {
2335 26 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
2336
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (length == atom.size) {
2337 26 const uint8_t range_value = par->extradata[original_size + 19];
2338
1/3
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
26 switch (range_value) {
2339 26 case 1:
2340 26 par->color_range = AVCOL_RANGE_MPEG;
2341 26 break;
2342 case 2:
2343 par->color_range = AVCOL_RANGE_JPEG;
2344 break;
2345 default:
2346 av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
2347 break;
2348 }
2349 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
2350 } else {
2351 /* For some reason the whole atom was not added to the extradata */
2352 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
2353 }
2354 } else {
2355 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
2356 }
2357 } else {
2358 av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
2359 }
2360 }
2361
2362 26 return ret;
2363 }
2364
2365 4 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2366 {
2367 4 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
2368 }
2369
2370 34 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2371 {
2372 AVStream *st;
2373 int ret;
2374
2375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (c->fc->nb_streams < 1)
2376 return 0;
2377 34 st = c->fc->streams[c->fc->nb_streams-1];
2378
2379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if ((uint64_t)atom.size > (1<<30))
2380 return AVERROR_INVALIDDATA;
2381
2382
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2 times.
34 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2383
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
2385 // pass all frma atom to codec, needed at least for QDMC and QDM2
2386 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2388 return ret;
2389
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 } else if (atom.size > 8) { /* to read frma, esds atoms */
2390
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) {
2391 uint64_t buffer;
2392 10 ret = ffio_ensure_seekback(pb, 8);
2393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2394 return ret;
2395 10 buffer = avio_rb64(pb);
2396 10 atom.size -= 8;
2397
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
2398
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 <= atom.size
2399
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 >= 8) {
2400 10 avio_skip(pb, -8);
2401 10 atom.size += 8;
2402 } else if (!st->codecpar->extradata_size) {
2403 #define ALAC_EXTRADATA_SIZE 36
2404 st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
2405 if (!st->codecpar->extradata)
2406 return AVERROR(ENOMEM);
2407 st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
2408 AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
2409 AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
2410 AV_WB64(st->codecpar->extradata + 12, buffer);
2411 avio_read(pb, st->codecpar->extradata + 20, 16);
2412 avio_skip(pb, atom.size - 24);
2413 return 0;
2414 }
2415 }
2416
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if ((ret = mov_read_default(c, pb, atom)) < 0)
2417 return ret;
2418 } else
2419 avio_skip(pb, atom.size);
2420 34 return 0;
2421 }
2422
2423 /**
2424 * This function reads atom content and puts data in extradata without tag
2425 * nor size unlike mov_read_extradata.
2426 */
2427 138 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2428 {
2429 AVStream *st;
2430 int ret;
2431
2432 138 st = get_curr_st(c);
2433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (!st)
2434 return 0;
2435
2436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if ((uint64_t)atom.size > (1<<30))
2437 return AVERROR_INVALIDDATA;
2438
2439
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 137 times.
138 if (atom.type == MKTAG('v','v','c','C')) {
2440 1 avio_skip(pb, 4);
2441 1 atom.size -= 4;
2442 }
2443
2444
2/2
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 4 times.
138 if (atom.size >= 10) {
2445 // Broken files created by legacy versions of libavformat will
2446 // wrap a whole fiel atom inside of a glbl atom.
2447 134 unsigned size = avio_rb32(pb);
2448 134 unsigned type = avio_rl32(pb);
2449
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 134 times.
134 if (avio_feof(pb))
2450 return AVERROR_INVALIDDATA;
2451 134 avio_seek(pb, -8, SEEK_CUR);
2452
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 126 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
134 if (type == MKTAG('f','i','e','l') && size == atom.size)
2453 8 return mov_read_default(c, pb, atom);
2454 }
2455
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 130 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
130 if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
2456 av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
2457 return 0;
2458 }
2459 130 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 130 times.
130 if (ret < 0)
2461 return ret;
2462
3/4
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 38 times.
130 if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
2463 /* HEVC-based Dolby Vision derived from hvc1.
2464 Happens to match with an identifier
2465 previously utilized for DV. Thus, if we have
2466 the hvcC extradata box available as specified,
2467 set codec to HEVC */
2468 st->codecpar->codec_id = AV_CODEC_ID_HEVC;
2469
2470 130 return 0;
2471 }
2472
2473 2 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2474 {
2475 AVStream *st;
2476 uint8_t profile_level;
2477 int ret;
2478
2479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
2480 return 0;
2481 2 st = c->fc->streams[c->fc->nb_streams-1];
2482
2483
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)
2484 return AVERROR_INVALIDDATA;
2485
2486 2 profile_level = avio_r8(pb);
2487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((profile_level & 0xf0) != 0xc0)
2488 return 0;
2489
2490 2 avio_seek(pb, 6, SEEK_CUR);
2491 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
2492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2493 return ret;
2494
2495 2 return 0;
2496 }
2497
2498 static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2499 {
2500 AVStream* st;
2501 MOVStreamContext* sc;
2502
2503 if (c->fc->nb_streams < 1)
2504 return 0;
2505
2506 /* For SBAS this should be fine - though beware if someone implements a
2507 * tref atom processor that doesn't drop down to default then this may
2508 * be lost. */
2509 if (atom.size > 4) {
2510 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2511 return AVERROR_PATCHWELCOME;
2512 }
2513
2514 st = c->fc->streams[c->fc->nb_streams - 1];
2515 sc = st->priv_data;
2516 sc->tref_id = avio_rb32(pb);
2517 sc->tref_flags |= MOV_TREF_FLAG_ENHANCEMENT;
2518
2519 return 0;
2520 }
2521
2522 /**
2523 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2524 * but can have extradata appended at the end after the 40 bytes belonging
2525 * to the struct.
2526 */
2527 static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2528 {
2529 AVStream *st;
2530 int ret;
2531
2532 if (c->fc->nb_streams < 1)
2533 return 0;
2534 if (atom.size <= 40)
2535 return 0;
2536 st = c->fc->streams[c->fc->nb_streams-1];
2537
2538 if ((uint64_t)atom.size > (1<<30))
2539 return AVERROR_INVALIDDATA;
2540
2541 avio_skip(pb, 40);
2542 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
2543 if (ret < 0)
2544 return ret;
2545
2546 return 0;
2547 }
2548
2549 593 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2550 {
2551 AVStream *st;
2552 MOVStreamContext *sc;
2553 unsigned int i, entries;
2554
2555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->trak_index < 0) {
2556 av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
2557 return 0;
2558 }
2559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->fc->nb_streams < 1)
2560 return 0;
2561 593 st = c->fc->streams[c->fc->nb_streams-1];
2562 593 sc = st->priv_data;
2563
2564 593 avio_r8(pb); /* version */
2565 593 avio_rb24(pb); /* flags */
2566
2567 // Clamp allocation size for `chunk_offsets` -- don't throw an error for an
2568 // invalid count since the EOF path doesn't throw either.
2569 593 entries = avio_rb32(pb);
2570 593 entries =
2571
2/2
✓ Branch 0 taken 588 times.
✓ Branch 1 taken 5 times.
593 FFMIN(entries,
2572 FFMAX(0, (atom.size - 8) /
2573 (atom.type == MKTAG('s', 't', 'c', 'o') ? 4 : 8)));
2574
2575
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 577 times.
593 if (!entries)
2576 16 return 0;
2577
2578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 577 times.
577 if (sc->chunk_offsets) {
2579 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2580 return 0;
2581 }
2582
2583 577 av_free(sc->chunk_offsets);
2584 577 sc->chunk_count = 0;
2585 577 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 577 times.
577 if (!sc->chunk_offsets)
2587 return AVERROR(ENOMEM);
2588 577 sc->chunk_count = entries;
2589
2590
2/2
✓ Branch 0 taken 573 times.
✓ Branch 1 taken 4 times.
577 if (atom.type == MKTAG('s','t','c','o'))
2591
3/4
✓ Branch 0 taken 42906 times.
✓ Branch 1 taken 573 times.
✓ Branch 2 taken 42906 times.
✗ Branch 3 not taken.
43479 for (i = 0; i < entries && !pb->eof_reached; i++)
2592 42906 sc->chunk_offsets[i] = avio_rb32(pb);
2593
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (atom.type == MKTAG('c','o','6','4'))
2594
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++) {
2595 136336 sc->chunk_offsets[i] = avio_rb64(pb);
2596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136336 times.
136336 if (sc->chunk_offsets[i] < 0) {
2597 av_log(c->fc, AV_LOG_WARNING, "Impossible chunk_offset\n");
2598 sc->chunk_offsets[i] = 0;
2599 }
2600 }
2601 else
2602 return AVERROR_INVALIDDATA;
2603
2604 577 sc->chunk_count = i;
2605
2606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 577 times.
577 if (pb->eof_reached) {
2607 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2608 return AVERROR_EOF;
2609 }
2610
2611 577 return 0;
2612 }
2613
2614 630 static int mov_codec_id(AVStream *st, uint32_t format)
2615 {
2616 630 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2617
2618
2/2
✓ Branch 0 taken 410 times.
✓ Branch 1 taken 220 times.
630 if (id <= 0 &&
2619
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 3 times.
410 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 407 times.
407 (format & 0xFFFF) == 'T' + ('S' << 8)))
2621 3 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2622
2623
4/4
✓ Branch 0 taken 293 times.
✓ Branch 1 taken 337 times.
✓ Branch 2 taken 223 times.
✓ Branch 3 taken 70 times.
630 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2624 223 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2625
3/4
✓ Branch 0 taken 389 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 389 times.
✗ Branch 3 not taken.
407 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2626 /* skip old ASF MPEG-4 tag */
2627
2/2
✓ Branch 0 taken 385 times.
✓ Branch 1 taken 4 times.
389 format && format != MKTAG('m','p','4','s')) {
2628 385 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2629
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 330 times.
385 if (id <= 0)
2630 55 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2631
2/2
✓ Branch 0 taken 334 times.
✓ Branch 1 taken 51 times.
385 if (id > 0)
2632 334 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2633
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 47 times.
51 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2634
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2635
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2636 47 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2637
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6 times.
47 if (id <= 0) {
2638
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 2 times.
80 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2639
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 2 times.
80 AV_CODEC_ID_TTML : id;
2640 }
2641
2642
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 37 times.
47 if (id > 0)
2643 10 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2644 else
2645 37 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2646 }
2647 }
2648
2649 630 st->codecpar->codec_tag = format;
2650
2651 630 return id;
2652 }
2653
2654 311 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2655 AVStream *st, MOVStreamContext *sc)
2656 {
2657 311 uint8_t codec_name[32] = { 0 };
2658 int64_t stsd_start;
2659 unsigned int len;
2660 311 uint32_t id = 0;
2661
2662 /* The first 16 bytes of the video sample description are already
2663 * read in ff_mov_read_stsd_entries() */
2664 311 stsd_start = avio_tell(pb) - 16;
2665
2666 311 avio_rb16(pb); /* version */
2667 311 avio_rb16(pb); /* revision level */
2668 311 id = avio_rl32(pb); /* vendor */
2669 311 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2670 311 avio_rb32(pb); /* temporal quality */
2671 311 avio_rb32(pb); /* spatial quality */
2672
2673 311 st->codecpar->width = avio_rb16(pb); /* width */
2674 311 st->codecpar->height = avio_rb16(pb); /* height */
2675
2676 311 avio_rb32(pb); /* horiz resolution */
2677 311 avio_rb32(pb); /* vert resolution */
2678 311 avio_rb32(pb); /* data size, always 0 */
2679 311 avio_rb16(pb); /* frames per samples */
2680
2681 311 len = avio_r8(pb); /* codec name, pascal string */
2682
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 310 times.
311 if (len > 31)
2683 1 len = 31;
2684 311 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2685
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 2 times.
311 if (len < 31)
2686 309 avio_skip(pb, 31 - len);
2687
2688
2/2
✓ Branch 0 taken 249 times.
✓ Branch 1 taken 62 times.
311 if (codec_name[0])
2689 249 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2690
2691 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 311 times.
311 if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2693 st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2694 st->codecpar->width &= ~1;
2695 st->codecpar->height &= ~1;
2696 }
2697 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 311 times.
311 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2699 !strncmp(codec_name, "Sorenson H263", 13))
2700 st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2701
2702 311 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2703
2704 311 avio_seek(pb, stsd_start, SEEK_SET);
2705
2706
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 293 times.
311 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2707 18 st->codecpar->bits_per_coded_sample &= 0x1F;
2708 18 sc->has_palette = 1;
2709 }
2710 311 }
2711
2712 241 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2713 AVStream *st, MOVStreamContext *sc)
2714 {
2715 int bits_per_sample, flags;
2716 241 uint16_t version = avio_rb16(pb);
2717 241 uint32_t id = 0;
2718 241 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2719 int channel_count;
2720
2721 241 avio_rb16(pb); /* revision level */
2722 241 id = avio_rl32(pb); /* vendor */
2723 241 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2724
2725 241 channel_count = avio_rb16(pb);
2726
2727 241 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2728 241 st->codecpar->ch_layout.nb_channels = channel_count;
2729 241 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
2730 241 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
2731
2732 241 sc->audio_cid = avio_rb16(pb);
2733 241 avio_rb16(pb); /* packet size = 0 */
2734
2735 241 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
2736
2737 // Read QT version 1 fields. In version 0 these do not exist.
2738 241 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
2739
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 ||
2740
1/2
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
155 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
2741
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)) {
2742
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 40 times.
90 if (version == 1) {
2743 50 sc->samples_per_frame = avio_rb32(pb);
2744 50 avio_rb32(pb); /* bytes per packet */
2745 50 sc->bytes_per_frame = avio_rb32(pb);
2746 50 avio_rb32(pb); /* bytes per sample */
2747
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
40 } else if (version == 2) {
2748 4 avio_rb32(pb); /* sizeof struct only */
2749 4 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
2750 4 channel_count = avio_rb32(pb);
2751 4 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2752 4 st->codecpar->ch_layout.nb_channels = channel_count;
2753 4 avio_rb32(pb); /* always 0x7F000000 */
2754 4 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
2755
2756 4 flags = avio_rb32(pb); /* lpcm format specific flag */
2757 4 sc->bytes_per_frame = avio_rb32(pb);
2758 4 sc->samples_per_frame = avio_rb32(pb);
2759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
2760 st->codecpar->codec_id =
2761 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
2762 flags);
2763 }
2764
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)) {
2765 /* can't correctly handle variable sized packet as audio unit */
2766
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 switch (st->codecpar->codec_id) {
2767 case AV_CODEC_ID_MP2:
2768 case AV_CODEC_ID_MP3:
2769 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
2770 break;
2771 }
2772 }
2773 }
2774
2775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (sc->format == 0) {
2776 if (st->codecpar->bits_per_coded_sample == 8)
2777 st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
2778 else if (st->codecpar->bits_per_coded_sample == 16)
2779 st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
2780 }
2781
2782
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) {
2783 7 case AV_CODEC_ID_PCM_S8:
2784 case AV_CODEC_ID_PCM_U8:
2785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
2786 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2787 7 break;
2788 19 case AV_CODEC_ID_PCM_S16LE:
2789 case AV_CODEC_ID_PCM_S16BE:
2790
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
19 if (st->codecpar->bits_per_coded_sample == 8)
2791 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
2792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 24)
2793 st->codecpar->codec_id =
2794 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2795 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
2796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 32)
2797 st->codecpar->codec_id =
2798 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2799 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
2800 19 break;
2801 /* set values for old format before stsd version 1 appeared */
2802 2 case AV_CODEC_ID_MACE3:
2803 2 sc->samples_per_frame = 6;
2804 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
2805 2 break;
2806 8 case AV_CODEC_ID_MACE6:
2807 8 sc->samples_per_frame = 6;
2808 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
2809 8 break;
2810 5 case AV_CODEC_ID_ADPCM_IMA_QT:
2811 5 sc->samples_per_frame = 64;
2812 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
2813 5 break;
2814 1 case AV_CODEC_ID_GSM:
2815 1 sc->samples_per_frame = 160;
2816 1 sc->bytes_per_frame = 33;
2817 1 break;
2818 199 default:
2819 199 break;
2820 }
2821
2822 241 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2823
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) {
2824 48 st->codecpar->bits_per_coded_sample = bits_per_sample;
2825 48 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
2826 }
2827 241 }
2828
2829 11 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
2830 AVStream *st, MOVStreamContext *sc,
2831 int64_t size)
2832 {
2833 // ttxt stsd contains display flags, justification, background
2834 // color, fonts, and default styles, so fake an atom to read it
2835 11 MOVAtom fake_atom = { .size = size };
2836 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
2837 // in extradata unlike stpp MP4 TTML.
2838
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
2839
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
2840 9 mov_read_glbl(c, pb, fake_atom);
2841 11 st->codecpar->width = sc->width;
2842 11 st->codecpar->height = sc->height;
2843 11 }
2844
2845 static uint32_t yuv_to_rgba(uint32_t ycbcr)
2846 {
2847 uint8_t r, g, b;
2848 int y, cb, cr;
2849
2850 y = (ycbcr >> 16) & 0xFF;
2851 cr = (ycbcr >> 8) & 0xFF;
2852 cb = ycbcr & 0xFF;
2853
2854 b = av_clip_uint8((1164 * (y - 16) + 2018 * (cb - 128)) / 1000);
2855 g = av_clip_uint8((1164 * (y - 16) - 813 * (cr - 128) - 391 * (cb - 128)) / 1000);
2856 r = av_clip_uint8((1164 * (y - 16) + 1596 * (cr - 128) ) / 1000);
2857
2858 return (r << 16) | (g << 8) | b;
2859 }
2860
2861 static int mov_rewrite_dvd_sub_extradata(AVStream *st)
2862 {
2863 char buf[256] = {0};
2864 uint8_t *src = st->codecpar->extradata;
2865 int i, ret;
2866
2867 if (st->codecpar->extradata_size != 64)
2868 return 0;
2869
2870 if (st->codecpar->width > 0 && st->codecpar->height > 0)
2871 snprintf(buf, sizeof(buf), "size: %dx%d\n",
2872 st->codecpar->width, st->codecpar->height);
2873 av_strlcat(buf, "palette: ", sizeof(buf));
2874
2875 for (i = 0; i < 16; i++) {
2876 uint32_t yuv = AV_RB32(src + i * 4);
2877 uint32_t rgba = yuv_to_rgba(yuv);
2878
2879 av_strlcatf(buf, sizeof(buf), "%06"PRIx32"%s", rgba, i != 15 ? ", " : "");
2880 }
2881
2882 if (av_strlcat(buf, "\n", sizeof(buf)) >= sizeof(buf))
2883 return 0;
2884
2885 ret = ff_alloc_extradata(st->codecpar, strlen(buf));
2886 if (ret < 0)
2887 return ret;
2888 memcpy(st->codecpar->extradata, buf, st->codecpar->extradata_size);
2889
2890 return 0;
2891 }
2892
2893 41 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
2894 AVStream *st, MOVStreamContext *sc,
2895 int64_t size)
2896 {
2897 int ret;
2898
2899
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 22 times.
41 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
2900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if ((int)size != size)
2901 return AVERROR(ENOMEM);
2902
2903 19 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
2904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
2905 return ret;
2906
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (size > 16) {
2907 19 MOVStreamContext *tmcd_ctx = st->priv_data;
2908 int val;
2909 19 val = AV_RB32(st->codecpar->extradata + 4);
2910 19 tmcd_ctx->tmcd_flags = val;
2911 19 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
2912 19 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
2913 19 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
2914
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (size > 30) {
2915 4 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
2916 4 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
2917
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) {
2918 4 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
2919
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 &&
2920
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 st->codecpar->extradata[30] /* Don't add empty string */) {
2921 4 char *reel_name = av_malloc(str_size + 1);
2922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!reel_name)
2923 return AVERROR(ENOMEM);
2924 4 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
2925 4 reel_name[str_size] = 0; /* Add null terminator */
2926 4 av_dict_set(&st->metadata, "reel_name", reel_name,
2927 AV_DICT_DONT_STRDUP_VAL);
2928 }
2929 }
2930 }
2931 }
2932 } else {
2933 /* other codec type, just skip (rtp, mp4s ...) */
2934 22 avio_skip(pb, size);
2935 }
2936 41 return 0;
2937 }
2938
2939 593 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
2940 AVStream *st, MOVStreamContext *sc)
2941 {
2942 593 FFStream *const sti = ffstream(st);
2943
2944
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 352 times.
593 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
2945
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)
2946 st->codecpar->sample_rate = sc->time_scale;
2947
2948 /* special codec parameters handling */
2949
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 474 times.
593 switch (st->codecpar->codec_id) {
2950 #if CONFIG_DV_DEMUXER
2951 case AV_CODEC_ID_DVAUDIO:
2952 if (c->dv_fctx) {
2953 avpriv_request_sample(c->fc, "multiple DV audio streams");
2954 return AVERROR(ENOSYS);
2955 }
2956
2957 c->dv_fctx = avformat_alloc_context();
2958 if (!c->dv_fctx) {
2959 av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
2960 return AVERROR(ENOMEM);
2961 }
2962 c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
2963 if (!c->dv_demux) {
2964 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
2965 return AVERROR(ENOMEM);
2966 }
2967 sc->dv_audio_container = 1;
2968 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2969 break;
2970 #endif
2971 /* no ifdef since parameters are always those */
2972 case AV_CODEC_ID_QCELP:
2973 av_channel_layout_uninit(&st->codecpar->ch_layout);
2974 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2975 // force sample rate for qcelp when not stored in mov
2976 if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
2977 st->codecpar->sample_rate = 8000;
2978 // FIXME: Why is the following needed for some files?
2979 sc->samples_per_frame = 160;
2980 if (!sc->bytes_per_frame)
2981 sc->bytes_per_frame = 35;
2982 break;
2983 case AV_CODEC_ID_AMR_NB:
2984 av_channel_layout_uninit(&st->codecpar->ch_layout);
2985 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2986 /* force sample rate for amr, stsd in 3gp does not store sample rate */
2987 st->codecpar->sample_rate = 8000;
2988 break;
2989 11 case AV_CODEC_ID_AMR_WB:
2990 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
2991 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2992 11 st->codecpar->sample_rate = 16000;
2993 11 break;
2994 1 case AV_CODEC_ID_MP2:
2995 case AV_CODEC_ID_MP3:
2996 /* force type after stsd for m1a hdlr */
2997 1 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2998 1 break;
2999 15 case AV_CODEC_ID_GSM:
3000 case AV_CODEC_ID_ADPCM_MS:
3001 case AV_CODEC_ID_ADPCM_IMA_WAV:
3002 case AV_CODEC_ID_ILBC:
3003 case AV_CODEC_ID_MACE3:
3004 case AV_CODEC_ID_MACE6:
3005 case AV_CODEC_ID_QDM2:
3006 15 st->codecpar->block_align = sc->bytes_per_frame;
3007 15 break;
3008 16 case AV_CODEC_ID_ALAC:
3009
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
3010 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
3011
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
3012 av_channel_layout_uninit(&st->codecpar->ch_layout);
3013 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3014 st->codecpar->ch_layout.nb_channels = channel_count;
3015 }
3016 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
3017 }
3018 16 break;
3019 10 case AV_CODEC_ID_AC3:
3020 case AV_CODEC_ID_EAC3:
3021 case AV_CODEC_ID_MPEG1VIDEO:
3022 case AV_CODEC_ID_VC1:
3023 case AV_CODEC_ID_VP8:
3024 case AV_CODEC_ID_VP9:
3025 10 sti->need_parsing = AVSTREAM_PARSE_FULL;
3026 10 break;
3027 66 case AV_CODEC_ID_EVC:
3028 case AV_CODEC_ID_AV1:
3029 /* field_order detection of H264 requires parsing */
3030 case AV_CODEC_ID_H264:
3031 66 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3032 66 break;
3033 474 default:
3034 474 break;
3035 }
3036 593 return 0;
3037 }
3038
3039 604 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
3040 int codec_tag, int format,
3041 int64_t size)
3042 {
3043
3/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 593 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
604 if (codec_tag &&
3044 (codec_tag != format &&
3045 // AVID 1:1 samples with differing data format and codec tag exist
3046 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
3047 // prores is allowed to have differing data format and codec tag
3048 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
3049 // so is dv (sigh)
3050 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
3051 (c->fc->video_codec_id ? ff_codec_get_id(ff_codec_movvideo_tags, format) != c->fc->video_codec_id
3052 : codec_tag != MKTAG('j','p','e','g')))) {
3053 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3054 * export it as a separate AVStream but this needs a few changes
3055 * in the MOV demuxer, patch welcome. */
3056
3057 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3058 avio_skip(pb, size);
3059 return 1;
3060 }
3061
3062 604 return 0;
3063 }
3064
3065 593 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3066 {
3067 AVStream *st;
3068 MOVStreamContext *sc;
3069 int pseudo_stream_id;
3070
3071
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 av_assert0 (c->fc->nb_streams >= 1);
3072 593 st = c->fc->streams[c->fc->nb_streams-1];
3073 593 sc = st->priv_data;
3074
3075 593 for (pseudo_stream_id = 0;
3076
3/4
✓ Branch 0 taken 604 times.
✓ Branch 1 taken 593 times.
✓ Branch 2 taken 604 times.
✗ Branch 3 not taken.
1197 pseudo_stream_id < entries && !pb->eof_reached;
3077 604 pseudo_stream_id++) {
3078 //Parsing Sample description table
3079 enum AVCodecID id;
3080 604 int ret, dref_id = 1;
3081 604 MOVAtom a = { AV_RL32("stsd") };
3082 604 int64_t start_pos = avio_tell(pb);
3083 604 int64_t size = avio_rb32(pb); /* size */
3084 604 uint32_t format = avio_rl32(pb); /* data format */
3085
3086
1/2
✓ Branch 0 taken 604 times.
✗ Branch 1 not taken.
604 if (size >= 16) {
3087 604 avio_rb32(pb); /* reserved */
3088 604 avio_rb16(pb); /* reserved */
3089 604 dref_id = avio_rb16(pb);
3090 } else if (size <= 7) {
3091 av_log(c->fc, AV_LOG_ERROR,
3092 "invalid size %"PRId64" in stsd\n", size);
3093 return AVERROR_INVALIDDATA;
3094 }
3095
3096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 604 times.
604 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3097 604 size - (avio_tell(pb) - start_pos))) {
3098 sc->stsd_count++;
3099 continue;
3100 }
3101
3102
2/2
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 11 times.
604 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
3103 604 sc->dref_id= dref_id;
3104 604 sc->format = format;
3105
3106 604 id = mov_codec_id(st, format);
3107
3108 604 av_log(c->fc, AV_LOG_TRACE,
3109 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3110 604 av_fourcc2str(format), st->codecpar->codec_type);
3111
3112 604 st->codecpar->codec_id = id;
3113
2/2
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 293 times.
604 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3114 311 mov_parse_stsd_video(c, pb, st, sc);
3115
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 52 times.
293 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3116 241 mov_parse_stsd_audio(c, pb, st, sc);
3117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (st->codecpar->sample_rate < 0) {
3118 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3119 return AVERROR_INVALIDDATA;
3120 }
3121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (st->codecpar->ch_layout.nb_channels < 0) {
3122 av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3123 return AVERROR_INVALIDDATA;
3124 }
3125
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 41 times.
52 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3126 11 mov_parse_stsd_subtitle(c, pb, st, sc,
3127 11 size - (avio_tell(pb) - start_pos));
3128 } else {
3129 41 ret = mov_parse_stsd_data(c, pb, st, sc,
3130 41 size - (avio_tell(pb) - start_pos));
3131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ret < 0)
3132 return ret;
3133 }
3134 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3135 604 a.size = size - (avio_tell(pb) - start_pos);
3136
2/2
✓ Branch 0 taken 476 times.
✓ Branch 1 taken 128 times.
604 if (a.size > 8) {
3137
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 476 times.
476 if ((ret = mov_read_default(c, pb, a)) < 0)
3138 return ret;
3139
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 127 times.
128 } else if (a.size > 0)
3140 1 avio_skip(pb, a.size);
3141
3142
3/4
✓ Branch 0 taken 604 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 340 times.
✓ Branch 3 taken 264 times.
604 if (sc->extradata && st->codecpar->extradata) {
3143 340 int extra_size = st->codecpar->extradata_size;
3144
3145 /* Move the current stream extradata to the stream context one. */
3146 340 sc->extradata_size[pseudo_stream_id] = extra_size;
3147 340 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3148 340 st->codecpar->extradata = NULL;
3149 340 st->codecpar->extradata_size = 0;
3150 }
3151 604 sc->stsd_count++;
3152 }
3153
3154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (pb->eof_reached) {
3155 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3156 return AVERROR_EOF;
3157 }
3158
3159 593 return 0;
3160 }
3161
3162 593 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3163 {
3164 AVStream *st;
3165 MOVStreamContext *sc;
3166 int ret, entries;
3167
3168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->fc->nb_streams < 1)
3169 return 0;
3170 593 st = c->fc->streams[c->fc->nb_streams - 1];
3171 593 sc = st->priv_data;
3172
3173 593 sc->stsd_version = avio_r8(pb);
3174 593 avio_rb24(pb); /* flags */
3175 593 entries = avio_rb32(pb);
3176
3177 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3178
3/6
✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 593 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 593 times.
593 if (entries <= 0 || entries > atom.size / 8 || entries > 1024) {
3179 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3180 return AVERROR_INVALIDDATA;
3181 }
3182
3183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (sc->extradata) {
3184 av_log(c->fc, AV_LOG_ERROR,
3185 "Duplicate stsd found in this track.\n");
3186 return AVERROR_INVALIDDATA;
3187 }
3188
3189 /* Prepare space for hosting multiple extradata. */
3190 593 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (!sc->extradata)
3192 return AVERROR(ENOMEM);
3193
3194 593 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (!sc->extradata_size) {
3196 ret = AVERROR(ENOMEM);
3197 goto fail;
3198 }
3199
3200 593 ret = ff_mov_read_stsd_entries(c, pb, entries);
3201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (ret < 0)
3202 goto fail;
3203
3204 /* Restore back the primary extradata. */
3205 593 av_freep(&st->codecpar->extradata);
3206 593 st->codecpar->extradata_size = sc->extradata_size[0];
3207
2/2
✓ Branch 0 taken 330 times.
✓ Branch 1 taken 263 times.
593 if (sc->extradata_size[0]) {
3208 330 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 330 times.
330 if (!st->codecpar->extradata)
3210 return AVERROR(ENOMEM);
3211 330 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3212 }
3213
3214 593 return mov_finalize_stsd_codec(c, pb, st, sc);
3215 fail:
3216 if (sc->extradata) {
3217 int j;
3218 for (j = 0; j < sc->stsd_count; j++)
3219 av_freep(&sc->extradata[j]);
3220 }
3221
3222 av_freep(&sc->extradata);
3223 av_freep(&sc->extradata_size);
3224 return ret;
3225 }
3226
3227 593 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3228 {
3229 AVStream *st;
3230 MOVStreamContext *sc;
3231 unsigned int i, entries;
3232
3233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->trak_index < 0) {
3234 av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3235 return 0;
3236 }
3237
3238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->fc->nb_streams < 1)
3239 return 0;
3240 593 st = c->fc->streams[c->fc->nb_streams-1];
3241 593 sc = st->priv_data;
3242
3243 593 avio_r8(pb); /* version */
3244 593 avio_rb24(pb); /* flags */
3245
3246 593 entries = avio_rb32(pb);
3247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if ((uint64_t)entries * 12 + 4 > atom.size)
3248 return AVERROR_INVALIDDATA;
3249
3250 593 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3251
3252
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 578 times.
593 if (!entries)
3253 15 return 0;
3254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (sc->stsc_data) {
3255 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3256 return 0;
3257 }
3258 578 av_free(sc->stsc_data);
3259 578 sc->stsc_count = 0;
3260 578 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3261
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (!sc->stsc_data)
3262 return AVERROR(ENOMEM);
3263
3264
3/4
✓ Branch 0 taken 3778 times.
✓ Branch 1 taken 578 times.
✓ Branch 2 taken 3778 times.
✗ Branch 3 not taken.
4356 for (i = 0; i < entries && !pb->eof_reached; i++) {
3265 3778 sc->stsc_data[i].first = avio_rb32(pb);
3266 3778 sc->stsc_data[i].count = avio_rb32(pb);
3267 3778 sc->stsc_data[i].id = avio_rb32(pb);
3268 }
3269
3270 578 sc->stsc_count = i;
3271
2/2
✓ Branch 0 taken 3778 times.
✓ Branch 1 taken 578 times.
4356 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3272 3778 int64_t first_min = i + 1;
3273
5/6
✓ Branch 0 taken 3200 times.
✓ Branch 1 taken 578 times.
✓ Branch 2 taken 3200 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3200 times.
✓ Branch 5 taken 578 times.
3778 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
3274
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) ||
3275
1/2
✓ Branch 0 taken 3778 times.
✗ Branch 1 not taken.
3778 sc->stsc_data[i].first < first_min ||
3276
1/2
✓ Branch 0 taken 3778 times.
✗ Branch 1 not taken.
3778 sc->stsc_data[i].count < 1 ||
3277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3778 times.
3778 sc->stsc_data[i].id < 1) {
3278 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);
3279 if (i+1 >= sc->stsc_count) {
3280 if (sc->stsc_data[i].count == 0 && i > 0) {
3281 sc->stsc_count --;
3282 continue;
3283 }
3284 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3285 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3286 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3287 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3288 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3289 continue;
3290 }
3291 av_assert0(sc->stsc_data[i+1].first >= 2);
3292 // We replace this entry by the next valid
3293 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3294 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3295 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3296 }
3297 }
3298
3299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (pb->eof_reached) {
3300 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3301 return AVERROR_EOF;
3302 }
3303
3304 578 return 0;
3305 }
3306
3307 340678 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3308 {
3309 340678 return index < count - 1;
3310 }
3311
3312 /* Compute the samples value for the stsc entry at the given index. */
3313 55564 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3314 {
3315 int chunk_count;
3316
3317
2/2
✓ Branch 1 taken 55368 times.
✓ Branch 2 taken 196 times.
55564 if (mov_stsc_index_valid(index, sc->stsc_count))
3318 55368 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3319 else {
3320 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3322 196 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3323 }
3324
3325 55564 return sc->stsc_data[index].count * (int64_t)chunk_count;
3326 }
3327
3328 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3329 {
3330 AVStream *st;
3331 MOVStreamContext *sc;
3332 unsigned i, entries;
3333
3334 if (c->trak_index < 0) {
3335 av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3336 return 0;
3337 }
3338
3339 if (c->fc->nb_streams < 1)
3340 return 0;
3341 st = c->fc->streams[c->fc->nb_streams-1];
3342 sc = st->priv_data;
3343
3344 avio_rb32(pb); // version + flags
3345
3346 entries = avio_rb32(pb);
3347 if (sc->stps_data)
3348 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3349 av_free(sc->stps_data);
3350 sc->stps_count = 0;
3351 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3352 if (!sc->stps_data)
3353 return AVERROR(ENOMEM);
3354
3355 for (i = 0; i < entries && !pb->eof_reached; i++) {
3356 sc->stps_data[i] = avio_rb32(pb);
3357 }
3358
3359 sc->stps_count = i;
3360
3361 if (pb->eof_reached) {
3362 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3363 return AVERROR_EOF;
3364 }
3365
3366 return 0;
3367 }
3368
3369 143 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3370 {
3371 AVStream *st;
3372 FFStream *sti;
3373 MOVStreamContext *sc;
3374 unsigned int i, entries;
3375
3376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (c->trak_index < 0) {
3377 av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3378 return 0;
3379 }
3380
3381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (c->fc->nb_streams < 1)
3382 return 0;
3383 143 st = c->fc->streams[c->fc->nb_streams-1];
3384 143 sti = ffstream(st);
3385 143 sc = st->priv_data;
3386
3387 143 avio_r8(pb); /* version */
3388 143 avio_rb24(pb); /* flags */
3389
3390 143 entries = avio_rb32(pb);
3391
3392 143 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3393
3394
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 137 times.
143 if (!entries) {
3395 6 sc->keyframe_absent = 1;
3396
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)
3397 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3398 6 return 0;
3399 }
3400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
137 if (sc->keyframes)
3401 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
137 if (entries >= UINT_MAX / sizeof(int))
3403 return AVERROR_INVALIDDATA;
3404 137 av_freep(&sc->keyframes);
3405 137 sc->keyframe_count = 0;
3406 137 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
137 if (!sc->keyframes)
3408 return AVERROR(ENOMEM);
3409
3410
3/4
✓ Branch 0 taken 5701 times.
✓ Branch 1 taken 137 times.
✓ Branch 2 taken 5701 times.
✗ Branch 3 not taken.
5838 for (i = 0; i < entries && !pb->eof_reached; i++) {
3411 5701 sc->keyframes[i] = avio_rb32(pb);
3412 }
3413
3414 137 sc->keyframe_count = i;
3415
3416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
137 if (pb->eof_reached) {
3417 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3418 return AVERROR_EOF;
3419 }
3420
3421 137 return 0;
3422 }
3423
3424 593 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3425 {
3426 AVStream *st;
3427 MOVStreamContext *sc;
3428 unsigned int i, entries, sample_size, field_size, num_bytes;
3429 GetBitContext gb;
3430 unsigned char* buf;
3431 int ret;
3432
3433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->trak_index < 0) {
3434 av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3435 return 0;
3436 }
3437
3438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->fc->nb_streams < 1)
3439 return 0;
3440 593 st = c->fc->streams[c->fc->nb_streams-1];
3441 593 sc = st->priv_data;
3442
3443 593 avio_r8(pb); /* version */
3444 593 avio_rb24(pb); /* flags */
3445
3446
1/2
✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
593 if (atom.type == MKTAG('s','t','s','z')) {
3447 593 sample_size = avio_rb32(pb);
3448
2/2
✓ Branch 0 taken 552 times.
✓ Branch 1 taken 41 times.
593 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3449 552 sc->sample_size = sample_size;
3450 593 sc->stsz_sample_size = sample_size;
3451 593 field_size = 32;
3452 } else {
3453 sample_size = 0;
3454 avio_rb24(pb); /* reserved */
3455 field_size = avio_r8(pb);
3456 }
3457 593 entries = avio_rb32(pb);
3458
3459 593 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3460
3461 593 sc->sample_count = entries;
3462
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 395 times.
593 if (sample_size)
3463 198 return 0;
3464
3465
4/8
✓ Branch 0 taken 395 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 395 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 395 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 395 times.
395 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
3466 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3467 return AVERROR_INVALIDDATA;
3468 }
3469
3470
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 379 times.
395 if (!entries)
3471 16 return 0;
3472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 379 times.
379 if (entries >= (INT_MAX - 4 - 8 * AV_INPUT_BUFFER_PADDING_SIZE) / field_size)
3473 return AVERROR_INVALIDDATA;
3474
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 379 times.
379 if (sc->sample_sizes)
3475 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3476 379 av_free(sc->sample_sizes);
3477 379 sc->sample_count = 0;
3478 379 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 379 times.
379 if (!sc->sample_sizes)
3480 return AVERROR(ENOMEM);
3481
3482 379 num_bytes = (entries*field_size+4)>>3;
3483
3484 379 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 379 times.
379 if (!buf) {
3486 av_freep(&sc->sample_sizes);
3487 return AVERROR(ENOMEM);
3488 }
3489
3490 379 ret = ffio_read_size(pb, buf, num_bytes);
3491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 379 times.
379 if (ret < 0) {
3492 av_freep(&sc->sample_sizes);
3493 av_free(buf);
3494 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3495 return 0;
3496 }
3497
3498 379 init_get_bits(&gb, buf, 8*num_bytes);
3499
3500
2/2
✓ Branch 0 taken 226833 times.
✓ Branch 1 taken 379 times.
227212 for (i = 0; i < entries; i++) {
3501 226833 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 226833 times.
226833 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3503 av_free(buf);
3504 av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3505 return AVERROR_INVALIDDATA;
3506 }
3507 226833 sc->data_size += sc->sample_sizes[i];
3508 }
3509
3510 379 sc->sample_count = i;
3511
3512 379 av_free(buf);
3513
3514 379 return 0;
3515 }
3516
3517 593 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3518 {
3519 AVStream *st;
3520 MOVStreamContext *sc;
3521 593 unsigned int i, entries, alloc_size = 0;
3522 593 int64_t duration = 0;
3523 593 int64_t total_sample_count = 0;
3524 593 int64_t current_dts = 0;
3525 593 int64_t corrected_dts = 0;
3526
3527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->trak_index < 0) {
3528 av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3529 return 0;
3530 }
3531
3532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->fc->nb_streams < 1)
3533 return 0;
3534 593 st = c->fc->streams[c->fc->nb_streams-1];
3535 593 sc = st->priv_data;
3536
3537 593 avio_r8(pb); /* version */
3538 593 avio_rb24(pb); /* flags */
3539 593 entries = avio_rb32(pb);
3540
3541 593 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3542 593 c->fc->nb_streams-1, entries);
3543
3544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (sc->stts_data)
3545 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3546 593 av_freep(&sc->stts_data);
3547 593 sc->stts_count = 0;
3548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3549 return AVERROR(ENOMEM);
3550
3551
3/4
✓ Branch 0 taken 2942 times.
✓ Branch 1 taken 593 times.
✓ Branch 2 taken 2942 times.
✗ Branch 3 not taken.
3535 for (i = 0; i < entries && !pb->eof_reached; i++) {
3552 unsigned int sample_duration;
3553 unsigned int sample_count;
3554 2942 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3555 2942 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &alloc_size,
3556 min_entries * sizeof(*sc->stts_data));
3557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2942 times.
2942 if (!stts_data) {
3558 av_freep(&sc->stts_data);
3559 sc->stts_count = 0;
3560 return AVERROR(ENOMEM);
3561 }
3562 2942 sc->stts_count = min_entries;
3563 2942 sc->stts_data = stts_data;
3564
3565 2942 sample_count = avio_rb32(pb);
3566 2942 sample_duration = avio_rb32(pb);
3567
3568 2942 sc->stts_data[i].count= sample_count;
3569 2942 sc->stts_data[i].duration= sample_duration;
3570
3571 2942 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3572 sample_count, sample_duration);
3573
3574 /* STTS sample offsets are uint32 but some files store it as int32
3575 * with negative values used to correct DTS delays.
3576 There may be abnormally large values as well. */
3577
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2941 times.
2942 if (sample_duration > c->max_stts_delta) {
3578 // assume high delta is a correction if negative when cast as int32
3579 1 int32_t delta_magnitude = (int32_t)sample_duration;
3580 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",
3581 sample_duration, i, sample_count, st->index);
3582 1 sc->stts_data[i].duration = 1;
3583
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 corrected_dts += (delta_magnitude < 0 ? (int64_t)delta_magnitude : 1) * sample_count;
3584 } else {
3585 2941 corrected_dts += sample_duration * (uint64_t)sample_count;
3586 }
3587
3588 2942 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3589
3590
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2920 times.
2942 if (current_dts > corrected_dts) {
3591 22 int64_t drift = (current_dts - corrected_dts)/FFMAX(sample_count, 1);
3592
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;
3593 22 current_dts -= correction * (uint64_t)sample_count;
3594 22 sc->stts_data[i].duration -= correction;
3595 }
3596
3597 2942 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3598 2942 total_sample_count+=sc->stts_data[i].count;
3599 }
3600
3601 593 sc->stts_count = i;
3602
3603
2/2
✓ Branch 0 taken 577 times.
✓ Branch 1 taken 16 times.
593 if (duration > 0 &&
3604
1/2
✓ Branch 0 taken 577 times.
✗ Branch 1 not taken.
577 duration <= INT64_MAX - sc->duration_for_fps &&
3605
1/2
✓ Branch 0 taken 577 times.
✗ Branch 1 not taken.
577 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3606 577 sc->duration_for_fps += duration;
3607 577 sc->nb_frames_for_fps += total_sample_count;
3608 }
3609
3610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (pb->eof_reached) {
3611 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3612 return AVERROR_EOF;
3613 }
3614
3615 593 st->nb_frames= total_sample_count;
3616
2/2
✓ Branch 0 taken 577 times.
✓ Branch 1 taken 16 times.
593 if (duration)
3617 577 st->duration= FFMIN(st->duration, duration);
3618
3619 // All samples have zero duration. They have higher chance be chose by
3620 // mov_find_next_sample, which leads to seek again and again.
3621 //
3622 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3623 // So only mark data stream as discarded for safety.
3624
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 577 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
593 if (!duration && sc->stts_count &&
3625 st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3626 av_log(c->fc, AV_LOG_WARNING,
3627 "All samples in data stream index:id [%d:%d] have zero "
3628 "duration, stream set to be discarded by default. Override "
3629 "using AVStream->discard or -discard for ffmpeg command.\n",
3630 st->index, sc->id);
3631 st->discard = AVDISCARD_ALL;
3632 }
3633 593 sc->track_end = duration;
3634 593 return 0;
3635 }
3636
3637 44 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3638 {
3639 AVStream *st;
3640 MOVStreamContext *sc;
3641 int64_t i, entries;
3642
3643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (c->fc->nb_streams < 1)
3644 return 0;
3645 44 st = c->fc->streams[c->fc->nb_streams - 1];
3646 44 sc = st->priv_data;
3647
3648 44 avio_r8(pb); /* version */
3649 44 avio_rb24(pb); /* flags */
3650 44 entries = atom.size - 4;
3651
3652 44 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3653 44 c->fc->nb_streams - 1, entries);
3654
3655
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 36 times.
44 if (sc->sdtp_data)
3656 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3657 44 av_freep(&sc->sdtp_data);
3658 44 sc->sdtp_count = 0;
3659
3660 44 sc->sdtp_data = av_malloc(entries);
3661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (!sc->sdtp_data)
3662 return AVERROR(ENOMEM);
3663
3664
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++)
3665 3807 sc->sdtp_data[i] = avio_r8(pb);
3666 44 sc->sdtp_count = i;
3667
3668 44 return 0;
3669 }
3670
3671 10827 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3672 {
3673
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 9691 times.
10827 if (duration < 0) {
3674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3675 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3676 duration++;
3677 }
3678 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3679 }
3680 10827 }
3681
3682 63 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3683 {
3684 AVStream *st;
3685 MOVStreamContext *sc;
3686 63 unsigned int i, entries, ctts_count = 0;
3687
3688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->trak_index < 0) {
3689 av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
3690 return 0;
3691 }
3692
3693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->fc->nb_streams < 1)
3694 return 0;
3695 63 st = c->fc->streams[c->fc->nb_streams-1];
3696 63 sc = st->priv_data;
3697
3698 63 avio_r8(pb); /* version */
3699 63 avio_rb24(pb); /* flags */
3700 63 entries = avio_rb32(pb);
3701
3702 63 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3703
3704
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 59 times.
63 if (!entries)
3705 4 return 0;
3706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
3707 return AVERROR_INVALIDDATA;
3708 59 av_freep(&sc->ctts_data);
3709 59 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
3710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->ctts_data)
3711 return AVERROR(ENOMEM);
3712
3713
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++) {
3714 4874 int count = avio_rb32(pb);
3715 4874 int duration = avio_rb32(pb);
3716
3717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (count <= 0) {
3718 av_log(c->fc, AV_LOG_TRACE,
3719 "ignoring CTTS entry with count=%d duration=%d\n",
3720 count, duration);
3721 continue;
3722 }
3723
3724 4874 add_ctts_entry(&sc->ctts_data, &ctts_count, &sc->ctts_allocated_size,
3725 count, duration);
3726
3727 4874 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
3728 count, duration);
3729
3730
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4874 if (FFNABS(duration) < -(1<<28) && i+2<entries) {
3731 av_log(c->fc, AV_LOG_WARNING, "CTTS invalid\n");
3732 av_freep(&sc->ctts_data);
3733 sc->ctts_count = 0;
3734 return 0;
3735 }
3736
3737
2/2
✓ Branch 0 taken 4761 times.
✓ Branch 1 taken 113 times.
4874 if (i+2<entries)
3738 4761 mov_update_dts_shift(sc, duration, c->fc);
3739 }
3740
3741 59 sc->ctts_count = ctts_count;
3742
3743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (pb->eof_reached) {
3744 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
3745 return AVERROR_EOF;
3746 }
3747
3748 59 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
3749
3750 59 return 0;
3751 }
3752
3753 28 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3754 {
3755 AVStream *st;
3756 MOVStreamContext *sc;
3757 uint8_t version;
3758 uint32_t grouping_type;
3759 uint32_t default_length;
3760 av_unused uint32_t default_group_description_index;
3761 uint32_t entry_count;
3762
3763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (c->fc->nb_streams < 1)
3764 return 0;
3765 28 st = c->fc->streams[c->fc->nb_streams - 1];
3766 28 sc = st->priv_data;
3767
3768 28 version = avio_r8(pb); /* version */
3769 28 avio_rb24(pb); /* flags */
3770 28 grouping_type = avio_rl32(pb);
3771
3772 /*
3773 * This function only supports "sync" boxes, but the code is able to parse
3774 * other boxes (such as "tscl", "tsas" and "stsa")
3775 */
3776
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 5 times.
28 if (grouping_type != MKTAG('s','y','n','c'))
3777 23 return 0;
3778
3779
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
3780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
3781 5 entry_count = avio_rb32(pb);
3782
3783 5 av_freep(&sc->sgpd_sync);
3784 5 sc->sgpd_sync_count = entry_count;
3785 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
3786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
3787 return AVERROR(ENOMEM);
3788
3789
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++) {
3790 8 uint32_t description_length = default_length;
3791
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)
3792 description_length = avio_rb32(pb);
3793
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
3794 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
3795 8 sc->sgpd_sync[i] = nal_unit_type;
3796 8 description_length -= 1;
3797 }
3798 8 avio_skip(pb, description_length);
3799 }
3800
3801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
3802 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
3803 return AVERROR_EOF;
3804 }
3805
3806 5 return 0;
3807 }
3808
3809 25 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3810 {
3811 AVStream *st;
3812 MOVStreamContext *sc;
3813 unsigned int i, entries;
3814 uint8_t version;
3815 uint32_t grouping_type;
3816 MOVSbgp *table, **tablep;
3817 int *table_count;
3818
3819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (c->fc->nb_streams < 1)
3820 return 0;
3821 25 st = c->fc->streams[c->fc->nb_streams-1];
3822 25 sc = st->priv_data;
3823
3824 25 version = avio_r8(pb); /* version */
3825 25 avio_rb24(pb); /* flags */
3826 25 grouping_type = avio_rl32(pb);
3827
3828
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 24 times.
25 if (grouping_type == MKTAG('r','a','p',' ')) {
3829 1 tablep = &sc->rap_group;
3830 1 table_count = &sc->rap_group_count;
3831
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19 times.
24 } else if (grouping_type == MKTAG('s','y','n','c')) {
3832 5 tablep = &sc->sync_group;
3833 5 table_count = &sc->sync_group_count;
3834 } else {
3835 19 return 0;
3836 }
3837
3838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
3839 avio_rb32(pb); /* grouping_type_parameter */
3840
3841 6 entries = avio_rb32(pb);
3842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
3843 return 0;
3844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
3845 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
3846 6 av_freep(tablep);
3847 6 table = av_malloc_array(entries, sizeof(*table));
3848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
3849 return AVERROR(ENOMEM);
3850 6 *tablep = table;
3851
3852
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++) {
3853 32 table[i].count = avio_rb32(pb); /* sample_count */
3854 32 table[i].index = avio_rb32(pb); /* group_description_index */
3855 }
3856
3857 6 *table_count = i;
3858
3859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
3860 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
3861 return AVERROR_EOF;
3862 }
3863
3864 6 return 0;
3865 }
3866
3867 /**
3868 * Get ith edit list entry (media time, duration).
3869 */
3870 899 static int get_edit_list_entry(MOVContext *mov,
3871 const MOVStreamContext *msc,
3872 unsigned int edit_list_index,
3873 int64_t *edit_list_media_time,
3874 int64_t *edit_list_duration,
3875 int64_t global_timescale)
3876 {
3877
2/2
✓ Branch 0 taken 436 times.
✓ Branch 1 taken 463 times.
899 if (edit_list_index == msc->elst_count) {
3878 436 return 0;
3879 }
3880 463 *edit_list_media_time = msc->elst_data[edit_list_index].time;
3881 463 *edit_list_duration = msc->elst_data[edit_list_index].duration;
3882
3883 /* duration is in global timescale units;convert to msc timescale */
3884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 463 times.
463 if (global_timescale == 0) {
3885 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
3886 return 0;
3887 }
3888 463 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
3889 global_timescale);
3890
3891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 463 times.
463 if (*edit_list_duration + (uint64_t)*edit_list_media_time > INT64_MAX)
3892 *edit_list_duration = 0;
3893
3894 463 return 1;
3895 }
3896
3897 /**
3898 * Find the closest previous frame to the timestamp_pts, in e_old index
3899 * entries. Searching for just any frame / just key frames can be controlled by
3900 * last argument 'flag'.
3901 * Note that if ctts_data is not NULL, we will always search for a key frame
3902 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
3903 * return the first frame of the video.
3904 *
3905 * Here the timestamp_pts is considered to be a presentation timestamp and
3906 * the timestamp of index entries are considered to be decoding timestamps.
3907 *
3908 * Returns 0 if successful in finding a frame, else returns -1.
3909 * Places the found index corresponding output arg.
3910 *
3911 * If ctts_old is not NULL, then refines the searched entry by searching
3912 * backwards from the found timestamp, to find the frame with correct PTS.
3913 *
3914 * Places the found ctts_index and ctts_sample in corresponding output args.
3915 */
3916 462 static int find_prev_closest_index(AVStream *st,
3917 AVIndexEntry *e_old,
3918 int nb_old,
3919 MOVCtts* ctts_data,
3920 int64_t ctts_count,
3921 int64_t timestamp_pts,
3922 int flag,
3923 int64_t* index,
3924 int64_t* ctts_index,
3925 int64_t* ctts_sample)
3926 {
3927 462 MOVStreamContext *msc = st->priv_data;
3928 462 FFStream *const sti = ffstream(st);
3929 462 AVIndexEntry *e_keep = sti->index_entries;
3930 462 int nb_keep = sti->nb_index_entries;
3931 462 int64_t i = 0;
3932 int64_t index_ctts_count;
3933
3934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 462 times.
462 av_assert0(index);
3935
3936 // If dts_shift > 0, then all the index timestamps will have to be offset by
3937 // at least dts_shift amount to obtain PTS.
3938 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
3939
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 453 times.
462 if (msc->dts_shift > 0) {
3940 9 timestamp_pts -= msc->dts_shift;
3941 }
3942
3943 462 sti->index_entries = e_old;
3944 462 sti->nb_index_entries = nb_old;
3945 462 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
3946
3947 // Keep going backwards in the index entries until the timestamp is the same.
3948
2/2
✓ Branch 0 taken 461 times.
✓ Branch 1 taken 1 times.
462 if (*index >= 0) {
3949
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 437 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
461 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
3950 i--) {
3951 if ((flag & AVSEEK_FLAG_ANY) ||
3952 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
3953 *index = i - 1;
3954 }
3955 }
3956 }
3957
3958 // If we have CTTS then refine the search, by searching backwards over PTS
3959 // computed by adding corresponding CTTS durations to index timestamps.
3960
4/4
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 398 times.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 1 times.
462 if (ctts_data && *index >= 0) {
3961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(ctts_index);
3962
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(ctts_sample);
3963 // Find out the ctts_index for the found frame.
3964 63 *ctts_index = 0;
3965 63 *ctts_sample = 0;
3966
2/2
✓ Branch 0 taken 175 times.
✓ Branch 1 taken 63 times.
238 for (index_ctts_count = 0; index_ctts_count < *index; index_ctts_count++) {
3967
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (*ctts_index < ctts_count) {
3968 175 (*ctts_sample)++;
3969
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (ctts_data[*ctts_index].count == *ctts_sample) {
3970 175 (*ctts_index)++;
3971 175 *ctts_sample = 0;
3972 }
3973 }
3974 }
3975
3976
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 && (*ctts_index) >= 0 && (*ctts_index) < ctts_count) {
3977 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
3978 // No need to add dts_shift to the timestamp here becase timestamp_pts has already been
3979 // compensated by dts_shift above.
3980
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 8 times.
70 if ((e_old[*index].timestamp + ctts_data[*ctts_index].duration) <= timestamp_pts &&
3981
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 4 times.
62 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
3982 58 break;
3983 }
3984
3985 12 (*index)--;
3986
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (*ctts_sample == 0) {
3987 12 (*ctts_index)--;
3988
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 if (*ctts_index >= 0)
3989 7 *ctts_sample = ctts_data[*ctts_index].count - 1;
3990 } else {
3991 (*ctts_sample)--;
3992 }
3993 }
3994 }
3995
3996 /* restore AVStream state*/
3997 462 sti->index_entries = e_keep;
3998 462 sti->nb_index_entries = nb_keep;
3999
2/2
✓ Branch 0 taken 456 times.
✓ Branch 1 taken 6 times.
462 return *index >= 0 ? 0 : -1;
4000 }
4001
4002 /**
4003 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
4004 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
4005 *
4006 * This function is similar to ff_add_index_entry in libavformat/utils.c
4007 * except that here we are always unconditionally adding an index entry to
4008 * the end, instead of searching the entries list and skipping the add if
4009 * there is an existing entry with the same timestamp.
4010 * This is needed because the mov_fix_index calls this func with the same
4011 * unincremented timestamp for successive discarded frames.
4012 */
4013 348497 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
4014 int size, int distance, int flags)
4015 {
4016 348497 FFStream *const sti = ffstream(st);
4017 AVIndexEntry *entries, *ie;
4018 348497 int64_t index = -1;
4019 348497 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
4020
4021 // Double the allocation each time, to lower memory fragmentation.
4022 // Another difference from ff_add_index_entry function.
4023 348497 const size_t requested_size =
4024 348497 min_size_needed > sti->index_entries_allocated_size ?
4025
2/2
✓ Branch 0 taken 1968 times.
✓ Branch 1 taken 346529 times.
348497 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
4026 min_size_needed;
4027
4028
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348497 times.
348497 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
4029 return -1;
4030
4031 348497 entries = av_fast_realloc(sti->index_entries,
4032 &sti->index_entries_allocated_size,
4033 requested_size);
4034
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348497 times.
348497 if (!entries)
4035 return -1;
4036
4037 348497 sti->index_entries = entries;
4038
4039 348497 index = sti->nb_index_entries++;
4040 348497 ie= &entries[index];
4041
4042 348497 ie->pos = pos;
4043 348497 ie->timestamp = timestamp;
4044 348497 ie->min_distance= distance;
4045 348497 ie->size= size;
4046 348497 ie->flags = flags;
4047 348497 return index;
4048 }
4049
4050 /**
4051 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4052 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4053 */
4054 27 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4055 int64_t* frame_duration_buffer,
4056 int frame_duration_buffer_size) {
4057 27 FFStream *const sti = ffstream(st);
4058 27 int i = 0;
4059
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);
4060
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 27 times.
164 for (i = 0; i < frame_duration_buffer_size; i++) {
4061 137 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4062 137 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4063 }
4064 27 }
4065
4066 /**
4067 * Append a new ctts entry to ctts_data.
4068 * Returns the new ctts_count if successful, else returns -1.
4069 */
4070 282744 static int64_t add_ctts_entry(MOVCtts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size,
4071 int count, int duration)
4072 {
4073 MOVCtts *ctts_buf_new;
4074 282744 const size_t min_size_needed = (*ctts_count + 1) * sizeof(MOVCtts);
4075 282744 const size_t requested_size =
4076 282744 min_size_needed > *allocated_size ?
4077
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 282530 times.
282744 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4078 min_size_needed;
4079
4080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 282744 times.
282744 if ((unsigned)(*ctts_count) >= UINT_MAX / sizeof(MOVCtts) - 1)
4081 return -1;
4082
4083 282744 ctts_buf_new = av_fast_realloc(*ctts_data, allocated_size, requested_size);
4084
4085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 282744 times.
282744 if (!ctts_buf_new)
4086 return -1;
4087
4088 282744 *ctts_data = ctts_buf_new;
4089
4090 282744 ctts_buf_new[*ctts_count].count = count;
4091 282744 ctts_buf_new[*ctts_count].duration = duration;
4092
4093 282744 *ctts_count = (*ctts_count) + 1;
4094 282744 return *ctts_count;
4095 }
4096
4097 #define MAX_REORDER_DELAY 16
4098 600 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4099 {
4100 600 MOVStreamContext *msc = st->priv_data;
4101 600 FFStream *const sti = ffstream(st);
4102 600 int ctts_ind = 0;
4103 600 int ctts_sample = 0;
4104 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4105 600 int buf_start = 0;
4106 int j, r, num_swaps;
4107
4108
2/2
✓ Branch 0 taken 10200 times.
✓ Branch 1 taken 600 times.
10800 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4109 10200 pts_buf[j] = INT64_MIN;
4110
4111
3/4
✓ Branch 0 taken 600 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 541 times.
600 if (st->codecpar->video_delay <= 0 && msc->ctts_data &&
4112
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 16 times.
59 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4113 43 st->codecpar->video_delay = 0;
4114
3/4
✓ Branch 0 taken 138279 times.
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 138279 times.
✗ Branch 3 not taken.
138322 for (int ind = 0; ind < sti->nb_index_entries && ctts_ind < msc->ctts_count; ++ind) {
4115 // Point j to the last elem of the buffer and insert the current pts there.
4116 138279 j = buf_start;
4117 138279 buf_start = (buf_start + 1);
4118
2/2
✓ Branch 0 taken 8111 times.
✓ Branch 1 taken 130168 times.
138279 if (buf_start == MAX_REORDER_DELAY + 1)
4119 8111 buf_start = 0;
4120
4121 138279 pts_buf[j] = sti->index_entries[ind].timestamp + msc->ctts_data[ctts_ind].duration;
4122
4123 // The timestamps that are already in the sorted buffer, and are greater than the
4124 // current pts, are exactly the timestamps that need to be buffered to output PTS
4125 // in correct sorted order.
4126 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4127 // can be computed as the maximum no. of swaps any particular timestamp needs to
4128 // go through, to keep this buffer in sorted order.
4129 138279 num_swaps = 0;
4130
2/2
✓ Branch 0 taken 142294 times.
✓ Branch 1 taken 4 times.
142298 while (j != buf_start) {
4131 142294 r = j - 1;
4132
2/2
✓ Branch 0 taken 8389 times.
✓ Branch 1 taken 133905 times.
142294 if (r < 0) r = MAX_REORDER_DELAY;
4133
2/2
✓ Branch 0 taken 4019 times.
✓ Branch 1 taken 138275 times.
142294 if (pts_buf[j] < pts_buf[r]) {
4134 4019 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4135 4019 ++num_swaps;
4136 } else {
4137 138275 break;
4138 }
4139 4019 j = r;
4140 }
4141 138279 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4142
4143 138279 ctts_sample++;
4144
1/2
✓ Branch 0 taken 138279 times.
✗ Branch 1 not taken.
138279 if (ctts_sample == msc->ctts_data[ctts_ind].count) {
4145 138279 ctts_ind++;
4146 138279 ctts_sample = 0;
4147 }
4148 }
4149 43 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4150 43 st->codecpar->video_delay, st->index);
4151 }
4152 600 }
4153
4154 103383 static void mov_current_sample_inc(MOVStreamContext *sc)
4155 {
4156 103383 sc->current_sample++;
4157 103383 sc->current_index++;
4158
2/2
✓ Branch 0 taken 61384 times.
✓ Branch 1 taken 41999 times.
103383 if (sc->index_ranges &&
4159
2/2
✓ Branch 0 taken 420 times.
✓ Branch 1 taken 60964 times.
61384 sc->current_index >= sc->current_index_range->end &&
4160
1/2
✓ Branch 0 taken 420 times.
✗ Branch 1 not taken.
420 sc->current_index_range->end) {
4161 420 sc->current_index_range++;
4162 420 sc->current_index = sc->current_index_range->start;
4163 }
4164 103383 }
4165
4166 static void mov_current_sample_dec(MOVStreamContext *sc)
4167 {
4168 sc->current_sample--;
4169 sc->current_index--;
4170 if (sc->index_ranges &&
4171 sc->current_index < sc->current_index_range->start &&
4172 sc->current_index_range > sc->index_ranges) {
4173 sc->current_index_range--;
4174 sc->current_index = sc->current_index_range->end - 1;
4175 }
4176 }
4177
4178 335 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4179 {
4180 int64_t range_size;
4181
4182 335 sc->current_sample = current_sample;
4183 335 sc->current_index = current_sample;
4184
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 309 times.
335 if (!sc->index_ranges) {
4185 26 return;
4186 }
4187
4188 309 for (sc->current_index_range = sc->index_ranges;
4189
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 sc->current_index_range->end;
4190 sc->current_index_range++) {
4191 309 range_size = sc->current_index_range->end - sc->current_index_range->start;
4192
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 if (range_size > current_sample) {
4193 309 sc->current_index = sc->current_index_range->start + current_sample;
4194 309 break;
4195 }
4196 current_sample -= range_size;
4197 }
4198 }
4199
4200 /**
4201 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4202 * which are needed to decode them) that fall in the edit list time ranges.
4203 * Also fixes the timestamps of the index entries to match the timeline
4204 * specified the edit lists.
4205 */
4206 600 static void mov_fix_index(MOVContext *mov, AVStream *st)
4207 {
4208 600 MOVStreamContext *msc = st->priv_data;
4209 600 FFStream *const sti = ffstream(st);
4210 600 AVIndexEntry *e_old = sti->index_entries;
4211 600 int nb_old = sti->nb_index_entries;
4212 600 const AVIndexEntry *e_old_end = e_old + nb_old;
4213 600 const AVIndexEntry *current = NULL;
4214 600 MOVCtts *ctts_data_old = msc->ctts_data;
4215 600 int64_t ctts_index_old = 0;
4216 600 int64_t ctts_sample_old = 0;
4217 600 int64_t ctts_count_old = msc->ctts_count;
4218 600 int64_t edit_list_media_time = 0;
4219 600 int64_t edit_list_duration = 0;
4220 600 int64_t frame_duration = 0;
4221 600 int64_t edit_list_dts_counter = 0;
4222 600 int64_t edit_list_dts_entry_end = 0;
4223 600 int64_t edit_list_start_ctts_sample = 0;
4224 int64_t curr_cts;
4225 600 int64_t curr_ctts = 0;
4226 600 int64_t empty_edits_sum_duration = 0;
4227 600 int64_t edit_list_index = 0;
4228 int64_t index;
4229 int flags;
4230 600 int64_t start_dts = 0;
4231 600 int64_t edit_list_start_encountered = 0;
4232 600 int64_t search_timestamp = 0;
4233 600 int64_t* frame_duration_buffer = NULL;
4234 600 int num_discarded_begin = 0;
4235 600 int first_non_zero_audio_edit = -1;
4236 600 int packet_skip_samples = 0;
4237 600 MOVIndexRange *current_index_range = NULL;
4238 600 int found_keyframe_after_edit = 0;
4239 600 int found_non_empty_edit = 0;
4240
4241
4/6
✓ Branch 0 taken 436 times.
✓ Branch 1 taken 164 times.
✓ Branch 2 taken 436 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 436 times.
600 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
4242 164 return;
4243 }
4244
4245 // allocate the index ranges array
4246 436 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4247 sizeof(msc->index_ranges[0]));
4248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 436 times.
436 if (!msc->index_ranges) {
4249 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4250 return;
4251 }
4252 436 msc->current_index_range = msc->index_ranges;
4253
4254 // Clean AVStream from traces of old index
4255 436 sti->index_entries = NULL;
4256 436 sti->index_entries_allocated_size = 0;
4257 436 sti->nb_index_entries = 0;
4258
4259 // Clean ctts fields of MOVStreamContext
4260 436 msc->ctts_data = NULL;
4261 436 msc->ctts_count = 0;
4262 436 msc->ctts_index = 0;
4263 436 msc->ctts_sample = 0;
4264 436 msc->ctts_allocated_size = 0;
4265
4266 // Reinitialize min_corrected_pts so that it can be computed again.
4267 436 msc->min_corrected_pts = -1;
4268
4269 // If the dts_shift is positive (in case of negative ctts values in mov),
4270 // then negate the DTS by dts_shift
4271
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 427 times.
436 if (msc->dts_shift > 0) {
4272 9 edit_list_dts_entry_end -= msc->dts_shift;
4273 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4274 }
4275
4276 436 start_dts = edit_list_dts_entry_end;
4277
4278
2/2
✓ Branch 0 taken 463 times.
✓ Branch 1 taken 436 times.
1335 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
4279 899 &edit_list_duration, mov->time_scale)) {
4280 463 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4281 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4282 463 edit_list_index++;
4283 463 edit_list_dts_counter = edit_list_dts_entry_end;
4284 463 edit_list_dts_entry_end += edit_list_duration;
4285 463 num_discarded_begin = 0;
4286
4/4
✓ Branch 0 taken 440 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 436 times.
463 if (!found_non_empty_edit && edit_list_media_time == -1) {
4287 4 empty_edits_sum_duration += edit_list_duration;
4288 4 continue;
4289 }
4290 459 found_non_empty_edit = 1;
4291
4292 // If we encounter a non-negative edit list reset the skip_samples/start_pad fields and set them
4293 // according to the edit list below.
4294
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 332 times.
459 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4295
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit < 0) {
4296 127 first_non_zero_audio_edit = 1;
4297 } else {
4298 first_non_zero_audio_edit = 0;
4299 }
4300
4301
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit > 0)
4302 127 sti->skip_samples = msc->start_pad = 0;
4303 }
4304
4305 // While reordering frame index according to edit list we must handle properly
4306 // the scenario when edit list entry starts from none key frame.
4307 // We find closest previous key frame and preserve it and consequent frames in index.
4308 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4309 459 search_timestamp = edit_list_media_time;
4310
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 332 times.
459 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4311 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4312 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4313 // edit_list_media_time to cover the decoder delay.
4314 127 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
4315 }
4316
4317
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 456 times.
459 if (find_prev_closest_index(st, e_old, nb_old, ctts_data_old, ctts_count_old, search_timestamp, 0,
4318 &index, &ctts_index_old, &ctts_sample_old) < 0) {
4319 3 av_log(mov->fc, AV_LOG_WARNING,
4320 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4321 st->index, edit_list_index, search_timestamp);
4322
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 if (find_prev_closest_index(st, e_old, nb_old, ctts_data_old, ctts_count_old, search_timestamp, AVSEEK_FLAG_ANY,
4323 &index, &ctts_index_old, &ctts_sample_old) < 0) {
4324 3 av_log(mov->fc, AV_LOG_WARNING,
4325 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4326 st->index, edit_list_index, search_timestamp);
4327 3 index = 0;
4328 3 ctts_index_old = 0;
4329 3 ctts_sample_old = 0;
4330 }
4331 }
4332 459 current = e_old + index;
4333 459 edit_list_start_ctts_sample = ctts_sample_old;
4334
4335 // Iterate over index and arrange it according to edit list
4336 459 edit_list_start_encountered = 0;
4337 459 found_keyframe_after_edit = 0;
4338
2/2
✓ Branch 0 taken 348497 times.
✓ Branch 1 taken 111 times.
348608 for (; current < e_old_end; current++, index++) {
4339 // check if frame outside edit list mark it for discard
4340 696994 frame_duration = (current + 1 < e_old_end) ?
4341
2/2
✓ Branch 0 taken 348065 times.
✓ Branch 1 taken 432 times.
348497 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4342
4343 348497 flags = current->flags;
4344
4345 // frames (pts) before or after edit list
4346 348497 curr_cts = current->timestamp + msc->dts_shift;
4347 348497 curr_ctts = 0;
4348
4349
3/4
✓ Branch 0 taken 138853 times.
✓ Branch 1 taken 209644 times.
✓ Branch 2 taken 138853 times.
✗ Branch 3 not taken.
348497 if (ctts_data_old && ctts_index_old < ctts_count_old) {
4350 138853 curr_ctts = ctts_data_old[ctts_index_old].duration;
4351 138853 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", ctts_index: %"PRId64", ctts_count: %"PRId64"\n",
4352 curr_cts, curr_ctts, ctts_index_old, ctts_count_old);
4353 138853 curr_cts += curr_ctts;
4354 138853 ctts_sample_old++;
4355
1/2
✓ Branch 0 taken 138853 times.
✗ Branch 1 not taken.
138853 if (ctts_sample_old == ctts_data_old[ctts_index_old].count) {
4356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138853 times.
138853 if (add_ctts_entry(&msc->ctts_data, &msc->ctts_count,
4357 &msc->ctts_allocated_size,
4358 138853 ctts_data_old[ctts_index_old].count - edit_list_start_ctts_sample,
4359 138853 ctts_data_old[ctts_index_old].duration) == -1) {
4360 av_log(mov->fc, AV_LOG_ERROR, "Cannot add CTTS entry %"PRId64" - {%"PRId64", %d}\n",
4361 ctts_index_old,
4362 ctts_data_old[ctts_index_old].count - edit_list_start_ctts_sample,
4363 ctts_data_old[ctts_index_old].duration);
4364 break;
4365 }
4366 138853 ctts_index_old++;
4367 138853 ctts_sample_old = 0;
4368 138853 edit_list_start_ctts_sample = 0;
4369 }
4370 }
4371
4372
4/4
✓ Branch 0 taken 348345 times.
✓ Branch 1 taken 152 times.
✓ Branch 2 taken 130 times.
✓ Branch 3 taken 348215 times.
348497 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
4373
4/4
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 205 times.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 46 times.
282 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
4374
4/6
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
31 curr_cts < edit_list_media_time && curr_cts + frame_duration > edit_list_media_time &&
4375 first_non_zero_audio_edit > 0) {
4376 11 packet_skip_samples = edit_list_media_time - curr_cts;
4377 11 sti->skip_samples += packet_skip_samples;
4378
4379 // Shift the index entry timestamp by packet_skip_samples to be correct.
4380 11 edit_list_dts_counter -= packet_skip_samples;
4381
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (edit_list_start_encountered == 0) {
4382 11 edit_list_start_encountered = 1;
4383 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4384 // discarded packets.
4385
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 if (frame_duration_buffer) {
4386 6 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4387 frame_duration_buffer, num_discarded_begin);
4388 6 av_freep(&frame_duration_buffer);
4389 }
4390 }
4391
4392 11 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4393 } else {
4394 271 flags |= AVINDEX_DISCARD_FRAME;
4395 271 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4396
4397
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 132 times.
271 if (edit_list_start_encountered == 0) {
4398 139 num_discarded_begin++;
4399 139 frame_duration_buffer = av_realloc(frame_duration_buffer,
4400 num_discarded_begin * sizeof(int64_t));
4401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if (!frame_duration_buffer) {
4402 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4403 break;
4404 }
4405 139 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4406
4407 // Increment skip_samples for the first non-zero audio edit list
4408
3/4
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 73 times.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
139 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4409
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 46 times.
66 first_non_zero_audio_edit > 0 && st->codecpar->codec_id != AV_CODEC_ID_VORBIS) {
4410 20 sti->skip_samples += frame_duration;
4411 }
4412 }
4413 }
4414 } else {
4415
2/2
✓ Branch 0 taken 435 times.
✓ Branch 1 taken 347780 times.
348215 if (msc->min_corrected_pts < 0) {
4416 435 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4417 } else {
4418 347780 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4419 }
4420
2/2
✓ Branch 0 taken 446 times.
✓ Branch 1 taken 347769 times.
348215 if (edit_list_start_encountered == 0) {
4421 446 edit_list_start_encountered = 1;
4422 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4423 // discarded packets.
4424
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 425 times.
446 if (frame_duration_buffer) {
4425 21 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4426 frame_duration_buffer, num_discarded_begin);
4427 21 av_freep(&frame_duration_buffer);
4428 }
4429 }
4430 }
4431
4432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348497 times.
348497 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
4433 348497 current->min_distance, flags) == -1) {
4434 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4435 break;
4436 }
4437
4438 // Update the index ranges array
4439
4/4
✓ Branch 0 taken 348061 times.
✓ Branch 1 taken 436 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 348040 times.
348497 if (!current_index_range || index != current_index_range->end) {
4440 457 current_index_range = current_index_range ? current_index_range + 1
4441
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 436 times.
457 : msc->index_ranges;
4442 457 current_index_range->start = index;
4443 }
4444 348497 current_index_range->end = index + 1;
4445
4446 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4447
2/2
✓ Branch 0 taken 348358 times.
✓ Branch 1 taken 139 times.
348497 if (edit_list_start_encountered > 0) {
4448 348358 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4449 }
4450
4451 // Break when found first key frame after edit entry completion
4452
2/2
✓ Branch 0 taken 615 times.
✓ Branch 1 taken 347882 times.
348497 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
4453
3/4
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 255 times.
615 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
4454
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 339 times.
360 if (ctts_data_old) {
4455 // If we have CTTS and this is the first keyframe after edit elist,
4456 // wait for one more, because there might be trailing B-frames after this I-frame
4457 // that do belong to the edit.
4458
3/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 9 times.
21 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO && found_keyframe_after_edit == 0) {
4459 12 found_keyframe_after_edit = 1;
4460 12 continue;
4461 }
4462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ctts_sample_old != 0) {
4463 if (add_ctts_entry(&msc->ctts_data, &msc->ctts_count,
4464 &msc->ctts_allocated_size,
4465 ctts_sample_old - edit_list_start_ctts_sample,
4466 ctts_data_old[ctts_index_old].duration) == -1) {
4467 av_log(mov->fc, AV_LOG_ERROR, "Cannot add CTTS entry %"PRId64" - {%"PRId64", %d}\n",
4468 ctts_index_old, ctts_sample_old - edit_list_start_ctts_sample,
4469 ctts_data_old[ctts_index_old].duration);
4470 break;
4471 }
4472 }
4473 }
4474 348 break;
4475 }
4476 }
4477 }
4478 // If there are empty edits, then msc->min_corrected_pts might be positive
4479 // intentionally. So we subtract the sum duration of emtpy edits here.
4480 436 msc->min_corrected_pts -= empty_edits_sum_duration;
4481
4482 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4483 // dts by that amount to make the first pts zero.
4484
2/2
✓ Branch 0 taken 267 times.
✓ Branch 1 taken 169 times.
436 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4485
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 226 times.
267 if (msc->min_corrected_pts > 0) {
4486 41 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4487
2/2
✓ Branch 0 taken 2829 times.
✓ Branch 1 taken 41 times.
2870 for (int i = 0; i < sti->nb_index_entries; ++i)
4488 2829 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4489 }
4490 }
4491 // Start time should be equal to zero or the duration of any empty edits.
4492 436 st->start_time = empty_edits_sum_duration;
4493
4494 // Update av stream length, if it ends up shorter than the track's media duration
4495 436 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4496 436 msc->start_pad = sti->skip_samples;
4497
4498 // Free the old index and the old CTTS structures
4499 436 av_free(e_old);
4500 436 av_free(ctts_data_old);
4501 436 av_freep(&frame_duration_buffer);
4502
4503 // Null terminate the index ranges array
4504 436 current_index_range = current_index_range ? current_index_range + 1
4505
1/2
✓ Branch 0 taken 436 times.
✗ Branch 1 not taken.
436 : msc->index_ranges;
4506 436 current_index_range->start = 0;
4507 436 current_index_range->end = 0;
4508 436 msc->current_index = msc->index_ranges[0].start;
4509 }
4510
4511 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4512 {
4513
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4514
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == HEVC_NAL_CRA_NUT)
4515 5 return i + 1;
4516 return 0;
4517 }
4518
4519 616 static int build_open_gop_key_points(AVStream *st)
4520 {
4521 int k;
4522 616 int sample_id = 0;
4523 uint32_t cra_index;
4524 616 MOVStreamContext *sc = st->priv_data;
4525
4526
4/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 580 times.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 5 times.
616 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count)
4527 611 return 0;
4528
4529 /* Build an unrolled index of the samples */
4530 5 sc->sample_offsets_count = 0;
4531
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4533 return AVERROR(ENOMEM);
4534 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4535 }
4536 5 av_freep(&sc->sample_offsets);
4537 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4539 return AVERROR(ENOMEM);
4540 5 k = 0;
4541
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4542
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4543 322 sc->sample_offsets[k++] = sc->ctts_data[i].duration;
4544
4545 /* The following HEVC NAL type reveal the use of open GOP sync points
4546 * (TODO: BLA types may also be concerned) */
4547 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4549 return 0;
4550
4551 /* Build a list of open-GOP key samples */
4552 5 sc->open_key_samples_count = 0;
4553
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4554
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (sc->sync_group[i].count > INT_MAX - sc->open_key_samples_count)
4556 return AVERROR(ENOMEM);
4557 11 sc->open_key_samples_count += sc->sync_group[i].count;
4558 }
4559 5 av_freep(&sc->open_key_samples);
4560 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4562 return AVERROR(ENOMEM);
4563 5 k = 0;
4564
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4565 28 const MOVSbgp *sg = &sc->sync_group[i];
4566
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4567
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4568 11 sc->open_key_samples[k++] = sample_id;
4569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4570 return AVERROR_PATCHWELCOME;
4571 28 sample_id += sg->count;
4572 }
4573
4574 /* Identify the minimal time step between samples */
4575 5 sc->min_sample_duration = UINT_MAX;
4576
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4577 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4578
4579 5 return 0;
4580 }
4581
4582 616 static void mov_build_index(MOVContext *mov, AVStream *st)
4583 {
4584 616 MOVStreamContext *sc = st->priv_data;
4585 616 FFStream *const sti = ffstream(st);
4586 int64_t current_offset;
4587 616 int64_t current_dts = 0;
4588 616 unsigned int stts_index = 0;
4589 616 unsigned int stsc_index = 0;
4590 616 unsigned int stss_index = 0;
4591 616 unsigned int stps_index = 0;
4592 unsigned int i, j;
4593 616 uint64_t stream_size = 0;
4594 616 MOVCtts *ctts_data_old = sc->ctts_data;
4595 616 unsigned int ctts_count_old = sc->ctts_count;
4596
4597 616 int ret = build_open_gop_key_points(st);
4598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 616 times.
616 if (ret < 0)
4599 return;
4600
4601
2/2
✓ Branch 0 taken 438 times.
✓ Branch 1 taken 178 times.
616 if (sc->elst_count) {
4602 438 int i, edit_start_index = 0, multiple_edits = 0;
4603 438 int64_t empty_duration = 0; // empty duration of the first edit list entry
4604 438 int64_t start_time = 0; // start time of the media
4605
4606
2/2
✓ Branch 0 taken 465 times.
✓ Branch 1 taken 438 times.
903 for (i = 0; i < sc->elst_count; i++) {
4607 465 const MOVElst *e = &sc->elst_data[i];
4608
4/4
✓ Branch 0 taken 438 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 434 times.
465 if (i == 0 && e->time == -1) {
4609 /* if empty, the first entry is the start time of the stream
4610 * relative to the presentation itself */
4611 4 empty_duration = e->duration;
4612 4 edit_start_index = 1;
4613
3/4
✓ Branch 0 taken 438 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 438 times.
✗ Branch 3 not taken.
461 } else if (i == edit_start_index && e->time >= 0) {
4614 438 start_time = e->time;
4615 } else {
4616 23 multiple_edits = 1;
4617 }
4618 }
4619
4620
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 432 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
438 if (multiple_edits && !mov->advanced_editlist) {
4621 if (mov->advanced_editlist_autodisabled)
4622 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4623 "not supported in fragmented MP4 files\n");
4624 else
4625 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4626 "Use -advanced_editlist to correctly decode otherwise "
4627 "a/v desync might occur\n");
4628 }
4629
4630 /* adjust first dts according to edit list */
4631
5/6
✓ Branch 0 taken 434 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 365 times.
✓ Branch 4 taken 73 times.
✗ Branch 5 not taken.
438 if ((empty_duration || start_time) && mov->time_scale > 0) {
4632
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 69 times.
73 if (empty_duration)
4633 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
4634
4635
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)
4636 av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
4637
4638 73 sc->time_offset = start_time - (uint64_t)empty_duration;
4639 73 sc->min_corrected_pts = start_time;
4640
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 72 times.
73 if (!mov->advanced_editlist)
4641 1 current_dts = -sc->time_offset;
4642 }
4643
4644
4/4
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 430 times.
438 if (!multiple_edits && !mov->advanced_editlist &&
4645
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)
4646 sc->start_pad = start_time;
4647 }
4648
4649 /* only use old uncompressed audio chunk demuxing when stts specifies it */
4650
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 375 times.
616 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4651
4/4
✓ Branch 0 taken 186 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 120 times.
✓ Branch 3 taken 66 times.
775 sc->stts_count == 1 && sc->stts_data[0].duration == 1)) {
4652 550 unsigned int current_sample = 0;
4653 550 unsigned int stts_sample = 0;
4654 unsigned int sample_size;
4655 550 unsigned int distance = 0;
4656 550 unsigned int rap_group_index = 0;
4657 550 unsigned int rap_group_sample = 0;
4658
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 549 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
550 int rap_group_present = sc->rap_group_count && sc->rap_group;
4659
4/8
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 413 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 137 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 413 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
550 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
4660
4661 550 current_dts -= sc->dts_shift;
4662
4663
3/4
✓ Branch 0 taken 534 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 534 times.
550 if (!sc->sample_count || sti->nb_index_entries)
4664 16 return;
4665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 534 times.
534 if (sc->sample_count >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4666 return;
4667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 534 times.
534 if (av_reallocp_array(&sti->index_entries,
4668 534 sti->nb_index_entries + sc->sample_count,
4669 sizeof(*sti->index_entries)) < 0) {
4670 sti->nb_index_entries = 0;
4671 return;
4672 }
4673 534 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
4674
4675
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 475 times.
534 if (ctts_data_old) {
4676 // Expand ctts entries such that we have a 1-1 mapping with samples
4677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (sc->sample_count >= UINT_MAX / sizeof(*sc->ctts_data))
4678 return;
4679 59 sc->ctts_count = 0;
4680 59 sc->ctts_allocated_size = 0;
4681 118 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size,
4682 59 sc->sample_count * sizeof(*sc->ctts_data));
4683
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->ctts_data) {
4684 av_free(ctts_data_old);
4685 return;
4686 }
4687
4688 59 memset((uint8_t*)(sc->ctts_data), 0, sc->ctts_allocated_size);
4689
4690
2/2
✓ Branch 0 taken 4874 times.
✓ Branch 1 taken 59 times.
4933 for (i = 0; i < ctts_count_old &&
4691
1/2
✓ Branch 0 taken 4874 times.
✗ Branch 1 not taken.
9748 sc->ctts_count < sc->sample_count; i++)
4692
2/2
✓ Branch 0 taken 139017 times.
✓ Branch 1 taken 4874 times.
143891 for (j = 0; j < ctts_data_old[i].count &&
4693
1/2
✓ Branch 0 taken 139017 times.
✗ Branch 1 not taken.
278034 sc->ctts_count < sc->sample_count; j++)
4694 139017 add_ctts_entry(&sc->ctts_data, &sc->ctts_count,
4695 &sc->ctts_allocated_size, 1,
4696 139017 ctts_data_old[i].duration);
4697 59 av_free(ctts_data_old);
4698 }
4699
4700
2/2
✓ Branch 0 taken 173837 times.
✓ Branch 1 taken 534 times.
174371 for (i = 0; i < sc->chunk_count; i++) {
4701
2/2
✓ Branch 0 taken 173303 times.
✓ Branch 1 taken 534 times.
173837 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
4702 173837 current_offset = sc->chunk_offsets[i];
4703
2/2
✓ Branch 1 taken 8859 times.
✓ Branch 2 taken 167521 times.
176380 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4704
2/2
✓ Branch 0 taken 2543 times.
✓ Branch 1 taken 6316 times.
8859 i + 1 == sc->stsc_data[stsc_index + 1].first)
4705 2543 stsc_index++;
4706
4707
4/6
✓ Branch 0 taken 173837 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7346 times.
✓ Branch 3 taken 166491 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7346 times.
173837 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
4708 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
4709 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
4710 sc->stsz_sample_size = sc->sample_size;
4711 }
4712
3/4
✓ Branch 0 taken 7346 times.
✓ Branch 1 taken 166491 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7346 times.
173837 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
4713 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
4714 sc->stsz_sample_size = sc->sample_size;
4715 }
4716
4717
2/2
✓ Branch 0 taken 235842 times.
✓ Branch 1 taken 173837 times.
409679 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
4718 235842 int keyframe = 0;
4719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235842 times.
235842 if (current_sample >= sc->sample_count) {
4720 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
4721 return;
4722 }
4723
4724
6/6
✓ Branch 0 taken 231086 times.
✓ Branch 1 taken 4756 times.
✓ Branch 2 taken 152594 times.
✓ Branch 3 taken 78492 times.
✓ Branch 4 taken 5701 times.
✓ Branch 5 taken 146893 times.
235842 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
4725 84193 keyframe = 1;
4726
2/2
✓ Branch 0 taken 5564 times.
✓ Branch 1 taken 78629 times.
84193 if (stss_index + 1 < sc->keyframe_count)
4727 5564 stss_index++;
4728
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 151649 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
151649 } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
4729 keyframe = 1;
4730 if (stps_index + 1 < sc->stps_count)
4731 stps_index++;
4732 }
4733
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 235654 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
235842 if (rap_group_present && rap_group_index < sc->rap_group_count) {
4734
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
4735 2 keyframe = 1;
4736
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
4737 4 rap_group_sample = 0;
4738 4 rap_group_index++;
4739 }
4740 }
4741
2/2
✓ Branch 0 taken 4756 times.
✓ Branch 1 taken 231086 times.
235842 if (sc->keyframe_absent
4742
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !sc->stps_count
4743
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !rap_group_present
4744
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)))
4745 3884 keyframe = 1;
4746
2/2
✓ Branch 0 taken 88077 times.
✓ Branch 1 taken 147765 times.
235842 if (keyframe)
4747 88077 distance = 0;
4748
2/2
✓ Branch 0 taken 8986 times.
✓ Branch 1 taken 226856 times.
235842 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
4749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235842 times.
235842 if (current_offset > INT64_MAX - sample_size) {
4750 av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
4751 current_offset,
4752 sample_size);
4753 return;
4754 }
4755
4756
2/2
✓ Branch 0 taken 235761 times.
✓ Branch 1 taken 81 times.
235842 if (sc->pseudo_stream_id == -1 ||
4757
1/2
✓ Branch 0 taken 235761 times.
✗ Branch 1 not taken.
235761 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
4758 AVIndexEntry *e;
4759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235842 times.
235842 if (sample_size > 0x3FFFFFFF) {
4760 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
4761 return;
4762 }
4763 235842 e = &sti->index_entries[sti->nb_index_entries++];
4764 235842 e->pos = current_offset;
4765 235842 e->timestamp = current_dts;
4766 235842 e->size = sample_size;
4767 235842 e->min_distance = distance;
4768 235842 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
4769 235842 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
4770 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
4771 current_offset, current_dts, sample_size, distance, keyframe);
4772
4/4
✓ Branch 0 taken 154942 times.
✓ Branch 1 taken 80900 times.
✓ Branch 2 taken 10309 times.
✓ Branch 3 taken 144633 times.
235842 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries < 100)
4773 10309 ff_rfps_add_frame(mov->fc, st, current_dts);
4774 }
4775
4776 235842 current_offset += sample_size;
4777 235842 stream_size += sample_size;
4778
4779 235842 current_dts += sc->stts_data[stts_index].duration;
4780
4781 235842 distance++;
4782 235842 stts_sample++;
4783 235842 current_sample++;
4784
4/4
✓ Branch 0 taken 23440 times.
✓ Branch 1 taken 212402 times.
✓ Branch 2 taken 2365 times.
✓ Branch 3 taken 21075 times.
235842 if (stts_index + 1 < sc->stts_count && stts_sample == sc->stts_data[stts_index].count) {
4785 2365 stts_sample = 0;
4786 2365 stts_index++;
4787 }
4788 }
4789 }
4790
2/2
✓ Branch 0 taken 511 times.
✓ Branch 1 taken 23 times.
534 if (st->duration > 0)
4791 511 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
4792 } else {
4793 66 unsigned chunk_samples, total = 0;
4794
4795
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (!sc->chunk_count)
4796 return;
4797
4798 // compute total chunk count
4799
2/2
✓ Branch 0 taken 723 times.
✓ Branch 1 taken 66 times.
789 for (i = 0; i < sc->stsc_count; i++) {
4800 unsigned count, chunk_count;
4801
4802 723 chunk_samples = sc->stsc_data[i].count;
4803
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 66 times.
723 if (i != sc->stsc_count - 1 &&
4804
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) {
4805 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
4806 return;
4807 }
4808
4809
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 648 times.
723 if (sc->samples_per_frame >= 160) { // gsm
4810 75 count = chunk_samples / sc->samples_per_frame;
4811
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 117 times.
648 } else if (sc->samples_per_frame > 1) {
4812 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
4813 531 count = (chunk_samples+samples-1) / samples;
4814 } else {
4815 117 count = (chunk_samples+1023) / 1024;
4816 }
4817
4818
2/2
✓ Branch 1 taken 657 times.
✓ Branch 2 taken 66 times.
723 if (mov_stsc_index_valid(i, sc->stsc_count))
4819 657 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
4820 else
4821 66 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
4822 723 total += chunk_count * count;
4823 }
4824
4825 66 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
4826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4827 return;
4828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (av_reallocp_array(&sti->index_entries,
4829 66 sti->nb_index_entries + total,
4830 sizeof(*sti->index_entries)) < 0) {
4831 sti->nb_index_entries = 0;
4832 return;
4833 }
4834 66 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
4835
4836 // populate index
4837
2/2
✓ Branch 0 taken 5428 times.
✓ Branch 1 taken 66 times.
5494 for (i = 0; i < sc->chunk_count; i++) {
4838 5428 current_offset = sc->chunk_offsets[i];
4839
2/2
✓ Branch 1 taken 5287 times.
✓ Branch 2 taken 141 times.
5428 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4840
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 4630 times.
5287 i + 1 == sc->stsc_data[stsc_index + 1].first)
4841 657 stsc_index++;
4842 5428 chunk_samples = sc->stsc_data[stsc_index].count;
4843
4844
2/2
✓ Branch 0 taken 162532 times.
✓ Branch 1 taken 5428 times.
167960 while (chunk_samples > 0) {
4845 AVIndexEntry *e;
4846 unsigned size, samples;
4847
4848
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) {
4849 avpriv_request_sample(mov->fc,
4850 "Zero bytes per frame, but %d samples per frame",
4851 sc->samples_per_frame);
4852 return;
4853 }
4854
4855
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 148174 times.
162532 if (sc->samples_per_frame >= 160) { // gsm
4856 14358 samples = sc->samples_per_frame;
4857 14358 size = sc->bytes_per_frame;
4858 } else {
4859
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 138611 times.
148174 if (sc->samples_per_frame > 1) {
4860 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
4861 sc->samples_per_frame, chunk_samples);
4862 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
4863 } else {
4864 138611 samples = FFMIN(1024, chunk_samples);
4865 138611 size = samples * sc->sample_size;
4866 }
4867 }
4868
4869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (sti->nb_index_entries >= total) {
4870 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
4871 return;
4872 }
4873
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (size > 0x3FFFFFFF) {
4874 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
4875 return;
4876 }
4877 162532 e = &sti->index_entries[sti->nb_index_entries++];
4878 162532 e->pos = current_offset;
4879 162532 e->timestamp = current_dts;
4880 162532 e->size = size;
4881 162532 e->min_distance = 0;
4882 162532 e->flags = AVINDEX_KEYFRAME;
4883 162532 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
4884 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
4885 size, samples);
4886
4887 162532 current_offset += size;
4888 162532 current_dts += samples;
4889 162532 chunk_samples -= samples;
4890 }
4891 }
4892 }
4893
4894
2/4
✓ Branch 0 taken 600 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 600 times.
✗ Branch 3 not taken.
600 if (!mov->ignore_editlist && mov->advanced_editlist) {
4895 // Fix index according to edit lists.
4896 600 mov_fix_index(mov, st);
4897 }
4898
4899 // Update start time of the stream.
4900
5/6
✓ Branch 0 taken 164 times.
✓ Branch 1 taken 436 times.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 117 times.
✓ Branch 4 taken 47 times.
✗ Branch 5 not taken.
600 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) {
4901 47 st->start_time = sti->index_entries[0].timestamp + sc->dts_shift;
4902
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 44 times.
47 if (sc->ctts_data) {
4903 3 st->start_time += sc->ctts_data[0].duration;
4904 }
4905 }
4906
4907 600 mov_estimate_video_delay(mov, st);
4908 }
4909
4910 static int test_same_origin(const char *src, const char *ref) {
4911 char src_proto[64];
4912 char ref_proto[64];
4913 char src_auth[256];
4914 char ref_auth[256];
4915 char src_host[256];
4916 char ref_host[256];
4917 int src_port=-1;
4918 int ref_port=-1;
4919
4920 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
4921 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
4922
4923 if (strlen(src) == 0) {
4924 return -1;
4925 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
4926 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
4927 strlen(src_host) + 1 >= sizeof(src_host) ||
4928 strlen(ref_host) + 1 >= sizeof(ref_host)) {
4929 return 0;
4930 } else if (strcmp(src_proto, ref_proto) ||
4931 strcmp(src_auth, ref_auth) ||
4932 strcmp(src_host, ref_host) ||
4933 src_port != ref_port) {
4934 return 0;
4935 } else
4936 return 1;
4937 }
4938
4939 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
4940 {
4941 /* try relative path, we do not try the absolute because it can leak information about our
4942 system to an attacker */
4943 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
4944 char filename[1025];
4945 const char *src_path;
4946 int i, l;
4947
4948 /* find a source dir */
4949 src_path = strrchr(src, '/');
4950 if (src_path)
4951 src_path++;
4952 else
4953 src_path = src;
4954
4955 /* find a next level down to target */
4956 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
4957 if (ref->path[l] == '/') {
4958 if (i == ref->nlvl_to - 1)
4959 break;
4960 else
4961 i++;
4962 }
4963
4964 /* compose filename if next level down to target was found */
4965 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
4966 memcpy(filename, src, src_path - src);
4967 filename[src_path - src] = 0;
4968
4969 for (i = 1; i < ref->nlvl_from; i++)
4970 av_strlcat(filename, "../", sizeof(filename));
4971
4972 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
4973 if (!c->use_absolute_path) {
4974 int same_origin = test_same_origin(src, filename);
4975
4976 if (!same_origin) {
4977 av_log(c->fc, AV_LOG_ERROR,
4978 "Reference with mismatching origin, %s not tried for security reasons, "
4979 "set demuxer option use_absolute_path to allow it anyway\n",
4980 ref->path);
4981 return AVERROR(ENOENT);
4982 }
4983
4984 if (strstr(ref->path + l + 1, "..") ||
4985 strstr(ref->path + l + 1, ":") ||
4986 (ref->nlvl_from > 1 && same_origin < 0) ||
4987 (filename[0] == '/' && src_path == src))
4988 return AVERROR(ENOENT);
4989 }
4990
4991 if (strlen(filename) + 1 == sizeof(filename))
4992 return AVERROR(ENOENT);
4993 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
4994 return 0;
4995 }
4996 } else if (c->use_absolute_path) {
4997 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
4998 "this is a possible security issue\n");
4999 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5000 return 0;
5001 } else {
5002 av_log(c->fc, AV_LOG_ERROR,
5003 "Absolute path %s not tried for security reasons, "
5004 "set demuxer option use_absolute_path to allow absolute paths\n",
5005 ref->path);
5006 }
5007
5008 return AVERROR(ENOENT);
5009 }
5010
5011 1263 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5012 {
5013
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1249 times.
1263 if (sc->time_scale <= 0) {
5014 14 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5015 14 sc->time_scale = c->time_scale;
5016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (sc->time_scale <= 0)
5017 sc->time_scale = 1;
5018 }
5019 1263 }
5020
5021 #if CONFIG_IAMFDEC
5022 10 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5023 {
5024 10 const MOVStreamContext *sc = st->priv_data;
5025 10 const IAMFContext *iamf = &sc->iamf->iamf;
5026
5027
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5028 10 const AVStreamGroup *stg = NULL;
5029
5030
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5031
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)
5032 10 stg = c->fc->stream_groups[j];
5033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 av_assert0(stg);
5034
5035
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int j = 0; j < stg->nb_streams; j++) {
5036 50 const FFStream *sti = cffstream(st);
5037 50 AVStream *out = stg->streams[j];
5038 50 FFStream *out_sti = ffstream(stg->streams[j]);
5039
5040 50 out->codecpar->bit_rate = 0;
5041
5042
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 40 times.
50 if (out == st)
5043 10 continue;
5044
5045 40 out->time_base = st->time_base;
5046 40 out->start_time = st->start_time;
5047 40 out->duration = st->duration;
5048 40 out->nb_frames = st->nb_frames;
5049 40 out->discard = st->discard;
5050
5051
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 av_assert0(!out_sti->index_entries);
5052 40 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (!out_sti->index_entries)
5054 return AVERROR(ENOMEM);
5055
5056 40 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5057 40 out_sti->nb_index_entries = sti->nb_index_entries;
5058 40 out_sti->skip_samples = sti->skip_samples;
5059 40 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5060 }
5061 }
5062
5063 10 return 0;
5064 }
5065 #endif
5066
5067 593 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5068 {
5069 AVStream *st;
5070 MOVStreamContext *sc;
5071 int ret;
5072
5073 593 st = avformat_new_stream(c->fc, NULL);
5074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (!st) return AVERROR(ENOMEM);
5075 593 st->id = -1;
5076 593 sc = av_mallocz(sizeof(MOVStreamContext));
5077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (!sc) return AVERROR(ENOMEM);
5078
5079 593 st->priv_data = sc;
5080 593 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5081 593 sc->ffindex = st->index;
5082 593 c->trak_index = st->index;
5083 593 sc->tref_flags = 0;
5084 593 sc->tref_id = -1;
5085 593 sc->refcount = 1;
5086
5087
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 593 times.
593 if ((ret = mov_read_default(c, pb, atom)) < 0)
5088 return ret;
5089
5090 593 c->trak_index = -1;
5091
5092 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5093 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5094
5/6
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 577 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 15 times.
593 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
5095 1 sc->stsc_count = 0;
5096 1 av_freep(&sc->stsc_data);
5097 }
5098
5099 /* sanity checks */
5100
4/6
✓ Branch 0 taken 577 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 577 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 577 times.
✗ Branch 5 not taken.
593 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5101
3/4
✓ Branch 0 taken 379 times.
✓ Branch 1 taken 198 times.
✓ Branch 2 taken 379 times.
✗ Branch 3 not taken.
577 (!sc->sample_size && !sc->sample_count))) ||
5102
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 577 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
593 (!sc->chunk_count && sc->sample_count)) {
5103 av_log(c->fc, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5104 st->index);
5105 return 0;
5106 }
5107
3/4
✓ Branch 0 taken 577 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 577 times.
593 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
5108 av_log(c->fc, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5109 st->index);
5110 return AVERROR_INVALIDDATA;
5111 }
5112
5113 593 fix_timescale(c, sc);
5114
5115 593 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5116
5117 /*
5118 * Advanced edit list support does not work with fragemented MP4s, which
5119 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5120 * In these files, trun atoms may be streamed in.
5121 */
5122
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 577 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 4 times.
593 if (!sc->stts_count && c->advanced_editlist) {
5123
5124 12 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5125 "MP4. disabling.\n");
5126 12 c->advanced_editlist = 0;
5127 12 c->advanced_editlist_autodisabled = 1;
5128 }
5129
5130 593 mov_build_index(c, st);
5131
5132 #if CONFIG_IAMFDEC
5133
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 583 times.
593 if (sc->iamf) {
5134 10 ret = mov_update_iamf_streams(c, st);
5135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
5136 return ret;
5137 }
5138 #endif
5139
5140
3/4
✓ Branch 0 taken 592 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 592 times.
593 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
5141 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5142 if (c->enable_drefs) {
5143 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5144 av_log(c->fc, AV_LOG_ERROR,
5145 "stream %d, error opening alias: path='%s', dir='%s', "
5146 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5147 st->index, dref->path, dref->dir, dref->filename,
5148 dref->volume, dref->nlvl_from, dref->nlvl_to);
5149 } else {
5150 av_log(c->fc, AV_LOG_WARNING,
5151 "Skipped opening external track: "
5152 "stream %d, alias: path='%s', dir='%s', "
5153 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5154 "Set enable_drefs to allow this.\n",
5155 st->index, dref->path, dref->dir, dref->filename,
5156 dref->volume, dref->nlvl_from, dref->nlvl_to);
5157 }
5158 } else {
5159 593 sc->pb = c->fc->pb;
5160 593 sc->pb_is_copied = 1;
5161 }
5162
5163
2/2
✓ Branch 0 taken 301 times.
✓ Branch 1 taken 292 times.
593 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5164
3/4
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 244 times.
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
301 if (sc->h_spacing && sc->v_spacing)
5165 57 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5166 57 sc->h_spacing, sc->v_spacing, INT_MAX);
5167
4/6
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 241 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 241 times.
✗ Branch 5 not taken.
301 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
5168
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 &&
5169
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)) {
5170 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5171 (int64_t)st->codecpar->height * sc->width,
5172 (int64_t)st->codecpar->width * sc->height, INT_MAX);
5173 }
5174
5175 #if FF_API_R_FRAME_RATE
5176
6/6
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 266 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 23 times.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 1 times.
301 if (sc->stts_count == 1 || (sc->stts_count == 2 && sc->stts_data[1].count == 1))
5177 277 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5178 277 sc->time_scale, sc->stts_data[0].duration, INT_MAX);
5179 #endif
5180 }
5181
5182 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
5183
3/4
✓ Branch 0 taken 263 times.
✓ Branch 1 taken 330 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 263 times.
593 if (!st->codecpar->extradata_size && st->codecpar->codec_id == AV_CODEC_ID_H264 &&
5184 TAG_IS_AVCI(st->codecpar->codec_tag)) {
5185 ret = ff_generate_avci_extradata(st);
5186 if (ret < 0)
5187 return ret;
5188 }
5189
5190
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 569 times.
593 switch (st->codecpar->codec_id) {
5191 #if CONFIG_H261_DECODER
5192 24 case AV_CODEC_ID_H261:
5193 #endif
5194 #if CONFIG_H263_DECODER
5195 case AV_CODEC_ID_H263:
5196 #endif
5197 #if CONFIG_MPEG4_DECODER
5198 case AV_CODEC_ID_MPEG4:
5199 #endif
5200 24 st->codecpar->width = 0; /* let decoder init width/height */
5201 24 st->codecpar->height= 0;
5202 24 break;
5203 }
5204
5205 // If the duration of the mp3 packets is not constant, then they could need a parser
5206
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 592 times.
593 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 && sc->stts_count > 3
5208 && sc->stts_count*10 > st->nb_frames
5209 && sc->time_scale == st->codecpar->sample_rate) {
5210 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5211 }
5212 /* Do not need those anymore. */
5213 593 av_freep(&sc->chunk_offsets);
5214 593 av_freep(&sc->sample_sizes);
5215 593 av_freep(&sc->keyframes);
5216 593 av_freep(&sc->stts_data);
5217 593 av_freep(&sc->stps_data);
5218 593 av_freep(&sc->elst_data);
5219 593 av_freep(&sc->rap_group);
5220 593 av_freep(&sc->sync_group);
5221 593 av_freep(&sc->sgpd_sync);
5222
5223 593 return 0;
5224 }
5225
5226 124 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5227 {
5228 int ret;
5229 124 c->itunes_metadata = 1;
5230 124 ret = mov_read_default(c, pb, atom);
5231 124 c->itunes_metadata = 0;
5232 124 return ret;
5233 }
5234
5235 11 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5236 {
5237 uint32_t count;
5238 uint32_t i;
5239
5240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
5241 return 0;
5242
5243 11 avio_skip(pb, 4);
5244 11 count = avio_rb32(pb);
5245 11 atom.size -= 8;
5246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (count >= UINT_MAX / sizeof(*c->meta_keys)) {
5247 av_log(c->fc, AV_LOG_ERROR,
5248 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5249 return AVERROR_INVALIDDATA;
5250 }
5251
5252 11 c->meta_keys_count = count + 1;
5253 11 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
5254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!c->meta_keys)
5255 return AVERROR(ENOMEM);
5256
5257
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i <= count; ++i) {
5258 58 uint32_t key_size = avio_rb32(pb);
5259 58 uint32_t type = avio_rl32(pb);
5260
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) {
5261 av_log(c->fc, AV_LOG_ERROR,
5262 "The key# %"PRIu32" in meta has invalid size:"
5263 "%"PRIu32"\n", i, key_size);
5264 return AVERROR_INVALIDDATA;
5265 }
5266 58 atom.size -= key_size;
5267 58 key_size -= 8;
5268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (type != MKTAG('m','d','t','a')) {
5269 avio_skip(pb, key_size);
5270 continue;
5271 }
5272 58 c->meta_keys[i] = av_mallocz(key_size + 1);
5273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!c->meta_keys[i])
5274 return AVERROR(ENOMEM);
5275 58 avio_read(pb, c->meta_keys[i], key_size);
5276 }
5277
5278 11 return 0;
5279 }
5280
5281 65 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5282 {
5283 65 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5284 65 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5285 int i;
5286 65 int ret = 0;
5287 AVStream *st;
5288 MOVStreamContext *sc;
5289
5290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (c->fc->nb_streams < 1)
5291 return 0;
5292 65 st = c->fc->streams[c->fc->nb_streams-1];
5293 65 sc = st->priv_data;
5294
5295
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 65 times.
260 for (i = 0; i < 3; i++) {
5296 uint8_t **p;
5297 uint32_t len, tag;
5298
5299
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 195 times.
195 if (end - avio_tell(pb) <= 12)
5300 break;
5301
5302 195 len = avio_rb32(pb);
5303 195 tag = avio_rl32(pb);
5304 195 avio_skip(pb, 4); // flags
5305
5306
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))
5307 break;
5308 195 len -= 12;
5309
5310
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 130 times.
195 if (tag == MKTAG('m', 'e', 'a', 'n'))
5311 65 p = &mean;
5312
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 65 times.
130 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5313 65 p = &key;
5314
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) {
5315 65 avio_skip(pb, 4);
5316 65 len -= 4;
5317 65 p = &val;
5318 } else
5319 break;
5320
5321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (*p)
5322 break;
5323
5324 195 *p = av_malloc(len + 1);
5325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*p) {
5326 ret = AVERROR(ENOMEM);
5327 break;
5328 }
5329 195 ret = ffio_read_size(pb, *p, len);
5330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (ret < 0) {
5331 av_freep(p);
5332 break;
5333 }
5334 195 (*p)[len] = 0;
5335 }
5336
5337
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) {
5338
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 32 times.
65 if (strcmp(key, "iTunSMPB") == 0) {
5339 int priming, remainder, samples;
5340
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
5341
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)
5342 33 sc->start_pad = priming;
5343 }
5344 }
5345
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 10 times.
120 if (strcmp(key, "cdec") != 0) {
5346 55 av_dict_set(&c->fc->metadata, key, val,
5347 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5348 55 key = val = NULL;
5349 }
5350 } else {
5351 av_log(c->fc, AV_LOG_VERBOSE,
5352 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5353 }
5354
5355 65 avio_seek(pb, end, SEEK_SET);
5356 65 av_freep(&key);
5357 65 av_freep(&val);
5358 65 av_freep(&mean);
5359 65 return ret;
5360 }
5361
5362 23 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5363 {
5364 MOVStreamContext *sc;
5365 AVStream *st;
5366
5367 23 st = avformat_new_stream(c->fc, NULL);
5368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!st)
5369 return AVERROR(ENOMEM);
5370 23 sc = av_mallocz(sizeof(MOVStreamContext));
5371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc)
5372 return AVERROR(ENOMEM);
5373
5374 23 item->st = st;
5375 23 st->id = item->item_id;
5376 23 st->priv_data = sc;
5377 23 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5378 23 st->codecpar->codec_id = mov_codec_id(st, item->type);
5379 23 sc->id = st->id;
5380 23 sc->ffindex = st->index;
5381 23 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5382 23 st->time_base.num = st->time_base.den = 1;
5383 23 st->nb_frames = 1;
5384 23 sc->time_scale = 1;
5385 23 sc->pb = c->fc->pb;
5386 23 sc->pb_is_copied = 1;
5387 23 sc->refcount = 1;
5388
5389
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 if (item->name)
5390 23 av_dict_set(&st->metadata, "title", item->name, 0);
5391
5392 // Populate the necessary fields used by mov_build_index.
5393 23 sc->stsc_count = 1;
5394 23 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc->stsc_data)
5396 return AVERROR(ENOMEM);
5397 23 sc->stsc_data[0].first = 1;
5398 23 sc->stsc_data[0].count = 1;
5399 23 sc->stsc_data[0].id = 1;
5400 23 sc->chunk_count = 1;
5401 23 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc->chunk_offsets)
5403 return AVERROR(ENOMEM);
5404 23 sc->sample_count = 1;
5405 23 sc->sample_sizes = av_malloc_array(1, sizeof(*sc->sample_sizes));
5406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc->sample_sizes)
5407 return AVERROR(ENOMEM);
5408 23 sc->stts_count = 1;
5409 23 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc->stts_data)
5411 return AVERROR(ENOMEM);
5412 23 sc->stts_data[0].count = 1;
5413 // Not used for still images. But needed by mov_build_index.
5414 23 sc->stts_data[0].duration = 0;
5415
5416 23 return 0;
5417 }
5418
5419 138 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5420 {
5421
1/2
✓ Branch 0 taken 400 times.
✗ Branch 1 not taken.
400 while (atom.size > 8) {
5422 uint32_t tag;
5423
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 400 times.
400 if (avio_feof(pb))
5424 return AVERROR_EOF;
5425 400 tag = avio_rl32(pb);
5426 400 atom.size -= 4;
5427
2/2
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 262 times.
400 if (tag == MKTAG('h','d','l','r')) {
5428 138 avio_seek(pb, -8, SEEK_CUR);
5429 138 atom.size += 8;
5430 138 return mov_read_default(c, pb, atom);
5431 }
5432 }
5433 return 0;
5434 }
5435
5436 // return 1 when matrix is identity, 0 otherwise
5437 #define IS_MATRIX_IDENT(matrix) \
5438 ( (matrix)[0][0] == (1 << 16) && \
5439 (matrix)[1][1] == (1 << 16) && \
5440 (matrix)[2][2] == (1 << 30) && \
5441 !(matrix)[0][1] && !(matrix)[0][2] && \
5442 !(matrix)[1][0] && !(matrix)[1][2] && \
5443 !(matrix)[2][0] && !(matrix)[2][1])
5444
5445 593 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5446 {
5447 int i, j, e;
5448 int width;
5449 int height;
5450 int display_matrix[3][3];
5451 593 int res_display_matrix[3][3] = { { 0 } };
5452 AVStream *st;
5453 MOVStreamContext *sc;
5454 int version;
5455 int flags;
5456
5457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->fc->nb_streams < 1)
5458 return 0;
5459 593 st = c->fc->streams[c->fc->nb_streams-1];
5460 593 sc = st->priv_data;
5461
5462 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5463 // avoids corrupting AVStreams mapped to an earlier tkhd.
5464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (st->id != -1)
5465 return AVERROR_INVALIDDATA;
5466
5467 593 version = avio_r8(pb);
5468 593 flags = avio_rb24(pb);
5469 593 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5470
5471
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 584 times.
593 if (version == 1) {
5472 9 avio_rb64(pb);
5473 9 avio_rb64(pb);
5474 } else {
5475 584 avio_rb32(pb); /* creation time */
5476 584 avio_rb32(pb); /* modification time */
5477 }
5478 593 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5479 593 sc->id = st->id;
5480 593 avio_rb32(pb); /* reserved */
5481
5482 /* highlevel (considering edits) duration in movie timebase */
5483
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 584 times.
593 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5484 593 avio_rb32(pb); /* reserved */
5485 593 avio_rb32(pb); /* reserved */
5486
5487 593 avio_rb16(pb); /* layer */
5488 593 avio_rb16(pb); /* alternate group */
5489 593 avio_rb16(pb); /* volume */
5490 593 avio_rb16(pb); /* reserved */
5491
5492 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
5493 // they're kept in fixed point format through all calculations
5494 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
5495 // side data, but the scale factor is not needed to calculate aspect ratio
5496
2/2
✓ Branch 0 taken 1779 times.
✓ Branch 1 taken 593 times.
2372 for (i = 0; i < 3; i++) {
5497 1779 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
5498 1779 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
5499 1779 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
5500 }
5501
5502 593 width = avio_rb32(pb); // 16.16 fixed point track width
5503 593 height = avio_rb32(pb); // 16.16 fixed point track height
5504 593 sc->width = width >> 16;
5505 593 sc->height = height >> 16;
5506
5507 // apply the moov display matrix (after the tkhd one)
5508
2/2
✓ Branch 0 taken 1779 times.
✓ Branch 1 taken 593 times.
2372 for (i = 0; i < 3; i++) {
5509 1779 const int sh[3] = { 16, 16, 30 };
5510
2/2
✓ Branch 0 taken 5337 times.
✓ Branch 1 taken 1779 times.
7116 for (j = 0; j < 3; j++) {
5511
2/2
✓ Branch 0 taken 16011 times.
✓ Branch 1 taken 5337 times.
21348 for (e = 0; e < 3; e++) {
5512 16011 res_display_matrix[i][j] +=
5513 16011 ((int64_t) display_matrix[i][e] *
5514 16011 c->movie_display_matrix[e][j]) >> sh[e];
5515 }
5516 }
5517 }
5518
5519 // save the matrix when it is not the default identity
5520
10/18
✓ Branch 0 taken 584 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 584 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 584 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 584 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 584 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 584 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 584 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 584 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 584 times.
593 if (!IS_MATRIX_IDENT(res_display_matrix)) {
5521 9 av_freep(&sc->display_matrix);
5522 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
5523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
5524 return AVERROR(ENOMEM);
5525
5526
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
5527
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
5528 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
5529 }
5530
5531 // transform the display width/height according to the matrix
5532 // to keep the same scale, use [width height 1<<16]
5533
5/6
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 282 times.
✓ Branch 2 taken 311 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 303 times.
593 if (width && height && sc->display_matrix) {
5534 double disp_transform[2];
5535
5536
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
5537 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
5538 16 sc->display_matrix[3 + i]);
5539
5540
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 &&
5541
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) &&
5542
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
5543 3 st->sample_aspect_ratio = av_d2q(
5544 3 disp_transform[0] / disp_transform[1],
5545 INT_MAX);
5546 }
5547 593 return 0;
5548 }
5549
5550 388 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5551 {
5552 388 MOVFragment *frag = &c->fragment;
5553 388 MOVTrackExt *trex = NULL;
5554 int flags, track_id, i;
5555 MOVFragmentStreamInfo * frag_stream_info;
5556
5557 388 avio_r8(pb); /* version */
5558 388 flags = avio_rb24(pb);
5559
5560 388 track_id = avio_rb32(pb);
5561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!track_id)
5562 return AVERROR_INVALIDDATA;
5563
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < c->trex_count; i++)
5564
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (c->trex_data[i].track_id == track_id) {
5565 388 trex = &c->trex_data[i];
5566 388 break;
5567 }
5568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!trex) {
5569 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
5570 return 0;
5571 }
5572 388 c->fragment.found_tfhd = 1;
5573 388 frag->track_id = track_id;
5574 388 set_frag_stream(&c->frag_index, track_id);
5575
5576 776 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
5577
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
776 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
5578
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 21 times.
388 frag->moof_offset : frag->implicit_offset;
5579
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;
5580
5581 776 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
5582
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 383 times.
388 avio_rb32(pb) : trex->duration;
5583 776 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
5584
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 382 times.
388 avio_rb32(pb) : trex->size;
5585 776 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
5586
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 365 times.
388 avio_rb32(pb) : trex->flags;
5587 388 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
5588
5589 388 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5590
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5591 388 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
5592 388 frag_stream_info->stsd_id = frag->stsd_id;
5593 }
5594 388 return 0;
5595 }
5596
5597 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5598 {
5599 unsigned i, num;
5600 void *new_tracks;
5601
5602 2 num = atom.size / 4;
5603
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
5604 return AVERROR(ENOMEM);
5605
5606 2 av_free(c->chapter_tracks);
5607 2 c->chapter_tracks = new_tracks;
5608 2 c->nb_chapter_tracks = num;
5609
5610
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++)
5611 2 c->chapter_tracks[i] = avio_rb32(pb);
5612
5613 2 c->nb_chapter_tracks = i;
5614
5615 2 return 0;
5616 }
5617
5618 17 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5619 {
5620 MOVTrackExt *trex;
5621 int err;
5622
5623
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))
5624 return AVERROR_INVALIDDATA;
5625
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
5626 sizeof(*c->trex_data))) < 0) {
5627 c->trex_count = 0;
5628 return err;
5629 }
5630
5631 17 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
5632
5633 17 trex = &c->trex_data[c->trex_count++];
5634 17 avio_r8(pb); /* version */
5635 17 avio_rb24(pb); /* flags */
5636 17 trex->track_id = avio_rb32(pb);
5637 17 trex->stsd_id = avio_rb32(pb);
5638 17 trex->duration = avio_rb32(pb);
5639 17 trex->size = avio_rb32(pb);
5640 17 trex->flags = avio_rb32(pb);
5641 17 return 0;
5642 }
5643
5644 367 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5645 {
5646 367 MOVFragment *frag = &c->fragment;
5647 367 AVStream *st = NULL;
5648 MOVStreamContext *sc;
5649 int version, i;
5650 MOVFragmentStreamInfo * frag_stream_info;
5651 int64_t base_media_decode_time;
5652
5653
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 for (i = 0; i < c->fc->nb_streams; i++) {
5654 367 sc = c->fc->streams[i]->priv_data;
5655
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 if (sc->id == frag->track_id) {
5656 367 st = c->fc->streams[i];
5657 367 break;
5658 }
5659 }
5660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367 times.
367 if (!st) {
5661 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5662 return 0;
5663 }
5664 367 sc = st->priv_data;
5665
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)
5666 return 0;
5667 367 version = avio_r8(pb);
5668 367 avio_rb24(pb); /* flags */
5669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367 times.
367 if (version) {
5670 base_media_decode_time = avio_rb64(pb);
5671 } else {
5672 367 base_media_decode_time = avio_rb32(pb);
5673 }
5674
5675 367 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5676
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 if (frag_stream_info)
5677 367 frag_stream_info->tfdt_dts = base_media_decode_time;
5678 367 sc->track_end = base_media_decode_time;
5679
5680 367 return 0;
5681 }
5682
5683 388 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5684 {
5685 388 MOVFragment *frag = &c->fragment;
5686 388 AVStream *st = NULL;
5687 388 FFStream *sti = NULL;
5688 MOVStreamContext *sc;
5689 MOVCtts *ctts_data;
5690 uint64_t offset;
5691 388 int64_t dts, pts = AV_NOPTS_VALUE;
5692 388 int data_offset = 0;
5693 388 unsigned entries, first_sample_flags = frag->flags;
5694 int flags, distance, i;
5695 388 int64_t prev_dts = AV_NOPTS_VALUE;
5696 388 int next_frag_index = -1, index_entry_pos;
5697 size_t requested_size;
5698 size_t old_ctts_allocated_size;
5699 AVIndexEntry *new_entries;
5700 MOVFragmentStreamInfo * frag_stream_info;
5701
5702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!frag->found_tfhd) {
5703 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
5704 return AVERROR_INVALIDDATA;
5705 }
5706
5707
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < c->fc->nb_streams; i++) {
5708 394 sc = c->fc->streams[i]->priv_data;
5709
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (sc->id == frag->track_id) {
5710 388 st = c->fc->streams[i];
5711 388 sti = ffstream(st);
5712 388 break;
5713 }
5714 }
5715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!st) {
5716 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5717 return 0;
5718 }
5719 388 sc = st->priv_data;
5720
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)
5721 return 0;
5722
5723 // Find the next frag_index index that has a valid index_entry for
5724 // the current track_id.
5725 //
5726 // A valid index_entry means the trun for the fragment was read
5727 // and it's samples are in index_entries at the given position.
5728 // New index entries will be inserted before the index_entry found.
5729 388 index_entry_pos = sti->nb_index_entries;
5730
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++) {
5731 1621 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
5732
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) {
5733 next_frag_index = i;
5734 index_entry_pos = frag_stream_info->index_entry;
5735 break;
5736 }
5737 }
5738
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 av_assert0(index_entry_pos <= sti->nb_index_entries);
5739
5740 388 avio_r8(pb); /* version */
5741 388 flags = avio_rb24(pb);
5742 388 entries = avio_rb32(pb);
5743 388 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
5744
5745
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if ((uint64_t)entries+sc->ctts_count >= UINT_MAX/sizeof(*sc->ctts_data))
5746 return AVERROR_INVALIDDATA;
5747
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
5748
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);
5749
5750 388 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5751
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
5753 dts = frag_stream_info->next_trun_dts - sc->time_offset;
5754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5755 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
5756 pts = frag_stream_info->first_tfra_pts;
5757 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5758 ", using it for pts\n", pts);
5759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5760 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
5761 dts = frag_stream_info->first_tfra_pts;
5762 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5763 ", using it for dts\n", pts);
5764 } else {
5765 388 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
5766 388 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
5767
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;
5768
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;
5769
5770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (fallback_sidx) {
5771 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
5772 }
5773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (fallback_tfdt) {
5774 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
5775 }
5776
5777
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) {
5778 367 dts = frag_stream_info->tfdt_dts - sc->time_offset;
5779 367 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
5780 ", using it for dts\n", dts);
5781
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) {
5782 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
5783 // pts = frag_stream_info->sidx_pts;
5784 dts = frag_stream_info->sidx_pts - sc->time_offset;
5785 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
5786 ", using it for dts\n", frag_stream_info->sidx_pts);
5787 } else {
5788 21 dts = sc->track_end - sc->time_offset;
5789 21 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5790 ", using it for dts\n", dts);
5791 }
5792 }
5793 } else {
5794 dts = sc->track_end - sc->time_offset;
5795 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5796 ", using it for dts\n", dts);
5797 }
5798 388 offset = frag->base_data_offset + data_offset;
5799 388 distance = 0;
5800 388 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
5801
5802 // realloc space for new index entries
5803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
5804 entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
5805 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
5806 }
5807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (entries == 0)
5808 return 0;
5809
5810 388 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
5811 388 new_entries = av_fast_realloc(sti->index_entries,
5812 &sti->index_entries_allocated_size,
5813 requested_size);
5814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!new_entries)
5815 return AVERROR(ENOMEM);
5816 388 sti->index_entries= new_entries;
5817
5818 388 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->ctts_data);
5819 388 old_ctts_allocated_size = sc->ctts_allocated_size;
5820 388 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size,
5821 requested_size);
5822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!ctts_data)
5823 return AVERROR(ENOMEM);
5824 388 sc->ctts_data = ctts_data;
5825
5826 // In case there were samples without ctts entries, ensure they get
5827 // zero valued entries. This ensures clips which mix boxes with and
5828 // without ctts entries don't pickup uninitialized data.
5829 388 memset((uint8_t*)(sc->ctts_data) + old_ctts_allocated_size, 0,
5830 388 sc->ctts_allocated_size - old_ctts_allocated_size);
5831
5832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (index_entry_pos < sti->nb_index_entries) {
5833 // Make hole in index_entries and ctts_data for new samples
5834 memmove(sti->index_entries + index_entry_pos + entries,
5835 sti->index_entries + index_entry_pos,
5836 sizeof(*sti->index_entries) *
5837 (sti->nb_index_entries - index_entry_pos));
5838 memmove(sc->ctts_data + index_entry_pos + entries,
5839 sc->ctts_data + index_entry_pos,
5840 sizeof(*sc->ctts_data) * (sc->ctts_count - index_entry_pos));
5841 if (index_entry_pos < sc->current_sample) {
5842 sc->current_sample += entries;
5843 }
5844 }
5845
5846 388 sti->nb_index_entries += entries;
5847 388 sc->ctts_count = sti->nb_index_entries;
5848
5849 // Record the index_entry position in frag_index of this fragment
5850
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5851 388 frag_stream_info->index_entry = index_entry_pos;
5852
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info->index_base < 0)
5853 388 frag_stream_info->index_base = index_entry_pos;
5854 }
5855
5856
2/2
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 14 times.
388 if (index_entry_pos > 0)
5857 374 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
5858
5859
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++) {
5860 6066 unsigned sample_size = frag->size;
5861
2/2
✓ Branch 0 taken 5678 times.
✓ Branch 1 taken 388 times.
6066 int sample_flags = i ? frag->flags : first_sample_flags;
5862 6066 unsigned sample_duration = frag->duration;
5863 6066 unsigned ctts_duration = 0;
5864 6066 int keyframe = 0;
5865 6066 int index_entry_flags = 0;
5866
5867
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 5594 times.
6066 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
5868
2/2
✓ Branch 0 taken 6034 times.
✓ Branch 1 taken 32 times.
6066 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
5869
2/2
✓ Branch 0 taken 933 times.
✓ Branch 1 taken 5133 times.
6066 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
5870
2/2
✓ Branch 0 taken 5400 times.
✓ Branch 1 taken 666 times.
6066 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
5871
5872 6066 mov_update_dts_shift(sc, ctts_duration, c->fc);
5873
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6066 times.
6066 if (pts != AV_NOPTS_VALUE) {
5874 dts = pts - sc->dts_shift;
5875 if (flags & MOV_TRUN_SAMPLE_CTS) {
5876 dts -= ctts_duration;
5877 } else {
5878 dts -= sc->time_offset;
5879 }
5880 av_log(c->fc, AV_LOG_DEBUG,
5881 "pts %"PRId64" calculated dts %"PRId64
5882 " sc->dts_shift %d ctts.duration %d"
5883 " sc->time_offset %"PRId64
5884 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
5885 pts, dts,
5886 sc->dts_shift, ctts_duration,
5887 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
5888 pts = AV_NOPTS_VALUE;
5889 }
5890
5891
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 6034 times.
6066 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
5892 32 keyframe = 1;
5893 else
5894 6034 keyframe =
5895 6034 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
5896 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
5897
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 5666 times.
6066 if (keyframe) {
5898 400 distance = 0;
5899 400 index_entry_flags |= AVINDEX_KEYFRAME;
5900 }
5901 // Fragments can overlap in time. Discard overlapping frames after
5902 // decoding.
5903
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6042 times.
6066 if (prev_dts >= dts)
5904 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
5905
5906 6066 sti->index_entries[index_entry_pos].pos = offset;
5907 6066 sti->index_entries[index_entry_pos].timestamp = dts;
5908 6066 sti->index_entries[index_entry_pos].size = sample_size;
5909 6066 sti->index_entries[index_entry_pos].min_distance = distance;
5910 6066 sti->index_entries[index_entry_pos].flags = index_entry_flags;
5911
5912 6066 sc->ctts_data[index_entry_pos].count = 1;
5913 6066 sc->ctts_data[index_entry_pos].duration = ctts_duration;
5914 6066 index_entry_pos++;
5915
5916 6066 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
5917 "size %u, distance %d, keyframe %d\n", st->index,
5918 index_entry_pos, offset, dts, sample_size, distance, keyframe);
5919 6066 distance++;
5920
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6066 times.
6066 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
5921 return AVERROR_INVALIDDATA;
5922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6066 times.
6066 if (!sample_size)
5923 return AVERROR_INVALIDDATA;
5924 6066 dts += sample_duration;
5925 6066 offset += sample_size;
5926 6066 sc->data_size += sample_size;
5927
5928
1/2
✓ Branch 0 taken 6066 times.
✗ Branch 1 not taken.
6066 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
5929
1/2
✓ Branch 0 taken 6066 times.
✗ Branch 1 not taken.
6066 1 <= INT_MAX - sc->nb_frames_for_fps
5930 ) {
5931 6066 sc->duration_for_fps += sample_duration;
5932 6066 sc->nb_frames_for_fps ++;
5933 }
5934 }
5935
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info)
5936 388 frag_stream_info->next_trun_dts = dts + sc->time_offset;
5937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (i < entries) {
5938 // EOF found before reading all entries. Fix the hole this would
5939 // leave in index_entries and ctts_data
5940 int gap = entries - i;
5941 memmove(sti->index_entries + index_entry_pos,
5942 sti->index_entries + index_entry_pos + gap,
5943 sizeof(*sti->index_entries) *
5944 (sti->nb_index_entries - (index_entry_pos + gap)));
5945 memmove(sc->ctts_data + index_entry_pos,
5946 sc->ctts_data + index_entry_pos + gap,
5947 sizeof(*sc->ctts_data) *
5948 (sc->ctts_count - (index_entry_pos + gap)));
5949
5950 sti->nb_index_entries -= gap;
5951 sc->ctts_count -= gap;
5952 if (index_entry_pos < sc->current_sample) {
5953 sc->current_sample -= gap;
5954 }
5955 entries = i;
5956 }
5957
5958 // The end of this new fragment may overlap in time with the start
5959 // of the next fragment in index_entries. Mark the samples in the next
5960 // fragment that overlap with AVINDEX_DISCARD_FRAME
5961 388 prev_dts = AV_NOPTS_VALUE;
5962
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (index_entry_pos > 0)
5963 388 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
5964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
5965 if (prev_dts < sti->index_entries[i].timestamp)
5966 break;
5967 sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
5968 }
5969
5970 // If a hole was created to insert the new index_entries into,
5971 // the index_entry recorded for all subsequent moof must
5972 // be incremented by the number of entries inserted.
5973 388 fix_frag_index_entries(&c->frag_index, next_frag_index,
5974 388 frag->track_id, entries);
5975
5976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (pb->eof_reached) {
5977 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
5978 return AVERROR_EOF;
5979 }
5980
5981 388 frag->implicit_offset = offset;
5982
5983 388 sc->track_end = dts + sc->time_offset;
5984
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 379 times.
388 if (st->duration < sc->track_end)
5985 9 st->duration = sc->track_end;
5986
5987 388 return 0;
5988 }
5989
5990 43 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5991 {
5992 43 int64_t stream_size = avio_size(pb);
5993 43 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
5994 uint8_t version, is_complete;
5995 int64_t offadd;
5996 unsigned i, j, track_id, item_count;
5997 43 AVStream *st = NULL;
5998 43 AVStream *ref_st = NULL;
5999 43 MOVStreamContext *sc, *ref_sc = NULL;
6000 AVRational timescale;
6001
6002 43 version = avio_r8(pb);
6003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (version > 1) {
6004 avpriv_request_sample(c->fc, "sidx version %u", version);
6005 return 0;
6006 }
6007
6008 43 avio_rb24(pb); // flags
6009
6010 43 track_id = avio_rb32(pb); // Reference ID
6011
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 for (i = 0; i < c->fc->nb_streams; i++) {
6012 43 sc = c->fc->streams[i]->priv_data;
6013
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (sc->id == track_id) {
6014 43 st = c->fc->streams[i];
6015 43 break;
6016 }
6017 }
6018
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st) {
6019 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6020 return 0;
6021 }
6022
6023 43 sc = st->priv_data;
6024
6025 43 timescale = av_make_q(1, avio_rb32(pb));
6026
6027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (timescale.den <= 0) {
6028 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6029 return AVERROR_INVALIDDATA;
6030 }
6031
6032
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (version == 0) {
6033 43 pts = avio_rb32(pb);
6034 43 offadd= avio_rb32(pb);
6035 } else {
6036 pts = avio_rb64(pb);
6037 offadd= avio_rb64(pb);
6038 }
6039
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6040 return AVERROR_INVALIDDATA;
6041
6042 43 offset += (uint64_t)offadd;
6043
6044 43 avio_rb16(pb); // reserved
6045
6046 43 item_count = avio_rb16(pb);
6047
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (item_count == 0)
6048 return AVERROR_INVALIDDATA;
6049
6050
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 43 times.
411 for (i = 0; i < item_count; i++) {
6051 int index;
6052 MOVFragmentStreamInfo * frag_stream_info;
6053 368 uint32_t size = avio_rb32(pb);
6054 368 uint32_t duration = avio_rb32(pb);
6055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 368 times.
368 if (size & 0x80000000) {
6056 avpriv_request_sample(c->fc, "sidx reference_type 1");
6057 return AVERROR_PATCHWELCOME;
6058 }
6059 368 avio_rb32(pb); // sap_flags
6060 368 timestamp = av_rescale_q(pts, timescale, st->time_base);
6061
6062 368 index = update_frag_index(c, offset);
6063 368 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6064
1/2
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
368 if (frag_stream_info)
6065 368 frag_stream_info->sidx_pts = timestamp;
6066
6067
1/2
✓ Branch 1 taken 368 times.
✗ Branch 2 not taken.
368 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6068
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 368 times.
368 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6069 )
6070 return AVERROR_INVALIDDATA;
6071 368 offset += size;
6072 368 pts += duration;
6073 }
6074
6075 43 st->duration = sc->track_end = pts;
6076
6077 43 sc->has_sidx = 1;
6078
6079 // See if the remaining bytes are just an mfra which we can ignore.
6080 43 is_complete = offset == stream_size;
6081
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 ) {
6082 int64_t ret;
6083 38 int64_t original_pos = avio_tell(pb);
6084
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
38 if (!c->have_read_mfra_size) {
6085
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6086 return ret;
6087 3 c->mfra_size = avio_rb32(pb);
6088 3 c->have_read_mfra_size = 1;
6089
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6090 return ret;
6091 }
6092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (offset == stream_size - c->mfra_size)
6093 is_complete = 1;
6094 }
6095
6096
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 38 times.
43 if (is_complete) {
6097 // Find first entry in fragment index that came from an sidx.
6098 // This will pretty much always be the first entry.
6099
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 5 times.
373 for (i = 0; i < c->frag_index.nb_items; i++) {
6100 368 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6101
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++) {
6102 MOVFragmentStreamInfo * si;
6103 5 si = &item->stream_info[j];
6104
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (si->sidx_pts != AV_NOPTS_VALUE) {
6105 5 ref_st = c->fc->streams[j];
6106 5 ref_sc = ref_st->priv_data;
6107 5 break;
6108 }
6109 }
6110 }
6111
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++) {
6112 5 st = c->fc->streams[i];
6113 5 sc = st->priv_data;
6114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->has_sidx) {
6115 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6116 }
6117 }
6118
6119 5 c->frag_index.complete = 1;
6120 }
6121
6122 43 return 0;
6123 }
6124
6125 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6126 /* like the files created with Adobe Premiere 5.0, for samples see */
6127 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6128 267 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6129 {
6130 int err;
6131
6132
1/2
✓ Branch 0 taken 267 times.
✗ Branch 1 not taken.
267 if (atom.size < 8)
6133 267 return 0; /* continue */
6134 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6135 avio_skip(pb, atom.size - 4);
6136 return 0;
6137 }
6138 atom.type = avio_rl32(pb);
6139 atom.size -= 8;
6140 if (atom.type != MKTAG('m','d','a','t')) {
6141 avio_skip(pb, atom.size);
6142 return 0;
6143 }
6144 err = mov_read_mdat(c, pb, atom);
6145 return err;
6146 }
6147
6148 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6149 {
6150 #if CONFIG_ZLIB
6151 FFIOContext ctx;
6152 uint8_t *cmov_data;
6153 uint8_t *moov_data; /* uncompressed data */
6154 long cmov_len, moov_len;
6155 3 int ret = -1;
6156
6157 3 avio_rb32(pb); /* dcom atom */
6158
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6159 return AVERROR_INVALIDDATA;
6160
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6161 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6162 return AVERROR_INVALIDDATA;
6163 }
6164 3 avio_rb32(pb); /* cmvd atom */
6165
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6166 return AVERROR_INVALIDDATA;
6167 3 moov_len = avio_rb32(pb); /* uncompressed size */
6168 3 cmov_len = atom.size - 6 * 4;
6169
6170 3 cmov_data = av_malloc(cmov_len);
6171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6172 return AVERROR(ENOMEM);
6173 3 moov_data = av_malloc(moov_len);
6174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6175 av_free(cmov_data);
6176 return AVERROR(ENOMEM);
6177 }
6178 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6180 goto free_and_return;
6181
6182 3 ret = AVERROR_INVALIDDATA;
6183
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)
6184 goto free_and_return;
6185 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6186 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6187 3 atom.type = MKTAG('m','o','o','v');
6188 3 atom.size = moov_len;
6189 3 ret = mov_read_default(c, &ctx.pub, atom);
6190 3 free_and_return:
6191 3 av_free(moov_data);
6192 3 av_free(cmov_data);
6193 3 return ret;
6194 #else
6195 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6196 return AVERROR(ENOSYS);
6197 #endif
6198 }
6199
6200 /* edit list atom */
6201 438 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6202 {
6203 MOVStreamContext *sc;
6204 int i, edit_count, version;
6205 int64_t elst_entry_size;
6206
6207
2/4
✓ Branch 0 taken 438 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 438 times.
438 if (c->fc->nb_streams < 1 || c->ignore_editlist)
6208 return 0;
6209 438 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6210
6211 438 version = avio_r8(pb); /* version */
6212 438 avio_rb24(pb); /* flags */
6213 438 edit_count = avio_rb32(pb); /* entries */
6214 438 atom.size -= 8;
6215
6216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 438 times.
438 elst_entry_size = version == 1 ? 20 : 12;
6217
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 437 times.
438 if (atom.size != edit_count * elst_entry_size) {
6218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6219 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6220 edit_count, atom.size + 8);
6221 return AVERROR_INVALIDDATA;
6222 } else {
6223 1 edit_count = atom.size / elst_entry_size;
6224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6225 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6226 }
6227 }
6228 }
6229
6230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 438 times.
438 if (!edit_count)
6231 return 0;
6232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 438 times.
438 if (sc->elst_data)
6233 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6234 438 av_free(sc->elst_data);
6235 438 sc->elst_count = 0;
6236 438 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 438 times.
438 if (!sc->elst_data)
6238 return AVERROR(ENOMEM);
6239
6240 438 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6241
4/6
✓ Branch 0 taken 465 times.
✓ Branch 1 taken 438 times.
✓ Branch 2 taken 465 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 465 times.
✗ Branch 5 not taken.
903 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
6242 465 MOVElst *e = &sc->elst_data[i];
6243
6244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 465 times.
465 if (version == 1) {
6245 e->duration = avio_rb64(pb);
6246 e->time = avio_rb64(pb);
6247 atom.size -= 16;
6248 } else {
6249 465 e->duration = avio_rb32(pb); /* segment duration */
6250 465 e->time = (int32_t)avio_rb32(pb); /* media time */
6251 465 atom.size -= 8;
6252 }
6253 465 e->rate = avio_rb32(pb) / 65536.0;
6254 465 atom.size -= 4;
6255 465 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6256 465 e->duration, e->time, e->rate);
6257
6258
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 461 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
465 if (e->time < 0 && e->time != -1 &&
6259 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6260 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6261 c->fc->nb_streams-1, i, e->time);
6262 return AVERROR_INVALIDDATA;
6263 }
6264 }
6265 438 sc->elst_count = i;
6266
6267 438 return 0;
6268 }
6269
6270 18 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6271 {
6272 MOVStreamContext *sc;
6273
6274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->fc->nb_streams < 1)
6275 return AVERROR_INVALIDDATA;
6276 18 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6277 18 sc->timecode_track = avio_rb32(pb);
6278 18 return 0;
6279 }
6280
6281 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6282 {
6283 AVStream *st;
6284 int version, color_range, color_primaries, color_trc, color_space;
6285
6286 if (c->fc->nb_streams < 1)
6287 return 0;
6288 st = c->fc->streams[c->fc->nb_streams - 1];
6289
6290 if (atom.size < 5) {
6291 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6292 return AVERROR_INVALIDDATA;
6293 }
6294
6295 version = avio_r8(pb);
6296 if (version != 1) {
6297 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6298 return 0;
6299 }
6300 avio_skip(pb, 3); /* flags */
6301
6302 avio_skip(pb, 2); /* profile + level */
6303 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6304 color_primaries = avio_r8(pb);
6305 color_trc = avio_r8(pb);
6306 color_space = avio_r8(pb);
6307 if (avio_rb16(pb)) /* codecIntializationDataSize */
6308 return AVERROR_INVALIDDATA;
6309
6310 if (!av_color_primaries_name(color_primaries))
6311 color_primaries = AVCOL_PRI_UNSPECIFIED;
6312 if (!av_color_transfer_name(color_trc))
6313 color_trc = AVCOL_TRC_UNSPECIFIED;
6314 if (!av_color_space_name(color_space))
6315 color_space = AVCOL_SPC_UNSPECIFIED;
6316
6317 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6318 st->codecpar->color_primaries = color_primaries;
6319 st->codecpar->color_trc = color_trc;
6320 st->codecpar->color_space = color_space;
6321
6322 return 0;
6323 }
6324
6325 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6326 {
6327 MOVStreamContext *sc;
6328 int i, version;
6329
6330 if (c->fc->nb_streams < 1)
6331 return AVERROR_INVALIDDATA;
6332
6333 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6334
6335 if (atom.size < 5) {
6336 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6337 return AVERROR_INVALIDDATA;
6338 }
6339
6340 version = avio_r8(pb);
6341 if (version) {
6342 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6343 return 0;
6344 }
6345 if (sc->mastering) {
6346 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6347 return 0;
6348 }
6349
6350 avio_skip(pb, 3); /* flags */
6351
6352 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6353 if (!sc->mastering)
6354 return AVERROR(ENOMEM);
6355
6356 for (i = 0; i < 3; i++) {
6357 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6358 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6359 }
6360 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6361 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6362
6363 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6364 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6365
6366 sc->mastering->has_primaries = 1;
6367 sc->mastering->has_luminance = 1;
6368
6369 return 0;
6370 }
6371
6372 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6373 {
6374 MOVStreamContext *sc;
6375 const int mapping[3] = {1, 2, 0};
6376 const int chroma_den = 50000;
6377 const int luma_den = 10000;
6378 int i;
6379
6380 if (c->fc->nb_streams < 1)
6381 return AVERROR_INVALIDDATA;
6382
6383 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6384
6385 if (atom.size < 24) {
6386 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6387 return AVERROR_INVALIDDATA;
6388 }
6389
6390 if (sc->mastering) {
6391 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6392 return 0;
6393 }
6394
6395 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6396 if (!sc->mastering)
6397 return AVERROR(ENOMEM);
6398
6399 for (i = 0; i < 3; i++) {
6400 const int j = mapping[i];
6401 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6402 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6403 }
6404 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6405 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6406
6407 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6408 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6409
6410 sc->mastering->has_luminance = 1;
6411 sc->mastering->has_primaries = 1;
6412
6413 return 0;
6414 }
6415
6416 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6417 {
6418 MOVStreamContext *sc;
6419 int version;
6420
6421 if (c->fc->nb_streams < 1)
6422 return AVERROR_INVALIDDATA;
6423
6424 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6425
6426 if (atom.size < 5) {
6427 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
6428 return AVERROR_INVALIDDATA;
6429 }
6430
6431 version = avio_r8(pb);
6432 if (version) {
6433 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
6434 return 0;
6435 }
6436 avio_skip(pb, 3); /* flags */
6437
6438 if (sc->coll){
6439 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
6440 return 0;
6441 }
6442
6443 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6444 if (!sc->coll)
6445 return AVERROR(ENOMEM);
6446
6447 sc->coll->MaxCLL = avio_rb16(pb);
6448 sc->coll->MaxFALL = avio_rb16(pb);
6449
6450 return 0;
6451 }
6452
6453 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6454 {
6455 MOVStreamContext *sc;
6456
6457 if (c->fc->nb_streams < 1)
6458 return AVERROR_INVALIDDATA;
6459
6460 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6461
6462 if (atom.size < 4) {
6463 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
6464 return AVERROR_INVALIDDATA;
6465 }
6466
6467 if (sc->coll){
6468 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
6469 return 0;
6470 }
6471
6472 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6473 if (!sc->coll)
6474 return AVERROR(ENOMEM);
6475
6476 sc->coll->MaxCLL = avio_rb16(pb);
6477 sc->coll->MaxFALL = avio_rb16(pb);
6478
6479 return 0;
6480 }
6481
6482 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6483 {
6484 MOVStreamContext *sc;
6485 4 const int illuminance_den = 10000;
6486 4 const int ambient_den = 50000;
6487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
6488 return AVERROR_INVALIDDATA;
6489 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
6491 av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
6492 return AVERROR_INVALIDDATA;
6493 }
6494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
6495 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
6496 return 0;
6497 }
6498 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
6499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
6500 return AVERROR(ENOMEM);
6501 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
6502 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
6503 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
6504 4 return 0;
6505 }
6506
6507 1 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6508 {
6509 AVStream *st;
6510 MOVStreamContext *sc;
6511 enum AVStereo3DType type;
6512 int mode;
6513
6514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6515 return 0;
6516
6517 1 st = c->fc->streams[c->fc->nb_streams - 1];
6518 1 sc = st->priv_data;
6519
6520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 5) {
6521 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
6522 return AVERROR_INVALIDDATA;
6523 }
6524
6525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sc->stereo3d)
6526 return AVERROR_INVALIDDATA;
6527
6528 1 avio_skip(pb, 4); /* version + flags */
6529
6530 1 mode = avio_r8(pb);
6531
1/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 switch (mode) {
6532 1 case 0:
6533 1 type = AV_STEREO3D_2D;
6534 1 break;
6535 case 1:
6536 type = AV_STEREO3D_TOPBOTTOM;
6537 break;
6538 case 2:
6539 type = AV_STEREO3D_SIDEBYSIDE;
6540 break;
6541 default:
6542 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
6543 return 0;
6544 }
6545
6546 1 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->stereo3d)
6548 return AVERROR(ENOMEM);
6549
6550 1 sc->stereo3d->type = type;
6551 1 return 0;
6552 }
6553
6554 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6555 {
6556 AVStream *st;
6557 MOVStreamContext *sc;
6558 int size, version, layout;
6559 int32_t yaw, pitch, roll;
6560 1 uint32_t l = 0, t = 0, r = 0, b = 0;
6561 1 uint32_t tag, padding = 0;
6562 enum AVSphericalProjection projection;
6563
6564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6565 return 0;
6566
6567 1 st = c->fc->streams[c->fc->nb_streams - 1];
6568 1 sc = st->priv_data;
6569
6570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
6571 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
6572 return AVERROR_INVALIDDATA;
6573 }
6574
6575 1 size = avio_rb32(pb);
6576
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)
6577 return AVERROR_INVALIDDATA;
6578
6579 1 tag = avio_rl32(pb);
6580
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
6581 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
6582 return 0;
6583 }
6584 1 version = avio_r8(pb);
6585
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6586 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6587 version);
6588 return 0;
6589 }
6590 1 avio_skip(pb, 3); /* flags */
6591 1 avio_skip(pb, size - 12); /* metadata_source */
6592
6593 1 size = avio_rb32(pb);
6594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6595 return AVERROR_INVALIDDATA;
6596
6597 1 tag = avio_rl32(pb);
6598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
6599 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
6600 return 0;
6601 }
6602
6603 1 size = avio_rb32(pb);
6604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6605 return AVERROR_INVALIDDATA;
6606
6607 1 tag = avio_rl32(pb);
6608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
6609 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
6610 return 0;
6611 }
6612 1 version = avio_r8(pb);
6613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6614 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6615 version);
6616 return 0;
6617 }
6618 1 avio_skip(pb, 3); /* flags */
6619
6620 /* 16.16 fixed point */
6621 1 yaw = avio_rb32(pb);
6622 1 pitch = avio_rb32(pb);
6623 1 roll = avio_rb32(pb);
6624
6625 1 size = avio_rb32(pb);
6626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6627 return AVERROR_INVALIDDATA;
6628
6629 1 tag = avio_rl32(pb);
6630 1 version = avio_r8(pb);
6631
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6632 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6633 version);
6634 return 0;
6635 }
6636 1 avio_skip(pb, 3); /* flags */
6637
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
6638 case MKTAG('c','b','m','p'):
6639 layout = avio_rb32(pb);
6640 if (layout) {
6641 av_log(c->fc, AV_LOG_WARNING,
6642 "Unsupported cubemap layout %d\n", layout);
6643 return 0;
6644 }
6645 projection = AV_SPHERICAL_CUBEMAP;
6646 padding = avio_rb32(pb);
6647 break;
6648 1 case MKTAG('e','q','u','i'):
6649 1 t = avio_rb32(pb);
6650 1 b = avio_rb32(pb);
6651 1 l = avio_rb32(pb);
6652 1 r = avio_rb32(pb);
6653
6654
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) {
6655 av_log(c->fc, AV_LOG_ERROR,
6656 "Invalid bounding rectangle coordinates "
6657 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
6658 return AVERROR_INVALIDDATA;
6659 }
6660
6661
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)
6662 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
6663 else
6664 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6665 1 break;
6666 default:
6667 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
6668 return 0;
6669 }
6670
6671 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
6673 return AVERROR(ENOMEM);
6674
6675 1 sc->spherical->projection = projection;
6676
6677 1 sc->spherical->yaw = yaw;
6678 1 sc->spherical->pitch = pitch;
6679 1 sc->spherical->roll = roll;
6680
6681 1 sc->spherical->padding = padding;
6682
6683 1 sc->spherical->bound_left = l;
6684 1 sc->spherical->bound_top = t;
6685 1 sc->spherical->bound_right = r;
6686 1 sc->spherical->bound_bottom = b;
6687
6688 1 return 0;
6689 }
6690
6691 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6692 {
6693 AVStream *st;
6694 MOVStreamContext *sc;
6695 int size;
6696 uint32_t tag;
6697 enum AVSphericalProjection projection;
6698
6699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6700 return 0;
6701
6702 3 st = c->fc->streams[c->fc->nb_streams - 1];
6703 3 sc = st->priv_data;
6704
6705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 16) {
6706 av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
6707 return AVERROR_INVALIDDATA;
6708 }
6709
6710 3 size = avio_rb32(pb);
6711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 16) {
6712 av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
6713 return AVERROR_INVALIDDATA;
6714 }
6715
6716 3 tag = avio_rl32(pb);
6717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
6718 av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: 0x%08X\n", tag);
6719 return AVERROR_INVALIDDATA;
6720 }
6721
6722 3 avio_skip(pb, 1); // version
6723 3 avio_skip(pb, 3); // flags
6724
6725 3 tag = avio_rl32(pb);
6726
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) {
6727 3 case MKTAG('r','e','c','t'):
6728 3 projection = AV_SPHERICAL_RECTILINEAR;
6729 3 break;
6730 case MKTAG('e','q','u','i'):
6731 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6732 break;
6733 case MKTAG('h','e','q','u'):
6734 projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
6735 break;
6736 case MKTAG('f','i','s','h'):
6737 projection = AV_SPHERICAL_FISHEYE;
6738 break;
6739 default:
6740 av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: 0x%08X\n", tag);
6741 return AVERROR_INVALIDDATA;
6742 }
6743
6744 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6745
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
6746 return AVERROR(ENOMEM);
6747
6748 3 sc->spherical->projection = projection;
6749
6750 3 return 0;
6751 }
6752
6753 3 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6754 {
6755 AVStream *st;
6756 MOVStreamContext *sc;
6757 3 int size, flags = 0;
6758 int64_t remaining;
6759 3 uint32_t tag, baseline = 0;
6760 3 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
6761 3 enum AVStereo3DType type = AV_STEREO3D_2D;
6762 3 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
6763 3 AVRational horizontal_disparity_adjustment = { 0, 1 };
6764
6765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6766 return 0;
6767
6768 3 st = c->fc->streams[c->fc->nb_streams - 1];
6769 3 sc = st->priv_data;
6770
6771 3 remaining = atom.size;
6772
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 while (remaining > 0) {
6773 9 size = avio_rb32(pb);
6774
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 ) {
6775 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
6776 return AVERROR_INVALIDDATA;
6777 }
6778
6779 9 tag = avio_rl32(pb);
6780
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) {
6781 3 case MKTAG('s','t','r','i'): {
6782 int has_right, has_left;
6783 uint8_t tmp;
6784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 13) {
6785 av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
6786 return AVERROR_INVALIDDATA;
6787 }
6788 3 avio_skip(pb, 1); // version
6789 3 avio_skip(pb, 3); // flags
6790
6791 3 tmp = avio_r8(pb);
6792
6793 // eye_views_reversed
6794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tmp & 8) {
6795 flags |= AV_STEREO3D_FLAG_INVERT;
6796 }
6797 // has_additional_views
6798 3 if (tmp & 4) {
6799 // skip...
6800 }
6801
6802 3 has_right = tmp & 2; // has_right_eye_view
6803 3 has_left = tmp & 1; // has_left_eye_view
6804
6805
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)
6806 3 view = AV_STEREO3D_VIEW_PACKED;
6807 else if (has_left)
6808 view = AV_STEREO3D_VIEW_LEFT;
6809 else if (has_right)
6810 view = AV_STEREO3D_VIEW_RIGHT;
6811
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)
6812 3 type = AV_STEREO3D_UNSPEC;
6813
6814 3 break;
6815 }
6816 case MKTAG('h','e','r','o'): {
6817 int tmp;
6818 if (size != 13) {
6819 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
6820 return AVERROR_INVALIDDATA;
6821 }
6822 avio_skip(pb, 1); // version
6823 avio_skip(pb, 3); // flags
6824
6825 tmp = avio_r8(pb);
6826 if (tmp == 0)
6827 primary_eye = AV_PRIMARY_EYE_NONE;
6828 else if (tmp == 1)
6829 primary_eye = AV_PRIMARY_EYE_LEFT;
6830 else if (tmp == 2)
6831 primary_eye = AV_PRIMARY_EYE_RIGHT;
6832 else
6833 av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
6834
6835 break;
6836 }
6837 3 case MKTAG('c','a','m','s'): {
6838 uint32_t subtag;
6839 int subsize;
6840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
6841 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
6842 return AVERROR_INVALIDDATA;
6843 }
6844
6845 3 subsize = avio_rb32(pb);
6846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
6847 av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
6848 return AVERROR_INVALIDDATA;
6849 }
6850
6851 3 subtag = avio_rl32(pb);
6852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
6853 av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got 0x%08X\n", subtag);
6854 return AVERROR_INVALIDDATA;
6855 }
6856
6857 3 avio_skip(pb, 1); // version
6858 3 avio_skip(pb, 3); // flags
6859
6860 3 baseline = avio_rb32(pb);
6861
6862 3 break;
6863 }
6864 3 case MKTAG('c','m','f','y'): {
6865 uint32_t subtag;
6866 int subsize;
6867 int32_t adjustment;
6868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
6869 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
6870 return AVERROR_INVALIDDATA;
6871 }
6872
6873 3 subsize = avio_rb32(pb);
6874
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
6875 av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
6876 return AVERROR_INVALIDDATA;
6877 }
6878
6879 3 subtag = avio_rl32(pb);
6880
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
6881 av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got 0x%08X\n", subtag);
6882 return AVERROR_INVALIDDATA;
6883 }
6884
6885 3 avio_skip(pb, 1); // version
6886 3 avio_skip(pb, 3); // flags
6887
6888 3 adjustment = (int32_t) avio_rb32(pb);
6889
6890 3 horizontal_disparity_adjustment.num = (int) adjustment;
6891 3 horizontal_disparity_adjustment.den = 10000;
6892
6893 3 break;
6894 }
6895 default:
6896 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: 0x%08X\n", tag);
6897 avio_skip(pb, size - 8);
6898 break;
6899 }
6900 9 remaining -= size;
6901 }
6902
6903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
6904 av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
6905 return AVERROR_INVALIDDATA;
6906 }
6907
6908
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (type == AV_STEREO3D_2D)
6909 return 0;
6910
6911
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->stereo3d) {
6912 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6913
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
6914 return AVERROR(ENOMEM);
6915 }
6916
6917 3 sc->stereo3d->flags = flags;
6918 3 sc->stereo3d->type = type;
6919 3 sc->stereo3d->view = view;
6920 3 sc->stereo3d->primary_eye = primary_eye;
6921 3 sc->stereo3d->baseline = baseline;
6922 3 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
6923
6924 3 return 0;
6925 }
6926
6927 3 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6928 {
6929 int size;
6930 int64_t remaining;
6931 uint32_t tag;
6932
6933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6934 return 0;
6935
6936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8) {
6937 av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
6938 return AVERROR_INVALIDDATA;
6939 }
6940
6941 3 remaining = atom.size;
6942
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 while (remaining > 0) {
6943 6 size = avio_rb32(pb);
6944
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 ) {
6945 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
6946 return AVERROR_INVALIDDATA;
6947 }
6948
6949 6 tag = avio_rl32(pb);
6950
2/3
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 switch (tag) {
6951 3 case MKTAG('p','r','o','j'): {
6952 3 MOVAtom proj = { tag, size - 8 };
6953 3 int ret = mov_read_vexu_proj(c, pb, proj);
6954
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6955 return ret;
6956 3 break;
6957 }
6958 3 case MKTAG('e','y','e','s'): {
6959 3 MOVAtom eyes = { tag, size - 8 };
6960 3 int ret = mov_read_eyes(c, pb, eyes);
6961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6962 return ret;
6963 3 break;
6964 }
6965 default:
6966 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: 0x%08X\n", tag);
6967 avio_skip(pb, size - 8);
6968 break;
6969 }
6970 6 remaining -= size;
6971 }
6972
6973
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
6974 av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
6975 return AVERROR_INVALIDDATA;
6976 }
6977
6978 3 return 0;
6979 }
6980
6981 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6982 {
6983 AVStream *st;
6984 MOVStreamContext *sc;
6985
6986
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6987 return 0;
6988
6989 3 st = c->fc->streams[c->fc->nb_streams - 1];
6990 3 sc = st->priv_data;
6991
6992
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
6993 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
6994 return AVERROR_INVALIDDATA;
6995 }
6996
6997
6998
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
6999 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7000 if (!sc->stereo3d)
7001 return AVERROR(ENOMEM);
7002 }
7003
7004 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7005 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7006
7007 3 return 0;
7008 }
7009
7010 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7011 {
7012 int ret = 0;
7013 uint8_t *buffer = av_malloc(len + 1);
7014 const char *val;
7015
7016 if (!buffer)
7017 return AVERROR(ENOMEM);
7018 buffer[len] = '\0';
7019
7020 ret = ffio_read_size(pb, buffer, len);
7021 if (ret < 0)
7022 goto out;
7023
7024 /* Check for mandatory keys and values, try to support XML as best-effort */
7025 if (!sc->spherical &&
7026 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7027 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7028 av_stristr(val, "true") &&
7029 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7030 av_stristr(val, "true") &&
7031 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7032 av_stristr(val, "equirectangular")) {
7033 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7034 if (!sc->spherical)
7035 goto out;
7036
7037 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7038
7039 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7040 enum AVStereo3DType mode;
7041
7042 if (av_stristr(buffer, "left-right"))
7043 mode = AV_STEREO3D_SIDEBYSIDE;
7044 else if (av_stristr(buffer, "top-bottom"))
7045 mode = AV_STEREO3D_TOPBOTTOM;
7046 else
7047 mode = AV_STEREO3D_2D;
7048
7049 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7050 if (!sc->stereo3d)
7051 goto out;
7052
7053 sc->stereo3d->type = mode;
7054 }
7055
7056 /* orientation */
7057 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7058 if (val)
7059 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7060 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7061 if (val)
7062 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7063 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7064 if (val)
7065 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7066 }
7067
7068 out:
7069 av_free(buffer);
7070 return ret;
7071 }
7072
7073 15 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7074 {
7075 AVStream *st;
7076 MOVStreamContext *sc;
7077 int64_t ret;
7078 AVUUID uuid;
7079 static const AVUUID uuid_isml_manifest = {
7080 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7081 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7082 };
7083 static const AVUUID uuid_xmp = {
7084 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7085 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7086 };
7087 static const AVUUID uuid_spherical = {
7088 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7089 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7090 };
7091
7092
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))
7093 return AVERROR_INVALIDDATA;
7094
7095
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 14 times.
15 if (c->fc->nb_streams < 1)
7096 1 return 0;
7097 14 st = c->fc->streams[c->fc->nb_streams - 1];
7098 14 sc = st->priv_data;
7099
7100 14 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0)
7102 return ret;
7103
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7104 uint8_t *buffer, *ptr;
7105 char *endptr;
7106 size_t len = atom.size - AV_UUID_LEN;
7107
7108 if (len < 4) {
7109 return AVERROR_INVALIDDATA;
7110 }
7111 ret = avio_skip(pb, 4); // zeroes
7112 len -= 4;
7113
7114 buffer = av_mallocz(len + 1);
7115 if (!buffer) {
7116 return AVERROR(ENOMEM);
7117 }
7118 ret = ffio_read_size(pb, buffer, len);
7119 if (ret < 0) {
7120 av_free(buffer);
7121 return ret;
7122 }
7123
7124 ptr = buffer;
7125 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7126 ptr += sizeof("systemBitrate=\"") - 1;
7127 c->bitrates_count++;
7128 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7129 if (!c->bitrates) {
7130 c->bitrates_count = 0;
7131 av_free(buffer);
7132 return AVERROR(ENOMEM);
7133 }
7134 errno = 0;
7135 ret = strtol(ptr, &endptr, 10);
7136 if (ret < 0 || errno || *endptr != '"') {
7137 c->bitrates[c->bitrates_count - 1] = 0;
7138 } else {
7139 c->bitrates[c->bitrates_count - 1] = ret;
7140 }
7141 }
7142
7143 av_free(buffer);
7144
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7145 uint8_t *buffer;
7146 size_t len = atom.size - AV_UUID_LEN;
7147 if (c->export_xmp) {
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 buffer[len] = '\0';
7158 av_dict_set(&c->fc->metadata, "xmp",
7159 buffer, AV_DICT_DONT_STRDUP_VAL);
7160 } else {
7161 // skip all uuid atom, which makes it fast for long uuid-xmp file
7162 ret = avio_skip(pb, len);
7163 if (ret < 0)
7164 return ret;
7165 }
7166
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7167 size_t len = atom.size - AV_UUID_LEN;
7168 ret = mov_parse_uuid_spherical(sc, pb, len);
7169 if (ret < 0)
7170 return ret;
7171 if (!sc->spherical)
7172 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7173 }
7174
7175 14 return 0;
7176 }
7177
7178 187 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7179 {
7180 int ret;
7181 uint8_t content[16];
7182
7183
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 96 times.
187 if (atom.size < 8)
7184 91 return 0;
7185
7186 96 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (ret < 0)
7188 return ret;
7189
7190
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 55 times.
96 if ( !c->found_moov
7191
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 23 times.
41 && !c->found_mdat
7192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 && !memcmp(content, "Anevia\x1A\x1A", 8)
7193 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7194 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7195 }
7196
7197 96 return 0;
7198 }
7199
7200 35 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7201 {
7202 35 uint32_t format = avio_rl32(pb);
7203 MOVStreamContext *sc;
7204 enum AVCodecID id;
7205 AVStream *st;
7206
7207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (c->fc->nb_streams < 1)
7208 return 0;
7209 35 st = c->fc->streams[c->fc->nb_streams - 1];
7210 35 sc = st->priv_data;
7211
7212
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 32 times.
35 switch (sc->format)
7213 {
7214 3 case MKTAG('e','n','c','v'): // encrypted video
7215 case MKTAG('e','n','c','a'): // encrypted audio
7216 3 id = mov_codec_id(st, format);
7217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7218 st->codecpar->codec_id != id) {
7219 av_log(c->fc, AV_LOG_WARNING,
7220 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7221 (char*)&format, st->codecpar->codec_id);
7222 break;
7223 }
7224
7225 3 st->codecpar->codec_id = id;
7226 3 sc->format = format;
7227 3 break;
7228
7229 32 default:
7230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (format != sc->format) {
7231 av_log(c->fc, AV_LOG_WARNING,
7232 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7233 (char*)&format, (char*)&sc->format);
7234 }
7235 32 break;
7236 }
7237
7238 35 return 0;
7239 }
7240
7241 /**
7242 * Gets the current encryption info and associated current stream context. If
7243 * we are parsing a track fragment, this will return the specific encryption
7244 * info for this fragment; otherwise this will return the global encryption
7245 * info for the current stream.
7246 */
7247 6 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7248 {
7249 MOVFragmentStreamInfo *frag_stream_info;
7250 AVStream *st;
7251 int i;
7252
7253 6 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7254
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (frag_stream_info) {
7255
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 for (i = 0; i < c->fc->nb_streams; i++) {
7256 3 *sc = c->fc->streams[i]->priv_data;
7257
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if ((*sc)->id == frag_stream_info->id) {
7258 3 st = c->fc->streams[i];
7259 3 break;
7260 }
7261 }
7262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (i == c->fc->nb_streams)
7263 return 0;
7264 3 *sc = st->priv_data;
7265
7266
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!frag_stream_info->encryption_index) {
7267 // If this stream isn't encrypted, don't create the index.
7268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!(*sc)->cenc.default_encrypted_sample)
7269 return 0;
7270 1 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!frag_stream_info->encryption_index)
7272 return AVERROR(ENOMEM);
7273 }
7274 3 *encryption_index = frag_stream_info->encryption_index;
7275 3 return 1;
7276 } else {
7277 // No current track fragment, using stream level encryption info.
7278
7279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7280 return 0;
7281 3 st = c->fc->streams[c->fc->nb_streams - 1];
7282 3 *sc = st->priv_data;
7283
7284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!(*sc)->cenc.encryption_index) {
7285 // If this stream isn't encrypted, don't create the index.
7286 if (!(*sc)->cenc.default_encrypted_sample)
7287 return 0;
7288 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7289 if (!(*sc)->cenc.encryption_index)
7290 return AVERROR(ENOMEM);
7291 }
7292
7293 3 *encryption_index = (*sc)->cenc.encryption_index;
7294 3 return 1;
7295 }
7296 }
7297
7298 72 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7299 {
7300 int i, ret;
7301 unsigned int subsample_count;
7302 AVSubsampleEncryptionInfo *subsamples;
7303
7304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!sc->cenc.default_encrypted_sample) {
7305 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7306 return AVERROR_INVALIDDATA;
7307 }
7308
7309
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) {
7310 72 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!*sample)
7312 return AVERROR(ENOMEM);
7313 } else
7314 *sample = NULL;
7315
7316
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (sc->cenc.per_sample_iv_size != 0) {
7317
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) {
7318 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
7319 av_encryption_info_free(*sample);
7320 *sample = NULL;
7321 return ret;
7322 }
7323 }
7324
7325
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (use_subsamples) {
7326 72 subsample_count = avio_rb16(pb);
7327 72 av_free((*sample)->subsamples);
7328 72 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
7329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!(*sample)->subsamples) {
7330 av_encryption_info_free(*sample);
7331 *sample = NULL;
7332 return AVERROR(ENOMEM);
7333 }
7334
7335
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++) {
7336 72 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
7337 72 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
7338 }
7339
7340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (pb->eof_reached) {
7341 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
7342 av_encryption_info_free(*sample);
7343 *sample = NULL;
7344 return AVERROR_INVALIDDATA;
7345 }
7346 72 (*sample)->subsample_count = subsample_count;
7347 }
7348
7349 72 return 0;
7350 }
7351
7352 2 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7353 {
7354 AVEncryptionInfo **encrypted_samples;
7355 MOVEncryptionIndex *encryption_index;
7356 MOVStreamContext *sc;
7357 int use_subsamples, ret;
7358 2 unsigned int sample_count, i, alloc_size = 0;
7359
7360 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7362 return ret;
7363
7364
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7365 // This can happen if we have both saio/saiz and senc atoms.
7366 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
7367 1 return 0;
7368 }
7369
7370 1 avio_r8(pb); /* version */
7371 1 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
7372
7373 1 sample_count = avio_rb32(pb);
7374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7375 return AVERROR(ENOMEM);
7376
7377
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1 times.
49 for (i = 0; i < sample_count; i++) {
7378 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7379 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7380 min_samples * sizeof(*encrypted_samples));
7381
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (encrypted_samples) {
7382 48 encryption_index->encrypted_samples = encrypted_samples;
7383
7384 48 ret = mov_read_sample_encryption_info(
7385 48 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
7386 } else {
7387 ret = AVERROR(ENOMEM);
7388 }
7389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (pb->eof_reached) {
7390 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
7391 if (ret >= 0)
7392 av_encryption_info_free(encryption_index->encrypted_samples[i]);
7393 ret = AVERROR_INVALIDDATA;
7394 }
7395
7396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0) {
7397 for (; i > 0; i--)
7398 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7399 av_freep(&encryption_index->encrypted_samples);
7400 return ret;
7401 }
7402 }
7403 1 encryption_index->nb_encrypted_samples = sample_count;
7404
7405 1 return 0;
7406 }
7407
7408 1 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
7409 {
7410 AVEncryptionInfo **sample, **encrypted_samples;
7411 int64_t prev_pos;
7412 size_t sample_count, sample_info_size, i;
7413 1 int ret = 0;
7414 1 unsigned int alloc_size = 0;
7415
7416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->nb_encrypted_samples)
7417 return 0;
7418 1 sample_count = encryption_index->auxiliary_info_sample_count;
7419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count != 1) {
7420 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
7421 return AVERROR_PATCHWELCOME;
7422 }
7423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7424 return AVERROR(ENOMEM);
7425
7426 1 prev_pos = avio_tell(pb);
7427
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
7428
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]) {
7429 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
7430 goto finish;
7431 }
7432
7433
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++) {
7434 24 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7435 24 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7436 min_samples * sizeof(*encrypted_samples));
7437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!encrypted_samples) {
7438 ret = AVERROR(ENOMEM);
7439 goto finish;
7440 }
7441 24 encryption_index->encrypted_samples = encrypted_samples;
7442
7443 24 sample = &encryption_index->encrypted_samples[i];
7444 48 sample_info_size = encryption_index->auxiliary_info_default_size
7445 24 ? encryption_index->auxiliary_info_default_size
7446
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 : encryption_index->auxiliary_info_sizes[i];
7447
7448 24 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
7449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (ret < 0)
7450 goto finish;
7451 }
7452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7453 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
7454 ret = AVERROR_INVALIDDATA;
7455 } else {
7456 1 encryption_index->nb_encrypted_samples = sample_count;
7457 }
7458
7459 1 finish:
7460 1 avio_seek(pb, prev_pos, SEEK_SET);
7461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
7462 for (; i > 0; i--) {
7463 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7464 }
7465 av_freep(&encryption_index->encrypted_samples);
7466 }
7467 1 return ret;
7468 }
7469
7470 2 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7471 {
7472 MOVEncryptionIndex *encryption_index;
7473 MOVStreamContext *sc;
7474 int ret;
7475 unsigned int sample_count, aux_info_type, aux_info_param;
7476
7477 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7479 return ret;
7480
7481
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7482 // This can happen if we have both saio/saiz and senc atoms.
7483 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
7484 1 return 0;
7485 }
7486
7487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_sample_count) {
7488 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
7489 return AVERROR_INVALIDDATA;
7490 }
7491
7492 1 avio_r8(pb); /* version */
7493
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7494 aux_info_type = avio_rb32(pb);
7495 aux_info_param = avio_rb32(pb);
7496 if (sc->cenc.default_encrypted_sample) {
7497 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7498 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
7499 return 0;
7500 }
7501 if (aux_info_param != 0) {
7502 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
7503 return 0;
7504 }
7505 } else {
7506 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7507 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7508 aux_info_type == MKBETAG('c','e','n','s') ||
7509 aux_info_type == MKBETAG('c','b','c','1') ||
7510 aux_info_type == MKBETAG('c','b','c','s')) &&
7511 aux_info_param == 0) {
7512 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
7513 return AVERROR_INVALIDDATA;
7514 } else {
7515 return 0;
7516 }
7517 }
7518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7519 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7520 return 0;
7521 }
7522
7523 1 encryption_index->auxiliary_info_default_size = avio_r8(pb);
7524 1 sample_count = avio_rb32(pb);
7525
7526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_default_size == 0) {
7527 if (sample_count == 0)
7528 return AVERROR_INVALIDDATA;
7529
7530 encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
7531 if (!encryption_index->auxiliary_info_sizes)
7532 return AVERROR(ENOMEM);
7533
7534 ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
7535 if (ret != sample_count) {
7536 av_freep(&encryption_index->auxiliary_info_sizes);
7537
7538 if (ret >= 0)
7539 ret = AVERROR_INVALIDDATA;
7540 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
7541 av_err2str(ret));
7542 return ret;
7543 }
7544 }
7545 1 encryption_index->auxiliary_info_sample_count = sample_count;
7546
7547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7548 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7549 }
7550
7551 1 return 0;
7552 }
7553
7554 2 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7555 {
7556 uint64_t *auxiliary_offsets;
7557 MOVEncryptionIndex *encryption_index;
7558 MOVStreamContext *sc;
7559 int i, ret;
7560 unsigned int version, entry_count, aux_info_type, aux_info_param;
7561 2 unsigned int alloc_size = 0;
7562
7563 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7565 return ret;
7566
7567
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7568 // This can happen if we have both saio/saiz and senc atoms.
7569 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
7570 1 return 0;
7571 }
7572
7573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7574 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
7575 return AVERROR_INVALIDDATA;
7576 }
7577
7578 1 version = avio_r8(pb); /* version */
7579
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7580 aux_info_type = avio_rb32(pb);
7581 aux_info_param = avio_rb32(pb);
7582 if (sc->cenc.default_encrypted_sample) {
7583 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7584 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
7585 return 0;
7586 }
7587 if (aux_info_param != 0) {
7588 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
7589 return 0;
7590 }
7591 } else {
7592 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7593 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7594 aux_info_type == MKBETAG('c','e','n','s') ||
7595 aux_info_type == MKBETAG('c','b','c','1') ||
7596 aux_info_type == MKBETAG('c','b','c','s')) &&
7597 aux_info_param == 0) {
7598 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
7599 return AVERROR_INVALIDDATA;
7600 } else {
7601 return 0;
7602 }
7603 }
7604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7605 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7606 return 0;
7607 }
7608
7609 1 entry_count = avio_rb32(pb);
7610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
7611 return AVERROR(ENOMEM);
7612
7613
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++) {
7614
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);
7615 1 auxiliary_offsets = av_fast_realloc(
7616 1 encryption_index->auxiliary_offsets, &alloc_size,
7617 min_offsets * sizeof(*auxiliary_offsets));
7618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!auxiliary_offsets) {
7619 av_freep(&encryption_index->auxiliary_offsets);
7620 return AVERROR(ENOMEM);
7621 }
7622 1 encryption_index->auxiliary_offsets = auxiliary_offsets;
7623
7624
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (version == 0) {
7625 1 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
7626 } else {
7627 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
7628 }
7629
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (c->frag_index.current >= 0) {
7630 1 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
7631 }
7632 }
7633
7634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7635 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
7636 av_freep(&encryption_index->auxiliary_offsets);
7637 return AVERROR_INVALIDDATA;
7638 }
7639
7640 1 encryption_index->auxiliary_offsets_count = entry_count;
7641
7642
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (encryption_index->auxiliary_info_sample_count) {
7643 1 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7644 }
7645
7646 return 0;
7647 }
7648
7649 2 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7650 {
7651 AVEncryptionInitInfo *info, *old_init_info;
7652 uint8_t **key_ids;
7653 AVStream *st;
7654 const AVPacketSideData *old_side_data;
7655 uint8_t *side_data, *extra_data;
7656 size_t side_data_size;
7657 2 int ret = 0;
7658 2 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
7659
7660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
7661 return 0;
7662 2 st = c->fc->streams[c->fc->nb_streams-1];
7663
7664 2 version = avio_r8(pb); /* version */
7665 2 avio_rb24(pb); /* flags */
7666
7667 2 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
7668 /* key_id_size */ 16, /* data_size */ 0);
7669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info)
7670 return AVERROR(ENOMEM);
7671
7672
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
7673 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
7674 goto finish;
7675 }
7676
7677
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version > 0) {
7678 2 kid_count = avio_rb32(pb);
7679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
7680 ret = AVERROR(ENOMEM);
7681 goto finish;
7682 }
7683
7684
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++) {
7685 2 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
7686 2 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
7687 min_kid_count * sizeof(*key_ids));
7688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!key_ids) {
7689 ret = AVERROR(ENOMEM);
7690 goto finish;
7691 }
7692 2 info->key_ids = key_ids;
7693
7694 2 info->key_ids[i] = av_mallocz(16);
7695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info->key_ids[i]) {
7696 ret = AVERROR(ENOMEM);
7697 goto finish;
7698 }
7699 2 info->num_key_ids = i + 1;
7700
7701
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
7702 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
7703 goto finish;
7704 }
7705 }
7706
7707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
7708 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
7709 ret = AVERROR_INVALIDDATA;
7710 goto finish;
7711 }
7712 }
7713
7714 2 extra_data_size = avio_rb32(pb);
7715 2 extra_data = av_malloc(extra_data_size);
7716
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!extra_data) {
7717 ret = AVERROR(ENOMEM);
7718 goto finish;
7719 }
7720 2 ret = avio_read(pb, extra_data, extra_data_size);
7721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != extra_data_size) {
7722 av_free(extra_data);
7723
7724 if (ret >= 0)
7725 ret = AVERROR_INVALIDDATA;
7726 goto finish;
7727 }
7728
7729 2 av_freep(&info->data); // malloc(0) may still allocate something.
7730 2 info->data = extra_data;
7731 2 info->data_size = extra_data_size;
7732
7733 // If there is existing initialization data, append to the list.
7734 2 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
7735 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
7736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (old_side_data) {
7737 old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
7738 if (old_init_info) {
7739 // Append to the end of the list.
7740 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
7741 if (!cur->next) {
7742 cur->next = info;
7743 break;
7744 }
7745 }
7746 info = old_init_info;
7747 } else {
7748 // Assume existing side-data will be valid, so the only error we could get is OOM.
7749 ret = AVERROR(ENOMEM);
7750 goto finish;
7751 }
7752 }
7753
7754 2 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
7755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!side_data) {
7756 ret = AVERROR(ENOMEM);
7757 goto finish;
7758 }
7759
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
7760 2 &st->codecpar->nb_coded_side_data,
7761 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
7762 side_data, side_data_size, 0))
7763 av_free(side_data);
7764
7765 2 finish:
7766 2 av_encryption_init_info_free(info);
7767 2 return ret;
7768 }
7769
7770 3 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7771 {
7772 AVStream *st;
7773 MOVStreamContext *sc;
7774
7775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7776 return 0;
7777 3 st = c->fc->streams[c->fc->nb_streams-1];
7778 3 sc = st->priv_data;
7779
7780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7781 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
7782 return AVERROR_PATCHWELCOME;
7783 }
7784
7785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8)
7786 return AVERROR_INVALIDDATA;
7787
7788 3 avio_rb32(pb); /* version and flags */
7789
7790
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->cenc.default_encrypted_sample) {
7791 3 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7793 return AVERROR(ENOMEM);
7794 }
7795 }
7796
7797 3 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
7798 3 return 0;
7799 }
7800
7801 3 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7802 {
7803 AVStream *st;
7804 MOVStreamContext *sc;
7805 unsigned int version, pattern, is_protected, iv_size;
7806
7807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7808 return 0;
7809 3 st = c->fc->streams[c->fc->nb_streams-1];
7810 3 sc = st->priv_data;
7811
7812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7813 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
7814 return AVERROR_PATCHWELCOME;
7815 }
7816
7817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7818 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7819 if (!sc->cenc.default_encrypted_sample) {
7820 return AVERROR(ENOMEM);
7821 }
7822 }
7823
7824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 20)
7825 return AVERROR_INVALIDDATA;
7826
7827 3 version = avio_r8(pb); /* version */
7828 3 avio_rb24(pb); /* flags */
7829
7830 3 avio_r8(pb); /* reserved */
7831 3 pattern = avio_r8(pb);
7832
7833
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (version > 0) {
7834 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
7835 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
7836 }
7837
7838 3 is_protected = avio_r8(pb);
7839
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) {
7840 // The whole stream should be by-default encrypted.
7841 3 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
7842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.encryption_index)
7843 return AVERROR(ENOMEM);
7844 }
7845 3 sc->cenc.per_sample_iv_size = avio_r8(pb);
7846
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 &&
7847 sc->cenc.per_sample_iv_size != 16) {
7848 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
7849 return AVERROR_INVALIDDATA;
7850 }
7851
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) {
7852 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
7853 return AVERROR_INVALIDDATA;
7854 }
7855
7856
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) {
7857 1 iv_size = avio_r8(pb);
7858
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) {
7859 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
7860 return AVERROR_INVALIDDATA;
7861 }
7862
7863
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) {
7864 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
7865 return AVERROR_INVALIDDATA;
7866 }
7867 }
7868
7869 3 return 0;
7870 }
7871
7872 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7873 {
7874 AVStream *st;
7875 int last, type, size, ret;
7876 uint8_t buf[4];
7877
7878 if (c->fc->nb_streams < 1)
7879 return 0;
7880 st = c->fc->streams[c->fc->nb_streams-1];
7881
7882 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
7883 return AVERROR_INVALIDDATA;
7884
7885 /* Check FlacSpecificBox version. */
7886 if (avio_r8(pb) != 0)
7887 return AVERROR_INVALIDDATA;
7888
7889 avio_rb24(pb); /* Flags */
7890
7891 if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
7892 av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
7893 return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
7894 }
7895 flac_parse_block_header(buf, &last, &type, &size);
7896
7897 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
7898 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
7899 return AVERROR_INVALIDDATA;
7900 }
7901
7902 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
7903 if (ret < 0)
7904 return ret;
7905
7906 if (!last)
7907 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
7908
7909 return 0;
7910 }
7911
7912 146 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
7913 {
7914 int i, ret;
7915 int bytes_of_protected_data;
7916
7917
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 143 times.
146 if (!sc->cenc.aes_ctr) {
7918 /* initialize the cipher */
7919 3 sc->cenc.aes_ctr = av_aes_ctr_alloc();
7920
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.aes_ctr) {
7921 return AVERROR(ENOMEM);
7922 }
7923
7924 3 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
7925
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
7926 return ret;
7927 }
7928 }
7929
7930 146 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
7931
7932
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!sample->subsample_count) {
7933 /* decrypt the whole packet */
7934 48 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
7935 48 return 0;
7936 }
7937
7938
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 98 times.
196 for (i = 0; i < sample->subsample_count; i++) {
7939
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) {
7940 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
7941 return AVERROR_INVALIDDATA;
7942 }
7943
7944 /* skip the clear bytes */
7945 98 input += sample->subsamples[i].bytes_of_clear_data;
7946 98 size -= sample->subsamples[i].bytes_of_clear_data;
7947
7948 /* decrypt the encrypted bytes */
7949
7950 98 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
7951 98 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
7952
7953 98 input += bytes_of_protected_data;
7954 98 size -= bytes_of_protected_data;
7955 }
7956
7957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (size > 0) {
7958 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
7959 return AVERROR_INVALIDDATA;
7960 }
7961
7962 98 return 0;
7963 }
7964
7965 static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
7966 {
7967 int i, ret;
7968 int num_of_encrypted_blocks;
7969 uint8_t iv[16];
7970
7971 if (!sc->cenc.aes_ctx) {
7972 /* initialize the cipher */
7973 sc->cenc.aes_ctx = av_aes_alloc();
7974 if (!sc->cenc.aes_ctx) {
7975 return AVERROR(ENOMEM);
7976 }
7977
7978 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
7979 if (ret < 0) {
7980 return ret;
7981 }
7982 }
7983
7984 memcpy(iv, sample->iv, 16);
7985
7986 /* whole-block full sample encryption */
7987 if (!sample->subsample_count) {
7988 /* decrypt the whole packet */
7989 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
7990 return 0;
7991 }
7992
7993 for (i = 0; i < sample->subsample_count; i++) {
7994 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
7995 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
7996 return AVERROR_INVALIDDATA;
7997 }
7998
7999 if (sample->subsamples[i].bytes_of_protected_data % 16) {
8000 av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8001 return AVERROR_INVALIDDATA;
8002 }
8003
8004 /* skip the clear bytes */
8005 input += sample->subsamples[i].bytes_of_clear_data;
8006 size -= sample->subsamples[i].bytes_of_clear_data;
8007
8008 /* decrypt the encrypted bytes */
8009 num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8010 if (num_of_encrypted_blocks > 0) {
8011 av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8012 }
8013 input += sample->subsamples[i].bytes_of_protected_data;
8014 size -= sample->subsamples[i].bytes_of_protected_data;
8015 }
8016
8017 if (size > 0) {
8018 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8019 return AVERROR_INVALIDDATA;
8020 }
8021
8022 return 0;
8023 }
8024
8025 static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8026 {
8027 int i, ret, rem_bytes;
8028 uint8_t *data;
8029
8030 if (!sc->cenc.aes_ctr) {
8031 /* initialize the cipher */
8032 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8033 if (!sc->cenc.aes_ctr) {
8034 return AVERROR(ENOMEM);
8035 }
8036
8037 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
8038 if (ret < 0) {
8039 return ret;
8040 }
8041 }
8042
8043 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8044
8045 /* whole-block full sample encryption */
8046 if (!sample->subsample_count) {
8047 /* decrypt the whole packet */
8048 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8049 return 0;
8050 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8051 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8052 return AVERROR_INVALIDDATA;
8053 }
8054
8055 for (i = 0; i < sample->subsample_count; i++) {
8056 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8057 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8058 return AVERROR_INVALIDDATA;
8059 }
8060
8061 /* skip the clear bytes */
8062 input += sample->subsamples[i].bytes_of_clear_data;
8063 size -= sample->subsamples[i].bytes_of_clear_data;
8064
8065 /* decrypt the encrypted bytes */
8066 data = input;
8067 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8068 while (rem_bytes > 0) {
8069 if (rem_bytes < 16*sample->crypt_byte_block) {
8070 break;
8071 }
8072 av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8073 data += 16*sample->crypt_byte_block;
8074 rem_bytes -= 16*sample->crypt_byte_block;
8075 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8076 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8077 }
8078 input += sample->subsamples[i].bytes_of_protected_data;
8079 size -= sample->subsamples[i].bytes_of_protected_data;
8080 }
8081
8082 if (size > 0) {
8083 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8084 return AVERROR_INVALIDDATA;
8085 }
8086
8087 return 0;
8088 }
8089
8090 static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8091 {
8092 int i, ret, rem_bytes;
8093 uint8_t iv[16];
8094 uint8_t *data;
8095
8096 if (!sc->cenc.aes_ctx) {
8097 /* initialize the cipher */
8098 sc->cenc.aes_ctx = av_aes_alloc();
8099 if (!sc->cenc.aes_ctx) {
8100 return AVERROR(ENOMEM);
8101 }
8102
8103 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8104 if (ret < 0) {
8105 return ret;
8106 }
8107 }
8108
8109 /* whole-block full sample encryption */
8110 if (!sample->subsample_count) {
8111 /* decrypt the whole packet */
8112 memcpy(iv, sample->iv, 16);
8113 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8114 return 0;
8115 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8116 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8117 return AVERROR_INVALIDDATA;
8118 }
8119
8120 for (i = 0; i < sample->subsample_count; i++) {
8121 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8122 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8123 return AVERROR_INVALIDDATA;
8124 }
8125
8126 /* skip the clear bytes */
8127 input += sample->subsamples[i].bytes_of_clear_data;
8128 size -= sample->subsamples[i].bytes_of_clear_data;
8129
8130 /* decrypt the encrypted bytes */
8131 memcpy(iv, sample->iv, 16);
8132 data = input;
8133 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8134 while (rem_bytes > 0) {
8135 if (rem_bytes < 16*sample->crypt_byte_block) {
8136 break;
8137 }
8138 av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8139 data += 16*sample->crypt_byte_block;
8140 rem_bytes -= 16*sample->crypt_byte_block;
8141 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8142 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8143 }
8144 input += sample->subsamples[i].bytes_of_protected_data;
8145 size -= sample->subsamples[i].bytes_of_protected_data;
8146 }
8147
8148 if (size > 0) {
8149 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8150 return AVERROR_INVALIDDATA;
8151 }
8152
8153 return 0;
8154 }
8155
8156 146 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8157 {
8158
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) {
8159 146 return cenc_scheme_decrypt(c, sc, sample, input, size);
8160 } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8161 return cbc1_scheme_decrypt(c, sc, sample, input, size);
8162 } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8163 return cens_scheme_decrypt(c, sc, sample, input, size);
8164 } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8165 return cbcs_scheme_decrypt(c, sc, sample, input, size);
8166 } else {
8167 av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8168 return AVERROR_INVALIDDATA;
8169 }
8170 }
8171
8172 96496 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8173 {
8174 96496 int current = frag_index->current;
8175
8176
2/2
✓ Branch 0 taken 95835 times.
✓ Branch 1 taken 661 times.
96496 if (!frag_index->nb_items)
8177 95835 return NULL;
8178
8179 // Check frag_index->current is the right one for pkt. It can out of sync.
8180
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) {
8181
2/2
✓ Branch 0 taken 639 times.
✓ Branch 1 taken 22 times.
661 if (frag_index->item[current].moof_offset < pkt->pos &&
8182
2/2
✓ Branch 0 taken 413 times.
✓ Branch 1 taken 226 times.
639 (current + 1 == frag_index->nb_items ||
8183
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 25 times.
413 frag_index->item[current + 1].moof_offset > pkt->pos))
8184 614 return get_frag_stream_info(frag_index, current, id);
8185 }
8186
8187
8188
2/2
✓ Branch 0 taken 3955 times.
✓ Branch 1 taken 4 times.
3959 for (int i = 0; i < frag_index->nb_items; i++) {
8189
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 3912 times.
3955 if (frag_index->item[i].moof_offset > pkt->pos)
8190 43 break;
8191 3912 current = i;
8192 }
8193 47 frag_index->current = current;
8194 47 return get_frag_stream_info(frag_index, current, id);
8195 }
8196
8197 96496 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8198 {
8199 MOVFragmentStreamInfo *frag_stream_info;
8200 MOVEncryptionIndex *encryption_index;
8201 AVEncryptionInfo *encrypted_sample;
8202 int encrypted_index, ret;
8203
8204 96496 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8205 96496 encrypted_index = current_index;
8206 96496 encryption_index = NULL;
8207
2/2
✓ Branch 0 taken 661 times.
✓ Branch 1 taken 95835 times.
96496 if (frag_stream_info) {
8208 // Note this only supports encryption info in the first sample descriptor.
8209
2/2
✓ Branch 0 taken 637 times.
✓ Branch 1 taken 24 times.
661 if (frag_stream_info->stsd_id == 1) {
8210
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 613 times.
637 if (frag_stream_info->encryption_index) {
8211 24 encrypted_index = current_index - frag_stream_info->index_base;
8212 24 encryption_index = frag_stream_info->encryption_index;
8213 } else {
8214 613 encryption_index = sc->cenc.encryption_index;
8215 }
8216 }
8217 } else {
8218 95835 encryption_index = sc->cenc.encryption_index;
8219 }
8220
8221
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 96350 times.
96496 if (encryption_index) {
8222
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_info_sample_count &&
8223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8224 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8225 return AVERROR_INVALIDDATA;
8226 }
8227
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_offsets_count &&
8228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8229 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8230 return AVERROR_INVALIDDATA;
8231 }
8232
8233 146 encrypted_sample = NULL;
8234
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!encryption_index->nb_encrypted_samples) {
8235 // Full-sample encryption with default settings.
8236 48 encrypted_sample = sc->cenc.default_encrypted_sample;
8237
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) {
8238 // Per-sample setting override.
8239 98 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (!encrypted_sample) {
8241 encrypted_sample = sc->cenc.default_encrypted_sample;
8242 }
8243 }
8244
8245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (!encrypted_sample) {
8246 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8247 return AVERROR_INVALIDDATA;
8248 }
8249
8250
1/2
✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
146 if (mov->decryption_key) {
8251 146 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
8252 } else {
8253 size_t size;
8254 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
8255 if (!side_data)
8256 return AVERROR(ENOMEM);
8257 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
8258 if (ret < 0)
8259 av_free(side_data);
8260 return ret;
8261 }
8262 }
8263
8264 96350 return 0;
8265 }
8266
8267 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8268 {
8269 const int OPUS_SEEK_PREROLL_MS = 80;
8270 int ret;
8271 AVStream *st;
8272 size_t size;
8273 uint16_t pre_skip;
8274
8275 if (c->fc->nb_streams < 1)
8276 return 0;
8277 st = c->fc->streams[c->fc->nb_streams-1];
8278
8279 if ((uint64_t)atom.size > (1<<30) || atom.size < 11)
8280 return AVERROR_INVALIDDATA;
8281
8282 /* Check OpusSpecificBox version. */
8283 if (avio_r8(pb) != 0) {
8284 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
8285 return AVERROR_INVALIDDATA;
8286 }
8287
8288 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
8289 size = atom.size + 8;
8290
8291 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
8292 return ret;
8293
8294 AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
8295 AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
8296 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
8297 avio_read(pb, st->codecpar->extradata + 9, size - 9);
8298
8299 /* OpusSpecificBox is stored in big-endian, but OpusHead is
8300 little-endian; aside from the preceeding magic and version they're
8301 otherwise currently identical. Data after output gain at offset 16
8302 doesn't need to be bytewapped. */
8303 pre_skip = AV_RB16A(st->codecpar->extradata + 10);
8304 AV_WL16A(st->codecpar->extradata + 10, pre_skip);
8305 AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
8306 AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
8307
8308 st->codecpar->initial_padding = pre_skip;
8309 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
8310 (AVRational){1, 1000},
8311 (AVRational){1, 48000});
8312
8313 return 0;
8314 }
8315
8316 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8317 {
8318 AVStream *st;
8319 unsigned format_info;
8320 int channel_assignment, channel_assignment1, channel_assignment2;
8321 int ratebits;
8322 uint64_t chmask;
8323
8324 if (c->fc->nb_streams < 1)
8325 return 0;
8326 st = c->fc->streams[c->fc->nb_streams-1];
8327
8328 if (atom.size < 10)
8329 return AVERROR_INVALIDDATA;
8330
8331 format_info = avio_rb32(pb);
8332
8333 ratebits = (format_info >> 28) & 0xF;
8334 channel_assignment1 = (format_info >> 15) & 0x1F;
8335 channel_assignment2 = format_info & 0x1FFF;
8336 if (channel_assignment2)
8337 channel_assignment = channel_assignment2;
8338 else
8339 channel_assignment = channel_assignment1;
8340
8341 st->codecpar->frame_size = 40 << (ratebits & 0x7);
8342 st->codecpar->sample_rate = mlp_samplerate(ratebits);
8343
8344 av_channel_layout_uninit(&st->codecpar->ch_layout);
8345 chmask = truehd_layout(channel_assignment);
8346 av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
8347
8348 return 0;
8349 }
8350
8351 4 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8352 {
8353 AVStream *st;
8354 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
8355 int ret;
8356 4 int64_t read_size = atom.size;
8357
8358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8359 return 0;
8360 4 st = c->fc->streams[c->fc->nb_streams-1];
8361
8362 // At most 24 bytes
8363 4 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
8364
8365
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
8366 return ret;
8367
8368 4 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
8369 }
8370
8371 3 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8372 {
8373 AVStream *st;
8374 uint8_t *buf;
8375 int ret, old_size, num_arrays;
8376
8377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
8378 return 0;
8379 3 st = c->fc->streams[c->fc->nb_streams-1];
8380
8381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata_size)
8382 // TODO: handle lhvC when present before hvcC
8383 return 0;
8384
8385
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)
8386 return AVERROR_INVALIDDATA;
8387
8388 3 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
8389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!buf)
8390 return AVERROR(ENOMEM);
8391 3 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8392
8393 3 ret = ffio_read_size(pb, buf, atom.size);
8394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8395 av_free(buf);
8396 av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
8397 return 0;
8398 }
8399
8400 3 num_arrays = buf[5];
8401 3 old_size = st->codecpar->extradata_size;
8402 3 atom.size -= 8 /* account for mov_realloc_extradata offseting */
8403 + 6 /* lhvC bytes before the arrays*/;
8404
8405 3 ret = mov_realloc_extradata(st->codecpar, atom);
8406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8407 av_free(buf);
8408 return ret;
8409 }
8410
8411 3 st->codecpar->extradata[22] += num_arrays;
8412 3 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
8413
8414 3 st->disposition |= AV_DISPOSITION_MULTILAYER;
8415
8416 3 av_free(buf);
8417 3 return 0;
8418 }
8419
8420 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8421 {
8422 4 AVFormatContext *ctx = c->fc;
8423 4 AVStream *st = NULL;
8424 AVBPrint scheme_buf, value_buf;
8425 4 int64_t scheme_str_len = 0, value_str_len = 0;
8426 4 int version, flags, ret = AVERROR_BUG;
8427 4 int64_t size = atom.size;
8428
8429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
8430 // 4 bytes for version + flags, 2x 1 byte for null
8431 return AVERROR_INVALIDDATA;
8432
8433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8434 return 0;
8435 4 st = c->fc->streams[c->fc->nb_streams-1];
8436
8437 4 version = avio_r8(pb);
8438 4 flags = avio_rb24(pb);
8439 4 size -= 4;
8440
8441
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) {
8442 av_log(ctx, AV_LOG_ERROR,
8443 "Unsupported 'kind' box with version %d, flags: %x",
8444 version, flags);
8445 return AVERROR_INVALIDDATA;
8446 }
8447
8448 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8449 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8450
8451
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,
8452 size)) < 0) {
8453 ret = scheme_str_len;
8454 goto cleanup;
8455 }
8456
8457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
8458 // we need to have another string, even if nullptr.
8459 // we check with + 1 since we expect that if size was not hit,
8460 // an additional null was read.
8461 ret = AVERROR_INVALIDDATA;
8462 goto cleanup;
8463 }
8464
8465 4 size -= scheme_str_len + 1;
8466
8467
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,
8468 size)) < 0) {
8469 ret = value_str_len;
8470 goto cleanup;
8471 }
8472
8473
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
8474 // in case of no trailing null, box is not valid.
8475 ret = AVERROR_INVALIDDATA;
8476 goto cleanup;
8477 }
8478
8479 4 av_log(ctx, AV_LOG_TRACE,
8480 "%s stream %d KindBox(scheme: %s, value: %s)\n",
8481 4 av_get_media_type_string(st->codecpar->codec_type),
8482 st->index,
8483 scheme_buf.str, value_buf.str);
8484
8485
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++) {
8486 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
8487
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
8488 continue;
8489
8490
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
8491 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
8492
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
8493 16 continue;
8494
8495 4 st->disposition |= value_map.disposition;
8496 }
8497 }
8498
8499 4 ret = 0;
8500
8501 4 cleanup:
8502
8503 4 av_bprint_finalize(&scheme_buf, NULL);
8504 4 av_bprint_finalize(&value_buf, NULL);
8505
8506 4 return ret;
8507 }
8508
8509 static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8510 {
8511 AVStream *st;
8512 AVChannelLayout ch_layout = { 0 };
8513 int ret, i, version, type;
8514 int ambisonic_order, channel_order, normalization, channel_count;
8515 int ambi_channels, non_diegetic_channels;
8516
8517 if (c->fc->nb_streams < 1)
8518 return 0;
8519
8520 st = c->fc->streams[c->fc->nb_streams - 1];
8521
8522 if (atom.size < 16) {
8523 av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
8524 return AVERROR_INVALIDDATA;
8525 }
8526
8527 version = avio_r8(pb);
8528 if (version) {
8529 av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
8530 return 0;
8531 }
8532
8533 type = avio_r8(pb);
8534 if (type & 0x7f) {
8535 av_log(c->fc, AV_LOG_WARNING,
8536 "Unsupported ambisonic type %d\n", type & 0x7f);
8537 return 0;
8538 }
8539 non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
8540
8541 ambisonic_order = avio_rb32(pb);
8542
8543 channel_order = avio_r8(pb);
8544 if (channel_order) {
8545 av_log(c->fc, AV_LOG_WARNING,
8546 "Unsupported channel_order %d\n", channel_order);
8547 return 0;
8548 }
8549
8550 normalization = avio_r8(pb);
8551 if (normalization) {
8552 av_log(c->fc, AV_LOG_WARNING,
8553 "Unsupported normalization %d\n", normalization);
8554 return 0;
8555 }
8556
8557 channel_count = avio_rb32(pb);
8558 if (ambisonic_order < 0 || ambisonic_order > 31 ||
8559 channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
8560 non_diegetic_channels)) {
8561 av_log(c->fc, AV_LOG_ERROR,
8562 "Invalid number of channels (%d / %d)\n",
8563 channel_count, ambisonic_order);
8564 return 0;
8565 }
8566 ambi_channels = channel_count - non_diegetic_channels;
8567
8568 ret = av_channel_layout_custom_init(&ch_layout, channel_count);
8569 if (ret < 0)
8570 return 0;
8571
8572 for (i = 0; i < channel_count; i++) {
8573 unsigned channel = avio_rb32(pb);
8574
8575 if (channel >= channel_count) {
8576 av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
8577 channel, ambisonic_order);
8578 av_channel_layout_uninit(&ch_layout);
8579 return 0;
8580 }
8581 if (channel >= ambi_channels)
8582 ch_layout.u.map[i].id = channel - ambi_channels;
8583 else
8584 ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
8585 }
8586
8587 ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
8588 if (ret < 0) {
8589 av_channel_layout_uninit(&ch_layout);
8590 return 0;
8591 }
8592
8593 av_channel_layout_uninit(&st->codecpar->ch_layout);
8594 st->codecpar->ch_layout = ch_layout;
8595
8596 return 0;
8597 }
8598
8599 static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8600 {
8601 AVStream *st;
8602 int version;
8603
8604 if (c->fc->nb_streams < 1)
8605 return 0;
8606
8607 st = c->fc->streams[c->fc->nb_streams - 1];
8608
8609 if (atom.size < 5) {
8610 av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
8611 return AVERROR_INVALIDDATA;
8612 }
8613
8614 version = avio_r8(pb);
8615 if (version) {
8616 av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
8617 return 0;
8618 }
8619
8620 st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
8621
8622 return 0;
8623 }
8624
8625 90 static int rb_size(AVIOContext *pb, int64_t *value, int size)
8626 {
8627
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 89 times.
90 if (size == 0)
8628 1 *value = 0;
8629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
89 else if (size == 1)
8630 *value = avio_r8(pb);
8631
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
89 else if (size == 2)
8632 *value = avio_rb16(pb);
8633
1/2
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
89 else if (size == 4)
8634 89 *value = avio_rb32(pb);
8635 else if (size == 8) {
8636 *value = avio_rb64(pb);
8637 if (*value < 0)
8638 return -1;
8639 } else
8640 return -1;
8641 90 return size;
8642 }
8643
8644 12 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8645 {
8646 12 avio_rb32(pb); // version & flags.
8647 12 c->primary_item_id = avio_rb16(pb);
8648 12 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
8649 12 return atom.size;
8650 }
8651
8652 6 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8653 {
8654 6 c->idat_offset = avio_tell(pb);
8655 6 return 0;
8656 }
8657
8658 12 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8659 {
8660 HEIFItem **heif_item;
8661 int version, offset_size, length_size, base_offset_size, index_size;
8662 int item_count, extent_count;
8663 int64_t base_offset, extent_offset, extent_length;
8664 uint8_t value;
8665
8666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->found_iloc) {
8667 av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
8668 return 0;
8669 }
8670
8671 12 version = avio_r8(pb);
8672 12 avio_rb24(pb); // flags.
8673
8674 12 value = avio_r8(pb);
8675 12 offset_size = (value >> 4) & 0xF;
8676 12 length_size = value & 0xF;
8677 12 value = avio_r8(pb);
8678 12 base_offset_size = (value >> 4) & 0xF;
8679
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 index_size = !version ? 0 : (value & 0xF);
8680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (index_size) {
8681 avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
8682 return AVERROR_PATCHWELCOME;
8683 }
8684
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8685
8686 12 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
8687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!heif_item)
8688 return AVERROR(ENOMEM);
8689 12 c->heif_item = heif_item;
8690
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (item_count > c->nb_heif_item)
8691 12 memset(&c->heif_item[c->nb_heif_item], 0,
8692 12 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
8693 12 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
8694
8695 12 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
8696
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 for (int i = 0; i < item_count; i++) {
8697 30 HEIFItem *item = c->heif_item[i];
8698
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8699
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
8700
8701
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (avio_feof(pb))
8702 return AVERROR_INVALIDDATA;
8703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (offset_type > 1) {
8704 avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
8705 return AVERROR_PATCHWELCOME;
8706 }
8707
8708 30 avio_rb16(pb); // data_reference_index.
8709
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (rb_size(pb, &base_offset, base_offset_size) < 0)
8710 return AVERROR_INVALIDDATA;
8711 30 extent_count = avio_rb16(pb);
8712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (extent_count > 1) {
8713 // For still AVIF images, we only support one extent item.
8714 avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
8715 return AVERROR_PATCHWELCOME;
8716 }
8717
8718
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 ||
8719 30 rb_size(pb, &extent_length, length_size) < 0 ||
8720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 base_offset > INT64_MAX - extent_offset)
8721 return AVERROR_INVALIDDATA;
8722
8723
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if (!item)
8724 30 item = c->heif_item[i] = av_mallocz(sizeof(*item));
8725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!item)
8726 return AVERROR(ENOMEM);
8727
8728 30 item->item_id = item_id;
8729
8730
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 24 times.
30 if (offset_type == 1)
8731 6 item->is_idat_relative = 1;
8732 30 item->extent_length = extent_length;
8733 30 item->extent_offset = base_offset + extent_offset;
8734 30 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, offset_type %d, "
8735 "extent_offset %"PRId64", extent_length %"PRId64"\n",
8736 i, offset_type, item->extent_offset, item->extent_length);
8737 }
8738
8739 12 c->found_iloc = 1;
8740 12 return atom.size;
8741 }
8742
8743 30 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom, int idx)
8744 {
8745 HEIFItem *item;
8746 AVBPrint item_name;
8747 30 int64_t size = atom.size;
8748 uint32_t item_type;
8749 int item_id;
8750 int version, ret;
8751
8752 30 version = avio_r8(pb);
8753 30 avio_rb24(pb); // flags.
8754 30 size -= 4;
8755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (size < 0)
8756 return AVERROR_INVALIDDATA;
8757
8758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (version < 2) {
8759 avpriv_report_missing_feature(c->fc, "infe version < 2");
8760 avio_skip(pb, size);
8761 return 1;
8762 }
8763
8764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
8765 30 avio_rb16(pb); // item_protection_index
8766 30 item_type = avio_rl32(pb);
8767 30 size -= 8;
8768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (size < 1)
8769 return AVERROR_INVALIDDATA;
8770
8771 30 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
8772 30 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
8773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (ret < 0) {
8774 av_bprint_finalize(&item_name, NULL);
8775 return ret;
8776 }
8777
8778 30 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
8779 30 item_id, av_fourcc2str(item_type), item_name.str);
8780
8781 30 size -= ret + 1;
8782
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (size > 0)
8783 avio_skip(pb, size);
8784
8785 30 item = c->heif_item[idx];
8786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!item)
8787 item = c->heif_item[idx] = av_mallocz(sizeof(*item));
8788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!item)
8789 return AVERROR(ENOMEM);
8790
8791
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 1 times.
30 if (ret)
8792 29 av_bprint_finalize(&item_name, &c->heif_item[idx]->name);
8793 30 c->heif_item[idx]->item_id = item_id;
8794 30 c->heif_item[idx]->type = item_type;
8795
8796
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 7 times.
30 switch (item_type) {
8797 23 case MKTAG('a','v','0','1'):
8798 case MKTAG('h','v','c','1'):
8799 23 ret = heif_add_stream(c, c->heif_item[idx]);
8800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (ret < 0)
8801 return ret;
8802 23 break;
8803 }
8804
8805 30 return 0;
8806 }
8807
8808 12 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8809 {
8810 HEIFItem **heif_item;
8811 int entry_count;
8812 12 int version, got_stream = 0, ret, i;
8813
8814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->found_iinf) {
8815 av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
8816 return 0;
8817 }
8818
8819 12 version = avio_r8(pb);
8820 12 avio_rb24(pb); // flags.
8821
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
8822
8823 12 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
8824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!heif_item)
8825 return AVERROR(ENOMEM);
8826 12 c->heif_item = heif_item;
8827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (entry_count > c->nb_heif_item)
8828 memset(&c->heif_item[c->nb_heif_item], 0,
8829 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
8830 12 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
8831
8832
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 for (i = 0; i < entry_count; i++) {
8833 MOVAtom infe;
8834
8835
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (avio_feof(pb)) {
8836 ret = AVERROR_INVALIDDATA;
8837 goto fail;
8838 }
8839 30 infe.size = avio_rb32(pb) - 8;
8840 30 infe.type = avio_rl32(pb);
8841 30 ret = mov_read_infe(c, pb, infe, i);
8842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (ret < 0)
8843 goto fail;
8844
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if (!ret)
8845 30 got_stream = 1;
8846 }
8847
8848 12 c->found_iinf = got_stream;
8849 12 return 0;
8850 fail:
8851 for (; i >= 0; i--) {
8852 HEIFItem *item = c->heif_item[i];
8853
8854 if (!item)
8855 continue;
8856
8857 av_freep(&item->name);
8858 if (!item->st)
8859 continue;
8860
8861 mov_free_stream_context(c->fc, item->st);
8862 ff_remove_stream(c->fc, item->st);
8863 item->st = NULL;
8864 }
8865 return ret;
8866 }
8867
8868 6 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
8869 {
8870 6 HEIFItem *item = NULL;
8871 HEIFGrid *grid;
8872 int entries, i;
8873
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8874
8875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 for (int i = 0; i < c->nb_heif_grid; i++) {
8876 if (c->heif_grid[i].item->item_id == from_item_id) {
8877 av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
8878 "referencing the same Derived Image item\n");
8879 return AVERROR_INVALIDDATA;
8880 }
8881 }
8882
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 for (int i = 0; i < c->nb_heif_item; i++) {
8883
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)
8884 14 continue;
8885 6 item = c->heif_item[i];
8886
8887
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 switch (item->type) {
8888 6 case MKTAG('g','r','i','d'):
8889 case MKTAG('i','o','v','l'):
8890 6 break;
8891 default:
8892 avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
8893 av_fourcc2str(item->type));
8894 return 0;
8895 }
8896 6 break;
8897 }
8898
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!item) {
8899 av_log(c->fc, AV_LOG_ERROR, "Missing grid information\n");
8900 return AVERROR_INVALIDDATA;
8901 }
8902
8903 6 grid = av_realloc_array(c->heif_grid, c->nb_heif_grid + 1U,
8904 sizeof(*c->heif_grid));
8905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!grid)
8906 return AVERROR(ENOMEM);
8907 6 c->heif_grid = grid;
8908 6 grid = &grid[c->nb_heif_grid++];
8909
8910 6 entries = avio_rb16(pb);
8911 6 grid->tile_id_list = av_malloc_array(entries, sizeof(*grid->tile_id_list));
8912 6 grid->tile_item_list = av_calloc(entries, sizeof(*grid->tile_item_list));
8913
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (!grid->tile_id_list || !grid->tile_item_list)
8914 return AVERROR(ENOMEM);
8915 /* 'to' item ids */
8916
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (i = 0; i < entries; i++)
8917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 grid->tile_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
8918 6 grid->nb_tiles = entries;
8919 6 grid->item = item;
8920
8921 6 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
8922 from_item_id, entries);
8923
8924 6 return 0;
8925 }
8926
8927 2 static int mov_read_iref_thmb(MOVContext *c, AVIOContext *pb, int version)
8928 {
8929 int entries;
8930
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);
8931
8932 2 entries = avio_rb16(pb);
8933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (entries > 1) {
8934 avpriv_request_sample(c->fc, "thmb in iref referencing several items");
8935 return AVERROR_PATCHWELCOME;
8936 }
8937 /* 'to' item ids */
8938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 to_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8939
8940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (to_item_id != c->primary_item_id)
8941 return 0;
8942
8943 2 c->thmb_item_id = from_item_id;
8944
8945 2 av_log(c->fc, AV_LOG_TRACE, "thmb: from_item_id %d, entries %d\n",
8946 from_item_id, entries);
8947
8948 2 return 0;
8949 }
8950
8951 8 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8952 {
8953 8 int version = avio_r8(pb);
8954 8 avio_rb24(pb); // flags
8955 8 atom.size -= 4;
8956
8957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (version > 1) {
8958 av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
8959 return 0;
8960 }
8961
8962
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 while (atom.size) {
8963 8 uint32_t type, size = avio_rb32(pb);
8964 8 int64_t next = avio_tell(pb);
8965
8966
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)
8967 return AVERROR_INVALIDDATA;
8968
8969 8 next += size - 4;
8970 8 type = avio_rl32(pb);
8971
2/3
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
8 switch (type) {
8972 6 case MKTAG('d','i','m','g'):
8973 6 mov_read_iref_dimg(c, pb, version);
8974 8 break;
8975 2 case MKTAG('t','h','m','b'):
8976 2 mov_read_iref_thmb(c, pb, version);
8977 2 break;
8978 default:
8979 av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
8980 av_fourcc2str(type), size);
8981 }
8982
8983 8 atom.size -= size;
8984 8 avio_seek(pb, next, SEEK_SET);
8985 }
8986 8 return 0;
8987 }
8988
8989 29 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8990 {
8991 HEIFItem *item;
8992 uint32_t width, height;
8993
8994 29 avio_r8(pb); /* version */
8995 29 avio_rb24(pb); /* flags */
8996 29 width = avio_rb32(pb);
8997 29 height = avio_rb32(pb);
8998
8999 29 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %u, height %u\n",
9000 c->cur_item_id, width, height);
9001
9002 29 item = heif_cur_item(c);
9003
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (item) {
9004 29 item->width = width;
9005 29 item->height = height;
9006 }
9007
9008 29 return 0;
9009 }
9010
9011 4 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9012 {
9013 HEIFItem *item;
9014 int angle;
9015
9016 4 angle = avio_r8(pb) & 0x3;
9017
9018 4 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
9019 c->cur_item_id, angle);
9020
9021 4 item = heif_cur_item(c);
9022
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item) {
9023 // angle * 90 specifies the angle (in anti-clockwise direction)
9024 // in units of degrees.
9025 4 item->rotation = angle * 90;
9026 }
9027
9028 4 return 0;
9029 }
9030
9031 4 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9032 {
9033 HEIFItem *item;
9034 int axis;
9035
9036 4 axis = avio_r8(pb) & 0x1;
9037
9038 4 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
9039 c->cur_item_id, axis);
9040
9041 4 item = heif_cur_item(c);
9042
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item) {
9043 4 item->hflip = axis;
9044 4 item->vflip = !axis;
9045 }
9046
9047 4 return 0;
9048 }
9049
9050 12 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9051 {
9052 typedef struct MOVAtoms {
9053 FFIOContext b;
9054 uint32_t type;
9055 int64_t size;
9056 uint8_t *data;
9057 } MOVAtoms;
9058 12 MOVAtoms *atoms = NULL;
9059 MOVAtom a;
9060 unsigned count;
9061 12 int nb_atoms = 0;
9062 int version, flags;
9063 int ret;
9064
9065 12 a.size = avio_rb32(pb);
9066 12 a.type = avio_rl32(pb);
9067
9068
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'))
9069 return AVERROR_INVALIDDATA;
9070
9071 12 a.size -= 8;
9072
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 12 times.
61 while (a.size >= 8) {
9073 49 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
9074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if (!ref) {
9075 ret = AVERROR(ENOMEM);
9076 goto fail;
9077 }
9078 49 ref->data = NULL;
9079 49 ref->size = avio_rb32(pb);
9080 49 ref->type = avio_rl32(pb);
9081
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)
9082 break;
9083 49 ref->data = av_malloc(ref->size);
9084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if (!ref->data) {
9085 ret = AVERROR_INVALIDDATA;
9086 goto fail;
9087 }
9088 49 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
9089 49 avio_seek(pb, -8, SEEK_CUR);
9090
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
49 if (avio_read(pb, ref->data, ref->size) != ref->size) {
9091 ret = AVERROR_INVALIDDATA;
9092 goto fail;
9093 }
9094 49 ffio_init_read_context(&ref->b, ref->data, ref->size);
9095 49 a.size -= ref->size;
9096 }
9097
9098
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (a.size) {
9099 ret = AVERROR_INVALIDDATA;
9100 goto fail;
9101 }
9102
9103 12 a.size = avio_rb32(pb);
9104 12 a.type = avio_rl32(pb);
9105
9106
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')) {
9107 ret = AVERROR_INVALIDDATA;
9108 goto fail;
9109 }
9110
9111 12 version = avio_r8(pb);
9112 12 flags = avio_rb24(pb);
9113 12 count = avio_rb32(pb);
9114
9115
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 12 times.
41 for (int i = 0; i < count; i++) {
9116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9117 29 int assoc_count = avio_r8(pb);
9118
9119
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 if (avio_feof(pb)) {
9120 ret = AVERROR_INVALIDDATA;
9121 goto fail;
9122 }
9123
9124
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 29 times.
101 for (int j = 0; j < assoc_count; j++) {
9125 MOVAtoms *ref;
9126 72 int index = avio_r8(pb) & 0x7f;
9127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (flags & 1) {
9128 index <<= 8;
9129 index |= avio_r8(pb);
9130 }
9131
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) {
9132 ret = AVERROR_INVALIDDATA;
9133 goto fail;
9134 }
9135 72 ref = &atoms[--index];
9136
9137 72 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
9138 72 index + 1, item_id, av_fourcc2str(ref->type));
9139
9140 72 c->cur_item_id = item_id;
9141
9142 72 ret = mov_read_default(c, &ref->b.pub,
9143 72 (MOVAtom) { .size = ref->size,
9144 .type = MKTAG('i','p','c','o') });
9145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (ret < 0)
9146 goto fail;
9147 72 ffio_init_read_context(&ref->b, ref->data, ref->size);
9148 }
9149 }
9150
9151 12 ret = 0;
9152 12 fail:
9153 12 c->cur_item_id = -1;
9154
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 12 times.
61 for (int i = 0; i < nb_atoms; i++)
9155 49 av_free(atoms[i].data);
9156 12 av_free(atoms);
9157
9158 12 return ret;
9159 }
9160
9161 static const MOVParseTableEntry mov_default_parse_table[] = {
9162 { MKTAG('A','C','L','R'), mov_read_aclr },
9163 { MKTAG('A','P','R','G'), mov_read_avid },
9164 { MKTAG('A','A','L','P'), mov_read_avid },
9165 { MKTAG('A','R','E','S'), mov_read_ares },
9166 { MKTAG('a','v','s','s'), mov_read_avss },
9167 { MKTAG('a','v','1','C'), mov_read_glbl },
9168 { MKTAG('c','h','p','l'), mov_read_chpl },
9169 { MKTAG('c','o','6','4'), mov_read_stco },
9170 { MKTAG('c','o','l','r'), mov_read_colr },
9171 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
9172 { MKTAG('d','i','n','f'), mov_read_default },
9173 { MKTAG('D','p','x','E'), mov_read_dpxe },
9174 { MKTAG('d','r','e','f'), mov_read_dref },
9175 { MKTAG('e','d','t','s'), mov_read_default },
9176 { MKTAG('e','l','s','t'), mov_read_elst },
9177 { MKTAG('e','n','d','a'), mov_read_enda },
9178 { MKTAG('f','i','e','l'), mov_read_fiel },
9179 { MKTAG('a','d','r','m'), mov_read_adrm },
9180 { MKTAG('f','t','y','p'), mov_read_ftyp },
9181 { MKTAG('g','l','b','l'), mov_read_glbl },
9182 { MKTAG('h','d','l','r'), mov_read_hdlr },
9183 { MKTAG('i','l','s','t'), mov_read_ilst },
9184 { MKTAG('j','p','2','h'), mov_read_jp2h },
9185 { MKTAG('m','d','a','t'), mov_read_mdat },
9186 { MKTAG('m','d','h','d'), mov_read_mdhd },
9187 { MKTAG('m','d','i','a'), mov_read_default },
9188 { MKTAG('m','e','t','a'), mov_read_meta },
9189 { MKTAG('m','i','n','f'), mov_read_default },
9190 { MKTAG('m','o','o','f'), mov_read_moof },
9191 { MKTAG('m','o','o','v'), mov_read_moov },
9192 { MKTAG('m','v','e','x'), mov_read_default },
9193 { MKTAG('m','v','h','d'), mov_read_mvhd },
9194 { MKTAG('S','M','I',' '), mov_read_svq3 },
9195 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
9196 { MKTAG('a','v','c','C'), mov_read_glbl },
9197 { MKTAG('p','a','s','p'), mov_read_pasp },
9198 { MKTAG('c','l','a','p'), mov_read_clap },
9199 { MKTAG('s','b','a','s'), mov_read_sbas },
9200 { MKTAG('s','i','d','x'), mov_read_sidx },
9201 { MKTAG('s','t','b','l'), mov_read_default },
9202 { MKTAG('s','t','c','o'), mov_read_stco },
9203 { MKTAG('s','t','p','s'), mov_read_stps },
9204 { MKTAG('s','t','r','f'), mov_read_strf },
9205 { MKTAG('s','t','s','c'), mov_read_stsc },
9206 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
9207 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
9208 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
9209 { MKTAG('s','t','t','s'), mov_read_stts },
9210 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
9211 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
9212 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
9213 { MKTAG('t','f','d','t'), mov_read_tfdt },
9214 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
9215 { MKTAG('t','r','a','k'), mov_read_trak },
9216 { MKTAG('t','r','a','f'), mov_read_default },
9217 { MKTAG('t','r','e','f'), mov_read_default },
9218 { MKTAG('t','m','c','d'), mov_read_tmcd },
9219 { MKTAG('c','h','a','p'), mov_read_chap },
9220 { MKTAG('t','r','e','x'), mov_read_trex },
9221 { MKTAG('t','r','u','n'), mov_read_trun },
9222 { MKTAG('u','d','t','a'), mov_read_default },
9223 { MKTAG('w','a','v','e'), mov_read_wave },
9224 { MKTAG('e','s','d','s'), mov_read_esds },
9225 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
9226 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
9227 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
9228 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
9229 { MKTAG('w','f','e','x'), mov_read_wfex },
9230 { MKTAG('c','m','o','v'), mov_read_cmov },
9231 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
9232 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
9233 { MKTAG('d','v','c','1'), mov_read_dvc1 },
9234 { MKTAG('s','g','p','d'), mov_read_sgpd },
9235 { MKTAG('s','b','g','p'), mov_read_sbgp },
9236 { MKTAG('h','v','c','C'), mov_read_glbl },
9237 { MKTAG('v','v','c','C'), mov_read_glbl },
9238 { MKTAG('u','u','i','d'), mov_read_uuid },
9239 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
9240 { MKTAG('f','r','e','e'), mov_read_free },
9241 { MKTAG('-','-','-','-'), mov_read_custom },
9242 { MKTAG('s','i','n','f'), mov_read_default },
9243 { MKTAG('f','r','m','a'), mov_read_frma },
9244 { MKTAG('s','e','n','c'), mov_read_senc },
9245 { MKTAG('s','a','i','z'), mov_read_saiz },
9246 { MKTAG('s','a','i','o'), mov_read_saio },
9247 { MKTAG('p','s','s','h'), mov_read_pssh },
9248 { MKTAG('s','c','h','m'), mov_read_schm },
9249 { MKTAG('s','c','h','i'), mov_read_default },
9250 { MKTAG('t','e','n','c'), mov_read_tenc },
9251 { MKTAG('d','f','L','a'), mov_read_dfla },
9252 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
9253 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
9254 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
9255 { MKTAG('h','f','o','v'), mov_read_hfov },
9256 { MKTAG('d','O','p','s'), mov_read_dops },
9257 { MKTAG('d','m','l','p'), mov_read_dmlp },
9258 { MKTAG('S','m','D','m'), mov_read_smdm },
9259 { MKTAG('C','o','L','L'), mov_read_coll },
9260 { MKTAG('v','p','c','C'), mov_read_vpcc },
9261 { MKTAG('m','d','c','v'), mov_read_mdcv },
9262 { MKTAG('c','l','l','i'), mov_read_clli },
9263 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
9264 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
9265 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
9266 { MKTAG('k','i','n','d'), mov_read_kind },
9267 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
9268 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
9269 { MKTAG('i','l','o','c'), mov_read_iloc },
9270 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
9271 { MKTAG('p','i','t','m'), mov_read_pitm },
9272 { MKTAG('e','v','c','C'), mov_read_glbl },
9273 { MKTAG('i','d','a','t'), mov_read_idat },
9274 { MKTAG('i','m','i','r'), mov_read_imir },
9275 { MKTAG('i','r','e','f'), mov_read_iref },
9276 { MKTAG('i','s','p','e'), mov_read_ispe },
9277 { MKTAG('i','r','o','t'), mov_read_irot },
9278 { MKTAG('i','p','r','p'), mov_read_iprp },
9279 { MKTAG('i','i','n','f'), mov_read_iinf },
9280 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
9281 { MKTAG('l','h','v','C'), mov_read_lhvc },
9282 { MKTAG('l','v','c','C'), mov_read_glbl },
9283 #if CONFIG_IAMFDEC
9284 { MKTAG('i','a','c','b'), mov_read_iacb },
9285 #endif
9286 { 0, NULL }
9287 };
9288
9289 6308 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9290 {
9291 6308 int64_t total_size = 0;
9292 MOVAtom a;
9293 int i;
9294
9295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6308 times.
6308 if (c->atom_depth > 10) {
9296 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
9297 return AVERROR_INVALIDDATA;
9298 }
9299 6308 c->atom_depth ++;
9300
9301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6308 times.
6308 if (atom.size < 0)
9302 atom.size = INT64_MAX;
9303
2/2
✓ Branch 0 taken 18086 times.
✓ Branch 1 taken 5828 times.
23914 while (total_size <= atom.size - 8) {
9304 18086 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
9305 18086 a.size = avio_rb32(pb);
9306 18086 a.type = avio_rl32(pb);
9307
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 18082 times.
18086 if (avio_feof(pb))
9308 4 break;
9309
3/4
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 17895 times.
✓ Branch 2 taken 187 times.
✗ Branch 3 not taken.
18082 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
9310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18082 times.
18082 a.type == MKTAG('h','o','o','v')) &&
9311 a.size >= 8 &&
9312 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
9313 uint32_t type;
9314 avio_skip(pb, 4);
9315 type = avio_rl32(pb);
9316 if (avio_feof(pb))
9317 break;
9318 avio_seek(pb, -8, SEEK_CUR);
9319 if (type == MKTAG('m','v','h','d') ||
9320 type == MKTAG('c','m','o','v')) {
9321 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
9322 a.type = MKTAG('m','o','o','v');
9323 }
9324 }
9325
2/2
✓ Branch 0 taken 15396 times.
✓ Branch 1 taken 2686 times.
18082 if (atom.type != MKTAG('r','o','o','t') &&
9326
2/2
✓ Branch 0 taken 13999 times.
✓ Branch 1 taken 1397 times.
15396 atom.type != MKTAG('m','o','o','v')) {
9327
1/2
✓ Branch 0 taken 13999 times.
✗ Branch 1 not taken.
13999 if (a.type == MKTAG('t','r','a','k') ||
9328
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13999 times.
13999 a.type == MKTAG('m','d','a','t')) {
9329 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
9330 avio_skip(pb, -8);
9331 c->atom_depth --;
9332 476 return 0;
9333 }
9334 }
9335 18082 total_size += 8;
9336
3/4
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 18059 times.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
18082 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
9337 23 a.size = avio_rb64(pb) - 8;
9338 23 total_size += 8;
9339 }
9340 18082 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
9341 18082 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
9342
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 18077 times.
18082 if (a.size == 0) {
9343 5 a.size = atom.size - total_size + 8;
9344 }
9345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18082 times.
18082 if (a.size < 0)
9346 break;
9347 18082 a.size -= 8;
9348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18082 times.
18082 if (a.size < 0)
9349 break;
9350 18082 a.size = FFMIN(a.size, atom.size - total_size);
9351
9352
2/2
✓ Branch 0 taken 822560 times.
✓ Branch 1 taken 1833 times.
824393 for (i = 0; mov_default_parse_table[i].type; i++)
9353
2/2
✓ Branch 0 taken 16249 times.
✓ Branch 1 taken 806311 times.
822560 if (mov_default_parse_table[i].type == a.type) {
9354 16249 parse = mov_default_parse_table[i].parse;
9355 16249 break;
9356 }
9357
9358 // container is user data
9359
4/4
✓ Branch 0 taken 1833 times.
✓ Branch 1 taken 16249 times.
✓ Branch 2 taken 1659 times.
✓ Branch 3 taken 174 times.
18082 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
9360
2/2
✓ Branch 0 taken 292 times.
✓ Branch 1 taken 1367 times.
1659 atom.type == MKTAG('i','l','s','t')))
9361 466 parse = mov_read_udta_string;
9362
9363 // Supports parsing the QuickTime Metadata Keys.
9364 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
9365
4/4
✓ Branch 0 taken 1367 times.
✓ Branch 1 taken 16715 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 1356 times.
18082 if (!parse && c->found_hdlr_mdta &&
9366
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 atom.type == MKTAG('m','e','t','a') &&
9367
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 a.type == MKTAG('k','e','y','s') &&
9368
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 c->meta_keys_count == 0) {
9369 11 parse = mov_read_keys;
9370 }
9371
9372
2/2
✓ Branch 0 taken 1356 times.
✓ Branch 1 taken 16726 times.
18082 if (!parse) { /* skip leaf atoms data */
9373 1356 avio_skip(pb, a.size);
9374 } else {
9375 16726 int64_t start_pos = avio_tell(pb);
9376 int64_t left;
9377 16726 int err = parse(c, pb, a);
9378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16726 times.
16726 if (err < 0) {
9379 c->atom_depth --;
9380 return err;
9381 }
9382
5/6
✓ Branch 0 taken 3078 times.
✓ Branch 1 taken 13648 times.
✓ Branch 2 taken 2780 times.
✓ Branch 3 taken 298 times.
✓ Branch 4 taken 2780 times.
✗ Branch 5 not taken.
16726 if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos &&
9383
6/8
✓ Branch 0 taken 2780 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2780 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2772 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 468 times.
✓ Branch 7 taken 2304 times.
5552 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
9384 2772 start_pos + a.size == avio_size(pb))) {
9385
4/6
✓ Branch 0 taken 476 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 476 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 468 times.
476 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
9386 8 c->next_root_atom = start_pos + a.size;
9387 476 c->atom_depth --;
9388 476 return 0;
9389 }
9390 16250 left = a.size - avio_tell(pb) + start_pos;
9391
2/2
✓ Branch 0 taken 1302 times.
✓ Branch 1 taken 14948 times.
16250 if (left > 0) /* skip garbage at atom end */
9392 1302 avio_skip(pb, left);
9393
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14946 times.
14948 else if (left < 0) {
9394 2 av_log(c->fc, AV_LOG_WARNING,
9395 "overread end of atom '%s' by %"PRId64" bytes\n",
9396 2 av_fourcc2str(a.type), -left);
9397 2 avio_seek(pb, left, SEEK_CUR);
9398 }
9399 }
9400
9401 17606 total_size += a.size;
9402 }
9403
9404
4/4
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 5726 times.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 4 times.
5832 if (total_size < atom.size && atom.size < 0x7ffff)
9405 102 avio_skip(pb, atom.size - total_size);
9406
9407 5832 c->atom_depth --;
9408 5832 return 0;
9409 }
9410
9411 7186 static int mov_probe(const AVProbeData *p)
9412 {
9413 int64_t offset;
9414 uint32_t tag;
9415 7186 int score = 0;
9416 7186 int moov_offset = -1;
9417
9418 /* check file header */
9419 7186 offset = 0;
9420 8854 for (;;) {
9421 int64_t size;
9422 16040 int minsize = 8;
9423 /* ignore invalid offset */
9424
2/2
✓ Branch 0 taken 7186 times.
✓ Branch 1 taken 8854 times.
16040 if ((offset + 8ULL) > (unsigned int)p->buf_size)
9425 7186 break;
9426 8854 size = AV_RB32(p->buf + offset);
9427
3/4
✓ Branch 0 taken 513 times.
✓ Branch 1 taken 8341 times.
✓ Branch 2 taken 513 times.
✗ Branch 3 not taken.
8854 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
9428 513 size = AV_RB64(p->buf+offset + 8);
9429 513 minsize = 16;
9430
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 8286 times.
8341 } else if (size == 0) {
9431 55 size = p->buf_size - offset;
9432 }
9433
2/2
✓ Branch 0 taken 396 times.
✓ Branch 1 taken 8458 times.
8854 if (size < minsize) {
9434 396 offset += 4;
9435 396 continue;
9436 }
9437 8458 tag = AV_RL32(p->buf + offset + 4);
9438
5/6
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 828 times.
✓ Branch 2 taken 352 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7154 times.
8458 switch(tag) {
9439 /* check for obvious tags */
9440 123 case MKTAG('m','o','o','v'):
9441 123 moov_offset = offset + 4;
9442 951 case MKTAG('m','d','a','t'):
9443 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
9444 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
9445 case MKTAG('f','t','y','p'):
9446
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 519 times.
951 if (tag == MKTAG('f','t','y','p') &&
9447
1/2
✓ Branch 0 taken 432 times.
✗ Branch 1 not taken.
432 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
9448
1/2
✓ Branch 0 taken 432 times.
✗ Branch 1 not taken.
432 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
9449
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 426 times.
432 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
9450 )) {
9451 6 score = FFMAX(score, 5);
9452 } else {
9453 945 score = AVPROBE_SCORE_MAX;
9454 }
9455 951 break;
9456 /* those are more common words, so rate then a bit less */
9457 352 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
9458 case MKTAG('w','i','d','e'):
9459 case MKTAG('f','r','e','e'):
9460 case MKTAG('j','u','n','k'):
9461 case MKTAG('p','i','c','t'):
9462 352 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
9463 352 break;
9464 case MKTAG(0x82,0x82,0x7f,0x7d):
9465 score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
9466 break;
9467 1 case MKTAG('s','k','i','p'):
9468 case MKTAG('u','u','i','d'):
9469 case MKTAG('p','r','f','l'):
9470 /* if we only find those cause probedata is too small at least rate them */
9471 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
9472 1 break;
9473 }
9474
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8458 times.
8458 if (size > INT64_MAX - offset)
9475 break;
9476 8458 offset += size;
9477 }
9478
4/4
✓ Branch 0 taken 463 times.
✓ Branch 1 taken 6723 times.
✓ Branch 2 taken 123 times.
✓ Branch 3 taken 340 times.
7186 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
9479 /* moov atom in the header - we should make sure that this is not a
9480 * MOV-packed MPEG-PS */
9481 123 offset = moov_offset;
9482
9483
2/2
✓ Branch 0 taken 120608 times.
✓ Branch 1 taken 123 times.
120731 while (offset < (p->buf_size - 16)) { /* Sufficient space */
9484 /* We found an actual hdlr atom */
9485
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 120476 times.
120608 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
9486
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 111 times.
132 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
9487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
9488 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
9489 /* We found a media handler reference atom describing an
9490 * MPEG-PS-in-MOV, return a
9491 * low score to force expanding the probe window until
9492 * mpegps_probe finds what it needs */
9493 return 5;
9494 } else {
9495 /* Keep looking */
9496 120608 offset += 2;
9497 }
9498 }
9499 }
9500
9501 7186 return score;
9502 }
9503
9504 // must be done after parsing all trak because there's no order requirement
9505 2 static void mov_read_chapters(AVFormatContext *s)
9506 {
9507 2 MOVContext *mov = s->priv_data;
9508 MOVStreamContext *sc;
9509 int64_t cur_pos;
9510 int i, j;
9511 int chapter_track;
9512
9513
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
9514 2 AVStream *st = NULL;
9515 2 FFStream *sti = NULL;
9516 2 chapter_track = mov->chapter_tracks[j];
9517
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
9518 4 sc = mov->fc->streams[i]->priv_data;
9519
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
9520 2 st = s->streams[i];
9521 2 break;
9522 }
9523 }
9524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
9525 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
9526 continue;
9527 }
9528 2 sti = ffstream(st);
9529
9530 2 sc = st->priv_data;
9531 2 cur_pos = avio_tell(sc->pb);
9532
9533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
9534 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
9535 if (!st->attached_pic.data && sti->nb_index_entries) {
9536 // Retrieve the first frame, if possible
9537 AVIndexEntry *sample = &sti->index_entries[0];
9538 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9539 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
9540 goto finish;
9541 }
9542
9543 if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
9544 goto finish;
9545 }
9546 } else {
9547 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
9548 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
9549 2 st->discard = AVDISCARD_ALL;
9550
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
9551 8 AVIndexEntry *sample = &sti->index_entries[i];
9552
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;
9553 uint8_t *title;
9554 uint16_t ch;
9555 int len, title_len;
9556
9557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
9558 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
9559 end = AV_NOPTS_VALUE;
9560 }
9561
9562
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9563 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
9564 goto finish;
9565 }
9566
9567 // the first two bytes are the length of the title
9568 8 len = avio_rb16(sc->pb);
9569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
9570 continue;
9571 8 title_len = 2*len + 1;
9572
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
9573 goto finish;
9574
9575 // The samples could theoretically be in any encoding if there's an encd
9576 // atom following, but in practice are only utf-8 or utf-16, distinguished
9577 // instead by the presence of a BOM
9578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
9579 title[0] = 0;
9580 } else {
9581 8 ch = avio_rb16(sc->pb);
9582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
9583 avio_get_str16be(sc->pb, len, title, title_len);
9584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
9585 avio_get_str16le(sc->pb, len, title, title_len);
9586 else {
9587 8 AV_WB16(title, ch);
9588
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)
9589 title[len] = 0;
9590 else
9591 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
9592 }
9593 }
9594
9595 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
9596 8 av_freep(&title);
9597 }
9598 }
9599 2 finish:
9600 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
9601 }
9602 2 }
9603
9604 19 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
9605 int64_t value, int flags)
9606 {
9607 AVTimecode tc;
9608 char buf[AV_TIMECODE_STR_SIZE];
9609 19 AVRational rate = st->avg_frame_rate;
9610 19 int ret = av_timecode_init(&tc, rate, flags, 0, s);
9611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
9612 return ret;
9613 19 av_dict_set(&st->metadata, "timecode",
9614 19 av_timecode_make_string(&tc, buf, value), 0);
9615 19 return 0;
9616 }
9617
9618 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
9619 {
9620 MOVStreamContext *sc = st->priv_data;
9621 FFStream *const sti = ffstream(st);
9622 char buf[AV_TIMECODE_STR_SIZE];
9623 int64_t cur_pos = avio_tell(sc->pb);
9624 int hh, mm, ss, ff, drop;
9625
9626 if (!sti->nb_index_entries)
9627 return -1;
9628
9629 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9630 avio_skip(s->pb, 13);
9631 hh = avio_r8(s->pb);
9632 mm = avio_r8(s->pb);
9633 ss = avio_r8(s->pb);
9634 drop = avio_r8(s->pb);
9635 ff = avio_r8(s->pb);
9636 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
9637 hh, mm, ss, drop ? ';' : ':', ff);
9638 av_dict_set(&st->metadata, "timecode", buf, 0);
9639
9640 avio_seek(sc->pb, cur_pos, SEEK_SET);
9641 return 0;
9642 }
9643
9644 19 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
9645 {
9646 19 MOVStreamContext *sc = st->priv_data;
9647 19 FFStream *const sti = ffstream(st);
9648 19 int flags = 0;
9649 19 int64_t cur_pos = avio_tell(sc->pb);
9650 int64_t value;
9651 19 AVRational tc_rate = st->avg_frame_rate;
9652 19 int tmcd_nb_frames = sc->tmcd_nb_frames;
9653 int rounded_tc_rate;
9654
9655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!sti->nb_index_entries)
9656 return -1;
9657
9658
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)
9659 return -1;
9660
9661 19 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9662 19 value = avio_rb32(s->pb);
9663
9664
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13 times.
19 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
9665
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
9666
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
9667
9668 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
9669 * not the case) and thus assume "frame number format" instead of QT one.
9670 * No sample with tmcd track can be found with a QT timecode at the moment,
9671 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
9672 * format). */
9673
9674 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
9675 * we multiply the frame number with the quotient.
9676 * See tickets #9492, #9710. */
9677 19 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
9678 /* Work around files where tmcd_nb_frames is rounded down from frame rate
9679 * instead of up. See ticket #5978. */
9680
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
9681
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
9682 10 tmcd_nb_frames = rounded_tc_rate;
9683 19 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
9684
9685 19 parse_timecode_in_framenum_format(s, st, value, flags);
9686
9687 19 avio_seek(sc->pb, cur_pos, SEEK_SET);
9688 19 return 0;
9689 }
9690
9691 1037 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
9692 int i;
9693
3/4
✓ Branch 0 taken 1037 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1033 times.
✓ Branch 3 taken 4 times.
1037 if (!index || !*index) return;
9694
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 4 times.
76 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
9695 72 av_encryption_info_free((*index)->encrypted_samples[i]);
9696 }
9697 4 av_freep(&(*index)->encrypted_samples);
9698 4 av_freep(&(*index)->auxiliary_info_sizes);
9699 4 av_freep(&(*index)->auxiliary_offsets);
9700 4 av_freep(index);
9701 }
9702
9703 670 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
9704 {
9705 670 MOVStreamContext *sc = st->priv_data;
9706
9707
3/4
✓ Branch 0 taken 670 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 630 times.
670 if (!sc || --sc->refcount) {
9708 40 st->priv_data = NULL;
9709 40 return;
9710 }
9711
9712 630 av_freep(&sc->ctts_data);
9713
2/2
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 630 times.
1223 for (int i = 0; i < sc->drefs_count; i++) {
9714 593 av_freep(&sc->drefs[i].path);
9715 593 av_freep(&sc->drefs[i].dir);
9716 }
9717 630 av_freep(&sc->drefs);
9718
9719 630 sc->drefs_count = 0;
9720
9721
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 616 times.
630 if (!sc->pb_is_copied)
9722 14 ff_format_io_close(s, &sc->pb);
9723
9724 630 sc->pb = NULL;
9725 630 av_freep(&sc->chunk_offsets);
9726 630 av_freep(&sc->stsc_data);
9727 630 av_freep(&sc->sample_sizes);
9728 630 av_freep(&sc->keyframes);
9729 630 av_freep(&sc->stts_data);
9730 630 av_freep(&sc->sdtp_data);
9731 630 av_freep(&sc->stps_data);
9732 630 av_freep(&sc->elst_data);
9733 630 av_freep(&sc->rap_group);
9734 630 av_freep(&sc->sync_group);
9735 630 av_freep(&sc->sgpd_sync);
9736 630 av_freep(&sc->sample_offsets);
9737 630 av_freep(&sc->open_key_samples);
9738 630 av_freep(&sc->display_matrix);
9739 630 av_freep(&sc->index_ranges);
9740
9741
2/2
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 37 times.
630 if (sc->extradata)
9742
2/2
✓ Branch 0 taken 604 times.
✓ Branch 1 taken 593 times.
1197 for (int i = 0; i < sc->stsd_count; i++)
9743 604 av_free(sc->extradata[i]);
9744 630 av_freep(&sc->extradata);
9745 630 av_freep(&sc->extradata_size);
9746
9747 630 mov_free_encryption_index(&sc->cenc.encryption_index);
9748 630 av_encryption_info_free(sc->cenc.default_encrypted_sample);
9749 630 av_aes_ctr_free(sc->cenc.aes_ctr);
9750
9751 630 av_freep(&sc->stereo3d);
9752 630 av_freep(&sc->spherical);
9753 630 av_freep(&sc->mastering);
9754 630 av_freep(&sc->coll);
9755 630 av_freep(&sc->ambient);
9756
9757 #if CONFIG_IAMFDEC
9758
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 620 times.
630 if (sc->iamf)
9759 10 ff_iamf_read_deinit(sc->iamf);
9760 #endif
9761 630 av_freep(&sc->iamf);
9762 }
9763
9764 492 static int mov_read_close(AVFormatContext *s)
9765 {
9766 492 MOVContext *mov = s->priv_data;
9767 int i, j;
9768
9769
2/2
✓ Branch 0 taken 670 times.
✓ Branch 1 taken 492 times.
1162 for (i = 0; i < s->nb_streams; i++) {
9770 670 AVStream *st = s->streams[i];
9771
9772 670 mov_free_stream_context(s, st);
9773 }
9774
9775 492 av_freep(&mov->dv_demux);
9776 492 avformat_free_context(mov->dv_fctx);
9777 492 mov->dv_fctx = NULL;
9778
9779
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 481 times.
492 if (mov->meta_keys) {
9780
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i < mov->meta_keys_count; i++) {
9781 58 av_freep(&mov->meta_keys[i]);
9782 }
9783 11 av_freep(&mov->meta_keys);
9784 }
9785
9786 492 av_freep(&mov->trex_data);
9787 492 av_freep(&mov->bitrates);
9788
9789
2/2
✓ Branch 0 taken 389 times.
✓ Branch 1 taken 492 times.
881 for (i = 0; i < mov->frag_index.nb_items; i++) {
9790 389 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
9791
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++) {
9792 407 mov_free_encryption_index(&frag[j].encryption_index);
9793 }
9794 389 av_freep(&mov->frag_index.item[i].stream_info);
9795 }
9796 492 av_freep(&mov->frag_index.item);
9797
9798 492 av_freep(&mov->aes_decrypt);
9799 492 av_freep(&mov->chapter_tracks);
9800
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 492 times.
522 for (i = 0; i < mov->nb_heif_item; i++) {
9801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!mov->heif_item[i])
9802 continue;
9803 30 av_freep(&mov->heif_item[i]->name);
9804 30 av_freep(&mov->heif_item[i]->icc_profile);
9805 30 av_freep(&mov->heif_item[i]);
9806 }
9807 492 av_freep(&mov->heif_item);
9808
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 492 times.
498 for (i = 0; i < mov->nb_heif_grid; i++) {
9809 6 av_freep(&mov->heif_grid[i].tile_id_list);
9810 6 av_freep(&mov->heif_grid[i].tile_item_list);
9811 }
9812 492 av_freep(&mov->heif_grid);
9813
9814 492 return 0;
9815 }
9816
9817 16 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
9818 {
9819 int i;
9820
9821
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 for (i = 0; i < s->nb_streams; i++) {
9822 24 AVStream *st = s->streams[i];
9823 24 MOVStreamContext *sc = st->priv_data;
9824
9825
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
9826
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 sc->timecode_track == tmcd_id)
9827 14 return 1;
9828 }
9829 2 return 0;
9830 }
9831
9832 /* look for a tmcd track not referenced by any video track, and export it globally */
9833 492 static void export_orphan_timecode(AVFormatContext *s)
9834 {
9835 int i;
9836
9837
2/2
✓ Branch 0 taken 667 times.
✓ Branch 1 taken 490 times.
1157 for (i = 0; i < s->nb_streams; i++) {
9838 667 AVStream *st = s->streams[i];
9839
9840
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 651 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 14 times.
683 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
9841 16 !tmcd_is_referenced(s, i + 1)) {
9842 2 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
9843
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (tcr) {
9844 2 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
9845 2 break;
9846 }
9847 }
9848 }
9849 492 }
9850
9851 static int read_tfra(MOVContext *mov, AVIOContext *f)
9852 {
9853 int version, fieldlength, i, j;
9854 int64_t pos = avio_tell(f);
9855 uint32_t size = avio_rb32(f);
9856 unsigned track_id, item_count;
9857
9858 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
9859 return 1;
9860 }
9861 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
9862
9863 version = avio_r8(f);
9864 avio_rb24(f);
9865 track_id = avio_rb32(f);
9866 fieldlength = avio_rb32(f);
9867 item_count = avio_rb32(f);
9868 for (i = 0; i < item_count; i++) {
9869 int64_t time, offset;
9870 int index;
9871 MOVFragmentStreamInfo * frag_stream_info;
9872
9873 if (avio_feof(f)) {
9874 return AVERROR_INVALIDDATA;
9875 }
9876
9877 if (version == 1) {
9878 time = avio_rb64(f);
9879 offset = avio_rb64(f);
9880 } else {
9881 time = avio_rb32(f);
9882 offset = avio_rb32(f);
9883 }
9884
9885 // The first sample of each stream in a fragment is always a random
9886 // access sample. So it's entry in the tfra can be used as the
9887 // initial PTS of the fragment.
9888 index = update_frag_index(mov, offset);
9889 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
9890 if (frag_stream_info &&
9891 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
9892 frag_stream_info->first_tfra_pts = time;
9893
9894 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
9895 avio_r8(f);
9896 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
9897 avio_r8(f);
9898 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
9899 avio_r8(f);
9900 }
9901
9902 avio_seek(f, pos + size, SEEK_SET);
9903 return 0;
9904 }
9905
9906 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
9907 {
9908 int64_t stream_size = avio_size(f);
9909 int64_t original_pos = avio_tell(f);
9910 int64_t seek_ret;
9911 int ret = -1;
9912 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
9913 ret = seek_ret;
9914 goto fail;
9915 }
9916 c->mfra_size = avio_rb32(f);
9917 c->have_read_mfra_size = 1;
9918 if (!c->mfra_size || c->mfra_size > stream_size) {
9919 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
9920 goto fail;
9921 }
9922 if ((seek_ret = avio_seek(f, -((int64_t) c->mfra_size), SEEK_CUR)) < 0) {
9923 ret = seek_ret;
9924 goto fail;
9925 }
9926 if (avio_rb32(f) != c->mfra_size) {
9927 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
9928 goto fail;
9929 }
9930 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
9931 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
9932 goto fail;
9933 }
9934 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
9935 do {
9936 ret = read_tfra(c, f);
9937 if (ret < 0)
9938 goto fail;
9939 } while (!ret);
9940 ret = 0;
9941 c->frag_index.complete = 1;
9942 fail:
9943 seek_ret = avio_seek(f, original_pos, SEEK_SET);
9944 if (seek_ret < 0) {
9945 av_log(c->fc, AV_LOG_ERROR,
9946 "failed to seek back after looking for mfra\n");
9947 ret = seek_ret;
9948 }
9949 return ret;
9950 }
9951
9952 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
9953 const HEIFItem *item)
9954 {
9955 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
9956 AV_PKT_DATA_ICC_PROFILE,
9957 item->icc_profile_size, 0);
9958 if (!sd)
9959 return AVERROR(ENOMEM);
9960
9961 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
9962
9963 return 0;
9964 }
9965
9966 4 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
9967 const HEIFItem *item)
9968 {
9969 int32_t *matrix;
9970 4 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data,
9971 nb_coded_side_data,
9972 AV_PKT_DATA_DISPLAYMATRIX,
9973 9 * sizeof(*matrix), 0);
9974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sd)
9975 return AVERROR(ENOMEM);
9976
9977 4 matrix = (int32_t*)sd->data;
9978 /* rotation is in the counter-clockwise direction whereas
9979 * av_display_rotation_set() expects its argument to be
9980 * oriented clockwise, so we need to negate it. */
9981 4 av_display_rotation_set(matrix, -item->rotation);
9982 4 av_display_matrix_flip(matrix, item->hflip, item->vflip);
9983
9984 4 return 0;
9985 }
9986
9987 2 static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid,
9988 AVStreamGroupTileGrid *tile_grid)
9989 {
9990 2 MOVContext *c = s->priv_data;
9991 2 const HEIFItem *item = grid->item;
9992 2 int64_t offset = 0, pos = avio_tell(s->pb);
9993 2 int x = 0, y = 0, i = 0;
9994 int tile_rows, tile_cols;
9995 int flags, size;
9996
9997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
9998 av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
9999 return AVERROR_PATCHWELCOME;
10000 }
10001
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (item->is_idat_relative) {
10002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!c->idat_offset) {
10003 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
10004 return AVERROR_INVALIDDATA;
10005 }
10006 2 offset = c->idat_offset;
10007 }
10008
10009 2 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10010
10011 2 avio_r8(s->pb); /* version */
10012 2 flags = avio_r8(s->pb);
10013
10014 2 tile_rows = avio_r8(s->pb) + 1;
10015 2 tile_cols = avio_r8(s->pb) + 1;
10016 /* actual width and height of output image */
10017
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);
10018
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);
10019
10020 /* ICC profile */
10021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (item->icc_profile_size) {
10022 int ret = set_icc_profile_from_item(&tile_grid->coded_side_data,
10023 &tile_grid->nb_coded_side_data, item);
10024 if (ret < 0)
10025 return ret;
10026 }
10027 /* rotation */
10028
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) {
10029 int ret = set_display_matrix_from_item(&tile_grid->coded_side_data,
10030 &tile_grid->nb_coded_side_data, item);
10031 if (ret < 0)
10032 return ret;
10033 }
10034
10035 2 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
10036 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
10037
10038 2 avio_seek(s->pb, pos, SEEK_SET);
10039
10040 2 size = tile_rows * tile_cols;
10041 2 tile_grid->nb_tiles = grid->nb_tiles;
10042
10043
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tile_grid->nb_tiles != size)
10044 return AVERROR_INVALIDDATA;
10045
10046
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < tile_cols; i++)
10047 4 tile_grid->coded_width += grid->tile_item_list[i]->width;
10048
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < size; i += tile_cols)
10049 4 tile_grid->coded_height += grid->tile_item_list[i]->height;
10050
10051 2 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!tile_grid->offsets)
10053 return AVERROR(ENOMEM);
10054
10055
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 while (y < tile_grid->coded_height) {
10056 4 int left_col = i;
10057
10058
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 while (x < tile_grid->coded_width) {
10059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (i == tile_grid->nb_tiles)
10060 return AVERROR_INVALIDDATA;
10061
10062 8 tile_grid->offsets[i].idx = i;
10063 8 tile_grid->offsets[i].horizontal = x;
10064 8 tile_grid->offsets[i].vertical = y;
10065
10066 8 x += grid->tile_item_list[i++]->width;
10067 }
10068
10069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (x > tile_grid->coded_width) {
10070 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10071 return AVERROR_INVALIDDATA;
10072 }
10073
10074 4 x = 0;
10075 4 y += grid->tile_item_list[left_col]->height;
10076 }
10077
10078
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) {
10079 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10080 return AVERROR_INVALIDDATA;
10081 }
10082
10083 2 return 0;
10084 }
10085
10086 4 static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid,
10087 AVStreamGroupTileGrid *tile_grid)
10088 {
10089 4 MOVContext *c = s->priv_data;
10090 4 const HEIFItem *item = grid->item;
10091 uint16_t canvas_fill_value[4];
10092 4 int64_t offset = 0, pos = avio_tell(s->pb);
10093 4 int ret = 0, flags;
10094
10095
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10096 av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
10097 return AVERROR_PATCHWELCOME;
10098 }
10099
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
10100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
10101 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
10102 return AVERROR_INVALIDDATA;
10103 }
10104 4 offset = c->idat_offset;
10105 }
10106
10107 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10108
10109 4 avio_r8(s->pb); /* version */
10110 4 flags = avio_r8(s->pb);
10111
10112
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10113 16 canvas_fill_value[i] = avio_rb16(s->pb);
10114 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
10115 4 canvas_fill_value[0], canvas_fill_value[1],
10116 4 canvas_fill_value[2], canvas_fill_value[3]);
10117
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10118 16 tile_grid->background[i] = canvas_fill_value[i];
10119
10120 /* actual width and height of output image */
10121 4 tile_grid->width =
10122
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);
10123 4 tile_grid->height =
10124
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);
10125
10126 /* rotation */
10127
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) {
10128 int ret = set_display_matrix_from_item(&tile_grid->coded_side_data,
10129 &tile_grid->nb_coded_side_data, item);
10130 if (ret < 0)
10131 return ret;
10132 }
10133
10134 /* ICC profile */
10135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (item->icc_profile_size) {
10136 int ret = set_icc_profile_from_item(&tile_grid->coded_side_data,
10137 &tile_grid->nb_coded_side_data, item);
10138 if (ret < 0)
10139 return ret;
10140 }
10141
10142 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
10143 tile_grid->width, tile_grid->height);
10144
10145 4 tile_grid->nb_tiles = grid->nb_tiles;
10146 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
10148 ret = AVERROR(ENOMEM);
10149 goto fail;
10150 }
10151
10152
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
10153 8 tile_grid->offsets[i].idx = grid->tile_item_list[i]->st->index;
10154
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);
10155
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);
10156 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
10157 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
10158 8 i, tile_grid->offsets[i].idx,
10159 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
10160 }
10161
10162 4 fail:
10163 4 avio_seek(s->pb, pos, SEEK_SET);
10164
10165 4 return ret;
10166 }
10167
10168 6 static int mov_parse_tiles(AVFormatContext *s)
10169 {
10170 6 MOVContext *mov = s->priv_data;
10171
10172
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (int i = 0; i < mov->nb_heif_grid; i++) {
10173 6 AVStreamGroup *stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
10174 AVStreamGroupTileGrid *tile_grid;
10175 6 const HEIFGrid *grid = &mov->heif_grid[i];
10176 6 int err, loop = 1;
10177
10178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!stg)
10179 return AVERROR(ENOMEM);
10180
10181 6 stg->id = grid->item->item_id;
10182 6 tile_grid = stg->params.tile_grid;
10183
10184
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (int j = 0; j < grid->nb_tiles; j++) {
10185 16 int tile_id = grid->tile_id_list[j];
10186 int k;
10187
10188
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 for (k = 0; k < mov->nb_heif_item; k++) {
10189 30 HEIFItem *item = mov->heif_item[k];
10190 30 AVStream *st = item->st;
10191
10192
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)
10193 14 continue;
10194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!st) {
10195 av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
10196 "reference a stream\n",
10197 tile_id, grid->item->item_id);
10198 ff_remove_stream_group(s, stg);
10199 loop = 0;
10200 break;
10201 }
10202
10203 16 grid->tile_item_list[j] = item;
10204
10205 16 err = avformat_stream_group_add_stream(stg, st);
10206
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
16 if (err < 0 && err != AVERROR(EEXIST))
10207 return err;
10208
10209
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
16 if (item->item_id != mov->primary_item_id)
10210 10 st->disposition |= AV_DISPOSITION_DEPENDENT;
10211 16 break;
10212 }
10213
10214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (k == mov->nb_heif_item) {
10215 av_assert0(loop);
10216 av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
10217 "exist\n",
10218 tile_id, grid->item->item_id);
10219 ff_remove_stream_group(s, stg);
10220 loop = 0;
10221 }
10222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!loop)
10223 break;
10224 }
10225
10226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!loop)
10227 continue;
10228
10229
2/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
6 switch (grid->item->type) {
10230 2 case MKTAG('g','r','i','d'):
10231 2 err = read_image_grid(s, grid, tile_grid);
10232 2 break;
10233 4 case MKTAG('i','o','v','l'):
10234 4 err = read_image_iovl(s, grid, tile_grid);
10235 4 break;
10236 default:
10237 av_assert0(0);
10238 }
10239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10240 return err;
10241
10242
10243
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (grid->item->name)
10244 6 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
10245
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (grid->item->item_id == mov->primary_item_id)
10246 2 stg->disposition |= AV_DISPOSITION_DEFAULT;
10247 }
10248
10249 6 return 0;
10250 }
10251
10252 12 static int mov_parse_heif_items(AVFormatContext *s)
10253 {
10254 12 MOVContext *mov = s->priv_data;
10255 int err;
10256
10257
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 for (int i = 0; i < mov->nb_heif_item; i++) {
10258 30 HEIFItem *item = mov->heif_item[i];
10259 MOVStreamContext *sc;
10260 AVStream *st;
10261 30 int64_t offset = 0;
10262
10263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!item)
10264 continue;
10265
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 23 times.
30 if (!item->st) {
10266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (item->item_id == mov->thmb_item_id) {
10267 av_log(s, AV_LOG_ERROR, "HEIF thumbnail doesn't reference a stream\n");
10268 return AVERROR_INVALIDDATA;
10269 }
10270 7 continue;
10271 }
10272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (item->is_idat_relative) {
10273 if (!mov->idat_offset) {
10274 av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
10275 return AVERROR_INVALIDDATA;
10276 }
10277 offset = mov->idat_offset;
10278 }
10279
10280 23 st = item->st;
10281 23 sc = st->priv_data;
10282 23 st->codecpar->width = item->width;
10283 23 st->codecpar->height = item->height;
10284
10285
2/4
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 23 times.
23 if (sc->sample_count != 1 || sc->chunk_count != 1)
10286 return AVERROR_INVALIDDATA;
10287
10288 23 sc->sample_sizes[0] = item->extent_length;
10289 23 sc->chunk_offsets[0] = item->extent_offset + offset;
10290
10291
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 13 times.
23 if (item->item_id == mov->primary_item_id)
10292 10 st->disposition |= AV_DISPOSITION_DEFAULT;
10293
10294
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) {
10295 4 err = set_display_matrix_from_item(&st->codecpar->coded_side_data,
10296 4 &st->codecpar->nb_coded_side_data, item);
10297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
10298 return err;
10299 }
10300
10301 23 mov_build_index(mov, st);
10302 }
10303
10304
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (mov->nb_heif_grid) {
10305 6 err = mov_parse_tiles(s);
10306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10307 return err;
10308 }
10309
10310 12 return 0;
10311 }
10312
10313 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
10314 int first_index)
10315 {
10316 MOVStreamContext *sc = st->priv_data;
10317
10318 if (sc->tref_id < 0)
10319 return NULL;
10320
10321 for (int i = first_index; i < s->nb_streams; i++)
10322 if (s->streams[i]->id == sc->tref_id)
10323 return s->streams[i];
10324
10325 return NULL;
10326 }
10327
10328 492 static int mov_parse_lcevc_streams(AVFormatContext *s)
10329 {
10330 int err;
10331
10332
2/2
✓ Branch 0 taken 670 times.
✓ Branch 1 taken 492 times.
1162 for (int i = 0; i < s->nb_streams; i++) {
10333 AVStreamGroup *stg;
10334 670 AVStream *st = s->streams[i];
10335 AVStream *st_base;
10336 670 MOVStreamContext *sc = st->priv_data;
10337 670 int j = 0;
10338
10339 /* Find an enhancement stream. */
10340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 670 times.
670 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC ||
10341 !(sc->tref_flags & MOV_TREF_FLAG_ENHANCEMENT))
10342 670 continue;
10343
10344 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10345
10346 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
10347 if (!stg)
10348 return AVERROR(ENOMEM);
10349
10350 stg->id = st->id;
10351 stg->params.lcevc->width = st->codecpar->width;
10352 stg->params.lcevc->height = st->codecpar->height;
10353 st->codecpar->width = 0;
10354 st->codecpar->height = 0;
10355
10356 while (st_base = mov_find_reference_track(s, st, j)) {
10357 err = avformat_stream_group_add_stream(stg, st_base);
10358 if (err < 0)
10359 return err;
10360
10361 j = st_base->index + 1;
10362 }
10363 if (!j) {
10364 av_log(s, AV_LOG_ERROR, "Failed to find base stream for enhancement stream\n");
10365 return AVERROR_INVALIDDATA;
10366 }
10367
10368 err = avformat_stream_group_add_stream(stg, st);
10369 if (err < 0)
10370 return err;
10371
10372 stg->params.lcevc->lcevc_index = stg->nb_streams - 1;
10373 }
10374
10375 492 return 0;
10376 }
10377
10378 492 static int mov_read_header(AVFormatContext *s)
10379 {
10380 492 MOVContext *mov = s->priv_data;
10381 492 AVIOContext *pb = s->pb;
10382 int j, err;
10383 492 MOVAtom atom = { AV_RL32("root") };
10384 int i;
10385
10386
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 489 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
492 if (mov->decryption_key_len != 0 && mov->decryption_key_len != AES_CTR_KEY_SIZE) {
10387 av_log(s, AV_LOG_ERROR, "Invalid decryption key len %d expected %d\n",
10388 mov->decryption_key_len, AES_CTR_KEY_SIZE);
10389 return AVERROR(EINVAL);
10390 }
10391
10392 492 mov->fc = s;
10393 492 mov->trak_index = -1;
10394 492 mov->thmb_item_id = -1;
10395 492 mov->primary_item_id = -1;
10396 492 mov->cur_item_id = -1;
10397 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
10398
1/2
✓ Branch 0 taken 492 times.
✗ Branch 1 not taken.
492 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
10399 492 atom.size = avio_size(pb);
10400 else
10401 atom.size = INT64_MAX;
10402
10403 /* check MOV header */
10404 do {
10405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 492 times.
492 if (mov->moov_retry)
10406 avio_seek(pb, 0, SEEK_SET);
10407
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 492 times.
492 if ((err = mov_read_default(mov, pb, atom)) < 0) {
10408 av_log(s, AV_LOG_ERROR, "error reading header\n");
10409 return err;
10410 }
10411 984 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10412
5/10
✓ Branch 0 taken 492 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 480 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.
492 !mov->found_moov && (!mov->found_iloc || !mov->found_iinf) && !mov->moov_retry++);
10413
3/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 480 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
492 if (!mov->found_moov && !mov->found_iloc && !mov->found_iinf) {
10414 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
10415 return AVERROR_INVALIDDATA;
10416 }
10417 492 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
10418
10419
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 480 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
492 if (mov->found_iloc && mov->found_iinf) {
10420 12 err = mov_parse_heif_items(s);
10421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (err < 0)
10422 return err;
10423 }
10424 // prevent iloc and iinf boxes from being parsed while reading packets.
10425 // this is needed because an iinf box may have been parsed but ignored
10426 // for having old infe boxes which create no streams.
10427 492 mov->found_iloc = mov->found_iinf = 1;
10428
10429
1/2
✓ Branch 0 taken 492 times.
✗ Branch 1 not taken.
492 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
10430
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 490 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
492 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
10431 2 mov_read_chapters(s);
10432
2/2
✓ Branch 0 taken 670 times.
✓ Branch 1 taken 492 times.
1162 for (i = 0; i < s->nb_streams; i++)
10433
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 651 times.
670 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
10434 19 mov_read_timecode_track(s, s->streams[i]);
10435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 651 times.
651 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
10436 mov_read_rtmd_track(s, s->streams[i]);
10437 }
10438 }
10439
10440 /* copy timecode metadata from tmcd tracks to the related video streams */
10441
2/2
✓ Branch 0 taken 670 times.
✓ Branch 1 taken 492 times.
1162 for (i = 0; i < s->nb_streams; i++) {
10442 670 AVStream *st = s->streams[i];
10443 670 MOVStreamContext *sc = st->priv_data;
10444
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 652 times.
670 if (sc->timecode_track > 0) {
10445 AVDictionaryEntry *tcr;
10446 18 int tmcd_st_id = -1;
10447
10448
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 18 times.
66 for (j = 0; j < s->nb_streams; j++) {
10449 48 MOVStreamContext *sc2 = s->streams[j]->priv_data;
10450
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 30 times.
48 if (sc2->id == sc->timecode_track)
10451 18 tmcd_st_id = j;
10452 }
10453
10454
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)
10455 continue;
10456 18 tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
10457
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 if (tcr)
10458 16 av_dict_set(&st->metadata, "timecode", tcr->value, 0);
10459 }
10460 }
10461 492 export_orphan_timecode(s);
10462
10463 /* Create LCEVC stream groups. */
10464 492 err = mov_parse_lcevc_streams(s);
10465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 492 times.
492 if (err < 0)
10466 return err;
10467
10468
2/2
✓ Branch 0 taken 670 times.
✓ Branch 1 taken 492 times.
1162 for (i = 0; i < s->nb_streams; i++) {
10469 670 AVStream *st = s->streams[i];
10470 670 FFStream *const sti = ffstream(st);
10471 670 MOVStreamContext *sc = st->priv_data;
10472 670 fix_timescale(mov, sc);
10473
2/2
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 389 times.
670 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
10474
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 165 times.
281 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
10475 116 sti->skip_samples = sc->start_pad;
10476 }
10477
5/6
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 332 times.
✓ Branch 2 taken 301 times.
✓ Branch 3 taken 37 times.
✓ Branch 4 taken 301 times.
✗ Branch 5 not taken.
670 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
10478 301 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
10479 301 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
10480
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 662 times.
670 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
10481
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) {
10482 4 st->codecpar->width = sc->width;
10483 4 st->codecpar->height = sc->height;
10484 }
10485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE) {
10486 if ((err = mov_rewrite_dvd_sub_extradata(st)) < 0)
10487 return err;
10488 }
10489 }
10490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 670 times.
670 if (mov->handbrake_version &&
10491 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
10492 st->codecpar->codec_id == AV_CODEC_ID_MP3) {
10493 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
10494 sti->need_parsing = AVSTREAM_PARSE_FULL;
10495 }
10496 }
10497
10498
3/4
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 480 times.
492 if (mov->trex_data || mov->use_mfra_for > 0) {
10499
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 12 times.
29 for (i = 0; i < s->nb_streams; i++) {
10500 17 AVStream *st = s->streams[i];
10501 17 MOVStreamContext *sc = st->priv_data;
10502
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 3 times.
17 if (sc->duration_for_fps > 0) {
10503 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
10504 14 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
10505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (st->codecpar->bit_rate == INT64_MIN) {
10506 av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
10507 sc->data_size, sc->time_scale);
10508 st->codecpar->bit_rate = 0;
10509 if (s->error_recognition & AV_EF_EXPLODE)
10510 return AVERROR_INVALIDDATA;
10511 }
10512 }
10513 }
10514 }
10515
10516
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 492 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
492 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
10517 if (mov->bitrates[i]) {
10518 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
10519 }
10520 }
10521
10522 492 ff_rfps_calculate(s);
10523
10524
2/2
✓ Branch 0 taken 670 times.
✓ Branch 1 taken 492 times.
1162 for (i = 0; i < s->nb_streams; i++) {
10525 670 AVStream *st = s->streams[i];
10526 670 MOVStreamContext *sc = st->priv_data;
10527
10528
3/3
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 338 times.
✓ Branch 2 taken 51 times.
670 switch (st->codecpar->codec_type) {
10529 281 case AVMEDIA_TYPE_AUDIO:
10530 281 err = ff_replaygain_export(st, s->metadata);
10531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 281 times.
281 if (err < 0)
10532 return err;
10533 281 break;
10534 338 case AVMEDIA_TYPE_VIDEO:
10535
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 330 times.
338 if (sc->display_matrix) {
10536
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,
10537 AV_PKT_DATA_DISPLAYMATRIX,
10538 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
10539 return AVERROR(ENOMEM);
10540
10541 8 sc->display_matrix = NULL;
10542 }
10543
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 334 times.
338 if (sc->stereo3d) {
10544
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,
10545 AV_PKT_DATA_STEREO3D,
10546 4 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
10547 return AVERROR(ENOMEM);
10548
10549 4 sc->stereo3d = NULL;
10550 }
10551
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 334 times.
338 if (sc->spherical) {
10552
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,
10553 AV_PKT_DATA_SPHERICAL,
10554 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
10555 return AVERROR(ENOMEM);
10556
10557 4 sc->spherical = NULL;
10558 }
10559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
338 if (sc->mastering) {
10560 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10561 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
10562 (uint8_t *)sc->mastering, sc->mastering_size, 0))
10563 return AVERROR(ENOMEM);
10564
10565 sc->mastering = NULL;
10566 }
10567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
338 if (sc->coll) {
10568 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10569 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
10570 (uint8_t *)sc->coll, sc->coll_size, 0))
10571 return AVERROR(ENOMEM);
10572
10573 sc->coll = NULL;
10574 }
10575
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 334 times.
338 if (sc->ambient) {
10576
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,
10577 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
10578 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
10579 return AVERROR(ENOMEM);
10580
10581 4 sc->ambient = NULL;
10582 }
10583 338 break;
10584 }
10585 }
10586 492 ff_configure_buffers_for_index(s, AV_TIME_BASE);
10587
10588
2/2
✓ Branch 0 taken 389 times.
✓ Branch 1 taken 492 times.
881 for (i = 0; i < mov->frag_index.nb_items; i++)
10589
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)
10590 385 mov->frag_index.item[i].headers_read = 1;
10591
10592 492 return 0;
10593 }
10594
10595 103905 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
10596 {
10597 103905 AVIndexEntry *sample = NULL;
10598 103905 int64_t best_dts = INT64_MAX;
10599 int i;
10600 103905 MOVContext *mov = s->priv_data;
10601
2/4
✓ Branch 0 taken 103905 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 103905 times.
103905 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
10602
2/2
✓ Branch 0 taken 133891 times.
✓ Branch 1 taken 103905 times.
237796 for (i = 0; i < s->nb_streams; i++) {
10603 133891 AVStream *avst = s->streams[i];
10604 133891 FFStream *const avsti = ffstream(avst);
10605 133891 MOVStreamContext *msc = avst->priv_data;
10606
4/4
✓ Branch 0 taken 125653 times.
✓ Branch 1 taken 8238 times.
✓ Branch 2 taken 122376 times.
✓ Branch 3 taken 3277 times.
133891 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
10607 122376 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
10608 122376 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
10609
2/2
✓ Branch 0 taken 108636 times.
✓ Branch 1 taken 13740 times.
122376 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
10610 122376 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
10611
3/6
✓ Branch 0 taken 18958 times.
✓ Branch 1 taken 103418 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18958 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
122376 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
10612
1/2
✓ Branch 0 taken 18958 times.
✗ Branch 1 not taken.
18958 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10613
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 18958 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 18958 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18958 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 16830 times.
✓ Branch 9 taken 2128 times.
18958 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
10614
4/4
✓ Branch 0 taken 8692 times.
✓ Branch 1 taken 8138 times.
✓ Branch 2 taken 2128 times.
✓ Branch 3 taken 8692 times.
18958 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
10615
2/2
✓ Branch 0 taken 715 times.
✓ Branch 1 taken 1413 times.
2128 (dtsdiff > AV_TIME_BASE && dts < best_dts)))))) {
10616 112271 sample = current_sample;
10617 112271 best_dts = dts;
10618 112271 *st = avst;
10619 }
10620 }
10621 }
10622 103905 return sample;
10623 }
10624
10625 9 static int should_retry(AVIOContext *pb, int error_code) {
10626
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))
10627 9 return 0;
10628
10629 return 1;
10630 }
10631
10632 42 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
10633 {
10634 int ret;
10635 42 MOVContext *mov = s->priv_data;
10636
10637
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)
10638 target = mov->frag_index.item[index].moof_offset;
10639
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) {
10640 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
10641 return AVERROR_INVALIDDATA;
10642 }
10643
10644 42 mov->next_root_atom = 0;
10645
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)
10646 42 index = search_frag_moof_offset(&mov->frag_index, target);
10647
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 &&
10648
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 mov->frag_index.item[index].moof_offset == target) {
10649
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (index + 1 < mov->frag_index.nb_items)
10650 35 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
10651
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (mov->frag_index.item[index].headers_read)
10652 35 return 0;
10653 3 mov->frag_index.item[index].headers_read = 1;
10654 }
10655
10656 7 mov->found_mdat = 0;
10657
10658 7 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
10659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
10660 return ret;
10661
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 3 times.
7 if (avio_feof(s->pb))
10662 4 return AVERROR_EOF;
10663 3 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
10664
10665 3 return 1;
10666 }
10667
10668 16 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
10669 {
10670 16 MOVStreamContext *sc = st->priv_data;
10671 uint8_t *side, *extradata;
10672 int extradata_size;
10673
10674 /* Save the current index. */
10675 16 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
10676
10677 /* Notify the decoder that extradata changed. */
10678 16 extradata_size = sc->extradata_size[sc->last_stsd_index];
10679 16 extradata = sc->extradata[sc->last_stsd_index];
10680
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) {
10681 13 side = av_packet_new_side_data(pkt,
10682 AV_PKT_DATA_NEW_EXTRADATA,
10683 extradata_size);
10684
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!side)
10685 return AVERROR(ENOMEM);
10686 13 memcpy(side, extradata, extradata_size);
10687 }
10688
10689 16 return 0;
10690 }
10691
10692 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int size)
10693 {
10694 int new_size, ret;
10695
10696 if (size <= 8)
10697 return AVERROR_INVALIDDATA;
10698 new_size = ((size - 8) / 2) * 3;
10699 ret = av_new_packet(pkt, new_size);
10700 if (ret < 0)
10701 return ret;
10702
10703 avio_skip(pb, 8);
10704 for (int j = 0; j < new_size; j += 3) {
10705 pkt->data[j] = 0xFC;
10706 pkt->data[j+1] = avio_r8(pb);
10707 pkt->data[j+2] = avio_r8(pb);
10708 }
10709
10710 return 0;
10711 }
10712
10713 103374 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
10714 int64_t current_index, AVPacket *pkt)
10715 {
10716 103374 MOVStreamContext *sc = st->priv_data;
10717
10718 103374 pkt->stream_index = sc->ffindex;
10719 103374 pkt->dts = sample->timestamp;
10720
2/2
✓ Branch 0 taken 237 times.
✓ Branch 1 taken 103137 times.
103374 if (sample->flags & AVINDEX_DISCARD_FRAME) {
10721 237 pkt->flags |= AV_PKT_FLAG_DISCARD;
10722 }
10723
3/4
✓ Branch 0 taken 3677 times.
✓ Branch 1 taken 99697 times.
✓ Branch 2 taken 3677 times.
✗ Branch 3 not taken.
103374 if (sc->ctts_data && sc->ctts_index < sc->ctts_count) {
10724 3677 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->ctts_data[sc->ctts_index].duration));
10725 /* update ctts context */
10726 3677 sc->ctts_sample++;
10727
1/2
✓ Branch 0 taken 3677 times.
✗ Branch 1 not taken.
3677 if (sc->ctts_index < sc->ctts_count &&
10728
1/2
✓ Branch 0 taken 3677 times.
✗ Branch 1 not taken.
3677 sc->ctts_data[sc->ctts_index].count == sc->ctts_sample) {
10729 3677 sc->ctts_index++;
10730 3677 sc->ctts_sample = 0;
10731 }
10732 } else {
10733 99697 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
10734
2/2
✓ Branch 0 taken 99200 times.
✓ Branch 1 taken 497 times.
99697 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
10735
10736
2/2
✓ Branch 0 taken 99667 times.
✓ Branch 1 taken 30 times.
99697 if (next_dts >= pkt->dts)
10737 99667 pkt->duration = next_dts - pkt->dts;
10738 99697 pkt->pts = pkt->dts;
10739 }
10740
10741
4/4
✓ Branch 0 taken 1037 times.
✓ Branch 1 taken 102337 times.
✓ Branch 2 taken 905 times.
✓ Branch 3 taken 132 times.
103374 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
10742 905 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
10743 905 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
10744
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;
10745 }
10746 103374 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
10747 103374 pkt->pos = sample->pos;
10748
10749 /* Multiple stsd handling. */
10750
2/2
✓ Branch 0 taken 102583 times.
✓ Branch 1 taken 791 times.
103374 if (sc->stsc_data) {
10751
1/2
✓ Branch 0 taken 102583 times.
✗ Branch 1 not taken.
102583 if (sc->stsc_data[sc->stsc_index].id > 0 &&
10752
2/2
✓ Branch 0 taken 102560 times.
✓ Branch 1 taken 23 times.
102583 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
10753
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 102544 times.
102560 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
10754 16 int ret = mov_change_extradata(st, pkt);
10755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0)
10756 return ret;
10757 }
10758
10759 /* Update the stsc index for the next sample */
10760 102583 sc->stsc_sample++;
10761
2/2
✓ Branch 1 taken 55183 times.
✓ Branch 2 taken 47400 times.
102583 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
10762
2/2
✓ Branch 1 taken 1190 times.
✓ Branch 2 taken 53993 times.
55183 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
10763 1190 sc->stsc_index++;
10764 1190 sc->stsc_sample = 0;
10765 }
10766 }
10767
10768 103374 return 0;
10769 }
10770
10771 97044 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
10772 {
10773 97044 MOVContext *mov = s->priv_data;
10774 MOVStreamContext *sc;
10775 AVIndexEntry *sample;
10776 97044 AVStream *st = NULL;
10777 97044 FFStream *avsti = NULL;
10778 int64_t current_index;
10779 int ret;
10780 int i;
10781 97044 mov->fc = s;
10782 6861 retry:
10783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103905 times.
103905 if (s->pb->pos == 0) {
10784
10785 // Discard current fragment index
10786 if (mov->frag_index.allocated_size > 0) {
10787 av_freep(&mov->frag_index.item);
10788 mov->frag_index.nb_items = 0;
10789 mov->frag_index.allocated_size = 0;
10790 mov->frag_index.current = -1;
10791 mov->frag_index.complete = 0;
10792 }
10793
10794 for (i = 0; i < s->nb_streams; i++) {
10795 AVStream *avst = s->streams[i];
10796 MOVStreamContext *msc = avst->priv_data;
10797
10798 // Clear current sample
10799 mov_current_sample_set(msc, 0);
10800 msc->ctts_index = 0;
10801
10802 // Discard current index entries
10803 avsti = ffstream(avst);
10804 if (avsti->index_entries_allocated_size > 0) {
10805 av_freep(&avsti->index_entries);
10806 avsti->index_entries_allocated_size = 0;
10807 avsti->nb_index_entries = 0;
10808 }
10809 }
10810
10811 if ((ret = mov_switch_root(s, -1, -1)) < 0)
10812 return ret;
10813 }
10814 103905 sample = mov_find_next_sample(s, &st);
10815
6/6
✓ Branch 0 taken 103418 times.
✓ Branch 1 taken 487 times.
✓ Branch 2 taken 472 times.
✓ Branch 3 taken 102946 times.
✓ Branch 4 taken 35 times.
✓ Branch 5 taken 437 times.
103905 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
10816
2/2
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 42 times.
522 if (!mov->next_root_atom)
10817 480 return AVERROR_EOF;
10818
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)
10819 4 return ret;
10820 38 goto retry;
10821 }
10822 103383 sc = st->priv_data;
10823 /* must be done just before reading, to avoid infinite loop on sample */
10824 103383 current_index = sc->current_index;
10825 103383 mov_current_sample_inc(sc);
10826
10827
2/2
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 102946 times.
103383 if (mov->next_root_atom) {
10828 437 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
10829 437 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
10830 }
10831
10832
2/2
✓ Branch 0 taken 96560 times.
✓ Branch 1 taken 6823 times.
103383 if (st->discard != AVDISCARD_ALL) {
10833 96560 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
10834
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 96553 times.
96560 if (ret64 != sample->pos) {
10835 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
10836 sc->ffindex, sample->pos);
10837
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
10838 mov_current_sample_dec(sc);
10839
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
10840 7 return (int)ret64;
10841 }
10842 return AVERROR_INVALIDDATA;
10843 }
10844
10845
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96553 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96553 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
10846 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
10847 goto retry;
10848 }
10849
10850
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96553 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96553 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
10851 ret = get_eia608_packet(sc->pb, pkt, sample->size);
10852 #if CONFIG_IAMFDEC
10853
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 96498 times.
96553 else if (sc->iamf) {
10854 int64_t pts, dts, pos, duration;
10855 55 int flags, size = sample->size;
10856 55 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
10857 55 pts = pkt->pts; dts = pkt->dts;
10858 55 pos = pkt->pos; flags = pkt->flags;
10859 55 duration = pkt->duration;
10860
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) {
10861 275 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, pkt);
10862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
275 if (ret < 0) {
10863 if (should_retry(sc->pb, ret))
10864 mov_current_sample_dec(sc);
10865 return ret;
10866 }
10867 275 size -= ret;
10868 275 pkt->pts = pts; pkt->dts = dts;
10869 275 pkt->pos = pos; pkt->flags |= flags;
10870 275 pkt->duration = duration;
10871 275 ret = ff_buffer_packet(s, pkt);
10872 }
10873
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 if (!ret)
10874 55 return FFERROR_REDO;
10875 }
10876 #endif
10877 else
10878 96498 ret = av_get_packet(sc->pb, pkt, sample->size);
10879
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 96496 times.
96498 if (ret < 0) {
10880
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (should_retry(sc->pb, ret)) {
10881 mov_current_sample_dec(sc);
10882 }
10883 2 return ret;
10884 }
10885 #if CONFIG_DV_DEMUXER
10886
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96496 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96496 if (mov->dv_demux && sc->dv_audio_container) {
10887 ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
10888 av_packet_unref(pkt);
10889 if (ret < 0)
10890 return ret;
10891 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
10892 if (ret < 0)
10893 return ret;
10894 }
10895 #endif
10896
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 96478 times.
96496 if (sc->has_palette) {
10897 uint8_t *pal;
10898
10899 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
10900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
10901 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
10902 } else {
10903 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
10904 18 sc->has_palette = 0;
10905 }
10906 }
10907
4/6
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 96208 times.
✓ Branch 3 taken 288 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 288 times.
✗ Branch 6 not taken.
96496 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
10908
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 288 times.
288 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
10909 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
10910 }
10911 }
10912
10913 103319 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
10914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103319 times.
103319 if (ret < 0)
10915 return ret;
10916
10917
2/2
✓ Branch 0 taken 6823 times.
✓ Branch 1 taken 96496 times.
103319 if (st->discard == AVDISCARD_ALL)
10918 6823 goto retry;
10919
10920
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96496 times.
96496 if (mov->aax_mode)
10921 aax_filter(pkt->data, pkt->size, mov);
10922
10923 96496 ret = cenc_filter(mov, st, sc, pkt, current_index);
10924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96496 times.
96496 if (ret < 0) {
10925 return ret;
10926 }
10927
10928 96496 return 0;
10929 }
10930
10931 361 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
10932 {
10933 361 MOVContext *mov = s->priv_data;
10934 int index;
10935
10936
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 26 times.
361 if (!mov->frag_index.complete)
10937 335 return 0;
10938
10939 26 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
10940
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 22 times.
26 if (index < 0)
10941 4 index = 0;
10942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (!mov->frag_index.item[index].headers_read)
10943 return mov_switch_root(s, -1, index);
10944
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (index + 1 < mov->frag_index.nb_items)
10945 26 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
10946
10947 26 return 0;
10948 }
10949
10950 static int is_open_key_sample(const MOVStreamContext *sc, int sample)
10951 {
10952 // TODO: a bisect search would scale much better
10953 for (int i = 0; i < sc->open_key_samples_count; i++) {
10954 const int oks = sc->open_key_samples[i];
10955 if (oks == sample)
10956 return 1;
10957 if (oks > sample) /* list is monotically increasing so we can stop early */
10958 break;
10959 }
10960 return 0;
10961 }
10962
10963 /*
10964 * Some key sample may be key frames but not IDR frames, so a random access to
10965 * them may not be allowed.
10966 */
10967 229 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
10968 {
10969 229 MOVStreamContext *sc = st->priv_data;
10970 229 FFStream *const sti = ffstream(st);
10971 int64_t key_sample_dts, key_sample_pts;
10972
10973
1/2
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
229 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
10974 229 return 1;
10975
10976 if (sample >= sc->sample_offsets_count)
10977 return 1;
10978
10979 key_sample_dts = sti->index_entries[sample].timestamp;
10980 key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
10981
10982 /*
10983 * If the sample needs to be presented before an open key sample, they may
10984 * not be decodable properly, even though they come after in decoding
10985 * order.
10986 */
10987 if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
10988 return 0;
10989
10990 return 1;
10991 }
10992
10993 361 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
10994 {
10995 361 MOVStreamContext *sc = st->priv_data;
10996 361 FFStream *const sti = ffstream(st);
10997 int sample, time_sample, ret, next_ts, requested_sample;
10998 unsigned int i;
10999
11000 // Here we consider timestamp to be PTS, hence try to offset it so that we
11001 // can search over the DTS timeline.
11002 361 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
11003
11004 361 ret = mov_seek_fragment(s, st, timestamp);
11005
1/2
✓ Branch 0 taken 361 times.
✗ Branch 1 not taken.
361 if (ret < 0)
11006 return ret;
11007
11008 for (;;) {
11009 361 sample = av_index_search_timestamp(st, timestamp, flags);
11010 361 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
11011
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)
11012 43 sample = 0;
11013
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 335 times.
361 if (sample < 0) /* not sure what to do */
11014 26 return AVERROR_INVALIDDATA;
11015
11016
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))
11017 break;
11018
11019 next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
11020 requested_sample = av_index_search_timestamp(st, next_ts, flags);
11021
11022 // If we've reached a different sample trying to find a good pts to
11023 // seek to, give up searching because we'll end up seeking back to
11024 // sample 0 on every seek.
11025 if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
11026 break;
11027
11028 timestamp = next_ts;
11029 }
11030
11031 335 mov_current_sample_set(sc, sample);
11032 335 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
11033 /* adjust ctts index */
11034
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 263 times.
335 if (sc->ctts_data) {
11035 72 time_sample = 0;
11036
1/2
✓ Branch 0 taken 57972 times.
✗ Branch 1 not taken.
57972 for (i = 0; i < sc->ctts_count; i++) {
11037 57972 int next = time_sample + sc->ctts_data[i].count;
11038
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 57900 times.
57972 if (next > sc->current_sample) {
11039 72 sc->ctts_index = i;
11040 72 sc->ctts_sample = sc->current_sample - time_sample;
11041 72 break;
11042 }
11043 57900 time_sample = next;
11044 }
11045 }
11046
11047 /* adjust stsd index */
11048
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 26 times.
335 if (sc->chunk_count) {
11049 309 time_sample = 0;
11050
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
381 for (i = 0; i < sc->stsc_count; i++) {
11051 381 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
11052
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 72 times.
381 if (next > sc->current_sample) {
11053 309 sc->stsc_index = i;
11054 309 sc->stsc_sample = sc->current_sample - time_sample;
11055 309 break;
11056 }
11057
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
11058 72 time_sample = next;
11059 }
11060 }
11061
11062 335 return sample;
11063 }
11064
11065 335 static int64_t mov_get_skip_samples(AVStream *st, int sample)
11066 {
11067 335 MOVStreamContext *sc = st->priv_data;
11068 335 FFStream *const sti = ffstream(st);
11069 335 int64_t first_ts = sti->index_entries[0].timestamp;
11070 335 int64_t ts = sti->index_entries[sample].timestamp;
11071 int64_t off;
11072
11073
2/2
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 151 times.
335 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
11074 184 return 0;
11075
11076 /* compute skip samples according to stream start_pad, seek ts and first ts */
11077 151 off = av_rescale_q(ts - first_ts, st->time_base,
11078 151 (AVRational){1, st->codecpar->sample_rate});
11079 151 return FFMAX(sc->start_pad - off, 0);
11080 }
11081
11082 340 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
11083 {
11084 340 MOVContext *mc = s->priv_data;
11085 AVStream *st;
11086 FFStream *sti;
11087 int sample;
11088 int i;
11089
11090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 340 times.
340 if (stream_index >= s->nb_streams)
11091 return AVERROR_INVALIDDATA;
11092
11093 340 st = s->streams[stream_index];
11094 340 sti = ffstream(st);
11095 340 sample = mov_seek_stream(s, st, sample_time, flags);
11096
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 314 times.
340 if (sample < 0)
11097 26 return sample;
11098
11099
1/2
✓ Branch 0 taken 314 times.
✗ Branch 1 not taken.
314 if (mc->seek_individually) {
11100 /* adjust seek timestamp to found sample timestamp */
11101 314 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
11102 314 sti->skip_samples = mov_get_skip_samples(st, sample);
11103
11104
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 314 times.
649 for (i = 0; i < s->nb_streams; i++) {
11105 335 AVStream *const st = s->streams[i];
11106 335 FFStream *const sti = ffstream(st);
11107 int64_t timestamp;
11108
11109
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 21 times.
335 if (stream_index == i)
11110 314 continue;
11111
11112 21 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
11113 21 sample = mov_seek_stream(s, st, timestamp, flags);
11114
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (sample >= 0)
11115 21 sti->skip_samples = mov_get_skip_samples(st, sample);
11116 }
11117 } else {
11118 for (i = 0; i < s->nb_streams; i++) {
11119 MOVStreamContext *sc;
11120 st = s->streams[i];
11121 sc = st->priv_data;
11122 mov_current_sample_set(sc, 0);
11123 }
11124 while (1) {
11125 MOVStreamContext *sc;
11126 AVIndexEntry *entry = mov_find_next_sample(s, &st);
11127 if (!entry)
11128 return AVERROR_INVALIDDATA;
11129 sc = st->priv_data;
11130 if (sc->ffindex == stream_index && sc->current_sample == sample)
11131 break;
11132 mov_current_sample_inc(sc);
11133 }
11134 }
11135 314 return 0;
11136 }
11137
11138 #define OFFSET(x) offsetof(MOVContext, x)
11139 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
11140 static const AVOption mov_options[] = {
11141 {"use_absolute_path",
11142 "allow using absolute path when opening alias, this is a possible security issue",
11143 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
11144 0, 1, FLAGS},
11145 {"seek_streams_individually",
11146 "Seek each stream individually to the closest point",
11147 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
11148 0, 1, FLAGS},
11149 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
11150 0, 1, FLAGS},
11151 {"advanced_editlist",
11152 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
11153 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
11154 0, 1, FLAGS},
11155 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
11156 0, 1, FLAGS},
11157 {"use_mfra_for",
11158 "use mfra for fragment timestamps",
11159 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
11160 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
11161 .unit = "use_mfra_for"},
11162 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
11163 FLAGS, .unit = "use_mfra_for" },
11164 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
11165 FLAGS, .unit = "use_mfra_for" },
11166 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
11167 FLAGS, .unit = "use_mfra_for" },
11168 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
11169 0, 1, FLAGS},
11170 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
11171 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11172 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
11173 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11174 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
11175 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11176 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
11177 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11178 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
11179 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11180 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
11181 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
11182 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
11183 .flags = AV_OPT_FLAG_DECODING_PARAM },
11184 { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11185 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
11186 {.i64 = 0}, 0, 1, FLAGS },
11187 { "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 },
11188 { "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 },
11189
11190 { NULL },
11191 };
11192
11193 static const AVClass mov_class = {
11194 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
11195 .item_name = av_default_item_name,
11196 .option = mov_options,
11197 .version = LIBAVUTIL_VERSION_INT,
11198 };
11199
11200 const FFInputFormat ff_mov_demuxer = {
11201 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
11202 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
11203 .p.priv_class = &mov_class,
11204 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v,avif,heic,heif",
11205 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
11206 .priv_data_size = sizeof(MOVContext),
11207 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
11208 .read_probe = mov_probe,
11209 .read_header = mov_read_header,
11210 .read_packet = mov_read_packet,
11211 .read_close = mov_read_close,
11212 .read_seek = mov_read_seek,
11213 };
11214