FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2025-01-20 09:27:23
Exec Total Coverage
Lines: 4257 6737 63.2%
Functions: 172 211 81.5%
Branches: 2386 4512 52.9%

Line Branch Exec Source
1 /*
2 * MOV demuxer
3 * Copyright (c) 2001 Fabrice Bellard
4 * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
5 *
6 * first version by Francois Revol <revol@free.fr>
7 * seek function by Gael Chardon <gael.dev@4now.net>
8 *
9 * This file is part of FFmpeg.
10 *
11 * FFmpeg is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * FFmpeg is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with FFmpeg; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #include "config_components.h"
27
28 #include <inttypes.h>
29 #include <limits.h>
30 #include <stdint.h>
31
32 #include "libavutil/attributes.h"
33 #include "libavutil/bprint.h"
34 #include "libavutil/channel_layout.h"
35 #include "libavutil/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 "dvdclut.h"
64 #include "iamf_parse.h"
65 #include "iamf_reader.h"
66 #include "dovi_isom.h"
67 #include "riff.h"
68 #include "isom.h"
69 #include "libavcodec/get_bits.h"
70 #include "id3v1.h"
71 #include "mov_chan.h"
72 #include "replaygain.h"
73
74 #if CONFIG_ZLIB
75 #include <zlib.h>
76 #endif
77
78 #include "qtpalette.h"
79
80 /* those functions parse an atom */
81 /* links atom IDs to parse functions */
82 typedef struct MOVParseTableEntry {
83 uint32_t type;
84 int (*parse)(MOVContext *ctx, AVIOContext *pb, MOVAtom atom);
85 } MOVParseTableEntry;
86
87 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom);
88 static int mov_read_mfra(MOVContext *c, AVIOContext *f);
89 static void mov_free_stream_context(AVFormatContext *s, AVStream *st);
90
91 24 static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
92 unsigned len, const char *key)
93 {
94 char buf[16];
95
96 24 short current, total = 0;
97 24 avio_rb16(pb); // unknown
98 24 current = avio_rb16(pb);
99
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (len >= 6)
100 24 total = avio_rb16(pb);
101
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19 times.
24 if (!total)
102 5 snprintf(buf, sizeof(buf), "%d", current);
103 else
104 19 snprintf(buf, sizeof(buf), "%d/%d", current, total);
105 24 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
106 24 av_dict_set(&c->fc->metadata, key, buf, 0);
107
108 24 return 0;
109 }
110
111 static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
112 unsigned len, const char *key)
113 {
114 /* bypass padding bytes */
115 avio_r8(pb);
116 avio_r8(pb);
117 avio_r8(pb);
118
119 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
120 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
121
122 return 0;
123 }
124
125 26 static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
126 unsigned len, const char *key)
127 {
128 26 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
129 26 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
130
131 26 return 0;
132 }
133
134 10 static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
135 unsigned len, const char *key)
136 {
137 short genre;
138
139 10 avio_r8(pb); // unknown
140
141 10 genre = avio_r8(pb);
142
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (genre < 1 || genre > ID3v1_GENRE_MAX)
143 return 0;
144 10 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
145 10 av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
146
147 10 return 0;
148 }
149
150 static const uint32_t mac_to_unicode[128] = {
151 0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
152 0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
153 0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,
154 0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,
155 0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,
156 0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,
157 0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,
158 0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,
159 0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,
160 0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,
161 0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,
162 0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,
163 0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,
164 0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,
165 0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,
166 0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7,
167 };
168
169 325 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
170 char *dst, int dstlen)
171 {
172 325 char *p = dst;
173 325 char *end = dst+dstlen-1;
174 int i;
175
176
2/2
✓ Branch 0 taken 2858 times.
✓ Branch 1 taken 325 times.
3183 for (i = 0; i < len; i++) {
177 2858 uint8_t t, c = avio_r8(pb);
178
179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2858 times.
2858 if (p >= end)
180 continue;
181
182
2/2
✓ Branch 0 taken 2855 times.
✓ Branch 1 taken 3 times.
2858 if (c < 0x80)
183 2855 *p++ = c;
184
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 else if (p < end)
185
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;);
186 }
187 325 *p = 0;
188 325 return p - dst;
189 }
190
191 /**
192 * Get the current item in the parsing process.
193 */
194 82 static HEIFItem *heif_cur_item(MOVContext *c)
195 {
196 82 HEIFItem *item = NULL;
197
198
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 12 times.
138 for (int i = 0; i < c->nb_heif_item; i++) {
199
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)
200 56 continue;
201
202 70 item = c->heif_item[i];
203 70 break;
204 }
205
206 82 return item;
207 }
208
209 /**
210 * Get the current stream in the parsing process. This can either be the
211 * latest stream added to the context, or the stream referenced by an item.
212 */
213 197 static AVStream *get_curr_st(MOVContext *c)
214 {
215 197 AVStream *st = NULL;
216 HEIFItem *item;
217
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
197 if (c->fc->nb_streams < 1)
219 return NULL;
220
221
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 29 times.
197 if (c->cur_item_id == -1)
222 168 return c->fc->streams[c->fc->nb_streams-1];
223
224 29 item = heif_cur_item(c);
225
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (item)
226 29 st = item->st;
227
228 29 return st;
229 }
230
231 14 static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
232 {
233 AVStream *st;
234 MOVStreamContext *sc;
235 enum AVCodecID id;
236 int ret;
237
238
2/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
14 switch (type) {
239 7 case 0xd: id = AV_CODEC_ID_MJPEG; break;
240 7 case 0xe: id = AV_CODEC_ID_PNG; break;
241 case 0x1b: id = AV_CODEC_ID_BMP; break;
242 default:
243 av_log(c->fc, AV_LOG_WARNING, "Unknown cover type: 0x%x.\n", type);
244 avio_skip(pb, len);
245 return 0;
246 }
247
248 14 sc = av_mallocz(sizeof(*sc));
249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!sc)
250 return AVERROR(ENOMEM);
251 14 ret = ff_add_attached_pic(c->fc, NULL, pb, NULL, len);
252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0) {
253 av_free(sc);
254 return ret;
255 }
256 14 st = c->fc->streams[c->fc->nb_streams - 1];
257 14 st->priv_data = sc;
258 14 sc->id = st->id;
259 14 sc->refcount = 1;
260
261
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 if (st->attached_pic.size >= 8 && id != AV_CODEC_ID_BMP) {
262
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
263 7 id = AV_CODEC_ID_PNG;
264 } else {
265 7 id = AV_CODEC_ID_MJPEG;
266 }
267 }
268 14 st->codecpar->codec_id = id;
269
270 14 return 0;
271 }
272
273 // 3GPP TS 26.244
274 static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
275 {
276 char language[4] = { 0 };
277 char buf[200], place[100];
278 uint16_t langcode = 0;
279 double longitude, latitude, altitude;
280 const char *key = "location";
281
282 if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) {
283 av_log(c->fc, AV_LOG_ERROR, "loci too short\n");
284 return AVERROR_INVALIDDATA;
285 }
286
287 avio_skip(pb, 4); // version+flags
288 langcode = avio_rb16(pb);
289 ff_mov_lang_to_iso639(langcode, language);
290 len -= 6;
291
292 len -= avio_get_str(pb, len, place, sizeof(place));
293 if (len < 1) {
294 av_log(c->fc, AV_LOG_ERROR, "place name too long\n");
295 return AVERROR_INVALIDDATA;
296 }
297 avio_skip(pb, 1); // role
298 len -= 1;
299
300 if (len < 12) {
301 av_log(c->fc, AV_LOG_ERROR,
302 "loci too short (%u bytes left, need at least %d)\n", len, 12);
303 return AVERROR_INVALIDDATA;
304 }
305 longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
306 latitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
307 altitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
308
309 // Try to output in the same format as the ?xyz field
310 snprintf(buf, sizeof(buf), "%+08.4f%+09.4f", latitude, longitude);
311 if (altitude)
312 av_strlcatf(buf, sizeof(buf), "%+f", altitude);
313 av_strlcatf(buf, sizeof(buf), "/%s", place);
314
315 if (*language && strcmp(language, "und")) {
316 char key2[16];
317 snprintf(key2, sizeof(key2), "%s-%s", key, language);
318 av_dict_set(&c->fc->metadata, key2, buf, 0);
319 }
320 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
321 return av_dict_set(&c->fc->metadata, key, buf, 0);
322 }
323
324 static int mov_metadata_hmmt(MOVContext *c, AVIOContext *pb, unsigned len)
325 {
326 int i, n_hmmt;
327
328 if (len < 2)
329 return 0;
330 if (c->ignore_chapters)
331 return 0;
332
333 n_hmmt = avio_rb32(pb);
334 if (n_hmmt > len / 4)
335 return AVERROR_INVALIDDATA;
336 for (i = 0; i < n_hmmt && !pb->eof_reached; i++) {
337 int moment_time = avio_rb32(pb);
338 avpriv_new_chapter(c->fc, i, av_make_q(1, 1000), moment_time, AV_NOPTS_VALUE, NULL);
339 }
340 if (avio_feof(pb))
341 return AVERROR_INVALIDDATA;
342 return 0;
343 }
344
345 466 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
346 {
347 466 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
348 466 char key2[32], language[4] = {0};
349 466 char *str = NULL;
350 466 const char *key = NULL;
351 466 uint16_t langcode = 0;
352 466 uint32_t data_type = 0, str_size_alloc;
353 uint64_t str_size;
354 466 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
355 466 int raw = 0;
356 466 int num = 0;
357
358
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) {
359 3 case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break;
360 3 case MKTAG( '@','P','R','Q'): key = "quicktime_version"; raw = 1; break;
361 2 case MKTAG( 'X','M','P','_'):
362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->export_xmp) { key = "xmp"; raw = 1; } break;
363 12 case MKTAG( 'a','A','R','T'): key = "album_artist"; break;
364 case MKTAG( 'a','k','I','D'): key = "account_type";
365 parse = mov_metadata_int8_no_padding; break;
366 case MKTAG( 'a','p','I','D'): key = "account_id"; break;
367 case MKTAG( 'c','a','t','g'): key = "category"; break;
368 13 case MKTAG( 'c','p','i','l'): key = "compilation";
369 13 parse = mov_metadata_int8_no_padding; break;
370 case MKTAG( 'c','p','r','t'): key = "copyright"; break;
371 case MKTAG( 'd','e','s','c'): key = "description"; break;
372 12 case MKTAG( 'd','i','s','k'): key = "disc";
373 12 parse = mov_metadata_track_or_disc_number; break;
374 case MKTAG( 'e','g','i','d'): key = "episode_uid";
375 parse = mov_metadata_int8_no_padding; break;
376 case MKTAG( 'F','I','R','M'): key = "firmware"; raw = 1; break;
377 10 case MKTAG( 'g','n','r','e'): key = "genre";
378 10 parse = mov_metadata_gnre; break;
379 case MKTAG( 'h','d','v','d'): key = "hd_video";
380 parse = mov_metadata_int8_no_padding; break;
381 case MKTAG( 'H','M','M','T'):
382 return mov_metadata_hmmt(c, pb, atom.size);
383 case MKTAG( 'k','e','y','w'): key = "keywords"; break;
384 case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
385 case MKTAG( 'l','o','c','i'):
386 return mov_metadata_loci(c, pb, atom.size);
387 case MKTAG( 'm','a','n','u'): key = "make"; break;
388 case MKTAG( 'm','o','d','l'): key = "model"; break;
389 case MKTAG( 'p','c','s','t'): key = "podcast";
390 parse = mov_metadata_int8_no_padding; break;
391 13 case MKTAG( 'p','g','a','p'): key = "gapless_playback";
392 13 parse = mov_metadata_int8_no_padding; break;
393 case MKTAG( 'p','u','r','d'): key = "purchase_date"; break;
394 case MKTAG( 'r','t','n','g'): key = "rating";
395 parse = mov_metadata_int8_no_padding; break;
396 case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break;
397 case MKTAG( 's','o','a','l'): key = "sort_album"; break;
398 case MKTAG( 's','o','a','r'): key = "sort_artist"; break;
399 case MKTAG( 's','o','c','o'): key = "sort_composer"; break;
400 case MKTAG( 's','o','n','m'): key = "sort_name"; break;
401 case MKTAG( 's','o','s','n'): key = "sort_show"; break;
402 case MKTAG( 's','t','i','k'): key = "media_type";
403 parse = mov_metadata_int8_no_padding; break;
404 12 case MKTAG( 't','r','k','n'): key = "track";
405 12 parse = mov_metadata_track_or_disc_number; break;
406 case MKTAG( 't','v','e','n'): key = "episode_id"; break;
407 case MKTAG( 't','v','e','s'): key = "episode_sort";
408 parse = mov_metadata_int8_bypass_padding; break;
409 case MKTAG( 't','v','n','n'): key = "network"; break;
410 case MKTAG( 't','v','s','h'): key = "show"; break;
411 case MKTAG( 't','v','s','n'): key = "season_number";
412 parse = mov_metadata_int8_bypass_padding; break;
413 16 case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
414 case MKTAG(0xa9,'P','R','D'): key = "producer"; break;
415 16 case MKTAG(0xa9,'a','l','b'): key = "album"; break;
416 3 case MKTAG(0xa9,'a','u','t'): key = "artist"; break;
417 case MKTAG(0xa9,'c','h','p'): key = "chapter"; break;
418 7 case MKTAG(0xa9,'c','m','t'): key = "comment"; break;
419 case MKTAG(0xa9,'c','o','m'): key = "composer"; break;
420 4 case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
421 16 case MKTAG(0xa9,'d','a','y'): key = "date"; break;
422 case MKTAG(0xa9,'d','i','r'): key = "director"; break;
423 case MKTAG(0xa9,'d','i','s'): key = "disclaimer"; break;
424 case MKTAG(0xa9,'e','d','1'): key = "edit_date"; break;
425 2 case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
426 case MKTAG(0xa9,'f','m','t'): key = "original_format"; break;
427 2 case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
428 case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
429 case MKTAG(0xa9,'h','s','t'): key = "host_computer"; break;
430 case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
431 case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
432 5 case MKTAG(0xa9,'m','a','k'): key = "make"; break;
433 5 case MKTAG(0xa9,'m','o','d'): key = "model"; break;
434 40 case MKTAG(0xa9,'n','a','m'): key = "title"; break;
435 case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break;
436 case MKTAG(0xa9,'p','r','d'): key = "producer"; break;
437 case MKTAG(0xa9,'p','r','f'): key = "performers"; break;
438 case MKTAG(0xa9,'r','e','q'): key = "playback_requirements"; break;
439 case MKTAG(0xa9,'s','r','c'): key = "original_source"; break;
440 case MKTAG(0xa9,'s','t','3'): key = "subtitle"; break;
441 58 case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
442 49 case MKTAG(0xa9,'t','o','o'): key = "encoder"; break;
443 case MKTAG(0xa9,'t','r','k'): key = "track"; break;
444 case MKTAG(0xa9,'u','r','l'): key = "URL"; break;
445 case MKTAG(0xa9,'w','r','n'): key = "warning"; break;
446 case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
447 5 case MKTAG(0xa9,'x','y','z'): key = "location"; break;
448 }
449 2 retry:
450
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) {
451 294 int data_size = avio_rb32(pb);
452 294 int tag = avio_rl32(pb);
453
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) {
454 294 data_type = avio_rb32(pb); // type
455 294 avio_rb32(pb); // unknown
456 294 str_size = data_size - 16;
457 294 atom.size -= 16;
458
459
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) {
460 59 uint32_t index = av_bswap32(atom.type); // BE number has been read as LE
461
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) {
462 59 key = c->meta_keys[index];
463 } else if (atom.type != MKTAG('c', 'o', 'v', 'r')) {
464 av_log(c->fc, AV_LOG_WARNING,
465 "The index of 'data' is out of range: %"PRId32" < 1 or >= %d.\n",
466 index, c->meta_keys_count);
467 }
468 }
469
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') ||
470
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 260 times.
260 (key && !strcmp(key, "com.apple.quicktime.artwork"))) {
471 14 int ret = mov_read_covr(c, pb, data_type, str_size);
472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0) {
473 av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
474 return ret;
475 }
476 14 atom.size -= str_size;
477
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (atom.size > 8)
478 2 goto retry;
479 12 return ret;
480 }
481 } else return 0;
482
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) {
483 99 str_size = avio_rb16(pb); // string length
484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (str_size > atom.size) {
485 raw = 1;
486 avio_seek(pb, -2, SEEK_CUR);
487 av_log(c->fc, AV_LOG_WARNING, "UDTA parsing failed retrying raw\n");
488 goto retry;
489 }
490 99 langcode = avio_rb16(pb);
491 99 ff_mov_lang_to_iso639(langcode, language);
492 99 atom.size -= 4;
493 } else
494 75 str_size = atom.size;
495
496
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) {
497 key = av_fourcc_make_string(tmp_key, atom.type);
498 }
499
500
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 365 times.
454 if (!key)
501 89 return 0;
502
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)
503 return AVERROR_INVALIDDATA;
504
505 // Allocates enough space if data_type is a int32 or float32 number, otherwise
506 // worst-case requirement for output string in case of utf8 coded input
507
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);
508
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;
509 365 str = av_mallocz(str_size_alloc);
510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 365 times.
365 if (!str)
511 return AVERROR(ENOMEM);
512
513
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 305 times.
365 if (parse)
514 60 parse(c, pb, str_size, key);
515 else {
516
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
517 14 mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
518
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 289 times.
291 } else if (data_type == 21) { // BE signed integer, variable size
519 2 int val = 0;
520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (str_size == 1)
521 val = (int8_t)avio_r8(pb);
522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 2)
523 val = (int16_t)avio_rb16(pb);
524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 3)
525 val = ((int32_t)(avio_rb24(pb)<<8))>>8;
526
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (str_size == 4)
527 2 val = (int32_t)avio_rb32(pb);
528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
529 av_log(c->fc, AV_LOG_ERROR,
530 "Failed to store the number (%d) in string.\n", val);
531 av_free(str);
532 return AVERROR_INVALIDDATA;
533 }
534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 289 times.
289 } else if (data_type == 22) { // BE unsigned integer, variable size
535 unsigned int val = 0;
536 if (str_size == 1)
537 val = avio_r8(pb);
538 else if (str_size == 2)
539 val = avio_rb16(pb);
540 else if (str_size == 3)
541 val = avio_rb24(pb);
542 else if (str_size == 4)
543 val = avio_rb32(pb);
544 if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
545 av_log(c->fc, AV_LOG_ERROR,
546 "Failed to store the number (%u) in string.\n", val);
547 av_free(str);
548 return AVERROR_INVALIDDATA;
549 }
550
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
551 13 float val = av_int2float(avio_rb32(pb));
552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
553 av_log(c->fc, AV_LOG_ERROR,
554 "Failed to store the float32 number (%f) in string.\n", val);
555 av_free(str);
556 return AVERROR_INVALIDDATA;
557 }
558
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) {
559 // data_type can be 0 if not set at all above. data_type 1 means
560 // UTF8 and 4 means "UTF8 sort". For any other type (UTF16 or e.g.
561 // a picture), don't return it blindly in a string that is supposed
562 // to be UTF8 text.
563 av_log(c->fc, AV_LOG_WARNING, "Skipping unhandled metadata %s of type %d\n", key, data_type);
564 av_free(str);
565 return 0;
566 } else {
567 276 int ret = ffio_read_size(pb, str, str_size);
568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 276 times.
276 if (ret < 0) {
569 av_free(str);
570 return ret;
571 }
572 276 str[str_size] = 0;
573 }
574 305 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
575 305 av_dict_set(&c->fc->metadata, key, str, 0);
576
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")) {
577 37 snprintf(key2, sizeof(key2), "%s-%s", key, language);
578 37 av_dict_set(&c->fc->metadata, key2, str, 0);
579 }
580
2/2
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 196 times.
305 if (!strcmp(key, "encoder")) {
581 int major, minor, micro;
582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 109 times.
109 if (sscanf(str, "HandBrake %d.%d.%d", &major, &minor, &micro) == 3) {
583 c->handbrake_version = 1000000*major + 1000*minor + micro;
584 }
585 }
586 }
587
588 365 av_freep(&str);
589 365 return 0;
590 }
591
592 12 static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
593 {
594 int64_t start;
595 int i, nb_chapters, str_len, version;
596 char str[256+1];
597 int ret;
598
599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->ignore_chapters)
600 return 0;
601
602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if ((atom.size -= 5) < 0)
603 return 0;
604
605 12 version = avio_r8(pb);
606 12 avio_rb24(pb);
607
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (version)
608 12 avio_rb32(pb); // ???
609 12 nb_chapters = avio_r8(pb);
610
611
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
30 for (i = 0; i < nb_chapters; i++) {
612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size < 9)
613 return 0;
614
615 18 start = avio_rb64(pb);
616 18 str_len = avio_r8(pb);
617
618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if ((atom.size -= 9+str_len) < 0)
619 return 0;
620
621 18 ret = ffio_read_size(pb, str, str_len);
622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (ret < 0)
623 return ret;
624 18 str[str_len] = 0;
625 18 avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
626 }
627 12 return 0;
628 }
629
630 #define MIN_DATA_ENTRY_BOX_SIZE 12
631 593 static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
632 {
633 AVStream *st;
634 MOVStreamContext *sc;
635 int entries, i, j;
636
637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->fc->nb_streams < 1)
638 return 0;
639 593 st = c->fc->streams[c->fc->nb_streams-1];
640 593 sc = st->priv_data;
641
642 593 avio_rb32(pb); // version + flags
643 593 entries = avio_rb32(pb);
644
1/2
✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
593 if (!entries ||
645
1/2
✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
593 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 entries >= UINT_MAX / sizeof(*sc->drefs))
647 return AVERROR_INVALIDDATA;
648
649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 for (i = 0; i < sc->drefs_count; i++) {
650 MOVDref *dref = &sc->drefs[i];
651 av_freep(&dref->path);
652 av_freep(&dref->dir);
653 }
654 593 av_free(sc->drefs);
655 593 sc->drefs_count = 0;
656 593 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (!sc->drefs)
658 return AVERROR(ENOMEM);
659 593 sc->drefs_count = entries;
660
661
2/2
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 593 times.
1186 for (i = 0; i < entries; i++) {
662 593 MOVDref *dref = &sc->drefs[i];
663 593 uint32_t size = avio_rb32(pb);
664 593 int64_t next = avio_tell(pb);
665
666
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)
667 return AVERROR_INVALIDDATA;
668
669 593 next += size - 4;
670
671 593 dref->type = avio_rl32(pb);
672 593 avio_rb32(pb); // version + flags
673
674
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) {
675 /* macintosh alias record */
676 uint16_t volume_len, len;
677 int16_t type;
678 int ret;
679
680 avio_skip(pb, 10);
681
682 volume_len = avio_r8(pb);
683 volume_len = FFMIN(volume_len, 27);
684 ret = ffio_read_size(pb, dref->volume, 27);
685 if (ret < 0)
686 return ret;
687 dref->volume[volume_len] = 0;
688 av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
689
690 avio_skip(pb, 12);
691
692 len = avio_r8(pb);
693 len = FFMIN(len, 63);
694 ret = ffio_read_size(pb, dref->filename, 63);
695 if (ret < 0)
696 return ret;
697 dref->filename[len] = 0;
698 av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
699
700 avio_skip(pb, 16);
701
702 /* read next level up_from_alias/down_to_target */
703 dref->nlvl_from = avio_rb16(pb);
704 dref->nlvl_to = avio_rb16(pb);
705 av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
706 dref->nlvl_from, dref->nlvl_to);
707
708 avio_skip(pb, 16);
709
710 for (type = 0; type != -1 && avio_tell(pb) < next; ) {
711 if (avio_feof(pb))
712 return AVERROR_EOF;
713 type = avio_rb16(pb);
714 len = avio_rb16(pb);
715 av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
716 if (len&1)
717 len += 1;
718 if (type == 2) { // absolute path
719 av_free(dref->path);
720 dref->path = av_mallocz(len+1);
721 if (!dref->path)
722 return AVERROR(ENOMEM);
723
724 ret = ffio_read_size(pb, dref->path, len);
725 if (ret < 0) {
726 av_freep(&dref->path);
727 return ret;
728 }
729 if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
730 len -= volume_len;
731 memmove(dref->path, dref->path+volume_len, len);
732 dref->path[len] = 0;
733 }
734 // trim string of any ending zeros
735 for (j = len - 1; j >= 0; j--) {
736 if (dref->path[j] == 0)
737 len--;
738 else
739 break;
740 }
741 for (j = 0; j < len; j++)
742 if (dref->path[j] == ':' || dref->path[j] == 0)
743 dref->path[j] = '/';
744 av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
745 } else if (type == 0) { // directory name
746 av_free(dref->dir);
747 dref->dir = av_malloc(len+1);
748 if (!dref->dir)
749 return AVERROR(ENOMEM);
750
751 ret = ffio_read_size(pb, dref->dir, len);
752 if (ret < 0) {
753 av_freep(&dref->dir);
754 return ret;
755 }
756 dref->dir[len] = 0;
757 for (j = 0; j < len; j++)
758 if (dref->dir[j] == ':')
759 dref->dir[j] = '/';
760 av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
761 } else
762 avio_skip(pb, len);
763 }
764 } else {
765 593 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
766 dref->type, size);
767 593 entries--;
768 593 i--;
769 }
770 593 avio_seek(pb, next, SEEK_SET);
771 }
772 593 return 0;
773 }
774
775 1085 static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
776 {
777 AVStream *st;
778 uint32_t type;
779 uint32_t ctype;
780 int64_t title_size;
781 char *title_str;
782 int ret;
783
784 1085 avio_r8(pb); /* version */
785 1085 avio_rb24(pb); /* flags */
786
787 /* component type */
788 1085 ctype = avio_rl32(pb);
789 1085 type = avio_rl32(pb); /* component subtype */
790
791 1085 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
792 1085 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
793
794
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 950 times.
1085 if (c->trak_index < 0) { // meta not inside a trak
795
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 124 times.
135 if (type == MKTAG('m','d','t','a')) {
796 11 c->found_hdlr_mdta = 1;
797 }
798 135 return 0;
799 }
800
801 950 st = c->fc->streams[c->fc->nb_streams-1];
802
803
2/2
✓ Branch 0 taken 301 times.
✓ Branch 1 taken 649 times.
950 if (type == MKTAG('v','i','d','e'))
804 301 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
805
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 408 times.
649 else if (type == MKTAG('s','o','u','n'))
806 241 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 408 times.
408 else if (type == MKTAG('m','1','a',' '))
808 st->codecpar->codec_id = AV_CODEC_ID_MP2;
809
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')))
810 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
811
812 950 avio_rb32(pb); /* component manufacture */
813 950 avio_rb32(pb); /* component flags */
814 950 avio_rb32(pb); /* component flags mask */
815
816 950 title_size = atom.size - 24;
817
2/2
✓ Branch 0 taken 947 times.
✓ Branch 1 taken 3 times.
950 if (title_size > 0) {
818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 947 times.
947 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
819 return AVERROR_INVALIDDATA;
820 947 title_str = av_malloc(title_size + 1); /* Add null terminator */
821
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 947 times.
947 if (!title_str)
822 return AVERROR(ENOMEM);
823
824 947 ret = ffio_read_size(pb, title_str, title_size);
825
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 947 times.
947 if (ret < 0) {
826 av_freep(&title_str);
827 return ret;
828 }
829 947 title_str[title_size] = 0;
830
2/2
✓ Branch 0 taken 896 times.
✓ Branch 1 taken 51 times.
947 if (title_str[0]) {
831
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);
832 // flag added so as to not set stream handler name if already set from mdia->hdlr
833 896 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
834 }
835 947 av_freep(&title_str);
836 }
837
838 950 return 0;
839 }
840
841 150 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
842 {
843 150 return ff_mov_read_esds(c->fc, pb);
844 }
845
846 7 static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
847 {
848 AVStream *st;
849 AVPacketSideData *sd;
850 enum AVAudioServiceType *ast;
851 int ac3info, acmod, lfeon, bsmod;
852 uint64_t mask;
853
854
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (c->fc->nb_streams < 1)
855 return 0;
856 7 st = c->fc->streams[c->fc->nb_streams-1];
857
858 7 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
859 7 &st->codecpar->nb_coded_side_data,
860 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
861 sizeof(*ast), 0);
862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sd)
863 return AVERROR(ENOMEM);
864
865 7 ast = (enum AVAudioServiceType*)sd->data;
866 7 ac3info = avio_rb24(pb);
867 7 bsmod = (ac3info >> 14) & 0x7;
868 7 acmod = (ac3info >> 11) & 0x7;
869 7 lfeon = (ac3info >> 10) & 0x1;
870
871 7 mask = ff_ac3_channel_layout_tab[acmod];
872
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (lfeon)
873 1 mask |= AV_CH_LOW_FREQUENCY;
874 7 av_channel_layout_uninit(&st->codecpar->ch_layout);
875 7 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
876
877 7 *ast = bsmod;
878
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)
879 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
880
881 7 return 0;
882 }
883
884 #if CONFIG_IAMFDEC
885 10 static int mov_read_iacb(MOVContext *c, AVIOContext *pb, MOVAtom atom)
886 {
887 AVStream *st;
888 MOVStreamContext *sc;
889 FFIOContext b;
890 AVIOContext *descriptor_pb;
891 AVDictionary *metadata;
892 IAMFContext *iamf;
893 int64_t start_time, duration;
894 unsigned descriptors_size;
895 int nb_frames, disposition;
896 int version, ret;
897
898
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (atom.size < 5)
899 return AVERROR_INVALIDDATA;
900
901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (c->fc->nb_streams < 1)
902 return 0;
903
904 10 version = avio_r8(pb);
905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (version != 1) {
906 av_log(c->fc, AV_LOG_ERROR, "%s configurationVersion %d",
907 version < 1 ? "invalid" : "unsupported", version);
908 return AVERROR_INVALIDDATA;
909 }
910
911 10 descriptors_size = ffio_read_leb(pb);
912
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)
913 return AVERROR_INVALIDDATA;
914
915 10 st = c->fc->streams[c->fc->nb_streams - 1];
916 10 sc = st->priv_data;
917
918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (st->codecpar->extradata) {
919 av_log(c->fc, AV_LOG_WARNING, "ignoring iacb\n");
920 return 0;
921 }
922
923 10 sc->iamf = av_mallocz(sizeof(*sc->iamf));
924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!sc->iamf)
925 return AVERROR(ENOMEM);
926 10 iamf = &sc->iamf->iamf;
927
928 10 st->codecpar->extradata = av_malloc(descriptors_size);
929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!st->codecpar->extradata)
930 return AVERROR(ENOMEM);
931 10 st->codecpar->extradata_size = descriptors_size;
932
933 10 ret = avio_read(pb, st->codecpar->extradata, descriptors_size);
934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret != descriptors_size)
935 return ret < 0 ? ret : AVERROR_INVALIDDATA;
936
937 10 ffio_init_read_context(&b, st->codecpar->extradata, descriptors_size);
938 10 descriptor_pb = &b.pub;
939
940 10 ret = ff_iamfdec_read_descriptors(iamf, descriptor_pb, descriptors_size, c->fc);
941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
942 return ret;
943
944 10 metadata = st->metadata;
945 10 st->metadata = NULL;
946 10 start_time = st->start_time;
947 10 nb_frames = st->nb_frames;
948 10 duration = st->duration;
949 10 disposition = st->disposition;
950
951
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_audio_elements; i++) {
952 10 IAMFAudioElement *audio_element = iamf->audio_elements[i];
953 const AVIAMFAudioElement *element;
954 AVStreamGroup *stg =
955 10 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, NULL);
956
957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!stg) {
958 ret = AVERROR(ENOMEM);
959 goto fail;
960 }
961
962 10 av_iamf_audio_element_free(&stg->params.iamf_audio_element);
963 10 stg->id = audio_element->audio_element_id;
964 /* Transfer ownership */
965 10 element = stg->params.iamf_audio_element = audio_element->element;
966 10 audio_element->element = NULL;
967
968
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int j = 0; j < audio_element->nb_substreams; j++) {
969 50 IAMFSubStream *substream = &audio_element->substreams[j];
970 AVStream *stream;
971
972
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) {
973
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (audio_element->layers[0].substream_count != 1)
974 2 disposition &= ~AV_DISPOSITION_DEFAULT;
975 10 stream = st;
976 } else
977 40 stream = avformat_new_stream(c->fc, NULL);
978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (!stream) {
979 ret = AVERROR(ENOMEM);
980 goto fail;
981 }
982
983 50 stream->start_time = start_time;
984 50 stream->nb_frames = nb_frames;
985 50 stream->duration = duration;
986 50 stream->disposition = disposition;
987
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 10 times.
50 if (stream != st) {
988 40 stream->priv_data = sc;
989 40 sc->refcount++;
990 }
991
992
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 42 times.
50 if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
993 8 stream->disposition |= AV_DISPOSITION_DEPENDENT;
994
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) {
995 40 stream->disposition |= AV_DISPOSITION_DEPENDENT;
996
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 6 times.
40 if (audio_element->layers[0].substream_count == 1)
997 34 stream->disposition &= ~AV_DISPOSITION_DEFAULT;
998 }
999
1000 50 ret = avcodec_parameters_copy(stream->codecpar, substream->codecpar);
1001
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (ret < 0)
1002 goto fail;
1003
1004 50 stream->id = substream->audio_substream_id;
1005
1006 50 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
1007
1008 50 ret = avformat_stream_group_add_stream(stg, stream);
1009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (ret < 0)
1010 goto fail;
1011 }
1012
1013 10 ret = av_dict_copy(&stg->metadata, metadata, 0);
1014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
1015 goto fail;
1016 }
1017
1018
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1019 10 IAMFMixPresentation *mix_presentation = iamf->mix_presentations[i];
1020 10 const AVIAMFMixPresentation *mix = mix_presentation->cmix;
1021 AVStreamGroup *stg =
1022 10 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, NULL);
1023
1024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!stg) {
1025 ret = AVERROR(ENOMEM);
1026 goto fail;
1027 }
1028
1029 10 av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
1030 10 stg->id = mix_presentation->mix_presentation_id;
1031 /* Transfer ownership */
1032 10 stg->params.iamf_mix_presentation = mix_presentation->mix;
1033 10 mix_presentation->mix = NULL;
1034
1035
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 10 times.
22 for (int j = 0; j < mix->nb_submixes; j++) {
1036 12 const AVIAMFSubmix *submix = mix->submixes[j];
1037
1038
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int k = 0; k < submix->nb_elements; k++) {
1039 12 const AVIAMFSubmixElement *submix_element = submix->elements[k];
1040 12 const AVStreamGroup *audio_element = NULL;
1041
1042
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 for (int l = 0; l < c->fc->nb_stream_groups; l++)
1043
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 &&
1044
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 c->fc->stream_groups[l]->id == submix_element->audio_element_id) {
1045 12 audio_element = c->fc->stream_groups[l];
1046 12 break;
1047 }
1048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 av_assert0(audio_element);
1049
1050
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 12 times.
64 for (int l = 0; l < audio_element->nb_streams; l++) {
1051 52 ret = avformat_stream_group_add_stream(stg, audio_element->streams[l]);
1052
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))
1053 goto fail;
1054 }
1055 }
1056 }
1057
1058 10 ret = av_dict_copy(&stg->metadata, metadata, 0);
1059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
1060 goto fail;
1061 }
1062
1063 10 ret = 0;
1064 10 fail:
1065 10 av_dict_free(&metadata);
1066
1067 10 return ret;
1068 }
1069 #endif
1070
1071 1 static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1072 {
1073 AVStream *st;
1074 AVPacketSideData *sd;
1075 enum AVAudioServiceType *ast;
1076 int eac3info, acmod, lfeon, bsmod;
1077 uint64_t mask;
1078
1079
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
1080 return 0;
1081 1 st = c->fc->streams[c->fc->nb_streams-1];
1082
1083 1 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1084 1 &st->codecpar->nb_coded_side_data,
1085 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
1086 sizeof(*ast), 0);
1087
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sd)
1088 return AVERROR(ENOMEM);
1089
1090 1 ast = (enum AVAudioServiceType*)sd->data;
1091
1092 /* No need to parse fields for additional independent substreams and its
1093 * associated dependent substreams since libavcodec's E-AC-3 decoder
1094 * does not support them yet. */
1095 1 avio_rb16(pb); /* data_rate and num_ind_sub */
1096 1 eac3info = avio_rb24(pb);
1097 1 bsmod = (eac3info >> 12) & 0x1f;
1098 1 acmod = (eac3info >> 9) & 0x7;
1099 1 lfeon = (eac3info >> 8) & 0x1;
1100
1101 1 mask = ff_ac3_channel_layout_tab[acmod];
1102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (lfeon)
1103 mask |= AV_CH_LOW_FREQUENCY;
1104 1 av_channel_layout_uninit(&st->codecpar->ch_layout);
1105 1 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
1106
1107 1 *ast = bsmod;
1108
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)
1109 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
1110
1111 1 return 0;
1112 }
1113
1114 static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1115 {
1116 #define DDTS_SIZE 20
1117 uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
1118 AVStream *st = NULL;
1119 uint32_t frame_duration_code = 0;
1120 uint32_t channel_layout_code = 0;
1121 GetBitContext gb;
1122 int ret;
1123
1124 if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
1125 return ret;
1126
1127 init_get_bits(&gb, buf, 8 * DDTS_SIZE);
1128
1129 if (c->fc->nb_streams < 1) {
1130 return 0;
1131 }
1132 st = c->fc->streams[c->fc->nb_streams-1];
1133
1134 st->codecpar->sample_rate = get_bits_long(&gb, 32);
1135 if (st->codecpar->sample_rate <= 0) {
1136 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
1137 return AVERROR_INVALIDDATA;
1138 }
1139 skip_bits_long(&gb, 32); /* max bitrate */
1140 st->codecpar->bit_rate = get_bits_long(&gb, 32);
1141 st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
1142 frame_duration_code = get_bits(&gb, 2);
1143 skip_bits(&gb, 30); /* various fields */
1144 channel_layout_code = get_bits(&gb, 16);
1145
1146 st->codecpar->frame_size =
1147 (frame_duration_code == 0) ? 512 :
1148 (frame_duration_code == 1) ? 1024 :
1149 (frame_duration_code == 2) ? 2048 :
1150 (frame_duration_code == 3) ? 4096 : 0;
1151
1152 if (channel_layout_code > 0xff) {
1153 av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout\n");
1154 }
1155 av_channel_layout_uninit(&st->codecpar->ch_layout);
1156 av_channel_layout_from_mask(&st->codecpar->ch_layout,
1157 ((channel_layout_code & 0x1) ? AV_CH_FRONT_CENTER : 0) |
1158 ((channel_layout_code & 0x2) ? AV_CH_FRONT_LEFT : 0) |
1159 ((channel_layout_code & 0x2) ? AV_CH_FRONT_RIGHT : 0) |
1160 ((channel_layout_code & 0x4) ? AV_CH_SIDE_LEFT : 0) |
1161 ((channel_layout_code & 0x4) ? AV_CH_SIDE_RIGHT : 0) |
1162 ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0));
1163
1164 return 0;
1165 }
1166
1167 51 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1168 {
1169 AVStream *st;
1170
1171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (c->fc->nb_streams < 1)
1172 return 0;
1173 51 st = c->fc->streams[c->fc->nb_streams-1];
1174
1175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (atom.size < 16)
1176 return 0;
1177
1178 /* skip version and flags */
1179 51 avio_skip(pb, 4);
1180
1181 51 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
1182
1183 51 return 0;
1184 }
1185
1186 5 static int mov_read_chnl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1187 {
1188 5 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
1189 int version, flags;
1190 int ret;
1191 AVStream *st;
1192
1193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
1194 return 0;
1195 5 st = c->fc->streams[c->fc->nb_streams-1];
1196
1197 5 version = avio_r8(pb);
1198 5 flags = avio_rb24(pb);
1199
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) {
1200 av_log(c->fc, AV_LOG_ERROR,
1201 "Unsupported 'chnl' box with version %d, flags: %#x",
1202 version, flags);
1203 return AVERROR_INVALIDDATA;
1204 }
1205
1206 5 ret = ff_mov_read_chnl(c->fc, pb, st);
1207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
1208 return ret;
1209
1210
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_tell(pb) != end) {
1211 av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data inside chnl\n",
1212 end - avio_tell(pb));
1213 avio_seek(pb, end, SEEK_SET);
1214 }
1215 5 return ret;
1216 }
1217
1218 2 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1219 {
1220 AVStream *st;
1221 int ret;
1222
1223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
1224 return 0;
1225 2 st = c->fc->streams[c->fc->nb_streams-1];
1226
1227
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)
1228 av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
1229
1230 2 return ret;
1231 }
1232
1233 16 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1234 {
1235 AVStream *st;
1236 HEIFItem *item;
1237 AVPacketSideData *sd;
1238 16 int width, height, err = 0;
1239 AVRational aperture_width, aperture_height, horiz_off, vert_off;
1240 AVRational pc_x, pc_y;
1241 uint64_t top, bottom, left, right;
1242
1243 16 item = heif_cur_item(c);
1244 16 st = get_curr_st(c);
1245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!st)
1246 return 0;
1247
1248 16 width = st->codecpar->width;
1249 16 height = st->codecpar->height;
1250
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) {
1251 4 width = item->width;
1252 4 height = item->height;
1253 }
1254
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
16 if (!width || !height) {
1255 err = AVERROR_INVALIDDATA;
1256 goto fail;
1257 }
1258
1259 16 aperture_width.num = avio_rb32(pb);
1260 16 aperture_width.den = avio_rb32(pb);
1261 16 aperture_height.num = avio_rb32(pb);
1262 16 aperture_height.den = avio_rb32(pb);
1263
1264 16 horiz_off.num = avio_rb32(pb);
1265 16 horiz_off.den = avio_rb32(pb);
1266 16 vert_off.num = avio_rb32(pb);
1267 16 vert_off.den = avio_rb32(pb);
1268
1269
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 ||
1270
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 ||
1271
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) {
1272 err = AVERROR_INVALIDDATA;
1273 goto fail;
1274 }
1275 16 av_log(c->fc, AV_LOG_TRACE, "clap: apertureWidth %d/%d, apertureHeight %d/%d "
1276 "horizOff %d/%d vertOff %d/%d\n",
1277 aperture_width.num, aperture_width.den, aperture_height.num, aperture_height.den,
1278 horiz_off.num, horiz_off.den, vert_off.num, vert_off.den);
1279
1280 16 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1281 16 pc_x = av_add_q(pc_x, horiz_off);
1282 16 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1283 16 pc_y = av_add_q(pc_y, vert_off);
1284
1285 16 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1286 16 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1287 16 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1288 16 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1289
1290 16 left = av_q2d(av_sub_q(pc_x, aperture_width));
1291 16 right = av_q2d(av_add_q(pc_x, aperture_width));
1292 16 top = av_q2d(av_sub_q(pc_y, aperture_height));
1293 16 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1294
1295
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 if (bottom > (height - 1) ||
1296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 right > (width - 1)) {
1297 2 err = AVERROR_INVALIDDATA;
1298 2 goto fail;
1299 }
1300
1301 14 bottom = height - 1 - bottom;
1302 14 right = width - 1 - right;
1303
1304
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
14 if (!(left | right | top | bottom))
1305 6 return 0;
1306
1307
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if ((left + right) >= width ||
1308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 (top + bottom) >= height) {
1309 err = AVERROR_INVALIDDATA;
1310 goto fail;
1311 }
1312
1313 8 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1314 8 &st->codecpar->nb_coded_side_data,
1315 AV_PKT_DATA_FRAME_CROPPING,
1316 sizeof(uint32_t) * 4, 0);
1317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!sd)
1318 return AVERROR(ENOMEM);
1319
1320 8 AV_WL32A(sd->data, top);
1321 8 AV_WL32A(sd->data + 4, bottom);
1322 8 AV_WL32A(sd->data + 8, left);
1323 8 AV_WL32A(sd->data + 12, right);
1324
1325 10 fail:
1326
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (err < 0) {
1327 2 int explode = !!(c->fc->error_recognition & AV_EF_EXPLODE);
1328
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");
1329
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!explode)
1330 2 err = 0;
1331 }
1332
1333 10 return err;
1334 }
1335
1336 /* This atom overrides any previously set aspect ratio */
1337 65 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1338 {
1339 65 const int num = avio_rb32(pb);
1340 65 const int den = avio_rb32(pb);
1341 AVStream *st;
1342 MOVStreamContext *sc;
1343
1344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (c->fc->nb_streams < 1)
1345 return 0;
1346 65 st = c->fc->streams[c->fc->nb_streams-1];
1347 65 sc = st->priv_data;
1348
1349 65 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1350
1351
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 2 times.
65 if (den != 0) {
1352 63 sc->h_spacing = num;
1353 63 sc->v_spacing = den;
1354 }
1355 65 return 0;
1356 }
1357
1358 /* this atom contains actual media data */
1359 872 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1360 {
1361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 872 times.
872 if (atom.size == 0) /* wrong one (MP4) */
1362 return 0;
1363 872 c->found_mdat=1;
1364 872 return 0; /* now go for moov */
1365 }
1366
1367 #define DRM_BLOB_SIZE 56
1368
1369 static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1370 {
1371 uint8_t intermediate_key[20];
1372 uint8_t intermediate_iv[20];
1373 uint8_t input[64];
1374 uint8_t output[64];
1375 uint8_t file_checksum[20];
1376 uint8_t calculated_checksum[20];
1377 char checksum_string[2 * sizeof(file_checksum) + 1];
1378 struct AVSHA *sha;
1379 int i;
1380 int ret = 0;
1381 uint8_t *activation_bytes = c->activation_bytes;
1382 uint8_t *fixed_key = c->audible_fixed_key;
1383
1384 c->aax_mode = 1;
1385
1386 sha = av_sha_alloc();
1387 if (!sha)
1388 return AVERROR(ENOMEM);
1389 av_free(c->aes_decrypt);
1390 c->aes_decrypt = av_aes_alloc();
1391 if (!c->aes_decrypt) {
1392 ret = AVERROR(ENOMEM);
1393 goto fail;
1394 }
1395
1396 /* drm blob processing */
1397 avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1398 avio_read(pb, input, DRM_BLOB_SIZE);
1399 avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1400 avio_read(pb, file_checksum, 20);
1401
1402 // required by external tools
1403 ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1);
1404 av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string);
1405
1406 /* verify activation data */
1407 if (!activation_bytes) {
1408 av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1409 ret = 0; /* allow ffprobe to continue working on .aax files */
1410 goto fail;
1411 }
1412 if (c->activation_bytes_size != 4) {
1413 av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1414 ret = AVERROR(EINVAL);
1415 goto fail;
1416 }
1417
1418 /* verify fixed key */
1419 if (c->audible_fixed_key_size != 16) {
1420 av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1421 ret = AVERROR(EINVAL);
1422 goto fail;
1423 }
1424
1425 /* AAX (and AAX+) key derivation */
1426 av_sha_init(sha, 160);
1427 av_sha_update(sha, fixed_key, 16);
1428 av_sha_update(sha, activation_bytes, 4);
1429 av_sha_final(sha, intermediate_key);
1430 av_sha_init(sha, 160);
1431 av_sha_update(sha, fixed_key, 16);
1432 av_sha_update(sha, intermediate_key, 20);
1433 av_sha_update(sha, activation_bytes, 4);
1434 av_sha_final(sha, intermediate_iv);
1435 av_sha_init(sha, 160);
1436 av_sha_update(sha, intermediate_key, 16);
1437 av_sha_update(sha, intermediate_iv, 16);
1438 av_sha_final(sha, calculated_checksum);
1439 if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1440 av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1441 ret = AVERROR_INVALIDDATA;
1442 goto fail;
1443 }
1444 av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1445 av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1446 for (i = 0; i < 4; i++) {
1447 // file data (in output) is stored in big-endian mode
1448 if (activation_bytes[i] != output[3 - i]) { // critical error
1449 av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1450 ret = AVERROR_INVALIDDATA;
1451 goto fail;
1452 }
1453 }
1454 memcpy(c->file_key, output + 8, 16);
1455 memcpy(input, output + 26, 16);
1456 av_sha_init(sha, 160);
1457 av_sha_update(sha, input, 16);
1458 av_sha_update(sha, c->file_key, 16);
1459 av_sha_update(sha, fixed_key, 16);
1460 av_sha_final(sha, c->file_iv);
1461
1462 fail:
1463 av_free(sha);
1464
1465 return ret;
1466 }
1467
1468 static int mov_aaxc_crypto(MOVContext *c)
1469 {
1470 if (c->audible_key_size != 16) {
1471 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n");
1472 return AVERROR(EINVAL);
1473 }
1474
1475 if (c->audible_iv_size != 16) {
1476 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n");
1477 return AVERROR(EINVAL);
1478 }
1479
1480 c->aes_decrypt = av_aes_alloc();
1481 if (!c->aes_decrypt) {
1482 return AVERROR(ENOMEM);
1483 }
1484
1485 memcpy(c->file_key, c->audible_key, 16);
1486 memcpy(c->file_iv, c->audible_iv, 16);
1487 c->aax_mode = 1;
1488
1489 return 0;
1490 }
1491
1492 // Audible AAX (and AAX+) bytestream decryption
1493 static int aax_filter(uint8_t *input, int size, MOVContext *c)
1494 {
1495 int blocks = 0;
1496 unsigned char iv[16];
1497
1498 memcpy(iv, c->file_iv, 16); // iv is overwritten
1499 blocks = size >> 4; // trailing bytes are not encrypted!
1500 av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1501 av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1502
1503 return 0;
1504 }
1505
1506 /* read major brand, minor version and compatible brands and store them as metadata */
1507 451 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1508 {
1509 uint32_t minor_ver;
1510 int comp_brand_size;
1511 char* comp_brands_str;
1512 451 uint8_t type[5] = {0};
1513 451 int ret = ffio_read_size(pb, type, 4);
1514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 451 times.
451 if (ret < 0)
1515 return ret;
1516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 451 times.
451 if (c->fc->nb_streams) {
1517 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1518 return AVERROR_INVALIDDATA;
1519 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate FTYP\n");
1520 return 0;
1521 }
1522
1523
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 232 times.
451 if (strcmp(type, "qt "))
1524 219 c->isom = 1;
1525 451 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1526 451 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1527 451 minor_ver = avio_rb32(pb); /* minor version */
1528 451 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1529
1530 451 comp_brand_size = atom.size - 8;
1531
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)
1532 return AVERROR_INVALIDDATA;
1533 451 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 451 times.
451 if (!comp_brands_str)
1535 return AVERROR(ENOMEM);
1536
1537 451 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 451 times.
451 if (ret < 0) {
1539 av_freep(&comp_brands_str);
1540 return ret;
1541 }
1542 451 comp_brands_str[comp_brand_size] = 0;
1543 451 av_dict_set(&c->fc->metadata, "compatible_brands",
1544 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1545
1546 // Logic for handling Audible's .aaxc files
1547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 451 times.
451 if (!strcmp(type, "aaxc")) {
1548 mov_aaxc_crypto(c);
1549 }
1550
1551 451 return 0;
1552 }
1553
1554 /* this atom should contain all header atoms */
1555 483 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1556 {
1557 int ret;
1558
1559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
483 if (c->found_moov) {
1560 av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1561 avio_skip(pb, atom.size);
1562 return 0;
1563 }
1564
1565
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 483 times.
483 if ((ret = mov_read_default(c, pb, atom)) < 0)
1566 return ret;
1567 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1568 /* so we don't parse the whole file if over a network */
1569 483 c->found_moov=1;
1570 483 return 0; /* now go for mdat */
1571 }
1572
1573 2869 static MOVFragmentStreamInfo * get_frag_stream_info(
1574 MOVFragmentIndex *frag_index,
1575 int index,
1576 int id)
1577 {
1578 int i;
1579 MOVFragmentIndexItem * item;
1580
1581
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)
1582 return NULL;
1583 2869 item = &frag_index->item[index];
1584
1/2
✓ Branch 0 taken 2993 times.
✗ Branch 1 not taken.
2993 for (i = 0; i < item->nb_stream_info; i++)
1585
2/2
✓ Branch 0 taken 2869 times.
✓ Branch 1 taken 124 times.
2993 if (item->stream_info[i].id == id)
1586 2869 return &item->stream_info[i];
1587
1588 // This shouldn't happen
1589 return NULL;
1590 }
1591
1592 388 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1593 {
1594 int i;
1595 MOVFragmentIndexItem * item;
1596
1597
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_index->current < 0 ||
1598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 frag_index->current >= frag_index->nb_items)
1599 return;
1600
1601 388 item = &frag_index->item[frag_index->current];
1602
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < item->nb_stream_info; i++)
1603
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (item->stream_info[i].id == id) {
1604 388 item->current = i;
1605 388 return;
1606 }
1607
1608 // id not found. This shouldn't happen.
1609 item->current = -1;
1610 }
1611
1612 1149 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1613 MOVFragmentIndex *frag_index)
1614 {
1615 MOVFragmentIndexItem *item;
1616
1/2
✓ Branch 0 taken 1149 times.
✗ Branch 1 not taken.
1149 if (frag_index->current < 0 ||
1617
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1146 times.
1149 frag_index->current >= frag_index->nb_items)
1618 3 return NULL;
1619
1620 1146 item = &frag_index->item[frag_index->current];
1621
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)
1622 1146 return &item->stream_info[item->current];
1623
1624 // This shouldn't happen
1625 return NULL;
1626 }
1627
1628 798 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1629 {
1630 int a, b, m;
1631 int64_t moof_offset;
1632
1633 // Optimize for appending new entries
1634
2/2
✓ Branch 0 taken 788 times.
✓ Branch 1 taken 10 times.
798 if (!frag_index->nb_items ||
1635
2/2
✓ Branch 0 taken 383 times.
✓ Branch 1 taken 405 times.
788 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1636 393 return frag_index->nb_items;
1637
1638 405 a = -1;
1639 405 b = frag_index->nb_items;
1640
1641
2/2
✓ Branch 0 taken 2655 times.
✓ Branch 1 taken 405 times.
3060 while (b - a > 1) {
1642 2655 m = (a + b) >> 1;
1643 2655 moof_offset = frag_index->item[m].moof_offset;
1644
2/2
✓ Branch 0 taken 732 times.
✓ Branch 1 taken 1923 times.
2655 if (moof_offset >= offset)
1645 732 b = m;
1646
2/2
✓ Branch 0 taken 2328 times.
✓ Branch 1 taken 327 times.
2655 if (moof_offset <= offset)
1647 2328 a = m;
1648 }
1649 405 return b;
1650 }
1651
1652 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1653 {
1654 av_assert0(frag_stream_info);
1655 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1656 return frag_stream_info->sidx_pts;
1657 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1658 return frag_stream_info->first_tfra_pts;
1659 return frag_stream_info->tfdt_dts;
1660 }
1661
1662 219 static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1663 MOVFragmentIndex *frag_index, int index)
1664 {
1665 MOVFragmentStreamInfo * frag_stream_info;
1666 219 MOVStreamContext *sc = dst_st->priv_data;
1667 int64_t timestamp;
1668 int i, j;
1669
1670 // If the stream is referenced by any sidx, limit the search
1671 // to fragments that referenced this stream in the sidx
1672
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (sc->has_sidx) {
1673 219 frag_stream_info = get_frag_stream_info(frag_index, index, sc->id);
1674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!frag_stream_info)
1675 return AV_NOPTS_VALUE;
1676
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1677 219 return frag_stream_info->sidx_pts;
1678 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1679 return frag_stream_info->first_tfra_pts;
1680 return frag_stream_info->sidx_pts;
1681 }
1682
1683 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
1684 AVStream *frag_stream = NULL;
1685 frag_stream_info = &frag_index->item[index].stream_info[i];
1686 for (j = 0; j < s->nb_streams; j++) {
1687 MOVStreamContext *sc2 = s->streams[j]->priv_data;
1688 if (sc2->id == frag_stream_info->id)
1689 frag_stream = s->streams[j];
1690 }
1691 if (!frag_stream) {
1692 av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1693 continue;
1694 }
1695 timestamp = get_stream_info_time(frag_stream_info);
1696 if (timestamp != AV_NOPTS_VALUE)
1697 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1698 }
1699 return AV_NOPTS_VALUE;
1700 }
1701
1702 26 static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1703 AVStream *st, int64_t timestamp)
1704 {
1705 int a, b, m, m0;
1706 int64_t frag_time;
1707
1708 26 a = -1;
1709 26 b = frag_index->nb_items;
1710
1711
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 26 times.
245 while (b - a > 1) {
1712 219 m0 = m = (a + b) >> 1;
1713
1714
2/4
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 219 times.
438 while (m < b &&
1715 219 (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
1716 m++;
1717
1718
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)
1719 93 a = m;
1720 else
1721 126 b = m0;
1722 }
1723
1724 26 return a;
1725 }
1726
1727 756 static int update_frag_index(MOVContext *c, int64_t offset)
1728 {
1729 int index, i;
1730 MOVFragmentIndexItem * item;
1731 MOVFragmentStreamInfo * frag_stream_info;
1732
1733 // If moof_offset already exists in frag_index, return index to it
1734 756 index = search_frag_moof_offset(&c->frag_index, offset);
1735
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 389 times.
756 if (index < c->frag_index.nb_items &&
1736
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 c->frag_index.item[index].moof_offset == offset)
1737 367 return index;
1738
1739 // offset is not yet in frag index.
1740 // Insert new item at index (sorted by moof offset)
1741 389 item = av_fast_realloc(c->frag_index.item,
1742 389 &c->frag_index.allocated_size,
1743 389 (c->frag_index.nb_items + 1) *
1744 sizeof(*c->frag_index.item));
1745
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (!item)
1746 return -1;
1747 389 c->frag_index.item = item;
1748
1749 389 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1750 sizeof(*item->stream_info));
1751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (!frag_stream_info)
1752 return -1;
1753
1754
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 389 times.
796 for (i = 0; i < c->fc->nb_streams; i++) {
1755 // Avoid building frag index if streams lack track id.
1756 407 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1757
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 407 times.
407 if (sc->id < 0) {
1758 av_free(frag_stream_info);
1759 return AVERROR_INVALIDDATA;
1760 }
1761
1762 407 frag_stream_info[i].id = sc->id;
1763 407 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1764 407 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1765 407 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1766 407 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1767 407 frag_stream_info[i].index_base = -1;
1768 407 frag_stream_info[i].index_entry = -1;
1769 407 frag_stream_info[i].encryption_index = NULL;
1770 407 frag_stream_info[i].stsd_id = -1;
1771 }
1772
1773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (index < c->frag_index.nb_items)
1774 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1775 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1776
1777 389 item = &c->frag_index.item[index];
1778 389 item->headers_read = 0;
1779 389 item->current = 0;
1780 389 item->nb_stream_info = c->fc->nb_streams;
1781 389 item->moof_offset = offset;
1782 389 item->stream_info = frag_stream_info;
1783 389 c->frag_index.nb_items++;
1784
1785 389 return index;
1786 }
1787
1788 388 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1789 int id, int entries)
1790 {
1791 int i;
1792 MOVFragmentStreamInfo * frag_stream_info;
1793
1794
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (index < 0)
1795 388 return;
1796 for (i = index; i < frag_index->nb_items; i++) {
1797 frag_stream_info = get_frag_stream_info(frag_index, i, id);
1798 if (frag_stream_info && frag_stream_info->index_entry >= 0)
1799 frag_stream_info->index_entry += entries;
1800 }
1801 }
1802
1803 388 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1804 {
1805 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1806 388 c->fragment.found_tfhd = 0;
1807
1808
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) {
1809 c->has_looked_for_mfra = 1;
1810 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1811 int ret;
1812 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1813 "for a mfra\n");
1814 if ((ret = mov_read_mfra(c, pb)) < 0) {
1815 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1816 "read the mfra (may be a live ismv)\n");
1817 }
1818 } else {
1819 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1820 "seekable, can not look for mfra\n");
1821 }
1822 }
1823 388 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1824 388 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1825 388 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1826 388 return mov_read_default(c, pb, atom);
1827 }
1828
1829 1073 static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version)
1830 {
1831 int64_t time;
1832
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1062 times.
1073 if (version == 1) {
1833 11 time = avio_rb64(pb);
1834 11 avio_rb64(pb);
1835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (time < 0) {
1836 av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n");
1837 return;
1838 }
1839 } else {
1840 1062 time = avio_rb32(pb);
1841 1062 avio_rb32(pb); /* modification time */
1842
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) {
1843 48 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1844 48 time += 2082844800;
1845 }
1846 }
1847
2/2
✓ Branch 0 taken 525 times.
✓ Branch 1 taken 548 times.
1073 if (time) {
1848 525 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1849
1850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 525 times.
525 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1851 av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n");
1852 return;
1853 }
1854
1855 525 avpriv_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1856 }
1857 }
1858
1859 593 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1860 {
1861 AVStream *st;
1862 MOVStreamContext *sc;
1863 int version;
1864 593 char language[4] = {0};
1865 unsigned lang;
1866
1867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->fc->nb_streams < 1)
1868 return 0;
1869 593 st = c->fc->streams[c->fc->nb_streams-1];
1870 593 sc = st->priv_data;
1871
1872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (sc->time_scale) {
1873 av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
1874 return AVERROR_INVALIDDATA;
1875 }
1876
1877 593 version = avio_r8(pb);
1878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (version > 1) {
1879 avpriv_request_sample(c->fc, "Version %d", version);
1880 return AVERROR_PATCHWELCOME;
1881 }
1882 593 avio_rb24(pb); /* flags */
1883 593 mov_metadata_creation_time(c, pb, &st->metadata, version);
1884
1885 593 sc->time_scale = avio_rb32(pb);
1886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (sc->time_scale <= 0) {
1887 av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
1888 sc->time_scale = 1;
1889 }
1890
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 584 times.
593 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1891
1892
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) ||
1893
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 584 times.
584 (version != 1 && st->duration == UINT32_MAX)) {
1894 5 st->duration = 0;
1895 }
1896
1897 593 lang = avio_rb16(pb); /* language */
1898
2/2
✓ Branch 1 taken 421 times.
✓ Branch 2 taken 172 times.
593 if (ff_mov_lang_to_iso639(lang, language))
1899 421 av_dict_set(&st->metadata, "language", language, 0);
1900 593 avio_rb16(pb); /* quality */
1901
1902 593 return 0;
1903 }
1904
1905 480 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1906 {
1907 int i;
1908 480 int version = avio_r8(pb); /* version */
1909 480 avio_rb24(pb); /* flags */
1910
1911 480 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
1912 480 c->time_scale = avio_rb32(pb); /* time scale */
1913
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 480 times.
480 if (c->time_scale <= 0) {
1914 av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
1915 c->time_scale = 1;
1916 }
1917 480 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
1918
1919
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 478 times.
480 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1920 480 avio_rb32(pb); /* preferred scale */
1921
1922 480 avio_rb16(pb); /* preferred volume */
1923
1924 480 avio_skip(pb, 10); /* reserved */
1925
1926 /* movie display matrix, store it in main context and use it later on */
1927
2/2
✓ Branch 0 taken 1440 times.
✓ Branch 1 taken 480 times.
1920 for (i = 0; i < 3; i++) {
1928 1440 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
1929 1440 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
1930 1440 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
1931 }
1932
1933 480 avio_rb32(pb); /* preview time */
1934 480 avio_rb32(pb); /* preview duration */
1935 480 avio_rb32(pb); /* poster time */
1936 480 avio_rb32(pb); /* selection time */
1937 480 avio_rb32(pb); /* selection duration */
1938 480 avio_rb32(pb); /* current time */
1939 480 avio_rb32(pb); /* next track ID */
1940
1941 480 return 0;
1942 }
1943
1944 7 static void set_last_stream_little_endian(AVFormatContext *fc)
1945 {
1946 AVStream *st;
1947
1948
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (fc->nb_streams < 1)
1949 return;
1950 7 st = fc->streams[fc->nb_streams-1];
1951
1952
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) {
1953 5 case AV_CODEC_ID_PCM_S16BE:
1954 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
1955 5 break;
1956 1 case AV_CODEC_ID_PCM_S24BE:
1957 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
1958 1 break;
1959 case AV_CODEC_ID_PCM_S32BE:
1960 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
1961 break;
1962 1 case AV_CODEC_ID_PCM_F32BE:
1963 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
1964 1 break;
1965 case AV_CODEC_ID_PCM_F64BE:
1966 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
1967 break;
1968 default:
1969 break;
1970 }
1971 }
1972
1973 5 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1974 {
1975 5 int little_endian = avio_rb16(pb) & 0xFF;
1976 5 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
1977
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (little_endian == 1)
1978 1 set_last_stream_little_endian(c->fc);
1979 5 return 0;
1980 }
1981
1982 6 static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1983 {
1984 int format_flags;
1985 int version, flags;
1986 int pcm_sample_size;
1987 6 AVFormatContext *fc = c->fc;
1988 AVStream *st;
1989 MOVStreamContext *sc;
1990
1991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 6) {
1992 av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n");
1993 return AVERROR_INVALIDDATA;
1994 }
1995
1996 6 version = avio_r8(pb);
1997 6 flags = avio_rb24(pb);
1998
1999
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) {
2000 av_log(c->fc, AV_LOG_ERROR,
2001 "Unsupported 'pcmC' box with version %d, flags: %x",
2002 version, flags);
2003 return AVERROR_INVALIDDATA;
2004 }
2005
2006 6 format_flags = avio_r8(pb);
2007 6 pcm_sample_size = avio_r8(pb);
2008
2009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fc->nb_streams < 1)
2010 return AVERROR_INVALIDDATA;
2011
2012 6 st = fc->streams[fc->nb_streams - 1];
2013 6 sc = st->priv_data;
2014
2015
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (sc->format == MOV_MP4_FPCM_TAG) {
2016
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (pcm_sample_size) {
2017 1 case 32:
2018 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE;
2019 1 break;
2020 case 64:
2021 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE;
2022 break;
2023 default:
2024 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2025 pcm_sample_size,
2026 av_fourcc2str(sc->format));
2027 return AVERROR_INVALIDDATA;
2028 }
2029
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (sc->format == MOV_MP4_IPCM_TAG) {
2030
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 switch (pcm_sample_size) {
2031 5 case 16:
2032 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2033 5 break;
2034 case 24:
2035 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
2036 break;
2037 case 32:
2038 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
2039 break;
2040 default:
2041 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2042 pcm_sample_size,
2043 av_fourcc2str(sc->format));
2044 return AVERROR_INVALIDDATA;
2045 }
2046 } else {
2047 av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n",
2048 av_fourcc2str(sc->format));
2049 return AVERROR_INVALIDDATA;
2050 }
2051
2052
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
2053 6 set_last_stream_little_endian(c->fc);
2054 6 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2055
2056 6 return 0;
2057 }
2058
2059 43 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2060 {
2061 AVStream *st;
2062 43 HEIFItem *item = NULL;
2063 43 char color_parameter_type[5] = { 0 };
2064 uint16_t color_primaries, color_trc, color_matrix;
2065 int ret;
2066
2067 43 st = get_curr_st(c);
2068
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st) {
2069 item = heif_cur_item(c);
2070 if (!item)
2071 return 0;
2072 }
2073
2074 43 ret = ffio_read_size(pb, color_parameter_type, 4);
2075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
2076 return ret;
2077
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 10 times.
43 if (strncmp(color_parameter_type, "nclx", 4) &&
2078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 strncmp(color_parameter_type, "nclc", 4) &&
2079 strncmp(color_parameter_type, "prof", 4)) {
2080 av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
2081 color_parameter_type);
2082 return 0;
2083 }
2084
2085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!strncmp(color_parameter_type, "prof", 4)) {
2086 AVPacketSideData *sd;
2087 uint8_t *icc_profile;
2088 if (st) {
2089 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
2090 &st->codecpar->nb_coded_side_data,
2091 AV_PKT_DATA_ICC_PROFILE,
2092 atom.size - 4, 0);
2093 if (!sd)
2094 return AVERROR(ENOMEM);
2095 icc_profile = sd->data;
2096 } else {
2097 av_freep(&item->icc_profile);
2098 icc_profile = item->icc_profile = av_malloc(atom.size - 4);
2099 if (!icc_profile) {
2100 item->icc_profile_size = 0;
2101 return AVERROR(ENOMEM);
2102 }
2103 item->icc_profile_size = atom.size - 4;
2104 }
2105 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
2106 if (ret < 0)
2107 return ret;
2108
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 } else if (st) {
2109 43 color_primaries = avio_rb16(pb);
2110 43 color_trc = avio_rb16(pb);
2111 43 color_matrix = avio_rb16(pb);
2112
2113 43 av_log(c->fc, AV_LOG_TRACE,
2114 "%s: pri %d trc %d matrix %d",
2115 color_parameter_type, color_primaries, color_trc, color_matrix);
2116
2117
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 33 times.
43 if (!strncmp(color_parameter_type, "nclx", 4)) {
2118 10 uint8_t color_range = avio_r8(pb) >> 7;
2119 10 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (color_range)
2121 st->codecpar->color_range = AVCOL_RANGE_JPEG;
2122 else
2123 10 st->codecpar->color_range = AVCOL_RANGE_MPEG;
2124 }
2125
2126
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_primaries_name(color_primaries))
2127 color_primaries = AVCOL_PRI_UNSPECIFIED;
2128
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_transfer_name(color_trc))
2129 color_trc = AVCOL_TRC_UNSPECIFIED;
2130
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_space_name(color_matrix))
2131 color_matrix = AVCOL_SPC_UNSPECIFIED;
2132
2133 43 st->codecpar->color_primaries = color_primaries;
2134 43 st->codecpar->color_trc = color_trc;
2135 43 st->codecpar->color_space = color_matrix;
2136 43 av_log(c->fc, AV_LOG_TRACE, "\n");
2137 }
2138 43 return 0;
2139 }
2140
2141 111 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2142 {
2143 AVStream *st;
2144 unsigned mov_field_order;
2145 111 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2146
2147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111 times.
111 if (c->fc->nb_streams < 1) // will happen with jp2 files
2148 return 0;
2149 111 st = c->fc->streams[c->fc->nb_streams-1];
2150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111 times.
111 if (atom.size < 2)
2151 return AVERROR_INVALIDDATA;
2152 111 mov_field_order = avio_rb16(pb);
2153
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 20 times.
111 if ((mov_field_order & 0xFF00) == 0x0100)
2154 91 decoded_field_order = AV_FIELD_PROGRESSIVE;
2155
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 else if ((mov_field_order & 0xFF00) == 0x0200) {
2156
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) {
2157 1 case 0x01: decoded_field_order = AV_FIELD_TT;
2158 1 break;
2159 case 0x06: decoded_field_order = AV_FIELD_BB;
2160 break;
2161 1 case 0x09: decoded_field_order = AV_FIELD_TB;
2162 1 break;
2163 18 case 0x0E: decoded_field_order = AV_FIELD_BT;
2164 18 break;
2165 }
2166 }
2167
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) {
2168 av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
2169 }
2170 111 st->codecpar->field_order = decoded_field_order;
2171
2172 111 return 0;
2173 }
2174
2175 68 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
2176 {
2177 68 int err = 0;
2178 68 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
2179
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)
2180 return AVERROR_INVALIDDATA;
2181
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
68 if ((err = av_reallocp(&par->extradata, size)) < 0) {
2182 par->extradata_size = 0;
2183 return err;
2184 }
2185 68 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
2186 68 return 0;
2187 }
2188
2189 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
2190 65 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2191 AVCodecParameters *par, uint8_t *buf)
2192 {
2193 65 int64_t result = atom.size;
2194 int err;
2195
2196 65 AV_WB32(buf , atom.size + 8);
2197 65 AV_WL32(buf + 4, atom.type);
2198 65 err = ffio_read_size(pb, buf + 8, atom.size);
2199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (err < 0) {
2200 par->extradata_size -= atom.size;
2201 return err;
2202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 } else if (err < atom.size) {
2203 av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
2204 par->extradata_size -= atom.size - err;
2205 result = err;
2206 }
2207 65 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2208 65 return result;
2209 }
2210
2211 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
2212 58 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2213 enum AVCodecID codec_id)
2214 {
2215 AVStream *st;
2216 uint64_t original_size;
2217 int err;
2218
2219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (c->fc->nb_streams < 1) // will happen with jp2 files
2220 return 0;
2221 58 st = c->fc->streams[c->fc->nb_streams-1];
2222
2223
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
58 if (st->codecpar->codec_id != codec_id)
2224 19 return 0; /* unexpected codec_id - don't mess with extradata */
2225
2226 39 original_size = st->codecpar->extradata_size;
2227 39 err = mov_realloc_extradata(st->codecpar, atom);
2228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err)
2229 return err;
2230
2231 39 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
2232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err < 0)
2233 return err;
2234 39 return 0; // Note: this is the original behavior to ignore truncation.
2235 }
2236
2237 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
2238 16 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2239 {
2240 16 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
2241 }
2242
2243 static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2244 {
2245 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS);
2246 }
2247
2248 static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2249 {
2250 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
2251 }
2252
2253 static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2254 {
2255 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
2256 }
2257
2258 19 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2259 {
2260 19 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
2261
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!ret)
2262 19 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
2263 19 return ret;
2264 }
2265
2266 static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2267 {
2268 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
2269
2270 if (!ret && c->fc->nb_streams >= 1) {
2271 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2272 if (par->extradata_size >= 40) {
2273 par->height = AV_RB16(&par->extradata[36]);
2274 par->width = AV_RB16(&par->extradata[38]);
2275 }
2276 }
2277 return ret;
2278 }
2279
2280 16 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2281 {
2282
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (c->fc->nb_streams >= 1) {
2283 16 AVStream *const st = c->fc->streams[c->fc->nb_streams - 1];
2284 16 FFStream *const sti = ffstream(st);
2285 16 AVCodecParameters *par = st->codecpar;
2286
2287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
2288 par->codec_id == AV_CODEC_ID_H264 &&
2289 atom.size > 11) {
2290 int cid;
2291 avio_skip(pb, 10);
2292 cid = avio_rb16(pb);
2293 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
2294 if (cid == 0xd4d || cid == 0xd4e)
2295 par->width = 1440;
2296 return 0;
2297
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
2298
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
2299
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
2300
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 atom.size >= 24) {
2301 int num, den;
2302 13 avio_skip(pb, 12);
2303 13 num = avio_rb32(pb);
2304 13 den = avio_rb32(pb);
2305
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)
2306 return 0;
2307
2/3
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
13 switch (avio_rb32(pb)) {
2308 12 case 2:
2309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (den >= INT_MAX / 2)
2310 return 0;
2311 12 den *= 2;
2312 13 case 1:
2313 13 sti->display_aspect_ratio = (AVRational){ num, den };
2314 13 default:
2315 13 return 0;
2316 }
2317 }
2318 }
2319
2320 3 return mov_read_avid(c, pb, atom);
2321 }
2322
2323 26 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2324 {
2325 26 int ret = 0;
2326 26 int length = 0;
2327 uint64_t original_size;
2328
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (c->fc->nb_streams >= 1) {
2329 26 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (par->codec_id == AV_CODEC_ID_H264)
2331 return 0;
2332
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (atom.size == 16) {
2333 26 original_size = par->extradata_size;
2334 26 ret = mov_realloc_extradata(par, atom);
2335
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!ret) {
2336 26 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
2337
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (length == atom.size) {
2338 26 const uint8_t range_value = par->extradata[original_size + 19];
2339
1/3
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
26 switch (range_value) {
2340 26 case 1:
2341 26 par->color_range = AVCOL_RANGE_MPEG;
2342 26 break;
2343 case 2:
2344 par->color_range = AVCOL_RANGE_JPEG;
2345 break;
2346 default:
2347 av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
2348 break;
2349 }
2350 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
2351 } else {
2352 /* For some reason the whole atom was not added to the extradata */
2353 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
2354 }
2355 } else {
2356 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
2357 }
2358 } else {
2359 av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
2360 }
2361 }
2362
2363 26 return ret;
2364 }
2365
2366 4 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2367 {
2368 4 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
2369 }
2370
2371 34 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2372 {
2373 AVStream *st;
2374 int ret;
2375
2376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (c->fc->nb_streams < 1)
2377 return 0;
2378 34 st = c->fc->streams[c->fc->nb_streams-1];
2379
2380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if ((uint64_t)atom.size > (1<<30))
2381 return AVERROR_INVALIDDATA;
2382
2383
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2 times.
34 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2384
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
2386 // pass all frma atom to codec, needed at least for QDMC and QDM2
2387 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2389 return ret;
2390
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 } else if (atom.size > 8) { /* to read frma, esds atoms */
2391
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) {
2392 uint64_t buffer;
2393 10 ret = ffio_ensure_seekback(pb, 8);
2394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2395 return ret;
2396 10 buffer = avio_rb64(pb);
2397 10 atom.size -= 8;
2398
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
2399
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 <= atom.size
2400
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 >= 8) {
2401 10 avio_skip(pb, -8);
2402 10 atom.size += 8;
2403 } else if (!st->codecpar->extradata_size) {
2404 #define ALAC_EXTRADATA_SIZE 36
2405 st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
2406 if (!st->codecpar->extradata)
2407 return AVERROR(ENOMEM);
2408 st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
2409 AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
2410 AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
2411 AV_WB64(st->codecpar->extradata + 12, buffer);
2412 avio_read(pb, st->codecpar->extradata + 20, 16);
2413 avio_skip(pb, atom.size - 24);
2414 return 0;
2415 }
2416 }
2417
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if ((ret = mov_read_default(c, pb, atom)) < 0)
2418 return ret;
2419 } else
2420 avio_skip(pb, atom.size);
2421 34 return 0;
2422 }
2423
2424 /**
2425 * This function reads atom content and puts data in extradata without tag
2426 * nor size unlike mov_read_extradata.
2427 */
2428 138 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2429 {
2430 AVStream *st;
2431 int ret;
2432
2433 138 st = get_curr_st(c);
2434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (!st)
2435 return 0;
2436
2437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if ((uint64_t)atom.size > (1<<30))
2438 return AVERROR_INVALIDDATA;
2439
2440
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 137 times.
138 if (atom.type == MKTAG('v','v','c','C')) {
2441 1 avio_skip(pb, 4);
2442 1 atom.size -= 4;
2443 }
2444
2445
2/2
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 4 times.
138 if (atom.size >= 10) {
2446 // Broken files created by legacy versions of libavformat will
2447 // wrap a whole fiel atom inside of a glbl atom.
2448 134 unsigned size = avio_rb32(pb);
2449 134 unsigned type = avio_rl32(pb);
2450
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 134 times.
134 if (avio_feof(pb))
2451 return AVERROR_INVALIDDATA;
2452 134 avio_seek(pb, -8, SEEK_CUR);
2453
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)
2454 8 return mov_read_default(c, pb, atom);
2455 }
2456
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) {
2457 av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
2458 return 0;
2459 }
2460 130 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 130 times.
130 if (ret < 0)
2462 return ret;
2463
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'))
2464 /* HEVC-based Dolby Vision derived from hvc1.
2465 Happens to match with an identifier
2466 previously utilized for DV. Thus, if we have
2467 the hvcC extradata box available as specified,
2468 set codec to HEVC */
2469 st->codecpar->codec_id = AV_CODEC_ID_HEVC;
2470
2471 130 return 0;
2472 }
2473
2474 2 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2475 {
2476 AVStream *st;
2477 uint8_t profile_level;
2478 int ret;
2479
2480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
2481 return 0;
2482 2 st = c->fc->streams[c->fc->nb_streams-1];
2483
2484
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)
2485 return AVERROR_INVALIDDATA;
2486
2487 2 profile_level = avio_r8(pb);
2488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((profile_level & 0xf0) != 0xc0)
2489 return 0;
2490
2491 2 avio_seek(pb, 6, SEEK_CUR);
2492 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
2493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2494 return ret;
2495
2496 2 return 0;
2497 }
2498
2499 static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2500 {
2501 AVStream* st;
2502 MOVStreamContext* sc;
2503
2504 if (c->fc->nb_streams < 1)
2505 return 0;
2506
2507 /* For SBAS this should be fine - though beware if someone implements a
2508 * tref atom processor that doesn't drop down to default then this may
2509 * be lost. */
2510 if (atom.size > 4) {
2511 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2512 return AVERROR_PATCHWELCOME;
2513 }
2514
2515 st = c->fc->streams[c->fc->nb_streams - 1];
2516 sc = st->priv_data;
2517 sc->tref_id = avio_rb32(pb);
2518 sc->tref_flags |= MOV_TREF_FLAG_ENHANCEMENT;
2519
2520 return 0;
2521 }
2522
2523 /**
2524 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2525 * but can have extradata appended at the end after the 40 bytes belonging
2526 * to the struct.
2527 */
2528 static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2529 {
2530 AVStream *st;
2531 int ret;
2532
2533 if (c->fc->nb_streams < 1)
2534 return 0;
2535 if (atom.size <= 40)
2536 return 0;
2537 st = c->fc->streams[c->fc->nb_streams-1];
2538
2539 if ((uint64_t)atom.size > (1<<30))
2540 return AVERROR_INVALIDDATA;
2541
2542 avio_skip(pb, 40);
2543 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
2544 if (ret < 0)
2545 return ret;
2546
2547 return 0;
2548 }
2549
2550 593 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2551 {
2552 AVStream *st;
2553 MOVStreamContext *sc;
2554 unsigned int i, entries;
2555
2556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->trak_index < 0) {
2557 av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
2558 return 0;
2559 }
2560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->fc->nb_streams < 1)
2561 return 0;
2562 593 st = c->fc->streams[c->fc->nb_streams-1];
2563 593 sc = st->priv_data;
2564
2565 593 avio_r8(pb); /* version */
2566 593 avio_rb24(pb); /* flags */
2567
2568 // Clamp allocation size for `chunk_offsets` -- don't throw an error for an
2569 // invalid count since the EOF path doesn't throw either.
2570 593 entries = avio_rb32(pb);
2571 593 entries =
2572
2/2
✓ Branch 0 taken 588 times.
✓ Branch 1 taken 5 times.
593 FFMIN(entries,
2573 FFMAX(0, (atom.size - 8) /
2574 (atom.type == MKTAG('s', 't', 'c', 'o') ? 4 : 8)));
2575
2576
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 577 times.
593 if (!entries)
2577 16 return 0;
2578
2579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 577 times.
577 if (sc->chunk_offsets) {
2580 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2581 return 0;
2582 }
2583
2584 577 av_free(sc->chunk_offsets);
2585 577 sc->chunk_count = 0;
2586 577 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 577 times.
577 if (!sc->chunk_offsets)
2588 return AVERROR(ENOMEM);
2589 577 sc->chunk_count = entries;
2590
2591
2/2
✓ Branch 0 taken 573 times.
✓ Branch 1 taken 4 times.
577 if (atom.type == MKTAG('s','t','c','o'))
2592
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++)
2593 42906 sc->chunk_offsets[i] = avio_rb32(pb);
2594
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (atom.type == MKTAG('c','o','6','4'))
2595
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++) {
2596 136336 sc->chunk_offsets[i] = avio_rb64(pb);
2597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136336 times.
136336 if (sc->chunk_offsets[i] < 0) {
2598 av_log(c->fc, AV_LOG_WARNING, "Impossible chunk_offset\n");
2599 sc->chunk_offsets[i] = 0;
2600 }
2601 }
2602 else
2603 return AVERROR_INVALIDDATA;
2604
2605 577 sc->chunk_count = i;
2606
2607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 577 times.
577 if (pb->eof_reached) {
2608 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2609 return AVERROR_EOF;
2610 }
2611
2612 577 return 0;
2613 }
2614
2615 630 static int mov_codec_id(AVStream *st, uint32_t format)
2616 {
2617 630 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2618
2619
2/2
✓ Branch 0 taken 410 times.
✓ Branch 1 taken 220 times.
630 if (id <= 0 &&
2620
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 3 times.
410 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 407 times.
407 (format & 0xFFFF) == 'T' + ('S' << 8)))
2622 3 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2623
2624
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) {
2625 223 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2626
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 &&
2627 /* skip old ASF MPEG-4 tag */
2628
2/2
✓ Branch 0 taken 385 times.
✓ Branch 1 taken 4 times.
389 format && format != MKTAG('m','p','4','s')) {
2629 385 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2630
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 330 times.
385 if (id <= 0)
2631 55 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2632
2/2
✓ Branch 0 taken 334 times.
✓ Branch 1 taken 51 times.
385 if (id > 0)
2633 334 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2634
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 47 times.
51 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2635
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2637 47 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2638
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6 times.
47 if (id <= 0) {
2639
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 2 times.
80 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2640
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 2 times.
80 AV_CODEC_ID_TTML : id;
2641 }
2642
2643
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 37 times.
47 if (id > 0)
2644 10 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2645 else
2646 37 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2647 }
2648 }
2649
2650 630 st->codecpar->codec_tag = format;
2651
2652 630 return id;
2653 }
2654
2655 311 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2656 AVStream *st, MOVStreamContext *sc)
2657 {
2658 311 uint8_t codec_name[32] = { 0 };
2659 int64_t stsd_start;
2660 unsigned int len;
2661 311 uint32_t id = 0;
2662
2663 /* The first 16 bytes of the video sample description are already
2664 * read in ff_mov_read_stsd_entries() */
2665 311 stsd_start = avio_tell(pb) - 16;
2666
2667 311 avio_rb16(pb); /* version */
2668 311 avio_rb16(pb); /* revision level */
2669 311 id = avio_rl32(pb); /* vendor */
2670 311 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2671 311 avio_rb32(pb); /* temporal quality */
2672 311 avio_rb32(pb); /* spatial quality */
2673
2674 311 st->codecpar->width = avio_rb16(pb); /* width */
2675 311 st->codecpar->height = avio_rb16(pb); /* height */
2676
2677 311 avio_rb32(pb); /* horiz resolution */
2678 311 avio_rb32(pb); /* vert resolution */
2679 311 avio_rb32(pb); /* data size, always 0 */
2680 311 avio_rb16(pb); /* frames per samples */
2681
2682 311 len = avio_r8(pb); /* codec name, pascal string */
2683
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 310 times.
311 if (len > 31)
2684 1 len = 31;
2685 311 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2686
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 2 times.
311 if (len < 31)
2687 309 avio_skip(pb, 31 - len);
2688
2689
2/2
✓ Branch 0 taken 249 times.
✓ Branch 1 taken 62 times.
311 if (codec_name[0])
2690 249 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2691
2692 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2693
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)) {
2694 st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2695 st->codecpar->width &= ~1;
2696 st->codecpar->height &= ~1;
2697 }
2698 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 311 times.
311 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2700 !strncmp(codec_name, "Sorenson H263", 13))
2701 st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2702
2703 311 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2704
2705 311 avio_seek(pb, stsd_start, SEEK_SET);
2706
2707
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 293 times.
311 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2708 18 st->codecpar->bits_per_coded_sample &= 0x1F;
2709 18 sc->has_palette = 1;
2710 }
2711 311 }
2712
2713 241 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2714 AVStream *st, MOVStreamContext *sc)
2715 {
2716 int bits_per_sample, flags;
2717 241 uint16_t version = avio_rb16(pb);
2718 241 uint32_t id = 0;
2719 241 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2720 int channel_count;
2721
2722 241 avio_rb16(pb); /* revision level */
2723 241 id = avio_rl32(pb); /* vendor */
2724 241 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2725
2726 241 channel_count = avio_rb16(pb);
2727
2728 241 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2729 241 st->codecpar->ch_layout.nb_channels = channel_count;
2730 241 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
2731 241 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
2732
2733 241 sc->audio_cid = avio_rb16(pb);
2734 241 avio_rb16(pb); /* packet size = 0 */
2735
2736 241 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
2737
2738 // Read QT version 1 fields. In version 0 these do not exist.
2739 241 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
2740
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 ||
2741
1/2
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
155 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
2742
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)) {
2743
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 40 times.
90 if (version == 1) {
2744 50 sc->samples_per_frame = avio_rb32(pb);
2745 50 avio_rb32(pb); /* bytes per packet */
2746 50 sc->bytes_per_frame = avio_rb32(pb);
2747 50 avio_rb32(pb); /* bytes per sample */
2748
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
40 } else if (version == 2) {
2749 4 avio_rb32(pb); /* sizeof struct only */
2750 4 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
2751 4 channel_count = avio_rb32(pb);
2752 4 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2753 4 st->codecpar->ch_layout.nb_channels = channel_count;
2754 4 avio_rb32(pb); /* always 0x7F000000 */
2755 4 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
2756
2757 4 flags = avio_rb32(pb); /* lpcm format specific flag */
2758 4 sc->bytes_per_frame = avio_rb32(pb);
2759 4 sc->samples_per_frame = avio_rb32(pb);
2760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
2761 st->codecpar->codec_id =
2762 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
2763 flags);
2764 }
2765
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)) {
2766 /* can't correctly handle variable sized packet as audio unit */
2767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 switch (st->codecpar->codec_id) {
2768 case AV_CODEC_ID_MP2:
2769 case AV_CODEC_ID_MP3:
2770 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
2771 break;
2772 }
2773 }
2774 }
2775
2776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (sc->format == 0) {
2777 if (st->codecpar->bits_per_coded_sample == 8)
2778 st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
2779 else if (st->codecpar->bits_per_coded_sample == 16)
2780 st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
2781 }
2782
2783
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) {
2784 7 case AV_CODEC_ID_PCM_S8:
2785 case AV_CODEC_ID_PCM_U8:
2786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
2787 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2788 7 break;
2789 19 case AV_CODEC_ID_PCM_S16LE:
2790 case AV_CODEC_ID_PCM_S16BE:
2791
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
19 if (st->codecpar->bits_per_coded_sample == 8)
2792 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
2793
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 24)
2794 st->codecpar->codec_id =
2795 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2796 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
2797
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 32)
2798 st->codecpar->codec_id =
2799 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2800 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
2801 19 break;
2802 /* set values for old format before stsd version 1 appeared */
2803 2 case AV_CODEC_ID_MACE3:
2804 2 sc->samples_per_frame = 6;
2805 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
2806 2 break;
2807 8 case AV_CODEC_ID_MACE6:
2808 8 sc->samples_per_frame = 6;
2809 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
2810 8 break;
2811 5 case AV_CODEC_ID_ADPCM_IMA_QT:
2812 5 sc->samples_per_frame = 64;
2813 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
2814 5 break;
2815 1 case AV_CODEC_ID_GSM:
2816 1 sc->samples_per_frame = 160;
2817 1 sc->bytes_per_frame = 33;
2818 1 break;
2819 199 default:
2820 199 break;
2821 }
2822
2823 241 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2824
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) {
2825 48 st->codecpar->bits_per_coded_sample = bits_per_sample;
2826 48 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
2827 }
2828 241 }
2829
2830 11 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
2831 AVStream *st, MOVStreamContext *sc,
2832 int64_t size)
2833 {
2834 // ttxt stsd contains display flags, justification, background
2835 // color, fonts, and default styles, so fake an atom to read it
2836 11 MOVAtom fake_atom = { .size = size };
2837 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
2838 // in extradata unlike stpp MP4 TTML.
2839
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
2840
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
2841 9 mov_read_glbl(c, pb, fake_atom);
2842 11 st->codecpar->width = sc->width;
2843 11 st->codecpar->height = sc->height;
2844 11 }
2845
2846 41 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
2847 AVStream *st, MOVStreamContext *sc,
2848 int64_t size)
2849 {
2850 int ret;
2851
2852
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 22 times.
41 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
2853
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if ((int)size != size)
2854 return AVERROR(ENOMEM);
2855
2856 19 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
2857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
2858 return ret;
2859
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (size > 16) {
2860 19 MOVStreamContext *tmcd_ctx = st->priv_data;
2861 int val;
2862 19 val = AV_RB32(st->codecpar->extradata + 4);
2863 19 tmcd_ctx->tmcd_flags = val;
2864 19 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
2865 19 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
2866 19 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
2867
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (size > 30) {
2868 4 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
2869 4 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
2870
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) {
2871 4 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
2872
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 &&
2873
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 st->codecpar->extradata[30] /* Don't add empty string */) {
2874 4 char *reel_name = av_malloc(str_size + 1);
2875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!reel_name)
2876 return AVERROR(ENOMEM);
2877 4 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
2878 4 reel_name[str_size] = 0; /* Add null terminator */
2879 4 av_dict_set(&st->metadata, "reel_name", reel_name,
2880 AV_DICT_DONT_STRDUP_VAL);
2881 }
2882 }
2883 }
2884 }
2885 } else {
2886 /* other codec type, just skip (rtp, mp4s ...) */
2887 22 avio_skip(pb, size);
2888 }
2889 41 return 0;
2890 }
2891
2892 593 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
2893 AVStream *st, MOVStreamContext *sc)
2894 {
2895 593 FFStream *const sti = ffstream(st);
2896
2897
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 352 times.
593 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
2898
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)
2899 st->codecpar->sample_rate = sc->time_scale;
2900
2901 /* special codec parameters handling */
2902
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) {
2903 #if CONFIG_DV_DEMUXER
2904 case AV_CODEC_ID_DVAUDIO:
2905 if (c->dv_fctx) {
2906 avpriv_request_sample(c->fc, "multiple DV audio streams");
2907 return AVERROR(ENOSYS);
2908 }
2909
2910 c->dv_fctx = avformat_alloc_context();
2911 if (!c->dv_fctx) {
2912 av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
2913 return AVERROR(ENOMEM);
2914 }
2915 c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
2916 if (!c->dv_demux) {
2917 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
2918 return AVERROR(ENOMEM);
2919 }
2920 sc->dv_audio_container = 1;
2921 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2922 break;
2923 #endif
2924 /* no ifdef since parameters are always those */
2925 case AV_CODEC_ID_QCELP:
2926 av_channel_layout_uninit(&st->codecpar->ch_layout);
2927 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2928 // force sample rate for qcelp when not stored in mov
2929 if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
2930 st->codecpar->sample_rate = 8000;
2931 // FIXME: Why is the following needed for some files?
2932 sc->samples_per_frame = 160;
2933 if (!sc->bytes_per_frame)
2934 sc->bytes_per_frame = 35;
2935 break;
2936 case AV_CODEC_ID_AMR_NB:
2937 av_channel_layout_uninit(&st->codecpar->ch_layout);
2938 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2939 /* force sample rate for amr, stsd in 3gp does not store sample rate */
2940 st->codecpar->sample_rate = 8000;
2941 break;
2942 11 case AV_CODEC_ID_AMR_WB:
2943 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
2944 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2945 11 st->codecpar->sample_rate = 16000;
2946 11 break;
2947 1 case AV_CODEC_ID_MP2:
2948 case AV_CODEC_ID_MP3:
2949 /* force type after stsd for m1a hdlr */
2950 1 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2951 1 break;
2952 15 case AV_CODEC_ID_GSM:
2953 case AV_CODEC_ID_ADPCM_MS:
2954 case AV_CODEC_ID_ADPCM_IMA_WAV:
2955 case AV_CODEC_ID_ILBC:
2956 case AV_CODEC_ID_MACE3:
2957 case AV_CODEC_ID_MACE6:
2958 case AV_CODEC_ID_QDM2:
2959 15 st->codecpar->block_align = sc->bytes_per_frame;
2960 15 break;
2961 16 case AV_CODEC_ID_ALAC:
2962
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
2963 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
2964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
2965 av_channel_layout_uninit(&st->codecpar->ch_layout);
2966 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2967 st->codecpar->ch_layout.nb_channels = channel_count;
2968 }
2969 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
2970 }
2971 16 break;
2972 10 case AV_CODEC_ID_AC3:
2973 case AV_CODEC_ID_EAC3:
2974 case AV_CODEC_ID_MPEG1VIDEO:
2975 case AV_CODEC_ID_VC1:
2976 case AV_CODEC_ID_VP8:
2977 case AV_CODEC_ID_VP9:
2978 10 sti->need_parsing = AVSTREAM_PARSE_FULL;
2979 10 break;
2980 66 case AV_CODEC_ID_EVC:
2981 case AV_CODEC_ID_AV1:
2982 /* field_order detection of H264 requires parsing */
2983 case AV_CODEC_ID_H264:
2984 66 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
2985 66 break;
2986 474 default:
2987 474 break;
2988 }
2989 593 return 0;
2990 }
2991
2992 604 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
2993 int codec_tag, int format,
2994 int64_t size)
2995 {
2996
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 &&
2997 (codec_tag != format &&
2998 // AVID 1:1 samples with differing data format and codec tag exist
2999 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
3000 // prores is allowed to have differing data format and codec tag
3001 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
3002 // so is dv (sigh)
3003 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
3004 (c->fc->video_codec_id ? ff_codec_get_id(ff_codec_movvideo_tags, format) != c->fc->video_codec_id
3005 : codec_tag != MKTAG('j','p','e','g')))) {
3006 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3007 * export it as a separate AVStream but this needs a few changes
3008 * in the MOV demuxer, patch welcome. */
3009
3010 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3011 avio_skip(pb, size);
3012 return 1;
3013 }
3014
3015 604 return 0;
3016 }
3017
3018 593 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3019 {
3020 AVStream *st;
3021 MOVStreamContext *sc;
3022 int pseudo_stream_id;
3023
3024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 av_assert0 (c->fc->nb_streams >= 1);
3025 593 st = c->fc->streams[c->fc->nb_streams-1];
3026 593 sc = st->priv_data;
3027
3028 593 for (pseudo_stream_id = 0;
3029
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;
3030 604 pseudo_stream_id++) {
3031 //Parsing Sample description table
3032 enum AVCodecID id;
3033 604 int ret, dref_id = 1;
3034 604 MOVAtom a = { AV_RL32("stsd") };
3035 604 int64_t start_pos = avio_tell(pb);
3036 604 int64_t size = avio_rb32(pb); /* size */
3037 604 uint32_t format = avio_rl32(pb); /* data format */
3038
3039
1/2
✓ Branch 0 taken 604 times.
✗ Branch 1 not taken.
604 if (size >= 16) {
3040 604 avio_rb32(pb); /* reserved */
3041 604 avio_rb16(pb); /* reserved */
3042 604 dref_id = avio_rb16(pb);
3043 } else if (size <= 7) {
3044 av_log(c->fc, AV_LOG_ERROR,
3045 "invalid size %"PRId64" in stsd\n", size);
3046 return AVERROR_INVALIDDATA;
3047 }
3048
3049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 604 times.
604 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3050 604 size - (avio_tell(pb) - start_pos))) {
3051 sc->stsd_count++;
3052 continue;
3053 }
3054
3055
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;
3056 604 sc->dref_id= dref_id;
3057 604 sc->format = format;
3058
3059 604 id = mov_codec_id(st, format);
3060
3061 604 av_log(c->fc, AV_LOG_TRACE,
3062 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3063 604 av_fourcc2str(format), st->codecpar->codec_type);
3064
3065 604 st->codecpar->codec_id = id;
3066
2/2
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 293 times.
604 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3067 311 mov_parse_stsd_video(c, pb, st, sc);
3068
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 52 times.
293 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3069 241 mov_parse_stsd_audio(c, pb, st, sc);
3070
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (st->codecpar->sample_rate < 0) {
3071 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3072 return AVERROR_INVALIDDATA;
3073 }
3074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (st->codecpar->ch_layout.nb_channels < 0) {
3075 av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3076 return AVERROR_INVALIDDATA;
3077 }
3078
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 41 times.
52 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3079 11 mov_parse_stsd_subtitle(c, pb, st, sc,
3080 11 size - (avio_tell(pb) - start_pos));
3081 } else {
3082 41 ret = mov_parse_stsd_data(c, pb, st, sc,
3083 41 size - (avio_tell(pb) - start_pos));
3084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ret < 0)
3085 return ret;
3086 }
3087 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3088 604 a.size = size - (avio_tell(pb) - start_pos);
3089
2/2
✓ Branch 0 taken 476 times.
✓ Branch 1 taken 128 times.
604 if (a.size > 8) {
3090
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 476 times.
476 if ((ret = mov_read_default(c, pb, a)) < 0)
3091 return ret;
3092
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 127 times.
128 } else if (a.size > 0)
3093 1 avio_skip(pb, a.size);
3094
3095
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) {
3096 340 int extra_size = st->codecpar->extradata_size;
3097
3098 /* Move the current stream extradata to the stream context one. */
3099 340 sc->extradata_size[pseudo_stream_id] = extra_size;
3100 340 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3101 340 st->codecpar->extradata = NULL;
3102 340 st->codecpar->extradata_size = 0;
3103 }
3104 604 sc->stsd_count++;
3105 }
3106
3107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (pb->eof_reached) {
3108 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3109 return AVERROR_EOF;
3110 }
3111
3112 593 return 0;
3113 }
3114
3115 593 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3116 {
3117 AVStream *st;
3118 MOVStreamContext *sc;
3119 int ret, entries;
3120
3121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->fc->nb_streams < 1)
3122 return 0;
3123 593 st = c->fc->streams[c->fc->nb_streams - 1];
3124 593 sc = st->priv_data;
3125
3126 593 sc->stsd_version = avio_r8(pb);
3127 593 avio_rb24(pb); /* flags */
3128 593 entries = avio_rb32(pb);
3129
3130 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3131
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) {
3132 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3133 return AVERROR_INVALIDDATA;
3134 }
3135
3136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (sc->extradata) {
3137 av_log(c->fc, AV_LOG_ERROR,
3138 "Duplicate stsd found in this track.\n");
3139 return AVERROR_INVALIDDATA;
3140 }
3141
3142 /* Prepare space for hosting multiple extradata. */
3143 593 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (!sc->extradata)
3145 return AVERROR(ENOMEM);
3146
3147 593 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (!sc->extradata_size) {
3149 ret = AVERROR(ENOMEM);
3150 goto fail;
3151 }
3152
3153 593 ret = ff_mov_read_stsd_entries(c, pb, entries);
3154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (ret < 0)
3155 goto fail;
3156
3157 /* Restore back the primary extradata. */
3158 593 av_freep(&st->codecpar->extradata);
3159 593 st->codecpar->extradata_size = sc->extradata_size[0];
3160
2/2
✓ Branch 0 taken 330 times.
✓ Branch 1 taken 263 times.
593 if (sc->extradata_size[0]) {
3161 330 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 330 times.
330 if (!st->codecpar->extradata)
3163 return AVERROR(ENOMEM);
3164 330 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3165 }
3166
3167 593 return mov_finalize_stsd_codec(c, pb, st, sc);
3168 fail:
3169 if (sc->extradata) {
3170 int j;
3171 for (j = 0; j < sc->stsd_count; j++)
3172 av_freep(&sc->extradata[j]);
3173 }
3174
3175 av_freep(&sc->extradata);
3176 av_freep(&sc->extradata_size);
3177 return ret;
3178 }
3179
3180 593 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3181 {
3182 AVStream *st;
3183 MOVStreamContext *sc;
3184 unsigned int i, entries;
3185
3186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->trak_index < 0) {
3187 av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3188 return 0;
3189 }
3190
3191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->fc->nb_streams < 1)
3192 return 0;
3193 593 st = c->fc->streams[c->fc->nb_streams-1];
3194 593 sc = st->priv_data;
3195
3196 593 avio_r8(pb); /* version */
3197 593 avio_rb24(pb); /* flags */
3198
3199 593 entries = avio_rb32(pb);
3200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if ((uint64_t)entries * 12 + 4 > atom.size)
3201 return AVERROR_INVALIDDATA;
3202
3203 593 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3204
3205
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 578 times.
593 if (!entries)
3206 15 return 0;
3207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (sc->stsc_data) {
3208 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3209 return 0;
3210 }
3211 578 av_free(sc->stsc_data);
3212 578 sc->stsc_count = 0;
3213 578 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (!sc->stsc_data)
3215 return AVERROR(ENOMEM);
3216
3217
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++) {
3218 3778 sc->stsc_data[i].first = avio_rb32(pb);
3219 3778 sc->stsc_data[i].count = avio_rb32(pb);
3220 3778 sc->stsc_data[i].id = avio_rb32(pb);
3221 }
3222
3223 578 sc->stsc_count = i;
3224
2/2
✓ Branch 0 taken 3778 times.
✓ Branch 1 taken 578 times.
4356 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3225 3778 int64_t first_min = i + 1;
3226
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) ||
3227
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) ||
3228
1/2
✓ Branch 0 taken 3778 times.
✗ Branch 1 not taken.
3778 sc->stsc_data[i].first < first_min ||
3229
1/2
✓ Branch 0 taken 3778 times.
✗ Branch 1 not taken.
3778 sc->stsc_data[i].count < 1 ||
3230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3778 times.
3778 sc->stsc_data[i].id < 1) {
3231 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);
3232 if (i+1 >= sc->stsc_count) {
3233 if (sc->stsc_data[i].count == 0 && i > 0) {
3234 sc->stsc_count --;
3235 continue;
3236 }
3237 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3238 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3239 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3240 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3241 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3242 continue;
3243 }
3244 av_assert0(sc->stsc_data[i+1].first >= 2);
3245 // We replace this entry by the next valid
3246 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3247 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3248 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3249 }
3250 }
3251
3252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (pb->eof_reached) {
3253 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3254 return AVERROR_EOF;
3255 }
3256
3257 578 return 0;
3258 }
3259
3260 340657 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3261 {
3262 340657 return index < count - 1;
3263 }
3264
3265 /* Compute the samples value for the stsc entry at the given index. */
3266 55552 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3267 {
3268 int chunk_count;
3269
3270
2/2
✓ Branch 1 taken 55356 times.
✓ Branch 2 taken 196 times.
55552 if (mov_stsc_index_valid(index, sc->stsc_count))
3271 55356 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3272 else {
3273 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3275 196 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3276 }
3277
3278 55552 return sc->stsc_data[index].count * (int64_t)chunk_count;
3279 }
3280
3281 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3282 {
3283 AVStream *st;
3284 MOVStreamContext *sc;
3285 unsigned i, entries;
3286
3287 if (c->trak_index < 0) {
3288 av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3289 return 0;
3290 }
3291
3292 if (c->fc->nb_streams < 1)
3293 return 0;
3294 st = c->fc->streams[c->fc->nb_streams-1];
3295 sc = st->priv_data;
3296
3297 avio_rb32(pb); // version + flags
3298
3299 entries = avio_rb32(pb);
3300 if (sc->stps_data)
3301 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3302 av_free(sc->stps_data);
3303 sc->stps_count = 0;
3304 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3305 if (!sc->stps_data)
3306 return AVERROR(ENOMEM);
3307
3308 for (i = 0; i < entries && !pb->eof_reached; i++) {
3309 sc->stps_data[i] = avio_rb32(pb);
3310 }
3311
3312 sc->stps_count = i;
3313
3314 if (pb->eof_reached) {
3315 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3316 return AVERROR_EOF;
3317 }
3318
3319 return 0;
3320 }
3321
3322 143 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3323 {
3324 AVStream *st;
3325 FFStream *sti;
3326 MOVStreamContext *sc;
3327 unsigned int i, entries;
3328
3329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (c->trak_index < 0) {
3330 av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3331 return 0;
3332 }
3333
3334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (c->fc->nb_streams < 1)
3335 return 0;
3336 143 st = c->fc->streams[c->fc->nb_streams-1];
3337 143 sti = ffstream(st);
3338 143 sc = st->priv_data;
3339
3340 143 avio_r8(pb); /* version */
3341 143 avio_rb24(pb); /* flags */
3342
3343 143 entries = avio_rb32(pb);
3344
3345 143 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3346
3347
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 137 times.
143 if (!entries) {
3348 6 sc->keyframe_absent = 1;
3349
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)
3350 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3351 6 return 0;
3352 }
3353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
137 if (sc->keyframes)
3354 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
137 if (entries >= UINT_MAX / sizeof(int))
3356 return AVERROR_INVALIDDATA;
3357 137 av_freep(&sc->keyframes);
3358 137 sc->keyframe_count = 0;
3359 137 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
137 if (!sc->keyframes)
3361 return AVERROR(ENOMEM);
3362
3363
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++) {
3364 5701 sc->keyframes[i] = avio_rb32(pb);
3365 }
3366
3367 137 sc->keyframe_count = i;
3368
3369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
137 if (pb->eof_reached) {
3370 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3371 return AVERROR_EOF;
3372 }
3373
3374 137 return 0;
3375 }
3376
3377 593 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3378 {
3379 AVStream *st;
3380 MOVStreamContext *sc;
3381 unsigned int i, entries, sample_size, field_size, num_bytes;
3382 GetBitContext gb;
3383 unsigned char* buf;
3384 int ret;
3385
3386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->trak_index < 0) {
3387 av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3388 return 0;
3389 }
3390
3391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->fc->nb_streams < 1)
3392 return 0;
3393 593 st = c->fc->streams[c->fc->nb_streams-1];
3394 593 sc = st->priv_data;
3395
3396 593 avio_r8(pb); /* version */
3397 593 avio_rb24(pb); /* flags */
3398
3399
1/2
✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
593 if (atom.type == MKTAG('s','t','s','z')) {
3400 593 sample_size = avio_rb32(pb);
3401
2/2
✓ Branch 0 taken 552 times.
✓ Branch 1 taken 41 times.
593 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3402 552 sc->sample_size = sample_size;
3403 593 sc->stsz_sample_size = sample_size;
3404 593 field_size = 32;
3405 } else {
3406 sample_size = 0;
3407 avio_rb24(pb); /* reserved */
3408 field_size = avio_r8(pb);
3409 }
3410 593 entries = avio_rb32(pb);
3411
3412 593 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3413
3414 593 sc->sample_count = entries;
3415
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 395 times.
593 if (sample_size)
3416 198 return 0;
3417
3418
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) {
3419 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3420 return AVERROR_INVALIDDATA;
3421 }
3422
3423
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 379 times.
395 if (!entries)
3424 16 return 0;
3425
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)
3426 return AVERROR_INVALIDDATA;
3427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 379 times.
379 if (sc->sample_sizes)
3428 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3429 379 av_free(sc->sample_sizes);
3430 379 sc->sample_count = 0;
3431 379 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 379 times.
379 if (!sc->sample_sizes)
3433 return AVERROR(ENOMEM);
3434
3435 379 num_bytes = (entries*field_size+4)>>3;
3436
3437 379 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 379 times.
379 if (!buf) {
3439 av_freep(&sc->sample_sizes);
3440 return AVERROR(ENOMEM);
3441 }
3442
3443 379 ret = ffio_read_size(pb, buf, num_bytes);
3444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 379 times.
379 if (ret < 0) {
3445 av_freep(&sc->sample_sizes);
3446 av_free(buf);
3447 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3448 return 0;
3449 }
3450
3451 379 init_get_bits(&gb, buf, 8*num_bytes);
3452
3453
2/2
✓ Branch 0 taken 226833 times.
✓ Branch 1 taken 379 times.
227212 for (i = 0; i < entries; i++) {
3454 226833 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 226833 times.
226833 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3456 av_free(buf);
3457 av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3458 return AVERROR_INVALIDDATA;
3459 }
3460 226833 sc->data_size += sc->sample_sizes[i];
3461 }
3462
3463 379 sc->sample_count = i;
3464
3465 379 av_free(buf);
3466
3467 379 return 0;
3468 }
3469
3470 593 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3471 {
3472 AVStream *st;
3473 MOVStreamContext *sc;
3474 unsigned int i, entries;
3475 593 int64_t duration = 0;
3476 593 int64_t total_sample_count = 0;
3477 593 int64_t current_dts = 0;
3478 593 int64_t corrected_dts = 0;
3479
3480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->trak_index < 0) {
3481 av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3482 return 0;
3483 }
3484
3485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->fc->nb_streams < 1)
3486 return 0;
3487 593 st = c->fc->streams[c->fc->nb_streams-1];
3488 593 sc = st->priv_data;
3489
3490 593 avio_r8(pb); /* version */
3491 593 avio_rb24(pb); /* flags */
3492 593 entries = avio_rb32(pb);
3493
3494 593 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3495 593 c->fc->nb_streams-1, entries);
3496
3497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (sc->stts_data)
3498 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3499 593 av_freep(&sc->stts_data);
3500 593 sc->stts_count = 0;
3501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3502 return AVERROR(ENOMEM);
3503
3504
3/4
✓ Branch 0 taken 2940 times.
✓ Branch 1 taken 593 times.
✓ Branch 2 taken 2940 times.
✗ Branch 3 not taken.
3533 for (i = 0; i < entries && !pb->eof_reached; i++) {
3505 unsigned int sample_duration;
3506 unsigned int sample_count;
3507 2940 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3508 2940 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3509 min_entries * sizeof(*sc->stts_data));
3510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2940 times.
2940 if (!stts_data) {
3511 av_freep(&sc->stts_data);
3512 sc->stts_count = 0;
3513 return AVERROR(ENOMEM);
3514 }
3515 2940 sc->stts_count = min_entries;
3516 2940 sc->stts_data = stts_data;
3517
3518 2940 sample_count = avio_rb32(pb);
3519 2940 sample_duration = avio_rb32(pb);
3520
3521 2940 sc->stts_data[i].count= sample_count;
3522 2940 sc->stts_data[i].duration= sample_duration;
3523
3524 2940 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3525 sample_count, sample_duration);
3526
3527 /* STTS sample offsets are uint32 but some files store it as int32
3528 * with negative values used to correct DTS delays.
3529 There may be abnormally large values as well. */
3530
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2939 times.
2940 if (sample_duration > c->max_stts_delta) {
3531 // assume high delta is a correction if negative when cast as int32
3532 1 int32_t delta_magnitude = (int32_t)sample_duration;
3533 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",
3534 sample_duration, i, sample_count, st->index);
3535 1 sc->stts_data[i].duration = 1;
3536
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 corrected_dts += (delta_magnitude < 0 ? (int64_t)delta_magnitude : 1) * sample_count;
3537 } else {
3538 2939 corrected_dts += sample_duration * (uint64_t)sample_count;
3539 }
3540
3541 2940 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3542
3543
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2918 times.
2940 if (current_dts > corrected_dts) {
3544 22 int64_t drift = (current_dts - corrected_dts)/FFMAX(sample_count, 1);
3545
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;
3546 22 current_dts -= correction * (uint64_t)sample_count;
3547 22 sc->stts_data[i].duration -= correction;
3548 }
3549
3550 2940 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3551 2940 total_sample_count+=sc->stts_data[i].count;
3552 }
3553
3554 593 sc->stts_count = i;
3555
3556
2/2
✓ Branch 0 taken 577 times.
✓ Branch 1 taken 16 times.
593 if (duration > 0 &&
3557
1/2
✓ Branch 0 taken 577 times.
✗ Branch 1 not taken.
577 duration <= INT64_MAX - sc->duration_for_fps &&
3558
1/2
✓ Branch 0 taken 577 times.
✗ Branch 1 not taken.
577 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3559 577 sc->duration_for_fps += duration;
3560 577 sc->nb_frames_for_fps += total_sample_count;
3561 }
3562
3563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (pb->eof_reached) {
3564 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3565 return AVERROR_EOF;
3566 }
3567
3568 593 st->nb_frames= total_sample_count;
3569
2/2
✓ Branch 0 taken 577 times.
✓ Branch 1 taken 16 times.
593 if (duration)
3570 577 st->duration= FFMIN(st->duration, duration);
3571
3572 // All samples have zero duration. They have higher chance be chose by
3573 // mov_find_next_sample, which leads to seek again and again.
3574 //
3575 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3576 // So only mark data stream as discarded for safety.
3577
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 &&
3578 st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3579 av_log(c->fc, AV_LOG_WARNING,
3580 "All samples in data stream index:id [%d:%d] have zero "
3581 "duration, stream set to be discarded by default. Override "
3582 "using AVStream->discard or -discard for ffmpeg command.\n",
3583 st->index, sc->id);
3584 st->discard = AVDISCARD_ALL;
3585 }
3586 593 sc->track_end = duration;
3587 593 return 0;
3588 }
3589
3590 44 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3591 {
3592 AVStream *st;
3593 MOVStreamContext *sc;
3594 int64_t i, entries;
3595
3596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (c->fc->nb_streams < 1)
3597 return 0;
3598 44 st = c->fc->streams[c->fc->nb_streams - 1];
3599 44 sc = st->priv_data;
3600
3601 44 avio_r8(pb); /* version */
3602 44 avio_rb24(pb); /* flags */
3603 44 entries = atom.size - 4;
3604
3605 44 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3606 44 c->fc->nb_streams - 1, entries);
3607
3608
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 36 times.
44 if (sc->sdtp_data)
3609 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3610 44 av_freep(&sc->sdtp_data);
3611 44 sc->sdtp_count = 0;
3612
3613 44 sc->sdtp_data = av_malloc(entries);
3614
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (!sc->sdtp_data)
3615 return AVERROR(ENOMEM);
3616
3617
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++)
3618 3807 sc->sdtp_data[i] = avio_r8(pb);
3619 44 sc->sdtp_count = i;
3620
3621 44 return 0;
3622 }
3623
3624 10827 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3625 {
3626
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 9691 times.
10827 if (duration < 0) {
3627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3628 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3629 duration++;
3630 }
3631 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3632 }
3633 10827 }
3634
3635 63 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3636 {
3637 AVStream *st;
3638 MOVStreamContext *sc;
3639 63 unsigned int i, entries, ctts_count = 0;
3640
3641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->trak_index < 0) {
3642 av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
3643 return 0;
3644 }
3645
3646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->fc->nb_streams < 1)
3647 return 0;
3648 63 st = c->fc->streams[c->fc->nb_streams-1];
3649 63 sc = st->priv_data;
3650
3651 63 avio_r8(pb); /* version */
3652 63 avio_rb24(pb); /* flags */
3653 63 entries = avio_rb32(pb);
3654
3655 63 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3656
3657
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 59 times.
63 if (!entries)
3658 4 return 0;
3659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
3660 return AVERROR_INVALIDDATA;
3661 59 av_freep(&sc->ctts_data);
3662 59 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
3663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->ctts_data)
3664 return AVERROR(ENOMEM);
3665
3666
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++) {
3667 MOVCtts *ctts_data;
3668 4874 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
3669 4874 const size_t requested_size =
3670 4874 min_size_needed > sc->ctts_allocated_size ?
3671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
3672 min_size_needed;
3673 4874 int count = avio_rb32(pb);
3674 4874 int duration = avio_rb32(pb);
3675
3676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (count <= 0) {
3677 av_log(c->fc, AV_LOG_TRACE,
3678 "ignoring CTTS entry with count=%d duration=%d\n",
3679 count, duration);
3680 continue;
3681 }
3682
3683
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
3684 return AVERROR(ENOMEM);
3685
3686 4874 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
3687
3688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (!ctts_data)
3689 return AVERROR(ENOMEM);
3690
3691 4874 sc->ctts_data = ctts_data;
3692
3693 4874 ctts_data[ctts_count].count = count;
3694 4874 ctts_data[ctts_count].offset = duration;
3695 4874 ctts_count++;
3696
3697 4874 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
3698 count, duration);
3699
3700
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) {
3701 av_log(c->fc, AV_LOG_WARNING, "CTTS invalid\n");
3702 av_freep(&sc->ctts_data);
3703 sc->ctts_count = 0;
3704 return 0;
3705 }
3706
3707
2/2
✓ Branch 0 taken 4761 times.
✓ Branch 1 taken 113 times.
4874 if (i+2<entries)
3708 4761 mov_update_dts_shift(sc, duration, c->fc);
3709 }
3710
3711 59 sc->ctts_count = ctts_count;
3712
3713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (pb->eof_reached) {
3714 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
3715 return AVERROR_EOF;
3716 }
3717
3718 59 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
3719
3720 59 return 0;
3721 }
3722
3723 28 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3724 {
3725 AVStream *st;
3726 MOVStreamContext *sc;
3727 uint8_t version;
3728 uint32_t grouping_type;
3729 uint32_t default_length;
3730 av_unused uint32_t default_group_description_index;
3731 uint32_t entry_count;
3732
3733
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (c->fc->nb_streams < 1)
3734 return 0;
3735 28 st = c->fc->streams[c->fc->nb_streams - 1];
3736 28 sc = st->priv_data;
3737
3738 28 version = avio_r8(pb); /* version */
3739 28 avio_rb24(pb); /* flags */
3740 28 grouping_type = avio_rl32(pb);
3741
3742 /*
3743 * This function only supports "sync" boxes, but the code is able to parse
3744 * other boxes (such as "tscl", "tsas" and "stsa")
3745 */
3746
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 5 times.
28 if (grouping_type != MKTAG('s','y','n','c'))
3747 23 return 0;
3748
3749
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
3750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
3751 5 entry_count = avio_rb32(pb);
3752
3753 5 av_freep(&sc->sgpd_sync);
3754 5 sc->sgpd_sync_count = entry_count;
3755 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
3756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
3757 return AVERROR(ENOMEM);
3758
3759
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++) {
3760 8 uint32_t description_length = default_length;
3761
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)
3762 description_length = avio_rb32(pb);
3763
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
3764 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
3765 8 sc->sgpd_sync[i] = nal_unit_type;
3766 8 description_length -= 1;
3767 }
3768 8 avio_skip(pb, description_length);
3769 }
3770
3771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
3772 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
3773 return AVERROR_EOF;
3774 }
3775
3776 5 return 0;
3777 }
3778
3779 25 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3780 {
3781 AVStream *st;
3782 MOVStreamContext *sc;
3783 unsigned int i, entries;
3784 uint8_t version;
3785 uint32_t grouping_type;
3786 MOVSbgp *table, **tablep;
3787 int *table_count;
3788
3789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (c->fc->nb_streams < 1)
3790 return 0;
3791 25 st = c->fc->streams[c->fc->nb_streams-1];
3792 25 sc = st->priv_data;
3793
3794 25 version = avio_r8(pb); /* version */
3795 25 avio_rb24(pb); /* flags */
3796 25 grouping_type = avio_rl32(pb);
3797
3798
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 24 times.
25 if (grouping_type == MKTAG('r','a','p',' ')) {
3799 1 tablep = &sc->rap_group;
3800 1 table_count = &sc->rap_group_count;
3801
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19 times.
24 } else if (grouping_type == MKTAG('s','y','n','c')) {
3802 5 tablep = &sc->sync_group;
3803 5 table_count = &sc->sync_group_count;
3804 } else {
3805 19 return 0;
3806 }
3807
3808
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
3809 avio_rb32(pb); /* grouping_type_parameter */
3810
3811 6 entries = avio_rb32(pb);
3812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
3813 return 0;
3814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
3815 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
3816 6 av_freep(tablep);
3817 6 table = av_malloc_array(entries, sizeof(*table));
3818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
3819 return AVERROR(ENOMEM);
3820 6 *tablep = table;
3821
3822
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++) {
3823 32 table[i].count = avio_rb32(pb); /* sample_count */
3824 32 table[i].index = avio_rb32(pb); /* group_description_index */
3825 }
3826
3827 6 *table_count = i;
3828
3829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
3830 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
3831 return AVERROR_EOF;
3832 }
3833
3834 6 return 0;
3835 }
3836
3837 /**
3838 * Get ith edit list entry (media time, duration).
3839 */
3840 899 static int get_edit_list_entry(MOVContext *mov,
3841 const MOVStreamContext *msc,
3842 unsigned int edit_list_index,
3843 int64_t *edit_list_media_time,
3844 int64_t *edit_list_duration,
3845 int64_t global_timescale)
3846 {
3847
2/2
✓ Branch 0 taken 436 times.
✓ Branch 1 taken 463 times.
899 if (edit_list_index == msc->elst_count) {
3848 436 return 0;
3849 }
3850 463 *edit_list_media_time = msc->elst_data[edit_list_index].time;
3851 463 *edit_list_duration = msc->elst_data[edit_list_index].duration;
3852
3853 /* duration is in global timescale units;convert to msc timescale */
3854
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 463 times.
463 if (global_timescale == 0) {
3855 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
3856 return 0;
3857 }
3858 463 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
3859 global_timescale);
3860
3861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 463 times.
463 if (*edit_list_duration + (uint64_t)*edit_list_media_time > INT64_MAX)
3862 *edit_list_duration = 0;
3863
3864 463 return 1;
3865 }
3866
3867 /**
3868 * Find the closest previous frame to the timestamp_pts, in e_old index
3869 * entries. Searching for just any frame / just key frames can be controlled by
3870 * last argument 'flag'.
3871 * Note that if ctts_data is not NULL, we will always search for a key frame
3872 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
3873 * return the first frame of the video.
3874 *
3875 * Here the timestamp_pts is considered to be a presentation timestamp and
3876 * the timestamp of index entries are considered to be decoding timestamps.
3877 *
3878 * Returns 0 if successful in finding a frame, else returns -1.
3879 * Places the found index corresponding output arg.
3880 *
3881 * If ctts_old is not NULL, then refines the searched entry by searching
3882 * backwards from the found timestamp, to find the frame with correct PTS.
3883 *
3884 * Places the found ctts_index and ctts_sample in corresponding output args.
3885 */
3886 462 static int find_prev_closest_index(AVStream *st,
3887 AVIndexEntry *e_old,
3888 int nb_old,
3889 MOVTimeToSample *tts_data,
3890 int64_t tts_count,
3891 int64_t timestamp_pts,
3892 int flag,
3893 int64_t* index,
3894 int64_t* tts_index,
3895 int64_t* tts_sample)
3896 {
3897 462 MOVStreamContext *msc = st->priv_data;
3898 462 FFStream *const sti = ffstream(st);
3899 462 AVIndexEntry *e_keep = sti->index_entries;
3900 462 int nb_keep = sti->nb_index_entries;
3901 462 int64_t i = 0;
3902
3903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 462 times.
462 av_assert0(index);
3904
3905 // If dts_shift > 0, then all the index timestamps will have to be offset by
3906 // at least dts_shift amount to obtain PTS.
3907 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
3908
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 453 times.
462 if (msc->dts_shift > 0) {
3909 9 timestamp_pts -= msc->dts_shift;
3910 }
3911
3912 462 sti->index_entries = e_old;
3913 462 sti->nb_index_entries = nb_old;
3914 462 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
3915
3916 // Keep going backwards in the index entries until the timestamp is the same.
3917
2/2
✓ Branch 0 taken 461 times.
✓ Branch 1 taken 1 times.
462 if (*index >= 0) {
3918
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;
3919 i--) {
3920 if ((flag & AVSEEK_FLAG_ANY) ||
3921 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
3922 *index = i - 1;
3923 }
3924 }
3925 }
3926
3927 // If we have CTTS then refine the search, by searching backwards over PTS
3928 // computed by adding corresponding CTTS durations to index timestamps.
3929
4/4
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 398 times.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 1 times.
462 if (msc->ctts_count && *index >= 0) {
3930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(tts_index);
3931
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(tts_sample);
3932 // Find out the ctts_index for the found frame.
3933 63 *tts_index = 0;
3934 63 *tts_sample = 0;
3935
2/2
✓ Branch 0 taken 175 times.
✓ Branch 1 taken 63 times.
238 for (int64_t index_tts_count = 0; index_tts_count < *index; index_tts_count++) {
3936
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (*tts_index < tts_count) {
3937 175 (*tts_sample)++;
3938
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (tts_data[*tts_index].count == *tts_sample) {
3939 175 (*tts_index)++;
3940 175 *tts_sample = 0;
3941 }
3942 }
3943 }
3944
3945
4/6
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 70 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 70 times.
✗ Branch 5 not taken.
75 while (*index >= 0 && (*tts_index) >= 0 && (*tts_index) < tts_count) {
3946 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
3947 // No need to add dts_shift to the timestamp here becase timestamp_pts has already been
3948 // compensated by dts_shift above.
3949
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 8 times.
70 if ((e_old[*index].timestamp + tts_data[*tts_index].offset) <= timestamp_pts &&
3950
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 4 times.
62 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
3951 58 break;
3952 }
3953
3954 12 (*index)--;
3955
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (*tts_sample == 0) {
3956 12 (*tts_index)--;
3957
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 if (*tts_index >= 0)
3958 7 *tts_sample = tts_data[*tts_index].count - 1;
3959 } else {
3960 (*tts_sample)--;
3961 }
3962 }
3963 }
3964
3965 /* restore AVStream state*/
3966 462 sti->index_entries = e_keep;
3967 462 sti->nb_index_entries = nb_keep;
3968
2/2
✓ Branch 0 taken 456 times.
✓ Branch 1 taken 6 times.
462 return *index >= 0 ? 0 : -1;
3969 }
3970
3971 /**
3972 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
3973 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
3974 *
3975 * This function is similar to ff_add_index_entry in libavformat/utils.c
3976 * except that here we are always unconditionally adding an index entry to
3977 * the end, instead of searching the entries list and skipping the add if
3978 * there is an existing entry with the same timestamp.
3979 * This is needed because the mov_fix_index calls this func with the same
3980 * unincremented timestamp for successive discarded frames.
3981 */
3982 348497 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
3983 int size, int distance, int flags)
3984 {
3985 348497 FFStream *const sti = ffstream(st);
3986 AVIndexEntry *entries, *ie;
3987 348497 int64_t index = -1;
3988 348497 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
3989
3990 // Double the allocation each time, to lower memory fragmentation.
3991 // Another difference from ff_add_index_entry function.
3992 348497 const size_t requested_size =
3993 348497 min_size_needed > sti->index_entries_allocated_size ?
3994
2/2
✓ Branch 0 taken 1968 times.
✓ Branch 1 taken 346529 times.
348497 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
3995 min_size_needed;
3996
3997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348497 times.
348497 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
3998 return -1;
3999
4000 348497 entries = av_fast_realloc(sti->index_entries,
4001 &sti->index_entries_allocated_size,
4002 requested_size);
4003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348497 times.
348497 if (!entries)
4004 return -1;
4005
4006 348497 sti->index_entries = entries;
4007
4008 348497 index = sti->nb_index_entries++;
4009 348497 ie= &entries[index];
4010
4011 348497 ie->pos = pos;
4012 348497 ie->timestamp = timestamp;
4013 348497 ie->min_distance= distance;
4014 348497 ie->size= size;
4015 348497 ie->flags = flags;
4016 348497 return index;
4017 }
4018
4019 /**
4020 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4021 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4022 */
4023 27 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4024 int64_t* frame_duration_buffer,
4025 int frame_duration_buffer_size) {
4026 27 FFStream *const sti = ffstream(st);
4027 27 int i = 0;
4028
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);
4029
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 27 times.
164 for (i = 0; i < frame_duration_buffer_size; i++) {
4030 137 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4031 137 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4032 }
4033 27 }
4034
4035 185998 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4036 int count, int offset, unsigned int duration)
4037 {
4038 MOVTimeToSample *tts_buf_new;
4039 185998 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4040 185998 const size_t requested_size =
4041 185998 min_size_needed > *allocated_size ?
4042
2/2
✓ Branch 0 taken 1337 times.
✓ Branch 1 taken 184661 times.
185998 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4043 min_size_needed;
4044
4045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 185998 times.
185998 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4046 return -1;
4047
4048 185998 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4049
4050
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 185998 times.
185998 if (!tts_buf_new)
4051 return -1;
4052
4053 185998 *tts_data = tts_buf_new;
4054
4055 185998 tts_buf_new[*tts_count].count = count;
4056 185998 tts_buf_new[*tts_count].offset = offset;
4057 185998 tts_buf_new[*tts_count].duration = duration;
4058
4059 185998 *tts_count = (*tts_count) + 1;
4060 185998 return 0;
4061 }
4062
4063 #define MAX_REORDER_DELAY 16
4064 600 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4065 {
4066 600 MOVStreamContext *msc = st->priv_data;
4067 600 FFStream *const sti = ffstream(st);
4068 600 int ctts_ind = 0;
4069 600 int ctts_sample = 0;
4070 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4071 600 int buf_start = 0;
4072 int j, r, num_swaps;
4073
4074
2/2
✓ Branch 0 taken 10200 times.
✓ Branch 1 taken 600 times.
10800 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4075 10200 pts_buf[j] = INT64_MIN;
4076
4077
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_count &&
4078
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 16 times.
59 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4079 43 st->codecpar->video_delay = 0;
4080
3/4
✓ Branch 0 taken 138279 times.
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 138279 times.
✗ Branch 3 not taken.
138322 for (int ind = 0; ind < sti->nb_index_entries && ctts_ind < msc->tts_count; ++ind) {
4081 // Point j to the last elem of the buffer and insert the current pts there.
4082 138279 j = buf_start;
4083 138279 buf_start = (buf_start + 1);
4084
2/2
✓ Branch 0 taken 8111 times.
✓ Branch 1 taken 130168 times.
138279 if (buf_start == MAX_REORDER_DELAY + 1)
4085 8111 buf_start = 0;
4086
4087 138279 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4088
4089 // The timestamps that are already in the sorted buffer, and are greater than the
4090 // current pts, are exactly the timestamps that need to be buffered to output PTS
4091 // in correct sorted order.
4092 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4093 // can be computed as the maximum no. of swaps any particular timestamp needs to
4094 // go through, to keep this buffer in sorted order.
4095 138279 num_swaps = 0;
4096
2/2
✓ Branch 0 taken 142294 times.
✓ Branch 1 taken 4 times.
142298 while (j != buf_start) {
4097 142294 r = j - 1;
4098
2/2
✓ Branch 0 taken 8389 times.
✓ Branch 1 taken 133905 times.
142294 if (r < 0) r = MAX_REORDER_DELAY;
4099
2/2
✓ Branch 0 taken 4019 times.
✓ Branch 1 taken 138275 times.
142294 if (pts_buf[j] < pts_buf[r]) {
4100 4019 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4101 4019 ++num_swaps;
4102 } else {
4103 138275 break;
4104 }
4105 4019 j = r;
4106 }
4107 138279 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4108
4109 138279 ctts_sample++;
4110
1/2
✓ Branch 0 taken 138279 times.
✗ Branch 1 not taken.
138279 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4111 138279 ctts_ind++;
4112 138279 ctts_sample = 0;
4113 }
4114 }
4115 43 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4116 43 st->codecpar->video_delay, st->index);
4117 }
4118 600 }
4119
4120 103374 static void mov_current_sample_inc(MOVStreamContext *sc)
4121 {
4122 103374 sc->current_sample++;
4123 103374 sc->current_index++;
4124
2/2
✓ Branch 0 taken 61375 times.
✓ Branch 1 taken 41999 times.
103374 if (sc->index_ranges &&
4125
2/2
✓ Branch 0 taken 420 times.
✓ Branch 1 taken 60955 times.
61375 sc->current_index >= sc->current_index_range->end &&
4126
1/2
✓ Branch 0 taken 420 times.
✗ Branch 1 not taken.
420 sc->current_index_range->end) {
4127 420 sc->current_index_range++;
4128 420 sc->current_index = sc->current_index_range->start;
4129 }
4130 103374 }
4131
4132 static void mov_current_sample_dec(MOVStreamContext *sc)
4133 {
4134 sc->current_sample--;
4135 sc->current_index--;
4136 if (sc->index_ranges &&
4137 sc->current_index < sc->current_index_range->start &&
4138 sc->current_index_range > sc->index_ranges) {
4139 sc->current_index_range--;
4140 sc->current_index = sc->current_index_range->end - 1;
4141 }
4142 }
4143
4144 335 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4145 {
4146 int64_t range_size;
4147
4148 335 sc->current_sample = current_sample;
4149 335 sc->current_index = current_sample;
4150
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 309 times.
335 if (!sc->index_ranges) {
4151 26 return;
4152 }
4153
4154 309 for (sc->current_index_range = sc->index_ranges;
4155
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 sc->current_index_range->end;
4156 sc->current_index_range++) {
4157 309 range_size = sc->current_index_range->end - sc->current_index_range->start;
4158
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 if (range_size > current_sample) {
4159 309 sc->current_index = sc->current_index_range->start + current_sample;
4160 309 break;
4161 }
4162 current_sample -= range_size;
4163 }
4164 }
4165
4166 /**
4167 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4168 * which are needed to decode them) that fall in the edit list time ranges.
4169 * Also fixes the timestamps of the index entries to match the timeline
4170 * specified the edit lists.
4171 */
4172 600 static void mov_fix_index(MOVContext *mov, AVStream *st)
4173 {
4174 600 MOVStreamContext *msc = st->priv_data;
4175 600 FFStream *const sti = ffstream(st);
4176 600 AVIndexEntry *e_old = sti->index_entries;
4177 600 int nb_old = sti->nb_index_entries;
4178 600 const AVIndexEntry *e_old_end = e_old + nb_old;
4179 600 const AVIndexEntry *current = NULL;
4180 600 MOVTimeToSample *tts_data_old = msc->tts_data;
4181 600 int64_t tts_index_old = 0;
4182 600 int64_t tts_sample_old = 0;
4183 600 int64_t tts_count_old = msc->tts_count;
4184 600 int64_t edit_list_media_time = 0;
4185 600 int64_t edit_list_duration = 0;
4186 600 int64_t frame_duration = 0;
4187 600 int64_t edit_list_dts_counter = 0;
4188 600 int64_t edit_list_dts_entry_end = 0;
4189 600 int64_t edit_list_start_tts_sample = 0;
4190 int64_t curr_cts;
4191 600 int64_t curr_ctts = 0;
4192 600 int64_t empty_edits_sum_duration = 0;
4193 600 int64_t edit_list_index = 0;
4194 int64_t index;
4195 int flags;
4196 600 int64_t start_dts = 0;
4197 600 int64_t edit_list_start_encountered = 0;
4198 600 int64_t search_timestamp = 0;
4199 600 int64_t* frame_duration_buffer = NULL;
4200 600 int num_discarded_begin = 0;
4201 600 int first_non_zero_audio_edit = -1;
4202 600 int packet_skip_samples = 0;
4203 600 MOVIndexRange *current_index_range = NULL;
4204 600 int found_keyframe_after_edit = 0;
4205 600 int found_non_empty_edit = 0;
4206
4207
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) {
4208 164 return;
4209 }
4210
4211 // allocate the index ranges array
4212 436 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4213 sizeof(msc->index_ranges[0]));
4214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 436 times.
436 if (!msc->index_ranges) {
4215 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4216 return;
4217 }
4218 436 msc->current_index_range = msc->index_ranges;
4219
4220 // Clean AVStream from traces of old index
4221 436 sti->index_entries = NULL;
4222 436 sti->index_entries_allocated_size = 0;
4223 436 sti->nb_index_entries = 0;
4224
4225 // Clean time to sample fields of MOVStreamContext
4226 436 msc->tts_data = NULL;
4227 436 msc->tts_count = 0;
4228 436 msc->tts_index = 0;
4229 436 msc->tts_sample = 0;
4230 436 msc->tts_allocated_size = 0;
4231
4232 // Reinitialize min_corrected_pts so that it can be computed again.
4233 436 msc->min_corrected_pts = -1;
4234
4235 // If the dts_shift is positive (in case of negative ctts values in mov),
4236 // then negate the DTS by dts_shift
4237
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 427 times.
436 if (msc->dts_shift > 0) {
4238 9 edit_list_dts_entry_end -= msc->dts_shift;
4239 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4240 }
4241
4242 436 start_dts = edit_list_dts_entry_end;
4243
4244
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,
4245 899 &edit_list_duration, mov->time_scale)) {
4246 463 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4247 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4248 463 edit_list_index++;
4249 463 edit_list_dts_counter = edit_list_dts_entry_end;
4250 463 edit_list_dts_entry_end += edit_list_duration;
4251 463 num_discarded_begin = 0;
4252
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) {
4253 4 empty_edits_sum_duration += edit_list_duration;
4254 4 continue;
4255 }
4256 459 found_non_empty_edit = 1;
4257
4258 // If we encounter a non-negative edit list reset the skip_samples/start_pad fields and set them
4259 // according to the edit list below.
4260
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 332 times.
459 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4261
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit < 0) {
4262 127 first_non_zero_audio_edit = 1;
4263 } else {
4264 first_non_zero_audio_edit = 0;
4265 }
4266
4267
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit > 0)
4268 127 sti->skip_samples = msc->start_pad = 0;
4269 }
4270
4271 // While reordering frame index according to edit list we must handle properly
4272 // the scenario when edit list entry starts from none key frame.
4273 // We find closest previous key frame and preserve it and consequent frames in index.
4274 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4275 459 search_timestamp = edit_list_media_time;
4276
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 332 times.
459 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4277 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4278 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4279 // edit_list_media_time to cover the decoder delay.
4280 127 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
4281 }
4282
4283
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 456 times.
459 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, 0,
4284 &index, &tts_index_old, &tts_sample_old) < 0) {
4285 3 av_log(mov->fc, AV_LOG_WARNING,
4286 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4287 st->index, edit_list_index, search_timestamp);
4288
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, AVSEEK_FLAG_ANY,
4289 &index, &tts_index_old, &tts_sample_old) < 0) {
4290 3 av_log(mov->fc, AV_LOG_WARNING,
4291 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4292 st->index, edit_list_index, search_timestamp);
4293 3 index = 0;
4294 3 tts_index_old = 0;
4295 3 tts_sample_old = 0;
4296 }
4297 }
4298 459 current = e_old + index;
4299 459 edit_list_start_tts_sample = tts_sample_old;
4300
4301 // Iterate over index and arrange it according to edit list
4302 459 edit_list_start_encountered = 0;
4303 459 found_keyframe_after_edit = 0;
4304
2/2
✓ Branch 0 taken 348497 times.
✓ Branch 1 taken 111 times.
348608 for (; current < e_old_end; current++, index++) {
4305 // check if frame outside edit list mark it for discard
4306 696994 frame_duration = (current + 1 < e_old_end) ?
4307
2/2
✓ Branch 0 taken 348065 times.
✓ Branch 1 taken 432 times.
348497 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4308
4309 348497 flags = current->flags;
4310
4311 // frames (pts) before or after edit list
4312 348497 curr_cts = current->timestamp + msc->dts_shift;
4313 348497 curr_ctts = 0;
4314
4315
4/4
✓ Branch 0 taken 186010 times.
✓ Branch 1 taken 162487 times.
✓ Branch 2 taken 185998 times.
✓ Branch 3 taken 12 times.
348497 if (tts_data_old && tts_index_old < tts_count_old) {
4316 185998 curr_ctts = tts_data_old[tts_index_old].offset;
4317 185998 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4318 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4319 185998 curr_cts += curr_ctts;
4320 185998 tts_sample_old++;
4321
1/2
✓ Branch 0 taken 185998 times.
✗ Branch 1 not taken.
185998 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 185998 times.
185998 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4323 &msc->tts_allocated_size,
4324 185998 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4325 185998 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4326 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4327 tts_index_old,
4328 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4329 tts_data_old[tts_index_old].offset);
4330 break;
4331 }
4332 185998 tts_index_old++;
4333 185998 tts_sample_old = 0;
4334 185998 edit_list_start_tts_sample = 0;
4335 }
4336 }
4337
4338
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)) {
4339
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 &&
4340
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 &&
4341 first_non_zero_audio_edit > 0) {
4342 11 packet_skip_samples = edit_list_media_time - curr_cts;
4343 11 sti->skip_samples += packet_skip_samples;
4344
4345 // Shift the index entry timestamp by packet_skip_samples to be correct.
4346 11 edit_list_dts_counter -= packet_skip_samples;
4347
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (edit_list_start_encountered == 0) {
4348 11 edit_list_start_encountered = 1;
4349 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4350 // discarded packets.
4351
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 if (frame_duration_buffer) {
4352 6 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4353 frame_duration_buffer, num_discarded_begin);
4354 6 av_freep(&frame_duration_buffer);
4355 }
4356 }
4357
4358 11 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4359 } else {
4360 271 flags |= AVINDEX_DISCARD_FRAME;
4361 271 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4362
4363
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 132 times.
271 if (edit_list_start_encountered == 0) {
4364 139 num_discarded_begin++;
4365 139 frame_duration_buffer = av_realloc(frame_duration_buffer,
4366 num_discarded_begin * sizeof(int64_t));
4367
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if (!frame_duration_buffer) {
4368 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4369 break;
4370 }
4371 139 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4372
4373 // Increment skip_samples for the first non-zero audio edit list
4374
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 &&
4375
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) {
4376 20 sti->skip_samples += frame_duration;
4377 }
4378 }
4379 }
4380 } else {
4381
2/2
✓ Branch 0 taken 435 times.
✓ Branch 1 taken 347780 times.
348215 if (msc->min_corrected_pts < 0) {
4382 435 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4383 } else {
4384 347780 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4385 }
4386
2/2
✓ Branch 0 taken 446 times.
✓ Branch 1 taken 347769 times.
348215 if (edit_list_start_encountered == 0) {
4387 446 edit_list_start_encountered = 1;
4388 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4389 // discarded packets.
4390
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 425 times.
446 if (frame_duration_buffer) {
4391 21 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4392 frame_duration_buffer, num_discarded_begin);
4393 21 av_freep(&frame_duration_buffer);
4394 }
4395 }
4396 }
4397
4398
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,
4399 348497 current->min_distance, flags) == -1) {
4400 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4401 break;
4402 }
4403
4404 // Update the index ranges array
4405
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) {
4406 457 current_index_range = current_index_range ? current_index_range + 1
4407
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 436 times.
457 : msc->index_ranges;
4408 457 current_index_range->start = index;
4409 }
4410 348497 current_index_range->end = index + 1;
4411
4412 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4413
2/2
✓ Branch 0 taken 348358 times.
✓ Branch 1 taken 139 times.
348497 if (edit_list_start_encountered > 0) {
4414 348358 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4415 }
4416
4417 // Break when found first key frame after edit entry completion
4418
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)) &&
4419
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)))) {
4420
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 339 times.
360 if (msc->ctts_count) {
4421 // If we have CTTS and this is the first keyframe after edit elist,
4422 // wait for one more, because there might be trailing B-frames after this I-frame
4423 // that do belong to the edit.
4424
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) {
4425 12 found_keyframe_after_edit = 1;
4426 12 continue;
4427 }
4428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (tts_sample_old != 0) {
4429 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4430 &msc->tts_allocated_size,
4431 tts_sample_old - edit_list_start_tts_sample,
4432 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4433 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4434 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4435 tts_data_old[tts_index_old].offset);
4436 break;
4437 }
4438 }
4439 }
4440 348 break;
4441 }
4442 }
4443 }
4444 // If there are empty edits, then msc->min_corrected_pts might be positive
4445 // intentionally. So we subtract the sum duration of emtpy edits here.
4446 436 msc->min_corrected_pts -= empty_edits_sum_duration;
4447
4448 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4449 // dts by that amount to make the first pts zero.
4450
2/2
✓ Branch 0 taken 267 times.
✓ Branch 1 taken 169 times.
436 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4451
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 226 times.
267 if (msc->min_corrected_pts > 0) {
4452 41 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4453
2/2
✓ Branch 0 taken 2829 times.
✓ Branch 1 taken 41 times.
2870 for (int i = 0; i < sti->nb_index_entries; ++i)
4454 2829 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4455 }
4456 }
4457 // Start time should be equal to zero or the duration of any empty edits.
4458 436 st->start_time = empty_edits_sum_duration;
4459
4460 // Update av stream length, if it ends up shorter than the track's media duration
4461 436 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4462 436 msc->start_pad = sti->skip_samples;
4463
4464 // Free the old index and the old CTTS structures
4465 436 av_free(e_old);
4466 436 av_free(tts_data_old);
4467 436 av_freep(&frame_duration_buffer);
4468
4469 // Null terminate the index ranges array
4470 436 current_index_range = current_index_range ? current_index_range + 1
4471
1/2
✓ Branch 0 taken 436 times.
✗ Branch 1 not taken.
436 : msc->index_ranges;
4472 436 current_index_range->start = 0;
4473 436 current_index_range->end = 0;
4474 436 msc->current_index = msc->index_ranges[0].start;
4475 }
4476
4477 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4478 {
4479
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4480
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == HEVC_NAL_CRA_NUT)
4481 5 return i + 1;
4482 return 0;
4483 }
4484
4485 616 static int build_open_gop_key_points(AVStream *st)
4486 {
4487 int k;
4488 616 int sample_id = 0;
4489 uint32_t cra_index;
4490 616 MOVStreamContext *sc = st->priv_data;
4491
4492
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)
4493 611 return 0;
4494
4495 /* Build an unrolled index of the samples */
4496 5 sc->sample_offsets_count = 0;
4497
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4499 return AVERROR(ENOMEM);
4500 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4501 }
4502 5 av_freep(&sc->sample_offsets);
4503 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4505 return AVERROR(ENOMEM);
4506 5 k = 0;
4507
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4508
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4509 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4510
4511 /* The following HEVC NAL type reveal the use of open GOP sync points
4512 * (TODO: BLA types may also be concerned) */
4513 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4515 return 0;
4516
4517 /* Build a list of open-GOP key samples */
4518 5 sc->open_key_samples_count = 0;
4519
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4520
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4521
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)
4522 return AVERROR(ENOMEM);
4523 11 sc->open_key_samples_count += sc->sync_group[i].count;
4524 }
4525 5 av_freep(&sc->open_key_samples);
4526 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4528 return AVERROR(ENOMEM);
4529 5 k = 0;
4530
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4531 28 const MOVSbgp *sg = &sc->sync_group[i];
4532
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4533
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4534 11 sc->open_key_samples[k++] = sample_id;
4535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4536 return AVERROR_PATCHWELCOME;
4537 28 sample_id += sg->count;
4538 }
4539
4540 /* Identify the minimal time step between samples */
4541 5 sc->min_sample_duration = UINT_MAX;
4542
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4543 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4544
4545 5 return 0;
4546 }
4547
4548 #define MOV_MERGE_CTTS 1
4549 #define MOV_MERGE_STTS 2
4550 /*
4551 * Merge stts and ctts arrays into a new combined array.
4552 * stts_count and ctts_count may be left untouched as they will be
4553 * used to check for the presence of either of them.
4554 */
4555 600 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4556 {
4557 600 MOVStreamContext *sc = st->priv_data;
4558
3/4
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 541 times.
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
600 int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS);
4559
3/4
✓ Branch 0 taken 600 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 534 times.
✓ Branch 3 taken 66 times.
600 int stts = sc->stts_data && (flags & MOV_MERGE_STTS);
4560 600 int idx = 0;
4561
4562
3/4
✓ Branch 0 taken 541 times.
✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 541 times.
600 if (!sc->ctts_data && !sc->stts_data)
4563 return 0;
4564 // Expand time to sample entries such that we have a 1-1 mapping with samples
4565
2/4
✓ Branch 0 taken 600 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 600 times.
600 if (!sc->sample_count || sc->sample_count >= UINT_MAX / sizeof(*sc->tts_data))
4566 return -1;
4567
4568
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 541 times.
600 if (ctts) {
4569 118 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4570 59 sc->sample_count * sizeof(*sc->tts_data));
4571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->tts_data)
4572 return -1;
4573
4574 59 memset(sc->tts_data, 0, sc->tts_allocated_size);
4575
4576
2/2
✓ Branch 0 taken 4874 times.
✓ Branch 1 taken 59 times.
4933 for (int i = 0; i < sc->ctts_count &&
4577
1/2
✓ Branch 0 taken 4874 times.
✗ Branch 1 not taken.
9748 idx < sc->sample_count; i++)
4578
2/2
✓ Branch 0 taken 139017 times.
✓ Branch 1 taken 4874 times.
143891 for (int j = 0; j < sc->ctts_data[i].count &&
4579
1/2
✓ Branch 0 taken 139017 times.
✗ Branch 1 not taken.
139017 idx < sc->sample_count; j++) {
4580 139017 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4581 139017 sc->tts_data[idx++].count = 1;
4582 }
4583
4584 59 sc->tts_count = idx;
4585 } else
4586 541 sc->ctts_count = 0;
4587 600 av_freep(&sc->ctts_data);
4588 600 sc->ctts_allocated_size = 0;
4589
4590 600 idx = 0;
4591
2/2
✓ Branch 0 taken 534 times.
✓ Branch 1 taken 66 times.
600 if (stts) {
4592 534 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4593 534 sc->sample_count * sizeof(*sc->tts_data));
4594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 534 times.
534 if (!tts_data)
4595 return -1;
4596
4597
2/2
✓ Branch 0 taken 475 times.
✓ Branch 1 taken 59 times.
534 if (!sc->tts_data)
4598 475 memset(tts_data, 0, sc->tts_allocated_size);
4599 534 sc->tts_data = tts_data;
4600
4601
2/2
✓ Branch 0 taken 2897 times.
✓ Branch 1 taken 534 times.
3431 for (int i = 0; i < sc->stts_count &&
4602
1/2
✓ Branch 0 taken 2897 times.
✗ Branch 1 not taken.
5794 idx < sc->sample_count; i++)
4603
2/2
✓ Branch 0 taken 235842 times.
✓ Branch 1 taken 2897 times.
238739 for (int j = 0; j < sc->stts_data[i].count &&
4604
1/2
✓ Branch 0 taken 235842 times.
✗ Branch 1 not taken.
235842 idx < sc->sample_count; j++) {
4605 235842 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4606 235842 sc->tts_data[idx++].count = 1;
4607 }
4608
4609 534 sc->tts_count = FFMAX(sc->tts_count, idx);
4610 } else
4611 66 sc->stts_count = 0;
4612 600 av_freep(&sc->stts_data);
4613 600 sc->stts_allocated_size = 0;
4614
4615 600 return 0;
4616 }
4617
4618 616 static void mov_build_index(MOVContext *mov, AVStream *st)
4619 {
4620 616 MOVStreamContext *sc = st->priv_data;
4621 616 FFStream *const sti = ffstream(st);
4622 int64_t current_offset;
4623 616 int64_t current_dts = 0;
4624 616 unsigned int stts_index = 0;
4625 616 unsigned int stsc_index = 0;
4626 616 unsigned int stss_index = 0;
4627 616 unsigned int stps_index = 0;
4628 unsigned int i, j;
4629 616 uint64_t stream_size = 0;
4630
4631 616 int ret = build_open_gop_key_points(st);
4632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 616 times.
616 if (ret < 0)
4633 return;
4634
4635
2/2
✓ Branch 0 taken 438 times.
✓ Branch 1 taken 178 times.
616 if (sc->elst_count) {
4636 438 int i, edit_start_index = 0, multiple_edits = 0;
4637 438 int64_t empty_duration = 0; // empty duration of the first edit list entry
4638 438 int64_t start_time = 0; // start time of the media
4639
4640
2/2
✓ Branch 0 taken 465 times.
✓ Branch 1 taken 438 times.
903 for (i = 0; i < sc->elst_count; i++) {
4641 465 const MOVElst *e = &sc->elst_data[i];
4642
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) {
4643 /* if empty, the first entry is the start time of the stream
4644 * relative to the presentation itself */
4645 4 empty_duration = e->duration;
4646 4 edit_start_index = 1;
4647
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) {
4648 438 start_time = e->time;
4649 } else {
4650 23 multiple_edits = 1;
4651 }
4652 }
4653
4654
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) {
4655 if (mov->advanced_editlist_autodisabled)
4656 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4657 "not supported in fragmented MP4 files\n");
4658 else
4659 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4660 "Use -advanced_editlist to correctly decode otherwise "
4661 "a/v desync might occur\n");
4662 }
4663
4664 /* adjust first dts according to edit list */
4665
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) {
4666
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 69 times.
73 if (empty_duration)
4667 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
4668
4669
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)
4670 av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
4671
4672 73 sc->time_offset = start_time - (uint64_t)empty_duration;
4673 73 sc->min_corrected_pts = start_time;
4674
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 72 times.
73 if (!mov->advanced_editlist)
4675 1 current_dts = -sc->time_offset;
4676 }
4677
4678
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 &&
4679
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)
4680 sc->start_pad = start_time;
4681 }
4682
4683 /* only use old uncompressed audio chunk demuxing when stts specifies it */
4684
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 375 times.
616 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4685
4/4
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 121 times.
✓ Branch 3 taken 66 times.
775 sc->stts_count == 1 && sc->stts_data[0].duration == 1)) {
4686 550 unsigned int current_sample = 0;
4687 550 unsigned int stts_sample = 0;
4688 unsigned int sample_size;
4689 550 unsigned int distance = 0;
4690 550 unsigned int rap_group_index = 0;
4691 550 unsigned int rap_group_sample = 0;
4692
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;
4693
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);
4694
4695 550 current_dts -= sc->dts_shift;
4696
4697
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)
4698 16 return;
4699
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)
4700 return;
4701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 534 times.
534 if (av_reallocp_array(&sti->index_entries,
4702 534 sti->nb_index_entries + sc->sample_count,
4703 sizeof(*sti->index_entries)) < 0) {
4704 sti->nb_index_entries = 0;
4705 return;
4706 }
4707 534 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
4708
4709 534 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
4710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 534 times.
534 if (ret < 0)
4711 return;
4712
4713
2/2
✓ Branch 0 taken 173837 times.
✓ Branch 1 taken 534 times.
174371 for (i = 0; i < sc->chunk_count; i++) {
4714
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;
4715 173837 current_offset = sc->chunk_offsets[i];
4716
2/2
✓ Branch 1 taken 8859 times.
✓ Branch 2 taken 167521 times.
176380 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4717
2/2
✓ Branch 0 taken 2543 times.
✓ Branch 1 taken 6316 times.
8859 i + 1 == sc->stsc_data[stsc_index + 1].first)
4718 2543 stsc_index++;
4719
4720
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 &&
4721 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
4722 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
4723 sc->stsz_sample_size = sc->sample_size;
4724 }
4725
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) {
4726 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
4727 sc->stsz_sample_size = sc->sample_size;
4728 }
4729
4730
2/2
✓ Branch 0 taken 235842 times.
✓ Branch 1 taken 173837 times.
409679 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
4731 235842 int keyframe = 0;
4732
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235842 times.
235842 if (current_sample >= sc->sample_count) {
4733 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
4734 return;
4735 }
4736
4737
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])) {
4738 84193 keyframe = 1;
4739
2/2
✓ Branch 0 taken 5564 times.
✓ Branch 1 taken 78629 times.
84193 if (stss_index + 1 < sc->keyframe_count)
4740 5564 stss_index++;
4741
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]) {
4742 keyframe = 1;
4743 if (stps_index + 1 < sc->stps_count)
4744 stps_index++;
4745 }
4746
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) {
4747
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
4748 2 keyframe = 1;
4749
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
4750 4 rap_group_sample = 0;
4751 4 rap_group_index++;
4752 }
4753 }
4754
2/2
✓ Branch 0 taken 4756 times.
✓ Branch 1 taken 231086 times.
235842 if (sc->keyframe_absent
4755
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !sc->stps_count
4756
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !rap_group_present
4757
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)))
4758 3884 keyframe = 1;
4759
2/2
✓ Branch 0 taken 88077 times.
✓ Branch 1 taken 147765 times.
235842 if (keyframe)
4760 88077 distance = 0;
4761
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];
4762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235842 times.
235842 if (current_offset > INT64_MAX - sample_size) {
4763 av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
4764 current_offset,
4765 sample_size);
4766 return;
4767 }
4768
4769
2/2
✓ Branch 0 taken 235761 times.
✓ Branch 1 taken 81 times.
235842 if (sc->pseudo_stream_id == -1 ||
4770
1/2
✓ Branch 0 taken 235761 times.
✗ Branch 1 not taken.
235761 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
4771 AVIndexEntry *e;
4772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235842 times.
235842 if (sample_size > 0x3FFFFFFF) {
4773 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
4774 return;
4775 }
4776 235842 e = &sti->index_entries[sti->nb_index_entries++];
4777 235842 e->pos = current_offset;
4778 235842 e->timestamp = current_dts;
4779 235842 e->size = sample_size;
4780 235842 e->min_distance = distance;
4781 235842 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
4782 235842 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
4783 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
4784 current_offset, current_dts, sample_size, distance, keyframe);
4785
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)
4786 10309 ff_rfps_add_frame(mov->fc, st, current_dts);
4787 }
4788
4789 235842 current_offset += sample_size;
4790 235842 stream_size += sample_size;
4791
4792 235842 current_dts += sc->tts_data[stts_index].duration;
4793
4794 235842 distance++;
4795 235842 stts_sample++;
4796 235842 current_sample++;
4797
3/4
✓ Branch 0 taken 235308 times.
✓ Branch 1 taken 534 times.
✓ Branch 2 taken 235308 times.
✗ Branch 3 not taken.
235842 if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) {
4798 235308 stts_sample = 0;
4799 235308 stts_index++;
4800 }
4801 }
4802 }
4803
2/2
✓ Branch 0 taken 511 times.
✓ Branch 1 taken 23 times.
534 if (st->duration > 0)
4804 511 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
4805 } else {
4806 66 unsigned chunk_samples, total = 0;
4807
4808 66 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
4809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
4810 return;
4811
4812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (!sc->chunk_count)
4813 return;
4814
4815 // compute total chunk count
4816
2/2
✓ Branch 0 taken 723 times.
✓ Branch 1 taken 66 times.
789 for (i = 0; i < sc->stsc_count; i++) {
4817 unsigned count, chunk_count;
4818
4819 723 chunk_samples = sc->stsc_data[i].count;
4820
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 66 times.
723 if (i != sc->stsc_count - 1 &&
4821
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) {
4822 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
4823 return;
4824 }
4825
4826
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 648 times.
723 if (sc->samples_per_frame >= 160) { // gsm
4827 75 count = chunk_samples / sc->samples_per_frame;
4828
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 117 times.
648 } else if (sc->samples_per_frame > 1) {
4829 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
4830 531 count = (chunk_samples+samples-1) / samples;
4831 } else {
4832 117 count = (chunk_samples+1023) / 1024;
4833 }
4834
4835
2/2
✓ Branch 1 taken 657 times.
✓ Branch 2 taken 66 times.
723 if (mov_stsc_index_valid(i, sc->stsc_count))
4836 657 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
4837 else
4838 66 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
4839 723 total += chunk_count * count;
4840 }
4841
4842 66 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
4843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4844 return;
4845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (av_reallocp_array(&sti->index_entries,
4846 66 sti->nb_index_entries + total,
4847 sizeof(*sti->index_entries)) < 0) {
4848 sti->nb_index_entries = 0;
4849 return;
4850 }
4851 66 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
4852
4853 // populate index
4854
2/2
✓ Branch 0 taken 5428 times.
✓ Branch 1 taken 66 times.
5494 for (i = 0; i < sc->chunk_count; i++) {
4855 5428 current_offset = sc->chunk_offsets[i];
4856
2/2
✓ Branch 1 taken 5287 times.
✓ Branch 2 taken 141 times.
5428 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4857
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 4630 times.
5287 i + 1 == sc->stsc_data[stsc_index + 1].first)
4858 657 stsc_index++;
4859 5428 chunk_samples = sc->stsc_data[stsc_index].count;
4860
4861
2/2
✓ Branch 0 taken 162532 times.
✓ Branch 1 taken 5428 times.
167960 while (chunk_samples > 0) {
4862 AVIndexEntry *e;
4863 unsigned size, samples;
4864
4865
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) {
4866 avpriv_request_sample(mov->fc,
4867 "Zero bytes per frame, but %d samples per frame",
4868 sc->samples_per_frame);
4869 return;
4870 }
4871
4872
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 148174 times.
162532 if (sc->samples_per_frame >= 160) { // gsm
4873 14358 samples = sc->samples_per_frame;
4874 14358 size = sc->bytes_per_frame;
4875 } else {
4876
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 138611 times.
148174 if (sc->samples_per_frame > 1) {
4877 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
4878 sc->samples_per_frame, chunk_samples);
4879 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
4880 } else {
4881 138611 samples = FFMIN(1024, chunk_samples);
4882 138611 size = samples * sc->sample_size;
4883 }
4884 }
4885
4886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (sti->nb_index_entries >= total) {
4887 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
4888 return;
4889 }
4890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (size > 0x3FFFFFFF) {
4891 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
4892 return;
4893 }
4894 162532 e = &sti->index_entries[sti->nb_index_entries++];
4895 162532 e->pos = current_offset;
4896 162532 e->timestamp = current_dts;
4897 162532 e->size = size;
4898 162532 e->min_distance = 0;
4899 162532 e->flags = AVINDEX_KEYFRAME;
4900 162532 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
4901 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
4902 size, samples);
4903
4904 162532 current_offset += size;
4905 162532 current_dts += samples;
4906 162532 chunk_samples -= samples;
4907 }
4908 }
4909 }
4910
4911
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) {
4912 // Fix index according to edit lists.
4913 600 mov_fix_index(mov, st);
4914 }
4915
4916 // Update start time of the stream.
4917
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) {
4918 47 st->start_time = sti->index_entries[0].timestamp + sc->dts_shift;
4919
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 if (sc->tts_data) {
4920 47 st->start_time += sc->tts_data[0].offset;
4921 }
4922 }
4923
4924 600 mov_estimate_video_delay(mov, st);
4925 }
4926
4927 static int test_same_origin(const char *src, const char *ref) {
4928 char src_proto[64];
4929 char ref_proto[64];
4930 char src_auth[256];
4931 char ref_auth[256];
4932 char src_host[256];
4933 char ref_host[256];
4934 int src_port=-1;
4935 int ref_port=-1;
4936
4937 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
4938 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
4939
4940 if (strlen(src) == 0) {
4941 return -1;
4942 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
4943 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
4944 strlen(src_host) + 1 >= sizeof(src_host) ||
4945 strlen(ref_host) + 1 >= sizeof(ref_host)) {
4946 return 0;
4947 } else if (strcmp(src_proto, ref_proto) ||
4948 strcmp(src_auth, ref_auth) ||
4949 strcmp(src_host, ref_host) ||
4950 src_port != ref_port) {
4951 return 0;
4952 } else
4953 return 1;
4954 }
4955
4956 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
4957 {
4958 /* try relative path, we do not try the absolute because it can leak information about our
4959 system to an attacker */
4960 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
4961 char filename[1025];
4962 const char *src_path;
4963 int i, l;
4964
4965 /* find a source dir */
4966 src_path = strrchr(src, '/');
4967 if (src_path)
4968 src_path++;
4969 else
4970 src_path = src;
4971
4972 /* find a next level down to target */
4973 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
4974 if (ref->path[l] == '/') {
4975 if (i == ref->nlvl_to - 1)
4976 break;
4977 else
4978 i++;
4979 }
4980
4981 /* compose filename if next level down to target was found */
4982 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
4983 memcpy(filename, src, src_path - src);
4984 filename[src_path - src] = 0;
4985
4986 for (i = 1; i < ref->nlvl_from; i++)
4987 av_strlcat(filename, "../", sizeof(filename));
4988
4989 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
4990 if (!c->use_absolute_path) {
4991 int same_origin = test_same_origin(src, filename);
4992
4993 if (!same_origin) {
4994 av_log(c->fc, AV_LOG_ERROR,
4995 "Reference with mismatching origin, %s not tried for security reasons, "
4996 "set demuxer option use_absolute_path to allow it anyway\n",
4997 ref->path);
4998 return AVERROR(ENOENT);
4999 }
5000
5001 if (strstr(ref->path + l + 1, "..") ||
5002 strstr(ref->path + l + 1, ":") ||
5003 (ref->nlvl_from > 1 && same_origin < 0) ||
5004 (filename[0] == '/' && src_path == src))
5005 return AVERROR(ENOENT);
5006 }
5007
5008 if (strlen(filename) + 1 == sizeof(filename))
5009 return AVERROR(ENOENT);
5010 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5011 return 0;
5012 }
5013 } else if (c->use_absolute_path) {
5014 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5015 "this is a possible security issue\n");
5016 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5017 return 0;
5018 } else {
5019 av_log(c->fc, AV_LOG_ERROR,
5020 "Absolute path %s not tried for security reasons, "
5021 "set demuxer option use_absolute_path to allow absolute paths\n",
5022 ref->path);
5023 }
5024
5025 return AVERROR(ENOENT);
5026 }
5027
5028 1263 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5029 {
5030
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1249 times.
1263 if (sc->time_scale <= 0) {
5031 14 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5032 14 sc->time_scale = c->time_scale;
5033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (sc->time_scale <= 0)
5034 sc->time_scale = 1;
5035 }
5036 1263 }
5037
5038 #if CONFIG_IAMFDEC
5039 10 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5040 {
5041 10 const MOVStreamContext *sc = st->priv_data;
5042 10 const IAMFContext *iamf = &sc->iamf->iamf;
5043
5044
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5045 10 const AVStreamGroup *stg = NULL;
5046
5047
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5048
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)
5049 10 stg = c->fc->stream_groups[j];
5050
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 av_assert0(stg);
5051
5052
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int j = 0; j < stg->nb_streams; j++) {
5053 50 const FFStream *sti = cffstream(st);
5054 50 AVStream *out = stg->streams[j];
5055 50 FFStream *out_sti = ffstream(stg->streams[j]);
5056
5057 50 out->codecpar->bit_rate = 0;
5058
5059
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 40 times.
50 if (out == st)
5060 10 continue;
5061
5062 40 out->time_base = st->time_base;
5063 40 out->start_time = st->start_time;
5064 40 out->duration = st->duration;
5065 40 out->nb_frames = st->nb_frames;
5066 40 out->discard = st->discard;
5067
5068
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 av_assert0(!out_sti->index_entries);
5069 40 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5070
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (!out_sti->index_entries)
5071 return AVERROR(ENOMEM);
5072
5073 40 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5074 40 out_sti->nb_index_entries = sti->nb_index_entries;
5075 40 out_sti->skip_samples = sti->skip_samples;
5076 40 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5077 }
5078 }
5079
5080 10 return 0;
5081 }
5082 #endif
5083
5084 616 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5085 {
5086
4/6
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 600 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 600 times.
✗ Branch 5 not taken.
616 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5087
3/4
✓ Branch 0 taken 402 times.
✓ Branch 1 taken 198 times.
✓ Branch 2 taken 402 times.
✗ Branch 3 not taken.
600 (!sc->sample_size && !sc->sample_count))) ||
5088
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 600 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
616 (!sc->chunk_count && sc->sample_count)) {
5089 av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5090 index);
5091 return 1;
5092 }
5093
5094
3/4
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 600 times.
616 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
5095 av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5096 index);
5097 return 2;
5098 }
5099 616 return 0;
5100 }
5101
5102 593 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5103 {
5104 AVStream *st;
5105 MOVStreamContext *sc;
5106 int ret;
5107
5108 593 st = avformat_new_stream(c->fc, NULL);
5109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (!st) return AVERROR(ENOMEM);
5110 593 st->id = -1;
5111 593 sc = av_mallocz(sizeof(MOVStreamContext));
5112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (!sc) return AVERROR(ENOMEM);
5113
5114 593 st->priv_data = sc;
5115 593 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5116 593 sc->ffindex = st->index;
5117 593 c->trak_index = st->index;
5118 593 sc->tref_flags = 0;
5119 593 sc->tref_id = -1;
5120 593 sc->refcount = 1;
5121
5122
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 593 times.
593 if ((ret = mov_read_default(c, pb, atom)) < 0)
5123 return ret;
5124
5125 593 c->trak_index = -1;
5126
5127 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5128 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5129
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) {
5130 1 sc->stsc_count = 0;
5131 1 av_freep(&sc->stsc_data);
5132 }
5133
5134 593 ret = sanity_checks(c->fc, sc, st->index);
5135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (ret)
5136 return ret > 1 ? AVERROR_INVALIDDATA : 0;
5137
5138 593 fix_timescale(c, sc);
5139
5140 593 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5141
5142 /*
5143 * Advanced edit list support does not work with fragemented MP4s, which
5144 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5145 * In these files, trun atoms may be streamed in.
5146 */
5147
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) {
5148
5149 12 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5150 "MP4. disabling.\n");
5151 12 c->advanced_editlist = 0;
5152 12 c->advanced_editlist_autodisabled = 1;
5153 }
5154
5155 593 mov_build_index(c, st);
5156
5157 #if CONFIG_IAMFDEC
5158
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 583 times.
593 if (sc->iamf) {
5159 10 ret = mov_update_iamf_streams(c, st);
5160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
5161 return ret;
5162 }
5163 #endif
5164
5165
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) {
5166 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5167 if (c->enable_drefs) {
5168 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5169 av_log(c->fc, AV_LOG_ERROR,
5170 "stream %d, error opening alias: path='%s', dir='%s', "
5171 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5172 st->index, dref->path, dref->dir, dref->filename,
5173 dref->volume, dref->nlvl_from, dref->nlvl_to);
5174 } else {
5175 av_log(c->fc, AV_LOG_WARNING,
5176 "Skipped opening external track: "
5177 "stream %d, alias: path='%s', dir='%s', "
5178 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5179 "Set enable_drefs to allow this.\n",
5180 st->index, dref->path, dref->dir, dref->filename,
5181 dref->volume, dref->nlvl_from, dref->nlvl_to);
5182 }
5183 } else {
5184 593 sc->pb = c->fc->pb;
5185 593 sc->pb_is_copied = 1;
5186 }
5187
5188
2/2
✓ Branch 0 taken 301 times.
✓ Branch 1 taken 292 times.
593 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5189 301 int stts_constant = !!sc->stts_count;
5190
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)
5191 57 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5192 57 sc->h_spacing, sc->v_spacing, INT_MAX);
5193
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 &&
5194
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 &&
5195
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)) {
5196 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5197 (int64_t)st->codecpar->height * sc->width,
5198 (int64_t)st->codecpar->width * sc->height, INT_MAX);
5199 }
5200
5201 #if FF_API_R_FRAME_RATE
5202
4/4
✓ Branch 0 taken 154778 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 154487 times.
✓ Branch 3 taken 291 times.
154788 for (unsigned int i = 1; sc->stts_count && i + 1 < sc->tts_count; i++) {
5203
2/2
✓ Branch 0 taken 152060 times.
✓ Branch 1 taken 2427 times.
154487 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5204 152060 continue;
5205 2427 stts_constant = 0;
5206 }
5207
2/2
✓ Branch 0 taken 277 times.
✓ Branch 1 taken 24 times.
301 if (stts_constant)
5208 277 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5209 277 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5210 #endif
5211 }
5212
5213 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
5214
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 &&
5215 TAG_IS_AVCI(st->codecpar->codec_tag)) {
5216 ret = ff_generate_avci_extradata(st);
5217 if (ret < 0)
5218 return ret;
5219 }
5220
5221
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 569 times.
593 switch (st->codecpar->codec_id) {
5222 #if CONFIG_H261_DECODER
5223 24 case AV_CODEC_ID_H261:
5224 #endif
5225 #if CONFIG_H263_DECODER
5226 case AV_CODEC_ID_H263:
5227 #endif
5228 #if CONFIG_MPEG4_DECODER
5229 case AV_CODEC_ID_MPEG4:
5230 #endif
5231 24 st->codecpar->width = 0; /* let decoder init width/height */
5232 24 st->codecpar->height= 0;
5233 24 break;
5234 }
5235
5236 // If the duration of the mp3 packets is not constant, then they could need a parser
5237
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 592 times.
593 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5238
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 && sc->time_scale == st->codecpar->sample_rate) {
5239 1 int stts_constant = 1;
5240
3/4
✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 287 times.
✓ Branch 3 taken 1 times.
288 for (int i = 1; sc->stts_count && i < sc->tts_count; i++) {
5241
1/2
✓ Branch 0 taken 287 times.
✗ Branch 1 not taken.
287 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5242 287 continue;
5243 stts_constant = 0;
5244 }
5245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!stts_constant)
5246 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5247 }
5248 /* Do not need those anymore. */
5249 593 av_freep(&sc->chunk_offsets);
5250 593 av_freep(&sc->sample_sizes);
5251 593 av_freep(&sc->keyframes);
5252 593 av_freep(&sc->stps_data);
5253 593 av_freep(&sc->elst_data);
5254 593 av_freep(&sc->rap_group);
5255 593 av_freep(&sc->sync_group);
5256 593 av_freep(&sc->sgpd_sync);
5257
5258 593 return 0;
5259 }
5260
5261 124 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5262 {
5263 int ret;
5264 124 c->itunes_metadata = 1;
5265 124 ret = mov_read_default(c, pb, atom);
5266 124 c->itunes_metadata = 0;
5267 124 return ret;
5268 }
5269
5270 11 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5271 {
5272 uint32_t count;
5273 uint32_t i;
5274
5275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
5276 return 0;
5277
5278 11 avio_skip(pb, 4);
5279 11 count = avio_rb32(pb);
5280 11 atom.size -= 8;
5281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (count >= UINT_MAX / sizeof(*c->meta_keys)) {
5282 av_log(c->fc, AV_LOG_ERROR,
5283 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5284 return AVERROR_INVALIDDATA;
5285 }
5286
5287 11 c->meta_keys_count = count + 1;
5288 11 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
5289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!c->meta_keys)
5290 return AVERROR(ENOMEM);
5291
5292
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i <= count; ++i) {
5293 58 uint32_t key_size = avio_rb32(pb);
5294 58 uint32_t type = avio_rl32(pb);
5295
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) {
5296 av_log(c->fc, AV_LOG_ERROR,
5297 "The key# %"PRIu32" in meta has invalid size:"
5298 "%"PRIu32"\n", i, key_size);
5299 return AVERROR_INVALIDDATA;
5300 }
5301 58 atom.size -= key_size;
5302 58 key_size -= 8;
5303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (type != MKTAG('m','d','t','a')) {
5304 avio_skip(pb, key_size);
5305 continue;
5306 }
5307 58 c->meta_keys[i] = av_mallocz(key_size + 1);
5308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!c->meta_keys[i])
5309 return AVERROR(ENOMEM);
5310 58 avio_read(pb, c->meta_keys[i], key_size);
5311 }
5312
5313 11 return 0;
5314 }
5315
5316 65 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5317 {
5318 65 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5319 65 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5320 int i;
5321 65 int ret = 0;
5322 AVStream *st;
5323 MOVStreamContext *sc;
5324
5325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (c->fc->nb_streams < 1)
5326 return 0;
5327 65 st = c->fc->streams[c->fc->nb_streams-1];
5328 65 sc = st->priv_data;
5329
5330
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 65 times.
260 for (i = 0; i < 3; i++) {
5331 uint8_t **p;
5332 uint32_t len, tag;
5333
5334
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 195 times.
195 if (end - avio_tell(pb) <= 12)
5335 break;
5336
5337 195 len = avio_rb32(pb);
5338 195 tag = avio_rl32(pb);
5339 195 avio_skip(pb, 4); // flags
5340
5341
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))
5342 break;
5343 195 len -= 12;
5344
5345
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 130 times.
195 if (tag == MKTAG('m', 'e', 'a', 'n'))
5346 65 p = &mean;
5347
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 65 times.
130 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5348 65 p = &key;
5349
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) {
5350 65 avio_skip(pb, 4);
5351 65 len -= 4;
5352 65 p = &val;
5353 } else
5354 break;
5355
5356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (*p)
5357 break;
5358
5359 195 *p = av_malloc(len + 1);
5360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*p) {
5361 ret = AVERROR(ENOMEM);
5362 break;
5363 }
5364 195 ret = ffio_read_size(pb, *p, len);
5365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (ret < 0) {
5366 av_freep(p);
5367 break;
5368 }
5369 195 (*p)[len] = 0;
5370 }
5371
5372
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) {
5373
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 32 times.
65 if (strcmp(key, "iTunSMPB") == 0) {
5374 int priming, remainder, samples;
5375
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
5376
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)
5377 33 sc->start_pad = priming;
5378 }
5379 }
5380
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 10 times.
120 if (strcmp(key, "cdec") != 0) {
5381 55 av_dict_set(&c->fc->metadata, key, val,
5382 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5383 55 key = val = NULL;
5384 }
5385 } else {
5386 av_log(c->fc, AV_LOG_VERBOSE,
5387 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5388 }
5389
5390 65 avio_seek(pb, end, SEEK_SET);
5391 65 av_freep(&key);
5392 65 av_freep(&val);
5393 65 av_freep(&mean);
5394 65 return ret;
5395 }
5396
5397 23 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5398 {
5399 MOVStreamContext *sc;
5400 AVStream *st;
5401
5402 23 st = avformat_new_stream(c->fc, NULL);
5403
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!st)
5404 return AVERROR(ENOMEM);
5405 23 sc = av_mallocz(sizeof(MOVStreamContext));
5406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc)
5407 return AVERROR(ENOMEM);
5408
5409 23 item->st = st;
5410 23 st->id = item->item_id;
5411 23 st->priv_data = sc;
5412 23 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5413 23 st->codecpar->codec_id = mov_codec_id(st, item->type);
5414 23 sc->id = st->id;
5415 23 sc->ffindex = st->index;
5416 23 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5417 23 st->time_base.num = st->time_base.den = 1;
5418 23 st->nb_frames = 1;
5419 23 sc->time_scale = 1;
5420 23 sc->pb = c->fc->pb;
5421 23 sc->pb_is_copied = 1;
5422 23 sc->refcount = 1;
5423
5424
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 if (item->name)
5425 23 av_dict_set(&st->metadata, "title", item->name, 0);
5426
5427 // Populate the necessary fields used by mov_build_index.
5428 23 sc->stsc_count = 1;
5429 23 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc->stsc_data)
5431 return AVERROR(ENOMEM);
5432 23 sc->stsc_data[0].first = 1;
5433 23 sc->stsc_data[0].count = 1;
5434 23 sc->stsc_data[0].id = 1;
5435 23 sc->chunk_count = 1;
5436 23 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc->chunk_offsets)
5438 return AVERROR(ENOMEM);
5439 23 sc->sample_count = 1;
5440 23 sc->sample_sizes = av_malloc_array(1, sizeof(*sc->sample_sizes));
5441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc->sample_sizes)
5442 return AVERROR(ENOMEM);
5443 23 sc->stts_count = 1;
5444 23 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!sc->stts_data)
5446 return AVERROR(ENOMEM);
5447 23 sc->stts_data[0].count = 1;
5448 // Not used for still images. But needed by mov_build_index.
5449 23 sc->stts_data[0].duration = 0;
5450
5451 23 return 0;
5452 }
5453
5454 138 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5455 {
5456
1/2
✓ Branch 0 taken 400 times.
✗ Branch 1 not taken.
400 while (atom.size > 8) {
5457 uint32_t tag;
5458
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 400 times.
400 if (avio_feof(pb))
5459 return AVERROR_EOF;
5460 400 tag = avio_rl32(pb);
5461 400 atom.size -= 4;
5462
2/2
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 262 times.
400 if (tag == MKTAG('h','d','l','r')) {
5463 138 avio_seek(pb, -8, SEEK_CUR);
5464 138 atom.size += 8;
5465 138 return mov_read_default(c, pb, atom);
5466 }
5467 }
5468 return 0;
5469 }
5470
5471 // return 1 when matrix is identity, 0 otherwise
5472 #define IS_MATRIX_IDENT(matrix) \
5473 ( (matrix)[0][0] == (1 << 16) && \
5474 (matrix)[1][1] == (1 << 16) && \
5475 (matrix)[2][2] == (1 << 30) && \
5476 !(matrix)[0][1] && !(matrix)[0][2] && \
5477 !(matrix)[1][0] && !(matrix)[1][2] && \
5478 !(matrix)[2][0] && !(matrix)[2][1])
5479
5480 593 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5481 {
5482 int i, j, e;
5483 int width;
5484 int height;
5485 int display_matrix[3][3];
5486 593 int res_display_matrix[3][3] = { { 0 } };
5487 AVStream *st;
5488 MOVStreamContext *sc;
5489 int version;
5490 int flags;
5491
5492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->fc->nb_streams < 1)
5493 return 0;
5494 593 st = c->fc->streams[c->fc->nb_streams-1];
5495 593 sc = st->priv_data;
5496
5497 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5498 // avoids corrupting AVStreams mapped to an earlier tkhd.
5499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (st->id != -1)
5500 return AVERROR_INVALIDDATA;
5501
5502 593 version = avio_r8(pb);
5503 593 flags = avio_rb24(pb);
5504 593 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5505
5506
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 584 times.
593 if (version == 1) {
5507 9 avio_rb64(pb);
5508 9 avio_rb64(pb);
5509 } else {
5510 584 avio_rb32(pb); /* creation time */
5511 584 avio_rb32(pb); /* modification time */
5512 }
5513 593 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5514 593 sc->id = st->id;
5515 593 avio_rb32(pb); /* reserved */
5516
5517 /* highlevel (considering edits) duration in movie timebase */
5518
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 584 times.
593 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5519 593 avio_rb32(pb); /* reserved */
5520 593 avio_rb32(pb); /* reserved */
5521
5522 593 avio_rb16(pb); /* layer */
5523 593 avio_rb16(pb); /* alternate group */
5524 593 avio_rb16(pb); /* volume */
5525 593 avio_rb16(pb); /* reserved */
5526
5527 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
5528 // they're kept in fixed point format through all calculations
5529 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
5530 // side data, but the scale factor is not needed to calculate aspect ratio
5531
2/2
✓ Branch 0 taken 1779 times.
✓ Branch 1 taken 593 times.
2372 for (i = 0; i < 3; i++) {
5532 1779 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
5533 1779 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
5534 1779 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
5535 }
5536
5537 593 width = avio_rb32(pb); // 16.16 fixed point track width
5538 593 height = avio_rb32(pb); // 16.16 fixed point track height
5539 593 sc->width = width >> 16;
5540 593 sc->height = height >> 16;
5541
5542 // apply the moov display matrix (after the tkhd one)
5543
2/2
✓ Branch 0 taken 1779 times.
✓ Branch 1 taken 593 times.
2372 for (i = 0; i < 3; i++) {
5544 1779 const int sh[3] = { 16, 16, 30 };
5545
2/2
✓ Branch 0 taken 5337 times.
✓ Branch 1 taken 1779 times.
7116 for (j = 0; j < 3; j++) {
5546
2/2
✓ Branch 0 taken 16011 times.
✓ Branch 1 taken 5337 times.
21348 for (e = 0; e < 3; e++) {
5547 16011 res_display_matrix[i][j] +=
5548 16011 ((int64_t) display_matrix[i][e] *
5549 16011 c->movie_display_matrix[e][j]) >> sh[e];
5550 }
5551 }
5552 }
5553
5554 // save the matrix when it is not the default identity
5555
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)) {
5556 9 av_freep(&sc->display_matrix);
5557 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
5558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
5559 return AVERROR(ENOMEM);
5560
5561
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
5562
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
5563 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
5564 }
5565
5566 // transform the display width/height according to the matrix
5567 // to keep the same scale, use [width height 1<<16]
5568
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) {
5569 double disp_transform[2];
5570
5571
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
5572 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
5573 16 sc->display_matrix[3 + i]);
5574
5575
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 &&
5576
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) &&
5577
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
5578 3 st->sample_aspect_ratio = av_d2q(
5579 3 disp_transform[0] / disp_transform[1],
5580 INT_MAX);
5581 }
5582 593 return 0;
5583 }
5584
5585 388 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5586 {
5587 388 MOVFragment *frag = &c->fragment;
5588 388 MOVTrackExt *trex = NULL;
5589 int flags, track_id, i;
5590 MOVFragmentStreamInfo * frag_stream_info;
5591
5592 388 avio_r8(pb); /* version */
5593 388 flags = avio_rb24(pb);
5594
5595 388 track_id = avio_rb32(pb);
5596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!track_id)
5597 return AVERROR_INVALIDDATA;
5598
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < c->trex_count; i++)
5599
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (c->trex_data[i].track_id == track_id) {
5600 388 trex = &c->trex_data[i];
5601 388 break;
5602 }
5603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!trex) {
5604 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
5605 return 0;
5606 }
5607 388 c->fragment.found_tfhd = 1;
5608 388 frag->track_id = track_id;
5609 388 set_frag_stream(&c->frag_index, track_id);
5610
5611 776 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
5612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
776 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
5613
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 21 times.
388 frag->moof_offset : frag->implicit_offset;
5614
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;
5615
5616 776 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
5617
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 383 times.
388 avio_rb32(pb) : trex->duration;
5618 776 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
5619
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 382 times.
388 avio_rb32(pb) : trex->size;
5620 776 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
5621
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 365 times.
388 avio_rb32(pb) : trex->flags;
5622 388 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
5623
5624 388 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5625
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5626 388 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
5627 388 frag_stream_info->stsd_id = frag->stsd_id;
5628 }
5629 388 return 0;
5630 }
5631
5632 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5633 {
5634 unsigned i, num;
5635 void *new_tracks;
5636
5637 2 num = atom.size / 4;
5638
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
5639 return AVERROR(ENOMEM);
5640
5641 2 av_free(c->chapter_tracks);
5642 2 c->chapter_tracks = new_tracks;
5643 2 c->nb_chapter_tracks = num;
5644
5645
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++)
5646 2 c->chapter_tracks[i] = avio_rb32(pb);
5647
5648 2 c->nb_chapter_tracks = i;
5649
5650 2 return 0;
5651 }
5652
5653 17 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5654 {
5655 MOVTrackExt *trex;
5656 int err;
5657
5658
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))
5659 return AVERROR_INVALIDDATA;
5660
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
5661 sizeof(*c->trex_data))) < 0) {
5662 c->trex_count = 0;
5663 return err;
5664 }
5665
5666 17 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
5667
5668 17 trex = &c->trex_data[c->trex_count++];
5669 17 avio_r8(pb); /* version */
5670 17 avio_rb24(pb); /* flags */
5671 17 trex->track_id = avio_rb32(pb);
5672 17 trex->stsd_id = avio_rb32(pb);
5673 17 trex->duration = avio_rb32(pb);
5674 17 trex->size = avio_rb32(pb);
5675 17 trex->flags = avio_rb32(pb);
5676 17 return 0;
5677 }
5678
5679 367 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5680 {
5681 367 MOVFragment *frag = &c->fragment;
5682 367 AVStream *st = NULL;
5683 MOVStreamContext *sc;
5684 int version, i;
5685 MOVFragmentStreamInfo * frag_stream_info;
5686 int64_t base_media_decode_time;
5687
5688
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 for (i = 0; i < c->fc->nb_streams; i++) {
5689 367 sc = c->fc->streams[i]->priv_data;
5690
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 if (sc->id == frag->track_id) {
5691 367 st = c->fc->streams[i];
5692 367 break;
5693 }
5694 }
5695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367 times.
367 if (!st) {
5696 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5697 return 0;
5698 }
5699 367 sc = st->priv_data;
5700
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)
5701 return 0;
5702 367 version = avio_r8(pb);
5703 367 avio_rb24(pb); /* flags */
5704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367 times.
367 if (version) {
5705 base_media_decode_time = avio_rb64(pb);
5706 } else {
5707 367 base_media_decode_time = avio_rb32(pb);
5708 }
5709
5710 367 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5711
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 if (frag_stream_info)
5712 367 frag_stream_info->tfdt_dts = base_media_decode_time;
5713 367 sc->track_end = base_media_decode_time;
5714
5715 367 return 0;
5716 }
5717
5718 388 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5719 {
5720 388 MOVFragment *frag = &c->fragment;
5721 388 AVStream *st = NULL;
5722 388 FFStream *sti = NULL;
5723 MOVStreamContext *sc;
5724 MOVTimeToSample *tts_data;
5725 uint64_t offset;
5726 388 int64_t dts, pts = AV_NOPTS_VALUE;
5727 388 int data_offset = 0;
5728 388 unsigned entries, first_sample_flags = frag->flags;
5729 int flags, distance, i;
5730 388 int64_t prev_dts = AV_NOPTS_VALUE;
5731 388 int next_frag_index = -1, index_entry_pos;
5732 size_t requested_size;
5733 size_t old_allocated_size;
5734 AVIndexEntry *new_entries;
5735 MOVFragmentStreamInfo * frag_stream_info;
5736
5737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!frag->found_tfhd) {
5738 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
5739 return AVERROR_INVALIDDATA;
5740 }
5741
5742
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < c->fc->nb_streams; i++) {
5743 394 sc = c->fc->streams[i]->priv_data;
5744
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (sc->id == frag->track_id) {
5745 388 st = c->fc->streams[i];
5746 388 sti = ffstream(st);
5747 388 break;
5748 }
5749 }
5750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!st) {
5751 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5752 return 0;
5753 }
5754 388 sc = st->priv_data;
5755
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)
5756 return 0;
5757
5758 // Find the next frag_index index that has a valid index_entry for
5759 // the current track_id.
5760 //
5761 // A valid index_entry means the trun for the fragment was read
5762 // and it's samples are in index_entries at the given position.
5763 // New index entries will be inserted before the index_entry found.
5764 388 index_entry_pos = sti->nb_index_entries;
5765
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++) {
5766 1621 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
5767
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) {
5768 next_frag_index = i;
5769 index_entry_pos = frag_stream_info->index_entry;
5770 break;
5771 }
5772 }
5773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 av_assert0(index_entry_pos <= sti->nb_index_entries);
5774
5775 388 avio_r8(pb); /* version */
5776 388 flags = avio_rb24(pb);
5777 388 entries = avio_rb32(pb);
5778 388 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
5779
5780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if ((uint64_t)entries+sc->tts_count >= UINT_MAX/sizeof(*sc->tts_data))
5781 return AVERROR_INVALIDDATA;
5782
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
5783
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);
5784
5785 388 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5786
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
5788 dts = frag_stream_info->next_trun_dts - sc->time_offset;
5789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5790 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
5791 pts = frag_stream_info->first_tfra_pts;
5792 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5793 ", using it for pts\n", pts);
5794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5795 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
5796 dts = frag_stream_info->first_tfra_pts;
5797 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5798 ", using it for dts\n", pts);
5799 } else {
5800 388 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
5801 388 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
5802
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;
5803
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;
5804
5805
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (fallback_sidx) {
5806 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
5807 }
5808
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (fallback_tfdt) {
5809 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
5810 }
5811
5812
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) {
5813 367 dts = frag_stream_info->tfdt_dts - sc->time_offset;
5814 367 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
5815 ", using it for dts\n", dts);
5816
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) {
5817 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
5818 // pts = frag_stream_info->sidx_pts;
5819 dts = frag_stream_info->sidx_pts - sc->time_offset;
5820 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
5821 ", using it for dts\n", frag_stream_info->sidx_pts);
5822 } else {
5823 21 dts = sc->track_end - sc->time_offset;
5824 21 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5825 ", using it for dts\n", dts);
5826 }
5827 }
5828 } else {
5829 dts = sc->track_end - sc->time_offset;
5830 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5831 ", using it for dts\n", dts);
5832 }
5833 388 offset = frag->base_data_offset + data_offset;
5834 388 distance = 0;
5835 388 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
5836
5837 // realloc space for new index entries
5838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
5839 entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
5840 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
5841 }
5842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (entries == 0)
5843 return 0;
5844
5845 388 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
5846 388 new_entries = av_fast_realloc(sti->index_entries,
5847 &sti->index_entries_allocated_size,
5848 requested_size);
5849
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!new_entries)
5850 return AVERROR(ENOMEM);
5851 388 sti->index_entries= new_entries;
5852
5853 388 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
5854 388 old_allocated_size = sc->tts_allocated_size;
5855 388 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
5856 requested_size);
5857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!tts_data)
5858 return AVERROR(ENOMEM);
5859 388 sc->tts_data = tts_data;
5860
5861 // In case there were samples without time to sample entries, ensure they get
5862 // zero valued entries. This ensures clips which mix boxes with and
5863 // without time to sample entries don't pickup uninitialized data.
5864 388 memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0,
5865 388 sc->tts_allocated_size - old_allocated_size);
5866
5867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (index_entry_pos < sti->nb_index_entries) {
5868 // Make hole in index_entries and tts_data for new samples
5869 memmove(sti->index_entries + index_entry_pos + entries,
5870 sti->index_entries + index_entry_pos,
5871 sizeof(*sti->index_entries) *
5872 (sti->nb_index_entries - index_entry_pos));
5873 memmove(sc->tts_data + index_entry_pos + entries,
5874 sc->tts_data + index_entry_pos,
5875 sizeof(*sc->tts_data) * (sc->tts_count - index_entry_pos));
5876 if (index_entry_pos < sc->current_sample) {
5877 sc->current_sample += entries;
5878 }
5879 }
5880
5881 388 sti->nb_index_entries += entries;
5882 388 sc->tts_count = sti->nb_index_entries;
5883 388 sc->stts_count = sti->nb_index_entries;
5884
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 28 times.
388 if (flags & MOV_TRUN_SAMPLE_CTS)
5885 360 sc->ctts_count = sti->nb_index_entries;
5886
5887 // Record the index_entry position in frag_index of this fragment
5888
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5889 388 frag_stream_info->index_entry = index_entry_pos;
5890
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info->index_base < 0)
5891 388 frag_stream_info->index_base = index_entry_pos;
5892 }
5893
5894
2/2
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 14 times.
388 if (index_entry_pos > 0)
5895 374 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
5896
5897
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++) {
5898 6066 unsigned sample_size = frag->size;
5899
2/2
✓ Branch 0 taken 5678 times.
✓ Branch 1 taken 388 times.
6066 int sample_flags = i ? frag->flags : first_sample_flags;
5900 6066 unsigned sample_duration = frag->duration;
5901 6066 unsigned ctts_duration = 0;
5902 6066 int keyframe = 0;
5903 6066 int index_entry_flags = 0;
5904
5905
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 5594 times.
6066 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
5906
2/2
✓ Branch 0 taken 6034 times.
✓ Branch 1 taken 32 times.
6066 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
5907
2/2
✓ Branch 0 taken 933 times.
✓ Branch 1 taken 5133 times.
6066 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
5908
2/2
✓ Branch 0 taken 5400 times.
✓ Branch 1 taken 666 times.
6066 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
5909
5910 6066 mov_update_dts_shift(sc, ctts_duration, c->fc);
5911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6066 times.
6066 if (pts != AV_NOPTS_VALUE) {
5912 dts = pts - sc->dts_shift;
5913 if (flags & MOV_TRUN_SAMPLE_CTS) {
5914 dts -= ctts_duration;
5915 } else {
5916 dts -= sc->time_offset;
5917 }
5918 av_log(c->fc, AV_LOG_DEBUG,
5919 "pts %"PRId64" calculated dts %"PRId64
5920 " sc->dts_shift %d ctts.duration %d"
5921 " sc->time_offset %"PRId64
5922 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
5923 pts, dts,
5924 sc->dts_shift, ctts_duration,
5925 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
5926 pts = AV_NOPTS_VALUE;
5927 }
5928
5929 6066 keyframe =
5930 6066 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
5931 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
5932
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 5666 times.
6066 if (keyframe) {
5933 400 distance = 0;
5934 400 index_entry_flags |= AVINDEX_KEYFRAME;
5935 }
5936 // Fragments can overlap in time. Discard overlapping frames after
5937 // decoding.
5938
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6042 times.
6066 if (prev_dts >= dts)
5939 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
5940
5941 6066 sti->index_entries[index_entry_pos].pos = offset;
5942 6066 sti->index_entries[index_entry_pos].timestamp = dts;
5943 6066 sti->index_entries[index_entry_pos].size = sample_size;
5944 6066 sti->index_entries[index_entry_pos].min_distance = distance;
5945 6066 sti->index_entries[index_entry_pos].flags = index_entry_flags;
5946
5947 6066 sc->tts_data[index_entry_pos].count = 1;
5948 6066 sc->tts_data[index_entry_pos].offset = ctts_duration;
5949 6066 sc->tts_data[index_entry_pos].duration = sample_duration;
5950 6066 index_entry_pos++;
5951
5952 6066 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
5953 "size %u, distance %d, keyframe %d\n", st->index,
5954 index_entry_pos, offset, dts, sample_size, distance, keyframe);
5955 6066 distance++;
5956
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6066 times.
6066 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
5957 return AVERROR_INVALIDDATA;
5958
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6066 times.
6066 if (!sample_size)
5959 return AVERROR_INVALIDDATA;
5960 6066 dts += sample_duration;
5961 6066 offset += sample_size;
5962 6066 sc->data_size += sample_size;
5963
5964
1/2
✓ Branch 0 taken 6066 times.
✗ Branch 1 not taken.
6066 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
5965
1/2
✓ Branch 0 taken 6066 times.
✗ Branch 1 not taken.
6066 1 <= INT_MAX - sc->nb_frames_for_fps
5966 ) {
5967 6066 sc->duration_for_fps += sample_duration;
5968 6066 sc->nb_frames_for_fps ++;
5969 }
5970 }
5971
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info)
5972 388 frag_stream_info->next_trun_dts = dts + sc->time_offset;
5973
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (i < entries) {
5974 // EOF found before reading all entries. Fix the hole this would
5975 // leave in index_entries and tts_data
5976 int gap = entries - i;
5977 memmove(sti->index_entries + index_entry_pos,
5978 sti->index_entries + index_entry_pos + gap,
5979 sizeof(*sti->index_entries) *
5980 (sti->nb_index_entries - (index_entry_pos + gap)));
5981 memmove(sc->tts_data + index_entry_pos,
5982 sc->tts_data + index_entry_pos + gap,
5983 sizeof(*sc->tts_data) *
5984 (sc->tts_count - (index_entry_pos + gap)));
5985
5986 sti->nb_index_entries -= gap;
5987 sc->tts_count -= gap;
5988 if (index_entry_pos < sc->current_sample) {
5989 sc->current_sample -= gap;
5990 }
5991 entries = i;
5992 }
5993
5994 // The end of this new fragment may overlap in time with the start
5995 // of the next fragment in index_entries. Mark the samples in the next
5996 // fragment that overlap with AVINDEX_DISCARD_FRAME
5997 388 prev_dts = AV_NOPTS_VALUE;
5998
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (index_entry_pos > 0)
5999 388 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
6001 if (prev_dts < sti->index_entries[i].timestamp)
6002 break;
6003 sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6004 }
6005
6006 // If a hole was created to insert the new index_entries into,
6007 // the index_entry recorded for all subsequent moof must
6008 // be incremented by the number of entries inserted.
6009 388 fix_frag_index_entries(&c->frag_index, next_frag_index,
6010 388 frag->track_id, entries);
6011
6012
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (pb->eof_reached) {
6013 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6014 return AVERROR_EOF;
6015 }
6016
6017 388 frag->implicit_offset = offset;
6018
6019 388 sc->track_end = dts + sc->time_offset;
6020
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 379 times.
388 if (st->duration < sc->track_end)
6021 9 st->duration = sc->track_end;
6022
6023 388 return 0;
6024 }
6025
6026 43 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6027 {
6028 43 int64_t stream_size = avio_size(pb);
6029 43 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6030 uint8_t version, is_complete;
6031 int64_t offadd;
6032 unsigned i, j, track_id, item_count;
6033 43 AVStream *st = NULL;
6034 43 AVStream *ref_st = NULL;
6035 43 MOVStreamContext *sc, *ref_sc = NULL;
6036 AVRational timescale;
6037
6038 43 version = avio_r8(pb);
6039
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (version > 1) {
6040 avpriv_request_sample(c->fc, "sidx version %u", version);
6041 return 0;
6042 }
6043
6044 43 avio_rb24(pb); // flags
6045
6046 43 track_id = avio_rb32(pb); // Reference ID
6047
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 for (i = 0; i < c->fc->nb_streams; i++) {
6048 43 sc = c->fc->streams[i]->priv_data;
6049
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (sc->id == track_id) {
6050 43 st = c->fc->streams[i];
6051 43 break;
6052 }
6053 }
6054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st) {
6055 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6056 return 0;
6057 }
6058
6059 43 sc = st->priv_data;
6060
6061 43 timescale = av_make_q(1, avio_rb32(pb));
6062
6063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (timescale.den <= 0) {
6064 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6065 return AVERROR_INVALIDDATA;
6066 }
6067
6068
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (version == 0) {
6069 43 pts = avio_rb32(pb);
6070 43 offadd= avio_rb32(pb);
6071 } else {
6072 pts = avio_rb64(pb);
6073 offadd= avio_rb64(pb);
6074 }
6075
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6076 return AVERROR_INVALIDDATA;
6077
6078 43 offset += (uint64_t)offadd;
6079
6080 43 avio_rb16(pb); // reserved
6081
6082 43 item_count = avio_rb16(pb);
6083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (item_count == 0)
6084 return AVERROR_INVALIDDATA;
6085
6086
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 43 times.
411 for (i = 0; i < item_count; i++) {
6087 int index;
6088 MOVFragmentStreamInfo * frag_stream_info;
6089 368 uint32_t size = avio_rb32(pb);
6090 368 uint32_t duration = avio_rb32(pb);
6091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 368 times.
368 if (size & 0x80000000) {
6092 avpriv_request_sample(c->fc, "sidx reference_type 1");
6093 return AVERROR_PATCHWELCOME;
6094 }
6095 368 avio_rb32(pb); // sap_flags
6096 368 timestamp = av_rescale_q(pts, timescale, st->time_base);
6097
6098 368 index = update_frag_index(c, offset);
6099 368 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6100
1/2
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
368 if (frag_stream_info)
6101 368 frag_stream_info->sidx_pts = timestamp;
6102
6103
1/2
✓ Branch 1 taken 368 times.
✗ Branch 2 not taken.
368 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6104
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 368 times.
368 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6105 )
6106 return AVERROR_INVALIDDATA;
6107 368 offset += size;
6108 368 pts += duration;
6109 }
6110
6111 43 st->duration = sc->track_end = pts;
6112
6113 43 sc->has_sidx = 1;
6114
6115 // See if the remaining bytes are just an mfra which we can ignore.
6116 43 is_complete = offset == stream_size;
6117
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 ) {
6118 int64_t ret;
6119 38 int64_t original_pos = avio_tell(pb);
6120
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
38 if (!c->have_read_mfra_size) {
6121
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6122 return ret;
6123 3 c->mfra_size = avio_rb32(pb);
6124 3 c->have_read_mfra_size = 1;
6125
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6126 return ret;
6127 }
6128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (offset == stream_size - c->mfra_size)
6129 is_complete = 1;
6130 }
6131
6132
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 38 times.
43 if (is_complete) {
6133 // Find first entry in fragment index that came from an sidx.
6134 // This will pretty much always be the first entry.
6135
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 5 times.
373 for (i = 0; i < c->frag_index.nb_items; i++) {
6136 368 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6137
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++) {
6138 MOVFragmentStreamInfo * si;
6139 5 si = &item->stream_info[j];
6140
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (si->sidx_pts != AV_NOPTS_VALUE) {
6141 5 ref_st = c->fc->streams[j];
6142 5 ref_sc = ref_st->priv_data;
6143 5 break;
6144 }
6145 }
6146 }
6147
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++) {
6148 5 st = c->fc->streams[i];
6149 5 sc = st->priv_data;
6150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->has_sidx) {
6151 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6152 }
6153 }
6154
6155 5 c->frag_index.complete = 1;
6156 }
6157
6158 43 return 0;
6159 }
6160
6161 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6162 /* like the files created with Adobe Premiere 5.0, for samples see */
6163 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6164 267 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6165 {
6166 int err;
6167
6168
1/2
✓ Branch 0 taken 267 times.
✗ Branch 1 not taken.
267 if (atom.size < 8)
6169 267 return 0; /* continue */
6170 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6171 avio_skip(pb, atom.size - 4);
6172 return 0;
6173 }
6174 atom.type = avio_rl32(pb);
6175 atom.size -= 8;
6176 if (atom.type != MKTAG('m','d','a','t')) {
6177 avio_skip(pb, atom.size);
6178 return 0;
6179 }
6180 err = mov_read_mdat(c, pb, atom);
6181 return err;
6182 }
6183
6184 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6185 {
6186 #if CONFIG_ZLIB
6187 FFIOContext ctx;
6188 uint8_t *cmov_data;
6189 uint8_t *moov_data; /* uncompressed data */
6190 long cmov_len, moov_len;
6191 3 int ret = -1;
6192
6193 3 avio_rb32(pb); /* dcom atom */
6194
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6195 return AVERROR_INVALIDDATA;
6196
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6197 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6198 return AVERROR_INVALIDDATA;
6199 }
6200 3 avio_rb32(pb); /* cmvd atom */
6201
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6202 return AVERROR_INVALIDDATA;
6203 3 moov_len = avio_rb32(pb); /* uncompressed size */
6204 3 cmov_len = atom.size - 6 * 4;
6205
6206 3 cmov_data = av_malloc(cmov_len);
6207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6208 return AVERROR(ENOMEM);
6209 3 moov_data = av_malloc(moov_len);
6210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6211 av_free(cmov_data);
6212 return AVERROR(ENOMEM);
6213 }
6214 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6216 goto free_and_return;
6217
6218 3 ret = AVERROR_INVALIDDATA;
6219
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)
6220 goto free_and_return;
6221 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6222 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6223 3 atom.type = MKTAG('m','o','o','v');
6224 3 atom.size = moov_len;
6225 3 ret = mov_read_default(c, &ctx.pub, atom);
6226 3 free_and_return:
6227 3 av_free(moov_data);
6228 3 av_free(cmov_data);
6229 3 return ret;
6230 #else
6231 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6232 return AVERROR(ENOSYS);
6233 #endif
6234 }
6235
6236 /* edit list atom */
6237 438 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6238 {
6239 MOVStreamContext *sc;
6240 int i, edit_count, version;
6241 int64_t elst_entry_size;
6242
6243
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)
6244 return 0;
6245 438 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6246
6247 438 version = avio_r8(pb); /* version */
6248 438 avio_rb24(pb); /* flags */
6249 438 edit_count = avio_rb32(pb); /* entries */
6250 438 atom.size -= 8;
6251
6252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 438 times.
438 elst_entry_size = version == 1 ? 20 : 12;
6253
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 437 times.
438 if (atom.size != edit_count * elst_entry_size) {
6254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6255 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6256 edit_count, atom.size + 8);
6257 return AVERROR_INVALIDDATA;
6258 } else {
6259 1 edit_count = atom.size / elst_entry_size;
6260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6261 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6262 }
6263 }
6264 }
6265
6266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 438 times.
438 if (!edit_count)
6267 return 0;
6268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 438 times.
438 if (sc->elst_data)
6269 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6270 438 av_free(sc->elst_data);
6271 438 sc->elst_count = 0;
6272 438 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 438 times.
438 if (!sc->elst_data)
6274 return AVERROR(ENOMEM);
6275
6276 438 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6277
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++) {
6278 465 MOVElst *e = &sc->elst_data[i];
6279
6280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 465 times.
465 if (version == 1) {
6281 e->duration = avio_rb64(pb);
6282 e->time = avio_rb64(pb);
6283 atom.size -= 16;
6284 } else {
6285 465 e->duration = avio_rb32(pb); /* segment duration */
6286 465 e->time = (int32_t)avio_rb32(pb); /* media time */
6287 465 atom.size -= 8;
6288 }
6289 465 e->rate = avio_rb32(pb) / 65536.0;
6290 465 atom.size -= 4;
6291 465 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6292 465 e->duration, e->time, e->rate);
6293
6294
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 &&
6295 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6296 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6297 c->fc->nb_streams-1, i, e->time);
6298 return AVERROR_INVALIDDATA;
6299 }
6300 }
6301 438 sc->elst_count = i;
6302
6303 438 return 0;
6304 }
6305
6306 18 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6307 {
6308 MOVStreamContext *sc;
6309
6310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->fc->nb_streams < 1)
6311 return AVERROR_INVALIDDATA;
6312 18 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6313 18 sc->timecode_track = avio_rb32(pb);
6314 18 return 0;
6315 }
6316
6317 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6318 {
6319 AVStream *st;
6320 int version, color_range, color_primaries, color_trc, color_space;
6321
6322 if (c->fc->nb_streams < 1)
6323 return 0;
6324 st = c->fc->streams[c->fc->nb_streams - 1];
6325
6326 if (atom.size < 5) {
6327 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6328 return AVERROR_INVALIDDATA;
6329 }
6330
6331 version = avio_r8(pb);
6332 if (version != 1) {
6333 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6334 return 0;
6335 }
6336 avio_skip(pb, 3); /* flags */
6337
6338 avio_skip(pb, 2); /* profile + level */
6339 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6340 color_primaries = avio_r8(pb);
6341 color_trc = avio_r8(pb);
6342 color_space = avio_r8(pb);
6343 if (avio_rb16(pb)) /* codecIntializationDataSize */
6344 return AVERROR_INVALIDDATA;
6345
6346 if (!av_color_primaries_name(color_primaries))
6347 color_primaries = AVCOL_PRI_UNSPECIFIED;
6348 if (!av_color_transfer_name(color_trc))
6349 color_trc = AVCOL_TRC_UNSPECIFIED;
6350 if (!av_color_space_name(color_space))
6351 color_space = AVCOL_SPC_UNSPECIFIED;
6352
6353 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6354 st->codecpar->color_primaries = color_primaries;
6355 st->codecpar->color_trc = color_trc;
6356 st->codecpar->color_space = color_space;
6357
6358 return 0;
6359 }
6360
6361 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6362 {
6363 MOVStreamContext *sc;
6364 int i, version;
6365
6366 if (c->fc->nb_streams < 1)
6367 return AVERROR_INVALIDDATA;
6368
6369 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6370
6371 if (atom.size < 5) {
6372 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6373 return AVERROR_INVALIDDATA;
6374 }
6375
6376 version = avio_r8(pb);
6377 if (version) {
6378 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6379 return 0;
6380 }
6381 if (sc->mastering) {
6382 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6383 return 0;
6384 }
6385
6386 avio_skip(pb, 3); /* flags */
6387
6388 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6389 if (!sc->mastering)
6390 return AVERROR(ENOMEM);
6391
6392 for (i = 0; i < 3; i++) {
6393 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6394 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6395 }
6396 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6397 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6398
6399 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6400 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6401
6402 sc->mastering->has_primaries = 1;
6403 sc->mastering->has_luminance = 1;
6404
6405 return 0;
6406 }
6407
6408 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6409 {
6410 MOVStreamContext *sc;
6411 const int mapping[3] = {1, 2, 0};
6412 const int chroma_den = 50000;
6413 const int luma_den = 10000;
6414 int i;
6415
6416 if (c->fc->nb_streams < 1)
6417 return AVERROR_INVALIDDATA;
6418
6419 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6420
6421 if (atom.size < 24) {
6422 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6423 return AVERROR_INVALIDDATA;
6424 }
6425
6426 if (sc->mastering) {
6427 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6428 return 0;
6429 }
6430
6431 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6432 if (!sc->mastering)
6433 return AVERROR(ENOMEM);
6434
6435 for (i = 0; i < 3; i++) {
6436 const int j = mapping[i];
6437 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6438 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6439 }
6440 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6441 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6442
6443 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6444 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6445
6446 sc->mastering->has_luminance = 1;
6447 sc->mastering->has_primaries = 1;
6448
6449 return 0;
6450 }
6451
6452 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6453 {
6454 MOVStreamContext *sc;
6455 int version;
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 < 5) {
6463 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
6464 return AVERROR_INVALIDDATA;
6465 }
6466
6467 version = avio_r8(pb);
6468 if (version) {
6469 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
6470 return 0;
6471 }
6472 avio_skip(pb, 3); /* flags */
6473
6474 if (sc->coll){
6475 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
6476 return 0;
6477 }
6478
6479 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6480 if (!sc->coll)
6481 return AVERROR(ENOMEM);
6482
6483 sc->coll->MaxCLL = avio_rb16(pb);
6484 sc->coll->MaxFALL = avio_rb16(pb);
6485
6486 return 0;
6487 }
6488
6489 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6490 {
6491 MOVStreamContext *sc;
6492
6493 if (c->fc->nb_streams < 1)
6494 return AVERROR_INVALIDDATA;
6495
6496 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6497
6498 if (atom.size < 4) {
6499 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
6500 return AVERROR_INVALIDDATA;
6501 }
6502
6503 if (sc->coll){
6504 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
6505 return 0;
6506 }
6507
6508 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6509 if (!sc->coll)
6510 return AVERROR(ENOMEM);
6511
6512 sc->coll->MaxCLL = avio_rb16(pb);
6513 sc->coll->MaxFALL = avio_rb16(pb);
6514
6515 return 0;
6516 }
6517
6518 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6519 {
6520 MOVStreamContext *sc;
6521 4 const int illuminance_den = 10000;
6522 4 const int ambient_den = 50000;
6523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
6524 return AVERROR_INVALIDDATA;
6525 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
6527 av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
6528 return AVERROR_INVALIDDATA;
6529 }
6530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
6531 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
6532 return 0;
6533 }
6534 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
6535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
6536 return AVERROR(ENOMEM);
6537 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
6538 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
6539 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
6540 4 return 0;
6541 }
6542
6543 1 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6544 {
6545 AVStream *st;
6546 MOVStreamContext *sc;
6547 enum AVStereo3DType type;
6548 int mode;
6549
6550
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6551 return 0;
6552
6553 1 st = c->fc->streams[c->fc->nb_streams - 1];
6554 1 sc = st->priv_data;
6555
6556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 5) {
6557 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
6558 return AVERROR_INVALIDDATA;
6559 }
6560
6561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sc->stereo3d)
6562 return AVERROR_INVALIDDATA;
6563
6564 1 avio_skip(pb, 4); /* version + flags */
6565
6566 1 mode = avio_r8(pb);
6567
1/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 switch (mode) {
6568 1 case 0:
6569 1 type = AV_STEREO3D_2D;
6570 1 break;
6571 case 1:
6572 type = AV_STEREO3D_TOPBOTTOM;
6573 break;
6574 case 2:
6575 type = AV_STEREO3D_SIDEBYSIDE;
6576 break;
6577 default:
6578 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
6579 return 0;
6580 }
6581
6582 1 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6583
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->stereo3d)
6584 return AVERROR(ENOMEM);
6585
6586 1 sc->stereo3d->type = type;
6587 1 return 0;
6588 }
6589
6590 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6591 {
6592 AVStream *st;
6593 MOVStreamContext *sc;
6594 int size, version, layout;
6595 int32_t yaw, pitch, roll;
6596 1 uint32_t l = 0, t = 0, r = 0, b = 0;
6597 1 uint32_t tag, padding = 0;
6598 enum AVSphericalProjection projection;
6599
6600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6601 return 0;
6602
6603 1 st = c->fc->streams[c->fc->nb_streams - 1];
6604 1 sc = st->priv_data;
6605
6606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
6607 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
6608 return AVERROR_INVALIDDATA;
6609 }
6610
6611 1 size = avio_rb32(pb);
6612
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)
6613 return AVERROR_INVALIDDATA;
6614
6615 1 tag = avio_rl32(pb);
6616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
6617 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
6618 return 0;
6619 }
6620 1 version = avio_r8(pb);
6621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6622 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6623 version);
6624 return 0;
6625 }
6626 1 avio_skip(pb, 3); /* flags */
6627 1 avio_skip(pb, size - 12); /* metadata_source */
6628
6629 1 size = avio_rb32(pb);
6630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6631 return AVERROR_INVALIDDATA;
6632
6633 1 tag = avio_rl32(pb);
6634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
6635 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
6636 return 0;
6637 }
6638
6639 1 size = avio_rb32(pb);
6640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6641 return AVERROR_INVALIDDATA;
6642
6643 1 tag = avio_rl32(pb);
6644
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
6645 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
6646 return 0;
6647 }
6648 1 version = avio_r8(pb);
6649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6650 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6651 version);
6652 return 0;
6653 }
6654 1 avio_skip(pb, 3); /* flags */
6655
6656 /* 16.16 fixed point */
6657 1 yaw = avio_rb32(pb);
6658 1 pitch = avio_rb32(pb);
6659 1 roll = avio_rb32(pb);
6660
6661 1 size = avio_rb32(pb);
6662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6663 return AVERROR_INVALIDDATA;
6664
6665 1 tag = avio_rl32(pb);
6666 1 version = avio_r8(pb);
6667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6668 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6669 version);
6670 return 0;
6671 }
6672 1 avio_skip(pb, 3); /* flags */
6673
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
6674 case MKTAG('c','b','m','p'):
6675 layout = avio_rb32(pb);
6676 if (layout) {
6677 av_log(c->fc, AV_LOG_WARNING,
6678 "Unsupported cubemap layout %d\n", layout);
6679 return 0;
6680 }
6681 projection = AV_SPHERICAL_CUBEMAP;
6682 padding = avio_rb32(pb);
6683 break;
6684 1 case MKTAG('e','q','u','i'):
6685 1 t = avio_rb32(pb);
6686 1 b = avio_rb32(pb);
6687 1 l = avio_rb32(pb);
6688 1 r = avio_rb32(pb);
6689
6690
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) {
6691 av_log(c->fc, AV_LOG_ERROR,
6692 "Invalid bounding rectangle coordinates "
6693 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
6694 return AVERROR_INVALIDDATA;
6695 }
6696
6697
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)
6698 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
6699 else
6700 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6701 1 break;
6702 default:
6703 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
6704 return 0;
6705 }
6706
6707 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6708
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
6709 return AVERROR(ENOMEM);
6710
6711 1 sc->spherical->projection = projection;
6712
6713 1 sc->spherical->yaw = yaw;
6714 1 sc->spherical->pitch = pitch;
6715 1 sc->spherical->roll = roll;
6716
6717 1 sc->spherical->padding = padding;
6718
6719 1 sc->spherical->bound_left = l;
6720 1 sc->spherical->bound_top = t;
6721 1 sc->spherical->bound_right = r;
6722 1 sc->spherical->bound_bottom = b;
6723
6724 1 return 0;
6725 }
6726
6727 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6728 {
6729 AVStream *st;
6730 MOVStreamContext *sc;
6731 int size;
6732 uint32_t tag;
6733 enum AVSphericalProjection projection;
6734
6735
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6736 return 0;
6737
6738 3 st = c->fc->streams[c->fc->nb_streams - 1];
6739 3 sc = st->priv_data;
6740
6741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 16) {
6742 av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
6743 return AVERROR_INVALIDDATA;
6744 }
6745
6746 3 size = avio_rb32(pb);
6747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 16) {
6748 av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
6749 return AVERROR_INVALIDDATA;
6750 }
6751
6752 3 tag = avio_rl32(pb);
6753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
6754 av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: 0x%08X\n", tag);
6755 return AVERROR_INVALIDDATA;
6756 }
6757
6758 3 avio_skip(pb, 1); // version
6759 3 avio_skip(pb, 3); // flags
6760
6761 3 tag = avio_rl32(pb);
6762
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) {
6763 3 case MKTAG('r','e','c','t'):
6764 3 projection = AV_SPHERICAL_RECTILINEAR;
6765 3 break;
6766 case MKTAG('e','q','u','i'):
6767 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6768 break;
6769 case MKTAG('h','e','q','u'):
6770 projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
6771 break;
6772 case MKTAG('f','i','s','h'):
6773 projection = AV_SPHERICAL_FISHEYE;
6774 break;
6775 default:
6776 av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: 0x%08X\n", tag);
6777 return AVERROR_INVALIDDATA;
6778 }
6779
6780 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
6782 return AVERROR(ENOMEM);
6783
6784 3 sc->spherical->projection = projection;
6785
6786 3 return 0;
6787 }
6788
6789 3 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6790 {
6791 AVStream *st;
6792 MOVStreamContext *sc;
6793 3 int size, flags = 0;
6794 int64_t remaining;
6795 3 uint32_t tag, baseline = 0;
6796 3 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
6797 3 enum AVStereo3DType type = AV_STEREO3D_2D;
6798 3 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
6799 3 AVRational horizontal_disparity_adjustment = { 0, 1 };
6800
6801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6802 return 0;
6803
6804 3 st = c->fc->streams[c->fc->nb_streams - 1];
6805 3 sc = st->priv_data;
6806
6807 3 remaining = atom.size;
6808
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 while (remaining > 0) {
6809 9 size = avio_rb32(pb);
6810
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 ) {
6811 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
6812 return AVERROR_INVALIDDATA;
6813 }
6814
6815 9 tag = avio_rl32(pb);
6816
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) {
6817 3 case MKTAG('s','t','r','i'): {
6818 int has_right, has_left;
6819 uint8_t tmp;
6820
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 13) {
6821 av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
6822 return AVERROR_INVALIDDATA;
6823 }
6824 3 avio_skip(pb, 1); // version
6825 3 avio_skip(pb, 3); // flags
6826
6827 3 tmp = avio_r8(pb);
6828
6829 // eye_views_reversed
6830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tmp & 8) {
6831 flags |= AV_STEREO3D_FLAG_INVERT;
6832 }
6833 // has_additional_views
6834 3 if (tmp & 4) {
6835 // skip...
6836 }
6837
6838 3 has_right = tmp & 2; // has_right_eye_view
6839 3 has_left = tmp & 1; // has_left_eye_view
6840
6841
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)
6842 3 view = AV_STEREO3D_VIEW_PACKED;
6843 else if (has_left)
6844 view = AV_STEREO3D_VIEW_LEFT;
6845 else if (has_right)
6846 view = AV_STEREO3D_VIEW_RIGHT;
6847
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)
6848 3 type = AV_STEREO3D_UNSPEC;
6849
6850 3 break;
6851 }
6852 case MKTAG('h','e','r','o'): {
6853 int tmp;
6854 if (size != 13) {
6855 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
6856 return AVERROR_INVALIDDATA;
6857 }
6858 avio_skip(pb, 1); // version
6859 avio_skip(pb, 3); // flags
6860
6861 tmp = avio_r8(pb);
6862 if (tmp == 0)
6863 primary_eye = AV_PRIMARY_EYE_NONE;
6864 else if (tmp == 1)
6865 primary_eye = AV_PRIMARY_EYE_LEFT;
6866 else if (tmp == 2)
6867 primary_eye = AV_PRIMARY_EYE_RIGHT;
6868 else
6869 av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
6870
6871 break;
6872 }
6873 3 case MKTAG('c','a','m','s'): {
6874 uint32_t subtag;
6875 int subsize;
6876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
6877 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
6878 return AVERROR_INVALIDDATA;
6879 }
6880
6881 3 subsize = avio_rb32(pb);
6882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
6883 av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
6884 return AVERROR_INVALIDDATA;
6885 }
6886
6887 3 subtag = avio_rl32(pb);
6888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
6889 av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got 0x%08X\n", subtag);
6890 return AVERROR_INVALIDDATA;
6891 }
6892
6893 3 avio_skip(pb, 1); // version
6894 3 avio_skip(pb, 3); // flags
6895
6896 3 baseline = avio_rb32(pb);
6897
6898 3 break;
6899 }
6900 3 case MKTAG('c','m','f','y'): {
6901 uint32_t subtag;
6902 int subsize;
6903 int32_t adjustment;
6904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
6905 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
6906 return AVERROR_INVALIDDATA;
6907 }
6908
6909 3 subsize = avio_rb32(pb);
6910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
6911 av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
6912 return AVERROR_INVALIDDATA;
6913 }
6914
6915 3 subtag = avio_rl32(pb);
6916
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
6917 av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got 0x%08X\n", subtag);
6918 return AVERROR_INVALIDDATA;
6919 }
6920
6921 3 avio_skip(pb, 1); // version
6922 3 avio_skip(pb, 3); // flags
6923
6924 3 adjustment = (int32_t) avio_rb32(pb);
6925
6926 3 horizontal_disparity_adjustment.num = (int) adjustment;
6927 3 horizontal_disparity_adjustment.den = 10000;
6928
6929 3 break;
6930 }
6931 default:
6932 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: 0x%08X\n", tag);
6933 avio_skip(pb, size - 8);
6934 break;
6935 }
6936 9 remaining -= size;
6937 }
6938
6939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
6940 av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
6941 return AVERROR_INVALIDDATA;
6942 }
6943
6944
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (type == AV_STEREO3D_2D)
6945 return 0;
6946
6947
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->stereo3d) {
6948 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
6950 return AVERROR(ENOMEM);
6951 }
6952
6953 3 sc->stereo3d->flags = flags;
6954 3 sc->stereo3d->type = type;
6955 3 sc->stereo3d->view = view;
6956 3 sc->stereo3d->primary_eye = primary_eye;
6957 3 sc->stereo3d->baseline = baseline;
6958 3 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
6959
6960 3 return 0;
6961 }
6962
6963 3 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6964 {
6965 int size;
6966 int64_t remaining;
6967 uint32_t tag;
6968
6969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6970 return 0;
6971
6972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8) {
6973 av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
6974 return AVERROR_INVALIDDATA;
6975 }
6976
6977 3 remaining = atom.size;
6978
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 while (remaining > 0) {
6979 6 size = avio_rb32(pb);
6980
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 ) {
6981 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
6982 return AVERROR_INVALIDDATA;
6983 }
6984
6985 6 tag = avio_rl32(pb);
6986
2/3
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 switch (tag) {
6987 3 case MKTAG('p','r','o','j'): {
6988 3 MOVAtom proj = { tag, size - 8 };
6989 3 int ret = mov_read_vexu_proj(c, pb, proj);
6990
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6991 return ret;
6992 3 break;
6993 }
6994 3 case MKTAG('e','y','e','s'): {
6995 3 MOVAtom eyes = { tag, size - 8 };
6996 3 int ret = mov_read_eyes(c, pb, eyes);
6997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6998 return ret;
6999 3 break;
7000 }
7001 default:
7002 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: 0x%08X\n", tag);
7003 avio_skip(pb, size - 8);
7004 break;
7005 }
7006 6 remaining -= size;
7007 }
7008
7009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7010 av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7011 return AVERROR_INVALIDDATA;
7012 }
7013
7014 3 return 0;
7015 }
7016
7017 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7018 {
7019 AVStream *st;
7020 MOVStreamContext *sc;
7021
7022
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7023 return 0;
7024
7025 3 st = c->fc->streams[c->fc->nb_streams - 1];
7026 3 sc = st->priv_data;
7027
7028
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7029 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7030 return AVERROR_INVALIDDATA;
7031 }
7032
7033
7034
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7035 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7036 if (!sc->stereo3d)
7037 return AVERROR(ENOMEM);
7038 }
7039
7040 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7041 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7042
7043 3 return 0;
7044 }
7045
7046 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7047 {
7048 int ret = 0;
7049 uint8_t *buffer = av_malloc(len + 1);
7050 const char *val;
7051
7052 if (!buffer)
7053 return AVERROR(ENOMEM);
7054 buffer[len] = '\0';
7055
7056 ret = ffio_read_size(pb, buffer, len);
7057 if (ret < 0)
7058 goto out;
7059
7060 /* Check for mandatory keys and values, try to support XML as best-effort */
7061 if (!sc->spherical &&
7062 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7063 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7064 av_stristr(val, "true") &&
7065 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7066 av_stristr(val, "true") &&
7067 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7068 av_stristr(val, "equirectangular")) {
7069 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7070 if (!sc->spherical)
7071 goto out;
7072
7073 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7074
7075 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7076 enum AVStereo3DType mode;
7077
7078 if (av_stristr(buffer, "left-right"))
7079 mode = AV_STEREO3D_SIDEBYSIDE;
7080 else if (av_stristr(buffer, "top-bottom"))
7081 mode = AV_STEREO3D_TOPBOTTOM;
7082 else
7083 mode = AV_STEREO3D_2D;
7084
7085 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7086 if (!sc->stereo3d)
7087 goto out;
7088
7089 sc->stereo3d->type = mode;
7090 }
7091
7092 /* orientation */
7093 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7094 if (val)
7095 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7096 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7097 if (val)
7098 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7099 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7100 if (val)
7101 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7102 }
7103
7104 out:
7105 av_free(buffer);
7106 return ret;
7107 }
7108
7109 15 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7110 {
7111 AVStream *st;
7112 MOVStreamContext *sc;
7113 int64_t ret;
7114 AVUUID uuid;
7115 static const AVUUID uuid_isml_manifest = {
7116 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7117 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7118 };
7119 static const AVUUID uuid_xmp = {
7120 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7121 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7122 };
7123 static const AVUUID uuid_spherical = {
7124 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7125 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7126 };
7127
7128
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))
7129 return AVERROR_INVALIDDATA;
7130
7131
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 14 times.
15 if (c->fc->nb_streams < 1)
7132 1 return 0;
7133 14 st = c->fc->streams[c->fc->nb_streams - 1];
7134 14 sc = st->priv_data;
7135
7136 14 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0)
7138 return ret;
7139
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7140 uint8_t *buffer, *ptr;
7141 char *endptr;
7142 size_t len = atom.size - AV_UUID_LEN;
7143
7144 if (len < 4) {
7145 return AVERROR_INVALIDDATA;
7146 }
7147 ret = avio_skip(pb, 4); // zeroes
7148 len -= 4;
7149
7150 buffer = av_mallocz(len + 1);
7151 if (!buffer) {
7152 return AVERROR(ENOMEM);
7153 }
7154 ret = ffio_read_size(pb, buffer, len);
7155 if (ret < 0) {
7156 av_free(buffer);
7157 return ret;
7158 }
7159
7160 ptr = buffer;
7161 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7162 ptr += sizeof("systemBitrate=\"") - 1;
7163 c->bitrates_count++;
7164 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7165 if (!c->bitrates) {
7166 c->bitrates_count = 0;
7167 av_free(buffer);
7168 return AVERROR(ENOMEM);
7169 }
7170 errno = 0;
7171 ret = strtol(ptr, &endptr, 10);
7172 if (ret < 0 || errno || *endptr != '"') {
7173 c->bitrates[c->bitrates_count - 1] = 0;
7174 } else {
7175 c->bitrates[c->bitrates_count - 1] = ret;
7176 }
7177 }
7178
7179 av_free(buffer);
7180
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7181 uint8_t *buffer;
7182 size_t len = atom.size - AV_UUID_LEN;
7183 if (c->export_xmp) {
7184 buffer = av_mallocz(len + 1);
7185 if (!buffer) {
7186 return AVERROR(ENOMEM);
7187 }
7188 ret = ffio_read_size(pb, buffer, len);
7189 if (ret < 0) {
7190 av_free(buffer);
7191 return ret;
7192 }
7193 buffer[len] = '\0';
7194 av_dict_set(&c->fc->metadata, "xmp",
7195 buffer, AV_DICT_DONT_STRDUP_VAL);
7196 } else {
7197 // skip all uuid atom, which makes it fast for long uuid-xmp file
7198 ret = avio_skip(pb, len);
7199 if (ret < 0)
7200 return ret;
7201 }
7202
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7203 size_t len = atom.size - AV_UUID_LEN;
7204 ret = mov_parse_uuid_spherical(sc, pb, len);
7205 if (ret < 0)
7206 return ret;
7207 if (!sc->spherical)
7208 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7209 }
7210
7211 14 return 0;
7212 }
7213
7214 187 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7215 {
7216 int ret;
7217 uint8_t content[16];
7218
7219
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 96 times.
187 if (atom.size < 8)
7220 91 return 0;
7221
7222 96 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (ret < 0)
7224 return ret;
7225
7226
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 55 times.
96 if ( !c->found_moov
7227
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 23 times.
41 && !c->found_mdat
7228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 && !memcmp(content, "Anevia\x1A\x1A", 8)
7229 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7230 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7231 }
7232
7233 96 return 0;
7234 }
7235
7236 35 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7237 {
7238 35 uint32_t format = avio_rl32(pb);
7239 MOVStreamContext *sc;
7240 enum AVCodecID id;
7241 AVStream *st;
7242
7243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (c->fc->nb_streams < 1)
7244 return 0;
7245 35 st = c->fc->streams[c->fc->nb_streams - 1];
7246 35 sc = st->priv_data;
7247
7248
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 32 times.
35 switch (sc->format)
7249 {
7250 3 case MKTAG('e','n','c','v'): // encrypted video
7251 case MKTAG('e','n','c','a'): // encrypted audio
7252 3 id = mov_codec_id(st, format);
7253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7254 st->codecpar->codec_id != id) {
7255 av_log(c->fc, AV_LOG_WARNING,
7256 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7257 (char*)&format, st->codecpar->codec_id);
7258 break;
7259 }
7260
7261 3 st->codecpar->codec_id = id;
7262 3 sc->format = format;
7263 3 break;
7264
7265 32 default:
7266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (format != sc->format) {
7267 av_log(c->fc, AV_LOG_WARNING,
7268 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7269 (char*)&format, (char*)&sc->format);
7270 }
7271 32 break;
7272 }
7273
7274 35 return 0;
7275 }
7276
7277 /**
7278 * Gets the current encryption info and associated current stream context. If
7279 * we are parsing a track fragment, this will return the specific encryption
7280 * info for this fragment; otherwise this will return the global encryption
7281 * info for the current stream.
7282 */
7283 6 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7284 {
7285 MOVFragmentStreamInfo *frag_stream_info;
7286 AVStream *st;
7287 int i;
7288
7289 6 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7290
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (frag_stream_info) {
7291
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 for (i = 0; i < c->fc->nb_streams; i++) {
7292 3 *sc = c->fc->streams[i]->priv_data;
7293
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if ((*sc)->id == frag_stream_info->id) {
7294 3 st = c->fc->streams[i];
7295 3 break;
7296 }
7297 }
7298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (i == c->fc->nb_streams)
7299 return 0;
7300 3 *sc = st->priv_data;
7301
7302
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!frag_stream_info->encryption_index) {
7303 // If this stream isn't encrypted, don't create the index.
7304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!(*sc)->cenc.default_encrypted_sample)
7305 return 0;
7306 1 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!frag_stream_info->encryption_index)
7308 return AVERROR(ENOMEM);
7309 }
7310 3 *encryption_index = frag_stream_info->encryption_index;
7311 3 return 1;
7312 } else {
7313 // No current track fragment, using stream level encryption info.
7314
7315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7316 return 0;
7317 3 st = c->fc->streams[c->fc->nb_streams - 1];
7318 3 *sc = st->priv_data;
7319
7320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!(*sc)->cenc.encryption_index) {
7321 // If this stream isn't encrypted, don't create the index.
7322 if (!(*sc)->cenc.default_encrypted_sample)
7323 return 0;
7324 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7325 if (!(*sc)->cenc.encryption_index)
7326 return AVERROR(ENOMEM);
7327 }
7328
7329 3 *encryption_index = (*sc)->cenc.encryption_index;
7330 3 return 1;
7331 }
7332 }
7333
7334 72 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7335 {
7336 int i, ret;
7337 unsigned int subsample_count;
7338 AVSubsampleEncryptionInfo *subsamples;
7339
7340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!sc->cenc.default_encrypted_sample) {
7341 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7342 return AVERROR_INVALIDDATA;
7343 }
7344
7345
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) {
7346 72 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!*sample)
7348 return AVERROR(ENOMEM);
7349 } else
7350 *sample = NULL;
7351
7352
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (sc->cenc.per_sample_iv_size != 0) {
7353
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) {
7354 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
7355 av_encryption_info_free(*sample);
7356 *sample = NULL;
7357 return ret;
7358 }
7359 }
7360
7361
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (use_subsamples) {
7362 72 subsample_count = avio_rb16(pb);
7363 72 av_free((*sample)->subsamples);
7364 72 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
7365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!(*sample)->subsamples) {
7366 av_encryption_info_free(*sample);
7367 *sample = NULL;
7368 return AVERROR(ENOMEM);
7369 }
7370
7371
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++) {
7372 72 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
7373 72 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
7374 }
7375
7376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (pb->eof_reached) {
7377 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
7378 av_encryption_info_free(*sample);
7379 *sample = NULL;
7380 return AVERROR_INVALIDDATA;
7381 }
7382 72 (*sample)->subsample_count = subsample_count;
7383 }
7384
7385 72 return 0;
7386 }
7387
7388 2 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7389 {
7390 AVEncryptionInfo **encrypted_samples;
7391 MOVEncryptionIndex *encryption_index;
7392 MOVStreamContext *sc;
7393 int use_subsamples, ret;
7394 2 unsigned int sample_count, i, alloc_size = 0;
7395
7396 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7398 return ret;
7399
7400
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7401 // This can happen if we have both saio/saiz and senc atoms.
7402 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
7403 1 return 0;
7404 }
7405
7406 1 avio_r8(pb); /* version */
7407 1 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
7408
7409 1 sample_count = avio_rb32(pb);
7410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7411 return AVERROR(ENOMEM);
7412
7413
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1 times.
49 for (i = 0; i < sample_count; i++) {
7414 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7415 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7416 min_samples * sizeof(*encrypted_samples));
7417
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (encrypted_samples) {
7418 48 encryption_index->encrypted_samples = encrypted_samples;
7419
7420 48 ret = mov_read_sample_encryption_info(
7421 48 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
7422 } else {
7423 ret = AVERROR(ENOMEM);
7424 }
7425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (pb->eof_reached) {
7426 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
7427 if (ret >= 0)
7428 av_encryption_info_free(encryption_index->encrypted_samples[i]);
7429 ret = AVERROR_INVALIDDATA;
7430 }
7431
7432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0) {
7433 for (; i > 0; i--)
7434 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7435 av_freep(&encryption_index->encrypted_samples);
7436 return ret;
7437 }
7438 }
7439 1 encryption_index->nb_encrypted_samples = sample_count;
7440
7441 1 return 0;
7442 }
7443
7444 1 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
7445 {
7446 AVEncryptionInfo **sample, **encrypted_samples;
7447 int64_t prev_pos;
7448 size_t sample_count, sample_info_size, i;
7449 1 int ret = 0;
7450 1 unsigned int alloc_size = 0;
7451
7452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->nb_encrypted_samples)
7453 return 0;
7454 1 sample_count = encryption_index->auxiliary_info_sample_count;
7455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count != 1) {
7456 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
7457 return AVERROR_PATCHWELCOME;
7458 }
7459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7460 return AVERROR(ENOMEM);
7461
7462 1 prev_pos = avio_tell(pb);
7463
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
7464
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]) {
7465 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
7466 goto finish;
7467 }
7468
7469
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++) {
7470 24 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7471 24 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7472 min_samples * sizeof(*encrypted_samples));
7473
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!encrypted_samples) {
7474 ret = AVERROR(ENOMEM);
7475 goto finish;
7476 }
7477 24 encryption_index->encrypted_samples = encrypted_samples;
7478
7479 24 sample = &encryption_index->encrypted_samples[i];
7480 48 sample_info_size = encryption_index->auxiliary_info_default_size
7481 24 ? encryption_index->auxiliary_info_default_size
7482
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 : encryption_index->auxiliary_info_sizes[i];
7483
7484 24 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
7485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (ret < 0)
7486 goto finish;
7487 }
7488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7489 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
7490 ret = AVERROR_INVALIDDATA;
7491 } else {
7492 1 encryption_index->nb_encrypted_samples = sample_count;
7493 }
7494
7495 1 finish:
7496 1 avio_seek(pb, prev_pos, SEEK_SET);
7497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
7498 for (; i > 0; i--) {
7499 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7500 }
7501 av_freep(&encryption_index->encrypted_samples);
7502 }
7503 1 return ret;
7504 }
7505
7506 2 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7507 {
7508 MOVEncryptionIndex *encryption_index;
7509 MOVStreamContext *sc;
7510 int ret;
7511 unsigned int sample_count, aux_info_type, aux_info_param;
7512
7513 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7515 return ret;
7516
7517
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7518 // This can happen if we have both saio/saiz and senc atoms.
7519 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
7520 1 return 0;
7521 }
7522
7523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_sample_count) {
7524 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
7525 return AVERROR_INVALIDDATA;
7526 }
7527
7528 1 avio_r8(pb); /* version */
7529
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7530 aux_info_type = avio_rb32(pb);
7531 aux_info_param = avio_rb32(pb);
7532 if (sc->cenc.default_encrypted_sample) {
7533 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7534 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
7535 return 0;
7536 }
7537 if (aux_info_param != 0) {
7538 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
7539 return 0;
7540 }
7541 } else {
7542 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7543 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7544 aux_info_type == MKBETAG('c','e','n','s') ||
7545 aux_info_type == MKBETAG('c','b','c','1') ||
7546 aux_info_type == MKBETAG('c','b','c','s')) &&
7547 aux_info_param == 0) {
7548 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
7549 return AVERROR_INVALIDDATA;
7550 } else {
7551 return 0;
7552 }
7553 }
7554
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7555 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7556 return 0;
7557 }
7558
7559 1 encryption_index->auxiliary_info_default_size = avio_r8(pb);
7560 1 sample_count = avio_rb32(pb);
7561
7562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_default_size == 0) {
7563 if (sample_count == 0)
7564 return AVERROR_INVALIDDATA;
7565
7566 encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
7567 if (!encryption_index->auxiliary_info_sizes)
7568 return AVERROR(ENOMEM);
7569
7570 ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
7571 if (ret != sample_count) {
7572 av_freep(&encryption_index->auxiliary_info_sizes);
7573
7574 if (ret >= 0)
7575 ret = AVERROR_INVALIDDATA;
7576 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
7577 av_err2str(ret));
7578 return ret;
7579 }
7580 }
7581 1 encryption_index->auxiliary_info_sample_count = sample_count;
7582
7583
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7584 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7585 }
7586
7587 1 return 0;
7588 }
7589
7590 2 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7591 {
7592 uint64_t *auxiliary_offsets;
7593 MOVEncryptionIndex *encryption_index;
7594 MOVStreamContext *sc;
7595 int i, ret;
7596 unsigned int version, entry_count, aux_info_type, aux_info_param;
7597 2 unsigned int alloc_size = 0;
7598
7599 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7601 return ret;
7602
7603
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7604 // This can happen if we have both saio/saiz and senc atoms.
7605 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
7606 1 return 0;
7607 }
7608
7609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7610 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
7611 return AVERROR_INVALIDDATA;
7612 }
7613
7614 1 version = avio_r8(pb); /* version */
7615
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7616 aux_info_type = avio_rb32(pb);
7617 aux_info_param = avio_rb32(pb);
7618 if (sc->cenc.default_encrypted_sample) {
7619 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7620 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
7621 return 0;
7622 }
7623 if (aux_info_param != 0) {
7624 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
7625 return 0;
7626 }
7627 } else {
7628 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7629 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7630 aux_info_type == MKBETAG('c','e','n','s') ||
7631 aux_info_type == MKBETAG('c','b','c','1') ||
7632 aux_info_type == MKBETAG('c','b','c','s')) &&
7633 aux_info_param == 0) {
7634 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
7635 return AVERROR_INVALIDDATA;
7636 } else {
7637 return 0;
7638 }
7639 }
7640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7641 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7642 return 0;
7643 }
7644
7645 1 entry_count = avio_rb32(pb);
7646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
7647 return AVERROR(ENOMEM);
7648
7649
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++) {
7650
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);
7651 1 auxiliary_offsets = av_fast_realloc(
7652 1 encryption_index->auxiliary_offsets, &alloc_size,
7653 min_offsets * sizeof(*auxiliary_offsets));
7654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!auxiliary_offsets) {
7655 av_freep(&encryption_index->auxiliary_offsets);
7656 return AVERROR(ENOMEM);
7657 }
7658 1 encryption_index->auxiliary_offsets = auxiliary_offsets;
7659
7660
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (version == 0) {
7661 1 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
7662 } else {
7663 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
7664 }
7665
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (c->frag_index.current >= 0) {
7666 1 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
7667 }
7668 }
7669
7670
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7671 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
7672 av_freep(&encryption_index->auxiliary_offsets);
7673 return AVERROR_INVALIDDATA;
7674 }
7675
7676 1 encryption_index->auxiliary_offsets_count = entry_count;
7677
7678
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (encryption_index->auxiliary_info_sample_count) {
7679 1 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7680 }
7681
7682 return 0;
7683 }
7684
7685 2 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7686 {
7687 AVEncryptionInitInfo *info, *old_init_info;
7688 uint8_t **key_ids;
7689 AVStream *st;
7690 const AVPacketSideData *old_side_data;
7691 uint8_t *side_data, *extra_data;
7692 size_t side_data_size;
7693 2 int ret = 0;
7694 2 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
7695
7696
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
7697 return 0;
7698 2 st = c->fc->streams[c->fc->nb_streams-1];
7699
7700 2 version = avio_r8(pb); /* version */
7701 2 avio_rb24(pb); /* flags */
7702
7703 2 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
7704 /* key_id_size */ 16, /* data_size */ 0);
7705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info)
7706 return AVERROR(ENOMEM);
7707
7708
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
7709 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
7710 goto finish;
7711 }
7712
7713
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version > 0) {
7714 2 kid_count = avio_rb32(pb);
7715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
7716 ret = AVERROR(ENOMEM);
7717 goto finish;
7718 }
7719
7720
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++) {
7721 2 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
7722 2 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
7723 min_kid_count * sizeof(*key_ids));
7724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!key_ids) {
7725 ret = AVERROR(ENOMEM);
7726 goto finish;
7727 }
7728 2 info->key_ids = key_ids;
7729
7730 2 info->key_ids[i] = av_mallocz(16);
7731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info->key_ids[i]) {
7732 ret = AVERROR(ENOMEM);
7733 goto finish;
7734 }
7735 2 info->num_key_ids = i + 1;
7736
7737
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
7738 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
7739 goto finish;
7740 }
7741 }
7742
7743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
7744 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
7745 ret = AVERROR_INVALIDDATA;
7746 goto finish;
7747 }
7748 }
7749
7750 2 extra_data_size = avio_rb32(pb);
7751 2 extra_data = av_malloc(extra_data_size);
7752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!extra_data) {
7753 ret = AVERROR(ENOMEM);
7754 goto finish;
7755 }
7756 2 ret = avio_read(pb, extra_data, extra_data_size);
7757
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != extra_data_size) {
7758 av_free(extra_data);
7759
7760 if (ret >= 0)
7761 ret = AVERROR_INVALIDDATA;
7762 goto finish;
7763 }
7764
7765 2 av_freep(&info->data); // malloc(0) may still allocate something.
7766 2 info->data = extra_data;
7767 2 info->data_size = extra_data_size;
7768
7769 // If there is existing initialization data, append to the list.
7770 2 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
7771 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
7772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (old_side_data) {
7773 old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
7774 if (old_init_info) {
7775 // Append to the end of the list.
7776 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
7777 if (!cur->next) {
7778 cur->next = info;
7779 break;
7780 }
7781 }
7782 info = old_init_info;
7783 } else {
7784 // Assume existing side-data will be valid, so the only error we could get is OOM.
7785 ret = AVERROR(ENOMEM);
7786 goto finish;
7787 }
7788 }
7789
7790 2 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
7791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!side_data) {
7792 ret = AVERROR(ENOMEM);
7793 goto finish;
7794 }
7795
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
7796 2 &st->codecpar->nb_coded_side_data,
7797 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
7798 side_data, side_data_size, 0))
7799 av_free(side_data);
7800
7801 2 finish:
7802 2 av_encryption_init_info_free(info);
7803 2 return ret;
7804 }
7805
7806 3 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7807 {
7808 AVStream *st;
7809 MOVStreamContext *sc;
7810
7811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7812 return 0;
7813 3 st = c->fc->streams[c->fc->nb_streams-1];
7814 3 sc = st->priv_data;
7815
7816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7817 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
7818 return AVERROR_PATCHWELCOME;
7819 }
7820
7821
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8)
7822 return AVERROR_INVALIDDATA;
7823
7824 3 avio_rb32(pb); /* version and flags */
7825
7826
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->cenc.default_encrypted_sample) {
7827 3 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7829 return AVERROR(ENOMEM);
7830 }
7831 }
7832
7833 3 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
7834 3 return 0;
7835 }
7836
7837 3 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7838 {
7839 AVStream *st;
7840 MOVStreamContext *sc;
7841 unsigned int version, pattern, is_protected, iv_size;
7842
7843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7844 return 0;
7845 3 st = c->fc->streams[c->fc->nb_streams-1];
7846 3 sc = st->priv_data;
7847
7848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7849 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
7850 return AVERROR_PATCHWELCOME;
7851 }
7852
7853
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7854 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7855 if (!sc->cenc.default_encrypted_sample) {
7856 return AVERROR(ENOMEM);
7857 }
7858 }
7859
7860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 20)
7861 return AVERROR_INVALIDDATA;
7862
7863 3 version = avio_r8(pb); /* version */
7864 3 avio_rb24(pb); /* flags */
7865
7866 3 avio_r8(pb); /* reserved */
7867 3 pattern = avio_r8(pb);
7868
7869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (version > 0) {
7870 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
7871 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
7872 }
7873
7874 3 is_protected = avio_r8(pb);
7875
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) {
7876 // The whole stream should be by-default encrypted.
7877 3 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
7878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.encryption_index)
7879 return AVERROR(ENOMEM);
7880 }
7881 3 sc->cenc.per_sample_iv_size = avio_r8(pb);
7882
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 &&
7883 sc->cenc.per_sample_iv_size != 16) {
7884 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
7885 return AVERROR_INVALIDDATA;
7886 }
7887
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) {
7888 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
7889 return AVERROR_INVALIDDATA;
7890 }
7891
7892
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) {
7893 1 iv_size = avio_r8(pb);
7894
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) {
7895 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
7896 return AVERROR_INVALIDDATA;
7897 }
7898
7899
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) {
7900 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
7901 return AVERROR_INVALIDDATA;
7902 }
7903 }
7904
7905 3 return 0;
7906 }
7907
7908 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7909 {
7910 AVStream *st;
7911 int last, type, size, ret;
7912 uint8_t buf[4];
7913
7914 if (c->fc->nb_streams < 1)
7915 return 0;
7916 st = c->fc->streams[c->fc->nb_streams-1];
7917
7918 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
7919 return AVERROR_INVALIDDATA;
7920
7921 /* Check FlacSpecificBox version. */
7922 if (avio_r8(pb) != 0)
7923 return AVERROR_INVALIDDATA;
7924
7925 avio_rb24(pb); /* Flags */
7926
7927 if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
7928 av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
7929 return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
7930 }
7931 flac_parse_block_header(buf, &last, &type, &size);
7932
7933 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
7934 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
7935 return AVERROR_INVALIDDATA;
7936 }
7937
7938 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
7939 if (ret < 0)
7940 return ret;
7941
7942 if (!last)
7943 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
7944
7945 return 0;
7946 }
7947
7948 146 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
7949 {
7950 int i, ret;
7951 int bytes_of_protected_data;
7952
7953
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 143 times.
146 if (!sc->cenc.aes_ctr) {
7954 /* initialize the cipher */
7955 3 sc->cenc.aes_ctr = av_aes_ctr_alloc();
7956
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.aes_ctr) {
7957 return AVERROR(ENOMEM);
7958 }
7959
7960 3 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
7961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
7962 return ret;
7963 }
7964 }
7965
7966 146 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
7967
7968
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!sample->subsample_count) {
7969 /* decrypt the whole packet */
7970 48 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
7971 48 return 0;
7972 }
7973
7974
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 98 times.
196 for (i = 0; i < sample->subsample_count; i++) {
7975
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) {
7976 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
7977 return AVERROR_INVALIDDATA;
7978 }
7979
7980 /* skip the clear bytes */
7981 98 input += sample->subsamples[i].bytes_of_clear_data;
7982 98 size -= sample->subsamples[i].bytes_of_clear_data;
7983
7984 /* decrypt the encrypted bytes */
7985
7986 98 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
7987 98 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
7988
7989 98 input += bytes_of_protected_data;
7990 98 size -= bytes_of_protected_data;
7991 }
7992
7993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (size > 0) {
7994 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
7995 return AVERROR_INVALIDDATA;
7996 }
7997
7998 98 return 0;
7999 }
8000
8001 static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8002 {
8003 int i, ret;
8004 int num_of_encrypted_blocks;
8005 uint8_t iv[16];
8006
8007 if (!sc->cenc.aes_ctx) {
8008 /* initialize the cipher */
8009 sc->cenc.aes_ctx = av_aes_alloc();
8010 if (!sc->cenc.aes_ctx) {
8011 return AVERROR(ENOMEM);
8012 }
8013
8014 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8015 if (ret < 0) {
8016 return ret;
8017 }
8018 }
8019
8020 memcpy(iv, sample->iv, 16);
8021
8022 /* whole-block full sample encryption */
8023 if (!sample->subsample_count) {
8024 /* decrypt the whole packet */
8025 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8026 return 0;
8027 }
8028
8029 for (i = 0; i < sample->subsample_count; i++) {
8030 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8031 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8032 return AVERROR_INVALIDDATA;
8033 }
8034
8035 if (sample->subsamples[i].bytes_of_protected_data % 16) {
8036 av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8037 return AVERROR_INVALIDDATA;
8038 }
8039
8040 /* skip the clear bytes */
8041 input += sample->subsamples[i].bytes_of_clear_data;
8042 size -= sample->subsamples[i].bytes_of_clear_data;
8043
8044 /* decrypt the encrypted bytes */
8045 num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8046 if (num_of_encrypted_blocks > 0) {
8047 av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8048 }
8049 input += sample->subsamples[i].bytes_of_protected_data;
8050 size -= sample->subsamples[i].bytes_of_protected_data;
8051 }
8052
8053 if (size > 0) {
8054 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8055 return AVERROR_INVALIDDATA;
8056 }
8057
8058 return 0;
8059 }
8060
8061 static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8062 {
8063 int i, ret, rem_bytes;
8064 uint8_t *data;
8065
8066 if (!sc->cenc.aes_ctr) {
8067 /* initialize the cipher */
8068 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8069 if (!sc->cenc.aes_ctr) {
8070 return AVERROR(ENOMEM);
8071 }
8072
8073 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
8074 if (ret < 0) {
8075 return ret;
8076 }
8077 }
8078
8079 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8080
8081 /* whole-block full sample encryption */
8082 if (!sample->subsample_count) {
8083 /* decrypt the whole packet */
8084 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8085 return 0;
8086 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8087 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8088 return AVERROR_INVALIDDATA;
8089 }
8090
8091 for (i = 0; i < sample->subsample_count; i++) {
8092 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8093 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8094 return AVERROR_INVALIDDATA;
8095 }
8096
8097 /* skip the clear bytes */
8098 input += sample->subsamples[i].bytes_of_clear_data;
8099 size -= sample->subsamples[i].bytes_of_clear_data;
8100
8101 /* decrypt the encrypted bytes */
8102 data = input;
8103 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8104 while (rem_bytes > 0) {
8105 if (rem_bytes < 16*sample->crypt_byte_block) {
8106 break;
8107 }
8108 av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8109 data += 16*sample->crypt_byte_block;
8110 rem_bytes -= 16*sample->crypt_byte_block;
8111 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8112 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8113 }
8114 input += sample->subsamples[i].bytes_of_protected_data;
8115 size -= sample->subsamples[i].bytes_of_protected_data;
8116 }
8117
8118 if (size > 0) {
8119 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8120 return AVERROR_INVALIDDATA;
8121 }
8122
8123 return 0;
8124 }
8125
8126 static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8127 {
8128 int i, ret, rem_bytes;
8129 uint8_t iv[16];
8130 uint8_t *data;
8131
8132 if (!sc->cenc.aes_ctx) {
8133 /* initialize the cipher */
8134 sc->cenc.aes_ctx = av_aes_alloc();
8135 if (!sc->cenc.aes_ctx) {
8136 return AVERROR(ENOMEM);
8137 }
8138
8139 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8140 if (ret < 0) {
8141 return ret;
8142 }
8143 }
8144
8145 /* whole-block full sample encryption */
8146 if (!sample->subsample_count) {
8147 /* decrypt the whole packet */
8148 memcpy(iv, sample->iv, 16);
8149 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8150 return 0;
8151 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8152 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8153 return AVERROR_INVALIDDATA;
8154 }
8155
8156 for (i = 0; i < sample->subsample_count; i++) {
8157 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8158 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8159 return AVERROR_INVALIDDATA;
8160 }
8161
8162 /* skip the clear bytes */
8163 input += sample->subsamples[i].bytes_of_clear_data;
8164 size -= sample->subsamples[i].bytes_of_clear_data;
8165
8166 /* decrypt the encrypted bytes */
8167 memcpy(iv, sample->iv, 16);
8168 data = input;
8169 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8170 while (rem_bytes > 0) {
8171 if (rem_bytes < 16*sample->crypt_byte_block) {
8172 break;
8173 }
8174 av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8175 data += 16*sample->crypt_byte_block;
8176 rem_bytes -= 16*sample->crypt_byte_block;
8177 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8178 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8179 }
8180 input += sample->subsamples[i].bytes_of_protected_data;
8181 size -= sample->subsamples[i].bytes_of_protected_data;
8182 }
8183
8184 if (size > 0) {
8185 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8186 return AVERROR_INVALIDDATA;
8187 }
8188
8189 return 0;
8190 }
8191
8192 146 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8193 {
8194
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) {
8195 146 return cenc_scheme_decrypt(c, sc, sample, input, size);
8196 } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8197 return cbc1_scheme_decrypt(c, sc, sample, input, size);
8198 } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8199 return cens_scheme_decrypt(c, sc, sample, input, size);
8200 } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8201 return cbcs_scheme_decrypt(c, sc, sample, input, size);
8202 } else {
8203 av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8204 return AVERROR_INVALIDDATA;
8205 }
8206 }
8207
8208 96488 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8209 {
8210 96488 int current = frag_index->current;
8211
8212
2/2
✓ Branch 0 taken 95827 times.
✓ Branch 1 taken 661 times.
96488 if (!frag_index->nb_items)
8213 95827 return NULL;
8214
8215 // Check frag_index->current is the right one for pkt. It can out of sync.
8216
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) {
8217
2/2
✓ Branch 0 taken 639 times.
✓ Branch 1 taken 22 times.
661 if (frag_index->item[current].moof_offset < pkt->pos &&
8218
2/2
✓ Branch 0 taken 413 times.
✓ Branch 1 taken 226 times.
639 (current + 1 == frag_index->nb_items ||
8219
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 25 times.
413 frag_index->item[current + 1].moof_offset > pkt->pos))
8220 614 return get_frag_stream_info(frag_index, current, id);
8221 }
8222
8223
8224
2/2
✓ Branch 0 taken 3955 times.
✓ Branch 1 taken 4 times.
3959 for (int i = 0; i < frag_index->nb_items; i++) {
8225
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 3912 times.
3955 if (frag_index->item[i].moof_offset > pkt->pos)
8226 43 break;
8227 3912 current = i;
8228 }
8229 47 frag_index->current = current;
8230 47 return get_frag_stream_info(frag_index, current, id);
8231 }
8232
8233 96488 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8234 {
8235 MOVFragmentStreamInfo *frag_stream_info;
8236 MOVEncryptionIndex *encryption_index;
8237 AVEncryptionInfo *encrypted_sample;
8238 int encrypted_index, ret;
8239
8240 96488 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8241 96488 encrypted_index = current_index;
8242 96488 encryption_index = NULL;
8243
2/2
✓ Branch 0 taken 661 times.
✓ Branch 1 taken 95827 times.
96488 if (frag_stream_info) {
8244 // Note this only supports encryption info in the first sample descriptor.
8245
2/2
✓ Branch 0 taken 637 times.
✓ Branch 1 taken 24 times.
661 if (frag_stream_info->stsd_id == 1) {
8246
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 613 times.
637 if (frag_stream_info->encryption_index) {
8247 24 encrypted_index = current_index - frag_stream_info->index_base;
8248 24 encryption_index = frag_stream_info->encryption_index;
8249 } else {
8250 613 encryption_index = sc->cenc.encryption_index;
8251 }
8252 }
8253 } else {
8254 95827 encryption_index = sc->cenc.encryption_index;
8255 }
8256
8257
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 96342 times.
96488 if (encryption_index) {
8258
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_info_sample_count &&
8259
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8260 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8261 return AVERROR_INVALIDDATA;
8262 }
8263
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_offsets_count &&
8264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8265 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8266 return AVERROR_INVALIDDATA;
8267 }
8268
8269 146 encrypted_sample = NULL;
8270
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!encryption_index->nb_encrypted_samples) {
8271 // Full-sample encryption with default settings.
8272 48 encrypted_sample = sc->cenc.default_encrypted_sample;
8273
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) {
8274 // Per-sample setting override.
8275 98 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (!encrypted_sample) {
8277 encrypted_sample = sc->cenc.default_encrypted_sample;
8278 }
8279 }
8280
8281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (!encrypted_sample) {
8282 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8283 return AVERROR_INVALIDDATA;
8284 }
8285
8286
1/2
✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
146 if (mov->decryption_key) {
8287 146 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
8288 } else {
8289 size_t size;
8290 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
8291 if (!side_data)
8292 return AVERROR(ENOMEM);
8293 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
8294 if (ret < 0)
8295 av_free(side_data);
8296 return ret;
8297 }
8298 }
8299
8300 96342 return 0;
8301 }
8302
8303 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8304 {
8305 const int OPUS_SEEK_PREROLL_MS = 80;
8306 int ret;
8307 AVStream *st;
8308 size_t size;
8309 uint16_t pre_skip;
8310
8311 if (c->fc->nb_streams < 1)
8312 return 0;
8313 st = c->fc->streams[c->fc->nb_streams-1];
8314
8315 if ((uint64_t)atom.size > (1<<30) || atom.size < 11)
8316 return AVERROR_INVALIDDATA;
8317
8318 /* Check OpusSpecificBox version. */
8319 if (avio_r8(pb) != 0) {
8320 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
8321 return AVERROR_INVALIDDATA;
8322 }
8323
8324 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
8325 size = atom.size + 8;
8326
8327 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
8328 return ret;
8329
8330 AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
8331 AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
8332 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
8333 avio_read(pb, st->codecpar->extradata + 9, size - 9);
8334
8335 /* OpusSpecificBox is stored in big-endian, but OpusHead is
8336 little-endian; aside from the preceeding magic and version they're
8337 otherwise currently identical. Data after output gain at offset 16
8338 doesn't need to be bytewapped. */
8339 pre_skip = AV_RB16A(st->codecpar->extradata + 10);
8340 AV_WL16A(st->codecpar->extradata + 10, pre_skip);
8341 AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
8342 AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
8343
8344 st->codecpar->initial_padding = pre_skip;
8345 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
8346 (AVRational){1, 1000},
8347 (AVRational){1, 48000});
8348
8349 return 0;
8350 }
8351
8352 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8353 {
8354 AVStream *st;
8355 unsigned format_info;
8356 int channel_assignment, channel_assignment1, channel_assignment2;
8357 int ratebits;
8358 uint64_t chmask;
8359
8360 if (c->fc->nb_streams < 1)
8361 return 0;
8362 st = c->fc->streams[c->fc->nb_streams-1];
8363
8364 if (atom.size < 10)
8365 return AVERROR_INVALIDDATA;
8366
8367 format_info = avio_rb32(pb);
8368
8369 ratebits = (format_info >> 28) & 0xF;
8370 channel_assignment1 = (format_info >> 15) & 0x1F;
8371 channel_assignment2 = format_info & 0x1FFF;
8372 if (channel_assignment2)
8373 channel_assignment = channel_assignment2;
8374 else
8375 channel_assignment = channel_assignment1;
8376
8377 st->codecpar->frame_size = 40 << (ratebits & 0x7);
8378 st->codecpar->sample_rate = mlp_samplerate(ratebits);
8379
8380 av_channel_layout_uninit(&st->codecpar->ch_layout);
8381 chmask = truehd_layout(channel_assignment);
8382 av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
8383
8384 return 0;
8385 }
8386
8387 4 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8388 {
8389 AVStream *st;
8390 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
8391 int ret;
8392 4 int64_t read_size = atom.size;
8393
8394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8395 return 0;
8396 4 st = c->fc->streams[c->fc->nb_streams-1];
8397
8398 // At most 24 bytes
8399 4 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
8400
8401
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
8402 return ret;
8403
8404 4 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
8405 }
8406
8407 3 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8408 {
8409 AVStream *st;
8410 uint8_t *buf;
8411 int ret, old_size, num_arrays;
8412
8413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
8414 return 0;
8415 3 st = c->fc->streams[c->fc->nb_streams-1];
8416
8417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata_size)
8418 // TODO: handle lhvC when present before hvcC
8419 return 0;
8420
8421
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)
8422 return AVERROR_INVALIDDATA;
8423
8424 3 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
8425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!buf)
8426 return AVERROR(ENOMEM);
8427 3 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8428
8429 3 ret = ffio_read_size(pb, buf, atom.size);
8430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8431 av_free(buf);
8432 av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
8433 return 0;
8434 }
8435
8436 3 num_arrays = buf[5];
8437 3 old_size = st->codecpar->extradata_size;
8438 3 atom.size -= 8 /* account for mov_realloc_extradata offseting */
8439 + 6 /* lhvC bytes before the arrays*/;
8440
8441 3 ret = mov_realloc_extradata(st->codecpar, atom);
8442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8443 av_free(buf);
8444 return ret;
8445 }
8446
8447 3 st->codecpar->extradata[22] += num_arrays;
8448 3 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
8449
8450 3 st->disposition |= AV_DISPOSITION_MULTILAYER;
8451
8452 3 av_free(buf);
8453 3 return 0;
8454 }
8455
8456 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8457 {
8458 4 AVFormatContext *ctx = c->fc;
8459 4 AVStream *st = NULL;
8460 AVBPrint scheme_buf, value_buf;
8461 4 int64_t scheme_str_len = 0, value_str_len = 0;
8462 4 int version, flags, ret = AVERROR_BUG;
8463 4 int64_t size = atom.size;
8464
8465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
8466 // 4 bytes for version + flags, 2x 1 byte for null
8467 return AVERROR_INVALIDDATA;
8468
8469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8470 return 0;
8471 4 st = c->fc->streams[c->fc->nb_streams-1];
8472
8473 4 version = avio_r8(pb);
8474 4 flags = avio_rb24(pb);
8475 4 size -= 4;
8476
8477
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) {
8478 av_log(ctx, AV_LOG_ERROR,
8479 "Unsupported 'kind' box with version %d, flags: %x",
8480 version, flags);
8481 return AVERROR_INVALIDDATA;
8482 }
8483
8484 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8485 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8486
8487
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,
8488 size)) < 0) {
8489 ret = scheme_str_len;
8490 goto cleanup;
8491 }
8492
8493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
8494 // we need to have another string, even if nullptr.
8495 // we check with + 1 since we expect that if size was not hit,
8496 // an additional null was read.
8497 ret = AVERROR_INVALIDDATA;
8498 goto cleanup;
8499 }
8500
8501 4 size -= scheme_str_len + 1;
8502
8503
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,
8504 size)) < 0) {
8505 ret = value_str_len;
8506 goto cleanup;
8507 }
8508
8509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
8510 // in case of no trailing null, box is not valid.
8511 ret = AVERROR_INVALIDDATA;
8512 goto cleanup;
8513 }
8514
8515 4 av_log(ctx, AV_LOG_TRACE,
8516 "%s stream %d KindBox(scheme: %s, value: %s)\n",
8517 4 av_get_media_type_string(st->codecpar->codec_type),
8518 st->index,
8519 scheme_buf.str, value_buf.str);
8520
8521
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++) {
8522 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
8523
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
8524 continue;
8525
8526
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
8527 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
8528
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
8529 16 continue;
8530
8531 4 st->disposition |= value_map.disposition;
8532 }
8533 }
8534
8535 4 ret = 0;
8536
8537 4 cleanup:
8538
8539 4 av_bprint_finalize(&scheme_buf, NULL);
8540 4 av_bprint_finalize(&value_buf, NULL);
8541
8542 4 return ret;
8543 }
8544
8545 static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8546 {
8547 AVStream *st;
8548 AVChannelLayout ch_layout = { 0 };
8549 int ret, i, version, type;
8550 int ambisonic_order, channel_order, normalization, channel_count;
8551 int ambi_channels, non_diegetic_channels;
8552
8553 if (c->fc->nb_streams < 1)
8554 return 0;
8555
8556 st = c->fc->streams[c->fc->nb_streams - 1];
8557
8558 if (atom.size < 16) {
8559 av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
8560 return AVERROR_INVALIDDATA;
8561 }
8562
8563 version = avio_r8(pb);
8564 if (version) {
8565 av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
8566 return 0;
8567 }
8568
8569 type = avio_r8(pb);
8570 if (type & 0x7f) {
8571 av_log(c->fc, AV_LOG_WARNING,
8572 "Unsupported ambisonic type %d\n", type & 0x7f);
8573 return 0;
8574 }
8575 non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
8576
8577 ambisonic_order = avio_rb32(pb);
8578
8579 channel_order = avio_r8(pb);
8580 if (channel_order) {
8581 av_log(c->fc, AV_LOG_WARNING,
8582 "Unsupported channel_order %d\n", channel_order);
8583 return 0;
8584 }
8585
8586 normalization = avio_r8(pb);
8587 if (normalization) {
8588 av_log(c->fc, AV_LOG_WARNING,
8589 "Unsupported normalization %d\n", normalization);
8590 return 0;
8591 }
8592
8593 channel_count = avio_rb32(pb);
8594 if (ambisonic_order < 0 || ambisonic_order > 31 ||
8595 channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
8596 non_diegetic_channels)) {
8597 av_log(c->fc, AV_LOG_ERROR,
8598 "Invalid number of channels (%d / %d)\n",
8599 channel_count, ambisonic_order);
8600 return 0;
8601 }
8602 ambi_channels = channel_count - non_diegetic_channels;
8603
8604 ret = av_channel_layout_custom_init(&ch_layout, channel_count);
8605 if (ret < 0)
8606 return 0;
8607
8608 for (i = 0; i < channel_count; i++) {
8609 unsigned channel = avio_rb32(pb);
8610
8611 if (channel >= channel_count) {
8612 av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
8613 channel, ambisonic_order);
8614 av_channel_layout_uninit(&ch_layout);
8615 return 0;
8616 }
8617 if (channel >= ambi_channels)
8618 ch_layout.u.map[i].id = channel - ambi_channels;
8619 else
8620 ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
8621 }
8622
8623 ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
8624 if (ret < 0) {
8625 av_channel_layout_uninit(&ch_layout);
8626 return 0;
8627 }
8628
8629 av_channel_layout_uninit(&st->codecpar->ch_layout);
8630 st->codecpar->ch_layout = ch_layout;
8631
8632 return 0;
8633 }
8634
8635 static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8636 {
8637 AVStream *st;
8638 int version;
8639
8640 if (c->fc->nb_streams < 1)
8641 return 0;
8642
8643 st = c->fc->streams[c->fc->nb_streams - 1];
8644
8645 if (atom.size < 5) {
8646 av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
8647 return AVERROR_INVALIDDATA;
8648 }
8649
8650 version = avio_r8(pb);
8651 if (version) {
8652 av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
8653 return 0;
8654 }
8655
8656 st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
8657
8658 return 0;
8659 }
8660
8661 90 static int rb_size(AVIOContext *pb, int64_t *value, int size)
8662 {
8663
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 89 times.
90 if (size == 0)
8664 1 *value = 0;
8665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
89 else if (size == 1)
8666 *value = avio_r8(pb);
8667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
89 else if (size == 2)
8668 *value = avio_rb16(pb);
8669
1/2
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
89 else if (size == 4)
8670 89 *value = avio_rb32(pb);
8671 else if (size == 8) {
8672 *value = avio_rb64(pb);
8673 if (*value < 0)
8674 return -1;
8675 } else
8676 return -1;
8677 90 return size;
8678 }
8679
8680 12 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8681 {
8682 12 avio_rb32(pb); // version & flags.
8683 12 c->primary_item_id = avio_rb16(pb);
8684 12 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
8685 12 return atom.size;
8686 }
8687
8688 6 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8689 {
8690 6 c->idat_offset = avio_tell(pb);
8691 6 return 0;
8692 }
8693
8694 12 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8695 {
8696 HEIFItem **heif_item;
8697 int version, offset_size, length_size, base_offset_size, index_size;
8698 int item_count, extent_count;
8699 int64_t base_offset, extent_offset, extent_length;
8700 uint8_t value;
8701
8702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->found_iloc) {
8703 av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
8704 return 0;
8705 }
8706
8707 12 version = avio_r8(pb);
8708 12 avio_rb24(pb); // flags.
8709
8710 12 value = avio_r8(pb);
8711 12 offset_size = (value >> 4) & 0xF;
8712 12 length_size = value & 0xF;
8713 12 value = avio_r8(pb);
8714 12 base_offset_size = (value >> 4) & 0xF;
8715
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 index_size = !version ? 0 : (value & 0xF);
8716
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (index_size) {
8717 avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
8718 return AVERROR_PATCHWELCOME;
8719 }
8720
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8721
8722 12 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
8723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!heif_item)
8724 return AVERROR(ENOMEM);
8725 12 c->heif_item = heif_item;
8726
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (item_count > c->nb_heif_item)
8727 12 memset(&c->heif_item[c->nb_heif_item], 0,
8728 12 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
8729 12 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
8730
8731 12 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
8732
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 for (int i = 0; i < item_count; i++) {
8733 30 HEIFItem *item = c->heif_item[i];
8734
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8735
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
8736
8737
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (avio_feof(pb))
8738 return AVERROR_INVALIDDATA;
8739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (offset_type > 1) {
8740 avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
8741 return AVERROR_PATCHWELCOME;
8742 }
8743
8744 30 avio_rb16(pb); // data_reference_index.
8745
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (rb_size(pb, &base_offset, base_offset_size) < 0)
8746 return AVERROR_INVALIDDATA;
8747 30 extent_count = avio_rb16(pb);
8748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (extent_count > 1) {
8749 // For still AVIF images, we only support one extent item.
8750 avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
8751 return AVERROR_PATCHWELCOME;
8752 }
8753
8754
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 ||
8755 30 rb_size(pb, &extent_length, length_size) < 0 ||
8756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 base_offset > INT64_MAX - extent_offset)
8757 return AVERROR_INVALIDDATA;
8758
8759
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if (!item)
8760 30 item = c->heif_item[i] = av_mallocz(sizeof(*item));
8761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!item)
8762 return AVERROR(ENOMEM);
8763
8764 30 item->item_id = item_id;
8765
8766
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 24 times.
30 if (offset_type == 1)
8767 6 item->is_idat_relative = 1;
8768 30 item->extent_length = extent_length;
8769 30 item->extent_offset = base_offset + extent_offset;
8770 30 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, offset_type %d, "
8771 "extent_offset %"PRId64", extent_length %"PRId64"\n",
8772 i, offset_type, item->extent_offset, item->extent_length);
8773 }
8774
8775 12 c->found_iloc = 1;
8776 12 return atom.size;
8777 }
8778
8779 30 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom, int idx)
8780 {
8781 HEIFItem *item;
8782 AVBPrint item_name;
8783 30 int64_t size = atom.size;
8784 uint32_t item_type;
8785 int item_id;
8786 int version, ret;
8787
8788 30 version = avio_r8(pb);
8789 30 avio_rb24(pb); // flags.
8790 30 size -= 4;
8791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (size < 0)
8792 return AVERROR_INVALIDDATA;
8793
8794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (version < 2) {
8795 avpriv_report_missing_feature(c->fc, "infe version < 2");
8796 avio_skip(pb, size);
8797 return 1;
8798 }
8799
8800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
8801 30 avio_rb16(pb); // item_protection_index
8802 30 item_type = avio_rl32(pb);
8803 30 size -= 8;
8804
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (size < 1)
8805 return AVERROR_INVALIDDATA;
8806
8807 30 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
8808 30 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
8809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (ret < 0) {
8810 av_bprint_finalize(&item_name, NULL);
8811 return ret;
8812 }
8813
8814 30 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
8815 30 item_id, av_fourcc2str(item_type), item_name.str);
8816
8817 30 size -= ret + 1;
8818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (size > 0)
8819 avio_skip(pb, size);
8820
8821 30 item = c->heif_item[idx];
8822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!item)
8823 item = c->heif_item[idx] = av_mallocz(sizeof(*item));
8824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!item)
8825 return AVERROR(ENOMEM);
8826
8827
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 1 times.
30 if (ret)
8828 29 av_bprint_finalize(&item_name, &c->heif_item[idx]->name);
8829 30 c->heif_item[idx]->item_id = item_id;
8830 30 c->heif_item[idx]->type = item_type;
8831
8832
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 7 times.
30 switch (item_type) {
8833 23 case MKTAG('a','v','0','1'):
8834 case MKTAG('h','v','c','1'):
8835 23 ret = heif_add_stream(c, c->heif_item[idx]);
8836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (ret < 0)
8837 return ret;
8838 23 break;
8839 }
8840
8841 30 return 0;
8842 }
8843
8844 12 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8845 {
8846 HEIFItem **heif_item;
8847 int entry_count;
8848 12 int version, got_stream = 0, ret, i;
8849
8850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->found_iinf) {
8851 av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
8852 return 0;
8853 }
8854
8855 12 version = avio_r8(pb);
8856 12 avio_rb24(pb); // flags.
8857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
8858
8859 12 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
8860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!heif_item)
8861 return AVERROR(ENOMEM);
8862 12 c->heif_item = heif_item;
8863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (entry_count > c->nb_heif_item)
8864 memset(&c->heif_item[c->nb_heif_item], 0,
8865 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
8866 12 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
8867
8868
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 for (i = 0; i < entry_count; i++) {
8869 MOVAtom infe;
8870
8871
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (avio_feof(pb)) {
8872 ret = AVERROR_INVALIDDATA;
8873 goto fail;
8874 }
8875 30 infe.size = avio_rb32(pb) - 8;
8876 30 infe.type = avio_rl32(pb);
8877 30 ret = mov_read_infe(c, pb, infe, i);
8878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (ret < 0)
8879 goto fail;
8880
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if (!ret)
8881 30 got_stream = 1;
8882 }
8883
8884 12 c->found_iinf = got_stream;
8885 12 return 0;
8886 fail:
8887 for (; i >= 0; i--) {
8888 HEIFItem *item = c->heif_item[i];
8889
8890 if (!item)
8891 continue;
8892
8893 av_freep(&item->name);
8894 if (!item->st)
8895 continue;
8896
8897 mov_free_stream_context(c->fc, item->st);
8898 ff_remove_stream(c->fc, item->st);
8899 item->st = NULL;
8900 }
8901 return ret;
8902 }
8903
8904 6 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
8905 {
8906 6 HEIFItem *item = NULL;
8907 HEIFGrid *grid;
8908 int entries, i;
8909
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8910
8911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 for (int i = 0; i < c->nb_heif_grid; i++) {
8912 if (c->heif_grid[i].item->item_id == from_item_id) {
8913 av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
8914 "referencing the same Derived Image item\n");
8915 return AVERROR_INVALIDDATA;
8916 }
8917 }
8918
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 for (int i = 0; i < c->nb_heif_item; i++) {
8919
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)
8920 14 continue;
8921 6 item = c->heif_item[i];
8922
8923
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 switch (item->type) {
8924 6 case MKTAG('g','r','i','d'):
8925 case MKTAG('i','o','v','l'):
8926 6 break;
8927 default:
8928 avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
8929 av_fourcc2str(item->type));
8930 return 0;
8931 }
8932 6 break;
8933 }
8934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!item) {
8935 av_log(c->fc, AV_LOG_ERROR, "Missing grid information\n");
8936 return AVERROR_INVALIDDATA;
8937 }
8938
8939 6 grid = av_realloc_array(c->heif_grid, c->nb_heif_grid + 1U,
8940 sizeof(*c->heif_grid));
8941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!grid)
8942 return AVERROR(ENOMEM);
8943 6 c->heif_grid = grid;
8944 6 grid = &grid[c->nb_heif_grid++];
8945
8946 6 entries = avio_rb16(pb);
8947 6 grid->tile_id_list = av_malloc_array(entries, sizeof(*grid->tile_id_list));
8948 6 grid->tile_idx_list = av_calloc(entries, sizeof(*grid->tile_idx_list));
8949 6 grid->tile_item_list = av_calloc(entries, sizeof(*grid->tile_item_list));
8950
3/6
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
6 if (!grid->tile_id_list || !grid->tile_item_list || !grid->tile_idx_list)
8951 return AVERROR(ENOMEM);
8952 /* 'to' item ids */
8953
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (i = 0; i < entries; i++)
8954
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 grid->tile_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
8955 6 grid->nb_tiles = entries;
8956 6 grid->item = item;
8957
8958 6 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
8959 from_item_id, entries);
8960
8961 6 return 0;
8962 }
8963
8964 2 static int mov_read_iref_thmb(MOVContext *c, AVIOContext *pb, int version)
8965 {
8966 int entries;
8967
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);
8968
8969 2 entries = avio_rb16(pb);
8970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (entries > 1) {
8971 avpriv_request_sample(c->fc, "thmb in iref referencing several items");
8972 return AVERROR_PATCHWELCOME;
8973 }
8974 /* 'to' item ids */
8975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 to_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8976
8977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (to_item_id != c->primary_item_id)
8978 return 0;
8979
8980 2 c->thmb_item_id = from_item_id;
8981
8982 2 av_log(c->fc, AV_LOG_TRACE, "thmb: from_item_id %d, entries %d\n",
8983 from_item_id, entries);
8984
8985 2 return 0;
8986 }
8987
8988 8 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8989 {
8990 8 int version = avio_r8(pb);
8991 8 avio_rb24(pb); // flags
8992 8 atom.size -= 4;
8993
8994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (version > 1) {
8995 av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
8996 return 0;
8997 }
8998
8999
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 while (atom.size) {
9000 8 uint32_t type, size = avio_rb32(pb);
9001 8 int64_t next = avio_tell(pb);
9002
9003
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)
9004 return AVERROR_INVALIDDATA;
9005
9006 8 next += size - 4;
9007 8 type = avio_rl32(pb);
9008
2/3
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
8 switch (type) {
9009 6 case MKTAG('d','i','m','g'):
9010 6 mov_read_iref_dimg(c, pb, version);
9011 8 break;
9012 2 case MKTAG('t','h','m','b'):
9013 2 mov_read_iref_thmb(c, pb, version);
9014 2 break;
9015 default:
9016 av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
9017 av_fourcc2str(type), size);
9018 }
9019
9020 8 atom.size -= size;
9021 8 avio_seek(pb, next, SEEK_SET);
9022 }
9023 8 return 0;
9024 }
9025
9026 29 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9027 {
9028 HEIFItem *item;
9029 uint32_t width, height;
9030
9031 29 avio_r8(pb); /* version */
9032 29 avio_rb24(pb); /* flags */
9033 29 width = avio_rb32(pb);
9034 29 height = avio_rb32(pb);
9035
9036 29 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %u, height %u\n",
9037 c->cur_item_id, width, height);
9038
9039 29 item = heif_cur_item(c);
9040
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (item) {
9041 29 item->width = width;
9042 29 item->height = height;
9043 }
9044
9045 29 return 0;
9046 }
9047
9048 4 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9049 {
9050 HEIFItem *item;
9051 int angle;
9052
9053 4 angle = avio_r8(pb) & 0x3;
9054
9055 4 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
9056 c->cur_item_id, angle);
9057
9058 4 item = heif_cur_item(c);
9059
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item) {
9060 // angle * 90 specifies the angle (in anti-clockwise direction)
9061 // in units of degrees.
9062 4 item->rotation = angle * 90;
9063 }
9064
9065 4 return 0;
9066 }
9067
9068 4 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9069 {
9070 HEIFItem *item;
9071 int axis;
9072
9073 4 axis = avio_r8(pb) & 0x1;
9074
9075 4 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
9076 c->cur_item_id, axis);
9077
9078 4 item = heif_cur_item(c);
9079
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item) {
9080 4 item->hflip = axis;
9081 4 item->vflip = !axis;
9082 }
9083
9084 4 return 0;
9085 }
9086
9087 12 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9088 {
9089 typedef struct MOVAtoms {
9090 FFIOContext b;
9091 uint32_t type;
9092 int64_t size;
9093 uint8_t *data;
9094 } MOVAtoms;
9095 12 MOVAtoms *atoms = NULL;
9096 MOVAtom a;
9097 unsigned count;
9098 12 int nb_atoms = 0;
9099 int version, flags;
9100 int ret;
9101
9102 12 a.size = avio_rb32(pb);
9103 12 a.type = avio_rl32(pb);
9104
9105
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'))
9106 return AVERROR_INVALIDDATA;
9107
9108 12 a.size -= 8;
9109
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 12 times.
61 while (a.size >= 8) {
9110 49 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
9111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if (!ref) {
9112 ret = AVERROR(ENOMEM);
9113 goto fail;
9114 }
9115 49 ref->data = NULL;
9116 49 ref->size = avio_rb32(pb);
9117 49 ref->type = avio_rl32(pb);
9118
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)
9119 break;
9120 49 ref->data = av_malloc(ref->size);
9121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if (!ref->data) {
9122 ret = AVERROR_INVALIDDATA;
9123 goto fail;
9124 }
9125 49 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
9126 49 avio_seek(pb, -8, SEEK_CUR);
9127
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
49 if (avio_read(pb, ref->data, ref->size) != ref->size) {
9128 ret = AVERROR_INVALIDDATA;
9129 goto fail;
9130 }
9131 49 ffio_init_read_context(&ref->b, ref->data, ref->size);
9132 49 a.size -= ref->size;
9133 }
9134
9135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (a.size) {
9136 ret = AVERROR_INVALIDDATA;
9137 goto fail;
9138 }
9139
9140 12 a.size = avio_rb32(pb);
9141 12 a.type = avio_rl32(pb);
9142
9143
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')) {
9144 ret = AVERROR_INVALIDDATA;
9145 goto fail;
9146 }
9147
9148 12 version = avio_r8(pb);
9149 12 flags = avio_rb24(pb);
9150 12 count = avio_rb32(pb);
9151
9152
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 12 times.
41 for (int i = 0; i < count; i++) {
9153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9154 29 int assoc_count = avio_r8(pb);
9155
9156
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 if (avio_feof(pb)) {
9157 ret = AVERROR_INVALIDDATA;
9158 goto fail;
9159 }
9160
9161
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 29 times.
101 for (int j = 0; j < assoc_count; j++) {
9162 MOVAtoms *ref;
9163 72 int index = avio_r8(pb) & 0x7f;
9164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (flags & 1) {
9165 index <<= 8;
9166 index |= avio_r8(pb);
9167 }
9168
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) {
9169 ret = AVERROR_INVALIDDATA;
9170 goto fail;
9171 }
9172 72 ref = &atoms[--index];
9173
9174 72 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
9175 72 index + 1, item_id, av_fourcc2str(ref->type));
9176
9177 72 c->cur_item_id = item_id;
9178
9179 72 ret = mov_read_default(c, &ref->b.pub,
9180 72 (MOVAtom) { .size = ref->size,
9181 .type = MKTAG('i','p','c','o') });
9182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (ret < 0)
9183 goto fail;
9184 72 ffio_init_read_context(&ref->b, ref->data, ref->size);
9185 }
9186 }
9187
9188 12 ret = 0;
9189 12 fail:
9190 12 c->cur_item_id = -1;
9191
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 12 times.
61 for (int i = 0; i < nb_atoms; i++)
9192 49 av_free(atoms[i].data);
9193 12 av_free(atoms);
9194
9195 12 return ret;
9196 }
9197
9198 static const MOVParseTableEntry mov_default_parse_table[] = {
9199 { MKTAG('A','C','L','R'), mov_read_aclr },
9200 { MKTAG('A','P','R','G'), mov_read_avid },
9201 { MKTAG('A','A','L','P'), mov_read_avid },
9202 { MKTAG('A','R','E','S'), mov_read_ares },
9203 { MKTAG('a','v','s','s'), mov_read_avss },
9204 { MKTAG('a','v','1','C'), mov_read_glbl },
9205 { MKTAG('c','h','p','l'), mov_read_chpl },
9206 { MKTAG('c','o','6','4'), mov_read_stco },
9207 { MKTAG('c','o','l','r'), mov_read_colr },
9208 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
9209 { MKTAG('d','i','n','f'), mov_read_default },
9210 { MKTAG('D','p','x','E'), mov_read_dpxe },
9211 { MKTAG('d','r','e','f'), mov_read_dref },
9212 { MKTAG('e','d','t','s'), mov_read_default },
9213 { MKTAG('e','l','s','t'), mov_read_elst },
9214 { MKTAG('e','n','d','a'), mov_read_enda },
9215 { MKTAG('f','i','e','l'), mov_read_fiel },
9216 { MKTAG('a','d','r','m'), mov_read_adrm },
9217 { MKTAG('f','t','y','p'), mov_read_ftyp },
9218 { MKTAG('g','l','b','l'), mov_read_glbl },
9219 { MKTAG('h','d','l','r'), mov_read_hdlr },
9220 { MKTAG('i','l','s','t'), mov_read_ilst },
9221 { MKTAG('j','p','2','h'), mov_read_jp2h },
9222 { MKTAG('m','d','a','t'), mov_read_mdat },
9223 { MKTAG('m','d','h','d'), mov_read_mdhd },
9224 { MKTAG('m','d','i','a'), mov_read_default },
9225 { MKTAG('m','e','t','a'), mov_read_meta },
9226 { MKTAG('m','i','n','f'), mov_read_default },
9227 { MKTAG('m','o','o','f'), mov_read_moof },
9228 { MKTAG('m','o','o','v'), mov_read_moov },
9229 { MKTAG('m','v','e','x'), mov_read_default },
9230 { MKTAG('m','v','h','d'), mov_read_mvhd },
9231 { MKTAG('S','M','I',' '), mov_read_svq3 },
9232 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
9233 { MKTAG('a','v','c','C'), mov_read_glbl },
9234 { MKTAG('p','a','s','p'), mov_read_pasp },
9235 { MKTAG('c','l','a','p'), mov_read_clap },
9236 { MKTAG('s','b','a','s'), mov_read_sbas },
9237 { MKTAG('s','i','d','x'), mov_read_sidx },
9238 { MKTAG('s','t','b','l'), mov_read_default },
9239 { MKTAG('s','t','c','o'), mov_read_stco },
9240 { MKTAG('s','t','p','s'), mov_read_stps },
9241 { MKTAG('s','t','r','f'), mov_read_strf },
9242 { MKTAG('s','t','s','c'), mov_read_stsc },
9243 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
9244 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
9245 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
9246 { MKTAG('s','t','t','s'), mov_read_stts },
9247 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
9248 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
9249 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
9250 { MKTAG('t','f','d','t'), mov_read_tfdt },
9251 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
9252 { MKTAG('t','r','a','k'), mov_read_trak },
9253 { MKTAG('t','r','a','f'), mov_read_default },
9254 { MKTAG('t','r','e','f'), mov_read_default },
9255 { MKTAG('t','m','c','d'), mov_read_tmcd },
9256 { MKTAG('c','h','a','p'), mov_read_chap },
9257 { MKTAG('t','r','e','x'), mov_read_trex },
9258 { MKTAG('t','r','u','n'), mov_read_trun },
9259 { MKTAG('u','d','t','a'), mov_read_default },
9260 { MKTAG('w','a','v','e'), mov_read_wave },
9261 { MKTAG('e','s','d','s'), mov_read_esds },
9262 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
9263 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
9264 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
9265 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
9266 { MKTAG('w','f','e','x'), mov_read_wfex },
9267 { MKTAG('c','m','o','v'), mov_read_cmov },
9268 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
9269 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
9270 { MKTAG('d','v','c','1'), mov_read_dvc1 },
9271 { MKTAG('s','g','p','d'), mov_read_sgpd },
9272 { MKTAG('s','b','g','p'), mov_read_sbgp },
9273 { MKTAG('h','v','c','C'), mov_read_glbl },
9274 { MKTAG('v','v','c','C'), mov_read_glbl },
9275 { MKTAG('u','u','i','d'), mov_read_uuid },
9276 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
9277 { MKTAG('f','r','e','e'), mov_read_free },
9278 { MKTAG('-','-','-','-'), mov_read_custom },
9279 { MKTAG('s','i','n','f'), mov_read_default },
9280 { MKTAG('f','r','m','a'), mov_read_frma },
9281 { MKTAG('s','e','n','c'), mov_read_senc },
9282 { MKTAG('s','a','i','z'), mov_read_saiz },
9283 { MKTAG('s','a','i','o'), mov_read_saio },
9284 { MKTAG('p','s','s','h'), mov_read_pssh },
9285 { MKTAG('s','c','h','m'), mov_read_schm },
9286 { MKTAG('s','c','h','i'), mov_read_default },
9287 { MKTAG('t','e','n','c'), mov_read_tenc },
9288 { MKTAG('d','f','L','a'), mov_read_dfla },
9289 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
9290 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
9291 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
9292 { MKTAG('h','f','o','v'), mov_read_hfov },
9293 { MKTAG('d','O','p','s'), mov_read_dops },
9294 { MKTAG('d','m','l','p'), mov_read_dmlp },
9295 { MKTAG('S','m','D','m'), mov_read_smdm },
9296 { MKTAG('C','o','L','L'), mov_read_coll },
9297 { MKTAG('v','p','c','C'), mov_read_vpcc },
9298 { MKTAG('m','d','c','v'), mov_read_mdcv },
9299 { MKTAG('c','l','l','i'), mov_read_clli },
9300 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
9301 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
9302 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
9303 { MKTAG('k','i','n','d'), mov_read_kind },
9304 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
9305 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
9306 { MKTAG('i','l','o','c'), mov_read_iloc },
9307 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
9308 { MKTAG('p','i','t','m'), mov_read_pitm },
9309 { MKTAG('e','v','c','C'), mov_read_glbl },
9310 { MKTAG('i','d','a','t'), mov_read_idat },
9311 { MKTAG('i','m','i','r'), mov_read_imir },
9312 { MKTAG('i','r','e','f'), mov_read_iref },
9313 { MKTAG('i','s','p','e'), mov_read_ispe },
9314 { MKTAG('i','r','o','t'), mov_read_irot },
9315 { MKTAG('i','p','r','p'), mov_read_iprp },
9316 { MKTAG('i','i','n','f'), mov_read_iinf },
9317 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
9318 { MKTAG('l','h','v','C'), mov_read_lhvc },
9319 { MKTAG('l','v','c','C'), mov_read_glbl },
9320 #if CONFIG_IAMFDEC
9321 { MKTAG('i','a','c','b'), mov_read_iacb },
9322 #endif
9323 { 0, NULL }
9324 };
9325
9326 6308 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9327 {
9328 6308 int64_t total_size = 0;
9329 MOVAtom a;
9330 int i;
9331
9332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6308 times.
6308 if (c->atom_depth > 10) {
9333 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
9334 return AVERROR_INVALIDDATA;
9335 }
9336 6308 c->atom_depth ++;
9337
9338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6308 times.
6308 if (atom.size < 0)
9339 atom.size = INT64_MAX;
9340
2/2
✓ Branch 0 taken 18086 times.
✓ Branch 1 taken 5828 times.
23914 while (total_size <= atom.size - 8) {
9341 18086 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
9342 18086 a.size = avio_rb32(pb);
9343 18086 a.type = avio_rl32(pb);
9344
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 18082 times.
18086 if (avio_feof(pb))
9345 4 break;
9346
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) ||
9347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18082 times.
18082 a.type == MKTAG('h','o','o','v')) &&
9348 a.size >= 8 &&
9349 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
9350 uint32_t type;
9351 avio_skip(pb, 4);
9352 type = avio_rl32(pb);
9353 if (avio_feof(pb))
9354 break;
9355 avio_seek(pb, -8, SEEK_CUR);
9356 if (type == MKTAG('m','v','h','d') ||
9357 type == MKTAG('c','m','o','v')) {
9358 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
9359 a.type = MKTAG('m','o','o','v');
9360 }
9361 }
9362
2/2
✓ Branch 0 taken 15396 times.
✓ Branch 1 taken 2686 times.
18082 if (atom.type != MKTAG('r','o','o','t') &&
9363
2/2
✓ Branch 0 taken 13999 times.
✓ Branch 1 taken 1397 times.
15396 atom.type != MKTAG('m','o','o','v')) {
9364
1/2
✓ Branch 0 taken 13999 times.
✗ Branch 1 not taken.
13999 if (a.type == MKTAG('t','r','a','k') ||
9365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13999 times.
13999 a.type == MKTAG('m','d','a','t')) {
9366 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
9367 avio_skip(pb, -8);
9368 c->atom_depth --;
9369 476 return 0;
9370 }
9371 }
9372 18082 total_size += 8;
9373
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 */
9374 23 a.size = avio_rb64(pb) - 8;
9375 23 total_size += 8;
9376 }
9377 18082 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
9378 18082 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
9379
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 18077 times.
18082 if (a.size == 0) {
9380 5 a.size = atom.size - total_size + 8;
9381 }
9382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18082 times.
18082 if (a.size < 0)
9383 break;
9384 18082 a.size -= 8;
9385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18082 times.
18082 if (a.size < 0)
9386 break;
9387 18082 a.size = FFMIN(a.size, atom.size - total_size);
9388
9389
2/2
✓ Branch 0 taken 822560 times.
✓ Branch 1 taken 1833 times.
824393 for (i = 0; mov_default_parse_table[i].type; i++)
9390
2/2
✓ Branch 0 taken 16249 times.
✓ Branch 1 taken 806311 times.
822560 if (mov_default_parse_table[i].type == a.type) {
9391 16249 parse = mov_default_parse_table[i].parse;
9392 16249 break;
9393 }
9394
9395 // container is user data
9396
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') ||
9397
2/2
✓ Branch 0 taken 292 times.
✓ Branch 1 taken 1367 times.
1659 atom.type == MKTAG('i','l','s','t')))
9398 466 parse = mov_read_udta_string;
9399
9400 // Supports parsing the QuickTime Metadata Keys.
9401 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
9402
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 &&
9403
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 atom.type == MKTAG('m','e','t','a') &&
9404
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 a.type == MKTAG('k','e','y','s') &&
9405
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 c->meta_keys_count == 0) {
9406 11 parse = mov_read_keys;
9407 }
9408
9409
2/2
✓ Branch 0 taken 1356 times.
✓ Branch 1 taken 16726 times.
18082 if (!parse) { /* skip leaf atoms data */
9410 1356 avio_skip(pb, a.size);
9411 } else {
9412 16726 int64_t start_pos = avio_tell(pb);
9413 int64_t left;
9414 16726 int err = parse(c, pb, a);
9415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16726 times.
16726 if (err < 0) {
9416 c->atom_depth --;
9417 return err;
9418 }
9419
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 &&
9420
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) ||
9421 2772 start_pos + a.size == avio_size(pb))) {
9422
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)
9423 8 c->next_root_atom = start_pos + a.size;
9424 476 c->atom_depth --;
9425 476 return 0;
9426 }
9427 16250 left = a.size - avio_tell(pb) + start_pos;
9428
2/2
✓ Branch 0 taken 1302 times.
✓ Branch 1 taken 14948 times.
16250 if (left > 0) /* skip garbage at atom end */
9429 1302 avio_skip(pb, left);
9430
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14946 times.
14948 else if (left < 0) {
9431 2 av_log(c->fc, AV_LOG_WARNING,
9432 "overread end of atom '%s' by %"PRId64" bytes\n",
9433 2 av_fourcc2str(a.type), -left);
9434 2 avio_seek(pb, left, SEEK_CUR);
9435 }
9436 }
9437
9438 17606 total_size += a.size;
9439 }
9440
9441
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)
9442 102 avio_skip(pb, atom.size - total_size);
9443
9444 5832 c->atom_depth --;
9445 5832 return 0;
9446 }
9447
9448 7203 static int mov_probe(const AVProbeData *p)
9449 {
9450 int64_t offset;
9451 uint32_t tag;
9452 7203 int score = 0;
9453 7203 int moov_offset = -1;
9454
9455 /* check file header */
9456 7203 offset = 0;
9457 8872 for (;;) {
9458 int64_t size;
9459 16075 int minsize = 8;
9460 /* ignore invalid offset */
9461
2/2
✓ Branch 0 taken 7203 times.
✓ Branch 1 taken 8872 times.
16075 if ((offset + 8ULL) > (unsigned int)p->buf_size)
9462 7203 break;
9463 8872 size = AV_RB32(p->buf + offset);
9464
3/4
✓ Branch 0 taken 518 times.
✓ Branch 1 taken 8354 times.
✓ Branch 2 taken 518 times.
✗ Branch 3 not taken.
8872 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
9465 518 size = AV_RB64(p->buf+offset + 8);
9466 518 minsize = 16;
9467
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 8299 times.
8354 } else if (size == 0) {
9468 55 size = p->buf_size - offset;
9469 }
9470
2/2
✓ Branch 0 taken 397 times.
✓ Branch 1 taken 8475 times.
8872 if (size < minsize) {
9471 397 offset += 4;
9472 397 continue;
9473 }
9474 8475 tag = AV_RL32(p->buf + offset + 4);
9475
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 7171 times.
8475 switch(tag) {
9476 /* check for obvious tags */
9477 123 case MKTAG('m','o','o','v'):
9478 123 moov_offset = offset + 4;
9479 951 case MKTAG('m','d','a','t'):
9480 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
9481 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
9482 case MKTAG('f','t','y','p'):
9483
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 519 times.
951 if (tag == MKTAG('f','t','y','p') &&
9484
1/2
✓ Branch 0 taken 432 times.
✗ Branch 1 not taken.
432 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
9485
1/2
✓ Branch 0 taken 432 times.
✗ Branch 1 not taken.
432 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
9486
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 426 times.
432 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
9487 )) {
9488 6 score = FFMAX(score, 5);
9489 } else {
9490 945 score = AVPROBE_SCORE_MAX;
9491 }
9492 951 break;
9493 /* those are more common words, so rate then a bit less */
9494 352 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
9495 case MKTAG('w','i','d','e'):
9496 case MKTAG('f','r','e','e'):
9497 case MKTAG('j','u','n','k'):
9498 case MKTAG('p','i','c','t'):
9499 352 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
9500 352 break;
9501 case MKTAG(0x82,0x82,0x7f,0x7d):
9502 score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
9503 break;
9504 1 case MKTAG('s','k','i','p'):
9505 case MKTAG('u','u','i','d'):
9506 case MKTAG('p','r','f','l'):
9507 /* if we only find those cause probedata is too small at least rate them */
9508 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
9509 1 break;
9510 }
9511
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8475 times.
8475 if (size > INT64_MAX - offset)
9512 break;
9513 8475 offset += size;
9514 }
9515
4/4
✓ Branch 0 taken 463 times.
✓ Branch 1 taken 6740 times.
✓ Branch 2 taken 123 times.
✓ Branch 3 taken 340 times.
7203 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
9516 /* moov atom in the header - we should make sure that this is not a
9517 * MOV-packed MPEG-PS */
9518 123 offset = moov_offset;
9519
9520
2/2
✓ Branch 0 taken 120608 times.
✓ Branch 1 taken 123 times.
120731 while (offset < (p->buf_size - 16)) { /* Sufficient space */
9521 /* We found an actual hdlr atom */
9522
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 120476 times.
120608 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
9523
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 111 times.
132 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
9524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
9525 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
9526 /* We found a media handler reference atom describing an
9527 * MPEG-PS-in-MOV, return a
9528 * low score to force expanding the probe window until
9529 * mpegps_probe finds what it needs */
9530 return 5;
9531 } else {
9532 /* Keep looking */
9533 120608 offset += 2;
9534 }
9535 }
9536 }
9537
9538 7203 return score;
9539 }
9540
9541 // must be done after parsing all trak because there's no order requirement
9542 2 static void mov_read_chapters(AVFormatContext *s)
9543 {
9544 2 MOVContext *mov = s->priv_data;
9545 MOVStreamContext *sc;
9546 int64_t cur_pos;
9547 int i, j;
9548 int chapter_track;
9549
9550
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
9551 2 AVStream *st = NULL;
9552 2 FFStream *sti = NULL;
9553 2 chapter_track = mov->chapter_tracks[j];
9554
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
9555 4 sc = mov->fc->streams[i]->priv_data;
9556
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
9557 2 st = s->streams[i];
9558 2 break;
9559 }
9560 }
9561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
9562 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
9563 continue;
9564 }
9565 2 sti = ffstream(st);
9566
9567 2 sc = st->priv_data;
9568 2 cur_pos = avio_tell(sc->pb);
9569
9570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
9571 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
9572 if (!st->attached_pic.data && sti->nb_index_entries) {
9573 // Retrieve the first frame, if possible
9574 AVIndexEntry *sample = &sti->index_entries[0];
9575 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9576 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
9577 goto finish;
9578 }
9579
9580 if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
9581 goto finish;
9582 }
9583 } else {
9584 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
9585 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
9586 2 st->discard = AVDISCARD_ALL;
9587
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
9588 8 AVIndexEntry *sample = &sti->index_entries[i];
9589
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;
9590 uint8_t *title;
9591 uint16_t ch;
9592 int len, title_len;
9593
9594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
9595 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
9596 end = AV_NOPTS_VALUE;
9597 }
9598
9599
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9600 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
9601 goto finish;
9602 }
9603
9604 // the first two bytes are the length of the title
9605 8 len = avio_rb16(sc->pb);
9606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
9607 continue;
9608 8 title_len = 2*len + 1;
9609
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
9610 goto finish;
9611
9612 // The samples could theoretically be in any encoding if there's an encd
9613 // atom following, but in practice are only utf-8 or utf-16, distinguished
9614 // instead by the presence of a BOM
9615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
9616 title[0] = 0;
9617 } else {
9618 8 ch = avio_rb16(sc->pb);
9619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
9620 avio_get_str16be(sc->pb, len, title, title_len);
9621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
9622 avio_get_str16le(sc->pb, len, title, title_len);
9623 else {
9624 8 AV_WB16(title, ch);
9625
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)
9626 title[len] = 0;
9627 else
9628 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
9629 }
9630 }
9631
9632 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
9633 8 av_freep(&title);
9634 }
9635 }
9636 2 finish:
9637 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
9638 }
9639 2 }
9640
9641 19 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
9642 int64_t value, int flags)
9643 {
9644 AVTimecode tc;
9645 char buf[AV_TIMECODE_STR_SIZE];
9646 19 AVRational rate = st->avg_frame_rate;
9647 19 int ret = av_timecode_init(&tc, rate, flags, 0, s);
9648
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
9649 return ret;
9650 19 av_dict_set(&st->metadata, "timecode",
9651 19 av_timecode_make_string(&tc, buf, value), 0);
9652 19 return 0;
9653 }
9654
9655 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
9656 {
9657 MOVStreamContext *sc = st->priv_data;
9658 FFStream *const sti = ffstream(st);
9659 char buf[AV_TIMECODE_STR_SIZE];
9660 int64_t cur_pos = avio_tell(sc->pb);
9661 int hh, mm, ss, ff, drop;
9662
9663 if (!sti->nb_index_entries)
9664 return -1;
9665
9666 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9667 avio_skip(s->pb, 13);
9668 hh = avio_r8(s->pb);
9669 mm = avio_r8(s->pb);
9670 ss = avio_r8(s->pb);
9671 drop = avio_r8(s->pb);
9672 ff = avio_r8(s->pb);
9673 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
9674 hh, mm, ss, drop ? ';' : ':', ff);
9675 av_dict_set(&st->metadata, "timecode", buf, 0);
9676
9677 avio_seek(sc->pb, cur_pos, SEEK_SET);
9678 return 0;
9679 }
9680
9681 19 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
9682 {
9683 19 MOVStreamContext *sc = st->priv_data;
9684 19 FFStream *const sti = ffstream(st);
9685 19 int flags = 0;
9686 19 int64_t cur_pos = avio_tell(sc->pb);
9687 int64_t value;
9688 19 AVRational tc_rate = st->avg_frame_rate;
9689 19 int tmcd_nb_frames = sc->tmcd_nb_frames;
9690 int rounded_tc_rate;
9691
9692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!sti->nb_index_entries)
9693 return -1;
9694
9695
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)
9696 return -1;
9697
9698 19 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9699 19 value = avio_rb32(s->pb);
9700
9701
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13 times.
19 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
9702
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
9703
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
9704
9705 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
9706 * not the case) and thus assume "frame number format" instead of QT one.
9707 * No sample with tmcd track can be found with a QT timecode at the moment,
9708 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
9709 * format). */
9710
9711 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
9712 * we multiply the frame number with the quotient.
9713 * See tickets #9492, #9710. */
9714 19 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
9715 /* Work around files where tmcd_nb_frames is rounded down from frame rate
9716 * instead of up. See ticket #5978. */
9717
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
9718
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
9719 10 tmcd_nb_frames = rounded_tc_rate;
9720 19 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
9721
9722 19 parse_timecode_in_framenum_format(s, st, value, flags);
9723
9724 19 avio_seek(sc->pb, cur_pos, SEEK_SET);
9725 19 return 0;
9726 }
9727
9728 1037 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
9729 int i;
9730
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;
9731
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 4 times.
76 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
9732 72 av_encryption_info_free((*index)->encrypted_samples[i]);
9733 }
9734 4 av_freep(&(*index)->encrypted_samples);
9735 4 av_freep(&(*index)->auxiliary_info_sizes);
9736 4 av_freep(&(*index)->auxiliary_offsets);
9737 4 av_freep(index);
9738 }
9739
9740 670 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
9741 {
9742 670 MOVStreamContext *sc = st->priv_data;
9743
9744
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) {
9745 40 st->priv_data = NULL;
9746 40 return;
9747 }
9748
9749 630 av_freep(&sc->tts_data);
9750
2/2
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 630 times.
1223 for (int i = 0; i < sc->drefs_count; i++) {
9751 593 av_freep(&sc->drefs[i].path);
9752 593 av_freep(&sc->drefs[i].dir);
9753 }
9754 630 av_freep(&sc->drefs);
9755
9756 630 sc->drefs_count = 0;
9757
9758
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 616 times.
630 if (!sc->pb_is_copied)
9759 14 ff_format_io_close(s, &sc->pb);
9760
9761 630 sc->pb = NULL;
9762 630 av_freep(&sc->chunk_offsets);
9763 630 av_freep(&sc->stsc_data);
9764 630 av_freep(&sc->sample_sizes);
9765 630 av_freep(&sc->keyframes);
9766 630 av_freep(&sc->ctts_data);
9767 630 av_freep(&sc->stts_data);
9768 630 av_freep(&sc->sdtp_data);
9769 630 av_freep(&sc->stps_data);
9770 630 av_freep(&sc->elst_data);
9771 630 av_freep(&sc->rap_group);
9772 630 av_freep(&sc->sync_group);
9773 630 av_freep(&sc->sgpd_sync);
9774 630 av_freep(&sc->sample_offsets);
9775 630 av_freep(&sc->open_key_samples);
9776 630 av_freep(&sc->display_matrix);
9777 630 av_freep(&sc->index_ranges);
9778
9779
2/2
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 37 times.
630 if (sc->extradata)
9780
2/2
✓ Branch 0 taken 604 times.
✓ Branch 1 taken 593 times.
1197 for (int i = 0; i < sc->stsd_count; i++)
9781 604 av_free(sc->extradata[i]);
9782 630 av_freep(&sc->extradata);
9783 630 av_freep(&sc->extradata_size);
9784
9785 630 mov_free_encryption_index(&sc->cenc.encryption_index);
9786 630 av_encryption_info_free(sc->cenc.default_encrypted_sample);
9787 630 av_aes_ctr_free(sc->cenc.aes_ctr);
9788
9789 630 av_freep(&sc->stereo3d);
9790 630 av_freep(&sc->spherical);
9791 630 av_freep(&sc->mastering);
9792 630 av_freep(&sc->coll);
9793 630 av_freep(&sc->ambient);
9794
9795 #if CONFIG_IAMFDEC
9796
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 620 times.
630 if (sc->iamf)
9797 10 ff_iamf_read_deinit(sc->iamf);
9798 #endif
9799 630 av_freep(&sc->iamf);
9800 }
9801
9802 492 static int mov_read_close(AVFormatContext *s)
9803 {
9804 492 MOVContext *mov = s->priv_data;
9805 int i, j;
9806
9807
2/2
✓ Branch 0 taken 670 times.
✓ Branch 1 taken 492 times.
1162 for (i = 0; i < s->nb_streams; i++) {
9808 670 AVStream *st = s->streams[i];
9809
9810 670 mov_free_stream_context(s, st);
9811 }
9812
9813 492 av_freep(&mov->dv_demux);
9814 492 avformat_free_context(mov->dv_fctx);
9815 492 mov->dv_fctx = NULL;
9816
9817
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 481 times.
492 if (mov->meta_keys) {
9818
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i < mov->meta_keys_count; i++) {
9819 58 av_freep(&mov->meta_keys[i]);
9820 }
9821 11 av_freep(&mov->meta_keys);
9822 }
9823
9824 492 av_freep(&mov->trex_data);
9825 492 av_freep(&mov->bitrates);
9826
9827
2/2
✓ Branch 0 taken 389 times.
✓ Branch 1 taken 492 times.
881 for (i = 0; i < mov->frag_index.nb_items; i++) {
9828 389 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
9829
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++) {
9830 407 mov_free_encryption_index(&frag[j].encryption_index);
9831 }
9832 389 av_freep(&mov->frag_index.item[i].stream_info);
9833 }
9834 492 av_freep(&mov->frag_index.item);
9835
9836 492 av_freep(&mov->aes_decrypt);
9837 492 av_freep(&mov->chapter_tracks);
9838
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 492 times.
522 for (i = 0; i < mov->nb_heif_item; i++) {
9839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!mov->heif_item[i])
9840 continue;
9841 30 av_freep(&mov->heif_item[i]->name);
9842 30 av_freep(&mov->heif_item[i]->icc_profile);
9843 30 av_freep(&mov->heif_item[i]);
9844 }
9845 492 av_freep(&mov->heif_item);
9846
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 492 times.
498 for (i = 0; i < mov->nb_heif_grid; i++) {
9847 6 av_freep(&mov->heif_grid[i].tile_id_list);
9848 6 av_freep(&mov->heif_grid[i].tile_idx_list);
9849 6 av_freep(&mov->heif_grid[i].tile_item_list);
9850 }
9851 492 av_freep(&mov->heif_grid);
9852
9853 492 return 0;
9854 }
9855
9856 16 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
9857 {
9858 int i;
9859
9860
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 for (i = 0; i < s->nb_streams; i++) {
9861 24 AVStream *st = s->streams[i];
9862 24 MOVStreamContext *sc = st->priv_data;
9863
9864
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
9865
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 sc->timecode_track == tmcd_id)
9866 14 return 1;
9867 }
9868 2 return 0;
9869 }
9870
9871 /* look for a tmcd track not referenced by any video track, and export it globally */
9872 492 static void export_orphan_timecode(AVFormatContext *s)
9873 {
9874 int i;
9875
9876
2/2
✓ Branch 0 taken 667 times.
✓ Branch 1 taken 490 times.
1157 for (i = 0; i < s->nb_streams; i++) {
9877 667 AVStream *st = s->streams[i];
9878
9879
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') &&
9880 16 !tmcd_is_referenced(s, i + 1)) {
9881 2 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
9882
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (tcr) {
9883 2 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
9884 2 break;
9885 }
9886 }
9887 }
9888 492 }
9889
9890 static int read_tfra(MOVContext *mov, AVIOContext *f)
9891 {
9892 int version, fieldlength, i, j;
9893 int64_t pos = avio_tell(f);
9894 uint32_t size = avio_rb32(f);
9895 unsigned track_id, item_count;
9896
9897 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
9898 return 1;
9899 }
9900 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
9901
9902 version = avio_r8(f);
9903 avio_rb24(f);
9904 track_id = avio_rb32(f);
9905 fieldlength = avio_rb32(f);
9906 item_count = avio_rb32(f);
9907 for (i = 0; i < item_count; i++) {
9908 int64_t time, offset;
9909 int index;
9910 MOVFragmentStreamInfo * frag_stream_info;
9911
9912 if (avio_feof(f)) {
9913 return AVERROR_INVALIDDATA;
9914 }
9915
9916 if (version == 1) {
9917 time = avio_rb64(f);
9918 offset = avio_rb64(f);
9919 } else {
9920 time = avio_rb32(f);
9921 offset = avio_rb32(f);
9922 }
9923
9924 // The first sample of each stream in a fragment is always a random
9925 // access sample. So it's entry in the tfra can be used as the
9926 // initial PTS of the fragment.
9927 index = update_frag_index(mov, offset);
9928 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
9929 if (frag_stream_info &&
9930 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
9931 frag_stream_info->first_tfra_pts = time;
9932
9933 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
9934 avio_r8(f);
9935 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
9936 avio_r8(f);
9937 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
9938 avio_r8(f);
9939 }
9940
9941 avio_seek(f, pos + size, SEEK_SET);
9942 return 0;
9943 }
9944
9945 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
9946 {
9947 int64_t stream_size = avio_size(f);
9948 int64_t original_pos = avio_tell(f);
9949 int64_t seek_ret;
9950 int ret = -1;
9951 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
9952 ret = seek_ret;
9953 goto fail;
9954 }
9955 c->mfra_size = avio_rb32(f);
9956 c->have_read_mfra_size = 1;
9957 if (!c->mfra_size || c->mfra_size > stream_size) {
9958 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
9959 goto fail;
9960 }
9961 if ((seek_ret = avio_seek(f, -((int64_t) c->mfra_size), SEEK_CUR)) < 0) {
9962 ret = seek_ret;
9963 goto fail;
9964 }
9965 if (avio_rb32(f) != c->mfra_size) {
9966 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
9967 goto fail;
9968 }
9969 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
9970 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
9971 goto fail;
9972 }
9973 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
9974 do {
9975 ret = read_tfra(c, f);
9976 if (ret < 0)
9977 goto fail;
9978 } while (!ret);
9979 ret = 0;
9980 c->frag_index.complete = 1;
9981 fail:
9982 seek_ret = avio_seek(f, original_pos, SEEK_SET);
9983 if (seek_ret < 0) {
9984 av_log(c->fc, AV_LOG_ERROR,
9985 "failed to seek back after looking for mfra\n");
9986 ret = seek_ret;
9987 }
9988 return ret;
9989 }
9990
9991 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
9992 const HEIFItem *item)
9993 {
9994 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
9995 AV_PKT_DATA_ICC_PROFILE,
9996 item->icc_profile_size, 0);
9997 if (!sd)
9998 return AVERROR(ENOMEM);
9999
10000 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
10001
10002 return 0;
10003 }
10004
10005 4 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10006 const HEIFItem *item)
10007 {
10008 int32_t *matrix;
10009 4 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data,
10010 nb_coded_side_data,
10011 AV_PKT_DATA_DISPLAYMATRIX,
10012 9 * sizeof(*matrix), 0);
10013
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sd)
10014 return AVERROR(ENOMEM);
10015
10016 4 matrix = (int32_t*)sd->data;
10017 /* rotation is in the counter-clockwise direction whereas
10018 * av_display_rotation_set() expects its argument to be
10019 * oriented clockwise, so we need to negate it. */
10020 4 av_display_rotation_set(matrix, -item->rotation);
10021 4 av_display_matrix_flip(matrix, item->hflip, item->vflip);
10022
10023 4 return 0;
10024 }
10025
10026 2 static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid,
10027 AVStreamGroupTileGrid *tile_grid)
10028 {
10029 2 MOVContext *c = s->priv_data;
10030 2 const HEIFItem *item = grid->item;
10031 2 int64_t offset = 0, pos = avio_tell(s->pb);
10032 2 int x = 0, y = 0, i = 0;
10033 int tile_rows, tile_cols;
10034 int flags, size;
10035
10036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10037 av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
10038 return AVERROR_PATCHWELCOME;
10039 }
10040
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (item->is_idat_relative) {
10041
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!c->idat_offset) {
10042 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
10043 return AVERROR_INVALIDDATA;
10044 }
10045 2 offset = c->idat_offset;
10046 }
10047
10048 2 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10049
10050 2 avio_r8(s->pb); /* version */
10051 2 flags = avio_r8(s->pb);
10052
10053 2 tile_rows = avio_r8(s->pb) + 1;
10054 2 tile_cols = avio_r8(s->pb) + 1;
10055 /* actual width and height of output image */
10056
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);
10057
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);
10058
10059 /* ICC profile */
10060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (item->icc_profile_size) {
10061 int ret = set_icc_profile_from_item(&tile_grid->coded_side_data,
10062 &tile_grid->nb_coded_side_data, item);
10063 if (ret < 0)
10064 return ret;
10065 }
10066 /* rotation */
10067
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) {
10068 int ret = set_display_matrix_from_item(&tile_grid->coded_side_data,
10069 &tile_grid->nb_coded_side_data, item);
10070 if (ret < 0)
10071 return ret;
10072 }
10073
10074 2 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
10075 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
10076
10077 2 avio_seek(s->pb, pos, SEEK_SET);
10078
10079 2 size = tile_rows * tile_cols;
10080 2 tile_grid->nb_tiles = grid->nb_tiles;
10081
10082
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tile_grid->nb_tiles != size)
10083 return AVERROR_INVALIDDATA;
10084
10085
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < tile_cols; i++)
10086 4 tile_grid->coded_width += grid->tile_item_list[i]->width;
10087
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < size; i += tile_cols)
10088 4 tile_grid->coded_height += grid->tile_item_list[i]->height;
10089
10090 2 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!tile_grid->offsets)
10092 return AVERROR(ENOMEM);
10093
10094
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 while (y < tile_grid->coded_height) {
10095 4 int left_col = i;
10096
10097
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 while (x < tile_grid->coded_width) {
10098
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (i == tile_grid->nb_tiles)
10099 return AVERROR_INVALIDDATA;
10100
10101 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10102 8 tile_grid->offsets[i].horizontal = x;
10103 8 tile_grid->offsets[i].vertical = y;
10104
10105 8 x += grid->tile_item_list[i++]->width;
10106 }
10107
10108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (x > tile_grid->coded_width) {
10109 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10110 return AVERROR_INVALIDDATA;
10111 }
10112
10113 4 x = 0;
10114 4 y += grid->tile_item_list[left_col]->height;
10115 }
10116
10117
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) {
10118 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10119 return AVERROR_INVALIDDATA;
10120 }
10121
10122 2 return 0;
10123 }
10124
10125 4 static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid,
10126 AVStreamGroupTileGrid *tile_grid)
10127 {
10128 4 MOVContext *c = s->priv_data;
10129 4 const HEIFItem *item = grid->item;
10130 uint16_t canvas_fill_value[4];
10131 4 int64_t offset = 0, pos = avio_tell(s->pb);
10132 4 int ret = 0, flags;
10133
10134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10135 av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
10136 return AVERROR_PATCHWELCOME;
10137 }
10138
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
10139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
10140 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
10141 return AVERROR_INVALIDDATA;
10142 }
10143 4 offset = c->idat_offset;
10144 }
10145
10146 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10147
10148 4 avio_r8(s->pb); /* version */
10149 4 flags = avio_r8(s->pb);
10150
10151
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10152 16 canvas_fill_value[i] = avio_rb16(s->pb);
10153 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
10154 4 canvas_fill_value[0], canvas_fill_value[1],
10155 4 canvas_fill_value[2], canvas_fill_value[3]);
10156
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10157 16 tile_grid->background[i] = canvas_fill_value[i];
10158
10159 /* actual width and height of output image */
10160 4 tile_grid->width =
10161
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);
10162 4 tile_grid->height =
10163
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);
10164
10165 /* rotation */
10166
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) {
10167 int ret = set_display_matrix_from_item(&tile_grid->coded_side_data,
10168 &tile_grid->nb_coded_side_data, item);
10169 if (ret < 0)
10170 return ret;
10171 }
10172
10173 /* ICC profile */
10174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (item->icc_profile_size) {
10175 int ret = set_icc_profile_from_item(&tile_grid->coded_side_data,
10176 &tile_grid->nb_coded_side_data, item);
10177 if (ret < 0)
10178 return ret;
10179 }
10180
10181 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
10182 tile_grid->width, tile_grid->height);
10183
10184 4 tile_grid->nb_tiles = grid->nb_tiles;
10185 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
10187 ret = AVERROR(ENOMEM);
10188 goto fail;
10189 }
10190
10191
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
10192 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10193
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);
10194
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);
10195 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
10196 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
10197 8 i, tile_grid->offsets[i].idx,
10198 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
10199 }
10200
10201 4 fail:
10202 4 avio_seek(s->pb, pos, SEEK_SET);
10203
10204 4 return ret;
10205 }
10206
10207 6 static int mov_parse_tiles(AVFormatContext *s)
10208 {
10209 6 MOVContext *mov = s->priv_data;
10210
10211
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (int i = 0; i < mov->nb_heif_grid; i++) {
10212 6 AVStreamGroup *stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
10213 AVStreamGroupTileGrid *tile_grid;
10214 6 const HEIFGrid *grid = &mov->heif_grid[i];
10215 6 int err, loop = 1;
10216
10217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!stg)
10218 return AVERROR(ENOMEM);
10219
10220 6 stg->id = grid->item->item_id;
10221 6 tile_grid = stg->params.tile_grid;
10222
10223
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (int j = 0; j < grid->nb_tiles; j++) {
10224 16 int tile_id = grid->tile_id_list[j];
10225 int k;
10226
10227
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 for (k = 0; k < mov->nb_heif_item; k++) {
10228 30 HEIFItem *item = mov->heif_item[k];
10229 AVStream *st;
10230
10231
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)
10232 14 continue;
10233 16 st = item->st;
10234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!st) {
10235 av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
10236 "reference a stream\n",
10237 tile_id, grid->item->item_id);
10238 ff_remove_stream_group(s, stg);
10239 loop = 0;
10240 break;
10241 }
10242
10243 16 grid->tile_item_list[j] = item;
10244 16 grid->tile_idx_list[j] = stg->nb_streams;
10245
10246 16 err = avformat_stream_group_add_stream(stg, st);
10247
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (err < 0) {
10248 int l;
10249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
10250 return err;
10251
10252
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_streams; l++)
10253
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->streams[l]->index == st->index)
10254 2 break;
10255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_streams);
10256 2 grid->tile_idx_list[j] = l;
10257 }
10258
10259
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
16 if (item->item_id != mov->primary_item_id)
10260 10 st->disposition |= AV_DISPOSITION_DEPENDENT;
10261 16 break;
10262 }
10263
10264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (k == mov->nb_heif_item) {
10265 av_assert0(loop);
10266 av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
10267 "exist\n",
10268 tile_id, grid->item->item_id);
10269 ff_remove_stream_group(s, stg);
10270 loop = 0;
10271 }
10272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!loop)
10273 break;
10274 }
10275
10276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!loop)
10277 continue;
10278
10279
2/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
6 switch (grid->item->type) {
10280 2 case MKTAG('g','r','i','d'):
10281 2 err = read_image_grid(s, grid, tile_grid);
10282 2 break;
10283 4 case MKTAG('i','o','v','l'):
10284 4 err = read_image_iovl(s, grid, tile_grid);
10285 4 break;
10286 default:
10287 av_assert0(0);
10288 }
10289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10290 return err;
10291
10292
10293
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (grid->item->name)
10294 6 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
10295
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (grid->item->item_id == mov->primary_item_id)
10296 2 stg->disposition |= AV_DISPOSITION_DEFAULT;
10297 }
10298
10299 6 return 0;
10300 }
10301
10302 12 static int mov_parse_heif_items(AVFormatContext *s)
10303 {
10304 12 MOVContext *mov = s->priv_data;
10305 int err;
10306
10307
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 for (int i = 0; i < mov->nb_heif_item; i++) {
10308 30 HEIFItem *item = mov->heif_item[i];
10309 MOVStreamContext *sc;
10310 AVStream *st;
10311 30 int64_t offset = 0;
10312
10313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!item)
10314 continue;
10315
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 23 times.
30 if (!item->st) {
10316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (item->item_id == mov->thmb_item_id) {
10317 av_log(s, AV_LOG_ERROR, "HEIF thumbnail doesn't reference a stream\n");
10318 return AVERROR_INVALIDDATA;
10319 }
10320 7 continue;
10321 }
10322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (item->is_idat_relative) {
10323 if (!mov->idat_offset) {
10324 av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
10325 return AVERROR_INVALIDDATA;
10326 }
10327 offset = mov->idat_offset;
10328 }
10329
10330 23 st = item->st;
10331 23 sc = st->priv_data;
10332 23 st->codecpar->width = item->width;
10333 23 st->codecpar->height = item->height;
10334
10335 23 err = sanity_checks(s, sc, item->item_id);
10336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (err)
10337 return AVERROR_INVALIDDATA;
10338
10339 23 sc->sample_sizes[0] = item->extent_length;
10340 23 sc->chunk_offsets[0] = item->extent_offset + offset;
10341
10342
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 13 times.
23 if (item->item_id == mov->primary_item_id)
10343 10 st->disposition |= AV_DISPOSITION_DEFAULT;
10344
10345
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) {
10346 4 err = set_display_matrix_from_item(&st->codecpar->coded_side_data,
10347 4 &st->codecpar->nb_coded_side_data, item);
10348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
10349 return err;
10350 }
10351
10352 23 mov_build_index(mov, st);
10353 }
10354
10355
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (mov->nb_heif_grid) {
10356 6 err = mov_parse_tiles(s);
10357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10358 return err;
10359 }
10360
10361 12 return 0;
10362 }
10363
10364 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
10365 int first_index)
10366 {
10367 MOVStreamContext *sc = st->priv_data;
10368
10369 if (sc->tref_id < 0)
10370 return NULL;
10371
10372 for (int i = first_index; i < s->nb_streams; i++)
10373 if (s->streams[i]->id == sc->tref_id)
10374 return s->streams[i];
10375
10376 return NULL;
10377 }
10378
10379 492 static int mov_parse_lcevc_streams(AVFormatContext *s)
10380 {
10381 int err;
10382
10383
2/2
✓ Branch 0 taken 670 times.
✓ Branch 1 taken 492 times.
1162 for (int i = 0; i < s->nb_streams; i++) {
10384 AVStreamGroup *stg;
10385 670 AVStream *st = s->streams[i];
10386 AVStream *st_base;
10387 670 MOVStreamContext *sc = st->priv_data;
10388 670 int j = 0;
10389
10390 /* Find an enhancement stream. */
10391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 670 times.
670 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC ||
10392 !(sc->tref_flags & MOV_TREF_FLAG_ENHANCEMENT))
10393 670 continue;
10394
10395 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10396
10397 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
10398 if (!stg)
10399 return AVERROR(ENOMEM);
10400
10401 stg->id = st->id;
10402 stg->params.lcevc->width = st->codecpar->width;
10403 stg->params.lcevc->height = st->codecpar->height;
10404 st->codecpar->width = 0;
10405 st->codecpar->height = 0;
10406
10407 while (st_base = mov_find_reference_track(s, st, j)) {
10408 err = avformat_stream_group_add_stream(stg, st_base);
10409 if (err < 0)
10410 return err;
10411
10412 j = st_base->index + 1;
10413 }
10414 if (!j) {
10415 av_log(s, AV_LOG_ERROR, "Failed to find base stream for enhancement stream\n");
10416 return AVERROR_INVALIDDATA;
10417 }
10418
10419 err = avformat_stream_group_add_stream(stg, st);
10420 if (err < 0)
10421 return err;
10422
10423 stg->params.lcevc->lcevc_index = stg->nb_streams - 1;
10424 }
10425
10426 492 return 0;
10427 }
10428
10429 492 static int mov_read_header(AVFormatContext *s)
10430 {
10431 492 MOVContext *mov = s->priv_data;
10432 492 AVIOContext *pb = s->pb;
10433 int j, err;
10434 492 MOVAtom atom = { AV_RL32("root") };
10435 int i;
10436
10437
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) {
10438 av_log(s, AV_LOG_ERROR, "Invalid decryption key len %d expected %d\n",
10439 mov->decryption_key_len, AES_CTR_KEY_SIZE);
10440 return AVERROR(EINVAL);
10441 }
10442
10443 492 mov->fc = s;
10444 492 mov->trak_index = -1;
10445 492 mov->thmb_item_id = -1;
10446 492 mov->primary_item_id = -1;
10447 492 mov->cur_item_id = -1;
10448 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
10449
1/2
✓ Branch 0 taken 492 times.
✗ Branch 1 not taken.
492 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
10450 492 atom.size = avio_size(pb);
10451 else
10452 atom.size = INT64_MAX;
10453
10454 /* check MOV header */
10455 do {
10456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 492 times.
492 if (mov->moov_retry)
10457 avio_seek(pb, 0, SEEK_SET);
10458
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 492 times.
492 if ((err = mov_read_default(mov, pb, atom)) < 0) {
10459 av_log(s, AV_LOG_ERROR, "error reading header\n");
10460 return err;
10461 }
10462 984 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10463
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++);
10464
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) {
10465 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
10466 return AVERROR_INVALIDDATA;
10467 }
10468 492 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
10469
10470
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) {
10471 12 err = mov_parse_heif_items(s);
10472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (err < 0)
10473 return err;
10474 }
10475 // prevent iloc and iinf boxes from being parsed while reading packets.
10476 // this is needed because an iinf box may have been parsed but ignored
10477 // for having old infe boxes which create no streams.
10478 492 mov->found_iloc = mov->found_iinf = 1;
10479
10480
1/2
✓ Branch 0 taken 492 times.
✗ Branch 1 not taken.
492 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
10481
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)
10482 2 mov_read_chapters(s);
10483
2/2
✓ Branch 0 taken 670 times.
✓ Branch 1 taken 492 times.
1162 for (i = 0; i < s->nb_streams; i++)
10484
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 651 times.
670 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
10485 19 mov_read_timecode_track(s, s->streams[i]);
10486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 651 times.
651 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
10487 mov_read_rtmd_track(s, s->streams[i]);
10488 }
10489 }
10490
10491 /* copy timecode metadata from tmcd tracks to the related video streams */
10492
2/2
✓ Branch 0 taken 670 times.
✓ Branch 1 taken 492 times.
1162 for (i = 0; i < s->nb_streams; i++) {
10493 670 AVStream *st = s->streams[i];
10494 670 MOVStreamContext *sc = st->priv_data;
10495
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 652 times.
670 if (sc->timecode_track > 0) {
10496 AVDictionaryEntry *tcr;
10497 18 int tmcd_st_id = -1;
10498
10499
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 18 times.
66 for (j = 0; j < s->nb_streams; j++) {
10500 48 MOVStreamContext *sc2 = s->streams[j]->priv_data;
10501
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 30 times.
48 if (sc2->id == sc->timecode_track)
10502 18 tmcd_st_id = j;
10503 }
10504
10505
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)
10506 continue;
10507 18 tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
10508
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 if (tcr)
10509 16 av_dict_set(&st->metadata, "timecode", tcr->value, 0);
10510 }
10511 }
10512 492 export_orphan_timecode(s);
10513
10514 /* Create LCEVC stream groups. */
10515 492 err = mov_parse_lcevc_streams(s);
10516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 492 times.
492 if (err < 0)
10517 return err;
10518
10519
2/2
✓ Branch 0 taken 670 times.
✓ Branch 1 taken 492 times.
1162 for (i = 0; i < s->nb_streams; i++) {
10520 670 AVStream *st = s->streams[i];
10521 670 FFStream *const sti = ffstream(st);
10522 670 MOVStreamContext *sc = st->priv_data;
10523 670 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
10524 670 fix_timescale(mov, sc);
10525
2/2
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 389 times.
670 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
10526
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 165 times.
281 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
10527 116 sti->skip_samples = sc->start_pad;
10528 }
10529
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)
10530 301 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
10531 301 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
10532
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 662 times.
670 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
10533
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) {
10534 4 st->codecpar->width = sc->width;
10535 4 st->codecpar->height = sc->height;
10536 }
10537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
10538 st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
10539
10540 for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
10541 dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
10542
10543 err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
10544 if (err < 0)
10545 return err;
10546
10547 av_freep(&st->codecpar->extradata);
10548 st->codecpar->extradata_size = 0;
10549
10550 err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
10551 st->codecpar);
10552 if (err < 0)
10553 return err;
10554 }
10555 }
10556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 670 times.
670 if (mov->handbrake_version &&
10557 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
10558 st->codecpar->codec_id == AV_CODEC_ID_MP3) {
10559 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
10560 sti->need_parsing = AVSTREAM_PARSE_FULL;
10561 }
10562 }
10563
10564
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) {
10565
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 12 times.
29 for (i = 0; i < s->nb_streams; i++) {
10566 17 AVStream *st = s->streams[i];
10567 17 MOVStreamContext *sc = st->priv_data;
10568
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 3 times.
17 if (sc->duration_for_fps > 0) {
10569 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
10570 14 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
10571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (st->codecpar->bit_rate == INT64_MIN) {
10572 av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
10573 sc->data_size, sc->time_scale);
10574 st->codecpar->bit_rate = 0;
10575 if (s->error_recognition & AV_EF_EXPLODE)
10576 return AVERROR_INVALIDDATA;
10577 }
10578 }
10579 }
10580 }
10581
10582
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++) {
10583 if (mov->bitrates[i]) {
10584 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
10585 }
10586 }
10587
10588 492 ff_rfps_calculate(s);
10589
10590
2/2
✓ Branch 0 taken 670 times.
✓ Branch 1 taken 492 times.
1162 for (i = 0; i < s->nb_streams; i++) {
10591 670 AVStream *st = s->streams[i];
10592 670 MOVStreamContext *sc = st->priv_data;
10593
10594
3/3
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 338 times.
✓ Branch 2 taken 51 times.
670 switch (st->codecpar->codec_type) {
10595 281 case AVMEDIA_TYPE_AUDIO:
10596 281 err = ff_replaygain_export(st, s->metadata);
10597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 281 times.
281 if (err < 0)
10598 return err;
10599 281 break;
10600 338 case AVMEDIA_TYPE_VIDEO:
10601
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 330 times.
338 if (sc->display_matrix) {
10602
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,
10603 AV_PKT_DATA_DISPLAYMATRIX,
10604 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
10605 return AVERROR(ENOMEM);
10606
10607 8 sc->display_matrix = NULL;
10608 }
10609
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 334 times.
338 if (sc->stereo3d) {
10610
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,
10611 AV_PKT_DATA_STEREO3D,
10612 4 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
10613 return AVERROR(ENOMEM);
10614
10615 4 sc->stereo3d = NULL;
10616 }
10617
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 334 times.
338 if (sc->spherical) {
10618
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,
10619 AV_PKT_DATA_SPHERICAL,
10620 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
10621 return AVERROR(ENOMEM);
10622
10623 4 sc->spherical = NULL;
10624 }
10625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
338 if (sc->mastering) {
10626 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10627 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
10628 (uint8_t *)sc->mastering, sc->mastering_size, 0))
10629 return AVERROR(ENOMEM);
10630
10631 sc->mastering = NULL;
10632 }
10633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
338 if (sc->coll) {
10634 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10635 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
10636 (uint8_t *)sc->coll, sc->coll_size, 0))
10637 return AVERROR(ENOMEM);
10638
10639 sc->coll = NULL;
10640 }
10641
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 334 times.
338 if (sc->ambient) {
10642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10643 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
10644 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
10645 return AVERROR(ENOMEM);
10646
10647 4 sc->ambient = NULL;
10648 }
10649 338 break;
10650 }
10651 }
10652 492 ff_configure_buffers_for_index(s, AV_TIME_BASE);
10653
10654
2/2
✓ Branch 0 taken 389 times.
✓ Branch 1 taken 492 times.
881 for (i = 0; i < mov->frag_index.nb_items; i++)
10655
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)
10656 385 mov->frag_index.item[i].headers_read = 1;
10657
10658 492 return 0;
10659 }
10660
10661 103896 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
10662 {
10663 103896 AVIndexEntry *sample = NULL;
10664 103896 int64_t best_dts = INT64_MAX;
10665 int i;
10666 103896 MOVContext *mov = s->priv_data;
10667
2/4
✓ Branch 0 taken 103896 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 103896 times.
103896 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
10668
2/2
✓ Branch 0 taken 133986 times.
✓ Branch 1 taken 103896 times.
237882 for (i = 0; i < s->nb_streams; i++) {
10669 133986 AVStream *avst = s->streams[i];
10670 133986 FFStream *const avsti = ffstream(avst);
10671 133986 MOVStreamContext *msc = avst->priv_data;
10672
4/4
✓ Branch 0 taken 125748 times.
✓ Branch 1 taken 8238 times.
✓ Branch 2 taken 122471 times.
✓ Branch 3 taken 3277 times.
133986 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
10673 122471 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
10674 122471 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
10675
2/2
✓ Branch 0 taken 108661 times.
✓ Branch 1 taken 13810 times.
122471 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
10676 122471 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
10677
3/6
✓ Branch 0 taken 19062 times.
✓ Branch 1 taken 103409 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19062 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
122471 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
10678
1/2
✓ Branch 0 taken 19062 times.
✗ Branch 1 not taken.
19062 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10679
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 19062 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 19062 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 19062 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 16947 times.
✓ Branch 9 taken 2115 times.
19062 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
10680
4/4
✓ Branch 0 taken 8806 times.
✓ Branch 1 taken 8141 times.
✓ Branch 2 taken 2115 times.
✓ Branch 3 taken 8806 times.
19062 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
10681
2/2
✓ Branch 0 taken 714 times.
✓ Branch 1 taken 1401 times.
2115 (dtsdiff > AV_TIME_BASE && dts < best_dts)))))) {
10682 112264 sample = current_sample;
10683 112264 best_dts = dts;
10684 112264 *st = avst;
10685 }
10686 }
10687 }
10688 103896 return sample;
10689 }
10690
10691 9 static int should_retry(AVIOContext *pb, int error_code) {
10692
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))
10693 9 return 0;
10694
10695 return 1;
10696 }
10697
10698 42 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
10699 {
10700 int ret;
10701 42 MOVContext *mov = s->priv_data;
10702
10703
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)
10704 target = mov->frag_index.item[index].moof_offset;
10705
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) {
10706 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
10707 return AVERROR_INVALIDDATA;
10708 }
10709
10710 42 mov->next_root_atom = 0;
10711
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)
10712 42 index = search_frag_moof_offset(&mov->frag_index, target);
10713
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 &&
10714
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 mov->frag_index.item[index].moof_offset == target) {
10715
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (index + 1 < mov->frag_index.nb_items)
10716 35 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
10717
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (mov->frag_index.item[index].headers_read)
10718 35 return 0;
10719 3 mov->frag_index.item[index].headers_read = 1;
10720 }
10721
10722 7 mov->found_mdat = 0;
10723
10724 7 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
10725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
10726 return ret;
10727
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 3 times.
7 if (avio_feof(s->pb))
10728 4 return AVERROR_EOF;
10729 3 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
10730
10731 3 return 1;
10732 }
10733
10734 16 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
10735 {
10736 16 MOVStreamContext *sc = st->priv_data;
10737 uint8_t *side, *extradata;
10738 int extradata_size;
10739
10740 /* Save the current index. */
10741 16 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
10742
10743 /* Notify the decoder that extradata changed. */
10744 16 extradata_size = sc->extradata_size[sc->last_stsd_index];
10745 16 extradata = sc->extradata[sc->last_stsd_index];
10746
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) {
10747 13 side = av_packet_new_side_data(pkt,
10748 AV_PKT_DATA_NEW_EXTRADATA,
10749 extradata_size);
10750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!side)
10751 return AVERROR(ENOMEM);
10752 13 memcpy(side, extradata, extradata_size);
10753 }
10754
10755 16 return 0;
10756 }
10757
10758 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int size)
10759 {
10760 int new_size, ret;
10761
10762 if (size <= 8)
10763 return AVERROR_INVALIDDATA;
10764 new_size = ((size - 8) / 2) * 3;
10765 ret = av_new_packet(pkt, new_size);
10766 if (ret < 0)
10767 return ret;
10768
10769 avio_skip(pb, 8);
10770 for (int j = 0; j < new_size; j += 3) {
10771 pkt->data[j] = 0xFC;
10772 pkt->data[j+1] = avio_r8(pb);
10773 pkt->data[j+2] = avio_r8(pb);
10774 }
10775
10776 return 0;
10777 }
10778
10779 103365 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
10780 int64_t current_index, AVPacket *pkt)
10781 {
10782 103365 MOVStreamContext *sc = st->priv_data;
10783
10784 103365 pkt->stream_index = sc->ffindex;
10785 103365 pkt->dts = sample->timestamp;
10786
2/2
✓ Branch 0 taken 237 times.
✓ Branch 1 taken 103128 times.
103365 if (sample->flags & AVINDEX_DISCARD_FRAME) {
10787 237 pkt->flags |= AV_PKT_FLAG_DISCARD;
10788 }
10789
4/4
✓ Branch 0 taken 83484 times.
✓ Branch 1 taken 19881 times.
✓ Branch 2 taken 83472 times.
✓ Branch 3 taken 12 times.
103365 if (sc->stts_count && sc->tts_index < sc->tts_count)
10790 83472 pkt->duration = sc->tts_data[sc->tts_index].duration;
10791
3/4
✓ Branch 0 taken 3010 times.
✓ Branch 1 taken 100355 times.
✓ Branch 2 taken 3010 times.
✗ Branch 3 not taken.
103365 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
10792 3010 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
10793 } else {
10794
2/2
✓ Branch 0 taken 15798 times.
✓ Branch 1 taken 84557 times.
100355 if (pkt->duration == 0) {
10795 15798 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
10796
2/2
✓ Branch 0 taken 15725 times.
✓ Branch 1 taken 73 times.
15798 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
10797
2/2
✓ Branch 0 taken 15772 times.
✓ Branch 1 taken 26 times.
15798 if (next_dts >= pkt->dts)
10798 15772 pkt->duration = next_dts - pkt->dts;
10799 }
10800 100355 pkt->pts = pkt->dts;
10801 }
10802
10803
4/4
✓ Branch 0 taken 83484 times.
✓ Branch 1 taken 19881 times.
✓ Branch 2 taken 83472 times.
✓ Branch 3 taken 12 times.
103365 if (sc->tts_data && sc->tts_index < sc->tts_count) {
10804 /* update tts context */
10805 83472 sc->tts_sample++;
10806
1/2
✓ Branch 0 taken 83472 times.
✗ Branch 1 not taken.
83472 if (sc->tts_index < sc->tts_count &&
10807
1/2
✓ Branch 0 taken 83472 times.
✗ Branch 1 not taken.
83472 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
10808 83472 sc->tts_index++;
10809 83472 sc->tts_sample = 0;
10810 }
10811 }
10812
10813
4/4
✓ Branch 0 taken 1037 times.
✓ Branch 1 taken 102328 times.
✓ Branch 2 taken 905 times.
✓ Branch 3 taken 132 times.
103365 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
10814 905 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
10815 905 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
10816
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;
10817 }
10818 103365 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
10819 103365 pkt->pos = sample->pos;
10820
10821 /* Multiple stsd handling. */
10822
2/2
✓ Branch 0 taken 102574 times.
✓ Branch 1 taken 791 times.
103365 if (sc->stsc_data) {
10823
1/2
✓ Branch 0 taken 102574 times.
✗ Branch 1 not taken.
102574 if (sc->stsc_data[sc->stsc_index].id > 0 &&
10824
2/2
✓ Branch 0 taken 102551 times.
✓ Branch 1 taken 23 times.
102574 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
10825
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 102535 times.
102551 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
10826 16 int ret = mov_change_extradata(st, pkt);
10827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0)
10828 return ret;
10829 }
10830
10831 /* Update the stsc index for the next sample */
10832 102574 sc->stsc_sample++;
10833
2/2
✓ Branch 1 taken 55171 times.
✓ Branch 2 taken 47403 times.
102574 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
10834
2/2
✓ Branch 1 taken 1190 times.
✓ Branch 2 taken 53981 times.
55171 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
10835 1190 sc->stsc_index++;
10836 1190 sc->stsc_sample = 0;
10837 }
10838 }
10839
10840 103365 return 0;
10841 }
10842
10843 97036 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
10844 {
10845 97036 MOVContext *mov = s->priv_data;
10846 MOVStreamContext *sc;
10847 AVIndexEntry *sample;
10848 97036 AVStream *st = NULL;
10849 97036 FFStream *avsti = NULL;
10850 int64_t current_index;
10851 int ret;
10852 int i;
10853 97036 mov->fc = s;
10854 6860 retry:
10855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103896 times.
103896 if (s->pb->pos == 0) {
10856
10857 // Discard current fragment index
10858 if (mov->frag_index.allocated_size > 0) {
10859 for(int i = 0; i < mov->frag_index.nb_items; i++) {
10860 av_freep(&mov->frag_index.item[i].stream_info);
10861 }
10862 av_freep(&mov->frag_index.item);
10863 mov->frag_index.nb_items = 0;
10864 mov->frag_index.allocated_size = 0;
10865 mov->frag_index.current = -1;
10866 mov->frag_index.complete = 0;
10867 }
10868
10869 for (i = 0; i < s->nb_streams; i++) {
10870 AVStream *avst = s->streams[i];
10871 MOVStreamContext *msc = avst->priv_data;
10872
10873 // Clear current sample
10874 mov_current_sample_set(msc, 0);
10875 msc->tts_index = 0;
10876
10877 // Discard current index entries
10878 avsti = ffstream(avst);
10879 if (avsti->index_entries_allocated_size > 0) {
10880 av_freep(&avsti->index_entries);
10881 avsti->index_entries_allocated_size = 0;
10882 avsti->nb_index_entries = 0;
10883 }
10884 }
10885
10886 if ((ret = mov_switch_root(s, -1, -1)) < 0)
10887 return ret;
10888 }
10889 103896 sample = mov_find_next_sample(s, &st);
10890
6/6
✓ Branch 0 taken 103409 times.
✓ Branch 1 taken 487 times.
✓ Branch 2 taken 472 times.
✓ Branch 3 taken 102937 times.
✓ Branch 4 taken 35 times.
✓ Branch 5 taken 437 times.
103896 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
10891
2/2
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 42 times.
522 if (!mov->next_root_atom)
10892 480 return AVERROR_EOF;
10893
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)
10894 4 return ret;
10895 38 goto retry;
10896 }
10897 103374 sc = st->priv_data;
10898 /* must be done just before reading, to avoid infinite loop on sample */
10899 103374 current_index = sc->current_index;
10900 103374 mov_current_sample_inc(sc);
10901
10902
2/2
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 102937 times.
103374 if (mov->next_root_atom) {
10903 437 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
10904 437 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
10905 }
10906
10907
2/2
✓ Branch 0 taken 96552 times.
✓ Branch 1 taken 6822 times.
103374 if (st->discard != AVDISCARD_ALL) {
10908 96552 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
10909
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 96545 times.
96552 if (ret64 != sample->pos) {
10910 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
10911 sc->ffindex, sample->pos);
10912
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
10913 mov_current_sample_dec(sc);
10914
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
10915 7 return (int)ret64;
10916 }
10917 return AVERROR_INVALIDDATA;
10918 }
10919
10920
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96545 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96545 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
10921 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
10922 goto retry;
10923 }
10924
10925
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96545 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96545 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
10926 ret = get_eia608_packet(sc->pb, pkt, sample->size);
10927 #if CONFIG_IAMFDEC
10928
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 96490 times.
96545 else if (sc->iamf) {
10929 int64_t pts, dts, pos, duration;
10930 55 int flags, size = sample->size;
10931 55 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
10932 55 pts = pkt->pts; dts = pkt->dts;
10933 55 pos = pkt->pos; flags = pkt->flags;
10934 55 duration = pkt->duration;
10935
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) {
10936 275 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, pkt);
10937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
275 if (ret < 0) {
10938 if (should_retry(sc->pb, ret))
10939 mov_current_sample_dec(sc);
10940 return ret;
10941 }
10942 275 size -= ret;
10943 275 pkt->pts = pts; pkt->dts = dts;
10944 275 pkt->pos = pos; pkt->flags |= flags;
10945 275 pkt->duration = duration;
10946 275 ret = ff_buffer_packet(s, pkt);
10947 }
10948
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 if (!ret)
10949 55 return FFERROR_REDO;
10950 }
10951 #endif
10952 else
10953 96490 ret = av_get_packet(sc->pb, pkt, sample->size);
10954
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 96488 times.
96490 if (ret < 0) {
10955
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (should_retry(sc->pb, ret)) {
10956 mov_current_sample_dec(sc);
10957 }
10958 2 return ret;
10959 }
10960 #if CONFIG_DV_DEMUXER
10961
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96488 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96488 if (mov->dv_demux && sc->dv_audio_container) {
10962 ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
10963 av_packet_unref(pkt);
10964 if (ret < 0)
10965 return ret;
10966 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
10967 if (ret < 0)
10968 return ret;
10969 }
10970 #endif
10971
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 96470 times.
96488 if (sc->has_palette) {
10972 uint8_t *pal;
10973
10974 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
10975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
10976 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
10977 } else {
10978 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
10979 18 sc->has_palette = 0;
10980 }
10981 }
10982
4/6
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 96200 times.
✓ Branch 3 taken 288 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 288 times.
✗ Branch 6 not taken.
96488 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
10983
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 288 times.
288 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
10984 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
10985 }
10986 }
10987
10988 103310 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
10989
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103310 times.
103310 if (ret < 0)
10990 return ret;
10991
10992
2/2
✓ Branch 0 taken 6822 times.
✓ Branch 1 taken 96488 times.
103310 if (st->discard == AVDISCARD_ALL)
10993 6822 goto retry;
10994
10995
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96488 times.
96488 if (mov->aax_mode)
10996 aax_filter(pkt->data, pkt->size, mov);
10997
10998 96488 ret = cenc_filter(mov, st, sc, pkt, current_index);
10999
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96488 times.
96488 if (ret < 0) {
11000 return ret;
11001 }
11002
11003 96488 return 0;
11004 }
11005
11006 361 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
11007 {
11008 361 MOVContext *mov = s->priv_data;
11009 int index;
11010
11011
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 26 times.
361 if (!mov->frag_index.complete)
11012 335 return 0;
11013
11014 26 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
11015
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 22 times.
26 if (index < 0)
11016 4 index = 0;
11017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (!mov->frag_index.item[index].headers_read)
11018 return mov_switch_root(s, -1, index);
11019
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (index + 1 < mov->frag_index.nb_items)
11020 26 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11021
11022 26 return 0;
11023 }
11024
11025 static int is_open_key_sample(const MOVStreamContext *sc, int sample)
11026 {
11027 // TODO: a bisect search would scale much better
11028 for (int i = 0; i < sc->open_key_samples_count; i++) {
11029 const int oks = sc->open_key_samples[i];
11030 if (oks == sample)
11031 return 1;
11032 if (oks > sample) /* list is monotically increasing so we can stop early */
11033 break;
11034 }
11035 return 0;
11036 }
11037
11038 /*
11039 * Some key sample may be key frames but not IDR frames, so a random access to
11040 * them may not be allowed.
11041 */
11042 229 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
11043 {
11044 229 MOVStreamContext *sc = st->priv_data;
11045 229 FFStream *const sti = ffstream(st);
11046 int64_t key_sample_dts, key_sample_pts;
11047
11048
1/2
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
229 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
11049 229 return 1;
11050
11051 if (sample >= sc->sample_offsets_count)
11052 return 1;
11053
11054 key_sample_dts = sti->index_entries[sample].timestamp;
11055 key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
11056
11057 /*
11058 * If the sample needs to be presented before an open key sample, they may
11059 * not be decodable properly, even though they come after in decoding
11060 * order.
11061 */
11062 if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
11063 return 0;
11064
11065 return 1;
11066 }
11067
11068 361 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
11069 {
11070 361 MOVStreamContext *sc = st->priv_data;
11071 361 FFStream *const sti = ffstream(st);
11072 int sample, time_sample, ret, next_ts, requested_sample;
11073 unsigned int i;
11074
11075 // Here we consider timestamp to be PTS, hence try to offset it so that we
11076 // can search over the DTS timeline.
11077 361 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
11078
11079 361 ret = mov_seek_fragment(s, st, timestamp);
11080
1/2
✓ Branch 0 taken 361 times.
✗ Branch 1 not taken.
361 if (ret < 0)
11081 return ret;
11082
11083 for (;;) {
11084 361 sample = av_index_search_timestamp(st, timestamp, flags);
11085 361 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
11086
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)
11087 43 sample = 0;
11088
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 335 times.
361 if (sample < 0) /* not sure what to do */
11089 26 return AVERROR_INVALIDDATA;
11090
11091
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))
11092 break;
11093
11094 next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
11095 requested_sample = av_index_search_timestamp(st, next_ts, flags);
11096
11097 // If we've reached a different sample trying to find a good pts to
11098 // seek to, give up searching because we'll end up seeking back to
11099 // sample 0 on every seek.
11100 if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
11101 break;
11102
11103 timestamp = next_ts;
11104 }
11105
11106 335 mov_current_sample_set(sc, sample);
11107 335 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
11108 /* adjust time to sample index */
11109
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 125 times.
335 if (sc->tts_data) {
11110 210 time_sample = 0;
11111
1/2
✓ Branch 0 taken 60235 times.
✗ Branch 1 not taken.
60235 for (i = 0; i < sc->tts_count; i++) {
11112 60235 int next = time_sample + sc->tts_data[i].count;
11113
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 60025 times.
60235 if (next > sc->current_sample) {
11114 210 sc->tts_index = i;
11115 210 sc->tts_sample = sc->current_sample - time_sample;
11116 210 break;
11117 }
11118 60025 time_sample = next;
11119 }
11120 }
11121
11122 /* adjust stsd index */
11123
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 26 times.
335 if (sc->chunk_count) {
11124 309 time_sample = 0;
11125
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
381 for (i = 0; i < sc->stsc_count; i++) {
11126 381 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
11127
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 72 times.
381 if (next > sc->current_sample) {
11128 309 sc->stsc_index = i;
11129 309 sc->stsc_sample = sc->current_sample - time_sample;
11130 309 break;
11131 }
11132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
11133 72 time_sample = next;
11134 }
11135 }
11136
11137 335 return sample;
11138 }
11139
11140 335 static int64_t mov_get_skip_samples(AVStream *st, int sample)
11141 {
11142 335 MOVStreamContext *sc = st->priv_data;
11143 335 FFStream *const sti = ffstream(st);
11144 335 int64_t first_ts = sti->index_entries[0].timestamp;
11145 335 int64_t ts = sti->index_entries[sample].timestamp;
11146 int64_t off;
11147
11148
2/2
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 151 times.
335 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
11149 184 return 0;
11150
11151 /* compute skip samples according to stream start_pad, seek ts and first ts */
11152 151 off = av_rescale_q(ts - first_ts, st->time_base,
11153 151 (AVRational){1, st->codecpar->sample_rate});
11154 151 return FFMAX(sc->start_pad - off, 0);
11155 }
11156
11157 340 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
11158 {
11159 340 MOVContext *mc = s->priv_data;
11160 AVStream *st;
11161 FFStream *sti;
11162 int sample;
11163 int i;
11164
11165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 340 times.
340 if (stream_index >= s->nb_streams)
11166 return AVERROR_INVALIDDATA;
11167
11168 340 st = s->streams[stream_index];
11169 340 sti = ffstream(st);
11170 340 sample = mov_seek_stream(s, st, sample_time, flags);
11171
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 314 times.
340 if (sample < 0)
11172 26 return sample;
11173
11174
1/2
✓ Branch 0 taken 314 times.
✗ Branch 1 not taken.
314 if (mc->seek_individually) {
11175 /* adjust seek timestamp to found sample timestamp */
11176 314 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
11177 314 sti->skip_samples = mov_get_skip_samples(st, sample);
11178
11179
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 314 times.
649 for (i = 0; i < s->nb_streams; i++) {
11180 335 AVStream *const st = s->streams[i];
11181 335 FFStream *const sti = ffstream(st);
11182 int64_t timestamp;
11183
11184
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 21 times.
335 if (stream_index == i)
11185 314 continue;
11186
11187 21 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
11188 21 sample = mov_seek_stream(s, st, timestamp, flags);
11189
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (sample >= 0)
11190 21 sti->skip_samples = mov_get_skip_samples(st, sample);
11191 }
11192 } else {
11193 for (i = 0; i < s->nb_streams; i++) {
11194 MOVStreamContext *sc;
11195 st = s->streams[i];
11196 sc = st->priv_data;
11197 mov_current_sample_set(sc, 0);
11198 }
11199 while (1) {
11200 MOVStreamContext *sc;
11201 AVIndexEntry *entry = mov_find_next_sample(s, &st);
11202 if (!entry)
11203 return AVERROR_INVALIDDATA;
11204 sc = st->priv_data;
11205 if (sc->ffindex == stream_index && sc->current_sample == sample)
11206 break;
11207 mov_current_sample_inc(sc);
11208 }
11209 }
11210 314 return 0;
11211 }
11212
11213 #define OFFSET(x) offsetof(MOVContext, x)
11214 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
11215 static const AVOption mov_options[] = {
11216 {"use_absolute_path",
11217 "allow using absolute path when opening alias, this is a possible security issue",
11218 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
11219 0, 1, FLAGS},
11220 {"seek_streams_individually",
11221 "Seek each stream individually to the closest point",
11222 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
11223 0, 1, FLAGS},
11224 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
11225 0, 1, FLAGS},
11226 {"advanced_editlist",
11227 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
11228 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
11229 0, 1, FLAGS},
11230 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
11231 0, 1, FLAGS},
11232 {"use_mfra_for",
11233 "use mfra for fragment timestamps",
11234 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
11235 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
11236 .unit = "use_mfra_for"},
11237 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
11238 FLAGS, .unit = "use_mfra_for" },
11239 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
11240 FLAGS, .unit = "use_mfra_for" },
11241 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
11242 FLAGS, .unit = "use_mfra_for" },
11243 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
11244 0, 1, FLAGS},
11245 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
11246 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11247 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
11248 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11249 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
11250 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11251 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
11252 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11253 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
11254 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11255 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
11256 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
11257 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
11258 .flags = AV_OPT_FLAG_DECODING_PARAM },
11259 { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11260 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
11261 {.i64 = 0}, 0, 1, FLAGS },
11262 { "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 },
11263 { "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 },
11264
11265 { NULL },
11266 };
11267
11268 static const AVClass mov_class = {
11269 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
11270 .item_name = av_default_item_name,
11271 .option = mov_options,
11272 .version = LIBAVUTIL_VERSION_INT,
11273 };
11274
11275 const FFInputFormat ff_mov_demuxer = {
11276 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
11277 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
11278 .p.priv_class = &mov_class,
11279 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v,avif,heic,heif",
11280 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
11281 .priv_data_size = sizeof(MOVContext),
11282 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
11283 .read_probe = mov_probe,
11284 .read_header = mov_read_header,
11285 .read_packet = mov_read_packet,
11286 .read_close = mov_read_close,
11287 .read_seek = mov_read_seek,
11288 };
11289