FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2026-09-16 13:08:21
Exec Total Coverage
Lines: 4782 7473 64.0%
Functions: 192 231 83.1%
Branches: 2744 5053 54.3%

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 #include <stdlib.h>
32
33 #include "libavutil/attributes.h"
34 #include "libavutil/bprint.h"
35 #include "libavutil/channel_layout.h"
36 #include "libavutil/dovi_meta.h"
37 #include "libavutil/internal.h"
38 #include "libavutil/intreadwrite.h"
39 #include "libavutil/intfloat.h"
40 #include "libavutil/mathematics.h"
41 #include "libavutil/avassert.h"
42 #include "libavutil/avstring.h"
43 #include "libavutil/dict.h"
44 #include "libavutil/display.h"
45 #include "libavutil/mem.h"
46 #include "libavutil/opt.h"
47 #include "libavutil/aes.h"
48 #include "libavutil/aes_ctr.h"
49 #include "libavutil/pixdesc.h"
50 #include "libavutil/sha.h"
51 #include "libavutil/spherical.h"
52 #include "libavutil/stereo3d.h"
53 #include "libavutil/timecode.h"
54 #include "libavutil/uuid.h"
55 #include "libavcodec/ac3tab.h"
56 #include "libavcodec/exif.h"
57 #include "libavcodec/flac.h"
58 #include "libavcodec/hevc/hevc.h"
59 #include "libavcodec/mpegaudiodecheader.h"
60 #include "libavcodec/mlp_parse.h"
61 #include "avformat.h"
62 #include "internal.h"
63 #include "avio_internal.h"
64 #include "demux.h"
65 #include "dvdclut.h"
66 #include "iamf_parse.h"
67 #include "iamf_reader.h"
68 #include "dovi_isom.h"
69 #include "riff.h"
70 #include "isom.h"
71 #include "libavcodec/get_bits.h"
72 #include "id3v1.h"
73 #include "mov_chan.h"
74 #include "replaygain.h"
75
76 #if CONFIG_ZLIB
77 #include <zlib.h>
78 #endif
79
80 #include "qtpalette.h"
81
82 /* those functions parse an atom */
83 /* links atom IDs to parse functions */
84 typedef struct MOVParseTableEntry {
85 uint32_t type;
86 int (*parse)(MOVContext *ctx, AVIOContext *pb, MOVAtom atom);
87 } MOVParseTableEntry;
88
89 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom);
90 static int mov_read_mfra(MOVContext *c, AVIOContext *f);
91 static void mov_free_stream_context(AVFormatContext *s, AVStream *st);
92
93 32 static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
94 unsigned len, const char *key)
95 {
96 char buf[16];
97
98 32 short current, total = 0;
99 32 avio_rb16(pb); // unknown
100 32 current = avio_rb16(pb);
101
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (len >= 6)
102 32 total = avio_rb16(pb);
103
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 25 times.
32 if (!total)
104 7 snprintf(buf, sizeof(buf), "%d", current);
105 else
106 25 snprintf(buf, sizeof(buf), "%d/%d", current, total);
107 32 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
108 32 av_dict_set(&c->fc->metadata, key, buf, 0);
109
110 32 return 0;
111 }
112
113 static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
114 unsigned len, const char *key)
115 {
116 /* bypass padding bytes */
117 avio_r8(pb);
118 avio_r8(pb);
119 avio_r8(pb);
120
121 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
122 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
123
124 return 0;
125 }
126
127 30 static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
128 unsigned len, const char *key)
129 {
130 30 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
131 30 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
132
133 30 return 0;
134 }
135
136 12 static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
137 unsigned len, const char *key)
138 {
139 short genre;
140
141 12 avio_r8(pb); // unknown
142
143 12 genre = avio_r8(pb);
144
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (genre < 1 || genre > ID3v1_GENRE_MAX)
145 return 0;
146 12 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
147 12 av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
148
149 12 return 0;
150 }
151
152 static const uint32_t mac_to_unicode[128] = {
153 0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
154 0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
155 0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,
156 0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,
157 0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,
158 0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,
159 0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,
160 0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,
161 0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,
162 0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,
163 0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,
164 0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,
165 0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,
166 0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,
167 0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,
168 0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7,
169 };
170
171 398 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
172 char *dst, int dstlen)
173 {
174 398 char *p = dst;
175 398 char *end = dst+dstlen-1;
176 int i;
177
178
2/2
✓ Branch 0 taken 3341 times.
✓ Branch 1 taken 398 times.
3739 for (i = 0; i < len; i++) {
179 3341 uint8_t t, c = avio_r8(pb);
180
181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3341 times.
3341 if (p >= end)
182 continue;
183
184
2/2
✓ Branch 0 taken 3333 times.
✓ Branch 1 taken 8 times.
3341 if (c < 0x80)
185 3333 *p++ = c;
186
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 else if (p < end)
187
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✓ Branch 9 taken 8 times.
16 PUT_UTF8(mac_to_unicode[c-0x80], t, if (p < end) *p++ = t;);
188 }
189 398 *p = 0;
190 398 return p - dst;
191 }
192
193 /**
194 * Get the requested item.
195 */
196 166 static HEIFItem *get_heif_item(MOVContext *c, unsigned id)
197 {
198 166 HEIFItem *item = NULL;
199
200
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 12 times.
380 for (int i = 0; i < c->nb_heif_item; i++) {
201
3/4
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 214 times.
✓ Branch 3 taken 154 times.
368 if (!c->heif_item[i] || c->heif_item[i]->item_id != id)
202 214 continue;
203
204 154 item = c->heif_item[i];
205 154 break;
206 }
207
208 166 return item;
209 }
210
211 /**
212 * Get the current stream in the parsing process. This can either be the
213 * latest stream added to the context, or the stream referenced by an item.
214 */
215 283 static AVStream *get_curr_st(MOVContext *c)
216 {
217 283 AVStream *st = NULL;
218 HEIFItem *item;
219
220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 283 times.
283 if (c->fc->nb_streams < 1)
221 return NULL;
222
223
2/2
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 49 times.
283 if (c->cur_item_id == -1)
224 234 return c->fc->streams[c->fc->nb_streams-1];
225
226 49 item = get_heif_item(c, c->cur_item_id);
227
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 if (item)
228 49 st = item->st;
229
230 49 return st;
231 }
232
233 16 static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
234 {
235 AVStream *st;
236 MOVStreamContext *sc;
237 enum AVCodecID id;
238 int ret;
239
240
2/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
16 switch (type) {
241 9 case 0xd: id = AV_CODEC_ID_MJPEG; break;
242 7 case 0xe: id = AV_CODEC_ID_PNG; break;
243 case 0x1b: id = AV_CODEC_ID_BMP; break;
244 default:
245 av_log(c->fc, AV_LOG_WARNING, "Unknown cover type: 0x%x.\n", type);
246 avio_skip(pb, len);
247 return 0;
248 }
249
250 16 sc = av_mallocz(sizeof(*sc));
251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!sc)
252 return AVERROR(ENOMEM);
253 16 ret = ff_add_attached_pic(c->fc, NULL, pb, NULL, len);
254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0) {
255 av_free(sc);
256 return ret;
257 }
258 16 st = c->fc->streams[c->fc->nb_streams - 1];
259 16 st->priv_data = sc;
260 16 sc->id = st->id;
261 16 sc->refcount = 1;
262
263
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 if (st->attached_pic.size >= 8 && id != AV_CODEC_ID_BMP) {
264
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 9 times.
16 if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
265 7 id = AV_CODEC_ID_PNG;
266 } else {
267 9 id = AV_CODEC_ID_MJPEG;
268 }
269 }
270 16 st->codecpar->codec_id = id;
271
272 16 return 0;
273 }
274
275 // 3GPP TS 26.244
276 static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
277 {
278 char language[4] = { 0 };
279 char buf[200], place[100];
280 uint16_t langcode = 0;
281 double longitude, latitude, altitude;
282 const char *key = "location";
283
284 if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) {
285 av_log(c->fc, AV_LOG_ERROR, "loci too short\n");
286 return AVERROR_INVALIDDATA;
287 }
288
289 avio_skip(pb, 4); // version+flags
290 langcode = avio_rb16(pb);
291 ff_mov_lang_to_iso639(langcode, language);
292 len -= 6;
293
294 len -= avio_get_str(pb, len, place, sizeof(place));
295 if (len < 1) {
296 av_log(c->fc, AV_LOG_ERROR, "place name too long\n");
297 return AVERROR_INVALIDDATA;
298 }
299 avio_skip(pb, 1); // role
300 len -= 1;
301
302 if (len < 12) {
303 av_log(c->fc, AV_LOG_ERROR,
304 "loci too short (%u bytes left, need at least %d)\n", len, 12);
305 return AVERROR_INVALIDDATA;
306 }
307 longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
308 latitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
309 altitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
310
311 // Try to output in the same format as the ?xyz field
312 snprintf(buf, sizeof(buf), "%+08.4f%+09.4f", latitude, longitude);
313 if (altitude)
314 av_strlcatf(buf, sizeof(buf), "%+f", altitude);
315 av_strlcatf(buf, sizeof(buf), "/%s", place);
316
317 if (*language && strcmp(language, "und")) {
318 char key2[16];
319 snprintf(key2, sizeof(key2), "%s-%s", key, language);
320 av_dict_set(&c->fc->metadata, key2, buf, 0);
321 }
322 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
323 return av_dict_set(&c->fc->metadata, key, buf, 0);
324 }
325
326 static int mov_metadata_hmmt(MOVContext *c, AVIOContext *pb, unsigned len)
327 {
328 int i, n_hmmt;
329
330 if (len < 2)
331 return 0;
332 if (c->ignore_chapters)
333 return 0;
334
335 n_hmmt = avio_rb32(pb);
336 if (n_hmmt > len / 4)
337 return AVERROR_INVALIDDATA;
338 for (i = 0; i < n_hmmt && !pb->eof_reached; i++) {
339 int moment_time = avio_rb32(pb);
340 avpriv_new_chapter(c->fc, i, av_make_q(1, 1000), moment_time, AV_NOPTS_VALUE, NULL);
341 }
342 if (avio_feof(pb))
343 return AVERROR_INVALIDDATA;
344 return 0;
345 }
346
347 550 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
348 {
349 550 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
350 550 char key2[32], language[4] = {0};
351 550 char *str = NULL;
352 550 const char *key = NULL;
353 550 uint16_t langcode = 0;
354 550 uint32_t data_type = 0, str_size_alloc;
355 uint64_t str_size;
356 550 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
357 550 int raw = 0;
358 550 int num = 0;
359 AVDictionary **metadata;
360
361
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 521 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
550 if (c->trak_index >= 0 && c->trak_index < c->fc->nb_streams)
362 29 metadata = &c->fc->streams[c->trak_index]->metadata;
363 else
364 521 metadata = &c->fc->metadata;
365
366
27/75
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 157 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 15 times.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 16 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 12 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 taken 5 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 15 times.
✗ 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 not taken.
✓ Branch 34 taken 16 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 40 taken 21 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 20 times.
✓ Branch 43 taken 3 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 12 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 4 times.
✓ Branch 48 taken 20 times.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✓ Branch 52 taken 2 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 5 times.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✓ Branch 59 taken 5 times.
✓ Branch 60 taken 5 times.
✓ Branch 61 taken 47 times.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✓ Branch 68 taken 63 times.
✓ Branch 69 taken 73 times.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✓ Branch 73 taken 3 times.
✓ Branch 74 taken 5 times.
550 switch (atom.type) {
367 3 case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break;
368 3 case MKTAG( '@','P','R','Q'): key = "quicktime_version"; raw = 1; break;
369 2 case MKTAG( 'X','M','P','_'):
370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->export_xmp) { key = "xmp"; raw = 1; } break;
371 16 case MKTAG( 'a','A','R','T'): key = "album_artist"; break;
372 case MKTAG( 'a','k','I','D'): key = "account_type";
373 parse = mov_metadata_int8_no_padding; break;
374 case MKTAG( 'a','p','I','D'): key = "account_id"; break;
375 case MKTAG( 'c','a','t','g'): key = "category"; break;
376 15 case MKTAG( 'c','p','i','l'): key = "compilation";
377 15 parse = mov_metadata_int8_no_padding; break;
378 2 case MKTAG( 'c','p','r','t'): key = "copyright"; break;
379 case MKTAG( 'd','e','s','c'): key = "description"; break;
380 16 case MKTAG( 'd','i','s','k'): key = "disc";
381 16 parse = mov_metadata_track_or_disc_number; break;
382 case MKTAG( 'e','g','i','d'): key = "episode_uid";
383 parse = mov_metadata_int8_no_padding; break;
384 case MKTAG( 'F','I','R','M'): key = "firmware"; raw = 1; break;
385 12 case MKTAG( 'g','n','r','e'): key = "genre";
386 12 parse = mov_metadata_gnre; break;
387 case MKTAG( 'h','d','v','d'): key = "hd_video";
388 parse = mov_metadata_int8_no_padding; break;
389 case MKTAG( 'H','M','M','T'):
390 return mov_metadata_hmmt(c, pb, atom.size);
391 case MKTAG( 'k','e','y','w'): key = "keywords"; break;
392 case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
393 case MKTAG( 'l','o','c','i'):
394 return mov_metadata_loci(c, pb, atom.size);
395 case MKTAG( 'm','a','n','u'): key = "make"; break;
396 case MKTAG( 'm','o','d','l'): key = "model"; break;
397 5 case MKTAG( 'n','a','m','e'): key = "name"; break;
398 case MKTAG( 'p','c','s','t'): key = "podcast";
399 parse = mov_metadata_int8_no_padding; break;
400 15 case MKTAG( 'p','g','a','p'): key = "gapless_playback";
401 15 parse = mov_metadata_int8_no_padding; break;
402 case MKTAG( 'p','u','r','d'): key = "purchase_date"; break;
403 case MKTAG( 'r','t','n','g'): key = "rating";
404 parse = mov_metadata_int8_no_padding; break;
405 case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break;
406 case MKTAG( 's','o','a','l'): key = "sort_album"; break;
407 case MKTAG( 's','o','a','r'): key = "sort_artist"; break;
408 case MKTAG( 's','o','c','o'): key = "sort_composer"; break;
409 case MKTAG( 's','o','n','m'): key = "sort_name"; break;
410 case MKTAG( 's','o','s','n'): key = "sort_show"; break;
411 case MKTAG( 's','t','i','k'): key = "media_type";
412 parse = mov_metadata_int8_no_padding; break;
413 16 case MKTAG( 't','r','k','n'): key = "track";
414 16 parse = mov_metadata_track_or_disc_number; break;
415 case MKTAG( 't','v','e','n'): key = "episode_id"; break;
416 case MKTAG( 't','v','e','s'): key = "episode_sort";
417 parse = mov_metadata_int8_bypass_padding; break;
418 case MKTAG( 't','v','n','n'): key = "network"; break;
419 case MKTAG( 't','v','s','h'): key = "show"; break;
420 case MKTAG( 't','v','s','n'): key = "season_number";
421 parse = mov_metadata_int8_bypass_padding; break;
422 21 case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
423 case MKTAG(0xa9,'P','R','D'): key = "producer"; break;
424 20 case MKTAG(0xa9,'a','l','b'): key = "album"; break;
425 3 case MKTAG(0xa9,'a','u','t'): key = "artist"; break;
426 case MKTAG(0xa9,'c','h','p'): key = "chapter"; break;
427 12 case MKTAG(0xa9,'c','m','t'): key = "comment"; break;
428 case MKTAG(0xa9,'c','o','m'): key = "composer"; break;
429 4 case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
430 20 case MKTAG(0xa9,'d','a','y'): key = "date"; break;
431 case MKTAG(0xa9,'d','i','r'): key = "director"; break;
432 case MKTAG(0xa9,'d','i','s'): key = "disclaimer"; break;
433 case MKTAG(0xa9,'e','d','1'): key = "edit_date"; break;
434 2 case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
435 case MKTAG(0xa9,'f','m','t'): key = "original_format"; break;
436 5 case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
437 case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
438 case MKTAG(0xa9,'h','s','t'): key = "host_computer"; break;
439 case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
440 case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
441 5 case MKTAG(0xa9,'m','a','k'): key = "make"; break;
442 5 case MKTAG(0xa9,'m','o','d'): key = "model"; break;
443 47 case MKTAG(0xa9,'n','a','m'): key = "title"; break;
444 case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break;
445 case MKTAG(0xa9,'p','r','d'): key = "producer"; break;
446 case MKTAG(0xa9,'p','r','f'): key = "performers"; break;
447 case MKTAG(0xa9,'r','e','q'): key = "playback_requirements"; break;
448 case MKTAG(0xa9,'s','r','c'): key = "original_source"; break;
449 case MKTAG(0xa9,'s','t','3'): key = "subtitle"; break;
450 63 case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
451 73 case MKTAG(0xa9,'t','o','o'): key = "encoder"; break;
452 case MKTAG(0xa9,'t','r','k'): key = "track"; break;
453 case MKTAG(0xa9,'u','r','l'): key = "URL"; break;
454 case MKTAG(0xa9,'w','r','n'): key = "warning"; break;
455 3 case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
456 5 case MKTAG(0xa9,'x','y','z'): key = "location"; break;
457 }
458 7 retry:
459
3/4
✓ Branch 0 taken 373 times.
✓ Branch 1 taken 184 times.
✓ Branch 2 taken 373 times.
✗ Branch 3 not taken.
914 if (c->itunes_metadata && atom.size > 8) {
460 373 int data_size = avio_rb32(pb);
461 373 int tag = avio_rl32(pb);
462
3/6
✓ Branch 0 taken 373 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 373 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 373 times.
✗ Branch 5 not taken.
373 if (tag == MKTAG('d','a','t','a') && data_size <= atom.size && data_size >= 16) {
463 373 data_type = avio_rb32(pb); // type
464 373 avio_rb32(pb); // unknown
465 373 str_size = data_size - 16;
466 373 atom.size -= 16;
467
468
5/6
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 276 times.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 38 times.
✓ Branch 4 taken 59 times.
✗ Branch 5 not taken.
373 if (!key && c->found_hdlr_mdta && c->meta_keys) {
469 59 uint32_t index = av_bswap32(atom.type); // BE number has been read as LE
470
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) {
471 59 key = c->meta_keys[index];
472 } else if (atom.type != MKTAG('c', 'o', 'v', 'r')) {
473 av_log(c->fc, AV_LOG_WARNING,
474 "The index of 'data' is out of range: %"PRId32" < 1 or >= %d.\n",
475 index, c->meta_keys_count);
476 }
477 }
478
4/4
✓ Branch 0 taken 357 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 335 times.
✓ Branch 3 taken 22 times.
373 if (atom.type == MKTAG('c', 'o', 'v', 'r') ||
479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 335 times.
335 (key && !strcmp(key, "com.apple.quicktime.artwork"))) {
480 16 int ret = mov_read_covr(c, pb, data_type, str_size);
481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0) {
482 av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
483 return ret;
484 }
485 16 atom.size -= str_size;
486
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (atom.size > 8)
487 2 goto retry;
488 14 return ret;
489 }
490 } else return 0;
491
8/10
✓ Branch 0 taken 166 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 120 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 46 times.
✓ Branch 6 taken 120 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 109 times.
✓ Branch 9 taken 11 times.
184 } else if (atom.size > 4 && (key || c->export_all) && !c->itunes_metadata && !raw) {
492 109 str_size = avio_rb16(pb); // string length
493
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 104 times.
109 if (str_size > atom.size) {
494 5 raw = 1;
495 5 avio_seek(pb, -2, SEEK_CUR);
496 5 av_log(c->fc, AV_LOG_WARNING, "UDTA parsing failed retrying raw\n");
497 5 goto retry;
498 }
499 104 langcode = avio_rb16(pb);
500 104 ff_mov_lang_to_iso639(langcode, language);
501 104 atom.size -= 4;
502 } else
503 75 str_size = atom.size;
504
505
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 536 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
536 if (c->export_all && !key) {
506 key = av_fourcc_make_string(tmp_key, atom.type);
507 }
508
509
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 450 times.
536 if (!key)
510 86 return 0;
511
2/4
✓ Branch 0 taken 450 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 450 times.
450 if (atom.size < 0 || str_size >= INT_MAX/2)
512 return AVERROR_INVALIDDATA;
513
514 // Allocates enough space if data_type is a int32 or float32 number, otherwise
515 // worst-case requirement for output string in case of utf8 coded input
516
3/4
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 405 times.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
450 num = (data_type >= 21 && data_type <= 23);
517
4/4
✓ Branch 0 taken 405 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 394 times.
✓ Branch 3 taken 11 times.
450 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
518 450 str = av_mallocz(str_size_alloc);
519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 450 times.
450 if (!str)
520 return AVERROR(ENOMEM);
521
522
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 376 times.
450 if (parse)
523 74 parse(c, pb, str_size, key);
524 else {
525
8/10
✓ Branch 0 taken 365 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 365 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 105 times.
✓ Branch 5 taken 260 times.
✓ Branch 6 taken 91 times.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 91 times.
376 if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
526 14 mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
527
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 360 times.
362 } else if (data_type == 21) { // BE signed integer, variable size
528 2 int val = 0;
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (str_size == 1)
530 val = (int8_t)avio_r8(pb);
531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 2)
532 val = (int16_t)avio_rb16(pb);
533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 3)
534 val = ((int32_t)(avio_rb24(pb)<<8))>>8;
535
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (str_size == 4)
536 2 val = (int32_t)avio_rb32(pb);
537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
538 av_log(c->fc, AV_LOG_ERROR,
539 "Failed to store the number (%d) in string.\n", val);
540 av_free(str);
541 return AVERROR_INVALIDDATA;
542 }
543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 360 times.
360 } else if (data_type == 22) { // BE unsigned integer, variable size
544 unsigned int val = 0;
545 if (str_size == 1)
546 val = avio_r8(pb);
547 else if (str_size == 2)
548 val = avio_rb16(pb);
549 else if (str_size == 3)
550 val = avio_rb24(pb);
551 else if (str_size == 4)
552 val = avio_rb32(pb);
553 if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
554 av_log(c->fc, AV_LOG_ERROR,
555 "Failed to store the number (%u) in string.\n", val);
556 av_free(str);
557 return AVERROR_INVALIDDATA;
558 }
559
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 347 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
373 } else if (data_type == 23 && str_size >= 4) { // BE float32
560 13 float val = av_int2float(avio_rb32(pb));
561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
562 av_log(c->fc, AV_LOG_ERROR,
563 "Failed to store the float32 number (%f) in string.\n", val);
564 av_free(str);
565 return AVERROR_INVALIDDATA;
566 }
567
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 347 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
347 } else if (data_type > 1 && data_type != 4) {
568 // data_type can be 0 if not set at all above. data_type 1 means
569 // UTF8 and 4 means "UTF8 sort". For any other type (UTF16 or e.g.
570 // a picture), don't return it blindly in a string that is supposed
571 // to be UTF8 text.
572 av_log(c->fc, AV_LOG_WARNING, "Skipping unhandled metadata %s of type %"PRIu32"\n", key, data_type);
573 av_free(str);
574 return 0;
575 } else {
576 347 int ret = ffio_read_size(pb, str, str_size);
577
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 347 times.
347 if (ret < 0) {
578 av_free(str);
579 return ret;
580 }
581 347 str[str_size] = 0;
582 }
583 376 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
584
4/4
✓ Branch 0 taken 261 times.
✓ Branch 1 taken 115 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 260 times.
376 if (c->itunes_metadata && av_dict_get(*metadata, key, NULL, 0))
585 1 av_dict_set(metadata, key, ";", AV_DICT_APPEND);
586
2/2
✓ Branch 0 taken 261 times.
✓ Branch 1 taken 115 times.
376 av_dict_set(metadata, key, str, c->itunes_metadata ? AV_DICT_APPEND : 0);
587
4/4
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 272 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 67 times.
376 if (*language && strcmp(language, "und")) {
588 37 snprintf(key2, sizeof(key2), "%s-%s", key, language);
589 37 av_dict_set(metadata, key2, str, 0);
590 }
591
2/2
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 238 times.
376 if (!strcmp(key, "encoder")) {
592 int major, minor, micro;
593
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 137 times.
138 if (sscanf(str, "HandBrake %d.%d.%d", &major, &minor, &micro) == 3) {
594 1 c->handbrake_version = 1000000*major + 1000*minor + micro;
595 }
596 }
597
598 376 atom.size -= str_size;
599 376 av_freep(&str);
600
601 // Read remaining data atoms for multi-valued iTunes tags (e.g. multiple
602 // artists stored as multiple data atoms within one tag atom), consistent
603 // with the existing covr path.
604 // Note: multiple sibling tag atoms with the same key (e.g. three separate
605 // ©ART atoms under ilst) are handled by the AV_DICT_APPEND logic above,
606 // since mov_read_udta_string() is called once per tag atom.
607
3/4
✓ Branch 0 taken 261 times.
✓ Branch 1 taken 115 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 261 times.
376 if (c->itunes_metadata && atom.size > 8)
608 goto retry;
609 }
610
611 450 av_freep(&str);
612 450 return 0;
613 }
614
615 12 static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
616 {
617 int64_t start;
618 int i, nb_chapters, str_len, version;
619 char str[256+1];
620 int ret;
621
622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->ignore_chapters)
623 return 0;
624
625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if ((atom.size -= 5) < 0)
626 return 0;
627
628 12 version = avio_r8(pb);
629 12 avio_rb24(pb);
630
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (version)
631 12 avio_rb32(pb); // ???
632 12 nb_chapters = avio_r8(pb);
633
634
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
30 for (i = 0; i < nb_chapters; i++) {
635
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size < 9)
636 return 0;
637
638 18 start = avio_rb64(pb);
639 18 str_len = avio_r8(pb);
640
641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if ((atom.size -= 9+str_len) < 0)
642 return 0;
643
644 18 ret = ffio_read_size(pb, str, str_len);
645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (ret < 0)
646 return ret;
647 18 str[str_len] = 0;
648 18 avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
649 }
650 12 return 0;
651 }
652
653 #define MIN_DATA_ENTRY_BOX_SIZE 12
654 712 static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
655 {
656 AVStream *st;
657 MOVStreamContext *sc;
658 int entries, i, j;
659
660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (c->fc->nb_streams < 1)
661 return 0;
662 712 st = c->fc->streams[c->fc->nb_streams-1];
663 712 sc = st->priv_data;
664
665 712 avio_rb32(pb); // version + flags
666 712 entries = avio_rb32(pb);
667
1/2
✓ Branch 0 taken 712 times.
✗ Branch 1 not taken.
712 if (!entries ||
668
1/2
✓ Branch 0 taken 712 times.
✗ Branch 1 not taken.
712 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 entries >= UINT_MAX / sizeof(*sc->drefs))
670 return AVERROR_INVALIDDATA;
671
672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 for (i = 0; i < sc->drefs_count; i++) {
673 MOVDref *dref = &sc->drefs[i];
674 av_freep(&dref->path);
675 av_freep(&dref->dir);
676 }
677 712 av_free(sc->drefs);
678 712 sc->drefs_count = 0;
679 712 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (!sc->drefs)
681 return AVERROR(ENOMEM);
682 712 sc->drefs_count = entries;
683
684
2/2
✓ Branch 0 taken 712 times.
✓ Branch 1 taken 712 times.
1424 for (i = 0; i < entries; i++) {
685 712 MOVDref *dref = &sc->drefs[i];
686 712 uint32_t size = avio_rb32(pb);
687 712 int64_t next = avio_tell(pb);
688
689
3/6
✓ Branch 0 taken 712 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 712 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 712 times.
712 if (size < 12 || next < 0 || next > INT64_MAX - size)
690 return AVERROR_INVALIDDATA;
691
692 712 next += size - 4;
693
694 712 dref->type = avio_rl32(pb);
695 712 avio_rb32(pb); // version + flags
696
697
3/4
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 575 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 137 times.
712 if (dref->type == MKTAG('a','l','i','s') && size > 150) {
698 /* macintosh alias record */
699 uint16_t volume_len, len;
700 int16_t type;
701 int ret;
702
703 avio_skip(pb, 10);
704
705 volume_len = avio_r8(pb);
706 volume_len = FFMIN(volume_len, 27);
707 ret = ffio_read_size(pb, dref->volume, 27);
708 if (ret < 0)
709 return ret;
710 dref->volume[volume_len] = 0;
711 av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
712
713 avio_skip(pb, 12);
714
715 len = avio_r8(pb);
716 len = FFMIN(len, 63);
717 ret = ffio_read_size(pb, dref->filename, 63);
718 if (ret < 0)
719 return ret;
720 dref->filename[len] = 0;
721 av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
722
723 avio_skip(pb, 16);
724
725 /* read next level up_from_alias/down_to_target */
726 dref->nlvl_from = avio_rb16(pb);
727 dref->nlvl_to = avio_rb16(pb);
728 av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
729 dref->nlvl_from, dref->nlvl_to);
730
731 avio_skip(pb, 16);
732
733 for (type = 0; type != -1 && avio_tell(pb) < next; ) {
734 if (avio_feof(pb))
735 return AVERROR_EOF;
736 type = avio_rb16(pb);
737 len = avio_rb16(pb);
738 av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
739 if (len&1)
740 len += 1;
741 if (type == 2) { // absolute path
742 av_free(dref->path);
743 dref->path = av_mallocz(len+1);
744 if (!dref->path)
745 return AVERROR(ENOMEM);
746
747 ret = ffio_read_size(pb, dref->path, len);
748 if (ret < 0) {
749 av_freep(&dref->path);
750 return ret;
751 }
752 if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
753 len -= volume_len;
754 memmove(dref->path, dref->path+volume_len, len);
755 dref->path[len] = 0;
756 }
757 // trim string of any ending zeros
758 for (j = len - 1; j >= 0; j--) {
759 if (dref->path[j] == 0)
760 len--;
761 else
762 break;
763 }
764 for (j = 0; j < len; j++)
765 if (dref->path[j] == ':' || dref->path[j] == 0)
766 dref->path[j] = '/';
767 av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
768 } else if (type == 0) { // directory name
769 av_free(dref->dir);
770 dref->dir = av_malloc(len+1);
771 if (!dref->dir)
772 return AVERROR(ENOMEM);
773
774 ret = ffio_read_size(pb, dref->dir, len);
775 if (ret < 0) {
776 av_freep(&dref->dir);
777 return ret;
778 }
779 dref->dir[len] = 0;
780 for (j = 0; j < len; j++)
781 if (dref->dir[j] == ':')
782 dref->dir[j] = '/';
783 av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
784 } else
785 avio_skip(pb, len);
786 }
787 } else {
788 712 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
789 dref->type, size);
790 712 entries--;
791 712 i--;
792 }
793 712 avio_seek(pb, next, SEEK_SET);
794 }
795 712 return 0;
796 }
797
798 1303 static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
799 {
800 AVStream *st;
801 uint32_t type;
802 uint32_t ctype;
803 int64_t title_size;
804 char *title_str;
805 int ret;
806
807 1303 avio_r8(pb); /* version */
808 1303 avio_rb24(pb); /* flags */
809
810 /* component type */
811 1303 ctype = avio_rl32(pb);
812 1303 type = avio_rl32(pb); /* component subtype */
813
814 1303 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
815 1303 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
816
817
2/2
✓ Branch 0 taken 205 times.
✓ Branch 1 taken 1098 times.
1303 if (c->trak_index < 0) { // meta not inside a trak
818
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 194 times.
205 if (type == MKTAG('m','d','t','a')) {
819 11 c->found_hdlr_mdta = 1;
820 }
821 205 return 0;
822 }
823
824 1098 st = c->fc->streams[c->fc->nb_streams-1];
825
826
2/2
✓ Branch 0 taken 369 times.
✓ Branch 1 taken 729 times.
1098 if (type == MKTAG('v','i','d','e'))
827 369 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
828
2/2
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 443 times.
729 else if (type == MKTAG('s','o','u','n'))
829 286 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 443 times.
443 else if (type == MKTAG('m','1','a',' '))
831 st->codecpar->codec_id = AV_CODEC_ID_MP2;
832
2/4
✓ Branch 0 taken 443 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 443 times.
443 else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
833 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
834
835 1098 avio_rb32(pb); /* component manufacture */
836 1098 avio_rb32(pb); /* component flags */
837 1098 avio_rb32(pb); /* component flags mask */
838
839 1098 title_size = atom.size - 24;
840
2/2
✓ Branch 0 taken 1095 times.
✓ Branch 1 taken 3 times.
1098 if (title_size > 0) {
841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1095 times.
1095 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
842 return AVERROR_INVALIDDATA;
843 1095 title_str = av_malloc(title_size + 1); /* Add null terminator */
844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1095 times.
1095 if (!title_str)
845 return AVERROR(ENOMEM);
846
847 1095 ret = ffio_read_size(pb, title_str, title_size);
848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1095 times.
1095 if (ret < 0) {
849 av_freep(&title_str);
850 return ret;
851 }
852 1095 title_str[title_size] = 0;
853
2/2
✓ Branch 0 taken 1031 times.
✓ Branch 1 taken 64 times.
1095 if (title_str[0]) {
854
4/4
✓ Branch 0 taken 748 times.
✓ Branch 1 taken 283 times.
✓ Branch 2 taken 746 times.
✓ Branch 3 taken 2 times.
1031 int off = (!c->isom && title_str[0] == title_size - 1);
855 // flag added so as to not set stream handler name if already set from mdia->hdlr
856 1031 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
857 }
858 1095 av_freep(&title_str);
859 }
860
861 1098 return 0;
862 }
863
864 197 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
865 {
866 197 return ff_mov_read_esds(c->fc, pb);
867 }
868
869 8 static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
870 {
871 AVStream *st;
872 AVPacketSideData *sd;
873 enum AVAudioServiceType *ast;
874 int ac3info, acmod, lfeon, bsmod;
875 uint64_t mask;
876
877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (c->fc->nb_streams < 1)
878 return 0;
879 8 st = c->fc->streams[c->fc->nb_streams-1];
880
881 8 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
882 8 &st->codecpar->nb_coded_side_data,
883 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
884 sizeof(*ast), 0);
885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!sd)
886 return AVERROR(ENOMEM);
887
888 8 ast = (enum AVAudioServiceType*)sd->data;
889 8 ac3info = avio_rb24(pb);
890 8 bsmod = (ac3info >> 14) & 0x7;
891 8 acmod = (ac3info >> 11) & 0x7;
892 8 lfeon = (ac3info >> 10) & 0x1;
893
894 8 mask = ff_ac3_channel_layout_tab[acmod];
895
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (lfeon)
896 1 mask |= AV_CH_LOW_FREQUENCY;
897 8 av_channel_layout_uninit(&st->codecpar->ch_layout);
898 8 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
899
900 8 *ast = bsmod;
901
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7)
902 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
903
904 8 return 0;
905 }
906
907 #if CONFIG_IAMFDEC
908 12 static int mov_read_iacb(MOVContext *c, AVIOContext *pb, MOVAtom atom)
909 {
910 AVStream *st;
911 MOVStreamContext *sc;
912 FFIOContext b;
913 AVIOContext *descriptor_pb;
914 AVDictionary *metadata;
915 IAMFContext *iamf;
916 int64_t start_time, duration;
917 unsigned descriptors_size;
918 int nb_frames, disposition;
919 int version, ret;
920
921
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (atom.size < 5)
922 return AVERROR_INVALIDDATA;
923
924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->fc->nb_streams < 1)
925 return 0;
926
927 12 version = avio_r8(pb);
928
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (version != 1) {
929 av_log(c->fc, AV_LOG_ERROR, "%s configurationVersion %d",
930 version < 1 ? "invalid" : "unsupported", version);
931 return AVERROR_INVALIDDATA;
932 }
933
934 12 descriptors_size = ffio_read_leb(pb);
935
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (!descriptors_size || descriptors_size > INT_MAX)
936 return AVERROR_INVALIDDATA;
937
938 12 st = c->fc->streams[c->fc->nb_streams - 1];
939 12 sc = st->priv_data;
940
941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->extradata) {
942 av_log(c->fc, AV_LOG_WARNING, "ignoring iacb\n");
943 return 0;
944 }
945
946 12 sc->iamf = av_mallocz(sizeof(*sc->iamf));
947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!sc->iamf)
948 return AVERROR(ENOMEM);
949 12 iamf = &sc->iamf->iamf;
950
951 12 ret = ff_alloc_extradata(st->codecpar, descriptors_size);
952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
953 return ret;
954
955 12 ret = avio_read(pb, st->codecpar->extradata, descriptors_size);
956
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret != descriptors_size)
957 return ret < 0 ? ret : AVERROR_INVALIDDATA;
958
959 12 ffio_init_read_context(&b, st->codecpar->extradata, descriptors_size);
960 12 descriptor_pb = &b.pub;
961
962 12 ret = ff_iamfdec_read_descriptors(iamf, descriptor_pb, descriptors_size, c->fc);
963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
964 return ret;
965
966 12 metadata = st->metadata;
967 12 st->metadata = NULL;
968 12 start_time = st->start_time;
969 12 nb_frames = st->nb_frames;
970 12 duration = st->duration;
971 12 disposition = st->disposition;
972
973
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_audio_elements; i++) {
974 12 IAMFAudioElement *audio_element = iamf->audio_elements[i];
975 const AVIAMFAudioElement *element;
976 AVStreamGroup *stg =
977 12 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, NULL);
978
979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!stg) {
980 ret = AVERROR(ENOMEM);
981 goto fail;
982 }
983
984 12 av_iamf_audio_element_free(&stg->params.iamf_audio_element);
985 12 stg->id = audio_element->audio_element_id;
986 /* Transfer ownership */
987 12 element = stg->params.iamf_audio_element = audio_element->element;
988 12 audio_element->element = NULL;
989
990
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < audio_element->nb_substreams; j++) {
991 64 IAMFSubStream *substream = &audio_element->substreams[j];
992 AVStream *stream;
993
994
3/4
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 52 times.
64 if (!i && !j) {
995
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
12 if (audio_element->layers[0].substream_count != 1)
996 2 disposition &= ~AV_DISPOSITION_DEFAULT;
997 12 stream = st;
998 } else
999 52 stream = avformat_new_stream(c->fc, NULL);
1000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (!stream) {
1001 ret = AVERROR(ENOMEM);
1002 goto fail;
1003 }
1004
1005 64 stream->start_time = start_time;
1006 64 stream->nb_frames = nb_frames;
1007 64 stream->duration = duration;
1008 64 stream->disposition = disposition;
1009
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 12 times.
64 if (stream != st) {
1010 52 stream->priv_data = sc;
1011 52 sc->refcount++;
1012 }
1013
1014
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 56 times.
64 if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
1015 8 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1016
3/4
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 12 times.
64 if (i || j) {
1017 52 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1018
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 6 times.
52 if (audio_element->layers[0].substream_count == 1)
1019 46 stream->disposition &= ~AV_DISPOSITION_DEFAULT;
1020 }
1021
1022 64 ret = avcodec_parameters_copy(stream->codecpar, substream->codecpar);
1023
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
1024 goto fail;
1025
1026 64 stream->id = substream->audio_substream_id;
1027
1028 64 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
1029
1030 64 ret = avformat_stream_group_add_stream(stg, stream);
1031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
1032 goto fail;
1033 }
1034
1035 12 ret = av_dict_copy(&stg->metadata, metadata, 0);
1036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1037 goto fail;
1038 }
1039
1040
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1041 12 IAMFMixPresentation *mix_presentation = iamf->mix_presentations[i];
1042 12 const AVIAMFMixPresentation *mix = mix_presentation->cmix;
1043 AVStreamGroup *stg =
1044 12 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, NULL);
1045
1046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!stg) {
1047 ret = AVERROR(ENOMEM);
1048 goto fail;
1049 }
1050
1051 12 av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
1052 12 stg->id = mix_presentation->mix_presentation_id;
1053 /* Transfer ownership */
1054 12 stg->params.iamf_mix_presentation = mix_presentation->mix;
1055 12 mix_presentation->mix = NULL;
1056
1057
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 12 times.
26 for (int j = 0; j < mix->nb_submixes; j++) {
1058 14 const AVIAMFSubmix *submix = mix->submixes[j];
1059
1060
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
28 for (int k = 0; k < submix->nb_elements; k++) {
1061 14 const AVIAMFSubmixElement *submix_element = submix->elements[k];
1062 14 const AVStreamGroup *audio_element = NULL;
1063
1064
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 for (int l = 0; l < c->fc->nb_stream_groups; l++)
1065
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (c->fc->stream_groups[l]->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT &&
1066
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 c->fc->stream_groups[l]->id == submix_element->audio_element_id) {
1067 14 audio_element = c->fc->stream_groups[l];
1068 14 break;
1069 }
1070
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 av_assert0(audio_element);
1071
1072
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 14 times.
80 for (int l = 0; l < audio_element->nb_streams; l++) {
1073 66 ret = avformat_stream_group_add_stream(stg, audio_element->streams[l]);
1074
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
66 if (ret < 0 && ret != AVERROR(EEXIST))
1075 goto fail;
1076 }
1077 }
1078 }
1079
1080 12 ret = av_dict_copy(&stg->metadata, metadata, 0);
1081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1082 goto fail;
1083 }
1084
1085 12 ret = 0;
1086 12 fail:
1087 12 av_dict_free(&metadata);
1088
1089 12 return ret;
1090 }
1091 #endif
1092
1093 5 static int mov_read_srat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1094 {
1095 AVStream *st;
1096 int32_t sample_rate;
1097
1098
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (atom.size < 8 || c->fc->nb_streams < 1)
1099 return 0;
1100
1101 5 st = c->fc->streams[c->fc->nb_streams-1];
1102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
1103 av_log(c->fc, AV_LOG_WARNING, "'srat' within non-audio sample entry, skip\n");
1104 return 0;
1105 }
1106
1107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!c->isom) {
1108 av_log(c->fc, AV_LOG_WARNING, "'srat' within non-isom, skip\n");
1109 return 0;
1110 }
1111
1112 5 avio_skip(pb, 4); // version+flags
1113 5 sample_rate = avio_rb32(pb);
1114
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (sample_rate > 0) {
1115 5 av_log(c->fc, AV_LOG_DEBUG,
1116 "overwrite sample rate from %d to %d by 'srat'\n",
1117 5 st->codecpar->sample_rate, sample_rate);
1118 5 st->codecpar->sample_rate = sample_rate;
1119 } else {
1120 av_log(c->fc, AV_LOG_WARNING,
1121 "ignore invalid sample rate %d in 'srat'\n", sample_rate);
1122 }
1123
1124 5 return 0;
1125 }
1126
1127 4 static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1128 {
1129 AVStream *st;
1130 AVPacketSideData *sd;
1131 enum AVAudioServiceType *ast;
1132 int eac3info, acmod, lfeon, bsmod;
1133 uint64_t mask;
1134
1135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
1136 return 0;
1137 4 st = c->fc->streams[c->fc->nb_streams-1];
1138
1139 4 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1140 4 &st->codecpar->nb_coded_side_data,
1141 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
1142 sizeof(*ast), 0);
1143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sd)
1144 return AVERROR(ENOMEM);
1145
1146 4 ast = (enum AVAudioServiceType*)sd->data;
1147
1148 /* No need to parse fields for additional independent substreams and its
1149 * associated dependent substreams since libavcodec's E-AC-3 decoder
1150 * does not support them yet. */
1151 4 avio_rb16(pb); /* data_rate and num_ind_sub */
1152 4 eac3info = avio_rb24(pb);
1153 4 bsmod = (eac3info >> 12) & 0x1f;
1154 4 acmod = (eac3info >> 9) & 0x7;
1155 4 lfeon = (eac3info >> 8) & 0x1;
1156
1157 4 mask = ff_ac3_channel_layout_tab[acmod];
1158
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (lfeon)
1159 1 mask |= AV_CH_LOW_FREQUENCY;
1160 4 av_channel_layout_uninit(&st->codecpar->ch_layout);
1161 4 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
1162
1163 4 *ast = bsmod;
1164
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7)
1165 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
1166
1167 4 return 0;
1168 }
1169
1170 /* Maps the DTS `StreamConstruction` field (ETSI TS 102 114 Table E-2) to the
1171 * coarse FFmpeg DTS profile enum. Extension-substream XLL maps to HD_MA;
1172 * extension-substream XXCH, X96, or XBR maps to HD_HRA; core-substream XCH or
1173 * XXCH maps to ES; core-substream X96 maps to 96/24; a core component alone
1174 * maps to DTS; and extension-substream LBR maps to Express. Value 0 (undefined)
1175 * and values outside 1..21 map to AV_PROFILE_UNKNOWN. */
1176 static int mov_dts_stream_construction_to_profile(unsigned int sc)
1177 {
1178 static const int profile[22] = {
1179 [ 1] = AV_PROFILE_DTS, /* core Core */
1180 [ 2] = AV_PROFILE_DTS_ES, /* core Core + core XCH */
1181 [ 3] = AV_PROFILE_DTS_ES, /* core Core + core XXCH */
1182 [ 4] = AV_PROFILE_DTS_96_24, /* core Core + core X96 */
1183 [ 5] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XXCH */
1184 [ 6] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XBR */
1185 [ 7] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XCH + ext XBR */
1186 [ 8] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XXCH + ext XBR */
1187 [ 9] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XXCH + ext XBR */
1188 [10] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext X96 */
1189 [11] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XCH + ext X96 */
1190 [12] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XXCH + ext X96 */
1191 [13] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XXCH + ext X96 */
1192 [14] = AV_PROFILE_DTS_HD_MA, /* core Core + ext XLL */
1193 [15] = AV_PROFILE_DTS_HD_MA, /* core Core + core XCH + ext XLL */
1194 [16] = AV_PROFILE_DTS_HD_MA, /* core Core + core X96 + ext XLL */
1195 [17] = AV_PROFILE_DTS_HD_MA, /* ext XLL */
1196 [18] = AV_PROFILE_DTS_EXPRESS, /* ext LBR */
1197 [19] = AV_PROFILE_DTS, /* ext Core */
1198 [20] = AV_PROFILE_DTS_HD_HRA, /* ext Core + ext XXCH */
1199 [21] = AV_PROFILE_DTS_HD_MA, /* ext Core + ext XLL */
1200 };
1201 if (!sc || sc > 21)
1202 return AV_PROFILE_UNKNOWN;
1203 return profile[sc];
1204 }
1205
1206 /* Maps the 16-bit DTS `ChannelLayout` bitmask (ETSI TS 102 114 Table E-5) to an
1207 * ffmpeg channel mask. Pair bits follow Table 7-10 / DCA_SPEAKER_PAIR_*;
1208 * LwRw (0x0400) and LssRss (0x0800) must not collapse onto SIDE like LsRs. */
1209 static uint64_t mov_dts_channel_layout_to_mask(unsigned int code)
1210 {
1211 static const struct { unsigned int dts; uint64_t av; } map[] = {
1212 { 0x0001, AV_CH_FRONT_CENTER },
1213 { 0x0002, AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT },
1214 { 0x0004, AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT },
1215 { 0x0008, AV_CH_LOW_FREQUENCY },
1216 { 0x0010, AV_CH_BACK_CENTER },
1217 { 0x0020, AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT },
1218 { 0x0040, AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT },
1219 { 0x0080, AV_CH_TOP_FRONT_CENTER },
1220 { 0x0100, AV_CH_TOP_CENTER },
1221 { 0x0200, AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER },
1222 { 0x0400, AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT },
1223 { 0x0800, AV_CH_SIDE_SURROUND_LEFT | AV_CH_SIDE_SURROUND_RIGHT },
1224 { 0x1000, AV_CH_LOW_FREQUENCY_2 },
1225 { 0x2000, AV_CH_TOP_SIDE_LEFT | AV_CH_TOP_SIDE_RIGHT },
1226 { 0x4000, AV_CH_TOP_BACK_CENTER },
1227 { 0x8000, AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT },
1228 };
1229 uint64_t mask = 0;
1230 int i;
1231 for (i = 0; i < FF_ARRAY_ELEMS(map); i++)
1232 if (code & map[i].dts)
1233 mask |= map[i].av;
1234 return mask;
1235 }
1236
1237 static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1238 {
1239 #define DDTS_SIZE 20
1240 uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
1241 AVStream *st = NULL;
1242 uint32_t frame_duration_code = 0;
1243 uint32_t channel_layout_code = 0;
1244 uint64_t channel_layout_mask;
1245 unsigned int stream_construction;
1246 unsigned int representation_type;
1247 GetBitContext gb;
1248 int ret;
1249
1250 if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
1251 return ret;
1252
1253 init_get_bits(&gb, buf, 8 * DDTS_SIZE);
1254
1255 if (c->fc->nb_streams < 1) {
1256 return 0;
1257 }
1258 st = c->fc->streams[c->fc->nb_streams-1];
1259
1260 st->codecpar->sample_rate = get_bits_long(&gb, 32);
1261 if (st->codecpar->sample_rate <= 0) {
1262 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
1263 return AVERROR_INVALIDDATA;
1264 }
1265 skip_bits_long(&gb, 32); /* max bitrate */
1266 st->codecpar->bit_rate = get_bits_long(&gb, 32);
1267 st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
1268 frame_duration_code = get_bits(&gb, 2);
1269 stream_construction = get_bits(&gb, 5); /* Table E-2 - profile source */
1270 skip_bits(&gb, 1); /* CoreLFEPresent */
1271 skip_bits(&gb, 6); /* CoreLayout */
1272 skip_bits(&gb, 14); /* CoreSize */
1273 skip_bits(&gb, 1); /* StereoDownmix */
1274 representation_type = get_bits(&gb, 3);
1275 channel_layout_code = get_bits(&gb, 16);
1276
1277 st->codecpar->frame_size =
1278 (frame_duration_code == 0) ? 512 :
1279 (frame_duration_code == 1) ? 1024 :
1280 (frame_duration_code == 2) ? 2048 :
1281 (frame_duration_code == 3) ? 4096 : 0;
1282
1283 /* Publish StreamConstruction as codecpar->profile, including for encrypted
1284 * tracks where frame headers cannot be inspected. */
1285 st->codecpar->profile = mov_dts_stream_construction_to_profile(stream_construction);
1286
1287 channel_layout_mask = mov_dts_channel_layout_to_mask(channel_layout_code);
1288 if (channel_layout_mask) {
1289 av_channel_layout_uninit(&st->codecpar->ch_layout);
1290 av_channel_layout_from_mask(&st->codecpar->ch_layout, channel_layout_mask);
1291 } else if (representation_type == 2 || representation_type == 3) {
1292 av_channel_layout_uninit(&st->codecpar->ch_layout);
1293 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
1294 }
1295
1296 return 0;
1297 }
1298
1299 50 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1300 {
1301 AVStream *st;
1302
1303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (c->fc->nb_streams < 1)
1304 return 0;
1305 50 st = c->fc->streams[c->fc->nb_streams-1];
1306
1307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (atom.size < 16)
1308 return 0;
1309
1310 /* skip version and flags */
1311 50 avio_skip(pb, 4);
1312
1313 50 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
1314
1315 50 return 0;
1316 }
1317
1318 5 static int mov_read_chnl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1319 {
1320 5 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
1321 int version, flags;
1322 int ret;
1323 AVStream *st;
1324
1325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
1326 return 0;
1327 5 st = c->fc->streams[c->fc->nb_streams-1];
1328
1329 5 version = avio_r8(pb);
1330 5 flags = avio_rb24(pb);
1331
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (version > 1 || flags != 0) {
1332 av_log(c->fc, AV_LOG_WARNING,
1333 "Unsupported 'chnl' box with version %d, flags: %#x\n",
1334 version, flags);
1335 return 0;
1336 }
1337
1338 5 ret = ff_mov_read_chnl(c->fc, pb, st, version);
1339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0) {
1340 avio_seek(pb, end, SEEK_SET);
1341 return 0;
1342 }
1343
1344
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_tell(pb) != end) {
1345 av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data inside chnl\n",
1346 end - avio_tell(pb));
1347 avio_seek(pb, end, SEEK_SET);
1348 }
1349 5 return ret;
1350 }
1351
1352 2 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1353 {
1354 AVStream *st;
1355 int ret;
1356
1357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
1358 return 0;
1359 2 st = c->fc->streams[c->fc->nb_streams-1];
1360
1361
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)
1362 av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
1363
1364 2 return ret;
1365 }
1366
1367 18 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1368 {
1369 AVStream *st;
1370 HEIFItem *item;
1371 AVPacketSideData *sd;
1372 18 int width, height, err = 0;
1373 AVRational aperture_width, aperture_height, horiz_off, vert_off;
1374 AVRational pc_x, pc_y;
1375 uint64_t top, bottom, left, right;
1376
1377 18 item = get_heif_item(c, c->cur_item_id);
1378 18 st = get_curr_st(c);
1379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!st)
1380 return 0;
1381
1382 18 width = st->codecpar->width;
1383 18 height = st->codecpar->height;
1384
4/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
18 if ((!width || !height) && item) {
1385 6 width = item->width;
1386 6 height = item->height;
1387 }
1388
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (!width || !height) {
1389 err = AVERROR_INVALIDDATA;
1390 goto fail;
1391 }
1392
1393 18 aperture_width.num = avio_rb32(pb);
1394 18 aperture_width.den = avio_rb32(pb);
1395 18 aperture_height.num = avio_rb32(pb);
1396 18 aperture_height.den = avio_rb32(pb);
1397
1398 18 horiz_off.num = avio_rb32(pb);
1399 18 horiz_off.den = avio_rb32(pb);
1400 18 vert_off.num = avio_rb32(pb);
1401 18 vert_off.den = avio_rb32(pb);
1402
1403
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 if (aperture_width.num < 0 || aperture_width.den < 0 ||
1404
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 aperture_height.num < 0 || aperture_height.den < 0 ||
1405
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 horiz_off.den < 0 || vert_off.den < 0) {
1406 err = AVERROR_INVALIDDATA;
1407 goto fail;
1408 }
1409
3/4
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
33 if ((av_cmp_q((AVRational) { width, 1 }, aperture_width) < 0) ||
1410 15 (av_cmp_q((AVRational) { height, 1 }, aperture_height) < 0)) {
1411 3 err = AVERROR_INVALIDDATA;
1412 3 goto fail;
1413 }
1414 15 av_log(c->fc, AV_LOG_TRACE, "clap: apertureWidth %d/%d, apertureHeight %d/%d "
1415 "horizOff %d/%d vertOff %d/%d\n",
1416 aperture_width.num, aperture_width.den, aperture_height.num, aperture_height.den,
1417 horiz_off.num, horiz_off.den, vert_off.num, vert_off.den);
1418
1419 15 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1420 15 pc_x = av_add_q(pc_x, horiz_off);
1421 15 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1422 15 pc_y = av_add_q(pc_y, vert_off);
1423
1424 15 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1425 15 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1426 15 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1427 15 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1428
1429 15 left = av_q2d(av_sub_q(pc_x, aperture_width));
1430 15 right = av_q2d(av_add_q(pc_x, aperture_width));
1431 15 top = av_q2d(av_sub_q(pc_y, aperture_height));
1432 15 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1433
1434
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (bottom > (height - 1) ||
1435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 right > (width - 1)) {
1436 err = AVERROR_INVALIDDATA;
1437 goto fail;
1438 }
1439
1440 15 bottom = height - 1 - bottom;
1441 15 right = width - 1 - right;
1442
1443
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
15 if (!(left | right | top | bottom))
1444 6 return 0;
1445
1446
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if ((left + right) >= width ||
1447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 (top + bottom) >= height) {
1448 err = AVERROR_INVALIDDATA;
1449 goto fail;
1450 }
1451
1452 9 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1453 9 &st->codecpar->nb_coded_side_data,
1454 AV_PKT_DATA_FRAME_CROPPING,
1455 sizeof(uint32_t) * 4, 0);
1456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sd)
1457 return AVERROR(ENOMEM);
1458
1459 9 AV_WL32A(sd->data, top);
1460 9 AV_WL32A(sd->data + 4, bottom);
1461 9 AV_WL32A(sd->data + 8, left);
1462 9 AV_WL32A(sd->data + 12, right);
1463
1464 12 fail:
1465
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 if (err < 0) {
1466 3 int explode = !!(c->fc->error_recognition & AV_EF_EXPLODE);
1467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 av_log(c->fc, explode ? AV_LOG_ERROR : AV_LOG_WARNING, "Invalid clap box\n");
1468
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!explode)
1469 3 err = 0;
1470 }
1471
1472 12 return err;
1473 }
1474
1475 /* This atom overrides any previously set aspect ratio */
1476 102 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1477 {
1478 102 const int num = avio_rb32(pb);
1479 102 const int den = avio_rb32(pb);
1480 AVStream *st;
1481 MOVStreamContext *sc;
1482
1483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102 times.
102 if (c->fc->nb_streams < 1)
1484 return 0;
1485 102 st = c->fc->streams[c->fc->nb_streams-1];
1486 102 sc = st->priv_data;
1487
1488 102 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1489
1490
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 2 times.
102 if (den != 0) {
1491 100 sc->h_spacing = num;
1492 100 sc->v_spacing = den;
1493 }
1494 102 return 0;
1495 }
1496
1497 /* this atom contains actual media data */
1498 1066 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1499 {
1500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1066 times.
1066 if (atom.size == 0) /* wrong one (MP4) */
1501 return 0;
1502 1066 c->found_mdat=1;
1503 1066 return 0; /* now go for moov */
1504 }
1505
1506 #define DRM_BLOB_SIZE 56
1507
1508 static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1509 {
1510 uint8_t intermediate_key[20];
1511 uint8_t intermediate_iv[20];
1512 uint8_t input[64];
1513 uint8_t output[64];
1514 uint8_t file_checksum[20];
1515 uint8_t calculated_checksum[20];
1516 char checksum_string[2 * sizeof(file_checksum) + 1];
1517 struct AVSHA *sha;
1518 int i;
1519 int ret = 0;
1520 uint8_t *activation_bytes = c->activation_bytes;
1521 uint8_t *fixed_key = c->audible_fixed_key;
1522
1523 c->aax_mode = 1;
1524
1525 sha = av_sha_alloc();
1526 if (!sha)
1527 return AVERROR(ENOMEM);
1528 av_free(c->aes_decrypt);
1529 c->aes_decrypt = av_aes_alloc();
1530 if (!c->aes_decrypt) {
1531 ret = AVERROR(ENOMEM);
1532 goto fail;
1533 }
1534
1535 /* drm blob processing */
1536 avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1537 avio_read(pb, input, DRM_BLOB_SIZE);
1538 avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1539 ret = ffio_read_size(pb, file_checksum, 20);
1540 if (ret < 0)
1541 goto fail;
1542
1543 // required by external tools
1544 ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1);
1545 av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string);
1546
1547 /* verify activation data */
1548 if (!activation_bytes) {
1549 av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1550 ret = 0; /* allow ffprobe to continue working on .aax files */
1551 goto fail;
1552 }
1553 if (c->activation_bytes_size != 4) {
1554 av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1555 ret = AVERROR(EINVAL);
1556 goto fail;
1557 }
1558
1559 /* verify fixed key */
1560 if (c->audible_fixed_key_size != 16) {
1561 av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1562 ret = AVERROR(EINVAL);
1563 goto fail;
1564 }
1565
1566 /* AAX (and AAX+) key derivation */
1567 av_sha_init(sha, 160);
1568 av_sha_update(sha, fixed_key, 16);
1569 av_sha_update(sha, activation_bytes, 4);
1570 av_sha_final(sha, intermediate_key);
1571 av_sha_init(sha, 160);
1572 av_sha_update(sha, fixed_key, 16);
1573 av_sha_update(sha, intermediate_key, 20);
1574 av_sha_update(sha, activation_bytes, 4);
1575 av_sha_final(sha, intermediate_iv);
1576 av_sha_init(sha, 160);
1577 av_sha_update(sha, intermediate_key, 16);
1578 av_sha_update(sha, intermediate_iv, 16);
1579 av_sha_final(sha, calculated_checksum);
1580 if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1581 av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1582 ret = AVERROR_INVALIDDATA;
1583 goto fail;
1584 }
1585 av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1586 av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1587 for (i = 0; i < 4; i++) {
1588 // file data (in output) is stored in big-endian mode
1589 if (activation_bytes[i] != output[3 - i]) { // critical error
1590 av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1591 ret = AVERROR_INVALIDDATA;
1592 goto fail;
1593 }
1594 }
1595 memcpy(c->file_key, output + 8, 16);
1596 memcpy(input, output + 26, 16);
1597 av_sha_init(sha, 160);
1598 av_sha_update(sha, input, 16);
1599 av_sha_update(sha, c->file_key, 16);
1600 av_sha_update(sha, fixed_key, 16);
1601 av_sha_final(sha, c->file_iv);
1602
1603 fail:
1604 av_free(sha);
1605
1606 return ret;
1607 }
1608
1609 static int mov_aaxc_crypto(MOVContext *c)
1610 {
1611 if (c->audible_key_size != 16) {
1612 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n");
1613 return AVERROR(EINVAL);
1614 }
1615
1616 if (c->audible_iv_size != 16) {
1617 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n");
1618 return AVERROR(EINVAL);
1619 }
1620
1621 c->aes_decrypt = av_aes_alloc();
1622 if (!c->aes_decrypt) {
1623 return AVERROR(ENOMEM);
1624 }
1625
1626 memcpy(c->file_key, c->audible_key, 16);
1627 memcpy(c->file_iv, c->audible_iv, 16);
1628 c->aax_mode = 1;
1629
1630 return 0;
1631 }
1632
1633 // Audible AAX (and AAX+) bytestream decryption
1634 static int aax_filter(uint8_t *input, int size, MOVContext *c)
1635 {
1636 int blocks = 0;
1637 unsigned char iv[16];
1638
1639 memcpy(iv, c->file_iv, 16); // iv is overwritten
1640 blocks = size >> 4; // trailing bytes are not encrypted!
1641 av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1642 av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1643
1644 return 0;
1645 }
1646
1647 /* read major brand, minor version and compatible brands and store them as metadata */
1648 548 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1649 {
1650 uint32_t minor_ver;
1651 int comp_brand_size;
1652 char* comp_brands_str;
1653 548 uint8_t type[5] = {0};
1654 548 int ret = ffio_read_size(pb, type, 4);
1655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 548 times.
548 if (ret < 0)
1656 return ret;
1657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 548 times.
548 if (c->fc->nb_streams) {
1658 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1659 return AVERROR_INVALIDDATA;
1660 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate FTYP\n");
1661 return 0;
1662 }
1663
1664
2/2
✓ Branch 0 taken 306 times.
✓ Branch 1 taken 242 times.
548 if (strcmp(type, "qt "))
1665 306 c->isom = 1;
1666 548 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1667 548 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1668 548 minor_ver = avio_rb32(pb); /* minor version */
1669 548 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1670
1671 548 comp_brand_size = atom.size - 8;
1672
2/4
✓ Branch 0 taken 548 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 548 times.
548 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1673 return AVERROR_INVALIDDATA;
1674 548 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 548 times.
548 if (!comp_brands_str)
1676 return AVERROR(ENOMEM);
1677
1678 548 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 548 times.
548 if (ret < 0) {
1680 av_freep(&comp_brands_str);
1681 return ret;
1682 }
1683 548 comp_brands_str[comp_brand_size] = 0;
1684 548 av_dict_set(&c->fc->metadata, "compatible_brands",
1685 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1686
1687 // Logic for handling Audible's .aaxc files
1688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 548 times.
548 if (!strcmp(type, "aaxc")) {
1689 mov_aaxc_crypto(c);
1690 }
1691
1692 548 return 0;
1693 }
1694
1695 /* this atom should contain all header atoms */
1696 593 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1697 {
1698 int ret;
1699
1700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 if (c->found_moov) {
1701 av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1702 avio_skip(pb, atom.size);
1703 return 0;
1704 }
1705
1706
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 593 times.
593 if ((ret = mov_read_default(c, pb, atom)) < 0)
1707 return ret;
1708 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1709 /* so we don't parse the whole file if over a network */
1710 593 c->found_moov=1;
1711 593 return 0; /* now go for mdat */
1712 }
1713
1714 3216 static MOVFragmentStreamInfo * get_frag_stream_info(
1715 MOVFragmentIndex *frag_index,
1716 int index,
1717 int id)
1718 {
1719 int i;
1720 MOVFragmentIndexItem * item;
1721
1722
2/4
✓ Branch 0 taken 3216 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3216 times.
3216 if (index < 0 || index >= frag_index->nb_items)
1723 return NULL;
1724 3216 item = &frag_index->item[index];
1725
1/2
✓ Branch 0 taken 3400 times.
✗ Branch 1 not taken.
3400 for (i = 0; i < item->nb_stream_info; i++)
1726
2/2
✓ Branch 0 taken 3216 times.
✓ Branch 1 taken 184 times.
3400 if (item->stream_info[i].id == id)
1727 3216 return &item->stream_info[i];
1728
1729 // This shouldn't happen
1730 return NULL;
1731 }
1732
1733 501 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1734 {
1735 int i;
1736 MOVFragmentIndexItem * item;
1737
1738
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (frag_index->current < 0 ||
1739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 frag_index->current >= frag_index->nb_items)
1740 return;
1741
1742 501 item = &frag_index->item[frag_index->current];
1743
1/2
✓ Branch 0 taken 560 times.
✗ Branch 1 not taken.
560 for (i = 0; i < item->nb_stream_info; i++)
1744
2/2
✓ Branch 0 taken 501 times.
✓ Branch 1 taken 59 times.
560 if (item->stream_info[i].id == id) {
1745 501 item->current = i;
1746 501 return;
1747 }
1748
1749 // id not found. This shouldn't happen.
1750 item->current = -1;
1751 }
1752
1753 1457 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1754 MOVFragmentIndex *frag_index)
1755 {
1756 MOVFragmentIndexItem *item;
1757
1/2
✓ Branch 0 taken 1457 times.
✗ Branch 1 not taken.
1457 if (frag_index->current < 0 ||
1758
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 1436 times.
1457 frag_index->current >= frag_index->nb_items)
1759 21 return NULL;
1760
1761 1436 item = &frag_index->item[frag_index->current];
1762
2/4
✓ Branch 0 taken 1436 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1436 times.
✗ Branch 3 not taken.
1436 if (item->current >= 0 && item->current < item->nb_stream_info)
1763 1436 return &item->stream_info[item->current];
1764
1765 // This shouldn't happen
1766 return NULL;
1767 }
1768
1769 901 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1770 {
1771 int a, b, m;
1772 int64_t moof_offset;
1773
1774 // Optimize for appending new entries
1775
2/2
✓ Branch 0 taken 882 times.
✓ Branch 1 taken 19 times.
901 if (!frag_index->nb_items ||
1776
2/2
✓ Branch 0 taken 465 times.
✓ Branch 1 taken 417 times.
882 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1777 484 return frag_index->nb_items;
1778
1779 417 a = -1;
1780 417 b = frag_index->nb_items;
1781
1782
2/2
✓ Branch 0 taken 2677 times.
✓ Branch 1 taken 417 times.
3094 while (b - a > 1) {
1783 2677 m = (a + b) >> 1;
1784 2677 moof_offset = frag_index->item[m].moof_offset;
1785
2/2
✓ Branch 0 taken 747 times.
✓ Branch 1 taken 1930 times.
2677 if (moof_offset >= offset)
1786 747 b = m;
1787
2/2
✓ Branch 0 taken 2345 times.
✓ Branch 1 taken 332 times.
2677 if (moof_offset <= offset)
1788 2345 a = m;
1789 }
1790 417 return b;
1791 }
1792
1793 7 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1794 {
1795
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 av_assert0(frag_stream_info);
1796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1797 return frag_stream_info->sidx_pts;
1798
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1799 4 return frag_stream_info->first_tfra_pts;
1800 3 return frag_stream_info->tfdt_dts;
1801 }
1802
1803 226 static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1804 MOVFragmentIndex *frag_index, int index)
1805 {
1806 MOVFragmentStreamInfo * frag_stream_info;
1807 226 MOVStreamContext *sc = dst_st->priv_data;
1808 int64_t timestamp;
1809 int i, j;
1810
1811 // If the stream is referenced by any sidx, limit the search
1812 // to fragments that referenced this stream in the sidx
1813
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 7 times.
226 if (sc->has_sidx) {
1814 219 frag_stream_info = get_frag_stream_info(frag_index, index, sc->id);
1815
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!frag_stream_info)
1816 return AV_NOPTS_VALUE;
1817
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1818 219 return frag_stream_info->sidx_pts;
1819 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1820 return frag_stream_info->first_tfra_pts;
1821 return frag_stream_info->sidx_pts;
1822 }
1823
1824
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 3 times.
15 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
1825
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7 times.
12 if (dst_st->id != frag_index->item[index].stream_info[i].id)
1826 5 continue;
1827 7 AVStream *frag_stream = NULL;
1828 7 frag_stream_info = &frag_index->item[index].stream_info[i];
1829
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
21 for (j = 0; j < s->nb_streams; j++) {
1830 14 MOVStreamContext *sc2 = s->streams[j]->priv_data;
1831
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (sc2->id == frag_stream_info->id)
1832 7 frag_stream = s->streams[j];
1833 }
1834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!frag_stream) {
1835 av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1836 continue;
1837 }
1838 7 timestamp = get_stream_info_time(frag_stream_info);
1839
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (timestamp != AV_NOPTS_VALUE)
1840 4 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1841 }
1842 3 return AV_NOPTS_VALUE;
1843 }
1844
1845 28 static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1846 AVStream *st, int64_t timestamp)
1847 {
1848 int a, b, m, m0;
1849 int64_t frag_time;
1850
1851 28 a = -1;
1852 28 b = frag_index->nb_items;
1853
1854
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 28 times.
252 while (b - a > 1) {
1855 224 m0 = m = (a + b) >> 1;
1856
1857
4/4
✓ Branch 0 taken 226 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 223 times.
453 while (m < b &&
1858 226 (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
1859 3 m++;
1860
1861
4/4
✓ Branch 0 taken 223 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 95 times.
✓ Branch 3 taken 128 times.
224 if (m < b && frag_time <= timestamp)
1862 95 a = m;
1863 else
1864 129 b = m0;
1865 }
1866
1867 28 return a;
1868 }
1869
1870 853 static int update_frag_index(MOVContext *c, int64_t offset)
1871 {
1872 int index, i;
1873 MOVFragmentIndexItem * item;
1874 MOVFragmentStreamInfo * frag_stream_info;
1875
1876 // If moof_offset already exists in frag_index, return index to it
1877 853 index = search_frag_moof_offset(&c->frag_index, offset);
1878
2/2
✓ Branch 0 taken 376 times.
✓ Branch 1 taken 477 times.
853 if (index < c->frag_index.nb_items &&
1879
2/2
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 2 times.
376 c->frag_index.item[index].moof_offset == offset)
1880 374 return index;
1881
1882 // offset is not yet in frag index.
1883 // Insert new item at index (sorted by moof offset)
1884 479 item = av_fast_realloc(c->frag_index.item,
1885 479 &c->frag_index.allocated_size,
1886 479 (c->frag_index.nb_items + 1) *
1887 sizeof(*c->frag_index.item));
1888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 479 times.
479 if (!item)
1889 return -1;
1890 479 c->frag_index.item = item;
1891
1892 479 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1893 sizeof(*item->stream_info));
1894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 479 times.
479 if (!frag_stream_info)
1895 return -1;
1896
1897
2/2
✓ Branch 0 taken 581 times.
✓ Branch 1 taken 479 times.
1060 for (i = 0; i < c->fc->nb_streams; i++) {
1898 // Avoid building frag index if streams lack track id.
1899 581 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 581 times.
581 if (sc->id < 0) {
1901 av_free(frag_stream_info);
1902 return AVERROR_INVALIDDATA;
1903 }
1904
1905 581 frag_stream_info[i].id = sc->id;
1906 581 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1907 581 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1908 581 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1909 581 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1910 581 frag_stream_info[i].index_base = -1;
1911 581 frag_stream_info[i].index_entry = -1;
1912 581 frag_stream_info[i].encryption_index = NULL;
1913 581 frag_stream_info[i].stsd_id = -1;
1914 }
1915
1916
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 477 times.
479 if (index < c->frag_index.nb_items)
1917 2 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1918 2 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1919
1920 479 item = &c->frag_index.item[index];
1921 479 item->headers_read = 0;
1922 479 item->current = 0;
1923 479 item->nb_stream_info = c->fc->nb_streams;
1924 479 item->moof_offset = offset;
1925 479 item->stream_info = frag_stream_info;
1926 479 c->frag_index.nb_items++;
1927
1928 479 return index;
1929 }
1930
1931 501 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1932 int id, int entries)
1933 {
1934 int i;
1935 MOVFragmentStreamInfo * frag_stream_info;
1936
1937
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (index < 0)
1938 501 return;
1939 for (i = index; i < frag_index->nb_items; i++) {
1940 frag_stream_info = get_frag_stream_info(frag_index, i, id);
1941 if (frag_stream_info && frag_stream_info->index_entry >= 0)
1942 frag_stream_info->index_entry += entries;
1943 }
1944 }
1945
1946 475 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1947 {
1948 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1949 475 c->fragment.found_tfhd = 0;
1950
1951
4/4
✓ Branch 0 taken 473 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 472 times.
475 if (!c->has_looked_for_mfra && c->use_mfra_for > 0) {
1952 1 c->has_looked_for_mfra = 1;
1953
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1954 int ret;
1955 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1956 "for a mfra\n");
1957
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((ret = mov_read_mfra(c, pb)) < 0) {
1958 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1959 "read the mfra (may be a live ismv)\n");
1960 }
1961 } else {
1962 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1963 "seekable, can not look for mfra\n");
1964 }
1965 }
1966 475 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1967 475 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1968 475 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1969 475 return mov_read_default(c, pb, atom);
1970 }
1971
1972 1302 static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version)
1973 {
1974 int64_t time;
1975
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1287 times.
1302 if (version == 1) {
1976 15 time = avio_rb64(pb);
1977 15 avio_rb64(pb);
1978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (time < 0) {
1979 av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n");
1980 return;
1981 }
1982 } else {
1983 1287 time = avio_rb32(pb);
1984 1287 avio_rb32(pb); /* modification time */
1985
4/4
✓ Branch 0 taken 625 times.
✓ Branch 1 taken 662 times.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 563 times.
1287 if (time > 0 && time < 2082844800) {
1986 62 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1987 62 time += 2082844800;
1988 }
1989 }
1990
2/2
✓ Branch 0 taken 631 times.
✓ Branch 1 taken 671 times.
1302 if (time) {
1991 631 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1992
1993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 631 times.
631 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1994 av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n");
1995 return;
1996 }
1997
1998 631 ff_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1999 }
2000 }
2001
2002 712 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2003 {
2004 AVStream *st;
2005 MOVStreamContext *sc;
2006 int version;
2007 712 char language[4] = {0};
2008 unsigned lang;
2009
2010
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (c->fc->nb_streams < 1)
2011 return 0;
2012 712 st = c->fc->streams[c->fc->nb_streams-1];
2013 712 sc = st->priv_data;
2014
2015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (sc->time_scale) {
2016 av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
2017 return AVERROR_INVALIDDATA;
2018 }
2019
2020 712 version = avio_r8(pb);
2021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (version > 1) {
2022 avpriv_request_sample(c->fc, "Version %d", version);
2023 return AVERROR_PATCHWELCOME;
2024 }
2025 712 avio_rb24(pb); /* flags */
2026 712 mov_metadata_creation_time(c, pb, &st->metadata, version);
2027
2028 712 sc->time_scale = avio_rb32(pb);
2029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (sc->time_scale <= 0) {
2030 av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
2031 sc->time_scale = 1;
2032 }
2033
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 699 times.
712 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
2034
2035
6/6
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 699 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 699 times.
✓ Branch 5 taken 4 times.
712 if ((version == 1 && st->duration == UINT64_MAX) ||
2036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 699 times.
699 (version != 1 && st->duration == UINT32_MAX)) {
2037 9 st->duration = 0;
2038 }
2039
2040 712 lang = avio_rb16(pb); /* language */
2041
2/2
✓ Branch 1 taken 538 times.
✓ Branch 2 taken 174 times.
712 if (ff_mov_lang_to_iso639(lang, language))
2042 538 av_dict_set(&st->metadata, "language", language, 0);
2043 712 avio_rb16(pb); /* quality */
2044
2045 712 return 0;
2046 }
2047
2048 590 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2049 {
2050 int i;
2051 590 int version = avio_r8(pb); /* version */
2052 590 avio_rb24(pb); /* flags */
2053
2054 590 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
2055 590 c->time_scale = avio_rb32(pb); /* time scale */
2056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 590 times.
590 if (c->time_scale <= 0) {
2057 av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
2058 c->time_scale = 1;
2059 }
2060 590 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
2061
2062
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 588 times.
590 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
2063 590 avio_rb32(pb); /* preferred scale */
2064
2065 590 avio_rb16(pb); /* preferred volume */
2066
2067 590 avio_skip(pb, 10); /* reserved */
2068
2069 /* movie display matrix, store it in main context and use it later on */
2070
2/2
✓ Branch 0 taken 1770 times.
✓ Branch 1 taken 590 times.
2360 for (i = 0; i < 3; i++) {
2071 1770 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
2072 1770 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
2073 1770 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
2074 }
2075
2076 590 avio_rb32(pb); /* preview time */
2077 590 avio_rb32(pb); /* preview duration */
2078 590 avio_rb32(pb); /* poster time */
2079 590 avio_rb32(pb); /* selection time */
2080 590 avio_rb32(pb); /* selection duration */
2081 590 avio_rb32(pb); /* current time */
2082 590 avio_rb32(pb); /* next track ID */
2083
2084 590 return 0;
2085 }
2086
2087 7 static void set_last_stream_little_endian(AVFormatContext *fc)
2088 {
2089 AVStream *st;
2090
2091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (fc->nb_streams < 1)
2092 return;
2093 7 st = fc->streams[fc->nb_streams-1];
2094
2095
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) {
2096 5 case AV_CODEC_ID_PCM_S16BE:
2097 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2098 5 break;
2099 1 case AV_CODEC_ID_PCM_S24BE:
2100 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
2101 1 break;
2102 case AV_CODEC_ID_PCM_S32BE:
2103 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
2104 break;
2105 1 case AV_CODEC_ID_PCM_F32BE:
2106 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
2107 1 break;
2108 case AV_CODEC_ID_PCM_F64BE:
2109 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
2110 break;
2111 default:
2112 break;
2113 }
2114 }
2115
2116 5 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2117 {
2118 5 int little_endian = avio_rb16(pb) & 0xFF;
2119 5 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
2120
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (little_endian == 1)
2121 1 set_last_stream_little_endian(c->fc);
2122 5 return 0;
2123 }
2124
2125 6 static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2126 {
2127 int format_flags;
2128 int version, flags;
2129 int pcm_sample_size;
2130 6 AVFormatContext *fc = c->fc;
2131 AVStream *st;
2132 MOVStreamContext *sc;
2133
2134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 6) {
2135 av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n");
2136 return AVERROR_INVALIDDATA;
2137 }
2138
2139 6 version = avio_r8(pb);
2140 6 flags = avio_rb24(pb);
2141
2142
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) {
2143 av_log(c->fc, AV_LOG_ERROR,
2144 "Unsupported 'pcmC' box with version %d, flags: %x",
2145 version, flags);
2146 return AVERROR_INVALIDDATA;
2147 }
2148
2149 6 format_flags = avio_r8(pb);
2150 6 pcm_sample_size = avio_r8(pb);
2151
2152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fc->nb_streams < 1)
2153 return AVERROR_INVALIDDATA;
2154
2155 6 st = fc->streams[fc->nb_streams - 1];
2156 6 sc = st->priv_data;
2157
2158
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (sc->format == MOV_MP4_FPCM_TAG) {
2159
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (pcm_sample_size) {
2160 1 case 32:
2161 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE;
2162 1 break;
2163 case 64:
2164 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE;
2165 break;
2166 default:
2167 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2168 pcm_sample_size,
2169 av_fourcc2str(sc->format));
2170 return AVERROR_INVALIDDATA;
2171 }
2172
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (sc->format == MOV_MP4_IPCM_TAG) {
2173
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 switch (pcm_sample_size) {
2174 5 case 16:
2175 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2176 5 break;
2177 case 24:
2178 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
2179 break;
2180 case 32:
2181 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
2182 break;
2183 default:
2184 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2185 pcm_sample_size,
2186 av_fourcc2str(sc->format));
2187 return AVERROR_INVALIDDATA;
2188 }
2189 } else {
2190 av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n",
2191 av_fourcc2str(sc->format));
2192 return AVERROR_INVALIDDATA;
2193 }
2194
2195
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
2196 6 set_last_stream_little_endian(c->fc);
2197 6 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2198
2199 6 return 0;
2200 }
2201
2202 55 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2203 {
2204 AVStream *st;
2205 55 HEIFItem *item = NULL;
2206 55 char color_parameter_type[5] = { 0 };
2207 uint16_t color_primaries, color_trc, color_matrix;
2208 int ret;
2209
2210 55 st = get_curr_st(c);
2211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
55 if (!st) {
2212 item = get_heif_item(c, c->cur_item_id);
2213 if (!item)
2214 return 0;
2215 }
2216
2217 55 ret = ffio_read_size(pb, color_parameter_type, 4);
2218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
55 if (ret < 0)
2219 return ret;
2220
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 22 times.
55 if (strncmp(color_parameter_type, "nclx", 4) &&
2221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 strncmp(color_parameter_type, "nclc", 4) &&
2222 strncmp(color_parameter_type, "prof", 4)) {
2223 av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
2224 color_parameter_type);
2225 return 0;
2226 }
2227
2228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
55 if (!strncmp(color_parameter_type, "prof", 4)) {
2229 AVPacketSideData *sd;
2230 uint8_t *icc_profile;
2231 if (st) {
2232 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
2233 &st->codecpar->nb_coded_side_data,
2234 AV_PKT_DATA_ICC_PROFILE,
2235 atom.size - 4, 0);
2236 if (!sd)
2237 return AVERROR(ENOMEM);
2238 icc_profile = sd->data;
2239 } else {
2240 if (c->heif_icc_profile_items >= c->fc->max_streams) {
2241 av_log(c->fc, AV_LOG_WARNING,
2242 "HEIF ICC profile copies exceed cap %d; ignoring further items\n",
2243 c->fc->max_streams);
2244 return 0;
2245 }
2246 av_freep(&item->icc_profile);
2247 icc_profile = item->icc_profile = av_malloc(atom.size - 4);
2248 if (!icc_profile) {
2249 item->icc_profile_size = 0;
2250 return AVERROR(ENOMEM);
2251 }
2252 item->icc_profile_size = atom.size - 4;
2253 c->heif_icc_profile_items++;
2254 }
2255 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
2256 if (ret < 0)
2257 return ret;
2258
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 } else if (st) {
2259 55 color_primaries = avio_rb16(pb);
2260 55 color_trc = avio_rb16(pb);
2261 55 color_matrix = avio_rb16(pb);
2262
2263 55 av_log(c->fc, AV_LOG_TRACE,
2264 "%s: pri %d trc %d matrix %d",
2265 color_parameter_type, color_primaries, color_trc, color_matrix);
2266
2267
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 33 times.
55 if (!strncmp(color_parameter_type, "nclx", 4)) {
2268 22 uint8_t color_range = avio_r8(pb) >> 7;
2269 22 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2270
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 20 times.
22 if (color_range)
2271 2 st->codecpar->color_range = AVCOL_RANGE_JPEG;
2272 else
2273 20 st->codecpar->color_range = AVCOL_RANGE_MPEG;
2274 }
2275
2276
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 55 times.
55 if (!av_color_primaries_name(color_primaries))
2277 color_primaries = AVCOL_PRI_UNSPECIFIED;
2278
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 55 times.
55 if (!av_color_transfer_name(color_trc))
2279 color_trc = AVCOL_TRC_UNSPECIFIED;
2280
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 55 times.
55 if (!av_color_space_name(color_matrix))
2281 color_matrix = AVCOL_SPC_UNSPECIFIED;
2282
2283 55 st->codecpar->color_primaries = color_primaries;
2284 55 st->codecpar->color_trc = color_trc;
2285 55 st->codecpar->color_space = color_matrix;
2286 55 av_log(c->fc, AV_LOG_TRACE, "\n");
2287 }
2288 55 return 0;
2289 }
2290
2291 118 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2292 {
2293 AVStream *st;
2294 unsigned mov_field_order;
2295 118 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2296
2297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (c->fc->nb_streams < 1) // will happen with jp2 files
2298 return 0;
2299 118 st = c->fc->streams[c->fc->nb_streams-1];
2300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (atom.size < 2)
2301 return AVERROR_INVALIDDATA;
2302 118 mov_field_order = avio_rb16(pb);
2303
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 22 times.
118 if ((mov_field_order & 0xFF00) == 0x0100)
2304 96 decoded_field_order = AV_FIELD_PROGRESSIVE;
2305
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 else if ((mov_field_order & 0xFF00) == 0x0200) {
2306
3/5
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
22 switch (mov_field_order & 0xFF) {
2307 1 case 0x01: decoded_field_order = AV_FIELD_TT;
2308 1 break;
2309 case 0x06: decoded_field_order = AV_FIELD_BB;
2310 break;
2311 1 case 0x09: decoded_field_order = AV_FIELD_TB;
2312 1 break;
2313 20 case 0x0E: decoded_field_order = AV_FIELD_BT;
2314 20 break;
2315 }
2316 }
2317
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
118 if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) {
2318 av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
2319 }
2320 118 st->codecpar->field_order = decoded_field_order;
2321
2322 118 return 0;
2323 }
2324
2325 69 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
2326 {
2327 69 int err = 0;
2328 69 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
2329
2/4
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
69 if (size > INT_MAX || (uint64_t)atom.size > INT_MAX)
2330 return AVERROR_INVALIDDATA;
2331
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
69 if ((err = av_reallocp(&par->extradata, size)) < 0) {
2332 par->extradata_size = 0;
2333 return err;
2334 }
2335 69 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
2336 69 return 0;
2337 }
2338
2339 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
2340 65 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2341 AVCodecParameters *par, uint8_t *buf)
2342 {
2343 65 int64_t result = atom.size;
2344 int err;
2345
2346 65 AV_WB32(buf , atom.size + 8);
2347 65 AV_WL32(buf + 4, atom.type);
2348 65 err = ffio_read_size(pb, buf + 8, atom.size);
2349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (err < 0) {
2350 par->extradata_size -= atom.size;
2351 return err;
2352
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 } else if (err < atom.size) {
2353 av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
2354 par->extradata_size -= atom.size - err;
2355 result = err;
2356 }
2357 65 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2358 65 return result;
2359 }
2360
2361 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
2362 58 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2363 enum AVCodecID codec_id)
2364 {
2365 AVStream *st;
2366 uint64_t original_size;
2367 int err;
2368
2369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (c->fc->nb_streams < 1) // will happen with jp2 files
2370 return 0;
2371 58 st = c->fc->streams[c->fc->nb_streams-1];
2372
2373
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
58 if (st->codecpar->codec_id != codec_id)
2374 19 return 0; /* unexpected codec_id - don't mess with extradata */
2375
2376 39 original_size = st->codecpar->extradata_size;
2377 39 err = mov_realloc_extradata(st->codecpar, atom);
2378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err)
2379 return err;
2380
2381 39 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
2382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err < 0)
2383 return err;
2384 39 return 0; // Note: this is the original behavior to ignore truncation.
2385 }
2386
2387 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
2388 16 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2389 {
2390 16 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
2391 }
2392
2393 static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2394 {
2395 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS);
2396 }
2397
2398 static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2399 {
2400 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
2401 }
2402
2403 static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2404 {
2405 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
2406 }
2407
2408 19 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2409 {
2410 19 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
2411
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!ret)
2412 19 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
2413 19 return ret;
2414 }
2415
2416 static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2417 {
2418 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
2419
2420 if (!ret && c->fc->nb_streams >= 1) {
2421 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2422 if (par->extradata_size >= 40) {
2423 par->height = AV_RB16(&par->extradata[36]);
2424 par->width = AV_RB16(&par->extradata[38]);
2425 }
2426 }
2427 return ret;
2428 }
2429
2430 16 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2431 {
2432
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (c->fc->nb_streams >= 1) {
2433 16 AVStream *const st = c->fc->streams[c->fc->nb_streams - 1];
2434 16 FFStream *const sti = ffstream(st);
2435 16 AVCodecParameters *par = st->codecpar;
2436
2437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
2438 par->codec_id == AV_CODEC_ID_H264 &&
2439 atom.size > 11) {
2440 int cid;
2441 avio_skip(pb, 10);
2442 cid = avio_rb16(pb);
2443 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
2444 if (cid == 0xd4d || cid == 0xd4e)
2445 par->width = 1440;
2446 return 0;
2447
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
2448
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
2449
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
2450
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 atom.size >= 24) {
2451 int num, den;
2452 13 avio_skip(pb, 12);
2453 13 num = avio_rb32(pb);
2454 13 den = avio_rb32(pb);
2455
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)
2456 return 0;
2457
2/3
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
13 switch (avio_rb32(pb)) {
2458 12 case 2:
2459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (den >= INT_MAX / 2)
2460 return 0;
2461 12 den *= 2;
2462 av_fallthrough;
2463 13 case 1:
2464 13 sti->display_aspect_ratio = (AVRational){ num, den };
2465 av_fallthrough;
2466 13 default:
2467 13 return 0;
2468 }
2469 }
2470 }
2471
2472 3 return mov_read_avid(c, pb, atom);
2473 }
2474
2475 26 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2476 {
2477 26 int ret = 0;
2478 26 int length = 0;
2479 uint64_t original_size;
2480
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (c->fc->nb_streams >= 1) {
2481 26 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (par->codec_id == AV_CODEC_ID_H264)
2483 return 0;
2484
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (atom.size == 16) {
2485 26 original_size = par->extradata_size;
2486 26 ret = mov_realloc_extradata(par, atom);
2487
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!ret) {
2488 26 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
2489
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (length == atom.size) {
2490 26 const uint8_t range_value = par->extradata[original_size + 19];
2491
1/3
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
26 switch (range_value) {
2492 26 case 1:
2493 26 par->color_range = AVCOL_RANGE_MPEG;
2494 26 break;
2495 case 2:
2496 par->color_range = AVCOL_RANGE_JPEG;
2497 break;
2498 default:
2499 av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
2500 break;
2501 }
2502 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
2503 } else {
2504 /* For some reason the whole atom was not added to the extradata */
2505 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
2506 }
2507 } else {
2508 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
2509 }
2510 } else {
2511 av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
2512 }
2513 }
2514
2515 26 return ret;
2516 }
2517
2518 4 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2519 {
2520 4 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
2521 }
2522
2523 33 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2524 {
2525 AVStream *st;
2526 int ret;
2527
2528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (c->fc->nb_streams < 1)
2529 return 0;
2530 33 st = c->fc->streams[c->fc->nb_streams-1];
2531
2532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if ((uint64_t)atom.size > (1<<30))
2533 return AVERROR_INVALIDDATA;
2534
2535
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 2 times.
33 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2536
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
2538 // pass all frma atom to codec, needed at least for QDMC and QDM2
2539 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2541 return ret;
2542
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 } else if (atom.size > 8) { /* to read frma, esds atoms */
2543
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
31 if (st->codecpar->codec_id == AV_CODEC_ID_ALAC && atom.size >= 24) {
2544 uint64_t buffer;
2545 10 ret = ffio_ensure_seekback(pb, 8);
2546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2547 return ret;
2548 10 buffer = avio_rb64(pb);
2549 10 atom.size -= 8;
2550
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
2551
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 <= atom.size
2552
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 >= 8) {
2553 10 avio_skip(pb, -8);
2554 10 atom.size += 8;
2555 } else if (!st->codecpar->extradata_size) {
2556 #define ALAC_EXTRADATA_SIZE 36
2557 st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
2558 if (!st->codecpar->extradata)
2559 return AVERROR(ENOMEM);
2560 st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
2561 AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
2562 AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
2563 AV_WB64(st->codecpar->extradata + 12, buffer);
2564 avio_read(pb, st->codecpar->extradata + 20, 16);
2565 avio_skip(pb, atom.size - 24);
2566 return 0;
2567 }
2568 }
2569
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 if ((ret = mov_read_default(c, pb, atom)) < 0)
2570 return ret;
2571 } else
2572 avio_skip(pb, atom.size);
2573 33 return 0;
2574 }
2575
2576 /**
2577 * This function reads atom content and puts data in extradata without tag
2578 * nor size unlike mov_read_extradata.
2579 */
2580 199 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2581 {
2582 AVStream *st;
2583 int ret;
2584
2585 199 st = get_curr_st(c);
2586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 199 times.
199 if (!st)
2587 return 0;
2588
2589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 199 times.
199 if ((uint64_t)atom.size > (1<<30))
2590 return AVERROR_INVALIDDATA;
2591
2592
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 198 times.
199 if (atom.type == MKTAG('v','v','c','C')) {
2593 1 avio_skip(pb, 4);
2594 1 atom.size -= 4;
2595 }
2596
2597
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 4 times.
199 if (atom.size >= 10) {
2598 // Broken files created by legacy versions of libavformat will
2599 // wrap a whole fiel atom inside of a glbl atom.
2600 195 unsigned size = avio_rb32(pb);
2601 195 unsigned type = avio_rl32(pb);
2602
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 195 times.
195 if (avio_feof(pb))
2603 return AVERROR_INVALIDDATA;
2604 195 avio_seek(pb, -8, SEEK_CUR);
2605
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 185 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
195 if (type == MKTAG('f','i','e','l') && size == atom.size)
2606 10 return mov_read_default(c, pb, atom);
2607 }
2608
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 189 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
189 if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
2609 av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
2610 return 0;
2611 }
2612 189 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 189 times.
189 if (ret < 0)
2614 return ret;
2615
3/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 117 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 72 times.
189 if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
2616 /* HEVC-based Dolby Vision derived from hvc1.
2617 Happens to match with an identifier
2618 previously utilized for DV. Thus, if we have
2619 the hvcC extradata box available as specified,
2620 set codec to HEVC */
2621 st->codecpar->codec_id = AV_CODEC_ID_HEVC;
2622
2623 189 return 0;
2624 }
2625
2626 2 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2627 {
2628 AVStream *st;
2629 uint8_t profile_level;
2630 int ret;
2631
2632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
2633 return 0;
2634 2 st = c->fc->streams[c->fc->nb_streams-1];
2635
2636
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)
2637 return AVERROR_INVALIDDATA;
2638
2639 2 profile_level = avio_r8(pb);
2640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((profile_level & 0xf0) != 0xc0)
2641 return 0;
2642
2643 2 avio_seek(pb, 6, SEEK_CUR);
2644 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
2645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2646 return ret;
2647
2648 2 return 0;
2649 }
2650
2651 52 static int mov_find_tref_id(const MovTref *tag, uint32_t id)
2652 {
2653
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 33 times.
64 for (int i = 0; i < tag->nb_id; i++) {
2654
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 12 times.
31 if (tag->id[i] == id)
2655 19 return 1;
2656 }
2657 33 return 0;
2658 }
2659
2660 33 static int mov_add_tref_id(MovTref *tag, uint32_t id)
2661 {
2662 33 int ret = mov_find_tref_id(tag, id);
2663
2664
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if (!ret) {
2665 33 uint32_t *tmp = av_realloc_array(tag->id, tag->nb_id + 1, sizeof(*tag->id));
2666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (!tmp)
2667 return AVERROR(ENOMEM);
2668 33 tag->id = tmp;
2669 33 tag->id[tag->nb_id++] = id;
2670 }
2671
2672 33 return 0;
2673 }
2674
2675 1433 static MovTref *mov_find_tref_tag(const MOVStreamContext *sc, uint32_t name)
2676 {
2677
2/2
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 1383 times.
1538 for (int i = 0; i < sc->nb_tref_tags; i++) {
2678 155 MovTref *entry = &sc->tref_tags[i];
2679
2680
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 105 times.
155 if (entry->name == name)
2681 50 return entry;
2682 }
2683 1383 return NULL;
2684 }
2685
2686 29 static MovTref *mov_add_tref_tag(MOVStreamContext *sc, uint32_t name)
2687 {
2688 29 MovTref *tag = mov_find_tref_tag(sc, name);
2689
2690
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (!tag) {
2691 29 MovTref *tmp = av_realloc_array(sc->tref_tags, sc->nb_tref_tags + 1,
2692 sizeof(*sc->tref_tags));
2693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (!tmp)
2694 return NULL;
2695 29 sc->tref_tags = tmp;
2696 29 tag = &sc->tref_tags[sc->nb_tref_tags++];
2697 29 *tag = (MovTref){ .name = name };
2698 }
2699
2700 29 return tag;
2701 }
2702
2703 11 static int mov_read_cdsc_rndr(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2704 {
2705 AVStream* st;
2706 MOVStreamContext* sc;
2707
2708
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
2709 return 0;
2710
2711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size > 4) {
2712 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type cdsc/rndr is supported\n");
2713 return AVERROR_PATCHWELCOME;
2714 }
2715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 4)
2716 return AVERROR_INVALIDDATA;
2717
2718 11 st = get_curr_st(c);
2719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!st)
2720 return AVERROR_INVALIDDATA;
2721 11 sc = st->priv_data;
2722
2723 11 MovTref *tag = mov_add_tref_tag(sc, atom.type);
2724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!tag)
2725 return AVERROR(ENOMEM);
2726
2727 11 int ret = mov_add_tref_id(tag, avio_rb32(pb));
2728
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0)
2729 return ret;
2730
2731 11 return 0;
2732 }
2733
2734 static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2735 {
2736 AVStream* st;
2737 MOVStreamContext* sc;
2738
2739 if (c->fc->nb_streams < 1)
2740 return 0;
2741
2742 /* For SBAS this should be fine - though beware if someone implements a
2743 * tref atom processor that doesn't drop down to default then this may
2744 * be lost. */
2745 if (atom.size > 4) {
2746 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2747 return AVERROR_PATCHWELCOME;
2748 }
2749 if (atom.size < 4)
2750 return AVERROR_INVALIDDATA;
2751
2752 st = c->fc->streams[c->fc->nb_streams - 1];
2753 sc = st->priv_data;
2754
2755 MovTref *tag = mov_add_tref_tag(sc, atom.type);
2756 if (!tag)
2757 return AVERROR(ENOMEM);
2758
2759 int ret = mov_add_tref_id(tag, avio_rb32(pb));
2760 if (ret < 0)
2761 return ret;
2762
2763 return 0;
2764 }
2765
2766 static int mov_read_vdep(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2767 {
2768 AVStream* st;
2769 MOVStreamContext* sc;
2770
2771 if (c->fc->nb_streams < 1)
2772 return 0;
2773
2774 if (atom.size > 4)
2775 av_log(c->fc, AV_LOG_WARNING, "More than one vdep reference is not supported.\n");
2776 if (atom.size < 4)
2777 return AVERROR_INVALIDDATA;
2778
2779 st = c->fc->streams[c->fc->nb_streams - 1];
2780 sc = st->priv_data;
2781
2782 MovTref *tag = mov_add_tref_tag(sc, atom.type);
2783 if (!tag)
2784 return AVERROR(ENOMEM);
2785
2786 int ret = mov_add_tref_id(tag, avio_rb32(pb));
2787 if (ret < 0)
2788 return ret;
2789
2790 return 0;
2791 }
2792
2793 /**
2794 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2795 * but can have extradata appended at the end after the 40 bytes belonging
2796 * to the struct.
2797 */
2798 static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2799 {
2800 AVStream *st;
2801 int ret;
2802
2803 if (c->fc->nb_streams < 1)
2804 return 0;
2805 if (atom.size <= 40)
2806 return 0;
2807 st = c->fc->streams[c->fc->nb_streams-1];
2808
2809 if ((uint64_t)atom.size > (1<<30))
2810 return AVERROR_INVALIDDATA;
2811
2812 avio_skip(pb, 40);
2813 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
2814 if (ret < 0)
2815 return ret;
2816
2817 return 0;
2818 }
2819
2820 712 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2821 {
2822 AVStream *st;
2823 MOVStreamContext *sc;
2824 unsigned int i, entries;
2825
2826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (c->trak_index < 0) {
2827 av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
2828 return 0;
2829 }
2830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (c->fc->nb_streams < 1)
2831 return 0;
2832 712 st = c->fc->streams[c->fc->nb_streams-1];
2833 712 sc = st->priv_data;
2834
2835 712 avio_r8(pb); /* version */
2836 712 avio_rb24(pb); /* flags */
2837
2838 // Clamp allocation size for `chunk_offsets` -- don't throw an error for an
2839 // invalid count since the EOF path doesn't throw either.
2840 712 entries = avio_rb32(pb);
2841 712 entries =
2842
2/2
✓ Branch 0 taken 707 times.
✓ Branch 1 taken 5 times.
712 FFMIN(entries,
2843 FFMAX(0, (atom.size - 8) /
2844 (atom.type == MKTAG('s', 't', 'c', 'o') ? 4 : 8)));
2845
2846
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 682 times.
712 if (!entries)
2847 30 return 0;
2848
2849
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 682 times.
682 if (sc->chunk_offsets) {
2850 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2851 return 0;
2852 }
2853
2854 682 av_free(sc->chunk_offsets);
2855 682 sc->chunk_count = 0;
2856 682 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 682 times.
682 if (!sc->chunk_offsets)
2858 return AVERROR(ENOMEM);
2859 682 sc->chunk_count = entries;
2860
2861
2/2
✓ Branch 0 taken 678 times.
✓ Branch 1 taken 4 times.
682 if (atom.type == MKTAG('s','t','c','o'))
2862
3/4
✓ Branch 0 taken 43934 times.
✓ Branch 1 taken 678 times.
✓ Branch 2 taken 43934 times.
✗ Branch 3 not taken.
44612 for (i = 0; i < entries && !pb->eof_reached; i++)
2863 43934 sc->chunk_offsets[i] = avio_rb32(pb);
2864
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (atom.type == MKTAG('c','o','6','4'))
2865
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++) {
2866 136336 sc->chunk_offsets[i] = avio_rb64(pb);
2867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136336 times.
136336 if (sc->chunk_offsets[i] < 0) {
2868 av_log(c->fc, AV_LOG_WARNING, "Impossible chunk_offset\n");
2869 sc->chunk_offsets[i] = 0;
2870 }
2871 }
2872 else
2873 return AVERROR_INVALIDDATA;
2874
2875 682 sc->chunk_count = i;
2876
2877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 682 times.
682 if (pb->eof_reached) {
2878 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2879 return AVERROR_EOF;
2880 }
2881
2882 682 return 0;
2883 }
2884
2885 782 static int mov_codec_id(AVStream *st, uint32_t format)
2886 {
2887 782 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2888
2889
2/2
✓ Branch 0 taken 519 times.
✓ Branch 1 taken 263 times.
782 if (id <= 0 &&
2890
2/2
✓ Branch 0 taken 516 times.
✓ Branch 1 taken 3 times.
519 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 516 times.
516 (format & 0xFFFF) == 'T' + ('S' << 8)))
2892 3 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2893
2894
4/4
✓ Branch 0 taken 344 times.
✓ Branch 1 taken 438 times.
✓ Branch 2 taken 266 times.
✓ Branch 3 taken 78 times.
782 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2895 266 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2896
3/4
✓ Branch 0 taken 496 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 496 times.
✗ Branch 3 not taken.
516 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2897 /* skip old ASF MPEG-4 tag */
2898
2/2
✓ Branch 0 taken 492 times.
✓ Branch 1 taken 4 times.
496 format && format != MKTAG('m','p','4','s')) {
2899 492 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2900
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 423 times.
492 if (id <= 0)
2901 69 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2902
2/2
✓ Branch 0 taken 427 times.
✓ Branch 1 taken 65 times.
492 if (id > 0)
2903 427 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2904
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 53 times.
65 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2905
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
12 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2907 53 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2908
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 6 times.
53 if (id <= 0) {
2909
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 4 times.
90 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2910
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 4 times.
90 AV_CODEC_ID_TTML : id;
2911 }
2912
2913
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 39 times.
53 if (id > 0)
2914 14 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2915 else
2916 39 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2917 }
2918 }
2919
2920 782 st->codecpar->codec_tag = format;
2921
2922 782 return id;
2923 }
2924
2925 384 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2926 AVStream *st, MOVStreamContext *sc)
2927 {
2928 384 uint8_t codec_name[32] = { 0 };
2929 int64_t stsd_start;
2930 unsigned int len;
2931 384 uint32_t id = 0;
2932
2933 /* The first 16 bytes of the video sample description are already
2934 * read in ff_mov_read_stsd_entries() */
2935 384 stsd_start = avio_tell(pb) - 16;
2936
2937
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 258 times.
384 if (c->isom) {
2938 126 avio_skip(pb, 2); /* pre_defined */
2939 126 avio_skip(pb, 2); /* reserved */
2940 126 avio_skip(pb, 12); /* pre_defined */
2941 } else {
2942 258 avio_rb16(pb); /* version */
2943 258 avio_rb16(pb); /* revision level */
2944 258 id = avio_rl32(pb); /* vendor */
2945 258 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2946 258 avio_rb32(pb); /* temporal quality */
2947 258 avio_rb32(pb); /* spatial quality */
2948 }
2949
2950 384 st->codecpar->width = avio_rb16(pb); /* width */
2951 384 st->codecpar->height = avio_rb16(pb); /* height */
2952
2953 384 avio_rb32(pb); /* horiz resolution */
2954 384 avio_rb32(pb); /* vert resolution */
2955 384 avio_rb32(pb); /* data size, always 0 */
2956 384 avio_rb16(pb); /* frames per samples */
2957
2958 384 len = avio_r8(pb); /* codec name, pascal string */
2959
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 383 times.
384 if (len > 31)
2960 1 len = 31;
2961 384 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2962
2/2
✓ Branch 0 taken 381 times.
✓ Branch 1 taken 3 times.
384 if (len < 31)
2963 381 avio_skip(pb, 31 - len);
2964
2965
2/2
✓ Branch 0 taken 292 times.
✓ Branch 1 taken 92 times.
384 if (codec_name[0])
2966 292 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2967
2968 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2970 st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2971 st->codecpar->width &= ~1;
2972 st->codecpar->height &= ~1;
2973 }
2974 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2976 !strncmp(codec_name, "Sorenson H263", 13))
2977 st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2978
2979 384 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2980
2981 384 avio_seek(pb, stsd_start, SEEK_SET);
2982
2983
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 366 times.
384 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2984 18 st->codecpar->bits_per_coded_sample &= 0x1F;
2985 18 sc->has_palette = 1;
2986 }
2987 384 }
2988
2989 286 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2990 AVStream *st, MOVStreamContext *sc)
2991 {
2992 int bits_per_sample, flags;
2993 286 uint16_t version = avio_rb16(pb);
2994 286 uint32_t id = 0;
2995 286 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2996 int channel_count;
2997
2998
2/2
✓ Branch 0 taken 199 times.
✓ Branch 1 taken 87 times.
286 if (c->isom)
2999 199 avio_skip(pb, 6); /* reserved */
3000 else {
3001 87 avio_rb16(pb); /* revision level */
3002 87 id = avio_rl32(pb); /* vendor */
3003 87 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
3004 }
3005
3006 286 channel_count = avio_rb16(pb);
3007
3008 286 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3009 286 st->codecpar->ch_layout.nb_channels = channel_count;
3010 286 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
3011 286 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
3012
3013 286 sc->audio_cid = avio_rb16(pb);
3014 286 avio_rb16(pb); /* packet size = 0 */
3015
3016 286 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
3017
3018 // Read QT version 1 fields. In version 0 these do not exist.
3019 286 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
3020
3/4
✓ Branch 0 taken 199 times.
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 199 times.
✗ Branch 3 not taken.
286 if (!c->isom ||
3021
1/2
✓ Branch 0 taken 199 times.
✗ Branch 1 not taken.
199 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
3022
4/4
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 190 times.
199 (sc->stsd_version == 0 && version > 0)) {
3023
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 42 times.
91 if (version == 1) {
3024 49 sc->samples_per_frame = avio_rb32(pb);
3025 49 avio_rb32(pb); /* bytes per packet */
3026 49 sc->bytes_per_frame = avio_rb32(pb);
3027 49 avio_rb32(pb); /* bytes per sample */
3028
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 38 times.
42 } else if (version == 2) {
3029 4 avio_rb32(pb); /* sizeof struct only */
3030 4 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
3031 4 channel_count = avio_rb32(pb);
3032 4 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3033 4 st->codecpar->ch_layout.nb_channels = channel_count;
3034 4 avio_rb32(pb); /* always 0x7F000000 */
3035 4 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
3036
3037 4 flags = avio_rb32(pb); /* lpcm format specific flag */
3038 4 sc->bytes_per_frame = avio_rb32(pb);
3039 4 sc->samples_per_frame = avio_rb32(pb);
3040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
3041 st->codecpar->codec_id =
3042 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
3043 flags);
3044 }
3045
6/6
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 49 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 25 times.
91 if (version == 0 || (version == 1 && sc->audio_cid != -2)) {
3046 /* can't correctly handle variable sized packet as audio unit */
3047
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 switch (st->codecpar->codec_id) {
3048 case AV_CODEC_ID_MP2:
3049 case AV_CODEC_ID_MP3:
3050 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
3051 break;
3052 }
3053 }
3054 }
3055
3056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 286 times.
286 if (sc->format == 0) {
3057 if (st->codecpar->bits_per_coded_sample == 8)
3058 st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
3059 else if (st->codecpar->bits_per_coded_sample == 16)
3060 st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
3061 }
3062
3063
7/7
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 242 times.
286 switch (st->codecpar->codec_id) {
3064 7 case AV_CODEC_ID_PCM_S8:
3065 case AV_CODEC_ID_PCM_U8:
3066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
3067 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
3068 7 break;
3069 21 case AV_CODEC_ID_PCM_S16LE:
3070 case AV_CODEC_ID_PCM_S16BE:
3071
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 19 times.
21 if (st->codecpar->bits_per_coded_sample == 8)
3072 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
3073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 else if (st->codecpar->bits_per_coded_sample == 24)
3074 st->codecpar->codec_id =
3075 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
3076 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
3077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 else if (st->codecpar->bits_per_coded_sample == 32)
3078 st->codecpar->codec_id =
3079 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
3080 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
3081 21 break;
3082 /* set values for old format before stsd version 1 appeared */
3083 2 case AV_CODEC_ID_MACE3:
3084 2 sc->samples_per_frame = 6;
3085 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
3086 2 break;
3087 8 case AV_CODEC_ID_MACE6:
3088 8 sc->samples_per_frame = 6;
3089 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
3090 8 break;
3091 5 case AV_CODEC_ID_ADPCM_IMA_QT:
3092 5 sc->samples_per_frame = 64;
3093 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
3094 5 break;
3095 1 case AV_CODEC_ID_GSM:
3096 1 sc->samples_per_frame = 160;
3097 1 sc->bytes_per_frame = 33;
3098 1 break;
3099 242 default:
3100 242 break;
3101 }
3102
3103 286 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
3104
3/4
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 236 times.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
286 if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->ch_layout.nb_channels <= INT_MAX) {
3105 50 st->codecpar->bits_per_coded_sample = bits_per_sample;
3106 50 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
3107 }
3108 286 }
3109
3110 15 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
3111 AVStream *st, MOVStreamContext *sc,
3112 int64_t size)
3113 {
3114 // ttxt stsd contains display flags, justification, background
3115 // color, fonts, and default styles, so fake an atom to read it
3116 15 MOVAtom fake_atom = { .size = size };
3117 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
3118 // in extradata unlike stpp MP4 TTML.
3119
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
3120
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
15 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
3121 11 mov_read_glbl(c, pb, fake_atom);
3122 15 st->codecpar->width = sc->width;
3123 15 st->codecpar->height = sc->height;
3124 15 }
3125
3126 43 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
3127 AVStream *st, MOVStreamContext *sc,
3128 int64_t size)
3129 {
3130 int ret;
3131
3132
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 24 times.
43 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
3133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if ((int)size != size)
3134 return AVERROR(ENOMEM);
3135
3136 19 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
3137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
3138 return ret;
3139
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (size > 16) {
3140 19 MOVStreamContext *tmcd_ctx = st->priv_data;
3141 int val;
3142 19 val = AV_RB32(st->codecpar->extradata + 4);
3143 19 tmcd_ctx->tmcd_flags = val;
3144 19 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
3145 19 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
3146 19 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
3147
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (size > 30) {
3148 4 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
3149 4 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
3150
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) {
3151 4 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
3152
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 &&
3153
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 st->codecpar->extradata[30] /* Don't add empty string */) {
3154 4 char *reel_name = av_malloc(str_size + 1);
3155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!reel_name)
3156 return AVERROR(ENOMEM);
3157 4 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
3158 4 reel_name[str_size] = 0; /* Add null terminator */
3159 4 av_dict_set(&st->metadata, "reel_name", reel_name,
3160 AV_DICT_DONT_STRDUP_VAL);
3161 }
3162 }
3163 }
3164 }
3165
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 } else if (st->codecpar->codec_id == AV_CODEC_ID_ITUT_T35) {
3166 2 int t35_identifier_length = avio_r8(pb);
3167
3168
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (t35_identifier_length <= 0 || t35_identifier_length >= size)
3169 return AVERROR_INVALIDDATA;
3170
3171 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, t35_identifier_length);
3172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
3173 return ret;
3174
3175 2 int hrsd_len = size - t35_identifier_length - 1;
3176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (hrsd_len > 0) {
3177 uint8_t *hrsd_str = av_malloc(hrsd_len + 1);
3178 if (!hrsd_str)
3179 return AVERROR(ENOMEM);
3180
3181 ret = ffio_read_size(pb, hrsd_str, hrsd_len);
3182 if (ret < 0) {
3183 av_free(hrsd_str);
3184 return ret;
3185 }
3186 if (hrsd_str[0]) {
3187 hrsd_str[hrsd_len] = 0;
3188 ret = av_dict_set(&st->metadata, "description", hrsd_str, AV_DICT_DONT_OVERWRITE);
3189 }
3190 av_free(hrsd_str);
3191 }
3192 } else {
3193 /* other codec type, just skip (rtp, mp4s ...) */
3194 22 avio_skip(pb, size);
3195 }
3196 43 return 0;
3197 }
3198
3199 712 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
3200 AVStream *st, MOVStreamContext *sc)
3201 {
3202 712 FFStream *const sti = ffstream(st);
3203
3204
2/2
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 426 times.
712 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
3205
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 286 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
286 !st->codecpar->sample_rate && sc->time_scale > 1)
3206 st->codecpar->sample_rate = sc->time_scale;
3207
3208 /* special codec parameters handling */
3209
7/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 15 times.
✓ Branch 6 taken 16 times.
✓ Branch 7 taken 14 times.
✓ Branch 8 taken 118 times.
✓ Branch 9 taken 535 times.
712 switch (st->codecpar->codec_id) {
3210 #if CONFIG_DV_DEMUXER
3211 case AV_CODEC_ID_DVAUDIO:
3212 if (c->dv_fctx) {
3213 avpriv_request_sample(c->fc, "multiple DV audio streams");
3214 return AVERROR(ENOSYS);
3215 }
3216
3217 c->dv_fctx = avformat_alloc_context();
3218 if (!c->dv_fctx) {
3219 av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
3220 return AVERROR(ENOMEM);
3221 }
3222 c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
3223 if (!c->dv_demux) {
3224 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
3225 return AVERROR(ENOMEM);
3226 }
3227 sc->dv_audio_container = 1;
3228 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
3229 break;
3230 #endif
3231 /* no ifdef since parameters are always those */
3232 case AV_CODEC_ID_QCELP:
3233 av_channel_layout_uninit(&st->codecpar->ch_layout);
3234 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3235 // force sample rate for qcelp when not stored in mov
3236 if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
3237 st->codecpar->sample_rate = 8000;
3238 // FIXME: Why is the following needed for some files?
3239 sc->samples_per_frame = 160;
3240 if (!sc->bytes_per_frame)
3241 sc->bytes_per_frame = 35;
3242 break;
3243 case AV_CODEC_ID_AMR_NB:
3244 av_channel_layout_uninit(&st->codecpar->ch_layout);
3245 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3246 /* force sample rate for amr, stsd in 3gp does not store sample rate */
3247 st->codecpar->sample_rate = 8000;
3248 break;
3249 11 case AV_CODEC_ID_AMR_WB:
3250 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
3251 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3252 11 st->codecpar->sample_rate = 16000;
3253 11 break;
3254 3 case AV_CODEC_ID_MP2:
3255 case AV_CODEC_ID_MP3:
3256 /* force type after stsd for m1a hdlr */
3257 3 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
3258 3 break;
3259 15 case AV_CODEC_ID_GSM:
3260 case AV_CODEC_ID_ADPCM_MS:
3261 case AV_CODEC_ID_ADPCM_IMA_WAV:
3262 case AV_CODEC_ID_ILBC:
3263 case AV_CODEC_ID_MACE3:
3264 case AV_CODEC_ID_MACE6:
3265 case AV_CODEC_ID_QDM2:
3266 15 st->codecpar->block_align = sc->bytes_per_frame;
3267 15 break;
3268 16 case AV_CODEC_ID_ALAC:
3269
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
3270 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
3271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
3272 av_channel_layout_uninit(&st->codecpar->ch_layout);
3273 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3274 st->codecpar->ch_layout.nb_channels = channel_count;
3275 }
3276 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
3277 }
3278 16 break;
3279 14 case AV_CODEC_ID_AC3:
3280 case AV_CODEC_ID_EAC3:
3281 case AV_CODEC_ID_MPEG1VIDEO:
3282 case AV_CODEC_ID_VC1:
3283 case AV_CODEC_ID_VP8:
3284 case AV_CODEC_ID_VP9:
3285 14 sti->need_parsing = AVSTREAM_PARSE_FULL;
3286 14 break;
3287 118 case AV_CODEC_ID_PRORES_RAW:
3288 case AV_CODEC_ID_PRORES:
3289 case AV_CODEC_ID_APV:
3290 case AV_CODEC_ID_EVC:
3291 case AV_CODEC_ID_LCEVC:
3292 case AV_CODEC_ID_AV1:
3293 /* field_order detection of H264 requires parsing */
3294 case AV_CODEC_ID_H264:
3295 118 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3296 118 break;
3297 535 default:
3298 535 break;
3299 }
3300 712 return 0;
3301 }
3302
3303 729 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
3304 int codec_tag, int format,
3305 int64_t size)
3306 {
3307
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 712 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 16 times.
729 if (codec_tag &&
3308 1 (codec_tag != format &&
3309 // AVID 1:1 samples with differing data format and codec tag exist
3310
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
3311 // prores is allowed to have differing data format and codec tag
3312
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
3313 // so is dv (sigh)
3314
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
3315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 (c->fc->video_codec_id ? ff_codec_get_id(ff_codec_movvideo_tags, format) != c->fc->video_codec_id
3316 : codec_tag != MKTAG('j','p','e','g')))) {
3317 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3318 * export it as a separate AVStream but this needs a few changes
3319 * in the MOV demuxer, patch welcome. */
3320
3321 1 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3322 1 avio_skip(pb, size);
3323 1 return 1;
3324 }
3325
3326 728 return 0;
3327 }
3328
3329 728 static int mov_finalize_stsd_entry(MOVContext *c, AVStream *st)
3330 {
3331 int ret;
3332
3333 /* special codec parameters handling */
3334
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 638 times.
728 switch (st->codecpar->codec_id) {
3335 90 case AV_CODEC_ID_H264:
3336 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
3337
1/30
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
90 if (!st->codecpar->extradata_size && TAG_IS_AVCI(st->codecpar->codec_tag)) {
3338 ret = ff_generate_avci_extradata(st);
3339 if (ret < 0)
3340 return ret;
3341 }
3342 90 break;
3343 638 default:
3344 638 break;
3345 }
3346
3347 728 return 0;
3348 }
3349
3350 712 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3351 {
3352 AVStream *st;
3353 MOVStreamContext *sc;
3354 int pseudo_stream_id;
3355
3356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 av_assert0 (c->fc->nb_streams >= 1);
3357 712 st = c->fc->streams[c->fc->nb_streams-1];
3358 712 sc = st->priv_data;
3359
3360 712 for (pseudo_stream_id = 0;
3361
3/4
✓ Branch 0 taken 729 times.
✓ Branch 1 taken 712 times.
✓ Branch 2 taken 729 times.
✗ Branch 3 not taken.
1441 pseudo_stream_id < entries && !pb->eof_reached;
3362 729 pseudo_stream_id++) {
3363 //Parsing Sample description table
3364 enum AVCodecID id;
3365 729 int ret, dref_id = 1;
3366 729 MOVAtom a = { AV_RL32("stsd") };
3367 729 int64_t start_pos = avio_tell(pb);
3368 729 int64_t size = avio_rb32(pb); /* size */
3369 729 uint32_t format = avio_rl32(pb); /* data format */
3370
3371
1/2
✓ Branch 0 taken 729 times.
✗ Branch 1 not taken.
729 if (size >= 16) {
3372 729 avio_rb32(pb); /* reserved */
3373 729 avio_rb16(pb); /* reserved */
3374 729 dref_id = avio_rb16(pb);
3375 } else if (size <= 7) {
3376 av_log(c->fc, AV_LOG_ERROR,
3377 "invalid size %"PRId64" in stsd\n", size);
3378 return AVERROR_INVALIDDATA;
3379 }
3380
3381
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 728 times.
729 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3382 729 size - (avio_tell(pb) - start_pos))) {
3383 1 sc->stsd_count++;
3384 1 continue;
3385 }
3386
3387
2/2
✓ Branch 0 taken 712 times.
✓ Branch 1 taken 16 times.
728 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
3388 728 sc->dref_id= dref_id;
3389 728 sc->format = format;
3390
3391 728 id = mov_codec_id(st, format);
3392
3393 728 av_log(c->fc, AV_LOG_TRACE,
3394 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3395 728 av_fourcc2str(format), st->codecpar->codec_type);
3396
3397 728 st->codecpar->codec_id = id;
3398
2/2
✓ Branch 0 taken 384 times.
✓ Branch 1 taken 344 times.
728 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3399 384 mov_parse_stsd_video(c, pb, st, sc);
3400
2/2
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 58 times.
344 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3401 286 mov_parse_stsd_audio(c, pb, st, sc);
3402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 286 times.
286 if (st->codecpar->sample_rate < 0) {
3403 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3404 return AVERROR_INVALIDDATA;
3405 }
3406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 286 times.
286 if (st->codecpar->ch_layout.nb_channels < 0) {
3407 av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3408 return AVERROR_INVALIDDATA;
3409 }
3410
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 43 times.
58 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3411 15 mov_parse_stsd_subtitle(c, pb, st, sc,
3412 15 size - (avio_tell(pb) - start_pos));
3413 } else {
3414 43 ret = mov_parse_stsd_data(c, pb, st, sc,
3415 43 size - (avio_tell(pb) - start_pos));
3416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
3417 return ret;
3418 }
3419 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3420 728 a.size = size - (avio_tell(pb) - start_pos);
3421
2/2
✓ Branch 0 taken 572 times.
✓ Branch 1 taken 156 times.
728 if (a.size > 8) {
3422
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 572 times.
572 if ((ret = mov_read_default(c, pb, a)) < 0)
3423 return ret;
3424
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 155 times.
156 } else if (a.size > 0)
3425 1 avio_skip(pb, a.size);
3426
3427 728 ret = mov_finalize_stsd_entry(c, st);
3428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 728 times.
728 if (ret < 0)
3429 return ret;
3430
3431
3/4
✓ Branch 0 taken 728 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 428 times.
✓ Branch 3 taken 300 times.
728 if (sc->extradata && st->codecpar->extradata) {
3432 428 int extra_size = st->codecpar->extradata_size;
3433
3434 /* Move the current stream extradata to the stream context one. */
3435 428 sc->extradata_size[pseudo_stream_id] = extra_size;
3436 428 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3437 428 st->codecpar->extradata = NULL;
3438 428 st->codecpar->extradata_size = 0;
3439 }
3440 728 sc->stsd_count++;
3441 }
3442
3443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (pb->eof_reached) {
3444 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3445 return AVERROR_EOF;
3446 }
3447
3448 712 return 0;
3449 }
3450
3451 712 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3452 {
3453 AVStream *st;
3454 MOVStreamContext *sc;
3455 int ret, entries;
3456
3457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (c->fc->nb_streams < 1)
3458 return 0;
3459 712 st = c->fc->streams[c->fc->nb_streams - 1];
3460 712 sc = st->priv_data;
3461
3462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (sc->extradata) {
3463 av_log(c->fc, AV_LOG_ERROR,
3464 "Duplicate stsd found in this track.\n");
3465 return AVERROR_INVALIDDATA;
3466 }
3467
3468 712 sc->stsd_version = avio_r8(pb);
3469 712 avio_rb24(pb); /* flags */
3470 712 entries = avio_rb32(pb);
3471
3472 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3473
3/6
✓ Branch 0 taken 712 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 712 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 712 times.
712 if (entries <= 0 || entries > atom.size / 8 || entries > 1024) {
3474 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3475 return AVERROR_INVALIDDATA;
3476 }
3477
3478 /* Prepare space for hosting multiple extradata. */
3479 712 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (!sc->extradata)
3481 return AVERROR(ENOMEM);
3482
3483 712 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (!sc->extradata_size) {
3485 ret = AVERROR(ENOMEM);
3486 goto fail;
3487 }
3488
3489 712 ret = ff_mov_read_stsd_entries(c, pb, entries);
3490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (ret < 0)
3491 goto fail;
3492
3493 /* Restore back the primary extradata. */
3494 712 av_freep(&st->codecpar->extradata);
3495 712 st->codecpar->extradata_size = sc->extradata_size[0];
3496
2/2
✓ Branch 0 taken 413 times.
✓ Branch 1 taken 299 times.
712 if (sc->extradata_size[0]) {
3497 413 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 413 times.
413 if (!st->codecpar->extradata)
3499 return AVERROR(ENOMEM);
3500 413 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3501 }
3502
3503 712 return mov_finalize_stsd_codec(c, pb, st, sc);
3504 fail:
3505 if (sc->extradata) {
3506 int j;
3507 for (j = 0; j < sc->stsd_count; j++)
3508 av_freep(&sc->extradata[j]);
3509 }
3510
3511 sc->stsd_count = 0;
3512 av_freep(&sc->extradata);
3513 av_freep(&sc->extradata_size);
3514 return ret;
3515 }
3516
3517 712 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3518 {
3519 AVStream *st;
3520 MOVStreamContext *sc;
3521 unsigned int i, entries;
3522
3523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (c->trak_index < 0) {
3524 av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3525 return 0;
3526 }
3527
3528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (c->fc->nb_streams < 1)
3529 return 0;
3530 712 st = c->fc->streams[c->fc->nb_streams-1];
3531 712 sc = st->priv_data;
3532
3533 712 avio_r8(pb); /* version */
3534 712 avio_rb24(pb); /* flags */
3535
3536 712 entries = avio_rb32(pb);
3537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if ((uint64_t)entries * 12 + 4 > atom.size)
3538 return AVERROR_INVALIDDATA;
3539
3540 712 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3541
3542
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 683 times.
712 if (!entries)
3543 29 return 0;
3544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 683 times.
683 if (sc->stsc_data) {
3545 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3546 return 0;
3547 }
3548 683 av_free(sc->stsc_data);
3549 683 sc->stsc_count = 0;
3550 683 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 683 times.
683 if (!sc->stsc_data)
3552 return AVERROR(ENOMEM);
3553
3554
3/4
✓ Branch 0 taken 3910 times.
✓ Branch 1 taken 683 times.
✓ Branch 2 taken 3910 times.
✗ Branch 3 not taken.
4593 for (i = 0; i < entries && !pb->eof_reached; i++) {
3555 3910 sc->stsc_data[i].first = avio_rb32(pb);
3556 3910 sc->stsc_data[i].count = avio_rb32(pb);
3557 3910 sc->stsc_data[i].id = avio_rb32(pb);
3558 }
3559
3560 683 sc->stsc_count = i;
3561
2/2
✓ Branch 0 taken 3910 times.
✓ Branch 1 taken 683 times.
4593 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3562 3910 int64_t first_min = i + 1;
3563
5/6
✓ Branch 0 taken 3227 times.
✓ Branch 1 taken 683 times.
✓ Branch 2 taken 3227 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3227 times.
✓ Branch 5 taken 683 times.
3910 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
3564
1/2
✓ Branch 0 taken 3227 times.
✗ Branch 1 not taken.
3227 (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) ||
3565
1/2
✓ Branch 0 taken 3910 times.
✗ Branch 1 not taken.
3910 sc->stsc_data[i].first < first_min ||
3566
1/2
✓ Branch 0 taken 3910 times.
✗ Branch 1 not taken.
3910 sc->stsc_data[i].count < 1 ||
3567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3910 times.
3910 sc->stsc_data[i].id < 1) {
3568 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);
3569 if (i+1 >= sc->stsc_count) {
3570 if (sc->stsc_data[i].count == 0 && i > 0) {
3571 sc->stsc_count --;
3572 continue;
3573 }
3574 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3575 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3576 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3577 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3578 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3579 continue;
3580 }
3581 av_assert0(sc->stsc_data[i+1].first >= 2);
3582 // We replace this entry by the next valid
3583 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3584 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3585 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3586 }
3587 }
3588
3589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 683 times.
683 if (pb->eof_reached) {
3590 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3591 return AVERROR_EOF;
3592 }
3593
3594 683 return 0;
3595 }
3596
3597 354864 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3598 {
3599 354864 return index < count - 1;
3600 }
3601
3602 /* Compute the samples value for the stsc entry at the given index. */
3603 57370 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3604 {
3605 int chunk_count;
3606
3607
2/2
✓ Branch 1 taken 57172 times.
✓ Branch 2 taken 198 times.
57370 if (mov_stsc_index_valid(index, sc->stsc_count))
3608 57172 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3609 else {
3610 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3612 198 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3613 }
3614
3615 57370 return sc->stsc_data[index].count * (int64_t)chunk_count;
3616 }
3617
3618 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3619 {
3620 AVStream *st;
3621 MOVStreamContext *sc;
3622 unsigned i, entries;
3623
3624 if (c->trak_index < 0) {
3625 av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3626 return 0;
3627 }
3628
3629 if (c->fc->nb_streams < 1)
3630 return 0;
3631 st = c->fc->streams[c->fc->nb_streams-1];
3632 sc = st->priv_data;
3633
3634 avio_rb32(pb); // version + flags
3635
3636 entries = avio_rb32(pb);
3637 if (sc->stps_data)
3638 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3639 av_free(sc->stps_data);
3640 sc->stps_count = 0;
3641 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3642 if (!sc->stps_data)
3643 return AVERROR(ENOMEM);
3644
3645 for (i = 0; i < entries && !pb->eof_reached; i++) {
3646 sc->stps_data[i] = avio_rb32(pb);
3647 }
3648
3649 sc->stps_count = i;
3650
3651 if (pb->eof_reached) {
3652 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3653 return AVERROR_EOF;
3654 }
3655
3656 return 0;
3657 }
3658
3659 181 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3660 {
3661 AVStream *st;
3662 FFStream *sti;
3663 MOVStreamContext *sc;
3664 unsigned int i, entries;
3665
3666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
181 if (c->trak_index < 0) {
3667 av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3668 return 0;
3669 }
3670
3671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
181 if (c->fc->nb_streams < 1)
3672 return 0;
3673 181 st = c->fc->streams[c->fc->nb_streams-1];
3674 181 sti = ffstream(st);
3675 181 sc = st->priv_data;
3676
3677 181 avio_r8(pb); /* version */
3678 181 avio_rb24(pb); /* flags */
3679
3680 181 entries = avio_rb32(pb);
3681
3682 181 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3683
3684
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 167 times.
181 if (!entries) {
3685 14 sc->keyframe_absent = 1;
3686
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
14 if (!sti->need_parsing && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
3687 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3688 14 return 0;
3689 }
3690
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 167 times.
167 if (sc->keyframes)
3691 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 167 times.
167 if (entries >= UINT_MAX / sizeof(int))
3693 return AVERROR_INVALIDDATA;
3694 167 av_freep(&sc->keyframes);
3695 167 sc->keyframe_count = 0;
3696 167 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 167 times.
167 if (!sc->keyframes)
3698 return AVERROR(ENOMEM);
3699
3700
3/4
✓ Branch 0 taken 5755 times.
✓ Branch 1 taken 167 times.
✓ Branch 2 taken 5755 times.
✗ Branch 3 not taken.
5922 for (i = 0; i < entries && !pb->eof_reached; i++) {
3701 5755 sc->keyframes[i] = avio_rb32(pb);
3702 }
3703
3704 167 sc->keyframe_count = i;
3705
3706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 167 times.
167 if (pb->eof_reached) {
3707 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3708 return AVERROR_EOF;
3709 }
3710
3711 167 return 0;
3712 }
3713
3714 712 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3715 {
3716 AVStream *st;
3717 MOVStreamContext *sc;
3718 unsigned int i, entries, sample_size, field_size, num_bytes;
3719 GetBitContext gb;
3720 unsigned char* buf;
3721 int ret;
3722
3723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (c->trak_index < 0) {
3724 av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3725 return 0;
3726 }
3727
3728
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (c->fc->nb_streams < 1)
3729 return 0;
3730 712 st = c->fc->streams[c->fc->nb_streams-1];
3731 712 sc = st->priv_data;
3732
3733 712 avio_r8(pb); /* version */
3734 712 avio_rb24(pb); /* flags */
3735
3736
1/2
✓ Branch 0 taken 712 times.
✗ Branch 1 not taken.
712 if (atom.type == MKTAG('s','t','s','z')) {
3737 712 sample_size = avio_rb32(pb);
3738
2/2
✓ Branch 0 taken 669 times.
✓ Branch 1 taken 43 times.
712 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3739 669 sc->sample_size = sample_size;
3740 712 sc->stsz_sample_size = sample_size;
3741 712 field_size = 32;
3742 } else {
3743 sample_size = 0;
3744 avio_rb24(pb); /* reserved */
3745 field_size = avio_r8(pb);
3746 }
3747 712 entries = avio_rb32(pb);
3748
3749 712 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3750
3751 712 sc->sample_count = entries;
3752
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 493 times.
712 if (sample_size)
3753 219 return 0;
3754
3755
4/8
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 493 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 493 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 493 times.
493 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
3756 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3757 return AVERROR_INVALIDDATA;
3758 }
3759
3760
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 463 times.
493 if (!entries)
3761 30 return 0;
3762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 463 times.
463 if (entries >= (INT_MAX - 4 - 8 * AV_INPUT_BUFFER_PADDING_SIZE) / field_size)
3763 return AVERROR_INVALIDDATA;
3764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 463 times.
463 if (sc->sample_sizes)
3765 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3766 463 av_free(sc->sample_sizes);
3767 463 sc->sample_count = 0;
3768 463 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 463 times.
463 if (!sc->sample_sizes)
3770 return AVERROR(ENOMEM);
3771
3772 463 num_bytes = (entries*field_size+4)>>3;
3773
3774 463 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 463 times.
463 if (!buf) {
3776 av_freep(&sc->sample_sizes);
3777 return AVERROR(ENOMEM);
3778 }
3779
3780 463 ret = ffio_read_size(pb, buf, num_bytes);
3781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 463 times.
463 if (ret < 0) {
3782 av_freep(&sc->sample_sizes);
3783 av_free(buf);
3784 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3785 return 0;
3786 }
3787
3788 463 init_get_bits(&gb, buf, 8*num_bytes);
3789
3790
2/2
✓ Branch 0 taken 239690 times.
✓ Branch 1 taken 463 times.
240153 for (i = 0; i < entries; i++) {
3791 239690 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 239690 times.
239690 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3793 av_free(buf);
3794 av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3795 return AVERROR_INVALIDDATA;
3796 }
3797 239690 sc->data_size += sc->sample_sizes[i];
3798 }
3799
3800 463 sc->sample_count = i;
3801
3802 463 av_free(buf);
3803
3804 463 return 0;
3805 }
3806
3807 712 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3808 {
3809 AVStream *st;
3810 MOVStreamContext *sc;
3811 unsigned int i, entries;
3812 712 int64_t duration = 0;
3813 712 int64_t total_sample_count = 0;
3814 712 int64_t current_dts = 0;
3815 712 int64_t corrected_dts = 0;
3816
3817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (c->trak_index < 0) {
3818 av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3819 return 0;
3820 }
3821
3822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (c->fc->nb_streams < 1)
3823 return 0;
3824 712 st = c->fc->streams[c->fc->nb_streams-1];
3825 712 sc = st->priv_data;
3826
3827 712 avio_r8(pb); /* version */
3828 712 avio_rb24(pb); /* flags */
3829 712 entries = avio_rb32(pb);
3830
3831 712 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3832 712 c->fc->nb_streams-1, entries);
3833
3834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (sc->stts_data)
3835 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3836 712 av_freep(&sc->stts_data);
3837 712 sc->stts_count = 0;
3838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3839 return AVERROR(ENOMEM);
3840
3841
3/4
✓ Branch 0 taken 3104 times.
✓ Branch 1 taken 712 times.
✓ Branch 2 taken 3104 times.
✗ Branch 3 not taken.
3816 for (i = 0; i < entries && !pb->eof_reached; i++) {
3842 unsigned int sample_duration;
3843 unsigned int sample_count;
3844 3104 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3845 3104 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3846 min_entries * sizeof(*sc->stts_data));
3847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3104 times.
3104 if (!stts_data) {
3848 av_freep(&sc->stts_data);
3849 sc->stts_count = 0;
3850 return AVERROR(ENOMEM);
3851 }
3852 3104 sc->stts_count = min_entries;
3853 3104 sc->stts_data = stts_data;
3854
3855 3104 sample_count = avio_rb32(pb);
3856 3104 sample_duration = avio_rb32(pb);
3857
3858 3104 sc->stts_data[i].count= sample_count;
3859 3104 sc->stts_data[i].duration= sample_duration;
3860
3861 3104 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3862 sample_count, sample_duration);
3863
3864 /* STTS sample offsets are uint32 but some files store it as int32
3865 * with negative values used to correct DTS delays.
3866 There may be abnormally large values as well. */
3867
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3103 times.
3104 if (sample_duration > c->max_stts_delta) {
3868 // assume high delta is a correction if negative when cast as int32
3869 1 int32_t delta_magnitude = (int32_t)sample_duration;
3870 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",
3871 sample_duration, i, sample_count, st->index);
3872 1 sc->stts_data[i].duration = 1;
3873
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 corrected_dts = av_sat_add64(corrected_dts, (delta_magnitude < 0 ? (int64_t)delta_magnitude : 1) * sample_count);
3874 } else {
3875 3103 corrected_dts += sample_duration * (uint64_t)sample_count;
3876 }
3877
3878 3104 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3879
3880
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 3082 times.
3104 if (current_dts > corrected_dts) {
3881 22 int64_t drift = av_sat_sub64(current_dts, corrected_dts) / FFMAX(sample_count, 1);
3882
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;
3883 22 current_dts -= correction * (uint64_t)sample_count;
3884 22 sc->stts_data[i].duration -= correction;
3885 }
3886
3887 3104 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3888 3104 total_sample_count+=sc->stts_data[i].count;
3889 }
3890
3891 712 sc->stts_count = i;
3892
3893
2/2
✓ Branch 0 taken 682 times.
✓ Branch 1 taken 30 times.
712 if (duration > 0 &&
3894
1/2
✓ Branch 0 taken 682 times.
✗ Branch 1 not taken.
682 duration <= INT64_MAX - sc->duration_for_fps &&
3895
1/2
✓ Branch 0 taken 682 times.
✗ Branch 1 not taken.
682 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3896 682 sc->duration_for_fps += duration;
3897 682 sc->nb_frames_for_fps += total_sample_count;
3898 }
3899
3900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (pb->eof_reached) {
3901 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3902 return AVERROR_EOF;
3903 }
3904
3905 712 st->nb_frames= total_sample_count;
3906
2/2
✓ Branch 0 taken 682 times.
✓ Branch 1 taken 30 times.
712 if (duration)
3907 682 st->duration= FFMIN(st->duration, duration);
3908
3909 // All samples have zero duration. They have higher chance be chose by
3910 // mov_find_next_sample, which leads to seek again and again.
3911 //
3912 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3913 // So only mark data stream as discarded for safety.
3914
3/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 682 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
712 if (!duration && sc->stts_count &&
3915 st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3916 av_log(c->fc, AV_LOG_WARNING,
3917 "All samples in data stream index:id [%d:%d] have zero "
3918 "duration, stream set to be discarded by default. Override "
3919 "using AVStream->discard or -discard for ffmpeg command.\n",
3920 st->index, sc->id);
3921 st->discard = AVDISCARD_ALL;
3922 }
3923 712 sc->track_end = duration;
3924 712 return 0;
3925 }
3926
3927 46 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3928 {
3929 AVStream *st;
3930 MOVStreamContext *sc;
3931 unsigned int i;
3932 int64_t entries;
3933
3934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (c->fc->nb_streams < 1)
3935 return 0;
3936 46 st = c->fc->streams[c->fc->nb_streams - 1];
3937 46 sc = st->priv_data;
3938
3939 46 avio_r8(pb); /* version */
3940 46 avio_rb24(pb); /* flags */
3941 46 entries = atom.size - 4;
3942
3943 46 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3944 46 c->fc->nb_streams - 1, entries);
3945
3946
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 38 times.
46 if (sc->sdtp_data)
3947 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3948 46 av_freep(&sc->sdtp_data);
3949 46 sc->sdtp_count = 0;
3950
3951
2/4
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
46 if (entries < 0 || entries > UINT_MAX)
3952 return AVERROR(ERANGE);
3953
3954 46 sc->sdtp_data = av_malloc(entries);
3955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!sc->sdtp_data)
3956 return AVERROR(ENOMEM);
3957
3958
3/4
✓ Branch 0 taken 3823 times.
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 3823 times.
✗ Branch 3 not taken.
3869 for (i = 0; i < entries && !pb->eof_reached; i++)
3959 3823 sc->sdtp_data[i] = avio_r8(pb);
3960 46 sc->sdtp_count = i;
3961
3962 46 return 0;
3963 }
3964
3965 13804 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3966 {
3967
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 12668 times.
13804 if (duration < 0) {
3968
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3969 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3970 duration++;
3971 }
3972 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3973 }
3974 13804 }
3975
3976 82 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3977 {
3978 AVStream *st;
3979 MOVStreamContext *sc;
3980 82 unsigned int i, entries, ctts_count = 0;
3981
3982
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 82 times.
82 if (c->trak_index < 0) {
3983 av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
3984 return 0;
3985 }
3986
3987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 82 times.
82 if (c->fc->nb_streams < 1)
3988 return 0;
3989 82 st = c->fc->streams[c->fc->nb_streams-1];
3990 82 sc = st->priv_data;
3991
3992 82 avio_r8(pb); /* version */
3993 82 avio_rb24(pb); /* flags */
3994 82 entries = avio_rb32(pb);
3995
3996 82 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3997
3998
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 78 times.
82 if (!entries)
3999 4 return 0;
4000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
4001 return AVERROR_INVALIDDATA;
4002 78 av_freep(&sc->ctts_data);
4003 78 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
4004
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 if (!sc->ctts_data)
4005 return AVERROR(ENOMEM);
4006
4007
3/4
✓ Branch 0 taken 5231 times.
✓ Branch 1 taken 78 times.
✓ Branch 2 taken 5231 times.
✗ Branch 3 not taken.
5309 for (i = 0; i < entries && !pb->eof_reached; i++) {
4008 MOVCtts *ctts_data;
4009 5231 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
4010 5231 const size_t requested_size =
4011 5231 min_size_needed > sc->ctts_allocated_size ?
4012
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5231 times.
5231 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
4013 min_size_needed;
4014 5231 int count = avio_rb32(pb);
4015 5231 int duration = avio_rb32(pb);
4016
4017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5231 times.
5231 if (count <= 0) {
4018 av_log(c->fc, AV_LOG_TRACE,
4019 "ignoring CTTS entry with count=%d duration=%d\n",
4020 count, duration);
4021 continue;
4022 }
4023
4024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5231 times.
5231 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
4025 return AVERROR(ENOMEM);
4026
4027 5231 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
4028
4029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5231 times.
5231 if (!ctts_data)
4030 return AVERROR(ENOMEM);
4031
4032 5231 sc->ctts_data = ctts_data;
4033
4034 5231 ctts_data[ctts_count].count = count;
4035 5231 ctts_data[ctts_count].offset = duration;
4036 5231 ctts_count++;
4037
4038 5231 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
4039 count, duration);
4040
4041
2/2
✓ Branch 0 taken 5087 times.
✓ Branch 1 taken 144 times.
5231 if (i+2<entries)
4042 5087 mov_update_dts_shift(sc, duration, c->fc);
4043 }
4044
4045 78 sc->ctts_count = ctts_count;
4046
4047
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 if (pb->eof_reached) {
4048 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
4049 return AVERROR_EOF;
4050 }
4051
4052 78 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
4053
4054 78 return 0;
4055 }
4056
4057 51 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4058 {
4059 AVStream *st;
4060 MOVStreamContext *sc;
4061 uint8_t version;
4062 uint32_t grouping_type;
4063 uint32_t default_length;
4064 av_unused uint32_t default_group_description_index;
4065 uint32_t entry_count;
4066
4067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (c->fc->nb_streams < 1)
4068 return 0;
4069 51 st = c->fc->streams[c->fc->nb_streams - 1];
4070 51 sc = st->priv_data;
4071
4072 51 version = avio_r8(pb); /* version */
4073 51 avio_rb24(pb); /* flags */
4074 51 grouping_type = avio_rl32(pb);
4075
4076 /*
4077 * This function only supports "sync" boxes, but the code is able to parse
4078 * other boxes (such as "tscl", "tsas" and "stsa")
4079 */
4080
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 5 times.
51 if (grouping_type != MKTAG('s','y','n','c'))
4081 46 return 0;
4082
4083
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
4084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
4085 5 entry_count = avio_rb32(pb);
4086
4087
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (entry_count > atom.size)
4088 return AVERROR_INVALIDDATA;
4089
4090 5 av_freep(&sc->sgpd_sync);
4091 5 sc->sgpd_sync_count = entry_count;
4092 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
4093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
4094 return AVERROR(ENOMEM);
4095
4096
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++) {
4097 8 uint32_t description_length = default_length;
4098
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)
4099 description_length = avio_rb32(pb);
4100
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
4101 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
4102 8 sc->sgpd_sync[i] = nal_unit_type;
4103 8 description_length -= 1;
4104 }
4105 8 avio_skip(pb, description_length);
4106 }
4107
4108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
4109 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
4110 return AVERROR_EOF;
4111 }
4112
4113 5 return 0;
4114 }
4115
4116 47 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4117 {
4118 AVStream *st;
4119 MOVStreamContext *sc;
4120 unsigned int i, entries;
4121 uint8_t version;
4122 uint32_t grouping_type;
4123 MOVSbgp *table, **tablep;
4124 int *table_count;
4125
4126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 if (c->fc->nb_streams < 1)
4127 return 0;
4128 47 st = c->fc->streams[c->fc->nb_streams-1];
4129 47 sc = st->priv_data;
4130
4131 47 version = avio_r8(pb); /* version */
4132 47 avio_rb24(pb); /* flags */
4133 47 grouping_type = avio_rl32(pb);
4134
4135
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 46 times.
47 if (grouping_type == MKTAG('r','a','p',' ')) {
4136 1 tablep = &sc->rap_group;
4137 1 table_count = &sc->rap_group_count;
4138
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 41 times.
46 } else if (grouping_type == MKTAG('s','y','n','c')) {
4139 5 tablep = &sc->sync_group;
4140 5 table_count = &sc->sync_group_count;
4141 } else {
4142 41 return 0;
4143 }
4144
4145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
4146 avio_rb32(pb); /* grouping_type_parameter */
4147
4148 6 entries = avio_rb32(pb);
4149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
4150 return 0;
4151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
4152 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
4153 6 av_freep(tablep);
4154 6 table = av_malloc_array(entries, sizeof(*table));
4155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
4156 return AVERROR(ENOMEM);
4157 6 *tablep = table;
4158
4159
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++) {
4160 32 table[i].count = avio_rb32(pb); /* sample_count */
4161 32 table[i].index = avio_rb32(pb); /* group_description_index */
4162 }
4163
4164 6 *table_count = i;
4165
4166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
4167 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
4168 return AVERROR_EOF;
4169 }
4170
4171 6 return 0;
4172 }
4173
4174 /**
4175 * Get ith edit list entry (media time, duration).
4176 */
4177 1077 static int get_edit_list_entry(MOVContext *mov,
4178 const MOVStreamContext *msc,
4179 unsigned int edit_list_index,
4180 int64_t *edit_list_media_time,
4181 int64_t *edit_list_duration,
4182 int64_t global_timescale)
4183 {
4184
2/2
✓ Branch 0 taken 524 times.
✓ Branch 1 taken 553 times.
1077 if (edit_list_index == msc->elst_count) {
4185 524 return 0;
4186 }
4187 553 *edit_list_media_time = msc->elst_data[edit_list_index].time;
4188 553 *edit_list_duration = msc->elst_data[edit_list_index].duration;
4189
4190 /* duration is in global timescale units;convert to msc timescale */
4191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 553 times.
553 if (global_timescale == 0) {
4192 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
4193 return 0;
4194 }
4195 553 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
4196 global_timescale);
4197
4198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 553 times.
553 if (*edit_list_duration + (uint64_t)*edit_list_media_time > INT64_MAX)
4199 *edit_list_duration = 0;
4200
4201 553 return 1;
4202 }
4203
4204 /**
4205 * Find the closest previous frame to the timestamp_pts, in e_old index
4206 * entries. Searching for just any frame / just key frames can be controlled by
4207 * last argument 'flag'.
4208 * Note that if ctts_data is not NULL, we will always search for a key frame
4209 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
4210 * return the first frame of the video.
4211 *
4212 * Here the timestamp_pts is considered to be a presentation timestamp and
4213 * the timestamp of index entries are considered to be decoding timestamps.
4214 *
4215 * Returns 0 if successful in finding a frame, else returns -1.
4216 * Places the found index corresponding output arg.
4217 *
4218 * If ctts_old is not NULL, then refines the searched entry by searching
4219 * backwards from the found timestamp, to find the frame with correct PTS.
4220 *
4221 * Places the found ctts_index and ctts_sample in corresponding output args.
4222 */
4223 553 static int find_prev_closest_index(AVStream *st,
4224 AVIndexEntry *e_old,
4225 int nb_old,
4226 MOVTimeToSample *tts_data,
4227 int64_t tts_count,
4228 int64_t timestamp_pts,
4229 int flag,
4230 int64_t* index,
4231 int64_t* tts_index,
4232 int64_t* tts_sample)
4233 {
4234 553 MOVStreamContext *msc = st->priv_data;
4235 553 FFStream *const sti = ffstream(st);
4236 553 AVIndexEntry *e_keep = sti->index_entries;
4237 553 int nb_keep = sti->nb_index_entries;
4238 553 int64_t i = 0;
4239
4240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 553 times.
553 av_assert0(index);
4241
4242 // If dts_shift > 0, then all the index timestamps will have to be offset by
4243 // at least dts_shift amount to obtain PTS.
4244 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
4245
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 544 times.
553 if (msc->dts_shift > 0) {
4246 9 timestamp_pts -= msc->dts_shift;
4247 }
4248
4249 553 sti->index_entries = e_old;
4250 553 sti->nb_index_entries = nb_old;
4251 553 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
4252
4253 // Keep going backwards in the index entries until the timestamp is the same.
4254
2/2
✓ Branch 0 taken 552 times.
✓ Branch 1 taken 1 times.
553 if (*index >= 0) {
4255
3/4
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 525 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
552 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
4256 i--) {
4257 if ((flag & AVSEEK_FLAG_ANY) ||
4258 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
4259 *index = i - 1;
4260 }
4261 }
4262 }
4263
4264 // If we have CTTS then refine the search, by searching backwards over PTS
4265 // computed by adding corresponding CTTS durations to index timestamps.
4266
4/4
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 467 times.
✓ Branch 2 taken 85 times.
✓ Branch 3 taken 1 times.
553 if (msc->ctts_count && *index >= 0) {
4267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 av_assert0(tts_index);
4268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 av_assert0(tts_sample);
4269 // Find out the ctts_index for the found frame.
4270 85 *tts_index = 0;
4271 85 *tts_sample = 0;
4272
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 85 times.
299 for (int64_t index_tts_count = 0; index_tts_count < *index; index_tts_count++) {
4273
1/2
✓ Branch 0 taken 214 times.
✗ Branch 1 not taken.
214 if (*tts_index < tts_count) {
4274 214 (*tts_sample)++;
4275
1/2
✓ Branch 0 taken 214 times.
✗ Branch 1 not taken.
214 if (tts_data[*tts_index].count == *tts_sample) {
4276 214 (*tts_index)++;
4277 214 *tts_sample = 0;
4278 }
4279 }
4280 }
4281
4282
4/6
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 95 times.
✗ Branch 5 not taken.
102 while (*index >= 0 && (*tts_index) >= 0 && (*tts_index) < tts_count) {
4283 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
4284 // No need to add dts_shift to the timestamp here because timestamp_pts has already been
4285 // compensated by dts_shift above.
4286
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 12 times.
95 if ((e_old[*index].timestamp + tts_data[*tts_index].offset) <= timestamp_pts &&
4287
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 5 times.
83 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
4288 78 break;
4289 }
4290
4291 17 (*index)--;
4292
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 if (*tts_sample == 0) {
4293 17 (*tts_index)--;
4294
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 7 times.
17 if (*tts_index >= 0)
4295 10 *tts_sample = tts_data[*tts_index].count - 1;
4296 } else {
4297 (*tts_sample)--;
4298 }
4299 }
4300 }
4301
4302 /* restore AVStream state*/
4303 553 sti->index_entries = e_keep;
4304 553 sti->nb_index_entries = nb_keep;
4305
2/2
✓ Branch 0 taken 545 times.
✓ Branch 1 taken 8 times.
553 return *index >= 0 ? 0 : -1;
4306 }
4307
4308 /**
4309 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
4310 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
4311 *
4312 * This function is similar to ff_add_index_entry in libavformat/utils.c
4313 * except that here we are always unconditionally adding an index entry to
4314 * the end, instead of searching the entries list and skipping the add if
4315 * there is an existing entry with the same timestamp.
4316 * This is needed because the mov_fix_index calls this func with the same
4317 * unincremented timestamp for successive discarded frames.
4318 */
4319 361175 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
4320 int size, int distance, int flags)
4321 {
4322 361175 FFStream *const sti = ffstream(st);
4323 AVIndexEntry *entries, *ie;
4324 361175 int64_t index = -1;
4325 361175 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
4326
4327 // Double the allocation each time, to lower memory fragmentation.
4328 // Another difference from ff_add_index_entry function.
4329 361175 const size_t requested_size =
4330 361175 min_size_needed > sti->index_entries_allocated_size ?
4331
2/2
✓ Branch 0 taken 2372 times.
✓ Branch 1 taken 358803 times.
361175 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
4332 min_size_needed;
4333
4334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 361175 times.
361175 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
4335 return -1;
4336
4337 361175 entries = av_fast_realloc(sti->index_entries,
4338 &sti->index_entries_allocated_size,
4339 requested_size);
4340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 361175 times.
361175 if (!entries)
4341 return -1;
4342
4343 361175 sti->index_entries = entries;
4344
4345 361175 index = sti->nb_index_entries++;
4346 361175 ie= &entries[index];
4347
4348 361175 ie->pos = pos;
4349 361175 ie->timestamp = timestamp;
4350 361175 ie->min_distance= distance;
4351 361175 ie->size= size;
4352 361175 ie->flags = flags;
4353 361175 return index;
4354 }
4355
4356 /**
4357 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4358 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4359 */
4360 48 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4361 int64_t* frame_duration_buffer,
4362 int frame_duration_buffer_size) {
4363 48 FFStream *const sti = ffstream(st);
4364 48 int i = 0;
4365
2/4
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
48 av_assert0(end_index >= 0 && end_index <= sti->nb_index_entries);
4366
2/2
✓ Branch 0 taken 193 times.
✓ Branch 1 taken 48 times.
241 for (i = 0; i < frame_duration_buffer_size; i++) {
4367 193 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4368 193 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4369 }
4370 48 }
4371
4372 195948 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4373 int count, int offset, unsigned int duration)
4374 {
4375 MOVTimeToSample *tts_buf_new;
4376 195948 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4377 195948 const size_t requested_size =
4378 195948 min_size_needed > *allocated_size ?
4379
2/2
✓ Branch 0 taken 1683 times.
✓ Branch 1 taken 194265 times.
195948 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4380 min_size_needed;
4381
4382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195948 times.
195948 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4383 return -1;
4384
4385 195948 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4386
4387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195948 times.
195948 if (!tts_buf_new)
4388 return -1;
4389
4390 195948 *tts_data = tts_buf_new;
4391
4392 195948 tts_buf_new[*tts_count].count = count;
4393 195948 tts_buf_new[*tts_count].offset = offset;
4394 195948 tts_buf_new[*tts_count].duration = duration;
4395
4396 195948 *tts_count = (*tts_count) + 1;
4397 195948 return 0;
4398 }
4399
4400 #define MAX_REORDER_DELAY 16
4401 725 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4402 {
4403 725 MOVStreamContext *msc = st->priv_data;
4404 725 FFStream *const sti = ffstream(st);
4405 725 int ctts_ind = 0;
4406 725 int ctts_sample = 0;
4407 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4408 725 int buf_start = 0;
4409 int j, r, num_swaps;
4410
4411
2/2
✓ Branch 0 taken 12325 times.
✓ Branch 1 taken 725 times.
13050 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4412 12325 pts_buf[j] = INT64_MIN;
4413
4414
3/4
✓ Branch 0 taken 725 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 78 times.
✓ Branch 3 taken 647 times.
725 if (st->codecpar->video_delay <= 0 && msc->ctts_count &&
4415
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 27 times.
78 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4416 51 st->codecpar->video_delay = 0;
4417
3/4
✓ Branch 0 taken 138515 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 138515 times.
✗ Branch 3 not taken.
138566 for (int ind = 0; ind < sti->nb_index_entries && ctts_ind < msc->tts_count; ++ind) {
4418 // Point j to the last elem of the buffer and insert the current pts there.
4419 138515 j = buf_start;
4420 138515 buf_start = (buf_start + 1);
4421
2/2
✓ Branch 0 taken 8121 times.
✓ Branch 1 taken 130394 times.
138515 if (buf_start == MAX_REORDER_DELAY + 1)
4422 8121 buf_start = 0;
4423
4424 138515 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4425
4426 // The timestamps that are already in the sorted buffer, and are greater than the
4427 // current pts, are exactly the timestamps that need to be buffered to output PTS
4428 // in correct sorted order.
4429 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4430 // can be computed as the maximum no. of swaps any particular timestamp needs to
4431 // go through, to keep this buffer in sorted order.
4432 138515 num_swaps = 0;
4433
2/2
✓ Branch 0 taken 142863 times.
✓ Branch 1 taken 4 times.
142867 while (j != buf_start) {
4434 142863 r = j - 1;
4435
2/2
✓ Branch 0 taken 8425 times.
✓ Branch 1 taken 134438 times.
142863 if (r < 0) r = MAX_REORDER_DELAY;
4436
2/2
✓ Branch 0 taken 4352 times.
✓ Branch 1 taken 138511 times.
142863 if (pts_buf[j] < pts_buf[r]) {
4437 4352 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4438 4352 ++num_swaps;
4439 } else {
4440 138511 break;
4441 }
4442 4352 j = r;
4443 }
4444 138515 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4445
4446 138515 ctts_sample++;
4447
1/2
✓ Branch 0 taken 138515 times.
✗ Branch 1 not taken.
138515 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4448 138515 ctts_ind++;
4449 138515 ctts_sample = 0;
4450 }
4451 }
4452 51 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4453 51 st->codecpar->video_delay, st->index);
4454 }
4455 725 }
4456
4457 117279 static void mov_current_sample_inc(MOVStreamContext *sc)
4458 {
4459 117279 sc->current_sample++;
4460 117279 sc->current_index++;
4461
2/2
✓ Branch 0 taken 71185 times.
✓ Branch 1 taken 46094 times.
117279 if (sc->index_ranges &&
4462
2/2
✓ Branch 0 taken 492 times.
✓ Branch 1 taken 70693 times.
71185 sc->current_index >= sc->current_index_range->end &&
4463
1/2
✓ Branch 0 taken 492 times.
✗ Branch 1 not taken.
492 sc->current_index_range->end) {
4464 492 sc->current_index_range++;
4465 492 sc->current_index = sc->current_index_range->start;
4466 }
4467 117279 }
4468
4469 static void mov_current_sample_dec(MOVStreamContext *sc)
4470 {
4471 sc->current_sample--;
4472 sc->current_index--;
4473 if (sc->index_ranges &&
4474 sc->current_index < sc->current_index_range->start &&
4475 sc->current_index_range > sc->index_ranges) {
4476 sc->current_index_range--;
4477 sc->current_index = sc->current_index_range->end - 1;
4478 }
4479 }
4480
4481 339 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4482 {
4483 int64_t range_size;
4484
4485 339 sc->current_sample = current_sample;
4486 339 sc->current_index = current_sample;
4487
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 311 times.
339 if (!sc->index_ranges) {
4488 28 return;
4489 }
4490
4491 311 for (sc->current_index_range = sc->index_ranges;
4492
1/2
✓ Branch 0 taken 311 times.
✗ Branch 1 not taken.
311 sc->current_index_range->end;
4493 sc->current_index_range++) {
4494 311 range_size = sc->current_index_range->end - sc->current_index_range->start;
4495
1/2
✓ Branch 0 taken 311 times.
✗ Branch 1 not taken.
311 if (range_size > current_sample) {
4496 311 sc->current_index = sc->current_index_range->start + current_sample;
4497 311 break;
4498 }
4499 current_sample -= range_size;
4500 }
4501 }
4502
4503 /**
4504 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4505 * which are needed to decode them) that fall in the edit list time ranges.
4506 * Also fixes the timestamps of the index entries to match the timeline
4507 * specified the edit lists.
4508 */
4509 725 static void mov_fix_index(MOVContext *mov, AVStream *st)
4510 {
4511 725 MOVStreamContext *msc = st->priv_data;
4512 725 FFStream *const sti = ffstream(st);
4513 725 AVIndexEntry *e_old = sti->index_entries;
4514 725 int nb_old = sti->nb_index_entries;
4515 725 const AVIndexEntry *e_old_end = e_old + nb_old;
4516 725 const AVIndexEntry *current = NULL;
4517 725 MOVTimeToSample *tts_data_old = msc->tts_data;
4518 725 int64_t tts_index_old = 0;
4519 725 int64_t tts_sample_old = 0;
4520 725 int64_t tts_count_old = msc->tts_count;
4521 725 int64_t edit_list_media_time = 0;
4522 725 int64_t edit_list_duration = 0;
4523 725 int64_t frame_duration = 0;
4524 725 int64_t edit_list_dts_counter = 0;
4525 725 int64_t edit_list_dts_entry_end = 0;
4526 725 int64_t edit_list_start_tts_sample = 0;
4527 int64_t curr_cts;
4528 725 int64_t curr_ctts = 0;
4529 725 int64_t empty_edits_sum_duration = 0;
4530 725 int64_t edit_list_index = 0;
4531 int64_t index;
4532 int flags;
4533 725 int64_t start_dts = 0;
4534 725 int64_t edit_list_start_encountered = 0;
4535 725 int64_t search_timestamp = 0;
4536 725 int64_t* frame_duration_buffer = NULL;
4537 725 int num_discarded_begin = 0;
4538 725 int first_non_zero_audio_edit = -1;
4539 725 int packet_skip_samples = 0;
4540 725 MOVIndexRange *current_index_range = NULL;
4541 725 int found_keyframe_after_edit = 0;
4542 725 int found_non_empty_edit = 0;
4543
4544
4/6
✓ Branch 0 taken 524 times.
✓ Branch 1 taken 201 times.
✓ Branch 2 taken 524 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 524 times.
725 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
4545 201 return;
4546 }
4547
4548 // allocate the index ranges array
4549 524 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4550 sizeof(msc->index_ranges[0]));
4551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 524 times.
524 if (!msc->index_ranges) {
4552 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4553 return;
4554 }
4555 524 msc->current_index_range = msc->index_ranges;
4556
4557 // Clean AVStream from traces of old index
4558 524 sti->index_entries = NULL;
4559 524 sti->index_entries_allocated_size = 0;
4560 524 sti->nb_index_entries = 0;
4561
4562 // Clean time to sample fields of MOVStreamContext
4563 524 msc->tts_data = NULL;
4564 524 msc->tts_count = 0;
4565 524 msc->tts_index = 0;
4566 524 msc->tts_sample = 0;
4567 524 msc->tts_allocated_size = 0;
4568
4569 // Reinitialize min_corrected_pts so that it can be computed again.
4570 524 msc->min_corrected_pts = -1;
4571
4572 // If the dts_shift is positive (in case of negative ctts values in mov),
4573 // then negate the DTS by dts_shift
4574
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 515 times.
524 if (msc->dts_shift > 0) {
4575 9 edit_list_dts_entry_end -= msc->dts_shift;
4576 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4577 }
4578
4579 524 start_dts = edit_list_dts_entry_end;
4580
4581
2/2
✓ Branch 0 taken 553 times.
✓ Branch 1 taken 524 times.
1601 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
4582 1077 &edit_list_duration, mov->time_scale)) {
4583 553 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4584 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4585 553 edit_list_index++;
4586 553 edit_list_dts_counter = edit_list_dts_entry_end;
4587 553 edit_list_dts_entry_end = av_sat_add64(edit_list_dts_entry_end, edit_list_duration);
4588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 553 times.
553 if (edit_list_dts_entry_end == INT64_MAX) {
4589 av_log(mov->fc, AV_LOG_ERROR, "Cannot calculate dts entry length with duration %"PRId64"\n",
4590 edit_list_duration);
4591 break;
4592 }
4593 553 num_discarded_begin = 0;
4594
4/4
✓ Branch 0 taken 528 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 524 times.
553 if (!found_non_empty_edit && edit_list_media_time == -1) {
4595 4 empty_edits_sum_duration += edit_list_duration;
4596 4 continue;
4597 }
4598 549 found_non_empty_edit = 1;
4599
4600 // If we encounter a non-negative edit list reset the skip_samples/initial_padding fields and set them
4601 // according to the edit list below.
4602
2/2
✓ Branch 0 taken 159 times.
✓ Branch 1 taken 390 times.
549 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4603
1/2
✓ Branch 0 taken 159 times.
✗ Branch 1 not taken.
159 if (first_non_zero_audio_edit < 0) {
4604 159 first_non_zero_audio_edit = 1;
4605 } else {
4606 first_non_zero_audio_edit = 0;
4607 }
4608
4609
1/2
✓ Branch 0 taken 159 times.
✗ Branch 1 not taken.
159 if (first_non_zero_audio_edit > 0)
4610 159 sti->skip_samples = st->codecpar->initial_padding = 0;
4611 }
4612
4613 // While reordering frame index according to edit list we must handle properly
4614 // the scenario when edit list entry starts from none key frame.
4615 // We find closest previous key frame and preserve it and consequent frames in index.
4616 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4617 549 search_timestamp = edit_list_media_time;
4618
2/2
✓ Branch 0 taken 159 times.
✓ Branch 1 taken 390 times.
549 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4619 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4620 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4621 // edit_list_media_time to cover the decoder delay.
4622 159 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
4623 }
4624
4625
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 545 times.
549 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, 0,
4626 &index, &tts_index_old, &tts_sample_old) < 0) {
4627 4 av_log(mov->fc, AV_LOG_WARNING,
4628 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4629 st->index, edit_list_index, search_timestamp);
4630
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, AVSEEK_FLAG_ANY,
4631 &index, &tts_index_old, &tts_sample_old) < 0) {
4632 4 av_log(mov->fc, AV_LOG_WARNING,
4633 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4634 st->index, edit_list_index, search_timestamp);
4635 4 index = 0;
4636 4 tts_index_old = 0;
4637 4 tts_sample_old = 0;
4638 }
4639 }
4640 549 current = e_old + index;
4641 549 edit_list_start_tts_sample = tts_sample_old;
4642
4643 // Iterate over index and arrange it according to edit list
4644 549 edit_list_start_encountered = 0;
4645 549 found_keyframe_after_edit = 0;
4646
2/2
✓ Branch 0 taken 361175 times.
✓ Branch 1 taken 143 times.
361318 for (; current < e_old_end; current++, index++) {
4647 // check if frame outside edit list mark it for discard
4648 722350 frame_duration = (current + 1 < e_old_end) ?
4649
2/2
✓ Branch 0 taken 360659 times.
✓ Branch 1 taken 516 times.
361175 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4650
4651 361175 flags = current->flags;
4652
4653 // frames (pts) before or after edit list
4654 361175 curr_cts = current->timestamp + msc->dts_shift;
4655 361175 curr_ctts = 0;
4656
4657
4/4
✓ Branch 0 taken 195960 times.
✓ Branch 1 taken 165215 times.
✓ Branch 2 taken 195948 times.
✓ Branch 3 taken 12 times.
361175 if (tts_data_old && tts_index_old < tts_count_old) {
4658 195948 curr_ctts = tts_data_old[tts_index_old].offset;
4659 195948 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4660 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4661 195948 curr_cts += curr_ctts;
4662 195948 tts_sample_old++;
4663
1/2
✓ Branch 0 taken 195948 times.
✗ Branch 1 not taken.
195948 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195948 times.
195948 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4665 &msc->tts_allocated_size,
4666 195948 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4667 195948 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4668 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4669 tts_index_old,
4670 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4671 tts_data_old[tts_index_old].offset);
4672 break;
4673 }
4674 195948 tts_index_old++;
4675 195948 tts_sample_old = 0;
4676 195948 edit_list_start_tts_sample = 0;
4677 }
4678 }
4679
4680
4/4
✓ Branch 0 taken 360953 times.
✓ Branch 1 taken 222 times.
✓ Branch 2 taken 157 times.
✓ Branch 3 taken 360796 times.
361175 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
4681
4/4
✓ Branch 0 taken 121 times.
✓ Branch 1 taken 258 times.
✓ Branch 2 taken 77 times.
✓ Branch 3 taken 44 times.
379 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
4682
4/6
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 52 times.
✓ Branch 4 taken 25 times.
✗ Branch 5 not taken.
77 curr_cts < edit_list_media_time && curr_cts + frame_duration > edit_list_media_time &&
4683 first_non_zero_audio_edit > 0) {
4684 25 packet_skip_samples = edit_list_media_time - curr_cts;
4685 25 sti->skip_samples += packet_skip_samples;
4686
4687 // Shift the index entry timestamp by packet_skip_samples to be correct.
4688 25 edit_list_dts_counter -= packet_skip_samples;
4689
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 if (edit_list_start_encountered == 0) {
4690 25 edit_list_start_encountered = 1;
4691 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4692 // discarded packets.
4693
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 10 times.
25 if (frame_duration_buffer) {
4694 15 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4695 frame_duration_buffer, num_discarded_begin);
4696 15 av_freep(&frame_duration_buffer);
4697 }
4698 }
4699
4700 25 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4701 } else {
4702 354 flags |= AVINDEX_DISCARD_FRAME;
4703 354 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4704
4705
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 159 times.
354 if (edit_list_start_encountered == 0) {
4706 195 num_discarded_begin++;
4707 195 frame_duration_buffer = av_realloc(frame_duration_buffer,
4708 num_discarded_begin * sizeof(int64_t));
4709
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!frame_duration_buffer) {
4710 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4711 break;
4712 }
4713 195 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4714
4715 // Increment skip_samples for the first non-zero audio edit list
4716
3/4
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
195 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4717
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 44 times.
96 first_non_zero_audio_edit > 0 && st->codecpar->codec_id != AV_CODEC_ID_VORBIS) {
4718 52 sti->skip_samples += frame_duration;
4719 }
4720 }
4721 }
4722 } else {
4723
2/2
✓ Branch 0 taken 523 times.
✓ Branch 1 taken 360273 times.
360796 if (msc->min_corrected_pts < 0) {
4724 523 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4725 } else {
4726 360273 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4727 }
4728
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 360274 times.
360796 if (edit_list_start_encountered == 0) {
4729 522 edit_list_start_encountered = 1;
4730 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4731 // discarded packets.
4732
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 489 times.
522 if (frame_duration_buffer) {
4733 33 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4734 frame_duration_buffer, num_discarded_begin);
4735 33 av_freep(&frame_duration_buffer);
4736 }
4737 }
4738 }
4739
4740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 361175 times.
361175 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
4741 361175 current->min_distance, flags) == -1) {
4742 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4743 break;
4744 }
4745
4746 // Update the index ranges array
4747
4/4
✓ Branch 0 taken 360651 times.
✓ Branch 1 taken 524 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 360628 times.
361175 if (!current_index_range || index != current_index_range->end) {
4748 547 current_index_range = current_index_range ? current_index_range + 1
4749
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 524 times.
547 : msc->index_ranges;
4750 547 current_index_range->start = index;
4751 }
4752 361175 current_index_range->end = index + 1;
4753
4754 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4755
2/2
✓ Branch 0 taken 360980 times.
✓ Branch 1 taken 195 times.
361175 if (edit_list_start_encountered > 0) {
4756 360980 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4757 }
4758
4759 // Break when found first key frame after edit entry completion
4760
2/2
✓ Branch 0 taken 743 times.
✓ Branch 1 taken 360432 times.
361175 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
4761
4/4
✓ Branch 0 taken 317 times.
✓ Branch 1 taken 426 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 316 times.
743 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
4762
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 395 times.
427 if (msc->ctts_count) {
4763 // If we have CTTS and this is the first keyframe after edit elist,
4764 // wait for one more, because there might be trailing B-frames after this I-frame
4765 // that do belong to the edit.
4766
3/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 11 times.
32 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO && found_keyframe_after_edit == 0) {
4767 21 found_keyframe_after_edit = 1;
4768 21 continue;
4769 }
4770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (tts_sample_old != 0) {
4771 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4772 &msc->tts_allocated_size,
4773 tts_sample_old - edit_list_start_tts_sample,
4774 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4775 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4776 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4777 tts_data_old[tts_index_old].offset);
4778 break;
4779 }
4780 }
4781 }
4782 406 break;
4783 }
4784 }
4785 }
4786 // If there are empty edits, then msc->min_corrected_pts might be positive
4787 // intentionally. So we subtract the sum duration of empty edits here.
4788 524 msc->min_corrected_pts -= empty_edits_sum_duration;
4789
4790 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4791 // dts by that amount to make the first pts zero.
4792
2/2
✓ Branch 0 taken 323 times.
✓ Branch 1 taken 201 times.
524 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4793
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 263 times.
323 if (msc->min_corrected_pts > 0) {
4794 60 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4795
2/2
✓ Branch 0 taken 3285 times.
✓ Branch 1 taken 60 times.
3345 for (int i = 0; i < sti->nb_index_entries; ++i)
4796 3285 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4797 }
4798 }
4799 // Start time should be equal to zero or the duration of any empty edits.
4800 524 st->start_time = empty_edits_sum_duration;
4801
4802 // Update av stream length, if it ends up shorter than the track's media duration
4803 524 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4804 524 st->codecpar->initial_padding = sti->skip_samples;
4805
4806 // Free the old index and the old CTTS structures
4807 524 av_free(e_old);
4808 524 av_free(tts_data_old);
4809 524 av_freep(&frame_duration_buffer);
4810
4811 // Null terminate the index ranges array
4812 524 current_index_range = current_index_range ? current_index_range + 1
4813
1/2
✓ Branch 0 taken 524 times.
✗ Branch 1 not taken.
524 : msc->index_ranges;
4814 524 current_index_range->start = 0;
4815 524 current_index_range->end = 0;
4816 524 msc->current_index = msc->index_ranges[0].start;
4817 }
4818
4819 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4820 {
4821
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4822
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == nal_unit_type)
4823 5 return i + 1;
4824 return 0;
4825 }
4826
4827 755 static int build_open_gop_key_points(AVStream *st)
4828 {
4829 int k;
4830 755 int sample_id = 0;
4831 uint32_t cra_index;
4832 755 MOVStreamContext *sc = st->priv_data;
4833
4834
4/4
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 687 times.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 5 times.
755 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count)
4835 750 return 0;
4836
4837 /* Build an unrolled index of the samples */
4838 5 sc->sample_offsets_count = 0;
4839
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4841 return AVERROR(ENOMEM);
4842 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4843 }
4844 5 av_freep(&sc->sample_offsets);
4845 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4847 return AVERROR(ENOMEM);
4848 5 k = 0;
4849
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4850
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4851 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4852
4853 /* The following HEVC NAL type reveal the use of open GOP sync points
4854 * (TODO: BLA types may also be concerned) */
4855 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4857 return 0;
4858
4859 /* Build a list of open-GOP key samples */
4860 5 sc->open_key_samples_count = 0;
4861
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4862
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4863
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)
4864 return AVERROR(ENOMEM);
4865 11 sc->open_key_samples_count += sc->sync_group[i].count;
4866 }
4867 5 av_freep(&sc->open_key_samples);
4868 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4870 return AVERROR(ENOMEM);
4871 5 k = 0;
4872
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4873 28 const MOVSbgp *sg = &sc->sync_group[i];
4874
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4875
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4876 11 sc->open_key_samples[k++] = sample_id;
4877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4878 return AVERROR_PATCHWELCOME;
4879 28 sample_id += sg->count;
4880 }
4881
4882 /* Identify the minimal time step between samples */
4883 5 sc->min_sample_duration = UINT_MAX;
4884
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4885 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4886
4887 5 return 0;
4888 }
4889
4890 #define MOV_MERGE_CTTS 1
4891 #define MOV_MERGE_STTS 2
4892 /*
4893 * Merge stts and ctts arrays into a new combined array.
4894 * stts_count and ctts_count may be left untouched as they will be
4895 * used to check for the presence of either of them.
4896 */
4897 725 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4898 {
4899 725 MOVStreamContext *sc = st->priv_data;
4900
3/4
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 647 times.
✓ Branch 2 taken 78 times.
✗ Branch 3 not taken.
725 int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS);
4901
3/4
✓ Branch 0 taken 725 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 657 times.
✓ Branch 3 taken 68 times.
725 int stts = sc->stts_data && (flags & MOV_MERGE_STTS);
4902 725 int idx = 0;
4903
4904
3/4
✓ Branch 0 taken 647 times.
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 647 times.
725 if (!sc->ctts_data && !sc->stts_data)
4905 return 0;
4906 // Expand time to sample entries such that we have a 1-1 mapping with samples
4907
2/4
✓ Branch 0 taken 725 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 725 times.
725 if (!sc->sample_count || sc->sample_count >= UINT_MAX / sizeof(*sc->tts_data))
4908 return -1;
4909
4910
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 647 times.
725 if (ctts) {
4911 156 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4912 78 sc->sample_count * sizeof(*sc->tts_data));
4913
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 if (!sc->tts_data)
4914 return -1;
4915
4916 78 memset(sc->tts_data, 0, sc->tts_allocated_size);
4917
4918
2/2
✓ Branch 0 taken 5231 times.
✓ Branch 1 taken 78 times.
5309 for (int i = 0; i < sc->ctts_count &&
4919
1/2
✓ Branch 0 taken 5231 times.
✗ Branch 1 not taken.
10462 idx < sc->sample_count; i++)
4920
2/2
✓ Branch 0 taken 139447 times.
✓ Branch 1 taken 5231 times.
144678 for (int j = 0; j < sc->ctts_data[i].count &&
4921
1/2
✓ Branch 0 taken 139447 times.
✗ Branch 1 not taken.
139447 idx < sc->sample_count; j++) {
4922 139447 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4923 139447 sc->tts_data[idx++].count = 1;
4924 }
4925
4926 78 sc->tts_count = idx;
4927 } else
4928 647 sc->ctts_count = 0;
4929 725 av_freep(&sc->ctts_data);
4930 725 sc->ctts_allocated_size = 0;
4931
4932 725 idx = 0;
4933
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 68 times.
725 if (stts) {
4934 657 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4935 657 sc->sample_count * sizeof(*sc->tts_data));
4936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 657 times.
657 if (!tts_data)
4937 return -1;
4938
4939
2/2
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 78 times.
657 if (!sc->tts_data)
4940 579 memset(tts_data, 0, sc->tts_allocated_size);
4941 657 sc->tts_data = tts_data;
4942
4943
2/2
✓ Branch 0 taken 3079 times.
✓ Branch 1 taken 657 times.
3736 for (int i = 0; i < sc->stts_count &&
4944
1/2
✓ Branch 0 taken 3079 times.
✗ Branch 1 not taken.
6158 idx < sc->sample_count; i++)
4945
2/2
✓ Branch 0 taken 248989 times.
✓ Branch 1 taken 3079 times.
252068 for (int j = 0; j < sc->stts_data[i].count &&
4946
1/2
✓ Branch 0 taken 248989 times.
✗ Branch 1 not taken.
248989 idx < sc->sample_count; j++) {
4947 248989 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4948 248989 sc->tts_data[idx++].count = 1;
4949 }
4950
4951 657 sc->tts_count = FFMAX(sc->tts_count, idx);
4952 } else
4953 68 sc->stts_count = 0;
4954 725 av_freep(&sc->stts_data);
4955 725 sc->stts_allocated_size = 0;
4956
4957 725 return 0;
4958 }
4959
4960 755 static void mov_build_index(MOVContext *mov, AVStream *st)
4961 {
4962 755 MOVStreamContext *sc = st->priv_data;
4963 755 FFStream *const sti = ffstream(st);
4964 int64_t current_offset;
4965 755 int64_t current_dts = 0;
4966 755 unsigned int stts_index = 0;
4967 755 unsigned int stsc_index = 0;
4968 755 unsigned int stss_index = 0;
4969 755 unsigned int stps_index = 0;
4970 unsigned int i, j;
4971 755 uint64_t stream_size = 0;
4972
4973 755 int ret = build_open_gop_key_points(st);
4974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 755 times.
755 if (ret < 0)
4975 return;
4976
4977
2/2
✓ Branch 0 taken 527 times.
✓ Branch 1 taken 228 times.
755 if (sc->elst_count) {
4978 527 int i, edit_start_index = 0, multiple_edits = 0;
4979 527 int64_t empty_duration = 0; // empty duration of the first edit list entry
4980 527 int64_t start_time = 0; // start time of the media
4981
4982
2/2
✓ Branch 0 taken 556 times.
✓ Branch 1 taken 527 times.
1083 for (i = 0; i < sc->elst_count; i++) {
4983 556 const MOVElst *e = &sc->elst_data[i];
4984
4/4
✓ Branch 0 taken 527 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 523 times.
556 if (i == 0 && e->time == -1) {
4985 /* if empty, the first entry is the start time of the stream
4986 * relative to the presentation itself */
4987 4 empty_duration = e->duration;
4988 4 edit_start_index = 1;
4989
3/4
✓ Branch 0 taken 527 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 527 times.
✗ Branch 3 not taken.
552 } else if (i == edit_start_index && e->time >= 0) {
4990 527 start_time = e->time;
4991 } else {
4992 25 multiple_edits = 1;
4993 }
4994 }
4995
4996
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 520 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
527 if (multiple_edits && !mov->advanced_editlist) {
4997 if (mov->advanced_editlist_autodisabled)
4998 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4999 "not supported in fragmented MP4 files\n");
5000 else
5001 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
5002 "Use -advanced_editlist to correctly decode otherwise "
5003 "a/v desync might occur\n");
5004 }
5005
5006 /* adjust first dts according to edit list */
5007
5/6
✓ Branch 0 taken 523 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 114 times.
✓ Branch 3 taken 409 times.
✓ Branch 4 taken 118 times.
✗ Branch 5 not taken.
527 if ((empty_duration || start_time) && mov->time_scale > 0) {
5008
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 114 times.
118 if (empty_duration)
5009 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
5010
5011
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 118 times.
118 if (av_sat_sub64(start_time, empty_duration) != start_time - (uint64_t)empty_duration)
5012 av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
5013
5014 118 sc->time_offset = start_time - (uint64_t)empty_duration;
5015 118 sc->min_corrected_pts = start_time;
5016
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 117 times.
118 if (!mov->advanced_editlist)
5017 1 current_dts = -av_clip64(sc->time_offset, -INT64_MAX, INT64_MAX);
5018 }
5019
5020
4/4
✓ Branch 0 taken 520 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 517 times.
527 if (!multiple_edits && !mov->advanced_editlist &&
5021
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
3 st->codecpar->codec_id == AV_CODEC_ID_AAC && start_time > 0)
5022 st->codecpar->initial_padding = av_rescale_q(start_time, st->time_base,
5023 (AVRational){1, st->codecpar->sample_rate});
5024 }
5025
5026 /* only use old uncompressed audio chunk demuxing when stts specifies it */
5027
2/2
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 469 times.
755 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
5028
5/6
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 238 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 170 times.
✓ Branch 5 taken 68 times.
943 sc->stts_count == 1 && sc->stts_data && sc->stts_data[0].duration == 1)) {
5029 687 unsigned int current_sample = 0;
5030 687 unsigned int stts_sample = 0;
5031 unsigned int sample_size;
5032 687 unsigned int distance = 0;
5033 687 unsigned int rap_group_index = 0;
5034 687 unsigned int rap_group_sample = 0;
5035
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 686 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
687 int rap_group_present = sc->rap_group_count && sc->rap_group;
5036
4/8
✓ Branch 0 taken 167 times.
✓ Branch 1 taken 520 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 167 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 520 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
687 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
5037
5038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 687 times.
687 av_assert0(sc->dts_shift >= 0);
5039
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 687 times.
687 if (current_dts < INT64_MIN + sc->dts_shift)
5040 return;
5041 687 current_dts -= sc->dts_shift;
5042
4/6
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 657 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 657 times.
687 if (!sc->sample_count || sti->nb_index_entries || sc->tts_count)
5043 30 return;
5044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 657 times.
657 if (sc->sample_count >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
5045 return;
5046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 657 times.
657 if (av_reallocp_array(&sti->index_entries,
5047 657 sti->nb_index_entries + sc->sample_count,
5048 sizeof(*sti->index_entries)) < 0) {
5049 sti->nb_index_entries = 0;
5050 return;
5051 }
5052 657 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
5053
5054 657 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
5055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 657 times.
657 if (ret < 0)
5056 return;
5057
5058
2/2
✓ Branch 0 taken 174753 times.
✓ Branch 1 taken 657 times.
175410 for (i = 0; i < sc->chunk_count; i++) {
5059
2/2
✓ Branch 0 taken 174096 times.
✓ Branch 1 taken 657 times.
174753 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
5060 174753 current_offset = sc->chunk_offsets[i];
5061
2/2
✓ Branch 1 taken 8723 times.
✓ Branch 2 taken 168586 times.
177309 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
5062
2/2
✓ Branch 0 taken 2556 times.
✓ Branch 1 taken 6167 times.
8723 i + 1 == sc->stsc_data[stsc_index + 1].first)
5063 2556 stsc_index++;
5064
5065
4/6
✓ Branch 0 taken 174753 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7410 times.
✓ Branch 3 taken 167343 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7410 times.
174753 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
5066 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
5067 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
5068 sc->stsz_sample_size = sc->sample_size;
5069 }
5070
3/4
✓ Branch 0 taken 7410 times.
✓ Branch 1 taken 167343 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7410 times.
174753 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
5071 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
5072 sc->stsz_sample_size = sc->sample_size;
5073 }
5074
5075
2/2
✓ Branch 0 taken 248989 times.
✓ Branch 1 taken 174753 times.
423742 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
5076 248989 int keyframe = 0;
5077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 248989 times.
248989 if (current_sample >= sc->sample_count) {
5078 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
5079 return;
5080 }
5081
5082
6/6
✓ Branch 0 taken 239278 times.
✓ Branch 1 taken 9711 times.
✓ Branch 2 taken 153366 times.
✓ Branch 3 taken 85912 times.
✓ Branch 4 taken 5755 times.
✓ Branch 5 taken 147611 times.
248989 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
5083 91667 keyframe = 1;
5084
2/2
✓ Branch 0 taken 5588 times.
✓ Branch 1 taken 86079 times.
91667 if (stss_index + 1 < sc->keyframe_count)
5085 5588 stss_index++;
5086
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 157322 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
157322 } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
5087 keyframe = 1;
5088 if (stps_index + 1 < sc->stps_count)
5089 stps_index++;
5090 }
5091
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 248801 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
248989 if (rap_group_present && rap_group_index < sc->rap_group_count) {
5092
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
5093 2 keyframe = 1;
5094
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
5095 4 rap_group_sample = 0;
5096 4 rap_group_index++;
5097 }
5098 }
5099
2/2
✓ Branch 0 taken 9711 times.
✓ Branch 1 taken 239278 times.
248989 if (sc->keyframe_absent
5100
1/2
✓ Branch 0 taken 9711 times.
✗ Branch 1 not taken.
9711 && !sc->stps_count
5101
1/2
✓ Branch 0 taken 9711 times.
✗ Branch 1 not taken.
9711 && !rap_group_present
5102
6/6
✓ Branch 0 taken 874 times.
✓ Branch 1 taken 8837 times.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 824 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 48 times.
9711 && (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || (i==0 && j==0)))
5103 8839 keyframe = 1;
5104
2/2
✓ Branch 0 taken 100506 times.
✓ Branch 1 taken 148483 times.
248989 if (keyframe)
5105 100506 distance = 0;
5106
2/2
✓ Branch 0 taken 9299 times.
✓ Branch 1 taken 239690 times.
248989 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
5107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 248989 times.
248989 if (current_offset > INT64_MAX - sample_size) {
5108 av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
5109 current_offset,
5110 sample_size);
5111 return;
5112 }
5113
5114
2/2
✓ Branch 0 taken 248892 times.
✓ Branch 1 taken 97 times.
248989 if (sc->pseudo_stream_id == -1 ||
5115
2/2
✓ Branch 0 taken 248890 times.
✓ Branch 1 taken 2 times.
248892 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
5116 AVIndexEntry *e;
5117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 248987 times.
248987 if (sample_size > 0x3FFFFFFF) {
5118 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
5119 return;
5120 }
5121 248987 e = &sti->index_entries[sti->nb_index_entries++];
5122 248987 e->pos = current_offset;
5123 248987 e->timestamp = current_dts;
5124 248987 e->size = sample_size;
5125 248987 e->min_distance = distance;
5126 248987 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
5127 248987 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
5128 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
5129 current_offset, current_dts, sample_size, distance, keyframe);
5130
4/4
✓ Branch 0 taken 156280 times.
✓ Branch 1 taken 92707 times.
✓ Branch 2 taken 11647 times.
✓ Branch 3 taken 144633 times.
248987 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries < 100)
5131 11647 ff_rfps_add_frame(mov->fc, st, current_dts);
5132 }
5133
5134 248989 current_offset += sample_size;
5135 248989 stream_size += sample_size;
5136
5137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 248989 times.
248989 if (current_dts > INT64_MAX - sc->tts_data[stts_index].duration)
5138 return;
5139 248989 current_dts += sc->tts_data[stts_index].duration;
5140
5141 248989 distance++;
5142 248989 stts_sample++;
5143 248989 current_sample++;
5144
3/4
✓ Branch 0 taken 248332 times.
✓ Branch 1 taken 657 times.
✓ Branch 2 taken 248332 times.
✗ Branch 3 not taken.
248989 if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) {
5145 248332 stts_sample = 0;
5146 248332 stts_index++;
5147 }
5148 }
5149 }
5150
2/2
✓ Branch 0 taken 614 times.
✓ Branch 1 taken 43 times.
657 if (st->duration > 0)
5151 614 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
5152 } else {
5153 68 unsigned chunk_samples, total = 0;
5154
5155
2/4
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 68 times.
68 if (!sc->chunk_count || sc->tts_count)
5156 return;
5157
5158 // compute total chunk count
5159
2/2
✓ Branch 0 taken 739 times.
✓ Branch 1 taken 68 times.
807 for (i = 0; i < sc->stsc_count; i++) {
5160 unsigned count, chunk_count;
5161
5162 739 chunk_samples = sc->stsc_data[i].count;
5163
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 68 times.
739 if (i != sc->stsc_count - 1 &&
5164
3/4
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 77 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 594 times.
671 sc->samples_per_frame && chunk_samples % sc->samples_per_frame) {
5165 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
5166 return;
5167 }
5168
5169
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 664 times.
739 if (sc->samples_per_frame >= 160) { // gsm
5170 75 count = chunk_samples / sc->samples_per_frame;
5171
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 133 times.
664 } else if (sc->samples_per_frame > 1) {
5172 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
5173 531 count = (chunk_samples+samples-1) / samples;
5174 } else {
5175 133 count = (chunk_samples+1023) / 1024;
5176 }
5177
5178
2/2
✓ Branch 1 taken 671 times.
✓ Branch 2 taken 68 times.
739 if (mov_stsc_index_valid(i, sc->stsc_count))
5179 671 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
5180 else
5181 68 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
5182 739 total += chunk_count * count;
5183 }
5184
5185 68 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
5186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
5187 return;
5188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (av_reallocp_array(&sti->index_entries,
5189 68 sti->nb_index_entries + total,
5190 sizeof(*sti->index_entries)) < 0) {
5191 sti->nb_index_entries = 0;
5192 return;
5193 }
5194 68 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
5195
5196 // populate index
5197
2/2
✓ Branch 0 taken 5560 times.
✓ Branch 1 taken 68 times.
5628 for (i = 0; i < sc->chunk_count; i++) {
5198 5560 current_offset = sc->chunk_offsets[i];
5199
2/2
✓ Branch 1 taken 5399 times.
✓ Branch 2 taken 161 times.
5560 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
5200
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 4728 times.
5399 i + 1 == sc->stsc_data[stsc_index + 1].first)
5201 671 stsc_index++;
5202 5560 chunk_samples = sc->stsc_data[stsc_index].count;
5203
5204
2/2
✓ Branch 0 taken 165262 times.
✓ Branch 1 taken 5560 times.
170822 while (chunk_samples > 0) {
5205 AVIndexEntry *e;
5206 unsigned size, samples;
5207
5208
3/4
✓ Branch 0 taken 23921 times.
✓ Branch 1 taken 141341 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 23921 times.
165262 if (sc->samples_per_frame > 1 && !sc->bytes_per_frame) {
5209 avpriv_request_sample(mov->fc,
5210 "Zero bytes per frame, but %d samples per frame",
5211 sc->samples_per_frame);
5212 return;
5213 }
5214
5215
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 150904 times.
165262 if (sc->samples_per_frame >= 160) { // gsm
5216 14358 samples = sc->samples_per_frame;
5217 14358 size = sc->bytes_per_frame;
5218 } else {
5219
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 141341 times.
150904 if (sc->samples_per_frame > 1) {
5220 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
5221 sc->samples_per_frame, chunk_samples);
5222 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
5223 } else {
5224 141341 samples = FFMIN(1024, chunk_samples);
5225 141341 size = samples * sc->sample_size;
5226 }
5227 }
5228
5229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165262 times.
165262 if (sti->nb_index_entries >= total) {
5230 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
5231 return;
5232 }
5233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165262 times.
165262 if (size > 0x3FFFFFFF) {
5234 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
5235 return;
5236 }
5237 165262 e = &sti->index_entries[sti->nb_index_entries++];
5238 165262 e->pos = current_offset;
5239 165262 e->timestamp = current_dts;
5240 165262 e->size = size;
5241 165262 e->min_distance = 0;
5242 165262 e->flags = AVINDEX_KEYFRAME;
5243 165262 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
5244 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
5245 size, samples);
5246
5247 165262 current_offset += size;
5248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165262 times.
165262 if (current_dts > INT64_MAX - samples)
5249 return;
5250 165262 current_dts += samples;
5251 165262 chunk_samples -= samples;
5252 }
5253 }
5254
5255 68 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
5256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (ret < 0)
5257 return;
5258 }
5259
5260
2/4
✓ Branch 0 taken 725 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 725 times.
✗ Branch 3 not taken.
725 if (!mov->ignore_editlist && mov->advanced_editlist) {
5261 // Fix index according to edit lists.
5262 725 mov_fix_index(mov, st);
5263 }
5264
5265 // Update start time of the stream.
5266
5/6
✓ Branch 0 taken 201 times.
✓ Branch 1 taken 524 times.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 130 times.
✓ Branch 4 taken 71 times.
✗ Branch 5 not taken.
725 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) {
5267 71 st->start_time = av_sat_add64(sti->index_entries[0].timestamp, sc->dts_shift);
5268
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 if (sc->tts_data) {
5269 71 st->start_time = av_sat_add64(st->start_time, sc->tts_data[0].offset);
5270 }
5271 }
5272
5273 725 mov_estimate_video_delay(mov, st);
5274 }
5275
5276 typedef struct MOVPresentationSample {
5277 int index;
5278 int64_t pts;
5279 } MOVPresentationSample;
5280
5281 12202 static int mov_compare_presentation_samples(const void *a, const void *b)
5282 {
5283 12202 const MOVPresentationSample *sa = a;
5284 12202 const MOVPresentationSample *sb = b;
5285
5286
2/2
✓ Branch 0 taken 12198 times.
✓ Branch 1 taken 4 times.
12202 if (sa->pts != sb->pts)
5287 12198 return (sa->pts > sb->pts) - (sa->pts < sb->pts);
5288 4 return (sa->index > sb->index) - (sa->index < sb->index);
5289 }
5290
5291 /*
5292 * Set sample durations from adjacent presentation timestamps.
5293 */
5294 712 static void mov_update_sample_durations(MOVContext *mov, AVStream *st)
5295 {
5296 712 MOVStreamContext *sc = st->priv_data;
5297 712 FFStream *const sti = ffstream(st);
5298 712 MOVPresentationSample *samples = NULL;
5299 712 MOVTimeToSample *tts_data = NULL;
5300 712 unsigned int tts_index = 0, tts_sample = 0;
5301 712 int count = sti->nb_index_entries;
5302
5303 /* A single STTS entry describes a fixed sample delta. */
5304
2/2
✓ Branch 0 taken 369 times.
✓ Branch 1 taken 343 times.
712 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
5305
4/4
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 295 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 62 times.
369 !sc->ctts_count || sc->stts_count < 2 ||
5306
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 !sc->tts_data || count < 2 ||
5307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 count >= UINT_MAX / sizeof(*tts_data))
5308 700 return;
5309
5310 12 samples = av_malloc_array(count, sizeof(*samples));
5311 12 tts_data = av_malloc_array(count, sizeof(*tts_data));
5312
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (!samples || !tts_data)
5313 goto fail;
5314
5315
2/2
✓ Branch 0 taken 2654 times.
✓ Branch 1 taken 12 times.
2666 for (int i = 0; i < count; i++) {
5316 int64_t dts, offset;
5317
5318
2/4
✓ Branch 0 taken 2654 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2654 times.
2654 if (tts_index >= sc->tts_count || !sc->tts_data[tts_index].count)
5319 goto fail;
5320
5321 2654 tts_data[i] = sc->tts_data[tts_index];
5322 2654 tts_data[i].count = 1;
5323
5324 2654 dts = sti->index_entries[i].timestamp;
5325 2654 offset = (int64_t)sc->dts_shift + tts_data[i].offset;
5326
3/4
✓ Branch 0 taken 2654 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2613 times.
✓ Branch 3 taken 41 times.
2654 if (dts == AV_NOPTS_VALUE ||
5327
2/4
✓ Branch 0 taken 2613 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2654 times.
2654 (offset > 0 && dts > INT64_MAX - offset) ||
5328 (offset < 0 && dts < INT64_MIN - offset))
5329 goto fail;
5330
5331 2654 samples[i].index = i;
5332 2654 samples[i].pts = dts + offset;
5333
5334
1/2
✓ Branch 0 taken 2654 times.
✗ Branch 1 not taken.
2654 if (++tts_sample == sc->tts_data[tts_index].count) {
5335 2654 tts_index++;
5336 2654 tts_sample = 0;
5337 }
5338 }
5339
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (tts_index != sc->tts_count || tts_sample)
5340 goto fail;
5341
5342 12 qsort(samples, count, sizeof(*samples), mov_compare_presentation_samples);
5343
5344
2/2
✓ Branch 0 taken 2624 times.
✓ Branch 1 taken 10 times.
2634 for (int i = 0; i + 1 < count; i++) {
5345 uint64_t duration;
5346
5347
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2622 times.
2624 if (samples[i].pts >= samples[i + 1].pts)
5348 2 goto fail;
5349
5350 /*
5351 * In VFR streams with reordered frames, STTS deltas follow decode
5352 * order while AVPacket.duration follows presentation order. CTTS
5353 * may produce presentation intervals that cannot be obtained by
5354 * merely permuting the STTS deltas, so derive each known duration
5355 * from adjacent PTS.
5356 */
5357 2622 duration = (uint64_t)samples[i + 1].pts - samples[i].pts;
5358
2/4
✓ Branch 0 taken 2622 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2622 times.
2622 if (!duration || duration > UINT_MAX)
5359 goto fail;
5360
5361 2622 tts_data[samples[i].index].duration = (unsigned int)duration;
5362 }
5363
5364 10 av_log(mov->fc, AV_LOG_DEBUG,
5365 "Updated sample durations in presentation order for stream %d\n",
5366 st->index);
5367
5368 10 av_freep(&sc->tts_data);
5369 10 sc->tts_data = tts_data;
5370 10 sc->tts_count = count;
5371 10 sc->tts_allocated_size = count * sizeof(*tts_data);
5372 10 tts_data = NULL;
5373
5374 12 fail:
5375 12 av_free(samples);
5376 12 av_free(tts_data);
5377 }
5378
5379 static int test_same_origin(const char *src, const char *ref) {
5380 char src_proto[64];
5381 char ref_proto[64];
5382 char src_auth[256];
5383 char ref_auth[256];
5384 char src_host[256];
5385 char ref_host[256];
5386 int src_port=-1;
5387 int ref_port=-1;
5388
5389 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
5390 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
5391
5392 if (strlen(src) == 0) {
5393 return -1;
5394 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
5395 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
5396 strlen(src_host) + 1 >= sizeof(src_host) ||
5397 strlen(ref_host) + 1 >= sizeof(ref_host)) {
5398 return 0;
5399 } else if (strcmp(src_proto, ref_proto) ||
5400 strcmp(src_auth, ref_auth) ||
5401 strcmp(src_host, ref_host) ||
5402 src_port != ref_port) {
5403 return 0;
5404 } else
5405 return 1;
5406 }
5407
5408 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
5409 {
5410 /* try relative path, we do not try the absolute because it can leak information about our
5411 system to an attacker */
5412 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
5413 char filename[1025];
5414 const char *src_path;
5415 int i, l;
5416
5417 /* find a source dir */
5418 src_path = strrchr(src, '/');
5419 if (src_path)
5420 src_path++;
5421 else
5422 src_path = src;
5423
5424 /* find a next level down to target */
5425 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
5426 if (ref->path[l] == '/') {
5427 if (i == ref->nlvl_to - 1)
5428 break;
5429 else
5430 i++;
5431 }
5432
5433 /* compose filename if next level down to target was found */
5434 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
5435 memcpy(filename, src, src_path - src);
5436 filename[src_path - src] = 0;
5437
5438 for (i = 1; i < ref->nlvl_from; i++)
5439 av_strlcat(filename, "../", sizeof(filename));
5440
5441 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
5442 if (!c->use_absolute_path) {
5443 int same_origin = test_same_origin(src, filename);
5444
5445 if (!same_origin) {
5446 av_log(c->fc, AV_LOG_ERROR,
5447 "Reference with mismatching origin, %s not tried for security reasons, "
5448 "set demuxer option use_absolute_path to allow it anyway\n",
5449 ref->path);
5450 return AVERROR(ENOENT);
5451 }
5452
5453 if (strstr(ref->path + l + 1, "..") ||
5454 strstr(ref->path + l + 1, ":") ||
5455 (ref->nlvl_from > 1 && same_origin < 0) ||
5456 (filename[0] == '/' && src_path == src))
5457 return AVERROR(ENOENT);
5458 }
5459
5460 if (strlen(filename) + 1 == sizeof(filename))
5461 return AVERROR(ENOENT);
5462 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5463 return 0;
5464 }
5465 } else if (c->use_absolute_path) {
5466 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5467 "this is a possible security issue\n");
5468 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5469 return 0;
5470 } else {
5471 av_log(c->fc, AV_LOG_ERROR,
5472 "Absolute path %s not tried for security reasons, "
5473 "set demuxer option use_absolute_path to allow absolute paths\n",
5474 ref->path);
5475 }
5476
5477 return AVERROR(ENOENT);
5478 }
5479
5480 1535 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5481 {
5482
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1519 times.
1535 if (sc->time_scale <= 0) {
5483 16 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5484 16 sc->time_scale = c->time_scale;
5485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (sc->time_scale <= 0)
5486 sc->time_scale = 1;
5487 }
5488 1535 }
5489
5490 #if CONFIG_IAMFDEC
5491 12 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5492 {
5493 12 const MOVStreamContext *sc = st->priv_data;
5494 12 const IAMFContext *iamf = &sc->iamf->iamf;
5495
5496
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5497 12 const AVStreamGroup *stg = NULL;
5498
5499
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5500
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 if (c->fc->stream_groups[j]->id == iamf->audio_elements[i]->audio_element_id)
5501 12 stg = c->fc->stream_groups[j];
5502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 av_assert0(stg);
5503
5504
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_streams; j++) {
5505 64 const FFStream *sti = cffstream(st);
5506 64 AVStream *out = stg->streams[j];
5507 64 FFStream *out_sti = ffstream(stg->streams[j]);
5508
5509 64 out->codecpar->bit_rate = 0;
5510
5511
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 52 times.
64 if (out == st)
5512 12 continue;
5513
5514 52 out->time_base = st->time_base;
5515 52 out->start_time = st->start_time;
5516 52 out->duration = st->duration;
5517 52 out->nb_frames = st->nb_frames;
5518 52 out->discard = st->discard;
5519
5520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 av_assert0(!out_sti->index_entries);
5521 52 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (!out_sti->index_entries)
5523 return AVERROR(ENOMEM);
5524
5525 52 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5526 52 out_sti->nb_index_entries = sti->nb_index_entries;
5527 52 out_sti->skip_samples = sti->skip_samples;
5528 52 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5529 }
5530 }
5531
5532 12 return 0;
5533 }
5534 #endif
5535
5536 755 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5537 {
5538
4/6
✓ Branch 0 taken 725 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 725 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 725 times.
✗ Branch 5 not taken.
755 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5539
3/4
✓ Branch 0 taken 463 times.
✓ Branch 1 taken 262 times.
✓ Branch 2 taken 463 times.
✗ Branch 3 not taken.
725 (!sc->sample_size && !sc->sample_count))) ||
5540
3/4
✓ Branch 0 taken 725 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 725 times.
✗ Branch 3 not taken.
755 (sc->sample_count && (!sc->chunk_count ||
5541
3/4
✓ Branch 0 taken 463 times.
✓ Branch 1 taken 262 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 463 times.
725 (!sc->sample_size && !sc->sample_sizes)))) {
5542 av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5543 index);
5544 return 1;
5545 }
5546
5547
3/4
✓ Branch 0 taken 725 times.
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 725 times.
755 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
5548 av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5549 index);
5550 return 2;
5551 }
5552 755 return 0;
5553 }
5554
5555 712 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5556 {
5557 AVStream *st;
5558 MOVStreamContext *sc;
5559 int ret;
5560
5561 712 st = avformat_new_stream(c->fc, NULL);
5562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (!st) return AVERROR(ENOMEM);
5563 712 st->id = -1;
5564 712 sc = av_mallocz(sizeof(MOVStreamContext));
5565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (!sc) return AVERROR(ENOMEM);
5566
5567 712 st->priv_data = sc;
5568 712 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5569 712 sc->ffindex = st->index;
5570 712 c->trak_index = st->index;
5571 712 sc->refcount = 1;
5572
5573
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 712 times.
712 if ((ret = mov_read_default(c, pb, atom)) < 0)
5574 return ret;
5575
5576 712 c->trak_index = -1;
5577
5578 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5579 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5580
5/6
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 682 times.
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 29 times.
712 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
5581 1 sc->stsc_count = 0;
5582 1 av_freep(&sc->stsc_data);
5583 }
5584
5585 712 ret = sanity_checks(c->fc, sc, st->index);
5586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (ret)
5587 return ret > 1 ? AVERROR_INVALIDDATA : 0;
5588
5589 712 fix_timescale(c, sc);
5590
5591 712 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5592
5593 /*
5594 * Advanced edit list support does not work with fragemented MP4s, which
5595 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5596 * In these files, trun atoms may be streamed in.
5597 */
5598
4/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 682 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 9 times.
712 if (!sc->stts_count && c->advanced_editlist) {
5599
5600 21 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5601 "MP4. disabling.\n");
5602 21 c->advanced_editlist = 0;
5603 21 c->advanced_editlist_autodisabled = 1;
5604 }
5605
5606 712 mov_build_index(c, st);
5607 /*
5608 * Fragment samples are appended later by mov_read_trun() and are not
5609 * covered by this non-fragmented track update.
5610 */
5611 712 mov_update_sample_durations(c, st);
5612
5613 #if CONFIG_IAMFDEC
5614
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 700 times.
712 if (sc->iamf) {
5615 12 ret = mov_update_iamf_streams(c, st);
5616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
5617 return ret;
5618 }
5619 #endif
5620
5621
3/4
✓ Branch 0 taken 711 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 711 times.
712 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
5622 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5623 if (c->enable_drefs) {
5624 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5625 av_log(c->fc, AV_LOG_ERROR,
5626 "stream %d, error opening alias: path='%s', dir='%s', "
5627 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5628 st->index, dref->path, dref->dir, dref->filename,
5629 dref->volume, dref->nlvl_from, dref->nlvl_to);
5630 } else {
5631 av_log(c->fc, AV_LOG_WARNING,
5632 "Skipped opening external track: "
5633 "stream %d, alias: path='%s', dir='%s', "
5634 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5635 "Set enable_drefs to allow this.\n",
5636 st->index, dref->path, dref->dir, dref->filename,
5637 dref->volume, dref->nlvl_from, dref->nlvl_to);
5638 }
5639 } else {
5640 712 sc->pb = c->fc->pb;
5641 712 sc->pb_is_copied = 1;
5642 }
5643
5644
2/2
✓ Branch 0 taken 369 times.
✓ Branch 1 taken 343 times.
712 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5645
3/4
✓ Branch 0 taken 351 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 351 times.
✗ Branch 3 not taken.
369 int stts_constant = sc->stts_count && sc->tts_count;
5646
3/4
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 280 times.
✓ Branch 2 taken 89 times.
✗ Branch 3 not taken.
369 if (sc->h_spacing && sc->v_spacing)
5647 89 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5648 89 sc->h_spacing, sc->v_spacing, INT_MAX);
5649
4/6
✓ Branch 0 taken 277 times.
✓ Branch 1 taken 92 times.
✓ Branch 2 taken 277 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 277 times.
✗ Branch 5 not taken.
369 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
5650
2/4
✓ Branch 0 taken 277 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 277 times.
✗ Branch 3 not taken.
277 sc->height && sc->width &&
5651
2/4
✓ Branch 0 taken 277 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 277 times.
277 (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
5652 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5653 (int64_t)st->codecpar->height * sc->width,
5654 (int64_t)st->codecpar->width * sc->height, INT_MAX);
5655 }
5656
5657 #if FF_API_R_FRAME_RATE
5658
4/4
✓ Branch 0 taken 156073 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 155722 times.
✓ Branch 3 taken 351 times.
156091 for (unsigned int i = 1; sc->stts_count && i + 1 < sc->tts_count; i++) {
5659
2/2
✓ Branch 0 taken 153227 times.
✓ Branch 1 taken 2495 times.
155722 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5660 153227 continue;
5661 2495 stts_constant = 0;
5662 }
5663
2/2
✓ Branch 0 taken 332 times.
✓ Branch 1 taken 37 times.
369 if (stts_constant)
5664 332 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5665 332 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5666 #endif
5667 }
5668
5669 #if CONFIG_H261_DECODER || CONFIG_H263_DECODER || CONFIG_MPEG4_DECODER
5670
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 682 times.
712 switch (st->codecpar->codec_id) {
5671 #if CONFIG_H261_DECODER
5672 30 case AV_CODEC_ID_H261:
5673 #endif
5674 #if CONFIG_H263_DECODER
5675 case AV_CODEC_ID_H263:
5676 #endif
5677 #if CONFIG_MPEG4_DECODER
5678 case AV_CODEC_ID_MPEG4:
5679 #endif
5680 30 st->codecpar->width = 0; /* let decoder init width/height */
5681 30 st->codecpar->height= 0;
5682 30 break;
5683 }
5684 #endif
5685
5686 // If the duration of the mp3 packets is not constant, then they could need a parser
5687
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 709 times.
712 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5688
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 && sc->time_scale == st->codecpar->sample_rate) {
5689 3 int stts_constant = 1;
5690
3/4
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 365 times.
✓ Branch 3 taken 3 times.
368 for (int i = 1; sc->stts_count && i < sc->tts_count; i++) {
5691
1/2
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
365 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5692 365 continue;
5693 stts_constant = 0;
5694 }
5695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!stts_constant)
5696 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5697 }
5698 /* Do not need those anymore. */
5699 712 av_freep(&sc->chunk_offsets);
5700 712 av_freep(&sc->sample_sizes);
5701 712 av_freep(&sc->keyframes);
5702 712 av_freep(&sc->stps_data);
5703 712 av_freep(&sc->elst_data);
5704 712 av_freep(&sc->rap_group);
5705 712 av_freep(&sc->sync_group);
5706 712 av_freep(&sc->sgpd_sync);
5707
5708 712 return 0;
5709 }
5710
5711 186 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5712 {
5713 int ret;
5714 186 c->itunes_metadata = 1;
5715 186 ret = mov_read_default(c, pb, atom);
5716 186 c->itunes_metadata = 0;
5717 186 return ret;
5718 }
5719
5720 11 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5721 {
5722 uint32_t count;
5723 uint32_t i;
5724
5725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
5726 return 0;
5727
5728 11 avio_skip(pb, 4);
5729 11 count = avio_rb32(pb);
5730 11 atom.size -= 8;
5731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (count >= UINT_MAX / sizeof(*c->meta_keys)) {
5732 av_log(c->fc, AV_LOG_ERROR,
5733 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5734 return AVERROR_INVALIDDATA;
5735 }
5736
5737 11 c->meta_keys_count = count + 1;
5738 11 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
5739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!c->meta_keys)
5740 return AVERROR(ENOMEM);
5741
5742
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i <= count; ++i) {
5743 58 uint32_t key_size = avio_rb32(pb);
5744 58 uint32_t type = avio_rl32(pb);
5745
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) {
5746 av_log(c->fc, AV_LOG_ERROR,
5747 "The key# %"PRIu32" in meta has invalid size:"
5748 "%"PRIu32"\n", i, key_size);
5749 return AVERROR_INVALIDDATA;
5750 }
5751 58 atom.size -= key_size;
5752 58 key_size -= 8;
5753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (type != MKTAG('m','d','t','a')) {
5754 avio_skip(pb, key_size);
5755 continue;
5756 }
5757 58 c->meta_keys[i] = av_mallocz(key_size + 1);
5758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!c->meta_keys[i])
5759 return AVERROR(ENOMEM);
5760 58 avio_read(pb, c->meta_keys[i], key_size);
5761 }
5762
5763 11 return 0;
5764 }
5765
5766 80 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5767 {
5768 80 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5769 80 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5770 int i;
5771 80 int ret = 0;
5772 AVStream *st;
5773
5774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (c->fc->nb_streams < 1)
5775 return 0;
5776 80 st = c->fc->streams[c->fc->nb_streams-1];
5777
5778
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 80 times.
320 for (i = 0; i < 3; i++) {
5779 uint8_t **p;
5780 uint32_t len, tag;
5781
5782
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 240 times.
240 if (end - avio_tell(pb) <= 12)
5783 break;
5784
5785 240 len = avio_rb32(pb);
5786 240 tag = avio_rl32(pb);
5787 240 avio_skip(pb, 4); // flags
5788
5789
2/4
✓ Branch 0 taken 240 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 240 times.
✗ Branch 4 not taken.
240 if (len < 12 || len - 12 > end - avio_tell(pb))
5790 break;
5791 240 len -= 12;
5792
5793
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 160 times.
240 if (tag == MKTAG('m', 'e', 'a', 'n'))
5794 80 p = &mean;
5795
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 80 times.
160 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5796 80 p = &key;
5797
2/4
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
80 else if (tag == MKTAG('d', 'a', 't', 'a') && len > 4) {
5798 80 avio_skip(pb, 4);
5799 80 len -= 4;
5800 80 p = &val;
5801 } else
5802 break;
5803
5804
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (*p)
5805 break;
5806
5807 240 *p = av_malloc(len + 1);
5808
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (!*p) {
5809 ret = AVERROR(ENOMEM);
5810 break;
5811 }
5812 240 ret = ffio_read_size(pb, *p, len);
5813
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (ret < 0) {
5814 av_freep(p);
5815 break;
5816 }
5817 240 (*p)[len] = 0;
5818 }
5819
5820
3/6
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 80 times.
✗ Branch 5 not taken.
80 if (mean && key && val) {
5821
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 38 times.
80 if (strcmp(key, "iTunSMPB") == 0) {
5822 int64_t priming, remainder, samples;
5823
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 if (ff_itunes_parse_smpb(val, &priming, &remainder, &samples) >= 0) {
5824
2/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
42 if(priming>0 && priming<16384)
5825 42 st->codecpar->initial_padding = priming = av_rescale_q(priming, st->time_base,
5826 42 (AVRational){ 1, st->codecpar->sample_rate });
5827
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 if (remainder > 0) {
5828 42 int64_t duration = av_rescale_q(st->duration, st->time_base,
5829 42 (AVRational){ 1, st->codecpar->sample_rate });
5830 42 remainder = av_rescale_q(remainder, st->time_base,
5831 42 (AVRational){ 1, st->codecpar->sample_rate });
5832 42 samples = av_rescale_q(samples, st->time_base,
5833 42 (AVRational){ 1, st->codecpar->sample_rate });
5834
2/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
42 if (duration > remainder && duration > samples) {
5835 42 ffstream(st)->first_discard_sample = duration - remainder;
5836 42 ffstream(st)->last_discard_sample = duration;
5837 }
5838 }
5839 42 av_log(c->fc, AV_LOG_DEBUG, "Parsed iTunSMPB: priming %"PRId64", "
5840 "remainder %"PRId64" samples %"PRId64"\n",
5841 priming, remainder, samples);
5842 }
5843 }
5844
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 if (strcmp(mean, "com.apple.iTunes") == 0 &&
5845
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 78 times.
80 strcmp(key, "DISCSUBTITLE") == 0) {
5846 2 av_dict_set(&c->fc->metadata, "disc_subtitle", val,
5847 AV_DICT_DONT_STRDUP_VAL);
5848 2 val = NULL;
5849 }
5850
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 10 times.
150 if (strcmp(key, "cdec") != 0) {
5851 70 av_dict_set(&c->fc->metadata, key, val,
5852 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5853 70 key = val = NULL;
5854 }
5855 } else {
5856 av_log(c->fc, AV_LOG_VERBOSE,
5857 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5858 }
5859
5860 80 avio_seek(pb, end, SEEK_SET);
5861 80 av_freep(&key);
5862 80 av_freep(&val);
5863 80 av_freep(&mean);
5864 80 return ret;
5865 }
5866
5867 43 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5868 {
5869 MOVStreamContext *sc;
5870 AVStream *st;
5871
5872 43 st = avformat_new_stream(c->fc, NULL);
5873
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st)
5874 return AVERROR(ENOMEM);
5875 43 sc = av_mallocz(sizeof(MOVStreamContext));
5876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc)
5877 goto fail;
5878
5879 43 item->st = st;
5880 43 st->id = item->item_id;
5881 43 st->priv_data = sc;
5882 43 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5883 43 st->codecpar->codec_id = mov_codec_id(st, item->type);
5884 43 sc->id = st->id;
5885 43 sc->ffindex = st->index;
5886 43 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5887 43 st->time_base.num = st->time_base.den = 1;
5888 43 st->nb_frames = 1;
5889 43 sc->time_scale = 1;
5890 43 sc->pb = c->fc->pb;
5891 43 sc->pb_is_copied = 1;
5892 43 sc->refcount = 1;
5893
5894
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (item->name)
5895 43 av_dict_set(&st->metadata, "title", item->name, 0);
5896
5897 // Populate the necessary fields used by mov_build_index.
5898 43 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->stsc_data)
5900 goto fail;
5901 43 sc->stsc_count = 1;
5902 43 sc->stsc_data[0].first = 1;
5903 43 sc->stsc_data[0].count = 1;
5904 43 sc->stsc_data[0].id = 1;
5905 43 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->chunk_offsets)
5907 goto fail;
5908 43 sc->chunk_count = 1;
5909 43 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->stts_data)
5911 goto fail;
5912 43 sc->stts_count = 1;
5913 43 sc->stts_data[0].count = 1;
5914 // Not used for still images. But needed by mov_build_index.
5915 43 sc->stts_data[0].duration = 0;
5916
5917 43 return 0;
5918 fail:
5919 mov_free_stream_context(c->fc, st);
5920 ff_remove_stream(c->fc, st);
5921 item->st = NULL;
5922
5923 return AVERROR(ENOMEM);
5924 }
5925
5926 208 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5927 {
5928
1/2
✓ Branch 0 taken 610 times.
✗ Branch 1 not taken.
610 while (atom.size > 8) {
5929 uint32_t tag;
5930
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 610 times.
610 if (avio_feof(pb))
5931 return AVERROR_EOF;
5932 610 tag = avio_rl32(pb);
5933 610 atom.size -= 4;
5934
2/2
✓ Branch 0 taken 208 times.
✓ Branch 1 taken 402 times.
610 if (tag == MKTAG('h','d','l','r')) {
5935 208 avio_seek(pb, -8, SEEK_CUR);
5936 208 atom.size += 8;
5937 208 return mov_read_default(c, pb, atom);
5938 }
5939 }
5940 return 0;
5941 }
5942
5943 // return 1 when matrix is identity, 0 otherwise
5944 #define IS_MATRIX_IDENT(matrix) \
5945 ( (matrix)[0][0] == (1 << 16) && \
5946 (matrix)[1][1] == (1 << 16) && \
5947 (matrix)[2][2] == (1 << 30) && \
5948 !(matrix)[0][1] && !(matrix)[0][2] && \
5949 !(matrix)[1][0] && !(matrix)[1][2] && \
5950 !(matrix)[2][0] && !(matrix)[2][1])
5951
5952 712 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5953 {
5954 int i, j, e;
5955 int width;
5956 int height;
5957 int display_matrix[3][3];
5958 712 int res_display_matrix[3][3] = { { 0 } };
5959 AVStream *st;
5960 MOVStreamContext *sc;
5961 int version;
5962 int flags;
5963
5964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (c->fc->nb_streams < 1)
5965 return 0;
5966 712 st = c->fc->streams[c->fc->nb_streams-1];
5967 712 sc = st->priv_data;
5968
5969 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5970 // avoids corrupting AVStreams mapped to an earlier tkhd.
5971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (st->id != -1)
5972 return AVERROR_INVALIDDATA;
5973
5974 712 version = avio_r8(pb);
5975 712 flags = avio_rb24(pb);
5976 712 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5977
5978
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 699 times.
712 if (version == 1) {
5979 13 avio_rb64(pb);
5980 13 avio_rb64(pb);
5981 } else {
5982 699 avio_rb32(pb); /* creation time */
5983 699 avio_rb32(pb); /* modification time */
5984 }
5985 712 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5986 712 sc->id = st->id;
5987 712 avio_rb32(pb); /* reserved */
5988
5989 /* highlevel (considering edits) duration in movie timebase */
5990
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 699 times.
712 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5991 712 avio_rb32(pb); /* reserved */
5992 712 avio_rb32(pb); /* reserved */
5993
5994 712 avio_rb16(pb); /* layer */
5995 712 avio_rb16(pb); /* alternate group */
5996 712 avio_rb16(pb); /* volume */
5997 712 avio_rb16(pb); /* reserved */
5998
5999 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
6000 // they're kept in fixed point format through all calculations
6001 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
6002 // side data, but the scale factor is not needed to calculate aspect ratio
6003
2/2
✓ Branch 0 taken 2136 times.
✓ Branch 1 taken 712 times.
2848 for (i = 0; i < 3; i++) {
6004 2136 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
6005 2136 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
6006 2136 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
6007 }
6008
6009 712 width = avio_rb32(pb); // 16.16 fixed point track width
6010 712 height = avio_rb32(pb); // 16.16 fixed point track height
6011 712 sc->width = width >> 16;
6012 712 sc->height = height >> 16;
6013
6014 // apply the moov display matrix (after the tkhd one)
6015
2/2
✓ Branch 0 taken 2136 times.
✓ Branch 1 taken 712 times.
2848 for (i = 0; i < 3; i++) {
6016 2136 const int sh[3] = { 16, 16, 30 };
6017
2/2
✓ Branch 0 taken 6408 times.
✓ Branch 1 taken 2136 times.
8544 for (j = 0; j < 3; j++) {
6018
2/2
✓ Branch 0 taken 19224 times.
✓ Branch 1 taken 6408 times.
25632 for (e = 0; e < 3; e++) {
6019 19224 res_display_matrix[i][j] +=
6020 19224 ((int64_t) display_matrix[i][e] *
6021 19224 c->movie_display_matrix[e][j]) >> sh[e];
6022 }
6023 }
6024 }
6025
6026 // save the matrix when it is not the default identity
6027
10/18
✓ Branch 0 taken 703 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 703 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 703 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 703 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 703 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 703 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 703 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 703 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 703 times.
712 if (!IS_MATRIX_IDENT(res_display_matrix)) {
6028 9 av_freep(&sc->display_matrix);
6029 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
6030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
6031 return AVERROR(ENOMEM);
6032
6033
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
6034
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
6035 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
6036 }
6037
6038 // transform the display width/height according to the matrix
6039 // to keep the same scale, use [width height 1<<16]
6040
5/6
✓ Branch 0 taken 379 times.
✓ Branch 1 taken 333 times.
✓ Branch 2 taken 379 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 371 times.
712 if (width && height && sc->display_matrix) {
6041 double disp_transform[2];
6042
6043
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
6044 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
6045 16 sc->display_matrix[3 + i]);
6046
6047
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 &&
6048
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) &&
6049
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
6050 3 st->sample_aspect_ratio = av_d2q(
6051 3 disp_transform[0] / disp_transform[1],
6052 INT_MAX);
6053 }
6054 712 return 0;
6055 }
6056
6057 501 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6058 {
6059 501 MOVFragment *frag = &c->fragment;
6060 501 MOVTrackExt *trex = NULL;
6061 int flags, track_id, i;
6062 MOVFragmentStreamInfo * frag_stream_info;
6063
6064 501 avio_r8(pb); /* version */
6065 501 flags = avio_rb24(pb);
6066
6067 501 track_id = avio_rb32(pb);
6068
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!track_id)
6069 return AVERROR_INVALIDDATA;
6070
1/2
✓ Branch 0 taken 560 times.
✗ Branch 1 not taken.
560 for (i = 0; i < c->trex_count; i++)
6071
2/2
✓ Branch 0 taken 501 times.
✓ Branch 1 taken 59 times.
560 if (c->trex_data[i].track_id == track_id) {
6072 501 trex = &c->trex_data[i];
6073 501 break;
6074 }
6075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!trex) {
6076 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
6077 return 0;
6078 }
6079 501 c->fragment.found_tfhd = 1;
6080 501 frag->track_id = track_id;
6081 501 set_frag_stream(&c->frag_index, track_id);
6082
6083 1002 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
6084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
1002 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
6085
2/2
✓ Branch 0 taken 428 times.
✓ Branch 1 taken 73 times.
501 frag->moof_offset : frag->implicit_offset;
6086
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 440 times.
501 frag->stsd_id = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id;
6087
6088 1002 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
6089
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 435 times.
501 avio_rb32(pb) : trex->duration;
6090 1002 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
6091
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 440 times.
501 avio_rb32(pb) : trex->size;
6092 1002 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
6093
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 366 times.
501 avio_rb32(pb) : trex->flags;
6094 501 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
6095
6096 501 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6097
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (frag_stream_info) {
6098 501 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
6099 501 frag_stream_info->stsd_id = frag->stsd_id;
6100 }
6101 501 return 0;
6102 }
6103
6104 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6105 {
6106 unsigned i, num;
6107 void *new_tracks;
6108
6109 2 num = atom.size / 4;
6110
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
6111 return AVERROR(ENOMEM);
6112
6113 2 av_free(c->chapter_tracks);
6114 2 c->chapter_tracks = new_tracks;
6115 2 c->nb_chapter_tracks = num;
6116
6117
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++)
6118 2 c->chapter_tracks[i] = avio_rb32(pb);
6119
6120 2 c->nb_chapter_tracks = i;
6121
6122 2 return 0;
6123 }
6124
6125 29 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6126 {
6127 MOVTrackExt *trex;
6128 int err;
6129
6130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if ((uint64_t)c->trex_count+1 >= UINT_MAX / sizeof(*c->trex_data))
6131 return AVERROR_INVALIDDATA;
6132
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
6133 sizeof(*c->trex_data))) < 0) {
6134 c->trex_count = 0;
6135 return err;
6136 }
6137
6138 29 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
6139
6140 29 trex = &c->trex_data[c->trex_count++];
6141 29 avio_r8(pb); /* version */
6142 29 avio_rb24(pb); /* flags */
6143 29 trex->track_id = avio_rb32(pb);
6144 29 trex->stsd_id = avio_rb32(pb);
6145 29 trex->duration = avio_rb32(pb);
6146 29 trex->size = avio_rb32(pb);
6147 29 trex->flags = avio_rb32(pb);
6148 29 return 0;
6149 }
6150
6151 428 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6152 {
6153 428 MOVFragment *frag = &c->fragment;
6154 428 AVStream *st = NULL;
6155 MOVStreamContext *sc;
6156 int version, i;
6157 MOVFragmentStreamInfo * frag_stream_info;
6158 int64_t base_media_decode_time;
6159
6160
1/2
✓ Branch 0 taken 455 times.
✗ Branch 1 not taken.
455 for (i = 0; i < c->fc->nb_streams; i++) {
6161 455 sc = c->fc->streams[i]->priv_data;
6162
2/2
✓ Branch 0 taken 428 times.
✓ Branch 1 taken 27 times.
455 if (sc->id == frag->track_id) {
6163 428 st = c->fc->streams[i];
6164 428 break;
6165 }
6166 }
6167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 428 times.
428 if (!st) {
6168 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
6169 return 0;
6170 }
6171 428 sc = st->priv_data;
6172
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 424 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
428 if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1)
6173 return 0;
6174 428 version = avio_r8(pb);
6175 428 avio_rb24(pb); /* flags */
6176
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 370 times.
428 if (version) {
6177 58 base_media_decode_time = avio_rb64(pb);
6178 } else {
6179 370 base_media_decode_time = avio_rb32(pb);
6180 }
6181
6182 428 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6183
1/2
✓ Branch 0 taken 428 times.
✗ Branch 1 not taken.
428 if (frag_stream_info)
6184 428 frag_stream_info->tfdt_dts = base_media_decode_time;
6185 428 sc->track_end = base_media_decode_time;
6186
6187 428 return 0;
6188 }
6189
6190 501 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6191 {
6192 501 MOVFragment *frag = &c->fragment;
6193 501 AVStream *st = NULL;
6194 501 FFStream *sti = NULL;
6195 MOVStreamContext *sc;
6196 MOVTimeToSample *tts_data;
6197 uint64_t offset;
6198 501 int64_t dts, pts = AV_NOPTS_VALUE;
6199 501 int data_offset = 0;
6200 501 unsigned entries, first_sample_flags = frag->flags;
6201 int flags, distance, i;
6202 501 int64_t prev_dts = AV_NOPTS_VALUE;
6203 501 int next_frag_index = -1, index_entry_pos;
6204 size_t requested_size;
6205 size_t old_allocated_size;
6206 AVIndexEntry *new_entries;
6207 MOVFragmentStreamInfo * frag_stream_info;
6208
6209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!frag->found_tfhd) {
6210 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
6211 return AVERROR_INVALIDDATA;
6212 }
6213
6214
1/2
✓ Branch 0 taken 560 times.
✗ Branch 1 not taken.
560 for (i = 0; i < c->fc->nb_streams; i++) {
6215 560 sc = c->fc->streams[i]->priv_data;
6216
2/2
✓ Branch 0 taken 501 times.
✓ Branch 1 taken 59 times.
560 if (sc->id == frag->track_id) {
6217 501 st = c->fc->streams[i];
6218 501 sti = ffstream(st);
6219 501 break;
6220 }
6221 }
6222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!st) {
6223 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
6224 return 0;
6225 }
6226 501 sc = st->priv_data;
6227
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 497 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
501 if (sc->pseudo_stream_id+1 != frag->stsd_id && sc->pseudo_stream_id != -1)
6228 return 0;
6229
6230 // Find the next frag_index index that has a valid index_entry for
6231 // the current track_id.
6232 //
6233 // A valid index_entry means the trun for the fragment was read
6234 // and it's samples are in index_entries at the given position.
6235 // New index entries will be inserted before the index_entry found.
6236 501 index_entry_pos = sti->nb_index_entries;
6237
2/2
✓ Branch 0 taken 1634 times.
✓ Branch 1 taken 501 times.
2135 for (i = c->frag_index.current + 1; i < c->frag_index.nb_items; i++) {
6238 1634 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
6239
2/4
✓ Branch 0 taken 1634 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1634 times.
1634 if (frag_stream_info && frag_stream_info->index_entry >= 0) {
6240 next_frag_index = i;
6241 index_entry_pos = frag_stream_info->index_entry;
6242 break;
6243 }
6244 }
6245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 av_assert0(index_entry_pos <= sti->nb_index_entries);
6246
6247 501 avio_r8(pb); /* version */
6248 501 flags = avio_rb24(pb);
6249 501 entries = avio_rb32(pb);
6250 501 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
6251
6252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if ((uint64_t)entries+sc->tts_count >= UINT_MAX/sizeof(*sc->tts_data))
6253 return AVERROR_INVALIDDATA;
6254
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
6255
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 424 times.
501 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb);
6256
6257 501 int entry_size = !!(flags & MOV_TRUN_SAMPLE_DURATION) * 4
6258 501 + !!(flags & MOV_TRUN_SAMPLE_SIZE) * 4
6259 501 + !!(flags & MOV_TRUN_SAMPLE_FLAGS) * 4
6260 501 + !!(flags & MOV_TRUN_SAMPLE_CTS) * 4;
6261 501 int64_t sample_data_size = avio_size(sc->pb);
6262 501 int64_t max_entries = INT64_MAX;
6263
6264
2/2
✓ Branch 0 taken 500 times.
✓ Branch 1 taken 1 times.
501 if (sample_data_size > 0)
6265 500 max_entries = sample_data_size - sti->nb_index_entries;
6266
2/2
✓ Branch 0 taken 475 times.
✓ Branch 1 taken 26 times.
501 if (entry_size) {
6267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 475 times.
475 int64_t size = sc->pb == pb ? sample_data_size : avio_size(pb);
6268 475 int64_t pos = avio_tell(pb);
6269 475 int64_t left = atom.size - 8 - !!(flags & MOV_TRUN_DATA_OFFSET) * 4
6270 475 - !!(flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) * 4;
6271
6272
3/4
✓ Branch 0 taken 475 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 474 times.
✓ Branch 3 taken 1 times.
475 if (pos >= 0 && size >= pos)
6273 474 left = FFMIN(left, size - pos);
6274 475 max_entries = FFMIN(max_entries, left / entry_size);
6275 }
6276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (entries > max_entries) {
6277 av_log(c->fc, AV_LOG_ERROR, "trun sample count %u exceeds the %"PRId64" "
6278 "samples the input can hold\n", entries, max_entries);
6279 return AVERROR_INVALIDDATA;
6280 }
6281
6282 501 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6283
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (frag_stream_info) {
6284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
6285 dts = frag_stream_info->next_trun_dts - sc->time_offset;
6286
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 498 times.
501 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
6287
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
6288 3 pts = frag_stream_info->first_tfra_pts;
6289 3 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
6290 ", using it for pts\n", pts);
6291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 498 times.
498 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
6292 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
6293 dts = frag_stream_info->first_tfra_pts;
6294 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
6295 ", using it for dts\n", pts);
6296 } else {
6297 498 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
6298 498 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
6299
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 498 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
498 int fallback_tfdt = !c->use_tfdt && !has_sidx && has_tfdt;
6300
4/6
✓ Branch 0 taken 498 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 425 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
498 int fallback_sidx = c->use_tfdt && !has_tfdt && has_sidx;
6301
6302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 498 times.
498 if (fallback_sidx) {
6303 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
6304 }
6305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 498 times.
498 if (fallback_tfdt) {
6306 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
6307 }
6308
6309
4/6
✓ Branch 0 taken 425 times.
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 425 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
498 if (has_tfdt && c->use_tfdt || fallback_tfdt) {
6310 425 dts = frag_stream_info->tfdt_dts - sc->time_offset;
6311 425 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
6312 ", using it for dts\n", dts);
6313
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
73 } else if (has_sidx && !c->use_tfdt || fallback_sidx) {
6314 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
6315 // pts = frag_stream_info->sidx_pts;
6316 dts = frag_stream_info->sidx_pts;
6317 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
6318 ", using it for dts\n", frag_stream_info->sidx_pts);
6319 } else {
6320 73 dts = sc->track_end - sc->time_offset;
6321 73 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
6322 ", using it for dts\n", dts);
6323 }
6324 }
6325 } else {
6326 dts = sc->track_end - sc->time_offset;
6327 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
6328 ", using it for dts\n", dts);
6329 }
6330 501 offset = frag->base_data_offset + data_offset;
6331 501 distance = 0;
6332 501 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
6333
6334 // realloc space for new index entries
6335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
6336 entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
6337 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
6338 }
6339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (entries == 0)
6340 return 0;
6341
6342 501 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
6343 501 new_entries = av_fast_realloc(sti->index_entries,
6344 &sti->index_entries_allocated_size,
6345 requested_size);
6346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!new_entries)
6347 return AVERROR(ENOMEM);
6348 501 sti->index_entries= new_entries;
6349
6350 501 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
6351 501 old_allocated_size = sc->tts_allocated_size;
6352 501 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
6353 requested_size);
6354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!tts_data)
6355 return AVERROR(ENOMEM);
6356 501 sc->tts_data = tts_data;
6357
6358 // In case there were samples without time to sample entries, ensure they get
6359 // zero valued entries. This ensures clips which mix boxes with and
6360 // without time to sample entries don't pickup uninitialized data.
6361 501 memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0,
6362 501 sc->tts_allocated_size - old_allocated_size);
6363
6364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (index_entry_pos < sti->nb_index_entries) {
6365 // Make hole in index_entries and tts_data for new samples
6366 memmove(sti->index_entries + index_entry_pos + entries,
6367 sti->index_entries + index_entry_pos,
6368 sizeof(*sti->index_entries) *
6369 (sti->nb_index_entries - index_entry_pos));
6370 memmove(sc->tts_data + index_entry_pos + entries,
6371 sc->tts_data + index_entry_pos,
6372 sizeof(*sc->tts_data) * (sc->tts_count - index_entry_pos));
6373 if (index_entry_pos < sc->current_sample) {
6374 sc->current_sample += entries;
6375 }
6376 }
6377
6378 501 sti->nb_index_entries += entries;
6379 501 sc->tts_count = sti->nb_index_entries;
6380 501 sc->stts_count = sti->nb_index_entries;
6381
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 115 times.
501 if (flags & MOV_TRUN_SAMPLE_CTS)
6382 386 sc->ctts_count = sti->nb_index_entries;
6383
6384 // Record the index_entry position in frag_index of this fragment
6385
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (frag_stream_info) {
6386 501 frag_stream_info->index_entry = index_entry_pos;
6387
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (frag_stream_info->index_base < 0)
6388 501 frag_stream_info->index_base = index_entry_pos;
6389 }
6390
6391
2/2
✓ Branch 0 taken 473 times.
✓ Branch 1 taken 28 times.
501 if (index_entry_pos > 0)
6392 473 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6393
6394
3/4
✓ Branch 0 taken 8717 times.
✓ Branch 1 taken 501 times.
✓ Branch 2 taken 8717 times.
✗ Branch 3 not taken.
9218 for (i = 0; i < entries && !pb->eof_reached; i++) {
6395 8717 unsigned sample_size = frag->size;
6396
2/2
✓ Branch 0 taken 8216 times.
✓ Branch 1 taken 501 times.
8717 int sample_flags = i ? frag->flags : first_sample_flags;
6397 8717 unsigned sample_duration = frag->duration;
6398 8717 unsigned ctts_duration = 0;
6399 8717 int keyframe = 0;
6400 8717 int index_entry_flags = 0;
6401
6402
2/2
✓ Branch 0 taken 1684 times.
✓ Branch 1 taken 7033 times.
8717 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
6403
2/2
✓ Branch 0 taken 8659 times.
✓ Branch 1 taken 58 times.
8717 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
6404
2/2
✓ Branch 0 taken 981 times.
✓ Branch 1 taken 7736 times.
8717 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
6405
2/2
✓ Branch 0 taken 6576 times.
✓ Branch 1 taken 2141 times.
8717 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
6406
6407
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8716 times.
8717 if (sample_duration > c->max_stts_delta) {
6408 1 av_log(c->fc, AV_LOG_WARNING,
6409 "Too large sample duration %u in trun entry %u in st:%d. Clipping to 1.\n",
6410 sample_duration, i, st->index);
6411 1 sample_duration = 1;
6412 }
6413
6414 8717 mov_update_dts_shift(sc, ctts_duration, c->fc);
6415
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8714 times.
8717 if (pts != AV_NOPTS_VALUE) {
6416 3 dts = pts - sc->dts_shift;
6417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (flags & MOV_TRUN_SAMPLE_CTS) {
6418 dts -= ctts_duration;
6419 } else {
6420 3 dts -= sc->time_offset;
6421 }
6422 3 av_log(c->fc, AV_LOG_DEBUG,
6423 "pts %"PRId64" calculated dts %"PRId64
6424 " sc->dts_shift %d ctts.duration %d"
6425 " sc->time_offset %"PRId64
6426 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
6427 pts, dts,
6428 sc->dts_shift, ctts_duration,
6429 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
6430 3 pts = AV_NOPTS_VALUE;
6431 }
6432
6433 8717 keyframe =
6434 8717 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
6435 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
6436
2/2
✓ Branch 0 taken 648 times.
✓ Branch 1 taken 8069 times.
8717 if (keyframe) {
6437 648 distance = 0;
6438 648 index_entry_flags |= AVINDEX_KEYFRAME;
6439 }
6440 // Fragments can overlap in time. Discard overlapping frames after
6441 // decoding.
6442
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8693 times.
8717 if (prev_dts >= dts)
6443 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
6444
6445 8717 sti->index_entries[index_entry_pos].pos = offset;
6446 8717 sti->index_entries[index_entry_pos].timestamp = dts;
6447 8717 sti->index_entries[index_entry_pos].size = sample_size;
6448 8717 sti->index_entries[index_entry_pos].min_distance = distance;
6449 8717 sti->index_entries[index_entry_pos].flags = index_entry_flags;
6450
6451 8717 sc->tts_data[index_entry_pos].count = 1;
6452 8717 sc->tts_data[index_entry_pos].offset = ctts_duration;
6453 8717 sc->tts_data[index_entry_pos].duration = sample_duration;
6454 8717 index_entry_pos++;
6455
6456 8717 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
6457 "size %u, distance %d, keyframe %d\n", st->index,
6458 index_entry_pos, offset, dts, sample_size, distance, keyframe);
6459 8717 distance++;
6460
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8717 times.
8717 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
6461 return AVERROR_INVALIDDATA;
6462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8717 times.
8717 if (!sample_size)
6463 return AVERROR_INVALIDDATA;
6464 8717 dts += sample_duration;
6465 8717 offset += sample_size;
6466 8717 sc->data_size += sample_size;
6467
6468
1/2
✓ Branch 0 taken 8717 times.
✗ Branch 1 not taken.
8717 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
6469
1/2
✓ Branch 0 taken 8717 times.
✗ Branch 1 not taken.
8717 1 <= INT_MAX - sc->nb_frames_for_fps
6470 ) {
6471 8717 sc->duration_for_fps += sample_duration;
6472 8717 sc->nb_frames_for_fps ++;
6473 }
6474 }
6475
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (frag_stream_info)
6476 501 frag_stream_info->next_trun_dts = dts + sc->time_offset;
6477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (i < entries) {
6478 // EOF found before reading all entries. Fix the hole this would
6479 // leave in index_entries and tts_data
6480 int gap = entries - i;
6481 memmove(sti->index_entries + index_entry_pos,
6482 sti->index_entries + index_entry_pos + gap,
6483 sizeof(*sti->index_entries) *
6484 (sti->nb_index_entries - (index_entry_pos + gap)));
6485 memmove(sc->tts_data + index_entry_pos,
6486 sc->tts_data + index_entry_pos + gap,
6487 sizeof(*sc->tts_data) *
6488 (sc->tts_count - (index_entry_pos + gap)));
6489
6490 sti->nb_index_entries -= gap;
6491 sc->tts_count -= gap;
6492 if (index_entry_pos < sc->current_sample) {
6493 sc->current_sample -= gap;
6494 }
6495 entries = i;
6496 }
6497
6498 // The end of this new fragment may overlap in time with the start
6499 // of the next fragment in index_entries. Mark the samples in the next
6500 // fragment that overlap with AVINDEX_DISCARD_FRAME
6501 501 prev_dts = AV_NOPTS_VALUE;
6502
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (index_entry_pos > 0)
6503 501 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
6505 if (prev_dts < sti->index_entries[i].timestamp)
6506 break;
6507 sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6508 }
6509
6510 // If a hole was created to insert the new index_entries into,
6511 // the index_entry recorded for all subsequent moof must
6512 // be incremented by the number of entries inserted.
6513 501 fix_frag_index_entries(&c->frag_index, next_frag_index,
6514 501 frag->track_id, entries);
6515
6516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (pb->eof_reached) {
6517 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6518 return AVERROR_EOF;
6519 }
6520
6521 501 frag->implicit_offset = offset;
6522
6523 501 sc->track_end = dts + sc->time_offset;
6524
2/2
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 383 times.
501 if (st->duration < sc->track_end)
6525 118 st->duration = sc->track_end;
6526
6527 501 return 0;
6528 }
6529
6530 46 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6531 {
6532 46 int64_t stream_size = avio_size(pb);
6533 46 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6534 uint8_t version, is_complete;
6535 int64_t offadd;
6536 unsigned i, j, track_id, item_count;
6537 46 AVStream *st = NULL;
6538 46 AVStream *ref_st = NULL;
6539 46 MOVStreamContext *sc, *ref_sc = NULL;
6540 AVRational timescale;
6541
6542 46 version = avio_r8(pb);
6543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (version > 1) {
6544 avpriv_request_sample(c->fc, "sidx version %u", version);
6545 return 0;
6546 }
6547
6548 46 avio_rb24(pb); // flags
6549
6550 46 track_id = avio_rb32(pb); // Reference ID
6551
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 for (i = 0; i < c->fc->nb_streams; i++) {
6552 46 sc = c->fc->streams[i]->priv_data;
6553
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 if (sc->id == track_id) {
6554 46 st = c->fc->streams[i];
6555 46 break;
6556 }
6557 }
6558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!st) {
6559 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6560 return 0;
6561 }
6562
6563 46 sc = st->priv_data;
6564
6565 46 timescale = av_make_q(1, avio_rb32(pb));
6566
6567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (timescale.den <= 0) {
6568 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6569 return AVERROR_INVALIDDATA;
6570 }
6571
6572
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1 times.
46 if (version == 0) {
6573 45 pts = avio_rb32(pb);
6574 45 offadd= avio_rb32(pb);
6575 } else {
6576 1 pts = avio_rb64(pb);
6577 1 offadd= avio_rb64(pb);
6578 }
6579
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6580 return AVERROR_INVALIDDATA;
6581
6582 46 offset += (uint64_t)offadd;
6583
6584 46 avio_rb16(pb); // reserved
6585
6586 46 item_count = avio_rb16(pb);
6587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (item_count == 0)
6588 return AVERROR_INVALIDDATA;
6589
6590
2/2
✓ Branch 0 taken 372 times.
✓ Branch 1 taken 46 times.
418 for (i = 0; i < item_count; i++) {
6591 int index;
6592 MOVFragmentStreamInfo * frag_stream_info;
6593 372 uint32_t size = avio_rb32(pb);
6594 372 uint32_t duration = avio_rb32(pb);
6595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
372 if (size & 0x80000000) {
6596 avpriv_request_sample(c->fc, "sidx reference_type 1");
6597 return AVERROR_PATCHWELCOME;
6598 }
6599 372 avio_rb32(pb); // sap_flags
6600 372 timestamp = av_rescale_q(pts, timescale, st->time_base);
6601
6602 372 index = update_frag_index(c, offset);
6603 372 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6604
1/2
✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
372 if (frag_stream_info)
6605 372 frag_stream_info->sidx_pts = timestamp;
6606
6607
1/2
✓ Branch 1 taken 372 times.
✗ Branch 2 not taken.
372 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6608
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 372 times.
372 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6609 )
6610 return AVERROR_INVALIDDATA;
6611 372 offset += size;
6612 372 pts += duration;
6613 }
6614
6615 46 st->duration = sc->track_end = pts;
6616
6617 46 sc->has_sidx = 1;
6618
6619 // See if the remaining bytes are just an mfra which we can ignore.
6620 46 is_complete = offset == stream_size;
6621
5/6
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
46 if (!is_complete && (pb->seekable & AVIO_SEEKABLE_NORMAL) && stream_size > 0 ) {
6622 int64_t ret;
6623 38 int64_t original_pos = avio_tell(pb);
6624
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
38 if (!c->have_read_mfra_size) {
6625
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6626 return ret;
6627 3 c->mfra_size = avio_rb32(pb);
6628 3 c->have_read_mfra_size = 1;
6629
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6630 return ret;
6631 }
6632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (offset == stream_size - c->mfra_size)
6633 is_complete = 1;
6634 }
6635
6636
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 39 times.
46 if (is_complete) {
6637 // Find first entry in fragment index that came from an sidx.
6638 // This will pretty much always be the first entry.
6639
2/2
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 7 times.
378 for (i = 0; i < c->frag_index.nb_items; i++) {
6640 371 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6641
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 364 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
371 for (j = 0; ref_st == NULL && j < item->nb_stream_info; j++) {
6642 MOVFragmentStreamInfo * si;
6643 7 si = &item->stream_info[j];
6644
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (si->sidx_pts != AV_NOPTS_VALUE) {
6645 7 ref_st = c->fc->streams[j];
6646 7 ref_sc = ref_st->priv_data;
6647 7 break;
6648 }
6649 }
6650 }
6651
3/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 7 times.
14 if (ref_st) for (i = 0; i < c->fc->nb_streams; i++) {
6652 7 st = c->fc->streams[i];
6653 7 sc = st->priv_data;
6654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sc->has_sidx) {
6655 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6656 }
6657 }
6658
6659
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (offadd == 0)
6660 7 c->frag_index.complete = 1;
6661 }
6662
6663 46 return 0;
6664 }
6665
6666 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6667 /* like the files created with Adobe Premiere 5.0, for samples see */
6668 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6669 296 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6670 {
6671 int err;
6672
6673
1/2
✓ Branch 0 taken 296 times.
✗ Branch 1 not taken.
296 if (atom.size < 8)
6674 296 return 0; /* continue */
6675 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6676 avio_skip(pb, atom.size - 4);
6677 return 0;
6678 }
6679 atom.type = avio_rl32(pb);
6680 atom.size -= 8;
6681 if (atom.type != MKTAG('m','d','a','t')) {
6682 avio_skip(pb, atom.size);
6683 return 0;
6684 }
6685 err = mov_read_mdat(c, pb, atom);
6686 return err;
6687 }
6688
6689 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6690 {
6691 #if CONFIG_ZLIB
6692 FFIOContext ctx;
6693 uint8_t *cmov_data;
6694 uint8_t *moov_data; /* uncompressed data */
6695 long cmov_len, moov_len;
6696 3 int ret = -1;
6697
6698 3 avio_rb32(pb); /* dcom atom */
6699
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6700 return AVERROR_INVALIDDATA;
6701
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6702 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6703 return AVERROR_INVALIDDATA;
6704 }
6705 3 avio_rb32(pb); /* cmvd atom */
6706
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6707 return AVERROR_INVALIDDATA;
6708 3 moov_len = avio_rb32(pb); /* uncompressed size */
6709 3 cmov_len = atom.size - 6 * 4;
6710
6711 3 cmov_data = av_malloc(cmov_len);
6712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6713 return AVERROR(ENOMEM);
6714 3 moov_data = av_malloc(moov_len);
6715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6716 av_free(cmov_data);
6717 return AVERROR(ENOMEM);
6718 }
6719 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6721 goto free_and_return;
6722
6723 3 ret = AVERROR_INVALIDDATA;
6724
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)
6725 goto free_and_return;
6726 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6727 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6728 3 atom.type = MKTAG('m','o','o','v');
6729 3 atom.size = moov_len;
6730 3 ret = mov_read_default(c, &ctx.pub, atom);
6731 3 free_and_return:
6732 3 av_free(moov_data);
6733 3 av_free(cmov_data);
6734 3 return ret;
6735 #else
6736 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6737 return AVERROR(ENOSYS);
6738 #endif
6739 }
6740
6741 /* edit list atom */
6742 527 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6743 {
6744 MOVStreamContext *sc;
6745 int i, edit_count, version;
6746 int64_t elst_entry_size;
6747
6748
2/4
✓ Branch 0 taken 527 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 527 times.
527 if (c->fc->nb_streams < 1 || c->ignore_editlist)
6749 return 0;
6750 527 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6751
6752 527 version = avio_r8(pb); /* version */
6753 527 avio_rb24(pb); /* flags */
6754 527 edit_count = avio_rb32(pb); /* entries */
6755 527 atom.size -= 8;
6756
6757
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 527 times.
527 elst_entry_size = version == 1 ? 20 : 12;
6758
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 526 times.
527 if (atom.size != edit_count * elst_entry_size) {
6759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6760 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6761 edit_count, atom.size + 8);
6762 return AVERROR_INVALIDDATA;
6763 } else {
6764 1 edit_count = atom.size / elst_entry_size;
6765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6766 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6767 }
6768 }
6769 }
6770
6771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 527 times.
527 if (!edit_count)
6772 return 0;
6773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 527 times.
527 if (sc->elst_data)
6774 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6775 527 av_free(sc->elst_data);
6776 527 sc->elst_count = 0;
6777 527 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 527 times.
527 if (!sc->elst_data)
6779 return AVERROR(ENOMEM);
6780
6781 527 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6782
4/6
✓ Branch 0 taken 556 times.
✓ Branch 1 taken 527 times.
✓ Branch 2 taken 556 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 556 times.
✗ Branch 5 not taken.
1083 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
6783 556 MOVElst *e = &sc->elst_data[i];
6784
6785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 556 times.
556 if (version == 1) {
6786 e->duration = avio_rb64(pb);
6787 e->time = avio_rb64(pb);
6788 atom.size -= 16;
6789 } else {
6790 556 e->duration = avio_rb32(pb); /* segment duration */
6791 556 e->time = (int32_t)avio_rb32(pb); /* media time */
6792 556 atom.size -= 8;
6793 }
6794 556 e->rate = avio_rb32(pb) / 65536.0;
6795 556 atom.size -= 4;
6796 556 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6797 556 e->duration, e->time, e->rate);
6798
6799
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 552 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
556 if (e->time < 0 && e->time != -1 &&
6800 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6801 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6802 c->fc->nb_streams-1, i, e->time);
6803 return AVERROR_INVALIDDATA;
6804 }
6805
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 556 times.
556 if (e->duration < 0) {
6806 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list duration=%"PRId64"\n",
6807 c->fc->nb_streams-1, i, e->duration);
6808 return AVERROR_INVALIDDATA;
6809 }
6810 }
6811 527 sc->elst_count = i;
6812
6813 527 return 0;
6814 }
6815
6816 18 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6817 {
6818 MOVStreamContext *sc;
6819 int err;
6820
6821
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->fc->nb_streams < 1)
6822 return AVERROR_INVALIDDATA;
6823 18 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6824
6825
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size % sizeof(uint32_t))
6826 return AVERROR_INVALIDDATA;
6827
6828 18 MovTref *tag = mov_add_tref_tag(sc, atom.type);
6829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!tag)
6830 return AVERROR(ENOMEM);
6831
6832 18 int nb_timecode_track = atom.size >> 2;
6833
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 18 times.
40 for (int i = 0; i < nb_timecode_track; i++) {
6834
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 if (avio_feof(pb))
6835 return AVERROR_INVALIDDATA;
6836 22 err = mov_add_tref_id(tag, avio_rb32(pb));
6837
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (err < 0)
6838 return err;
6839 }
6840
6841 18 return 0;
6842 }
6843
6844 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6845 {
6846 AVStream *st;
6847 int version, color_range, color_primaries, color_trc, color_space;
6848
6849 if (c->fc->nb_streams < 1)
6850 return 0;
6851 st = c->fc->streams[c->fc->nb_streams - 1];
6852
6853 if (atom.size < 5) {
6854 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6855 return AVERROR_INVALIDDATA;
6856 }
6857
6858 version = avio_r8(pb);
6859 if (version != 1) {
6860 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6861 return 0;
6862 }
6863 avio_skip(pb, 3); /* flags */
6864
6865 avio_skip(pb, 2); /* profile + level */
6866 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6867 color_primaries = avio_r8(pb);
6868 color_trc = avio_r8(pb);
6869 color_space = avio_r8(pb);
6870 if (avio_rb16(pb)) /* codecIntializationDataSize */
6871 return AVERROR_INVALIDDATA;
6872
6873 if (!av_color_primaries_name(color_primaries))
6874 color_primaries = AVCOL_PRI_UNSPECIFIED;
6875 if (!av_color_transfer_name(color_trc))
6876 color_trc = AVCOL_TRC_UNSPECIFIED;
6877 if (!av_color_space_name(color_space))
6878 color_space = AVCOL_SPC_UNSPECIFIED;
6879
6880 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6881 st->codecpar->color_primaries = color_primaries;
6882 st->codecpar->color_trc = color_trc;
6883 st->codecpar->color_space = color_space;
6884
6885 return 0;
6886 }
6887
6888 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6889 {
6890 MOVStreamContext *sc;
6891 int i, version;
6892
6893 if (c->fc->nb_streams < 1)
6894 return AVERROR_INVALIDDATA;
6895
6896 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6897
6898 if (atom.size < 5) {
6899 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6900 return AVERROR_INVALIDDATA;
6901 }
6902
6903 version = avio_r8(pb);
6904 if (version) {
6905 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6906 return 0;
6907 }
6908 if (sc->mastering) {
6909 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6910 return 0;
6911 }
6912
6913 avio_skip(pb, 3); /* flags */
6914
6915 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6916 if (!sc->mastering)
6917 return AVERROR(ENOMEM);
6918
6919 for (i = 0; i < 3; i++) {
6920 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6921 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6922 }
6923 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6924 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6925
6926 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6927 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6928
6929 sc->mastering->has_primaries = 1;
6930 sc->mastering->has_luminance = 1;
6931
6932 return 0;
6933 }
6934
6935 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6936 {
6937 MOVStreamContext *sc;
6938 const int mapping[3] = {1, 2, 0};
6939 const int chroma_den = 50000;
6940 const int luma_den = 10000;
6941 int i;
6942
6943 if (c->fc->nb_streams < 1)
6944 return AVERROR_INVALIDDATA;
6945
6946 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6947
6948 if (atom.size < 24) {
6949 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6950 return AVERROR_INVALIDDATA;
6951 }
6952
6953 if (sc->mastering) {
6954 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6955 return 0;
6956 }
6957
6958 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6959 if (!sc->mastering)
6960 return AVERROR(ENOMEM);
6961
6962 for (i = 0; i < 3; i++) {
6963 const int j = mapping[i];
6964 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6965 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6966 }
6967 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6968 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6969
6970 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6971 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6972
6973 sc->mastering->has_luminance = 1;
6974 sc->mastering->has_primaries = 1;
6975
6976 return 0;
6977 }
6978
6979 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6980 {
6981 MOVStreamContext *sc;
6982 int version;
6983
6984 if (c->fc->nb_streams < 1)
6985 return AVERROR_INVALIDDATA;
6986
6987 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6988
6989 if (atom.size < 5) {
6990 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
6991 return AVERROR_INVALIDDATA;
6992 }
6993
6994 version = avio_r8(pb);
6995 if (version) {
6996 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
6997 return 0;
6998 }
6999 avio_skip(pb, 3); /* flags */
7000
7001 if (sc->coll){
7002 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
7003 return 0;
7004 }
7005
7006 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
7007 if (!sc->coll)
7008 return AVERROR(ENOMEM);
7009
7010 sc->coll->MaxCLL = avio_rb16(pb);
7011 sc->coll->MaxFALL = avio_rb16(pb);
7012
7013 return 0;
7014 }
7015
7016 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7017 {
7018 MOVStreamContext *sc;
7019
7020 if (c->fc->nb_streams < 1)
7021 return AVERROR_INVALIDDATA;
7022
7023 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7024
7025 if (atom.size < 4) {
7026 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
7027 return AVERROR_INVALIDDATA;
7028 }
7029
7030 if (sc->coll){
7031 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
7032 return 0;
7033 }
7034
7035 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
7036 if (!sc->coll)
7037 return AVERROR(ENOMEM);
7038
7039 sc->coll->MaxCLL = avio_rb16(pb);
7040 sc->coll->MaxFALL = avio_rb16(pb);
7041
7042 return 0;
7043 }
7044
7045 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7046 {
7047 MOVStreamContext *sc;
7048 4 const int illuminance_den = 10000;
7049 4 const int ambient_den = 50000;
7050
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
7051 return AVERROR_INVALIDDATA;
7052 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
7054 av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
7055 return AVERROR_INVALIDDATA;
7056 }
7057
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
7058 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
7059 return 0;
7060 }
7061 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
7062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
7063 return AVERROR(ENOMEM);
7064 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
7065 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
7066 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
7067 4 return 0;
7068 }
7069
7070 3 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7071 {
7072 AVStream *st;
7073 MOVStreamContext *sc;
7074 enum AVStereo3DType type;
7075 int mode;
7076
7077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7078 return 0;
7079
7080 3 st = c->fc->streams[c->fc->nb_streams - 1];
7081 3 sc = st->priv_data;
7082
7083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 5) {
7084 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
7085 return AVERROR_INVALIDDATA;
7086 }
7087
7088
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->stereo3d)
7089 return AVERROR_INVALIDDATA;
7090
7091 3 avio_skip(pb, 4); /* version + flags */
7092
7093 3 mode = avio_r8(pb);
7094
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
3 switch (mode) {
7095 1 case 0:
7096 1 type = AV_STEREO3D_2D;
7097 1 break;
7098 case 1:
7099 type = AV_STEREO3D_TOPBOTTOM;
7100 break;
7101 2 case 2:
7102 2 type = AV_STEREO3D_SIDEBYSIDE;
7103 2 break;
7104 default:
7105 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
7106 return 0;
7107 }
7108
7109 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7111 return AVERROR(ENOMEM);
7112
7113 3 sc->stereo3d->type = type;
7114 3 return 0;
7115 }
7116
7117 static int mov_read_pack(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7118 {
7119 AVStream *st;
7120 MOVStreamContext *sc;
7121 int size = 0;
7122 int64_t remaining;
7123 uint32_t tag = 0;
7124 enum AVStereo3DType type = AV_STEREO3D_2D;
7125
7126 if (c->fc->nb_streams < 1)
7127 return 0;
7128
7129 st = c->fc->streams[c->fc->nb_streams - 1];
7130 sc = st->priv_data;
7131
7132 remaining = atom.size;
7133 while (remaining > 0) {
7134 size = avio_rb32(pb);
7135 if (size < 8 || size > remaining ) {
7136 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in pack box\n");
7137 return AVERROR_INVALIDDATA;
7138 }
7139
7140 tag = avio_rl32(pb);
7141 switch (tag) {
7142 case MKTAG('p','k','i','n'): {
7143 if (size != 16) {
7144 av_log(c->fc, AV_LOG_ERROR, "Invalid size of pkin box: %d\n", size);
7145 return AVERROR_INVALIDDATA;
7146 }
7147 avio_skip(pb, 1); // version
7148 avio_skip(pb, 3); // flags
7149
7150 tag = avio_rl32(pb);
7151 switch (tag) {
7152 case MKTAG('s','i','d','e'):
7153 type = AV_STEREO3D_SIDEBYSIDE;
7154 break;
7155 case MKTAG('o','v','e','r'):
7156 type = AV_STEREO3D_TOPBOTTOM;
7157 break;
7158 case 0:
7159 // This means value will be set in another layer
7160 break;
7161 default:
7162 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pkin: %s\n",
7163 av_fourcc2str(tag));
7164 avio_skip(pb, size - 8);
7165 break;
7166 }
7167
7168 break;
7169 }
7170 default:
7171 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pack: %s\n",
7172 av_fourcc2str(tag));
7173 avio_skip(pb, size - 8);
7174 break;
7175 }
7176 remaining -= size;
7177 }
7178
7179 if (remaining != 0) {
7180 av_log(c->fc, AV_LOG_ERROR, "Broken pack box\n");
7181 return AVERROR_INVALIDDATA;
7182 }
7183
7184 if (type == AV_STEREO3D_2D)
7185 return 0;
7186
7187 if (!sc->stereo3d) {
7188 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7189 if (!sc->stereo3d)
7190 return AVERROR(ENOMEM);
7191 }
7192
7193 sc->stereo3d->type = type;
7194
7195 return 0;
7196 }
7197
7198 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7199 {
7200 AVStream *st;
7201 MOVStreamContext *sc;
7202 int size, version, layout;
7203 int32_t yaw, pitch, roll;
7204 1 uint32_t l = 0, t = 0, r = 0, b = 0;
7205 1 uint32_t tag, padding = 0;
7206 enum AVSphericalProjection projection;
7207
7208
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
7209 return 0;
7210
7211 1 st = c->fc->streams[c->fc->nb_streams - 1];
7212 1 sc = st->priv_data;
7213
7214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
7215 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
7216 return AVERROR_INVALIDDATA;
7217 }
7218
7219 1 size = avio_rb32(pb);
7220
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)
7221 return AVERROR_INVALIDDATA;
7222
7223 1 tag = avio_rl32(pb);
7224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
7225 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
7226 return 0;
7227 }
7228 1 version = avio_r8(pb);
7229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7230 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7231 version);
7232 return 0;
7233 }
7234 1 avio_skip(pb, 3); /* flags */
7235 1 avio_skip(pb, size - 12); /* metadata_source */
7236
7237 1 size = avio_rb32(pb);
7238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7239 return AVERROR_INVALIDDATA;
7240
7241 1 tag = avio_rl32(pb);
7242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
7243 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
7244 return 0;
7245 }
7246
7247 1 size = avio_rb32(pb);
7248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7249 return AVERROR_INVALIDDATA;
7250
7251 1 tag = avio_rl32(pb);
7252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
7253 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
7254 return 0;
7255 }
7256 1 version = avio_r8(pb);
7257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7258 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7259 version);
7260 return 0;
7261 }
7262 1 avio_skip(pb, 3); /* flags */
7263
7264 /* 16.16 fixed point */
7265 1 yaw = avio_rb32(pb);
7266 1 pitch = avio_rb32(pb);
7267 1 roll = avio_rb32(pb);
7268
7269 1 size = avio_rb32(pb);
7270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7271 return AVERROR_INVALIDDATA;
7272
7273 1 tag = avio_rl32(pb);
7274 1 version = avio_r8(pb);
7275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7276 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7277 version);
7278 return 0;
7279 }
7280 1 avio_skip(pb, 3); /* flags */
7281
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
7282 case MKTAG('c','b','m','p'):
7283 layout = avio_rb32(pb);
7284 if (layout) {
7285 av_log(c->fc, AV_LOG_WARNING,
7286 "Unsupported cubemap layout %d\n", layout);
7287 return 0;
7288 }
7289 projection = AV_SPHERICAL_CUBEMAP;
7290 padding = avio_rb32(pb);
7291 break;
7292 1 case MKTAG('e','q','u','i'):
7293 1 t = avio_rb32(pb);
7294 1 b = avio_rb32(pb);
7295 1 l = avio_rb32(pb);
7296 1 r = avio_rb32(pb);
7297
7298
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) {
7299 av_log(c->fc, AV_LOG_ERROR,
7300 "Invalid bounding rectangle coordinates "
7301 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
7302 return AVERROR_INVALIDDATA;
7303 }
7304
7305
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)
7306 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
7307 else
7308 projection = AV_SPHERICAL_EQUIRECTANGULAR;
7309 1 break;
7310 default:
7311 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
7312 return 0;
7313 }
7314
7315 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
7317 return AVERROR(ENOMEM);
7318
7319 1 sc->spherical->projection = projection;
7320
7321 1 sc->spherical->yaw = yaw;
7322 1 sc->spherical->pitch = pitch;
7323 1 sc->spherical->roll = roll;
7324
7325 1 sc->spherical->padding = padding;
7326
7327 1 sc->spherical->bound_left = l;
7328 1 sc->spherical->bound_top = t;
7329 1 sc->spherical->bound_right = r;
7330 1 sc->spherical->bound_bottom = b;
7331
7332 1 return 0;
7333 }
7334
7335 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7336 {
7337 AVStream *st;
7338 MOVStreamContext *sc;
7339 int size;
7340 uint32_t tag;
7341 enum AVSphericalProjection projection;
7342
7343
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7344 return 0;
7345
7346 3 st = c->fc->streams[c->fc->nb_streams - 1];
7347 3 sc = st->priv_data;
7348
7349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 16) {
7350 av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
7351 return AVERROR_INVALIDDATA;
7352 }
7353
7354 3 size = avio_rb32(pb);
7355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size < 16) {
7356 av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
7357 return AVERROR_INVALIDDATA;
7358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (size > 16) {
7359 av_log(c->fc, AV_LOG_WARNING, "Box has more bytes (%d) than prji box required (16) \n", size);
7360 }
7361
7362 3 tag = avio_rl32(pb);
7363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
7364 av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: %s\n",
7365 av_fourcc2str(tag));
7366 return AVERROR_INVALIDDATA;
7367 }
7368
7369 // version and flags, only support (0, 0)
7370 3 unsigned n = avio_rl32(pb);
7371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (n != 0) {
7372 av_log(c->fc, AV_LOG_ERROR, "prji version %u, flag %u are not supported\n",
7373 n & 0xFF, n >> 8);
7374 return AVERROR_PATCHWELCOME;
7375 }
7376
7377 3 tag = avio_rl32(pb);
7378
1/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3 switch (tag) {
7379 3 case MKTAG('r','e','c','t'):
7380 3 projection = AV_SPHERICAL_RECTILINEAR;
7381 3 break;
7382 case MKTAG('e','q','u','i'):
7383 projection = AV_SPHERICAL_EQUIRECTANGULAR;
7384 break;
7385 case MKTAG('h','e','q','u'):
7386 projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
7387 break;
7388 case MKTAG('f','i','s','h'):
7389 projection = AV_SPHERICAL_FISHEYE;
7390 break;
7391 case MKTAG('p','r','i','m'):
7392 projection = AV_SPHERICAL_PARAMETRIC_IMMERSIVE;
7393 break;
7394 default:
7395 av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: %s\n", av_fourcc2str(tag));
7396 return AVERROR_INVALIDDATA;
7397 }
7398
7399 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
7401 return AVERROR(ENOMEM);
7402
7403 3 sc->spherical->projection = projection;
7404
7405 3 return 0;
7406 }
7407
7408 5 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7409 {
7410 AVStream *st;
7411 MOVStreamContext *sc;
7412 5 int size, flags = 0;
7413 int64_t remaining;
7414 5 uint32_t tag, baseline = 0;
7415 5 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
7416 5 enum AVStereo3DType type = AV_STEREO3D_2D;
7417 5 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
7418 5 AVRational horizontal_disparity_adjustment = { 0, 1 };
7419
7420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
7421 return 0;
7422
7423 5 st = c->fc->streams[c->fc->nb_streams - 1];
7424 5 sc = st->priv_data;
7425
7426 5 remaining = atom.size;
7427
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 while (remaining > 0) {
7428 11 size = avio_rb32(pb);
7429
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if (size < 8 || size > remaining ) {
7430 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
7431 return AVERROR_INVALIDDATA;
7432 }
7433
7434 11 tag = avio_rl32(pb);
7435
3/5
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
11 switch (tag) {
7436 5 case MKTAG('s','t','r','i'): {
7437 int has_right, has_left;
7438 uint8_t tmp;
7439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (size != 13) {
7440 av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
7441 return AVERROR_INVALIDDATA;
7442 }
7443 5 avio_skip(pb, 1); // version
7444 5 avio_skip(pb, 3); // flags
7445
7446 5 tmp = avio_r8(pb);
7447
7448 // eye_views_reversed
7449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (tmp & 8) {
7450 flags |= AV_STEREO3D_FLAG_INVERT;
7451 }
7452 // has_additional_views
7453 5 if (tmp & 4) {
7454 // skip...
7455 }
7456
7457 5 has_right = tmp & 2; // has_right_eye_view
7458 5 has_left = tmp & 1; // has_left_eye_view
7459
7460
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 if (has_left && has_right)
7461 5 view = AV_STEREO3D_VIEW_PACKED;
7462 else if (has_left)
7463 view = AV_STEREO3D_VIEW_LEFT;
7464 else if (has_right)
7465 view = AV_STEREO3D_VIEW_RIGHT;
7466
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 if (has_left || has_right)
7467 5 type = AV_STEREO3D_UNSPEC;
7468
7469 5 break;
7470 }
7471 case MKTAG('h','e','r','o'): {
7472 int tmp;
7473 if (size != 13) {
7474 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
7475 return AVERROR_INVALIDDATA;
7476 }
7477 avio_skip(pb, 1); // version
7478 avio_skip(pb, 3); // flags
7479
7480 tmp = avio_r8(pb);
7481 if (tmp == 0)
7482 primary_eye = AV_PRIMARY_EYE_NONE;
7483 else if (tmp == 1)
7484 primary_eye = AV_PRIMARY_EYE_LEFT;
7485 else if (tmp == 2)
7486 primary_eye = AV_PRIMARY_EYE_RIGHT;
7487 else
7488 av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
7489
7490 break;
7491 }
7492 3 case MKTAG('c','a','m','s'): {
7493 uint32_t subtag;
7494 int subsize;
7495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7496 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
7497 return AVERROR_INVALIDDATA;
7498 }
7499
7500 3 subsize = avio_rb32(pb);
7501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7502 av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
7503 return AVERROR_INVALIDDATA;
7504 }
7505
7506 3 subtag = avio_rl32(pb);
7507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
7508 av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got %s\n",
7509 av_fourcc2str(subtag));
7510 return AVERROR_INVALIDDATA;
7511 }
7512
7513 3 avio_skip(pb, 1); // version
7514 3 avio_skip(pb, 3); // flags
7515
7516 3 baseline = avio_rb32(pb);
7517
7518 3 break;
7519 }
7520 3 case MKTAG('c','m','f','y'): {
7521 uint32_t subtag;
7522 int subsize;
7523 int32_t adjustment;
7524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7525 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
7526 return AVERROR_INVALIDDATA;
7527 }
7528
7529 3 subsize = avio_rb32(pb);
7530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7531 av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
7532 return AVERROR_INVALIDDATA;
7533 }
7534
7535 3 subtag = avio_rl32(pb);
7536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
7537 av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got %s\n",
7538 av_fourcc2str(subtag));
7539 return AVERROR_INVALIDDATA;
7540 }
7541
7542 3 avio_skip(pb, 1); // version
7543 3 avio_skip(pb, 3); // flags
7544
7545 3 adjustment = (int32_t) avio_rb32(pb);
7546
7547 3 horizontal_disparity_adjustment.num = (int) adjustment;
7548 3 horizontal_disparity_adjustment.den = 10000;
7549
7550 3 break;
7551 }
7552 default:
7553 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: %s\n",
7554 av_fourcc2str(tag));
7555 avio_skip(pb, size - 8);
7556 break;
7557 }
7558 11 remaining -= size;
7559 }
7560
7561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (remaining != 0) {
7562 av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
7563 return AVERROR_INVALIDDATA;
7564 }
7565
7566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (type == AV_STEREO3D_2D)
7567 return 0;
7568
7569
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (!sc->stereo3d) {
7570 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7572 return AVERROR(ENOMEM);
7573 }
7574
7575 5 sc->stereo3d->flags = flags;
7576 /* eyes/stri only records packed vs single-eye, not SBS/TB. Keep a more
7577 * specific type already set by st3d. */
7578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (type != AV_STEREO3D_UNSPEC)
7579 sc->stereo3d->type = type;
7580
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 else if (sc->stereo3d->type == AV_STEREO3D_2D)
7581 3 sc->stereo3d->type = type;
7582 5 sc->stereo3d->view = view;
7583 5 sc->stereo3d->primary_eye = primary_eye;
7584 5 sc->stereo3d->baseline = baseline;
7585 5 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
7586
7587 5 return 0;
7588 }
7589
7590 5 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7591 {
7592 int size;
7593 int64_t remaining;
7594 uint32_t tag;
7595
7596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
7597 return 0;
7598
7599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (atom.size < 8) {
7600 av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
7601 return AVERROR_INVALIDDATA;
7602 }
7603
7604 5 remaining = atom.size;
7605
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5 times.
13 while (remaining > 0) {
7606 8 size = avio_rb32(pb);
7607
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (size < 8 || size > remaining ) {
7608 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
7609 return AVERROR_INVALIDDATA;
7610 }
7611
7612 8 tag = avio_rl32(pb);
7613
2/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 switch (tag) {
7614 3 case MKTAG('p','r','o','j'): {
7615 3 MOVAtom proj = { tag, size - 8 };
7616 3 int ret = mov_read_vexu_proj(c, pb, proj);
7617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7618 return ret;
7619 3 break;
7620 }
7621 5 case MKTAG('e','y','e','s'): {
7622 5 MOVAtom eyes = { tag, size - 8 };
7623 5 int ret = mov_read_eyes(c, pb, eyes);
7624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
7625 return ret;
7626 5 break;
7627 }
7628 case MKTAG('p','a','c','k'): {
7629 MOVAtom pack = { tag, size - 8 };
7630 int ret = mov_read_pack(c, pb, pack);
7631 if (ret < 0)
7632 return ret;
7633 break;
7634 }
7635 default:
7636 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: %s\n",
7637 av_fourcc2str(tag));
7638 avio_skip(pb, size - 8);
7639 break;
7640 }
7641 8 remaining -= size;
7642 }
7643
7644
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (remaining != 0) {
7645 av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7646 return AVERROR_INVALIDDATA;
7647 }
7648
7649 5 return 0;
7650 }
7651
7652 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7653 {
7654 AVStream *st;
7655 MOVStreamContext *sc;
7656
7657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7658 return 0;
7659
7660 3 st = c->fc->streams[c->fc->nb_streams - 1];
7661 3 sc = st->priv_data;
7662
7663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7664 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7665 return AVERROR_INVALIDDATA;
7666 }
7667
7668
7669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7670 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7671 if (!sc->stereo3d)
7672 return AVERROR(ENOMEM);
7673 }
7674
7675 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7676 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7677
7678 3 return 0;
7679 }
7680
7681 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7682 {
7683 int ret = 0;
7684 uint8_t *buffer = av_malloc(len + 1);
7685 const char *val;
7686
7687 if (!buffer)
7688 return AVERROR(ENOMEM);
7689 buffer[len] = '\0';
7690
7691 ret = ffio_read_size(pb, buffer, len);
7692 if (ret < 0)
7693 goto out;
7694
7695 /* Check for mandatory keys and values, try to support XML as best-effort */
7696 if (!sc->spherical &&
7697 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7698 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7699 av_stristr(val, "true") &&
7700 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7701 av_stristr(val, "true") &&
7702 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7703 av_stristr(val, "equirectangular")) {
7704 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7705 if (!sc->spherical)
7706 goto out;
7707
7708 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7709
7710 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7711 enum AVStereo3DType mode;
7712
7713 if (av_stristr(buffer, "left-right"))
7714 mode = AV_STEREO3D_SIDEBYSIDE;
7715 else if (av_stristr(buffer, "top-bottom"))
7716 mode = AV_STEREO3D_TOPBOTTOM;
7717 else
7718 mode = AV_STEREO3D_2D;
7719
7720 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7721 if (!sc->stereo3d)
7722 goto out;
7723
7724 sc->stereo3d->type = mode;
7725 }
7726
7727 /* orientation */
7728 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7729 if (val)
7730 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7731 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7732 if (val)
7733 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7734 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7735 if (val)
7736 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7737 }
7738
7739 out:
7740 av_free(buffer);
7741 return ret;
7742 }
7743
7744 69 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7745 {
7746 AVStream *st;
7747 MOVStreamContext *sc;
7748 int64_t ret;
7749 AVUUID uuid;
7750 static const AVUUID uuid_isml_manifest = {
7751 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7752 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7753 };
7754 static const AVUUID uuid_xmp = {
7755 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7756 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7757 };
7758 static const AVUUID uuid_spherical = {
7759 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7760 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7761 };
7762
7763
2/4
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
69 if (atom.size < AV_UUID_LEN || atom.size >= FFMIN(INT_MAX, SIZE_MAX))
7764 return AVERROR_INVALIDDATA;
7765
7766
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 66 times.
69 if (c->fc->nb_streams < 1)
7767 3 return 0;
7768 66 st = c->fc->streams[c->fc->nb_streams - 1];
7769 66 sc = st->priv_data;
7770
7771 66 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
7773 return ret;
7774
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7775 uint8_t *buffer, *ptr;
7776 char *endptr;
7777 size_t len = atom.size - AV_UUID_LEN;
7778
7779 if (len < 4) {
7780 return AVERROR_INVALIDDATA;
7781 }
7782 ret = avio_skip(pb, 4); // zeroes
7783 len -= 4;
7784
7785 buffer = av_mallocz(len + 1);
7786 if (!buffer) {
7787 return AVERROR(ENOMEM);
7788 }
7789 ret = ffio_read_size(pb, buffer, len);
7790 if (ret < 0) {
7791 av_free(buffer);
7792 return ret;
7793 }
7794
7795 ptr = buffer;
7796 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7797 ptr += sizeof("systemBitrate=\"") - 1;
7798 c->bitrates_count++;
7799 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7800 if (!c->bitrates) {
7801 c->bitrates_count = 0;
7802 av_free(buffer);
7803 return AVERROR(ENOMEM);
7804 }
7805 errno = 0;
7806 ret = strtol(ptr, &endptr, 10);
7807 if (ret < 0 || errno || *endptr != '"') {
7808 c->bitrates[c->bitrates_count - 1] = 0;
7809 } else {
7810 c->bitrates[c->bitrates_count - 1] = ret;
7811 }
7812 }
7813
7814 av_free(buffer);
7815
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7816 uint8_t *buffer;
7817 size_t len = atom.size - AV_UUID_LEN;
7818 if (c->export_xmp) {
7819 buffer = av_mallocz(len + 1);
7820 if (!buffer) {
7821 return AVERROR(ENOMEM);
7822 }
7823 ret = ffio_read_size(pb, buffer, len);
7824 if (ret < 0) {
7825 av_free(buffer);
7826 return ret;
7827 }
7828 buffer[len] = '\0';
7829 av_dict_set(&c->fc->metadata, "xmp",
7830 buffer, AV_DICT_DONT_STRDUP_VAL);
7831 } else {
7832 // skip all uuid atom, which makes it fast for long uuid-xmp file
7833 ret = avio_skip(pb, len);
7834 if (ret < 0)
7835 return ret;
7836 }
7837
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7838 size_t len = atom.size - AV_UUID_LEN;
7839 ret = mov_parse_uuid_spherical(sc, pb, len);
7840 if (ret < 0)
7841 return ret;
7842 if (!sc->spherical)
7843 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7844 }
7845
7846 66 return 0;
7847 }
7848
7849 255 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7850 {
7851 int ret;
7852 uint8_t content[16];
7853
7854
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 115 times.
255 if (atom.size < 8)
7855 140 return 0;
7856
7857 115 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 115 times.
115 if (ret < 0)
7859 return ret;
7860
7861
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 70 times.
115 if ( !c->found_moov
7862
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 23 times.
45 && !c->found_mdat
7863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 && !memcmp(content, "Anevia\x1A\x1A", 8)
7864 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7865 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7866 }
7867
7868 115 return 0;
7869 }
7870
7871 42 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7872 {
7873 42 uint32_t format = avio_rl32(pb);
7874 MOVStreamContext *sc;
7875 enum AVCodecID id;
7876 AVStream *st;
7877
7878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (c->fc->nb_streams < 1)
7879 return 0;
7880 42 st = c->fc->streams[c->fc->nb_streams - 1];
7881 42 sc = st->priv_data;
7882
7883
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 31 times.
42 switch (sc->format)
7884 {
7885 11 case MKTAG('e','n','c','v'): // encrypted video
7886 case MKTAG('e','n','c','a'): // encrypted audio
7887 11 id = mov_codec_id(st, format);
7888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7889 st->codecpar->codec_id != id) {
7890 av_log(c->fc, AV_LOG_WARNING,
7891 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7892 (char*)&format, st->codecpar->codec_id);
7893 break;
7894 }
7895
7896 11 st->codecpar->codec_id = id;
7897 11 sc->format = format;
7898 11 break;
7899
7900 31 default:
7901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (format != sc->format) {
7902 av_log(c->fc, AV_LOG_WARNING,
7903 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7904 (char*)&format, (char*)&sc->format);
7905 }
7906 31 break;
7907 }
7908
7909 42 return 0;
7910 }
7911
7912 /**
7913 * Gets the current encryption info and associated current stream context. If
7914 * we are parsing a track fragment, this will return the specific encryption
7915 * info for this fragment; otherwise this will return the global encryption
7916 * info for the current stream.
7917 */
7918 27 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7919 {
7920 MOVFragmentStreamInfo *frag_stream_info;
7921 AVStream *st;
7922 int i;
7923
7924 27 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7925
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 21 times.
27 if (frag_stream_info) {
7926
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 for (i = 0; i < c->fc->nb_streams; i++) {
7927 6 *sc = c->fc->streams[i]->priv_data;
7928
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if ((*sc)->id == frag_stream_info->id) {
7929 6 st = c->fc->streams[i];
7930 6 break;
7931 }
7932 }
7933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (i == c->fc->nb_streams)
7934 return 0;
7935 6 *sc = st->priv_data;
7936
7937
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (!frag_stream_info->encryption_index) {
7938 // If this stream isn't encrypted, don't create the index.
7939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(*sc)->cenc.default_encrypted_sample)
7940 return 0;
7941 2 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!frag_stream_info->encryption_index)
7943 return AVERROR(ENOMEM);
7944 }
7945 6 *encryption_index = frag_stream_info->encryption_index;
7946 6 return 1;
7947 } else {
7948 // No current track fragment, using stream level encryption info.
7949
7950
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (c->fc->nb_streams < 1)
7951 return 0;
7952 21 st = c->fc->streams[c->fc->nb_streams - 1];
7953 21 *sc = st->priv_data;
7954
7955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!(*sc)->cenc.encryption_index) {
7956 // If this stream isn't encrypted, don't create the index.
7957 if (!(*sc)->cenc.default_encrypted_sample)
7958 return 0;
7959 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7960 if (!(*sc)->cenc.encryption_index)
7961 return AVERROR(ENOMEM);
7962 }
7963
7964 21 *encryption_index = (*sc)->cenc.encryption_index;
7965 21 return 1;
7966 }
7967 }
7968
7969 195 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7970 {
7971 int i, ret;
7972 unsigned int subsample_count;
7973 AVSubsampleEncryptionInfo *subsamples;
7974
7975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!sc->cenc.default_encrypted_sample) {
7976 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7977 return AVERROR_INVALIDDATA;
7978 }
7979
7980
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
195 if (sc->cenc.per_sample_iv_size || use_subsamples) {
7981 195 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7982
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*sample)
7983 return AVERROR(ENOMEM);
7984 } else
7985 *sample = NULL;
7986
7987
1/2
✓ Branch 0 taken 195 times.
✗ Branch 1 not taken.
195 if (sc->cenc.per_sample_iv_size != 0) {
7988
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 195 times.
195 if ((ret = ffio_read_size(pb, (*sample)->iv, sc->cenc.per_sample_iv_size)) < 0) {
7989 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
7990 av_encryption_info_free(*sample);
7991 *sample = NULL;
7992 return ret;
7993 }
7994 }
7995
7996
1/2
✓ Branch 0 taken 195 times.
✗ Branch 1 not taken.
195 if (use_subsamples) {
7997 195 subsample_count = avio_rb16(pb);
7998 195 av_free((*sample)->subsamples);
7999 195 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
8000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!(*sample)->subsamples) {
8001 av_encryption_info_free(*sample);
8002 *sample = NULL;
8003 return AVERROR(ENOMEM);
8004 }
8005
8006
3/4
✓ Branch 0 taken 272 times.
✓ Branch 1 taken 195 times.
✓ Branch 2 taken 272 times.
✗ Branch 3 not taken.
467 for (i = 0; i < subsample_count && !pb->eof_reached; i++) {
8007 272 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
8008 272 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
8009 }
8010
8011
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (pb->eof_reached) {
8012 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
8013 av_encryption_info_free(*sample);
8014 *sample = NULL;
8015 return AVERROR_INVALIDDATA;
8016 }
8017 195 (*sample)->subsample_count = subsample_count;
8018 }
8019
8020 195 return 0;
8021 }
8022
8023 9 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8024 {
8025 AVEncryptionInfo **encrypted_samples;
8026 MOVEncryptionIndex *encryption_index;
8027 MOVStreamContext *sc;
8028 int use_subsamples, ret;
8029 9 unsigned int sample_count, i, alloc_size = 0;
8030
8031 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8032
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8033 return ret;
8034
8035
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (encryption_index->nb_encrypted_samples) {
8036 // This can happen if we have both saio/saiz and senc atoms.
8037 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
8038 2 return 0;
8039 }
8040
8041 7 avio_r8(pb); /* version */
8042 7 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
8043
8044 7 sample_count = avio_rb32(pb);
8045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
8046 return AVERROR(ENOMEM);
8047
8048
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 7 times.
154 for (i = 0; i < sample_count; i++) {
8049 147 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
8050 147 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
8051 min_samples * sizeof(*encrypted_samples));
8052
1/2
✓ Branch 0 taken 147 times.
✗ Branch 1 not taken.
147 if (encrypted_samples) {
8053 147 encryption_index->encrypted_samples = encrypted_samples;
8054
8055 147 ret = mov_read_sample_encryption_info(
8056 147 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
8057 } else {
8058 ret = AVERROR(ENOMEM);
8059 }
8060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
147 if (pb->eof_reached) {
8061 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
8062 if (ret >= 0)
8063 av_encryption_info_free(encryption_index->encrypted_samples[i]);
8064 ret = AVERROR_INVALIDDATA;
8065 }
8066
8067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
147 if (ret < 0) {
8068 for (; i > 0; i--)
8069 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
8070 av_freep(&encryption_index->encrypted_samples);
8071 return ret;
8072 }
8073 }
8074 7 encryption_index->nb_encrypted_samples = sample_count;
8075
8076 7 return 0;
8077 }
8078
8079 2 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
8080 {
8081 AVEncryptionInfo **sample, **encrypted_samples;
8082 int64_t prev_pos;
8083 size_t sample_count, sample_info_size, i;
8084 2 int ret = 0;
8085 2 unsigned int alloc_size = 0;
8086
8087
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->nb_encrypted_samples)
8088 return 0;
8089 2 sample_count = encryption_index->auxiliary_info_sample_count;
8090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count != 1) {
8091 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
8092 return AVERROR_PATCHWELCOME;
8093 }
8094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
8095 return AVERROR(ENOMEM);
8096
8097 2 prev_pos = avio_tell(pb);
8098
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
8099
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 avio_seek(pb, encryption_index->auxiliary_offsets[0], SEEK_SET) != encryption_index->auxiliary_offsets[0]) {
8100 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
8101 goto finish;
8102 }
8103
8104
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
50 for (i = 0; i < sample_count && !pb->eof_reached; i++) {
8105 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
8106 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
8107 min_samples * sizeof(*encrypted_samples));
8108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (!encrypted_samples) {
8109 ret = AVERROR(ENOMEM);
8110 goto finish;
8111 }
8112 48 encryption_index->encrypted_samples = encrypted_samples;
8113
8114 48 sample = &encryption_index->encrypted_samples[i];
8115 96 sample_info_size = encryption_index->auxiliary_info_default_size
8116 48 ? encryption_index->auxiliary_info_default_size
8117
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 : encryption_index->auxiliary_info_sizes[i];
8118
8119 48 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
8120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0)
8121 goto finish;
8122 }
8123
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
8124 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
8125 ret = AVERROR_INVALIDDATA;
8126 } else {
8127 2 encryption_index->nb_encrypted_samples = sample_count;
8128 }
8129
8130 2 finish:
8131 2 avio_seek(pb, prev_pos, SEEK_SET);
8132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
8133 for (; i > 0; i--) {
8134 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
8135 }
8136 av_freep(&encryption_index->encrypted_samples);
8137 }
8138 2 return ret;
8139 }
8140
8141 9 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8142 {
8143 MOVEncryptionIndex *encryption_index;
8144 MOVStreamContext *sc;
8145 int ret;
8146 unsigned int sample_count, aux_info_type, aux_info_param;
8147
8148 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8150 return ret;
8151
8152
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (encryption_index->nb_encrypted_samples) {
8153 // This can happen if we have both saio/saiz and senc atoms.
8154 7 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
8155 7 return 0;
8156 }
8157
8158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_sample_count) {
8159 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
8160 return AVERROR_INVALIDDATA;
8161 }
8162
8163 2 avio_r8(pb); /* version */
8164
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
8165 aux_info_type = avio_rb32(pb);
8166 aux_info_param = avio_rb32(pb);
8167 if (sc->cenc.default_encrypted_sample) {
8168 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
8169 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
8170 return 0;
8171 }
8172 if (aux_info_param != 0) {
8173 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
8174 return 0;
8175 }
8176 } else {
8177 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8178 if ((aux_info_type == MKBETAG('c','e','n','c') ||
8179 aux_info_type == MKBETAG('c','e','n','s') ||
8180 aux_info_type == MKBETAG('c','b','c','1') ||
8181 aux_info_type == MKBETAG('c','b','c','s')) &&
8182 aux_info_param == 0) {
8183 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
8184 return AVERROR_INVALIDDATA;
8185 } else {
8186 return 0;
8187 }
8188 }
8189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
8190 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8191 return 0;
8192 }
8193
8194 2 encryption_index->auxiliary_info_default_size = avio_r8(pb);
8195 2 sample_count = avio_rb32(pb);
8196
8197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_default_size == 0) {
8198 if (sample_count == 0)
8199 return AVERROR_INVALIDDATA;
8200
8201 encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
8202 if (!encryption_index->auxiliary_info_sizes)
8203 return AVERROR(ENOMEM);
8204
8205 ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
8206 if (ret != sample_count) {
8207 av_freep(&encryption_index->auxiliary_info_sizes);
8208
8209 if (ret >= 0)
8210 ret = AVERROR_INVALIDDATA;
8211 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
8212 av_err2str(ret));
8213 return ret;
8214 }
8215 }
8216 2 encryption_index->auxiliary_info_sample_count = sample_count;
8217
8218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
8219 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
8220 }
8221
8222 2 return 0;
8223 }
8224
8225 9 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8226 {
8227 uint64_t *auxiliary_offsets;
8228 MOVEncryptionIndex *encryption_index;
8229 MOVStreamContext *sc;
8230 int i, ret;
8231 unsigned int version, entry_count, aux_info_type, aux_info_param;
8232 9 unsigned int alloc_size = 0;
8233
8234 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8236 return ret;
8237
8238
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (encryption_index->nb_encrypted_samples) {
8239 // This can happen if we have both saio/saiz and senc atoms.
8240 7 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
8241 7 return 0;
8242 }
8243
8244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
8245 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
8246 return AVERROR_INVALIDDATA;
8247 }
8248
8249 2 version = avio_r8(pb); /* version */
8250
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
8251 aux_info_type = avio_rb32(pb);
8252 aux_info_param = avio_rb32(pb);
8253 if (sc->cenc.default_encrypted_sample) {
8254 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
8255 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
8256 return 0;
8257 }
8258 if (aux_info_param != 0) {
8259 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
8260 return 0;
8261 }
8262 } else {
8263 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8264 if ((aux_info_type == MKBETAG('c','e','n','c') ||
8265 aux_info_type == MKBETAG('c','e','n','s') ||
8266 aux_info_type == MKBETAG('c','b','c','1') ||
8267 aux_info_type == MKBETAG('c','b','c','s')) &&
8268 aux_info_param == 0) {
8269 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
8270 return AVERROR_INVALIDDATA;
8271 } else {
8272 return 0;
8273 }
8274 }
8275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
8276 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8277 return 0;
8278 }
8279
8280 2 entry_count = avio_rb32(pb);
8281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
8282 return AVERROR(ENOMEM);
8283
8284
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 < entry_count && !pb->eof_reached; i++) {
8285
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 unsigned int min_offsets = FFMIN(FFMAX(i + 1, 1024), entry_count);
8286 2 auxiliary_offsets = av_fast_realloc(
8287 2 encryption_index->auxiliary_offsets, &alloc_size,
8288 min_offsets * sizeof(*auxiliary_offsets));
8289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!auxiliary_offsets) {
8290 av_freep(&encryption_index->auxiliary_offsets);
8291 return AVERROR(ENOMEM);
8292 }
8293 2 encryption_index->auxiliary_offsets = auxiliary_offsets;
8294
8295
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version == 0) {
8296 2 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
8297 } else {
8298 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
8299 }
8300
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (c->frag_index.current >= 0) {
8301 2 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
8302 }
8303 }
8304
8305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
8306 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
8307 av_freep(&encryption_index->auxiliary_offsets);
8308 return AVERROR_INVALIDDATA;
8309 }
8310
8311 2 encryption_index->auxiliary_offsets_count = entry_count;
8312
8313
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (encryption_index->auxiliary_info_sample_count) {
8314 2 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
8315 }
8316
8317 return 0;
8318 }
8319
8320 4 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8321 {
8322 AVEncryptionInitInfo *info, *old_init_info;
8323 uint8_t **key_ids;
8324 AVStream *st;
8325 const AVPacketSideData *old_side_data;
8326 uint8_t *side_data, *extra_data;
8327 size_t side_data_size;
8328 4 int ret = 0;
8329 4 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
8330
8331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8332 return 0;
8333 4 st = c->fc->streams[c->fc->nb_streams-1];
8334
8335 4 version = avio_r8(pb); /* version */
8336 4 avio_rb24(pb); /* flags */
8337
8338 4 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
8339 /* key_id_size */ 16, /* data_size */ 0);
8340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info)
8341 return AVERROR(ENOMEM);
8342
8343
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
8344 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
8345 goto finish;
8346 }
8347
8348
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (version > 0) {
8349 4 kid_count = avio_rb32(pb);
8350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
8351 ret = AVERROR(ENOMEM);
8352 goto finish;
8353 }
8354
8355
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 for (unsigned int i = 0; i < kid_count && !pb->eof_reached; i++) {
8356 4 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
8357 4 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
8358 min_kid_count * sizeof(*key_ids));
8359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!key_ids) {
8360 ret = AVERROR(ENOMEM);
8361 goto finish;
8362 }
8363 4 info->key_ids = key_ids;
8364
8365 4 info->key_ids[i] = av_mallocz(16);
8366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info->key_ids[i]) {
8367 ret = AVERROR(ENOMEM);
8368 goto finish;
8369 }
8370 4 info->num_key_ids = i + 1;
8371
8372
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
8373 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
8374 goto finish;
8375 }
8376 }
8377
8378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pb->eof_reached) {
8379 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
8380 ret = AVERROR_INVALIDDATA;
8381 goto finish;
8382 }
8383 }
8384
8385 4 extra_data_size = avio_rb32(pb);
8386 4 extra_data = av_malloc(extra_data_size);
8387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!extra_data) {
8388 ret = AVERROR(ENOMEM);
8389 goto finish;
8390 }
8391 4 ret = avio_read(pb, extra_data, extra_data_size);
8392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != extra_data_size) {
8393 av_free(extra_data);
8394
8395 if (ret >= 0)
8396 ret = AVERROR_INVALIDDATA;
8397 goto finish;
8398 }
8399
8400 4 av_freep(&info->data); // malloc(0) may still allocate something.
8401 4 info->data = extra_data;
8402 4 info->data_size = extra_data_size;
8403
8404 // If there is existing initialization data, append to the list.
8405 4 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
8406 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
8407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (old_side_data) {
8408 old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
8409 if (old_init_info) {
8410 // Append to the end of the list.
8411 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
8412 if (!cur->next) {
8413 cur->next = info;
8414 break;
8415 }
8416 }
8417 info = old_init_info;
8418 } else {
8419 // Assume existing side-data will be valid, so the only error we could get is OOM.
8420 ret = AVERROR(ENOMEM);
8421 goto finish;
8422 }
8423 }
8424
8425 4 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
8426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!side_data) {
8427 ret = AVERROR(ENOMEM);
8428 goto finish;
8429 }
8430
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
8431 4 &st->codecpar->nb_coded_side_data,
8432 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
8433 side_data, side_data_size, 0))
8434 av_free(side_data);
8435
8436 4 finish:
8437 4 av_encryption_init_info_free(info);
8438 4 return ret;
8439 }
8440
8441 11 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8442 {
8443 AVStream *st;
8444 MOVStreamContext *sc;
8445
8446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
8447 return 0;
8448 11 st = c->fc->streams[c->fc->nb_streams-1];
8449 11 sc = st->priv_data;
8450
8451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (sc->pseudo_stream_id != 0) {
8452 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
8453 return AVERROR_PATCHWELCOME;
8454 }
8455
8456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
8457 return AVERROR_INVALIDDATA;
8458
8459 11 avio_rb32(pb); /* version and flags */
8460
8461
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (!sc->cenc.default_encrypted_sample) {
8462 11 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.default_encrypted_sample) {
8464 return AVERROR(ENOMEM);
8465 }
8466 }
8467
8468 11 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
8469 11 return 0;
8470 }
8471
8472 11 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8473 {
8474 AVStream *st;
8475 MOVStreamContext *sc;
8476 unsigned int version, pattern, is_protected, iv_size;
8477
8478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
8479 return 0;
8480 11 st = c->fc->streams[c->fc->nb_streams-1];
8481 11 sc = st->priv_data;
8482
8483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (sc->pseudo_stream_id != 0) {
8484 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
8485 return AVERROR_PATCHWELCOME;
8486 }
8487
8488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.default_encrypted_sample) {
8489 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8490 if (!sc->cenc.default_encrypted_sample) {
8491 return AVERROR(ENOMEM);
8492 }
8493 }
8494
8495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 20)
8496 return AVERROR_INVALIDDATA;
8497
8498 11 version = avio_r8(pb); /* version */
8499 11 avio_rb24(pb); /* flags */
8500
8501 11 avio_r8(pb); /* reserved */
8502 11 pattern = avio_r8(pb);
8503
8504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (version > 0) {
8505 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
8506 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
8507 }
8508
8509 11 is_protected = avio_r8(pb);
8510
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
11 if (is_protected && !sc->cenc.encryption_index) {
8511 // The whole stream should be by-default encrypted.
8512 11 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
8513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.encryption_index)
8514 return AVERROR(ENOMEM);
8515 }
8516 11 sc->cenc.per_sample_iv_size = avio_r8(pb);
8517
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
11 if (sc->cenc.per_sample_iv_size != 0 && sc->cenc.per_sample_iv_size != 8 &&
8518 sc->cenc.per_sample_iv_size != 16) {
8519 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
8520 return AVERROR_INVALIDDATA;
8521 }
8522
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (avio_read(pb, sc->cenc.default_encrypted_sample->key_id, 16) != 16) {
8523 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
8524 return AVERROR_INVALIDDATA;
8525 }
8526
8527
3/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 9 times.
11 if (is_protected && !sc->cenc.per_sample_iv_size) {
8528 2 iv_size = avio_r8(pb);
8529
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (iv_size != 8 && iv_size != 16) {
8530 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
8531 return AVERROR_INVALIDDATA;
8532 }
8533
8534
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_read(pb, sc->cenc.default_encrypted_sample->iv, iv_size) != iv_size) {
8535 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
8536 return AVERROR_INVALIDDATA;
8537 }
8538 }
8539
8540 11 return 0;
8541 }
8542
8543 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8544 {
8545 AVStream *st;
8546 int last, type, size, ret;
8547 uint8_t buf[4];
8548
8549 if (c->fc->nb_streams < 1)
8550 return 0;
8551 st = c->fc->streams[c->fc->nb_streams-1];
8552
8553 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
8554 return AVERROR_INVALIDDATA;
8555
8556 /* Check FlacSpecificBox version. */
8557 if (avio_r8(pb) != 0)
8558 return AVERROR_INVALIDDATA;
8559
8560 avio_rb24(pb); /* Flags */
8561
8562 if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
8563 av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
8564 return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
8565 }
8566 flac_parse_block_header(buf, &last, &type, &size);
8567
8568 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
8569 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
8570 return AVERROR_INVALIDDATA;
8571 }
8572
8573 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
8574 if (ret < 0)
8575 return ret;
8576
8577 if (!last)
8578 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
8579
8580 return 0;
8581 }
8582
8583 11 static int get_key_from_kid(uint8_t* out, int len, MOVContext *c, AVEncryptionInfo *sample) {
8584 AVDictionaryEntry *key_entry_hex;
8585 char kid_hex[16*2+1];
8586
8587
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
11 if (c->decryption_default_key && c->decryption_default_key_len != len) {
8588 av_log(c->fc, AV_LOG_ERROR, "invalid default decryption key length: got %d, expected %d\n", c->decryption_default_key_len, len);
8589 return -1;
8590 }
8591
8592
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
11 if (!c->decryption_keys) {
8593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 av_assert0(c->decryption_default_key);
8594 8 memcpy(out, c->decryption_default_key, len);
8595 8 return 0;
8596 }
8597
8598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sample->key_id_size != 16) {
8599 av_log(c->fc, AV_LOG_ERROR, "invalid key ID size: got %u, expected 16\n", sample->key_id_size);
8600 return -1;
8601 }
8602
8603 3 ff_data_to_hex(kid_hex, sample->key_id, 16, 1);
8604 3 key_entry_hex = av_dict_get(c->decryption_keys, kid_hex, NULL, AV_DICT_DONT_STRDUP_KEY|AV_DICT_DONT_STRDUP_VAL);
8605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!key_entry_hex) {
8606 if (!c->decryption_default_key) {
8607 av_log(c->fc, AV_LOG_ERROR, "unable to find KID %s\n", kid_hex);
8608 return -1;
8609 }
8610 memcpy(out, c->decryption_default_key, len);
8611 return 0;
8612 }
8613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (strlen(key_entry_hex->value) != len*2) {
8614 return -1;
8615 }
8616 3 ff_hex_to_data(out, key_entry_hex->value);
8617 3 return 0;
8618 }
8619
8620 341 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8621 {
8622 int i, ret;
8623 int bytes_of_protected_data;
8624 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8625
8626
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 330 times.
341 if (!sc->cenc.aes_ctr) {
8627 11 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0) {
8629 return ret;
8630 }
8631
8632 /* initialize the cipher */
8633 11 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.aes_ctr) {
8635 return AVERROR(ENOMEM);
8636 }
8637
8638 11 ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8639
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0) {
8640 return ret;
8641 }
8642 }
8643
8644 341 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8645
8646
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 245 times.
341 if (!sample->subsample_count) {
8647 /* decrypt the whole packet */
8648 96 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8649 96 return 0;
8650 }
8651
8652
2/2
✓ Branch 0 taken 321 times.
✓ Branch 1 taken 245 times.
566 for (i = 0; i < sample->subsample_count; i++) {
8653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 321 times.
321 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8654 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8655 return AVERROR_INVALIDDATA;
8656 }
8657
8658 /* skip the clear bytes */
8659 321 input += sample->subsamples[i].bytes_of_clear_data;
8660 321 size -= sample->subsamples[i].bytes_of_clear_data;
8661
8662 /* decrypt the encrypted bytes */
8663
8664 321 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
8665 321 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
8666
8667 321 input += bytes_of_protected_data;
8668 321 size -= bytes_of_protected_data;
8669 }
8670
8671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
245 if (size > 0) {
8672 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8673 return AVERROR_INVALIDDATA;
8674 }
8675
8676 245 return 0;
8677 }
8678
8679 static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8680 {
8681 int i, ret;
8682 int num_of_encrypted_blocks;
8683 uint8_t iv[16];
8684 uint8_t decryption_key[16];
8685
8686 if (!sc->cenc.aes_ctx) {
8687 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8688 if (ret < 0) {
8689 return ret;
8690 }
8691
8692 /* initialize the cipher */
8693 sc->cenc.aes_ctx = av_aes_alloc();
8694 if (!sc->cenc.aes_ctx) {
8695 return AVERROR(ENOMEM);
8696 }
8697
8698 ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8699 if (ret < 0) {
8700 return ret;
8701 }
8702 }
8703
8704 memcpy(iv, sample->iv, 16);
8705
8706 /* whole-block full sample encryption */
8707 if (!sample->subsample_count) {
8708 /* decrypt the whole packet */
8709 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8710 return 0;
8711 }
8712
8713 for (i = 0; i < sample->subsample_count; i++) {
8714 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8715 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8716 return AVERROR_INVALIDDATA;
8717 }
8718
8719 if (sample->subsamples[i].bytes_of_protected_data % 16) {
8720 av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8721 return AVERROR_INVALIDDATA;
8722 }
8723
8724 /* skip the clear bytes */
8725 input += sample->subsamples[i].bytes_of_clear_data;
8726 size -= sample->subsamples[i].bytes_of_clear_data;
8727
8728 /* decrypt the encrypted bytes */
8729 num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8730 if (num_of_encrypted_blocks > 0) {
8731 av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8732 }
8733 input += sample->subsamples[i].bytes_of_protected_data;
8734 size -= sample->subsamples[i].bytes_of_protected_data;
8735 }
8736
8737 if (size > 0) {
8738 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8739 return AVERROR_INVALIDDATA;
8740 }
8741
8742 return 0;
8743 }
8744
8745 static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8746 {
8747 int i, ret, rem_bytes;
8748 uint8_t *data;
8749 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8750
8751 if (!sc->cenc.aes_ctr) {
8752 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8753 if (ret < 0) {
8754 return ret;
8755 }
8756
8757 /* initialize the cipher */
8758 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8759 if (!sc->cenc.aes_ctr) {
8760 return AVERROR(ENOMEM);
8761 }
8762
8763 ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8764 if (ret < 0) {
8765 return ret;
8766 }
8767 }
8768
8769 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8770
8771 /* whole-block full sample encryption */
8772 if (!sample->subsample_count) {
8773 /* decrypt the whole packet */
8774 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8775 return 0;
8776 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8777 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8778 return AVERROR_INVALIDDATA;
8779 }
8780
8781 for (i = 0; i < sample->subsample_count; i++) {
8782 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8783 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8784 return AVERROR_INVALIDDATA;
8785 }
8786
8787 /* skip the clear bytes */
8788 input += sample->subsamples[i].bytes_of_clear_data;
8789 size -= sample->subsamples[i].bytes_of_clear_data;
8790
8791 /* decrypt the encrypted bytes */
8792 data = input;
8793 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8794 while (rem_bytes > 0) {
8795 if (rem_bytes < 16*sample->crypt_byte_block) {
8796 break;
8797 }
8798 av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8799 data += 16*sample->crypt_byte_block;
8800 rem_bytes -= 16*sample->crypt_byte_block;
8801 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8802 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8803 }
8804 input += sample->subsamples[i].bytes_of_protected_data;
8805 size -= sample->subsamples[i].bytes_of_protected_data;
8806 }
8807
8808 if (size > 0) {
8809 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8810 return AVERROR_INVALIDDATA;
8811 }
8812
8813 return 0;
8814 }
8815
8816 static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8817 {
8818 int i, ret, rem_bytes;
8819 uint8_t iv[16];
8820 uint8_t *data;
8821 uint8_t decryption_key[16];
8822
8823 if (!sc->cenc.aes_ctx) {
8824 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8825 if (ret < 0) {
8826 return ret;
8827 }
8828
8829 /* initialize the cipher */
8830 sc->cenc.aes_ctx = av_aes_alloc();
8831 if (!sc->cenc.aes_ctx) {
8832 return AVERROR(ENOMEM);
8833 }
8834
8835 ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8836 if (ret < 0) {
8837 return ret;
8838 }
8839 }
8840
8841 /* whole-block full sample encryption */
8842 if (!sample->subsample_count) {
8843 /* decrypt the whole packet */
8844 memcpy(iv, sample->iv, 16);
8845 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8846 return 0;
8847 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8848 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8849 return AVERROR_INVALIDDATA;
8850 }
8851
8852 for (i = 0; i < sample->subsample_count; i++) {
8853 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8854 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8855 return AVERROR_INVALIDDATA;
8856 }
8857
8858 /* skip the clear bytes */
8859 input += sample->subsamples[i].bytes_of_clear_data;
8860 size -= sample->subsamples[i].bytes_of_clear_data;
8861
8862 /* decrypt the encrypted bytes */
8863 memcpy(iv, sample->iv, 16);
8864 data = input;
8865 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8866 while (rem_bytes > 0) {
8867 if (rem_bytes < 16*sample->crypt_byte_block) {
8868 break;
8869 }
8870 av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8871 data += 16*sample->crypt_byte_block;
8872 rem_bytes -= 16*sample->crypt_byte_block;
8873 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8874 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8875 }
8876 input += sample->subsamples[i].bytes_of_protected_data;
8877 size -= sample->subsamples[i].bytes_of_protected_data;
8878 }
8879
8880 if (size > 0) {
8881 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8882 return AVERROR_INVALIDDATA;
8883 }
8884
8885 return 0;
8886 }
8887
8888 341 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8889 {
8890
3/6
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 341 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 341 times.
✗ Branch 5 not taken.
341 if (sample->scheme == MKBETAG('c','e','n','c') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8891 341 return cenc_scheme_decrypt(c, sc, sample, input, size);
8892 } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8893 return cbc1_scheme_decrypt(c, sc, sample, input, size);
8894 } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8895 return cens_scheme_decrypt(c, sc, sample, input, size);
8896 } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8897 return cbcs_scheme_decrypt(c, sc, sample, input, size);
8898 } else {
8899 av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8900 return AVERROR_INVALIDDATA;
8901 }
8902 }
8903
8904 107942 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8905 {
8906 107942 int current = frag_index->current;
8907
8908
2/2
✓ Branch 0 taken 106957 times.
✓ Branch 1 taken 985 times.
107942 if (!frag_index->nb_items)
8909 106957 return NULL;
8910
8911 // Check frag_index->current is the right one for pkt. It can out of sync.
8912
2/4
✓ Branch 0 taken 985 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 985 times.
✗ Branch 3 not taken.
985 if (current >= 0 && current < frag_index->nb_items) {
8913
2/2
✓ Branch 0 taken 958 times.
✓ Branch 1 taken 27 times.
985 if (frag_index->item[current].moof_offset < pkt->pos &&
8914
2/2
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 346 times.
958 (current + 1 == frag_index->nb_items ||
8915
2/2
✓ Branch 0 taken 536 times.
✓ Branch 1 taken 76 times.
612 frag_index->item[current + 1].moof_offset > pkt->pos))
8916 882 return get_frag_stream_info(frag_index, current, id);
8917 }
8918
8919
8920
2/2
✓ Branch 0 taken 4557 times.
✓ Branch 1 taken 9 times.
4566 for (int i = 0; i < frag_index->nb_items; i++) {
8921
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 4463 times.
4557 if (frag_index->item[i].moof_offset > pkt->pos)
8922 94 break;
8923 4463 current = i;
8924 }
8925 103 frag_index->current = current;
8926 103 return get_frag_stream_info(frag_index, current, id);
8927 }
8928
8929 107942 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8930 {
8931 MOVFragmentStreamInfo *frag_stream_info;
8932 MOVEncryptionIndex *encryption_index;
8933 AVEncryptionInfo *encrypted_sample;
8934 int encrypted_index, ret;
8935
8936 107942 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8937 107942 encrypted_index = current_index;
8938 107942 encryption_index = NULL;
8939
2/2
✓ Branch 0 taken 985 times.
✓ Branch 1 taken 106957 times.
107942 if (frag_stream_info) {
8940 // Note this only supports encryption info in the first sample descriptor.
8941
2/2
✓ Branch 0 taken 937 times.
✓ Branch 1 taken 48 times.
985 if (frag_stream_info->stsd_id == 1) {
8942
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 889 times.
937 if (frag_stream_info->encryption_index) {
8943 48 encrypted_index = current_index - frag_stream_info->index_base;
8944 48 encryption_index = frag_stream_info->encryption_index;
8945 } else {
8946 889 encryption_index = sc->cenc.encryption_index;
8947 }
8948 }
8949 } else {
8950 106957 encryption_index = sc->cenc.encryption_index;
8951 }
8952
8953
2/2
✓ Branch 0 taken 341 times.
✓ Branch 1 taken 107601 times.
107942 if (encryption_index) {
8954
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 293 times.
341 if (encryption_index->auxiliary_info_sample_count &&
8955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8956 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8957 return AVERROR_INVALIDDATA;
8958 }
8959
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 293 times.
341 if (encryption_index->auxiliary_offsets_count &&
8960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8961 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8962 return AVERROR_INVALIDDATA;
8963 }
8964
8965 341 encrypted_sample = NULL;
8966
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 245 times.
341 if (!encryption_index->nb_encrypted_samples) {
8967 // Full-sample encryption with default settings.
8968 96 encrypted_sample = sc->cenc.default_encrypted_sample;
8969
2/4
✓ Branch 0 taken 245 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 245 times.
✗ Branch 3 not taken.
245 } else if (encrypted_index >= 0 && encrypted_index < encryption_index->nb_encrypted_samples) {
8970 // Per-sample setting override.
8971 245 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
245 if (!encrypted_sample) {
8973 encrypted_sample = sc->cenc.default_encrypted_sample;
8974 }
8975 }
8976
8977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
341 if (!encrypted_sample) {
8978 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8979 return AVERROR_INVALIDDATA;
8980 }
8981
8982
3/4
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 146 times.
✓ Branch 2 taken 195 times.
✗ Branch 3 not taken.
341 if (mov->decryption_keys || mov->decryption_default_key) {
8983 341 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
8984 } else {
8985 size_t size;
8986 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
8987 if (!side_data)
8988 return AVERROR(ENOMEM);
8989 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
8990 if (ret < 0)
8991 av_free(side_data);
8992 return ret;
8993 }
8994 }
8995
8996 107601 return 0;
8997 }
8998
8999 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9000 {
9001 const int OPUS_SEEK_PREROLL_MS = 80;
9002 int ret;
9003 AVStream *st;
9004 size_t size;
9005 uint16_t pre_skip;
9006
9007 if (c->fc->nb_streams < 1)
9008 return 0;
9009 st = c->fc->streams[c->fc->nb_streams-1];
9010
9011 if ((uint64_t)atom.size > (1<<30) || atom.size < 11 || st->codecpar->extradata)
9012 return AVERROR_INVALIDDATA;
9013
9014 /* Check OpusSpecificBox version. */
9015 if (avio_r8(pb) != 0) {
9016 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
9017 return AVERROR_INVALIDDATA;
9018 }
9019
9020 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
9021 size = atom.size + 8;
9022
9023 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
9024 return ret;
9025
9026 AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
9027 AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
9028 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
9029 if ((ret = ffio_read_size(pb, st->codecpar->extradata + 9, size - 9)) < 0) {
9030 av_freep(&st->codecpar->extradata);
9031 st->codecpar->extradata_size = 0;
9032 return ret;
9033 }
9034
9035 /* OpusSpecificBox is stored in big-endian, but OpusHead is
9036 little-endian; aside from the preceding magic and version they're
9037 otherwise currently identical. Data after output gain at offset 16
9038 doesn't need to be bytewapped. */
9039 pre_skip = AV_RB16A(st->codecpar->extradata + 10);
9040 AV_WL16A(st->codecpar->extradata + 10, pre_skip);
9041 AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
9042 AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
9043
9044 st->codecpar->initial_padding = pre_skip;
9045 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
9046 (AVRational){1, 1000},
9047 (AVRational){1, 48000});
9048
9049 return 0;
9050 }
9051
9052 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9053 {
9054 AVStream *st;
9055 unsigned format_info;
9056 int channel_assignment, channel_assignment1, channel_assignment2;
9057 int ratebits;
9058 uint64_t chmask;
9059
9060 if (c->fc->nb_streams < 1)
9061 return 0;
9062 st = c->fc->streams[c->fc->nb_streams-1];
9063
9064 if (atom.size < 10)
9065 return AVERROR_INVALIDDATA;
9066
9067 format_info = avio_rb32(pb);
9068
9069 ratebits = (format_info >> 28) & 0xF;
9070 channel_assignment1 = (format_info >> 15) & 0x1F;
9071 channel_assignment2 = format_info & 0x1FFF;
9072 if (channel_assignment2)
9073 channel_assignment = channel_assignment2;
9074 else
9075 channel_assignment = channel_assignment1;
9076
9077 st->codecpar->frame_size = 40 << (ratebits & 0x7);
9078 st->codecpar->sample_rate = mlp_samplerate(ratebits);
9079
9080 av_channel_layout_uninit(&st->codecpar->ch_layout);
9081 chmask = truehd_layout(channel_assignment);
9082 av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
9083
9084 return 0;
9085 }
9086
9087 11 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9088 {
9089 AVStream *st;
9090 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
9091 int ret;
9092 11 int64_t read_size = atom.size;
9093
9094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
9095 return 0;
9096 11 st = c->fc->streams[c->fc->nb_streams-1];
9097
9098 // At most 24 bytes
9099 11 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
9100
9101
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
9102 return ret;
9103
9104 11 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
9105 }
9106
9107 7 static int mov_read_hvce(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9108 {
9109 AVStream *st;
9110 AVPacketSideData *sd;
9111 int ret;
9112
9113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (c->fc->nb_streams < 1)
9114 return 0;
9115 7 st = c->fc->streams[c->fc->nb_streams - 1];
9116
9117
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (atom.size < 23 || atom.size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
9118 return AVERROR_INVALIDDATA;
9119
9120 7 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
9121 7 &st->codecpar->nb_coded_side_data,
9122 AV_PKT_DATA_HEVC_CONF,
9123 7 atom.size, 0);
9124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sd)
9125 return AVERROR(ENOMEM);
9126
9127 7 ret = ffio_read_size(pb, sd->data, atom.size);
9128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
9129 return ret;
9130
9131 7 return 0;
9132 }
9133
9134 4 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9135 {
9136 AVStream *st;
9137 uint8_t *buf;
9138 int ret, old_size, num_arrays;
9139
9140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
9141 return 0;
9142 4 st = c->fc->streams[c->fc->nb_streams-1];
9143
9144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!st->codecpar->extradata_size)
9145 // TODO: handle lhvC when present before hvcC
9146 return 0;
9147
9148
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if (atom.size < 6 || st->codecpar->extradata_size < 23 ||
9149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 atom.size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
9150 return AVERROR_INVALIDDATA;
9151 }
9152
9153 4 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
9154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!buf)
9155 return AVERROR(ENOMEM);
9156 4 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
9157
9158 4 ret = ffio_read_size(pb, buf, atom.size);
9159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
9160 av_free(buf);
9161 av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
9162 return 0;
9163 }
9164
9165 4 num_arrays = buf[5];
9166 4 old_size = st->codecpar->extradata_size;
9167 4 atom.size -= 8 /* account for mov_realloc_extradata offsetting */
9168 + 6 /* lhvC bytes before the arrays*/;
9169
9170 4 ret = mov_realloc_extradata(st->codecpar, atom);
9171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
9172 av_free(buf);
9173 return ret;
9174 }
9175
9176 4 st->codecpar->extradata[22] += num_arrays;
9177 4 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
9178
9179 4 st->disposition |= AV_DISPOSITION_MULTILAYER;
9180
9181 4 av_free(buf);
9182 4 return 0;
9183 }
9184
9185 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9186 {
9187 4 AVFormatContext *ctx = c->fc;
9188 4 AVStream *st = NULL;
9189 AVBPrint scheme_buf, value_buf;
9190 4 int64_t scheme_str_len = 0, value_str_len = 0;
9191 4 int version, flags, ret = AVERROR_BUG;
9192 4 int64_t size = atom.size;
9193
9194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
9195 // 4 bytes for version + flags, 2x 1 byte for null
9196 return AVERROR_INVALIDDATA;
9197
9198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
9199 return 0;
9200 4 st = c->fc->streams[c->fc->nb_streams-1];
9201
9202 4 version = avio_r8(pb);
9203 4 flags = avio_rb24(pb);
9204 4 size -= 4;
9205
9206
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) {
9207 av_log(ctx, AV_LOG_ERROR,
9208 "Unsupported 'kind' box with version %d, flags: %x",
9209 version, flags);
9210 return AVERROR_INVALIDDATA;
9211 }
9212
9213 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
9214 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
9215
9216
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,
9217 size)) < 0) {
9218 ret = scheme_str_len;
9219 goto cleanup;
9220 }
9221
9222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
9223 // we need to have another string, even if nullptr.
9224 // we check with + 1 since we expect that if size was not hit,
9225 // an additional null was read.
9226 ret = AVERROR_INVALIDDATA;
9227 goto cleanup;
9228 }
9229
9230 4 size -= scheme_str_len + 1;
9231
9232
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,
9233 size)) < 0) {
9234 ret = value_str_len;
9235 goto cleanup;
9236 }
9237
9238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
9239 // in case of no trailing null, box is not valid.
9240 ret = AVERROR_INVALIDDATA;
9241 goto cleanup;
9242 }
9243
9244 4 av_log(ctx, AV_LOG_TRACE,
9245 "%s stream %d KindBox(scheme: %s, value: %s)\n",
9246 4 av_get_media_type_string(st->codecpar->codec_type),
9247 st->index,
9248 scheme_buf.str, value_buf.str);
9249
9250
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++) {
9251 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
9252
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
9253 continue;
9254
9255
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
9256 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
9257
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
9258 16 continue;
9259
9260 4 st->disposition |= value_map.disposition;
9261 }
9262 }
9263
9264 4 ret = 0;
9265
9266 4 cleanup:
9267
9268 4 av_bprint_finalize(&scheme_buf, NULL);
9269 4 av_bprint_finalize(&value_buf, NULL);
9270
9271 4 return ret;
9272 }
9273
9274 static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9275 {
9276 AVStream *st;
9277 AVChannelLayout ch_layout = { 0 };
9278 int ret, i, version, type;
9279 int ambisonic_order, channel_order, normalization, channel_count;
9280 int ambi_channels, non_diegetic_channels;
9281
9282 if (c->fc->nb_streams < 1)
9283 return 0;
9284
9285 st = c->fc->streams[c->fc->nb_streams - 1];
9286
9287 if (atom.size < 16) {
9288 av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
9289 return AVERROR_INVALIDDATA;
9290 }
9291
9292 version = avio_r8(pb);
9293 if (version) {
9294 av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
9295 return 0;
9296 }
9297
9298 type = avio_r8(pb);
9299 if (type & 0x7f) {
9300 av_log(c->fc, AV_LOG_WARNING,
9301 "Unsupported ambisonic type %d\n", type & 0x7f);
9302 return 0;
9303 }
9304 non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
9305
9306 ambisonic_order = avio_rb32(pb);
9307
9308 channel_order = avio_r8(pb);
9309 if (channel_order) {
9310 av_log(c->fc, AV_LOG_WARNING,
9311 "Unsupported channel_order %d\n", channel_order);
9312 return 0;
9313 }
9314
9315 normalization = avio_r8(pb);
9316 if (normalization) {
9317 av_log(c->fc, AV_LOG_WARNING,
9318 "Unsupported normalization %d\n", normalization);
9319 return 0;
9320 }
9321
9322 channel_count = avio_rb32(pb);
9323 if (ambisonic_order < 0 || ambisonic_order > 31 ||
9324 channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
9325 non_diegetic_channels)) {
9326 av_log(c->fc, AV_LOG_ERROR,
9327 "Invalid number of channels (%d / %d)\n",
9328 channel_count, ambisonic_order);
9329 return 0;
9330 }
9331 ambi_channels = channel_count - non_diegetic_channels;
9332
9333 ret = av_channel_layout_custom_init(&ch_layout, channel_count);
9334 if (ret < 0)
9335 return 0;
9336
9337 for (i = 0; i < channel_count; i++) {
9338 unsigned channel = avio_rb32(pb);
9339
9340 if (channel >= channel_count) {
9341 av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
9342 channel, ambisonic_order);
9343 av_channel_layout_uninit(&ch_layout);
9344 return 0;
9345 }
9346 if (channel >= ambi_channels)
9347 ch_layout.u.map[i].id = channel - ambi_channels;
9348 else
9349 ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
9350 }
9351
9352 ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
9353 if (ret < 0) {
9354 av_channel_layout_uninit(&ch_layout);
9355 return 0;
9356 }
9357
9358 av_channel_layout_uninit(&st->codecpar->ch_layout);
9359 st->codecpar->ch_layout = ch_layout;
9360
9361 return 0;
9362 }
9363
9364 static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9365 {
9366 AVStream *st;
9367 int version;
9368
9369 if (c->fc->nb_streams < 1)
9370 return 0;
9371
9372 st = c->fc->streams[c->fc->nb_streams - 1];
9373
9374 if (atom.size < 5) {
9375 av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
9376 return AVERROR_INVALIDDATA;
9377 }
9378
9379 version = avio_r8(pb);
9380 if (version) {
9381 av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
9382 return 0;
9383 }
9384
9385 st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
9386
9387 return 0;
9388 }
9389
9390 171 static int rb_size(AVIOContext *pb, int64_t *value, int size)
9391 {
9392
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 160 times.
171 if (size == 0)
9393 11 *value = 0;
9394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 else if (size == 1)
9395 *value = avio_r8(pb);
9396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 else if (size == 2)
9397 *value = avio_rb16(pb);
9398
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 else if (size == 4)
9399 160 *value = avio_rb32(pb);
9400 else if (size == 8) {
9401 *value = avio_rb64(pb);
9402 if (*value < 0)
9403 return -1;
9404 } else
9405 return -1;
9406 171 return size;
9407 }
9408
9409 18 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9410 {
9411 18 avio_rb32(pb); // version & flags.
9412 18 c->primary_item_id = avio_rb16(pb);
9413 18 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
9414 18 return atom.size;
9415 }
9416
9417 9 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9418 {
9419 9 c->idat_offset = avio_tell(pb);
9420 9 return 0;
9421 }
9422
9423 18 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9424 {
9425 HEIFItem **heif_item;
9426 int version, offset_size, length_size, base_offset_size, index_size;
9427 int item_count, extent_count;
9428 int64_t base_offset, extent_offset, extent_length;
9429 uint8_t value;
9430
9431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->found_iloc) {
9432 av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
9433 return 0;
9434 }
9435
9436 18 version = avio_r8(pb);
9437 18 avio_rb24(pb); // flags.
9438
9439 18 value = avio_r8(pb);
9440 18 offset_size = (value >> 4) & 0xF;
9441 18 length_size = value & 0xF;
9442 18 value = avio_r8(pb);
9443 18 base_offset_size = (value >> 4) & 0xF;
9444
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 7 times.
18 index_size = !version ? 0 : (value & 0xF);
9445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (index_size) {
9446 avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
9447 return AVERROR_PATCHWELCOME;
9448 }
9449
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9450
9451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (item_count > atom.size)
9452 return AVERROR_INVALIDDATA;
9453
9454 18 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
9455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!heif_item)
9456 return AVERROR(ENOMEM);
9457 18 c->heif_item = heif_item;
9458
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (item_count > c->nb_heif_item)
9459 18 memset(&c->heif_item[c->nb_heif_item], 0,
9460 18 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
9461 18 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
9462
9463 18 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
9464
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (int i = 0; i < item_count; i++) {
9465 57 HEIFItem *item = NULL;
9466
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9467
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 12 times.
57 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
9468 int j;
9469
9470
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (avio_feof(pb))
9471 return AVERROR_INVALIDDATA;
9472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (offset_type > 1) {
9473 avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
9474 return AVERROR_PATCHWELCOME;
9475 }
9476
9477 57 avio_rb16(pb); // data_reference_index.
9478
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (rb_size(pb, &base_offset, base_offset_size) < 0)
9479 return AVERROR_INVALIDDATA;
9480 57 extent_count = avio_rb16(pb);
9481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (extent_count > 1) {
9482 // For still AVIF images, we only support one extent item.
9483 avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
9484 return AVERROR_PATCHWELCOME;
9485 }
9486
9487
2/4
✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 57 times.
✗ Branch 4 not taken.
114 if (rb_size(pb, &extent_offset, offset_size) < 0 ||
9488 57 rb_size(pb, &extent_length, length_size) < 0 ||
9489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 base_offset > INT64_MAX - extent_offset)
9490 return AVERROR_INVALIDDATA;
9491
9492
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 for (j = 0; j < c->nb_heif_item; j++) {
9493 140 item = c->heif_item[j];
9494
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 83 times.
140 if (!item)
9495 57 item = c->heif_item[j] = av_mallocz(sizeof(*item));
9496
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
83 else if (item->item_id != item_id)
9497 83 continue;
9498 57 break;
9499 }
9500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item)
9501 return AVERROR(ENOMEM);
9502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (j == c->nb_heif_item)
9503 return AVERROR_INVALIDDATA;
9504
9505 57 item->item_id = item_id;
9506
9507
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 48 times.
57 if (offset_type == 1)
9508 9 item->is_idat_relative = 1;
9509 57 item->extent_length = extent_length;
9510 57 item->extent_offset = base_offset + extent_offset;
9511 57 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, item->item_id %d, offset_type %d, "
9512 "extent_offset %"PRId64", extent_length %"PRId64"\n",
9513 i, item->item_id, offset_type, item->extent_offset, item->extent_length);
9514 }
9515
9516 18 c->found_iloc = 1;
9517 18 return atom.size;
9518 }
9519
9520 57 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9521 {
9522 57 HEIFItem *item = NULL;
9523 AVBPrint item_name;
9524 57 int64_t size = atom.size;
9525 uint32_t item_type;
9526 int item_id;
9527 int i, version, ret;
9528
9529 57 version = avio_r8(pb);
9530 57 avio_rb24(pb); // flags.
9531 57 size -= 4;
9532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (size < 0)
9533 return AVERROR_INVALIDDATA;
9534
9535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (version < 2) {
9536 avpriv_report_missing_feature(c->fc, "infe version < 2");
9537 avio_skip(pb, size);
9538 return 1;
9539 }
9540
9541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
9542 57 avio_rb16(pb); // item_protection_index
9543 57 item_type = avio_rl32(pb);
9544 57 size -= 8;
9545
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (size < 1)
9546 return AVERROR_INVALIDDATA;
9547
9548 57 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
9549 57 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
9550
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (ret < 0) {
9551 av_bprint_finalize(&item_name, NULL);
9552 return ret;
9553 }
9554
9555 57 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
9556 57 item_id, av_fourcc2str(item_type), item_name.str);
9557
9558 57 size -= ret + 1;
9559
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 55 times.
57 if (size > 0)
9560 2 avio_skip(pb, size);
9561
9562
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 for (i = 0; i < c->nb_heif_item; i++) {
9563 140 item = c->heif_item[i];
9564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (!item)
9565 item = c->heif_item[i] = av_mallocz(sizeof(*item));
9566
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 57 times.
140 else if (item->item_id != item_id)
9567 83 continue;
9568 57 break;
9569 }
9570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item) {
9571 av_bprint_finalize(&item_name, NULL);
9572 return AVERROR(ENOMEM);
9573 }
9574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (i == c->nb_heif_item) {
9575 av_bprint_finalize(&item_name, NULL);
9576 return AVERROR_INVALIDDATA;
9577 }
9578
9579 57 av_freep(&item->name);
9580
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 1 times.
57 av_bprint_finalize(&item_name, ret ? &item->name : NULL);
9581 57 item->item_id = item_id;
9582 57 item->type = item_type;
9583
9584
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 14 times.
57 switch (item_type) {
9585 43 case MKTAG('a','v','0','1'):
9586 case MKTAG('j','p','e','g'):
9587 case MKTAG('h','v','c','1'):
9588 43 ret = heif_add_stream(c, item);
9589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
9590 return ret;
9591 43 break;
9592 }
9593
9594 57 return 0;
9595 }
9596
9597 18 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9598 {
9599 HEIFItem **heif_item;
9600 int entry_count;
9601 18 int version, got_stream = 0, ret, i;
9602
9603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->found_iinf) {
9604 av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
9605 return 0;
9606 }
9607
9608 18 version = avio_r8(pb);
9609 18 avio_rb24(pb); // flags.
9610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
9611
9612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (entry_count > atom.size)
9613 return AVERROR_INVALIDDATA;
9614
9615 18 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
9616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!heif_item)
9617 return AVERROR(ENOMEM);
9618 18 c->heif_item = heif_item;
9619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (entry_count > c->nb_heif_item)
9620 memset(&c->heif_item[c->nb_heif_item], 0,
9621 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
9622 18 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
9623
9624
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (i = 0; i < entry_count; i++) {
9625 MOVAtom infe;
9626
9627 57 infe.size = avio_rb32(pb) - 8;
9628 57 infe.type = avio_rl32(pb);
9629
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (avio_feof(pb)) {
9630 ret = AVERROR_INVALIDDATA;
9631 goto fail;
9632 }
9633 57 ret = mov_read_infe(c, pb, infe);
9634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (ret < 0)
9635 goto fail;
9636
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 if (!ret)
9637 57 got_stream = 1;
9638 }
9639
9640 18 c->found_iinf = got_stream;
9641 18 return 0;
9642 fail:
9643 for (; i >= 0; i--) {
9644 HEIFItem *item = c->heif_item[i];
9645
9646 if (!item)
9647 continue;
9648
9649 av_freep(&item->name);
9650 }
9651 return ret;
9652 }
9653
9654 9 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
9655 {
9656 9 HEIFItem *item = NULL;
9657 HEIFGrid *grid;
9658 int entries, i;
9659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9660 9 int ret = 0;
9661
9662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 for (int i = 0; i < c->nb_heif_grid; i++) {
9663 if (c->heif_grid[i].item->item_id == from_item_id) {
9664 av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
9665 "referencing the same Derived Image item\n");
9666 return AVERROR_INVALIDDATA;
9667 }
9668 }
9669
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 for (int i = 0; i < c->nb_heif_item; i++) {
9670
3/4
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 9 times.
35 if (!c->heif_item[i] || c->heif_item[i]->item_id != from_item_id)
9671 26 continue;
9672 9 item = c->heif_item[i];
9673
9674
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 switch (item->type) {
9675 9 case MKTAG('g','r','i','d'):
9676 case MKTAG('i','o','v','l'):
9677 9 break;
9678 default:
9679 avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
9680 av_fourcc2str(item->type));
9681 return 0;
9682 }
9683 9 break;
9684 }
9685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!item) {
9686 av_log(c->fc, AV_LOG_ERROR, "Missing grid information\n");
9687 return AVERROR_INVALIDDATA;
9688 }
9689
9690 9 entries = avio_rb16(pb);
9691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!entries) {
9692 av_log(c->fc, AV_LOG_ERROR,
9693 "Derived image item references no input images\n");
9694 return AVERROR_INVALIDDATA;
9695 }
9696
9697 9 grid = av_realloc_array(c->heif_grid, c->nb_heif_grid + 1U,
9698 sizeof(*c->heif_grid));
9699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!grid)
9700 return AVERROR(ENOMEM);
9701 9 c->heif_grid = grid;
9702 9 grid = &grid[c->nb_heif_grid];
9703
9704 9 grid->tile_id_list = av_malloc_array(entries, sizeof(*grid->tile_id_list));
9705 9 grid->tile_idx_list = av_calloc(entries, sizeof(*grid->tile_idx_list));
9706 9 grid->tile_item_list = av_calloc(entries, sizeof(*grid->tile_item_list));
9707
3/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
9 if (!grid->tile_id_list || !grid->tile_item_list || !grid->tile_idx_list) {
9708 ret = AVERROR(ENOMEM);
9709 goto fail;
9710 }
9711 /* 'to' item ids */
9712
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9 times.
37 for (i = 0; i < entries; i++) {
9713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 grid->tile_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
9714
9715
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if (avio_feof(pb)) {
9716 ret = AVERROR_INVALIDDATA;
9717 goto fail;
9718 }
9719 }
9720
9721 9 grid->nb_tiles = entries;
9722 9 grid->item = item;
9723 9 ++c->nb_heif_grid;
9724
9725 9 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
9726 from_item_id, entries);
9727
9728 9 return 0;
9729 fail:
9730 av_freep(&grid->tile_id_list);
9731 av_freep(&grid->tile_idx_list);
9732 av_freep(&grid->tile_item_list);
9733
9734 return ret;
9735 }
9736
9737 11 static int mov_read_iref_cdsc(MOVContext *c, AVIOContext *pb, uint32_t type, int version, uint32_t size)
9738 {
9739 11 HEIFItem *from_item = NULL;
9740 int entries;
9741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 int item_id_size = version ? 4 : 2;
9742
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9743 11 const HEIFItemRef ref = { type, from_item_id };
9744
9745 11 from_item = get_heif_item(c, from_item_id);
9746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!from_item) {
9747 av_log(c->fc, AV_LOG_ERROR, "Missing stream referenced by thmb item\n");
9748 return AVERROR_INVALIDDATA;
9749 }
9750
9751 11 entries = avio_rb16(pb);
9752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if ((int64_t)entries * item_id_size > (int64_t)size - item_id_size - 2) {
9753 av_log(c->fc, AV_LOG_ERROR, "iref %s entry count %d exceeds the sub-box size\n",
9754 av_fourcc2str(type), entries);
9755 return AVERROR_INVALIDDATA;
9756 }
9757 /* 'to' item ids */
9758
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (int i = 0; i < entries; i++) {
9759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 HEIFItem *item = get_heif_item(c, version ? avio_rb32(pb) : avio_rb16(pb));
9760
9761
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (avio_feof(pb))
9762 return AVERROR_INVALIDDATA;
9763
9764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!item) {
9765 av_log(c->fc, AV_LOG_WARNING, "Missing stream referenced by %s item\n",
9766 av_fourcc2str(type));
9767 continue;
9768 }
9769
9770
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (!av_dynarray2_add((void **)&item->iref_list, &item->nb_iref_list,
9771 sizeof(*item->iref_list), (const uint8_t *)&ref))
9772 return AVERROR(ENOMEM);
9773 }
9774
9775 11 av_log(c->fc, AV_LOG_TRACE, "%s: from_item_id %d, entries %d\n",
9776 11 av_fourcc2str(type), from_item_id, entries);
9777
9778 11 return 0;
9779 }
9780
9781 14 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9782 {
9783 14 int version = avio_r8(pb);
9784 int ret;
9785
9786 14 avio_rb24(pb); // flags
9787 14 atom.size -= 4;
9788
9789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (version > 1) {
9790 av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
9791 return 0;
9792 }
9793
9794
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 14 times.
34 while (atom.size) {
9795 20 int64_t next = avio_tell(pb);
9796 20 uint32_t type, size = avio_rb32(pb);
9797
9798
3/6
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
20 if (size < 14 || size > atom.size || next > INT64_MAX - size)
9799 return AVERROR_INVALIDDATA;
9800
9801 20 next += size;
9802 20 type = avio_rl32(pb);
9803
2/3
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
20 switch (type) {
9804 9 case MKTAG('d','i','m','g'):
9805 9 ret = mov_read_iref_dimg(c, pb, version);
9806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret < 0)
9807 return ret;
9808 20 break;
9809 11 case MKTAG('c','d','s','c'):
9810 case MKTAG('t','h','m','b'):
9811 11 ret = mov_read_iref_cdsc(c, pb, type, version, size - 8);
9812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0)
9813 return ret;
9814 11 break;
9815 default:
9816 av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
9817 av_fourcc2str(type), size);
9818 }
9819
9820 20 atom.size -= size;
9821 20 avio_seek(pb, next, SEEK_SET);
9822 }
9823 14 return 0;
9824 }
9825
9826 52 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9827 {
9828 HEIFItem *item;
9829 uint32_t width, height;
9830
9831 52 avio_r8(pb); /* version */
9832 52 avio_rb24(pb); /* flags */
9833 52 width = avio_rb32(pb);
9834 52 height = avio_rb32(pb);
9835
9836 52 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %"PRIu32", height %"PRIu32"\n",
9837 c->cur_item_id, width, height);
9838
9839
4/8
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 52 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 52 times.
52 if (!width || !height || width > INT_MAX || height > INT_MAX) {
9840 av_log(c->fc, AV_LOG_ERROR, "Invalid ispe dimensions %"PRIu32"x%"PRIu32"\n",
9841 width, height);
9842 return AVERROR_INVALIDDATA;
9843 }
9844
9845 52 item = get_heif_item(c, c->cur_item_id);
9846
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 if (item) {
9847 52 item->width = width;
9848 52 item->height = height;
9849 }
9850
9851 52 return 0;
9852 }
9853
9854 8 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9855 {
9856 HEIFItem *item;
9857 int angle;
9858
9859 8 angle = avio_r8(pb) & 0x3;
9860
9861 8 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
9862 c->cur_item_id, angle);
9863
9864 8 item = get_heif_item(c, c->cur_item_id);
9865
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (item) {
9866 // angle * 90 specifies the angle (in anti-clockwise direction)
9867 // in units of degrees.
9868 8 item->rotation = angle * 90;
9869 }
9870
9871 8 return 0;
9872 }
9873
9874 6 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9875 {
9876 HEIFItem *item;
9877 int axis;
9878
9879 6 axis = avio_r8(pb) & 0x1;
9880
9881 6 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
9882 c->cur_item_id, axis);
9883
9884 6 item = get_heif_item(c, c->cur_item_id);
9885
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
9886 6 item->hflip = axis;
9887 6 item->vflip = !axis;
9888 }
9889
9890 6 return 0;
9891 }
9892
9893 18 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9894 {
9895 typedef struct MOVAtoms {
9896 FFIOContext b;
9897 uint32_t type;
9898 int64_t size;
9899 uint8_t *data;
9900 } MOVAtoms;
9901 18 MOVAtoms *atoms = NULL;
9902 MOVAtom a;
9903 unsigned count;
9904 18 int nb_atoms = 0;
9905 int version, flags;
9906 int ret;
9907
9908 18 a.size = avio_rb32(pb);
9909 18 a.type = avio_rl32(pb);
9910
9911
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (a.size < 8 || a.type != MKTAG('i','p','c','o'))
9912 return AVERROR_INVALIDDATA;
9913
9914 18 a.size -= 8;
9915
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 while (a.size >= 8) {
9916 80 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
9917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!ref) {
9918 ret = AVERROR(ENOMEM);
9919 goto fail;
9920 }
9921 80 ref->data = NULL;
9922 80 ref->size = avio_rb32(pb);
9923 80 ref->type = avio_rl32(pb);
9924
2/4
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
80 if (ref->size > a.size || ref->size < 8)
9925 break;
9926 80 ref->data = av_malloc(ref->size);
9927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!ref->data) {
9928 ret = AVERROR_INVALIDDATA;
9929 goto fail;
9930 }
9931 80 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
9932 80 avio_seek(pb, -8, SEEK_CUR);
9933
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
80 if (avio_read(pb, ref->data, ref->size) != ref->size) {
9934 ret = AVERROR_INVALIDDATA;
9935 goto fail;
9936 }
9937 80 ffio_init_read_context(&ref->b, ref->data, ref->size);
9938 80 a.size -= ref->size;
9939 }
9940
9941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (a.size) {
9942 ret = AVERROR_INVALIDDATA;
9943 goto fail;
9944 }
9945
9946 18 a.size = avio_rb32(pb);
9947 18 a.type = avio_rl32(pb);
9948
9949
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (a.size < 8 || a.type != MKTAG('i','p','m','a')) {
9950 ret = AVERROR_INVALIDDATA;
9951 goto fail;
9952 }
9953
9954 18 version = avio_r8(pb);
9955 18 flags = avio_rb24(pb);
9956 18 count = avio_rb32(pb);
9957
9958
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 18 times.
70 for (int i = 0; i < count; i++) {
9959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9960 52 int assoc_count = avio_r8(pb);
9961
9962
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
52 if (avio_feof(pb)) {
9963 ret = AVERROR_INVALIDDATA;
9964 goto fail;
9965 }
9966
9967
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 52 times.
177 for (int j = 0; j < assoc_count; j++) {
9968 MOVAtoms *ref;
9969 125 int index = avio_r8(pb) & 0x7f;
9970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 if (flags & 1) {
9971 index <<= 8;
9972 index |= avio_r8(pb);
9973 }
9974
2/4
✓ Branch 0 taken 125 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 125 times.
125 if (index > nb_atoms || index <= 0) {
9975 ret = AVERROR_INVALIDDATA;
9976 goto fail;
9977 }
9978 125 ref = &atoms[--index];
9979
9980 125 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
9981 125 index + 1, item_id, av_fourcc2str(ref->type));
9982
9983 125 c->cur_item_id = item_id;
9984
9985 125 ret = mov_read_default(c, &ref->b.pub,
9986 125 (MOVAtom) { .size = ref->size,
9987 .type = MKTAG('i','p','c','o') });
9988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 if (ret < 0)
9989 goto fail;
9990 125 ffio_init_read_context(&ref->b, ref->data, ref->size);
9991 }
9992 }
9993
9994 18 ret = 0;
9995 18 fail:
9996 18 c->cur_item_id = -1;
9997
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 for (int i = 0; i < nb_atoms; i++)
9998 80 av_free(atoms[i].data);
9999 18 av_free(atoms);
10000
10001 18 return ret;
10002 }
10003
10004 static const MOVParseTableEntry mov_default_parse_table[] = {
10005 { MKTAG('A','C','L','R'), mov_read_aclr },
10006 { MKTAG('A','P','R','G'), mov_read_avid },
10007 { MKTAG('A','A','L','P'), mov_read_avid },
10008 { MKTAG('A','R','E','S'), mov_read_ares },
10009 { MKTAG('a','v','s','s'), mov_read_avss },
10010 { MKTAG('a','v','1','C'), mov_read_glbl },
10011 { MKTAG('c','h','p','l'), mov_read_chpl },
10012 { MKTAG('c','o','6','4'), mov_read_stco },
10013 { MKTAG('c','o','l','r'), mov_read_colr },
10014 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
10015 { MKTAG('d','i','n','f'), mov_read_default },
10016 { MKTAG('D','p','x','E'), mov_read_dpxe },
10017 { MKTAG('d','r','e','f'), mov_read_dref },
10018 { MKTAG('e','d','t','s'), mov_read_default },
10019 { MKTAG('e','l','s','t'), mov_read_elst },
10020 { MKTAG('e','n','d','a'), mov_read_enda },
10021 { MKTAG('f','i','e','l'), mov_read_fiel },
10022 { MKTAG('a','d','r','m'), mov_read_adrm },
10023 { MKTAG('f','t','y','p'), mov_read_ftyp },
10024 { MKTAG('g','l','b','l'), mov_read_glbl },
10025 { MKTAG('h','d','l','r'), mov_read_hdlr },
10026 { MKTAG('i','l','s','t'), mov_read_ilst },
10027 { MKTAG('j','p','2','h'), mov_read_jp2h },
10028 { MKTAG('m','d','a','t'), mov_read_mdat },
10029 { MKTAG('m','d','h','d'), mov_read_mdhd },
10030 { MKTAG('m','d','i','a'), mov_read_default },
10031 { MKTAG('m','e','t','a'), mov_read_meta },
10032 { MKTAG('m','i','n','f'), mov_read_default },
10033 { MKTAG('m','o','o','f'), mov_read_moof },
10034 { MKTAG('m','o','o','v'), mov_read_moov },
10035 { MKTAG('m','v','e','x'), mov_read_default },
10036 { MKTAG('m','v','h','d'), mov_read_mvhd },
10037 { MKTAG('S','M','I',' '), mov_read_svq3 },
10038 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
10039 { MKTAG('a','v','c','C'), mov_read_glbl },
10040 { MKTAG('p','a','s','p'), mov_read_pasp },
10041 { MKTAG('c','l','a','p'), mov_read_clap },
10042 { MKTAG('c','d','s','c'), mov_read_cdsc_rndr },
10043 { MKTAG('r','n','d','r'), mov_read_cdsc_rndr },
10044 { MKTAG('s','b','a','s'), mov_read_sbas },
10045 { MKTAG('v','d','e','p'), mov_read_vdep },
10046 { MKTAG('s','i','d','x'), mov_read_sidx },
10047 { MKTAG('s','t','b','l'), mov_read_default },
10048 { MKTAG('s','t','c','o'), mov_read_stco },
10049 { MKTAG('s','t','p','s'), mov_read_stps },
10050 { MKTAG('s','t','r','f'), mov_read_strf },
10051 { MKTAG('s','t','s','c'), mov_read_stsc },
10052 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
10053 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
10054 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
10055 { MKTAG('s','t','t','s'), mov_read_stts },
10056 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
10057 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
10058 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
10059 { MKTAG('t','f','d','t'), mov_read_tfdt },
10060 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
10061 { MKTAG('t','r','a','k'), mov_read_trak },
10062 { MKTAG('t','r','a','f'), mov_read_default },
10063 { MKTAG('t','r','e','f'), mov_read_default },
10064 { MKTAG('t','m','c','d'), mov_read_tmcd },
10065 { MKTAG('c','h','a','p'), mov_read_chap },
10066 { MKTAG('t','r','e','x'), mov_read_trex },
10067 { MKTAG('t','r','u','n'), mov_read_trun },
10068 { MKTAG('u','d','t','a'), mov_read_default },
10069 { MKTAG('w','a','v','e'), mov_read_wave },
10070 { MKTAG('e','s','d','s'), mov_read_esds },
10071 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
10072 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
10073 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
10074 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
10075 { MKTAG('w','f','e','x'), mov_read_wfex },
10076 { MKTAG('c','m','o','v'), mov_read_cmov },
10077 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
10078 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
10079 { MKTAG('d','v','c','1'), mov_read_dvc1 },
10080 { MKTAG('s','g','p','d'), mov_read_sgpd },
10081 { MKTAG('s','b','g','p'), mov_read_sbgp },
10082 { MKTAG('h','v','c','C'), mov_read_glbl },
10083 { MKTAG('v','v','c','C'), mov_read_glbl },
10084 { MKTAG('u','u','i','d'), mov_read_uuid },
10085 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
10086 { MKTAG('f','r','e','e'), mov_read_free },
10087 { MKTAG('-','-','-','-'), mov_read_custom },
10088 { MKTAG('s','i','n','f'), mov_read_default },
10089 { MKTAG('f','r','m','a'), mov_read_frma },
10090 { MKTAG('s','e','n','c'), mov_read_senc },
10091 { MKTAG('s','a','i','z'), mov_read_saiz },
10092 { MKTAG('s','a','i','o'), mov_read_saio },
10093 { MKTAG('p','s','s','h'), mov_read_pssh },
10094 { MKTAG('s','c','h','m'), mov_read_schm },
10095 { MKTAG('s','c','h','i'), mov_read_default },
10096 { MKTAG('t','e','n','c'), mov_read_tenc },
10097 { MKTAG('d','f','L','a'), mov_read_dfla },
10098 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
10099 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
10100 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
10101 { MKTAG('h','f','o','v'), mov_read_hfov },
10102 { MKTAG('d','O','p','s'), mov_read_dops },
10103 { MKTAG('d','m','l','p'), mov_read_dmlp },
10104 { MKTAG('S','m','D','m'), mov_read_smdm },
10105 { MKTAG('C','o','L','L'), mov_read_coll },
10106 { MKTAG('v','p','c','C'), mov_read_vpcc },
10107 { MKTAG('m','d','c','v'), mov_read_mdcv },
10108 { MKTAG('c','l','l','i'), mov_read_clli },
10109 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
10110 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
10111 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
10112 { MKTAG('h','v','c','E'), mov_read_hvce },
10113 { MKTAG('k','i','n','d'), mov_read_kind },
10114 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
10115 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
10116 { MKTAG('i','l','o','c'), mov_read_iloc },
10117 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
10118 { MKTAG('p','i','t','m'), mov_read_pitm },
10119 { MKTAG('e','v','c','C'), mov_read_glbl },
10120 { MKTAG('i','d','a','t'), mov_read_idat },
10121 { MKTAG('i','m','i','r'), mov_read_imir },
10122 { MKTAG('i','r','e','f'), mov_read_iref },
10123 { MKTAG('i','s','p','e'), mov_read_ispe },
10124 { MKTAG('i','r','o','t'), mov_read_irot },
10125 { MKTAG('i','p','r','p'), mov_read_iprp },
10126 { MKTAG('i','i','n','f'), mov_read_iinf },
10127 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
10128 { MKTAG('l','h','v','C'), mov_read_lhvc },
10129 { MKTAG('l','v','c','C'), mov_read_glbl },
10130 { MKTAG('a','p','v','C'), mov_read_glbl },
10131 #if CONFIG_IAMFDEC
10132 { MKTAG('i','a','c','b'), mov_read_iacb },
10133 #endif
10134 { MKTAG('s','r','a','t'), mov_read_srat },
10135 { 0, NULL }
10136 };
10137
10138 7799 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10139 {
10140 7799 int64_t total_size = 0;
10141 MOVAtom a;
10142 int i;
10143
10144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7799 times.
7799 if (c->atom_depth > 10) {
10145 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
10146 return AVERROR_INVALIDDATA;
10147 }
10148 7799 c->atom_depth ++;
10149
10150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7799 times.
7799 if (atom.size < 0)
10151 atom.size = INT64_MAX;
10152
2/2
✓ Branch 0 taken 22218 times.
✓ Branch 1 taken 7208 times.
29426 while (total_size <= atom.size - 8) {
10153 22218 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
10154 22218 a.size = avio_rb32(pb);
10155 22218 a.type = avio_rl32(pb);
10156
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 22211 times.
22218 if (avio_feof(pb))
10157 7 break;
10158
3/4
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 21956 times.
✓ Branch 2 taken 255 times.
✗ Branch 3 not taken.
22211 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
10159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22211 times.
22211 a.type == MKTAG('h','o','o','v')) &&
10160 a.size >= 8 &&
10161 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
10162 uint32_t type;
10163 avio_skip(pb, 4);
10164 type = avio_rl32(pb);
10165 if (avio_feof(pb))
10166 break;
10167 avio_seek(pb, -8, SEEK_CUR);
10168 if (type == MKTAG('m','v','h','d') ||
10169 type == MKTAG('c','m','o','v')) {
10170 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
10171 a.type = MKTAG('m','o','o','v');
10172 }
10173 }
10174
2/2
✓ Branch 0 taken 18927 times.
✓ Branch 1 taken 3284 times.
22211 if (atom.type != MKTAG('r','o','o','t') &&
10175
2/2
✓ Branch 0 taken 17208 times.
✓ Branch 1 taken 1719 times.
18927 atom.type != MKTAG('m','o','o','v')) {
10176
1/2
✓ Branch 0 taken 17208 times.
✗ Branch 1 not taken.
17208 if (a.type == MKTAG('t','r','a','k') ||
10177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17208 times.
17208 a.type == MKTAG('m','d','a','t')) {
10178 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
10179 avio_skip(pb, -8);
10180 c->atom_depth --;
10181 584 return 0;
10182 }
10183 }
10184 22211 total_size += 8;
10185
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 22182 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
22211 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
10186 29 a.size = avio_rb64(pb) - 8;
10187 29 total_size += 8;
10188 }
10189 22211 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
10190 22211 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
10191
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 22206 times.
22211 if (a.size == 0) {
10192 5 a.size = atom.size - total_size + 8;
10193 }
10194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22211 times.
22211 if (a.size < 0)
10195 break;
10196 22211 a.size -= 8;
10197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22211 times.
22211 if (a.size < 0)
10198 break;
10199 22211 a.size = FFMIN(a.size, atom.size - total_size);
10200
10201
2/2
✓ Branch 0 taken 1061838 times.
✓ Branch 1 taken 2200 times.
1064038 for (i = 0; mov_default_parse_table[i].type; i++)
10202
2/2
✓ Branch 0 taken 20011 times.
✓ Branch 1 taken 1041827 times.
1061838 if (mov_default_parse_table[i].type == a.type) {
10203 20011 parse = mov_default_parse_table[i].parse;
10204 20011 break;
10205 }
10206
10207 // container is user data
10208
4/4
✓ Branch 0 taken 2200 times.
✓ Branch 1 taken 20011 times.
✓ Branch 2 taken 2021 times.
✓ Branch 3 taken 179 times.
22211 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
10209
2/2
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 1650 times.
2021 atom.type == MKTAG('i','l','s','t')))
10210 550 parse = mov_read_udta_string;
10211
10212 // Supports parsing the QuickTime Metadata Keys.
10213 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
10214
4/4
✓ Branch 0 taken 1650 times.
✓ Branch 1 taken 20561 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 1639 times.
22211 if (!parse && c->found_hdlr_mdta &&
10215
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 atom.type == MKTAG('m','e','t','a') &&
10216
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 a.type == MKTAG('k','e','y','s') &&
10217
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 c->meta_keys_count == 0) {
10218 11 parse = mov_read_keys;
10219 }
10220
10221
2/2
✓ Branch 0 taken 1639 times.
✓ Branch 1 taken 20572 times.
22211 if (!parse) { /* skip leaf atoms data */
10222 1639 avio_skip(pb, a.size);
10223 } else {
10224 20572 int64_t start_pos = avio_tell(pb);
10225 int64_t left;
10226 20572 int err = parse(c, pb, a);
10227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20572 times.
20572 if (err < 0) {
10228 c->atom_depth --;
10229 return err;
10230 }
10231
5/6
✓ Branch 0 taken 3860 times.
✓ Branch 1 taken 16712 times.
✓ Branch 2 taken 3445 times.
✓ Branch 3 taken 415 times.
✓ Branch 4 taken 3445 times.
✗ Branch 5 not taken.
20572 if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos &&
10232
7/8
✓ Branch 0 taken 3444 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3444 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3430 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 569 times.
✓ Branch 7 taken 2861 times.
6875 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
10233 3430 start_pos + a.size == avio_size(pb))) {
10234
5/6
✓ Branch 0 taken 583 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 583 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 569 times.
584 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
10235 15 c->next_root_atom = start_pos + a.size;
10236 584 c->atom_depth --;
10237 584 return 0;
10238 }
10239 19988 left = a.size - avio_tell(pb) + start_pos;
10240
2/2
✓ Branch 0 taken 1723 times.
✓ Branch 1 taken 18265 times.
19988 if (left > 0) /* skip garbage at atom end */
10241 1723 avio_skip(pb, left);
10242
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18263 times.
18265 else if (left < 0) {
10243 2 av_log(c->fc, AV_LOG_WARNING,
10244 "overread end of atom '%s' by %"PRId64" bytes\n",
10245 2 av_fourcc2str(a.type), -left);
10246 2 avio_seek(pb, left, SEEK_CUR);
10247 }
10248 }
10249
10250 21627 total_size += a.size;
10251 }
10252
10253
4/4
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 7106 times.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 7 times.
7215 if (total_size < atom.size && atom.size < 0x7ffff)
10254 102 avio_skip(pb, atom.size - total_size);
10255
10256 7215 c->atom_depth --;
10257 7215 return 0;
10258 }
10259
10260 8043 static int mov_probe(const AVProbeData *p)
10261 {
10262 int64_t offset;
10263 uint32_t tag;
10264 8043 int score = 0;
10265 8043 int moov_offset = -1;
10266
10267 /* check file header */
10268 8043 offset = 0;
10269 9926 for (;;) {
10270 int64_t size;
10271 17969 int minsize = 8;
10272 /* ignore invalid offset */
10273
2/2
✓ Branch 0 taken 8043 times.
✓ Branch 1 taken 9926 times.
17969 if ((offset + 8ULL) > (unsigned int)p->buf_size)
10274 8043 break;
10275 9926 size = AV_RB32(p->buf + offset);
10276
3/4
✓ Branch 0 taken 539 times.
✓ Branch 1 taken 9387 times.
✓ Branch 2 taken 539 times.
✗ Branch 3 not taken.
9926 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
10277 539 size = AV_RB64(p->buf+offset + 8);
10278 539 minsize = 16;
10279
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 9315 times.
9387 } else if (size == 0) {
10280 72 size = p->buf_size - offset;
10281 }
10282
2/2
✓ Branch 0 taken 410 times.
✓ Branch 1 taken 9516 times.
9926 if (size < minsize) {
10283 410 offset += 4;
10284 410 continue;
10285 }
10286 9516 tag = AV_RL32(p->buf + offset + 4);
10287
5/6
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 997 times.
✓ Branch 2 taken 427 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7938 times.
9516 switch(tag) {
10288 /* check for obvious tags */
10289 153 case MKTAG('m','o','o','v'):
10290 153 moov_offset = offset + 4;
10291 av_fallthrough;
10292 1150 case MKTAG('m','d','a','t'):
10293 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
10294 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
10295 case MKTAG('f','t','y','p'):
10296
2/2
✓ Branch 0 taken 515 times.
✓ Branch 1 taken 635 times.
1150 if (tag == MKTAG('f','t','y','p') &&
10297
1/2
✓ Branch 0 taken 515 times.
✗ Branch 1 not taken.
515 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
10298
1/2
✓ Branch 0 taken 515 times.
✗ Branch 1 not taken.
515 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
10299
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 508 times.
515 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
10300 )) {
10301 7 score = FFMAX(score, 5);
10302 } else {
10303 1143 score = AVPROBE_SCORE_MAX;
10304 }
10305 1150 break;
10306 /* those are more common words, so rate then a bit less */
10307 427 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
10308 case MKTAG('w','i','d','e'):
10309 case MKTAG('f','r','e','e'):
10310 case MKTAG('j','u','n','k'):
10311 case MKTAG('p','i','c','t'):
10312 427 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
10313 427 break;
10314 case MKTAG(0x82,0x82,0x7f,0x7d):
10315 score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
10316 break;
10317 1 case MKTAG('s','k','i','p'):
10318 case MKTAG('u','u','i','d'):
10319 case MKTAG('p','r','f','l'):
10320 /* if we only find those cause probedata is too small at least rate them */
10321 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
10322 1 break;
10323 }
10324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9516 times.
9516 if (size > INT64_MAX - offset)
10325 break;
10326 9516 offset += size;
10327 }
10328
4/4
✓ Branch 0 taken 562 times.
✓ Branch 1 taken 7481 times.
✓ Branch 2 taken 153 times.
✓ Branch 3 taken 409 times.
8043 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
10329 /* moov atom in the header - we should make sure that this is not a
10330 * MOV-packed MPEG-PS */
10331 153 offset = moov_offset;
10332
10333
2/2
✓ Branch 0 taken 149640 times.
✓ Branch 1 taken 153 times.
149793 while (offset < (p->buf_size - 16)) { /* Sufficient space */
10334 /* We found an actual hdlr atom */
10335
2/2
✓ Branch 0 taken 163 times.
✓ Branch 1 taken 149477 times.
149640 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
10336
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 141 times.
163 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
10337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
10338 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
10339 /* We found a media handler reference atom describing an
10340 * MPEG-PS-in-MOV, return a
10341 * low score to force expanding the probe window until
10342 * mpegps_probe finds what it needs */
10343 return 5;
10344 } else {
10345 /* Keep looking */
10346 149640 offset += 2;
10347 }
10348 }
10349 }
10350
10351 8043 return score;
10352 }
10353
10354 // must be done after parsing all trak because there's no order requirement
10355 2 static void mov_read_chapters(AVFormatContext *s)
10356 {
10357 2 MOVContext *mov = s->priv_data;
10358 MOVStreamContext *sc;
10359 int64_t cur_pos;
10360 int i, j;
10361 int chapter_track;
10362
10363
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
10364 2 AVStream *st = NULL;
10365 2 FFStream *sti = NULL;
10366 2 chapter_track = mov->chapter_tracks[j];
10367
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
10368 4 sc = mov->fc->streams[i]->priv_data;
10369
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
10370 2 st = s->streams[i];
10371 2 break;
10372 }
10373 }
10374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
10375 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
10376 continue;
10377 }
10378 2 sti = ffstream(st);
10379
10380 2 sc = st->priv_data;
10381 2 cur_pos = avio_tell(sc->pb);
10382
10383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
10384 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
10385 if (!st->attached_pic.data && sti->nb_index_entries) {
10386 // Retrieve the first frame, if possible
10387 AVIndexEntry *sample = &sti->index_entries[0];
10388 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10389 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
10390 goto finish;
10391 }
10392
10393 if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
10394 goto finish;
10395 }
10396 } else {
10397 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10398 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
10399 2 st->discard = AVDISCARD_ALL;
10400
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
10401 8 AVIndexEntry *sample = &sti->index_entries[i];
10402
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;
10403 uint8_t *title;
10404 uint16_t ch;
10405 int len, title_len;
10406
10407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
10408 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
10409 end = AV_NOPTS_VALUE;
10410 }
10411
10412
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10413 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
10414 goto finish;
10415 }
10416
10417 // the first two bytes are the length of the title
10418 8 len = avio_rb16(sc->pb);
10419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
10420 continue;
10421 8 title_len = 2*len + 1;
10422
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
10423 goto finish;
10424
10425 // The samples could theoretically be in any encoding if there's an encd
10426 // atom following, but in practice are only utf-8 or utf-16, distinguished
10427 // instead by the presence of a BOM
10428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
10429 title[0] = 0;
10430 } else {
10431 8 ch = avio_rb16(sc->pb);
10432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
10433 avio_get_str16be(sc->pb, len, title, title_len);
10434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
10435 avio_get_str16le(sc->pb, len, title, title_len);
10436 else {
10437 8 AV_WB16(title, ch);
10438
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)
10439 title[len] = 0;
10440 else
10441 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
10442 }
10443 }
10444
10445 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
10446 8 av_freep(&title);
10447 }
10448 }
10449 2 finish:
10450 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
10451 }
10452 2 }
10453
10454 19 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
10455 int64_t value, int flags)
10456 {
10457 AVTimecode tc;
10458 char buf[AV_TIMECODE_STR_SIZE];
10459 19 AVRational rate = st->avg_frame_rate;
10460 19 int ret = av_timecode_init(&tc, rate, flags, 0, s);
10461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
10462 return ret;
10463 19 av_dict_set(&st->metadata, "timecode",
10464 19 av_timecode_make_string(&tc, buf, value), 0);
10465 19 return 0;
10466 }
10467
10468 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
10469 {
10470 MOVStreamContext *sc = st->priv_data;
10471 FFStream *const sti = ffstream(st);
10472 char buf[AV_TIMECODE_STR_SIZE];
10473 int64_t cur_pos = avio_tell(sc->pb);
10474 int hh, mm, ss, ff, drop;
10475
10476 if (!sti->nb_index_entries)
10477 return -1;
10478
10479 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10480 avio_skip(s->pb, 13);
10481 hh = avio_r8(s->pb);
10482 mm = avio_r8(s->pb);
10483 ss = avio_r8(s->pb);
10484 drop = avio_r8(s->pb);
10485 ff = avio_r8(s->pb);
10486 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
10487 hh, mm, ss, drop ? ';' : ':', ff);
10488 av_dict_set(&st->metadata, "timecode", buf, 0);
10489
10490 avio_seek(sc->pb, cur_pos, SEEK_SET);
10491 return 0;
10492 }
10493
10494 19 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
10495 {
10496 19 MOVStreamContext *sc = st->priv_data;
10497 19 FFStream *const sti = ffstream(st);
10498 19 int flags = 0;
10499 19 int64_t cur_pos = avio_tell(sc->pb);
10500 int64_t value;
10501 19 AVRational tc_rate = st->avg_frame_rate;
10502 19 int tmcd_nb_frames = sc->tmcd_nb_frames;
10503 int rounded_tc_rate;
10504
10505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!sti->nb_index_entries)
10506 return -1;
10507
10508
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)
10509 return -1;
10510
10511 19 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10512 19 value = avio_rb32(s->pb);
10513
10514
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 10 times.
19 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
10515
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
10516
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
10517
10518 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
10519 * not the case) and thus assume "frame number format" instead of QT one.
10520 * No sample with tmcd track can be found with a QT timecode at the moment,
10521 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
10522 * format). */
10523
10524 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
10525 * we multiply the frame number with the quotient.
10526 * See tickets #9492, #9710. */
10527 19 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
10528 /* Work around files where tmcd_nb_frames is rounded down from frame rate
10529 * instead of up. See ticket #5978. */
10530
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
10531
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
10532 10 tmcd_nb_frames = rounded_tc_rate;
10533 19 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
10534
10535 19 parse_timecode_in_framenum_format(s, st, value, flags);
10536
10537 19 avio_seek(sc->pb, cur_pos, SEEK_SET);
10538 19 return 0;
10539 }
10540
10541 1352 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
10542 int i;
10543
3/4
✓ Branch 0 taken 1352 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1339 times.
✓ Branch 3 taken 13 times.
1352 if (!index || !*index) return;
10544
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 13 times.
208 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
10545 195 av_encryption_info_free((*index)->encrypted_samples[i]);
10546 }
10547 13 av_freep(&(*index)->encrypted_samples);
10548 13 av_freep(&(*index)->auxiliary_info_sizes);
10549 13 av_freep(&(*index)->auxiliary_offsets);
10550 13 av_freep(index);
10551 }
10552
10553 823 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
10554 {
10555 823 MOVStreamContext *sc = st->priv_data;
10556
10557
3/4
✓ Branch 0 taken 823 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 771 times.
823 if (!sc || --sc->refcount) {
10558 52 st->priv_data = NULL;
10559 52 return;
10560 }
10561
10562 771 av_freep(&sc->tts_data);
10563
2/2
✓ Branch 0 taken 712 times.
✓ Branch 1 taken 771 times.
1483 for (int i = 0; i < sc->drefs_count; i++) {
10564 712 av_freep(&sc->drefs[i].path);
10565 712 av_freep(&sc->drefs[i].dir);
10566 }
10567 771 av_freep(&sc->drefs);
10568
10569 771 sc->drefs_count = 0;
10570
10571
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 755 times.
771 if (!sc->pb_is_copied)
10572 16 ff_format_io_close(s, &sc->pb);
10573
10574 771 sc->pb = NULL;
10575 771 av_freep(&sc->chunk_offsets);
10576 771 av_freep(&sc->stsc_data);
10577 771 av_freep(&sc->sample_sizes);
10578 771 av_freep(&sc->keyframes);
10579 771 av_freep(&sc->ctts_data);
10580 771 av_freep(&sc->stts_data);
10581 771 av_freep(&sc->sdtp_data);
10582 771 av_freep(&sc->stps_data);
10583 771 av_freep(&sc->elst_data);
10584 771 av_freep(&sc->rap_group);
10585 771 av_freep(&sc->sync_group);
10586 771 av_freep(&sc->sgpd_sync);
10587 771 av_freep(&sc->sample_offsets);
10588 771 av_freep(&sc->open_key_samples);
10589 771 av_freep(&sc->display_matrix);
10590 771 av_freep(&sc->index_ranges);
10591
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 771 times.
800 for (int i = 0; i < sc->nb_tref_tags; i++)
10592 29 av_freep(&sc->tref_tags[i].id);
10593 771 av_freep(&sc->tref_tags);
10594
10595
2/2
✓ Branch 0 taken 712 times.
✓ Branch 1 taken 59 times.
771 if (sc->extradata)
10596
2/2
✓ Branch 0 taken 729 times.
✓ Branch 1 taken 712 times.
1441 for (int i = 0; i < sc->stsd_count; i++)
10597 729 av_free(sc->extradata[i]);
10598 771 av_freep(&sc->extradata);
10599 771 av_freep(&sc->extradata_size);
10600
10601 771 mov_free_encryption_index(&sc->cenc.encryption_index);
10602 771 av_encryption_info_free(sc->cenc.default_encrypted_sample);
10603 771 av_aes_ctr_free(sc->cenc.aes_ctr);
10604
10605 771 av_freep(&sc->stereo3d);
10606 771 av_freep(&sc->spherical);
10607 771 av_freep(&sc->mastering);
10608 771 av_freep(&sc->coll);
10609 771 av_freep(&sc->ambient);
10610
10611 #if CONFIG_IAMFDEC
10612
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 759 times.
771 if (sc->iamf)
10613 12 ff_iamf_read_deinit(sc->iamf);
10614 #endif
10615 771 av_freep(&sc->iamf);
10616 }
10617
10618 608 static int mov_read_close(AVFormatContext *s)
10619 {
10620 608 MOVContext *mov = s->priv_data;
10621 int i, j;
10622
10623
2/2
✓ Branch 0 taken 823 times.
✓ Branch 1 taken 608 times.
1431 for (i = 0; i < s->nb_streams; i++) {
10624 823 AVStream *st = s->streams[i];
10625
10626 823 mov_free_stream_context(s, st);
10627 }
10628
10629 608 av_freep(&mov->dv_demux);
10630 608 avformat_free_context(mov->dv_fctx);
10631 608 mov->dv_fctx = NULL;
10632
10633
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 597 times.
608 if (mov->meta_keys) {
10634
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i < mov->meta_keys_count; i++) {
10635 58 av_freep(&mov->meta_keys[i]);
10636 }
10637 11 av_freep(&mov->meta_keys);
10638 }
10639
10640 608 av_freep(&mov->trex_data);
10641 608 av_freep(&mov->bitrates);
10642
10643
2/2
✓ Branch 0 taken 479 times.
✓ Branch 1 taken 608 times.
1087 for (i = 0; i < mov->frag_index.nb_items; i++) {
10644 479 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
10645
2/2
✓ Branch 0 taken 581 times.
✓ Branch 1 taken 479 times.
1060 for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) {
10646 581 mov_free_encryption_index(&frag[j].encryption_index);
10647 }
10648 479 av_freep(&mov->frag_index.item[i].stream_info);
10649 }
10650 608 av_freep(&mov->frag_index.item);
10651
10652 608 av_freep(&mov->aes_decrypt);
10653 608 av_freep(&mov->chapter_tracks);
10654
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 608 times.
665 for (i = 0; i < mov->nb_heif_item; i++) {
10655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!mov->heif_item[i])
10656 continue;
10657 57 av_freep(&mov->heif_item[i]->name);
10658 57 av_freep(&mov->heif_item[i]->iref_list);
10659 57 av_freep(&mov->heif_item[i]->icc_profile);
10660 57 av_freep(&mov->heif_item[i]);
10661 }
10662 608 av_freep(&mov->heif_item);
10663
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 608 times.
617 for (i = 0; i < mov->nb_heif_grid; i++) {
10664 9 av_freep(&mov->heif_grid[i].tile_id_list);
10665 9 av_freep(&mov->heif_grid[i].tile_idx_list);
10666 9 av_freep(&mov->heif_grid[i].tile_item_list);
10667 }
10668 608 av_freep(&mov->heif_grid);
10669
10670 608 return 0;
10671 }
10672
10673 19 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
10674 {
10675 int i;
10676
10677
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 for (i = 0; i < s->nb_streams; i++) {
10678 19 AVStream *st = s->streams[i];
10679 19 MOVStreamContext *sc = st->priv_data;
10680 19 MovTref *tag = mov_find_tref_tag(sc, MKTAG('t','m','c','d'));
10681
10682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!tag)
10683 continue;
10684
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 if (mov_find_tref_id(tag, tmcd_id))
10685 19 return 1;
10686 }
10687 return 0;
10688 }
10689
10690 /* look for a tmcd track not referenced by any video track, and export it globally */
10691 608 static void export_orphan_timecode(AVFormatContext *s)
10692 {
10693 int i;
10694
10695
2/2
✓ Branch 0 taken 823 times.
✓ Branch 1 taken 608 times.
1431 for (i = 0; i < s->nb_streams; i++) {
10696 823 AVStream *st = s->streams[i];
10697
10698
3/4
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 804 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
842 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
10699 19 !tmcd_is_referenced(s, st->id)) {
10700 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
10701 if (tcr) {
10702 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
10703 break;
10704 }
10705 }
10706 }
10707 608 }
10708
10709 3 static int read_tfra(MOVContext *mov, AVIOContext *f)
10710 {
10711 int version, fieldlength, i, j;
10712 3 int64_t pos = avio_tell(f);
10713 3 uint32_t size = avio_rb32(f);
10714 unsigned track_id, item_count;
10715
10716
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
10717 1 return 1;
10718 }
10719 2 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
10720
10721 2 version = avio_r8(f);
10722 2 avio_rb24(f);
10723 2 track_id = avio_rb32(f);
10724 2 fieldlength = avio_rb32(f);
10725 2 item_count = avio_rb32(f);
10726
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (i = 0; i < item_count; i++) {
10727 int64_t time, offset;
10728 int index;
10729 MOVFragmentStreamInfo * frag_stream_info;
10730
10731
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (avio_feof(f)) {
10732 return AVERROR_INVALIDDATA;
10733 }
10734
10735
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1) {
10736 time = avio_rb64(f);
10737 offset = avio_rb64(f);
10738 } else {
10739 6 time = avio_rb32(f);
10740 6 offset = avio_rb32(f);
10741 }
10742
10743 // The first sample of each stream in a fragment is always a random
10744 // access sample. So it's entry in the tfra can be used as the
10745 // initial PTS of the fragment.
10746 6 index = update_frag_index(mov, offset);
10747 6 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
10748
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (frag_stream_info &&
10749
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
10750 6 frag_stream_info->first_tfra_pts = time;
10751
10752
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
10753 6 avio_r8(f);
10754
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
10755 6 avio_r8(f);
10756
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
10757 6 avio_r8(f);
10758 }
10759
10760 2 avio_seek(f, pos + size, SEEK_SET);
10761 2 return 0;
10762 }
10763
10764 1 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
10765 {
10766 1 int64_t stream_size = avio_size(f);
10767 1 int64_t original_pos = avio_tell(f);
10768 int64_t seek_ret;
10769 1 int ret = -1;
10770
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
10771 ret = seek_ret;
10772 goto fail;
10773 }
10774 1 c->mfra_size = avio_rb32(f);
10775 1 c->have_read_mfra_size = 1;
10776
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!c->mfra_size || c->mfra_size > stream_size) {
10777 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
10778 goto fail;
10779 }
10780
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((seek_ret = avio_seek(f, -((int64_t) c->mfra_size), SEEK_CUR)) < 0) {
10781 ret = seek_ret;
10782 goto fail;
10783 }
10784
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != c->mfra_size) {
10785 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
10786 goto fail;
10787 }
10788
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
10789 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
10790 goto fail;
10791 }
10792 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
10793 do {
10794 3 ret = read_tfra(c, f);
10795
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
10796 goto fail;
10797
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 } while (!ret);
10798 1 ret = 0;
10799 1 c->frag_index.complete = 1;
10800 1 fail:
10801 1 seek_ret = avio_seek(f, original_pos, SEEK_SET);
10802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (seek_ret < 0) {
10803 av_log(c->fc, AV_LOG_ERROR,
10804 "failed to seek back after looking for mfra\n");
10805 ret = seek_ret;
10806 }
10807 1 return ret;
10808 }
10809
10810 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10811 const HEIFItem *item)
10812 {
10813 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
10814 AV_PKT_DATA_ICC_PROFILE,
10815 item->icc_profile_size, 0);
10816 if (!sd)
10817 return AVERROR(ENOMEM);
10818
10819 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
10820
10821 return 0;
10822 }
10823
10824 6 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10825 const HEIFItem *item)
10826 {
10827 int32_t *matrix;
10828 6 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data,
10829 nb_coded_side_data,
10830 AV_PKT_DATA_DISPLAYMATRIX,
10831 9 * sizeof(*matrix), 0);
10832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sd)
10833 return AVERROR(ENOMEM);
10834
10835 6 matrix = (int32_t*)sd->data;
10836 /* rotation is in the counter-clockwise direction whereas
10837 * av_display_rotation_set() expects its argument to be
10838 * oriented clockwise, so we need to negate it. */
10839 6 av_display_rotation_set(matrix, -item->rotation);
10840 6 av_display_matrix_flip(matrix, item->hflip, item->vflip);
10841
10842 6 return 0;
10843 }
10844
10845 5 static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid,
10846 AVStreamGroupTileGrid *tile_grid)
10847 {
10848 5 MOVContext *c = s->priv_data;
10849 5 const HEIFItem *item = grid->item;
10850 5 int64_t coded_width = 0, coded_height = 0;
10851 5 int64_t offset = 0, pos = avio_tell(s->pb);
10852 5 int64_t x = 0, y = 0;
10853 5 int i = 0;
10854 int tile_rows, tile_cols;
10855 int flags, size;
10856
10857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10858 av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
10859 return AVERROR_PATCHWELCOME;
10860 }
10861
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (item->is_idat_relative) {
10862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!c->idat_offset) {
10863 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
10864 return AVERROR_INVALIDDATA;
10865 }
10866 5 offset = c->idat_offset;
10867 }
10868
10869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (offset > INT64_MAX - item->extent_offset)
10870 return AVERROR_INVALIDDATA;
10871
10872 5 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10873
10874 5 avio_r8(s->pb); /* version */
10875 5 flags = avio_r8(s->pb);
10876
10877 5 tile_rows = avio_r8(s->pb) + 1;
10878 5 tile_cols = avio_r8(s->pb) + 1;
10879 /* actual width and height of output image */
10880
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 tile_grid->width = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
10881
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 tile_grid->height = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
10882
10883 5 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
10884 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
10885
10886 5 avio_seek(s->pb, pos, SEEK_SET);
10887
10888 5 size = tile_rows * tile_cols;
10889 5 tile_grid->nb_tiles = grid->nb_tiles;
10890
10891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (tile_grid->nb_tiles != size)
10892 return AVERROR_INVALIDDATA;
10893
10894
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < tile_cols; i++)
10895 10 coded_width += grid->tile_item_list[i]->width;
10896
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < size; i += tile_cols)
10897 10 coded_height += grid->tile_item_list[i]->height;
10898
10899
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (coded_width > INT_MAX || coded_height > INT_MAX)
10900 return AVERROR_INVALIDDATA;
10901
10902 5 tile_grid->coded_width = coded_width;
10903 5 tile_grid->coded_height = coded_height;
10904
10905 5 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!tile_grid->offsets)
10907 return AVERROR(ENOMEM);
10908
10909
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 while (y < tile_grid->coded_height) {
10910 10 int left_col = i;
10911
10912
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 while (x < tile_grid->coded_width) {
10913
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (i == tile_grid->nb_tiles)
10914 return AVERROR_INVALIDDATA;
10915
10916 20 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10917 20 tile_grid->offsets[i].horizontal = x;
10918 20 tile_grid->offsets[i].vertical = y;
10919
10920 20 x += grid->tile_item_list[i++]->width;
10921 }
10922
10923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (x > tile_grid->coded_width) {
10924 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10925 return AVERROR_INVALIDDATA;
10926 }
10927
10928 10 x = 0;
10929 10 y += grid->tile_item_list[left_col]->height;
10930 }
10931
10932
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (y > tile_grid->coded_height || i != tile_grid->nb_tiles) {
10933 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10934 return AVERROR_INVALIDDATA;
10935 }
10936
10937 5 return 0;
10938 }
10939
10940 4 static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid,
10941 AVStreamGroupTileGrid *tile_grid)
10942 {
10943 4 MOVContext *c = s->priv_data;
10944 4 const HEIFItem *item = grid->item;
10945 uint16_t canvas_fill_value[4];
10946 4 int64_t offset = 0, pos = avio_tell(s->pb);
10947 4 int ret = 0, flags;
10948
10949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10950 av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
10951 return AVERROR_PATCHWELCOME;
10952 }
10953
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
10954
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
10955 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
10956 return AVERROR_INVALIDDATA;
10957 }
10958 4 offset = c->idat_offset;
10959 }
10960
10961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (offset > INT64_MAX - item->extent_offset)
10962 return AVERROR_INVALIDDATA;
10963
10964 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10965
10966 4 avio_r8(s->pb); /* version */
10967 4 flags = avio_r8(s->pb);
10968
10969
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10970 16 canvas_fill_value[i] = avio_rb16(s->pb);
10971 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
10972 4 canvas_fill_value[0], canvas_fill_value[1],
10973 4 canvas_fill_value[2], canvas_fill_value[3]);
10974
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10975 16 tile_grid->background[i] = canvas_fill_value[i];
10976
10977 /* actual width and height of output image */
10978 4 tile_grid->width =
10979
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);
10980 4 tile_grid->height =
10981
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);
10982
10983 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
10984 tile_grid->width, tile_grid->height);
10985
10986 4 tile_grid->nb_tiles = grid->nb_tiles;
10987 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
10989 ret = AVERROR(ENOMEM);
10990 goto fail;
10991 }
10992
10993
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
10994 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10995
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);
10996
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);
10997 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
10998 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
10999 8 i, tile_grid->offsets[i].idx,
11000 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
11001 }
11002
11003 4 fail:
11004 4 avio_seek(s->pb, pos, SEEK_SET);
11005
11006 4 return ret;
11007 }
11008
11009 2 static int mov_parse_exif_item(AVFormatContext *s,
11010 AVPacketSideData **coded_side_data, int *nb_coded_side_data,
11011 const HEIFItem *ref)
11012 {
11013 2 MOVContext *c = s->priv_data;
11014 AVPacketSideData *sd;
11015 2 AVExifMetadata ifd = { 0 };
11016 AVBufferRef *buf;
11017 2 int64_t offset = 0, pos = avio_tell(s->pb);
11018 2 unsigned orientation_id = av_exif_get_tag_id("Orientation");
11019 int err;
11020
11021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11022 av_log(c->fc, AV_LOG_WARNING, "Exif metadata with non seekable input\n");
11023 return AVERROR_PATCHWELCOME;
11024 }
11025
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ref->is_idat_relative) {
11026 if (!c->idat_offset) {
11027 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the Exif metadata\n");
11028 return AVERROR_INVALIDDATA;
11029 }
11030 offset = c->idat_offset;
11031 }
11032
11033 2 buf = av_buffer_alloc(ref->extent_length);
11034
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!buf)
11035 return AVERROR(ENOMEM);
11036
11037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset > INT64_MAX - ref->extent_offset) {
11038 err = AVERROR(ENOMEM);
11039 goto fail;
11040 }
11041
11042 2 avio_seek(s->pb, ref->extent_offset + offset, SEEK_SET);
11043 2 err = avio_read(s->pb, buf->data, ref->extent_length);
11044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != ref->extent_length) {
11045 if (err > 0)
11046 err = AVERROR_INVALIDDATA;
11047 goto fail;
11048 }
11049
11050 // HEIF spec states that Exif metadata is informative. The irot item property is
11051 // the normative source of rotation information. So we remove any Orientation tag
11052 // present in the Exif buffer.
11053 2 err = av_exif_parse_buffer(s, buf->data, ref->extent_length, &ifd, AV_EXIF_T_OFF);
11054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0) {
11055 av_log(s, AV_LOG_ERROR, "Unable to parse Exif metadata\n");
11056 goto fail;
11057 }
11058
11059 2 err = av_exif_remove_entry(s, &ifd, orientation_id, 0);
11060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11061 goto fail;
11062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (!err)
11063 goto finish;
11064
11065 2 av_buffer_unref(&buf);
11066 2 err = av_exif_write(s, &ifd, &buf, AV_EXIF_T_OFF);
11067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11068 goto fail;
11069
11070 2 finish:
11071 2 offset = AV_RB32(buf->data) + 4;
11072
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset >= buf->size) {
11073 err = AVERROR_INVALIDDATA;
11074 goto fail;
11075 }
11076 2 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
11077 2 AV_PKT_DATA_EXIF, buf->size - offset, 0);
11078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!sd) {
11079 err = AVERROR(ENOMEM);
11080 goto fail;
11081 }
11082 2 memcpy(sd->data, buf->data + offset, buf->size - offset);
11083
11084 2 err = 0;
11085 2 fail:
11086 2 av_buffer_unref(&buf);
11087 2 av_exif_free(&ifd);
11088 2 avio_seek(s->pb, pos, SEEK_SET);
11089
11090 2 return err;
11091 }
11092
11093 9 static int mov_parse_tiles(AVFormatContext *s)
11094 {
11095 9 MOVContext *mov = s->priv_data;
11096
11097
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for (int i = 0; i < mov->nb_heif_grid; i++) {
11098 9 AVStreamGroup *stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
11099 AVStreamGroupTileGrid *tile_grid;
11100 9 const HEIFGrid *grid = &mov->heif_grid[i];
11101 9 int err, loop = 1;
11102
11103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!stg)
11104 return AVERROR(ENOMEM);
11105
11106 9 stg->id = grid->item->item_id;
11107 9 tile_grid = stg->params.tile_grid;
11108
11109
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9 times.
37 for (int j = 0; j < grid->nb_tiles; j++) {
11110 28 int tile_id = grid->tile_id_list[j];
11111 int k;
11112
11113
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 for (k = 0; k < mov->nb_heif_item; k++) {
11114 60 HEIFItem *item = mov->heif_item[k];
11115 AVStream *st;
11116
11117
3/4
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 28 times.
60 if (!item || item->item_id != tile_id)
11118 32 continue;
11119 28 st = item->st;
11120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!st) {
11121 av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
11122 "reference a stream\n",
11123 tile_id, grid->item->item_id);
11124 ff_remove_stream_group(s, stg);
11125 loop = 0;
11126 break;
11127 }
11128
11129 28 grid->tile_item_list[j] = item;
11130 28 grid->tile_idx_list[j] = stg->nb_streams;
11131
11132 28 err = avformat_stream_group_add_stream(stg, st);
11133
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 26 times.
28 if (err < 0) {
11134 int l;
11135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
11136 return err;
11137
11138
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_streams; l++)
11139
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->streams[l]->index == st->index)
11140 2 break;
11141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_streams);
11142 2 grid->tile_idx_list[j] = l;
11143 }
11144
11145
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 6 times.
28 if (item->item_id != mov->primary_item_id)
11146 22 st->disposition |= AV_DISPOSITION_DEPENDENT;
11147 28 break;
11148 }
11149
11150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (k == mov->nb_heif_item) {
11151 av_assert0(loop);
11152 av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
11153 "exist\n",
11154 tile_id, grid->item->item_id);
11155 ff_remove_stream_group(s, stg);
11156 loop = 0;
11157 }
11158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!loop)
11159 break;
11160 }
11161
11162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!loop)
11163 continue;
11164
11165
2/3
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
9 switch (grid->item->type) {
11166 5 case MKTAG('g','r','i','d'):
11167 5 err = read_image_grid(s, grid, tile_grid);
11168 5 break;
11169 4 case MKTAG('i','o','v','l'):
11170 4 err = read_image_iovl(s, grid, tile_grid);
11171 4 break;
11172 default:
11173 av_assert0(0);
11174 }
11175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err < 0)
11176 return err;
11177
11178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 for (int j = 0; j < grid->item->nb_iref_list; j++) {
11179 HEIFItem *ref = get_heif_item(mov, grid->item->iref_list[j].item_id);
11180
11181 av_assert0(ref);
11182 switch(ref->type) {
11183 case MKTAG('E','x','i','f'):
11184 err = mov_parse_exif_item(s, &tile_grid->coded_side_data,
11185 &tile_grid->nb_coded_side_data, ref);
11186 if (err < 0 && (s->error_recognition & AV_EF_EXPLODE))
11187 return err;
11188 break;
11189 default:
11190 break;
11191 }
11192 }
11193
11194 /* rotation */
11195
3/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
9 if (grid->item->rotation || grid->item->hflip || grid->item->vflip) {
11196 err = set_display_matrix_from_item(&tile_grid->coded_side_data,
11197 &tile_grid->nb_coded_side_data, grid->item);
11198 if (err < 0)
11199 return err;
11200 }
11201
11202 /* ICC profile */
11203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (grid->item->icc_profile_size) {
11204 err = set_icc_profile_from_item(&tile_grid->coded_side_data,
11205 &tile_grid->nb_coded_side_data, grid->item);
11206 if (err < 0)
11207 return err;
11208 }
11209
11210
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (grid->item->name)
11211 9 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
11212
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 if (grid->item->item_id == mov->primary_item_id)
11213 5 stg->disposition |= AV_DISPOSITION_DEFAULT;
11214 }
11215
11216 9 return 0;
11217 }
11218
11219 18 static int mov_parse_heif_items(AVFormatContext *s)
11220 {
11221 18 MOVContext *mov = s->priv_data;
11222 int err;
11223
11224
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (int i = 0; i < mov->nb_heif_item; i++) {
11225 57 HEIFItem *item = mov->heif_item[i];
11226 MOVStreamContext *sc;
11227 AVStream *st;
11228 57 int64_t offset = 0;
11229
11230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item)
11231 continue;
11232
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 43 times.
57 if (!item->st) {
11233 14 continue;
11234 }
11235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (item->is_idat_relative) {
11236 if (!mov->idat_offset) {
11237 av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
11238 return AVERROR_INVALIDDATA;
11239 }
11240 offset = mov->idat_offset;
11241 }
11242
11243 43 st = item->st;
11244 43 sc = st->priv_data;
11245 43 st->codecpar->width = item->width;
11246 43 st->codecpar->height = item->height;
11247
11248 43 sc->sample_size = sc->stsz_sample_size = item->extent_length;
11249 43 sc->sample_count = 1;
11250
11251 43 err = sanity_checks(s, sc, st->index);
11252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (err)
11253 return AVERROR_INVALIDDATA;
11254
11255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (offset > INT64_MAX - item->extent_offset)
11256 return AVERROR_INVALIDDATA;
11257
11258 43 sc->chunk_offsets[0] = item->extent_offset + offset;
11259
11260
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 30 times.
43 if (item->item_id == mov->primary_item_id)
11261 13 st->disposition |= AV_DISPOSITION_DEFAULT;
11262
11263
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 43 times.
54 for (int j = 0; j < item->nb_iref_list; j++) {
11264 11 HEIFItem *ref = get_heif_item(mov, item->iref_list[j].item_id);
11265
11266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 av_assert0(ref);
11267
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 switch(ref->type) {
11268 2 case MKTAG('E','x','i','f'):
11269 2 err = mov_parse_exif_item(s, &st->codecpar->coded_side_data,
11270 2 &st->codecpar->nb_coded_side_data, ref);
11271
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (err < 0 && (s->error_recognition & AV_EF_EXPLODE))
11272 return err;
11273 2 break;
11274 9 default:
11275 9 break;
11276 }
11277 }
11278
11279
4/6
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 37 times.
43 if (item->rotation || item->hflip || item->vflip) {
11280 6 err = set_display_matrix_from_item(&st->codecpar->coded_side_data,
11281 6 &st->codecpar->nb_coded_side_data, item);
11282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
11283 return err;
11284 }
11285
11286 43 mov_build_index(mov, st);
11287 }
11288
11289
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (mov->nb_heif_grid) {
11290 9 err = mov_parse_tiles(s);
11291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err < 0)
11292 return err;
11293 }
11294
11295 18 return 0;
11296 }
11297
11298 608 static int mov_parse_tmcd_streams(AVFormatContext *s)
11299 {
11300 int err;
11301
11302
2/2
✓ Branch 0 taken 823 times.
✓ Branch 1 taken 608 times.
1431 for (int i = 0; i < s->nb_streams; i++) {
11303 AVStreamGroup *stg;
11304 const AVDictionaryEntry *tcr;
11305 823 AVStream *st = s->streams[i];
11306
11307
2/2
✓ Branch 0 taken 804 times.
✓ Branch 1 taken 19 times.
823 if (st->codecpar->codec_tag != MKTAG('t','m','c','d'))
11308 804 continue;
11309
11310 19 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TREF, NULL);
11311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!stg)
11312 return AVERROR(ENOMEM);
11313
11314 19 stg->id = st->id;
11315 19 tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
11316
11317
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 19 times.
80 for (int j = 0; j < s->nb_streams; j++) {
11318 61 AVStream *st2 = s->streams[j];
11319 61 MOVStreamContext *sc2 = st2->priv_data;
11320 61 MovTref *tag = mov_find_tref_tag(sc2, MKTAG('t','m','c','d'));
11321
11322
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 20 times.
61 if (!tag)
11323 41 continue;
11324
11325
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 20 times.
52 for (int k = 0; k < tag->nb_id; k++) {
11326
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 20 times.
32 if (tag->id[k] != st->id)
11327 12 continue;
11328
11329 20 err = avformat_stream_group_add_stream(stg, st2);
11330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (err < 0)
11331 return err;
11332
11333
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (tcr)
11334 20 av_dict_set(&st2->metadata, "timecode", tcr->value, AV_DICT_DONT_OVERWRITE);
11335 }
11336 }
11337
11338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!stg->nb_streams) {
11339 ff_remove_stream_group(s, stg);
11340 continue;
11341 }
11342
11343 19 err = avformat_stream_group_add_stream(stg, st);
11344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (err < 0)
11345 return err;
11346
11347 19 stg->params.tref->metadata_index = stg->nb_streams - 1;
11348 }
11349 608 export_orphan_timecode(s);
11350
11351 608 return 0;
11352 }
11353
11354 11 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
11355 uint32_t *tref_id, int nb_tref_id, int first_index)
11356 {
11357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!nb_tref_id)
11358 return NULL;
11359
11360
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 for (int i = first_index; i < s->nb_streams; i++)
11361
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 for (int j = 0; j < nb_tref_id; j++)
11362
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (s->streams[i]->index != st->index &&
11363
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 s->streams[i]->id == tref_id[j])
11364 11 return s->streams[i];
11365
11366 return NULL;
11367 }
11368
11369 608 static int mov_parse_cdsc_and_rndr_streams(AVFormatContext *s)
11370 {
11371 static const uint32_t tref_tags[] = {
11372 MKTAG('c','d','s','c'),
11373 MKTAG('r','n','d','r'),
11374 };
11375
11376 int err;
11377
11378 // Don't try to add a group if there's only one track
11379
2/2
✓ Branch 0 taken 492 times.
✓ Branch 1 taken 116 times.
608 if (s->nb_streams <= 1)
11380 492 return 0;
11381
11382
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 116 times.
447 for (int i = 0; i < s->nb_streams; i++) {
11383 331 AVStream *st = s->streams[i];
11384 331 MOVStreamContext *sc = st->priv_data;
11385
11386
2/2
✓ Branch 0 taken 662 times.
✓ Branch 1 taken 331 times.
993 for (int c = 0; c < FF_ARRAY_ELEMS(tref_tags); c++) {
11387 AVStreamGroup *stg;
11388 AVStream *st_ref;
11389 662 MovTref *tag = mov_find_tref_tag(sc, tref_tags[c]);
11390
11391
2/2
✓ Branch 0 taken 651 times.
✓ Branch 1 taken 11 times.
662 if (!tag)
11392 651 continue;
11393
11394 11 st_ref = mov_find_reference_track(s, st, tag->id, tag->nb_id, 0);
11395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!st_ref) {
11396 av_log(s, AV_LOG_WARNING, "Failed to find referenced stream\n");
11397 continue;
11398 }
11399
11400 11 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TREF, NULL);
11401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!stg)
11402 return AVERROR(ENOMEM);
11403
11404 11 stg->id = st_ref->id;
11405
11406 11 err = avformat_stream_group_add_stream(stg, st_ref);
11407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11408 return err;
11409
11410 11 err = avformat_stream_group_add_stream(stg, st);
11411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11412 return err;
11413
11414 11 stg->params.tref->metadata_index = stg->nb_streams - 1;
11415 }
11416 }
11417
11418 116 return 0;
11419 }
11420
11421 608 static int mov_parse_lcevc_streams(AVFormatContext *s)
11422 {
11423 int err;
11424
11425 // Don't try to add a group if there's only one track
11426
2/2
✓ Branch 0 taken 492 times.
✓ Branch 1 taken 116 times.
608 if (s->nb_streams <= 1)
11427 492 return 0;
11428
11429
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 116 times.
447 for (int i = 0; i < s->nb_streams; i++) {
11430 AVStreamGroup *stg;
11431 331 AVStream *st = s->streams[i];
11432 AVStream *st_base;
11433 331 MOVStreamContext *sc = st->priv_data;
11434 331 MovTref *tag = mov_find_tref_tag(sc, MKTAG('s','b','a','s'));
11435 331 int j = 0;
11436
11437 /* Find an enhancement stream. */
11438
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 331 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
331 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC || !tag)
11439 331 continue;
11440
11441 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
11442 if (!stg)
11443 return AVERROR(ENOMEM);
11444
11445 stg->id = st->id;
11446 stg->params.layered_video->width = st->codecpar->width;
11447 stg->params.layered_video->height = st->codecpar->height;
11448
11449 while (st_base = mov_find_reference_track(s, st, tag->id, tag->nb_id, j)) {
11450 err = avformat_stream_group_add_stream(stg, st_base);
11451 if (err < 0)
11452 return err;
11453
11454 j = st_base->index + 1;
11455 }
11456 if (!j) {
11457 int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
11458 av_log(s, loglevel, "Failed to find base stream for LCEVC stream\n");
11459 ff_remove_stream_group(s, stg);
11460 if (s->error_recognition & AV_EF_EXPLODE)
11461 return AVERROR_INVALIDDATA;
11462 continue;
11463 }
11464
11465 err = avformat_stream_group_add_stream(stg, st);
11466 if (err < 0)
11467 return err;
11468
11469 stg->params.layered_video->el_index = stg->nb_streams - 1;
11470 }
11471
11472 116 return 0;
11473 }
11474
11475 608 static int mov_parse_dovi_streams(AVFormatContext *s)
11476 {
11477 int err;
11478
11479
2/2
✓ Branch 0 taken 492 times.
✓ Branch 1 taken 116 times.
608 if (s->nb_streams <= 1)
11480 492 return 0;
11481
11482 /* Identify legacy dual-track Dolby Vision profile 7 carriage per Annex
11483 * C of "Dolby Vision Streams Within the ISO Base Media File Format",
11484 * v2.7.1. The 'vdep' track reference type is shared with depth video
11485 * and multi-view dependencies. The spec-mandated DV-specific sample
11486 * entry combined with the dvcC configuration record disambiguates
11487 * those uses. */
11488
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 116 times.
447 for (int i = 0; i < s->nb_streams; i++) {
11489 AVStreamGroup *stg;
11490 331 AVStream *st = s->streams[i];
11491 AVStream *st_base;
11492 331 MOVStreamContext *sc = st->priv_data;
11493 331 MovTref *tag = mov_find_tref_tag(sc, MKTAG('v','d','e','p'));
11494 const AVPacketSideData *sd;
11495 const AVDOVIDecoderConfigurationRecord *dovi;
11496
11497
3/4
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 289 times.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
331 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !tag)
11498 331 continue;
11499
11500 if (st->codecpar->codec_tag != MKTAG('d','v','h','e') &&
11501 st->codecpar->codec_tag != MKTAG('d','v','h','1'))
11502 continue;
11503
11504 sd = av_packet_side_data_get(st->codecpar->coded_side_data,
11505 st->codecpar->nb_coded_side_data,
11506 AV_PKT_DATA_DOVI_CONF);
11507 if (!sd)
11508 continue;
11509 dovi = (const AVDOVIDecoderConfigurationRecord *)sd->data;
11510
11511 /* EL track of a dual-track stream: rpu_present_flag = 1,
11512 * el_present_flag = 1, bl_present_flag = 0, dv_profile = 7. */
11513 if (dovi->dv_profile != 7 || !dovi->rpu_present_flag ||
11514 !dovi->el_present_flag || dovi->bl_present_flag)
11515 continue;
11516
11517 st_base = mov_find_reference_track(s, st, tag->id, tag->nb_id, 0);
11518 if (!st_base) {
11519 int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
11520 av_log(s, loglevel, "Failed to find base layer for Dolby Vision EL stream\n");
11521 if (s->error_recognition & AV_EF_EXPLODE)
11522 return AVERROR_INVALIDDATA;
11523 continue;
11524 }
11525
11526 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_DOLBY_VISION, NULL);
11527 if (!stg)
11528 return AVERROR(ENOMEM);
11529
11530 stg->id = st->id;
11531
11532 err = avformat_stream_group_add_stream(stg, st_base);
11533 if (err < 0)
11534 return err;
11535
11536 err = avformat_stream_group_add_stream(stg, st);
11537 if (err < 0)
11538 return err;
11539
11540 stg->params.layered_video->el_index = stg->nb_streams - 1;
11541 stg->params.layered_video->width = st_base->codecpar->width;
11542 stg->params.layered_video->height = st_base->codecpar->height;
11543 }
11544
11545 116 return 0;
11546 }
11547
11548 608 static void fix_stream_ids(AVFormatContext *s)
11549 {
11550 608 int highest_id = 0, lowest_iamf_id = INT_MAX;
11551
11552
2/2
✓ Branch 0 taken 823 times.
✓ Branch 1 taken 608 times.
1431 for (int i = 0; i < s->nb_streams; i++) {
11553 823 const AVStream *st = s->streams[i];
11554 823 const MOVStreamContext *sc = st->priv_data;
11555
2/2
✓ Branch 0 taken 759 times.
✓ Branch 1 taken 64 times.
823 if (!sc->iamf)
11556 759 highest_id = FFMAX(highest_id, st->id);
11557 }
11558
11559
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 608 times.
671 for (int i = 0; i < s->nb_stream_groups; i++) {
11560 63 AVStreamGroup *stg = s->stream_groups[i];
11561
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 12 times.
63 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
11562 51 continue;
11563
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_streams; j++) {
11564 64 AVStream *st = stg->streams[j];
11565 64 lowest_iamf_id = FFMIN(lowest_iamf_id, st->id);
11566 }
11567 }
11568
11569
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 8 times.
608 if (highest_id < lowest_iamf_id)
11570 600 return;
11571
11572 8 highest_id += !lowest_iamf_id;
11573
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
12 for (int i = 0; highest_id > 1 && i < s->nb_stream_groups; i++) {
11574 4 AVStreamGroup *stg = s->stream_groups[i];
11575
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
11576 2 continue;
11577
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_streams; j++) {
11578 14 AVStream *st = stg->streams[j];
11579 14 MOVStreamContext *sc = st->priv_data;
11580 14 st->id += highest_id;
11581 14 sc->iamf_stream_offset = highest_id;
11582 }
11583 }
11584 }
11585
11586 608 static int mov_read_header(AVFormatContext *s)
11587 {
11588 608 MOVContext *mov = s->priv_data;
11589 608 AVIOContext *pb = s->pb;
11590 int j, err;
11591 608 MOVAtom atom = { AV_RL32("root") };
11592 int i;
11593
11594 608 mov->fc = s;
11595 608 mov->trak_index = -1;
11596 608 mov->primary_item_id = -1;
11597 608 mov->cur_item_id = -1;
11598 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
11599
2/2
✓ Branch 0 taken 607 times.
✓ Branch 1 taken 1 times.
608 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
11600 607 atom.size = avio_size(pb);
11601 else
11602 1 atom.size = INT64_MAX;
11603
11604 /* check MOV header */
11605 do {
11606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if (mov->moov_retry)
11607 avio_seek(pb, 0, SEEK_SET);
11608
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 608 times.
608 if ((err = mov_read_default(mov, pb, atom)) < 0) {
11609 av_log(s, AV_LOG_ERROR, "error reading header\n");
11610 return err;
11611 }
11612 1215 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
11613
6/10
✓ Branch 0 taken 607 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 589 times.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
608 !mov->found_moov && (!mov->found_iloc || !mov->found_iinf) && !mov->moov_retry++);
11614
3/6
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 590 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
608 if (!mov->found_moov && !mov->found_iloc && !mov->found_iinf) {
11615 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
11616 return AVERROR_INVALIDDATA;
11617 }
11618 608 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
11619
11620
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 590 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
608 if (mov->found_iloc && mov->found_iinf) {
11621 18 err = mov_parse_heif_items(s);
11622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (err < 0)
11623 return err;
11624 }
11625 // prevent iloc and iinf boxes from being parsed while reading packets.
11626 // this is needed because an iinf box may have been parsed but ignored
11627 // for having old infe boxes which create no streams.
11628 608 mov->found_iloc = mov->found_iinf = 1;
11629
11630
2/2
✓ Branch 0 taken 607 times.
✓ Branch 1 taken 1 times.
608 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
11631
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 605 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
607 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
11632 2 mov_read_chapters(s);
11633
2/2
✓ Branch 0 taken 822 times.
✓ Branch 1 taken 607 times.
1429 for (i = 0; i < s->nb_streams; i++)
11634
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 803 times.
822 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
11635 19 mov_read_timecode_track(s, s->streams[i]);
11636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 803 times.
803 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
11637 mov_read_rtmd_track(s, s->streams[i]);
11638 }
11639 }
11640
11641 /* Create metadata stream groups. */
11642 608 err = mov_parse_cdsc_and_rndr_streams(s);
11643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if (err < 0)
11644 return err;
11645
11646 /* copy timecode metadata from tmcd tracks to the related video streams */
11647 608 err = mov_parse_tmcd_streams(s);
11648
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if (err < 0)
11649 return err;
11650
11651 /* Create LCEVC stream groups. */
11652 608 err = mov_parse_lcevc_streams(s);
11653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if (err < 0)
11654 return err;
11655
11656 /* Create Dolby Vision Profile 7 stream groups. */
11657 608 err = mov_parse_dovi_streams(s);
11658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if (err < 0)
11659 return err;
11660
11661
2/2
✓ Branch 0 taken 823 times.
✓ Branch 1 taken 608 times.
1431 for (i = 0; i < s->nb_streams; i++) {
11662 823 AVStream *st = s->streams[i];
11663 823 FFStream *const sti = ffstream(st);
11664 823 MOVStreamContext *sc = st->priv_data;
11665 823 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
11666 823 fix_timescale(mov, sc);
11667
11668 /* Set the primary extradata based on the first Sample if it doesn't reference the first stsd entry. */
11669
6/6
✓ Branch 0 taken 777 times.
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 734 times.
✓ Branch 3 taken 43 times.
✓ Branch 4 taken 670 times.
✓ Branch 5 taken 64 times.
823 if (sc->stsc_count && sc->extradata_size && !sc->iamf &&
11670
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 667 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
670 sc->stsc_data[0].id > 1 && sc->stsc_data[0].id <= sc->stsd_count) {
11671 3 sc->last_stsd_index = sc->stsc_data[0].id - 1;
11672 3 av_freep(&st->codecpar->extradata);
11673 3 st->codecpar->extradata_size = sc->extradata_size[sc->last_stsd_index];
11674
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (sc->extradata_size[sc->last_stsd_index]) {
11675 3 st->codecpar->extradata = av_mallocz(sc->extradata_size[sc->last_stsd_index] + AV_INPUT_BUFFER_PADDING_SIZE);
11676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata)
11677 return AVERROR(ENOMEM);
11678 3 memcpy(st->codecpar->extradata, sc->extradata[sc->last_stsd_index], sc->extradata_size[sc->last_stsd_index]);
11679 }
11680 }
11681
11682
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 485 times.
823 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
11683
2/2
✓ Branch 0 taken 151 times.
✓ Branch 1 taken 187 times.
338 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
11684 151 sti->skip_samples = st->codecpar->initial_padding;
11685 }
11686
5/6
✓ Branch 0 taken 428 times.
✓ Branch 1 taken 395 times.
✓ Branch 2 taken 369 times.
✓ Branch 3 taken 59 times.
✓ Branch 4 taken 369 times.
✗ Branch 5 not taken.
823 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
11687 369 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
11688 369 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
11689
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 811 times.
823 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
11690
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
12 if (st->codecpar->width <= 0 || st->codecpar->height <= 0) {
11691 8 st->codecpar->width = sc->width;
11692 8 st->codecpar->height = sc->height;
11693 }
11694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
11695 st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
11696
11697 for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
11698 dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
11699
11700 err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
11701 if (err < 0)
11702 return err;
11703
11704 av_freep(&st->codecpar->extradata);
11705 st->codecpar->extradata_size = 0;
11706
11707 err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
11708 st->codecpar);
11709 if (err < 0)
11710 return err;
11711 }
11712 }
11713
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 822 times.
823 if (mov->handbrake_version &&
11714
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
11715 st->codecpar->codec_id == AV_CODEC_ID_MP3) {
11716 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
11717 sti->need_parsing = AVSTREAM_PARSE_FULL;
11718 }
11719 }
11720
11721
3/4
✓ Branch 0 taken 588 times.
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 588 times.
608 if (mov->trex_data || mov->use_mfra_for > 0) {
11722
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 20 times.
49 for (i = 0; i < s->nb_streams; i++) {
11723 29 AVStream *st = s->streams[i];
11724 29 MOVStreamContext *sc = st->priv_data;
11725
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 4 times.
29 if (sc->duration_for_fps > 0) {
11726 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
11727 25 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
11728
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (st->codecpar->bit_rate == INT64_MIN) {
11729 av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
11730 sc->data_size, sc->time_scale);
11731 st->codecpar->bit_rate = 0;
11732 if (s->error_recognition & AV_EF_EXPLODE)
11733 return AVERROR_INVALIDDATA;
11734 }
11735 }
11736 }
11737 }
11738
11739
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
608 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
11740 if (mov->bitrates[i]) {
11741 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
11742 }
11743 }
11744
11745 608 ff_rfps_calculate(s);
11746
11747
2/2
✓ Branch 0 taken 823 times.
✓ Branch 1 taken 608 times.
1431 for (i = 0; i < s->nb_streams; i++) {
11748 823 AVStream *st = s->streams[i];
11749 823 MOVStreamContext *sc = st->priv_data;
11750
11751
3/3
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 428 times.
✓ Branch 2 taken 57 times.
823 switch (st->codecpar->codec_type) {
11752 338 case AVMEDIA_TYPE_AUDIO:
11753 338 err = ff_replaygain_export(st, s->metadata);
11754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
338 if (err < 0)
11755 return err;
11756 338 break;
11757 428 case AVMEDIA_TYPE_VIDEO:
11758
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 420 times.
428 if (sc->display_matrix) {
11759
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,
11760 AV_PKT_DATA_DISPLAYMATRIX,
11761 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
11762 return AVERROR(ENOMEM);
11763
11764 8 sc->display_matrix = NULL;
11765 }
11766
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 422 times.
428 if (sc->stereo3d) {
11767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11768 AV_PKT_DATA_STEREO3D,
11769 6 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
11770 return AVERROR(ENOMEM);
11771
11772 6 sc->stereo3d = NULL;
11773 }
11774
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 424 times.
428 if (sc->spherical) {
11775
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,
11776 AV_PKT_DATA_SPHERICAL,
11777 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
11778 return AVERROR(ENOMEM);
11779
11780 4 sc->spherical = NULL;
11781 }
11782
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 428 times.
428 if (sc->mastering) {
11783 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11784 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
11785 (uint8_t *)sc->mastering, sc->mastering_size, 0))
11786 return AVERROR(ENOMEM);
11787
11788 sc->mastering = NULL;
11789 }
11790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 428 times.
428 if (sc->coll) {
11791 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11792 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
11793 (uint8_t *)sc->coll, sc->coll_size, 0))
11794 return AVERROR(ENOMEM);
11795
11796 sc->coll = NULL;
11797 }
11798
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 424 times.
428 if (sc->ambient) {
11799
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,
11800 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
11801 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
11802 return AVERROR(ENOMEM);
11803
11804 4 sc->ambient = NULL;
11805 }
11806 428 break;
11807 }
11808 }
11809
11810 608 fix_stream_ids(s);
11811
11812 608 ff_configure_buffers_for_index(s, AV_TIME_BASE);
11813
11814
2/2
✓ Branch 0 taken 479 times.
✓ Branch 1 taken 608 times.
1087 for (i = 0; i < mov->frag_index.nb_items; i++)
11815
2/2
✓ Branch 0 taken 469 times.
✓ Branch 1 taken 10 times.
479 if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset)
11816 469 mov->frag_index.item[i].headers_read = 1;
11817
11818 608 return 0;
11819 }
11820
11821 117898 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
11822 {
11823 117898 AVIndexEntry *sample = NULL;
11824 117898 int64_t best_dts = INT64_MAX;
11825 int i;
11826 117898 MOVContext *mov = s->priv_data;
11827
3/4
✓ Branch 0 taken 117898 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 117853 times.
117898 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
11828
2/2
✓ Branch 0 taken 152487 times.
✓ Branch 1 taken 117898 times.
270385 for (i = 0; i < s->nb_streams; i++) {
11829 152487 AVStream *avst = s->streams[i];
11830 152487 FFStream *const avsti = ffstream(avst);
11831 152487 MOVStreamContext *msc = avst->priv_data;
11832
4/4
✓ Branch 0 taken 142965 times.
✓ Branch 1 taken 9522 times.
✓ Branch 2 taken 139452 times.
✓ Branch 3 taken 3513 times.
152487 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
11833 139452 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
11834 139452 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
11835
2/2
✓ Branch 0 taken 123899 times.
✓ Branch 1 taken 15553 times.
139452 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
11836 139452 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
11837
3/6
✓ Branch 0 taken 22137 times.
✓ Branch 1 taken 117315 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22137 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
139452 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
11838
1/2
✓ Branch 0 taken 22137 times.
✗ Branch 1 not taken.
22137 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
11839
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 22137 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 22137 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 22137 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19934 times.
✓ Branch 9 taken 2203 times.
22137 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
11840
4/4
✓ Branch 0 taken 11742 times.
✓ Branch 1 taken 8192 times.
✓ Branch 2 taken 2203 times.
✓ Branch 3 taken 11742 times.
22137 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
11841
3/4
✓ Branch 0 taken 761 times.
✓ Branch 1 taken 1442 times.
✓ Branch 2 taken 761 times.
✗ Branch 3 not taken.
2203 (dtsdiff > AV_TIME_BASE && dts < best_dts && mov->interleaved_read)))))) {
11842 126268 sample = current_sample;
11843 126268 best_dts = dts;
11844 126268 *st = avst;
11845 }
11846 }
11847 }
11848 117898 return sample;
11849 }
11850
11851 9 static int should_retry(AVIOContext *pb, int error_code) {
11852
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))
11853 9 return 0;
11854
11855 return 1;
11856 }
11857
11858 49 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
11859 {
11860 int ret;
11861 49 MOVContext *mov = s->priv_data;
11862
11863
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
49 if (index >= 0 && index < mov->frag_index.nb_items)
11864 1 target = mov->frag_index.item[index].moof_offset;
11865
2/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 49 times.
49 if (target >= 0 && avio_seek(s->pb, target, SEEK_SET) != target) {
11866 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
11867 return AVERROR_INVALIDDATA;
11868 }
11869
11870 49 mov->next_root_atom = 0;
11871
4/6
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
49 if ((index < 0 && target >= 0) || index >= mov->frag_index.nb_items)
11872 48 index = search_frag_moof_offset(&mov->frag_index, target);
11873
3/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 7 times.
49 if (index >= 0 && index < mov->frag_index.nb_items &&
11874
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 mov->frag_index.item[index].moof_offset == target) {
11875
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 4 times.
42 if (index + 1 < mov->frag_index.nb_items)
11876 38 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11877
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 6 times.
42 if (mov->frag_index.item[index].headers_read)
11878 36 return 0;
11879 6 mov->frag_index.item[index].headers_read = 1;
11880 }
11881
11882 13 mov->found_mdat = 0;
11883
11884 13 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
11885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (ret < 0)
11886 return ret;
11887
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 6 times.
13 if (avio_feof(s->pb))
11888 7 return AVERROR_EOF;
11889 6 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
11890
11891 6 return 1;
11892 }
11893
11894 17 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
11895 {
11896 17 MOVStreamContext *sc = st->priv_data;
11897 uint8_t *side, *extradata;
11898 int extradata_size;
11899
11900 /* Save the current index. */
11901 17 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
11902
11903 /* Notify the decoder that extradata changed. */
11904 17 extradata_size = sc->extradata_size[sc->last_stsd_index];
11905 17 extradata = sc->extradata[sc->last_stsd_index];
11906
4/6
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
17 if (st->discard != AVDISCARD_ALL && extradata_size > 0 && extradata) {
11907 14 side = av_packet_new_side_data(pkt,
11908 AV_PKT_DATA_NEW_EXTRADATA,
11909 extradata_size);
11910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!side)
11911 return AVERROR(ENOMEM);
11912 14 memcpy(side, extradata, extradata_size);
11913 }
11914
11915 17 return 0;
11916 }
11917
11918 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
11919 {
11920 /* We can't make assumptions about the structure of the payload,
11921 because it may include multiple cdat and cdt2 samples. */
11922 const uint32_t cdat = AV_RB32("cdat");
11923 const uint32_t cdt2 = AV_RB32("cdt2");
11924 int ret, out_size = 0;
11925
11926 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
11927 if (src_size < 10)
11928 return AVERROR_INVALIDDATA;
11929
11930 /* avoid an int overflow: */
11931 if ((src_size - 8) / 2 >= INT_MAX / 3)
11932 return AVERROR_INVALIDDATA;
11933
11934 ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
11935 if (ret < 0)
11936 return ret;
11937
11938 /* parse and re-format the c608 payload in one pass. */
11939 while (src_size >= 10) {
11940 const uint32_t atom_size = avio_rb32(pb);
11941 const uint32_t atom_type = avio_rb32(pb);
11942 const uint32_t data_size = atom_size - 8;
11943 const uint8_t cc_field =
11944 atom_type == cdat ? 1 :
11945 atom_type == cdt2 ? 2 :
11946 0;
11947
11948 /* account for bytes consumed for atom size and type. */
11949 src_size -= 8;
11950
11951 /* make sure the data size stays within the buffer boundaries. */
11952 if (data_size < 2 || data_size > src_size) {
11953 ret = AVERROR_INVALIDDATA;
11954 break;
11955 }
11956
11957 /* make sure the data size is consistent with N byte pairs. */
11958 if (data_size % 2 != 0) {
11959 ret = AVERROR_INVALIDDATA;
11960 break;
11961 }
11962
11963 if (!cc_field) {
11964 /* neither cdat or cdt2 ... skip it */
11965 avio_skip(pb, data_size);
11966 src_size -= data_size;
11967 continue;
11968 }
11969
11970 for (uint32_t i = 0; i < data_size; i += 2) {
11971 pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
11972 pkt->data[out_size + 1] = avio_r8(pb);
11973 pkt->data[out_size + 2] = avio_r8(pb);
11974 out_size += 3;
11975 src_size -= 2;
11976 }
11977 }
11978
11979 if (src_size > 0)
11980 /* skip any remaining unread portion of the input payload */
11981 avio_skip(pb, src_size);
11982
11983 av_shrink_packet(pkt, out_size);
11984 return ret;
11985 }
11986
11987 117270 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
11988 int64_t current_index, AVPacket *pkt)
11989 {
11990 117270 MOVContext *mov = s->priv_data;
11991 117270 MOVStreamContext *sc = st->priv_data;
11992
11993 117270 pkt->stream_index = sc->ffindex;
11994 117270 pkt->dts = sample->timestamp;
11995
2/2
✓ Branch 0 taken 297 times.
✓ Branch 1 taken 116973 times.
117270 if (sample->flags & AVINDEX_DISCARD_FRAME) {
11996 297 pkt->flags |= AV_PKT_FLAG_DISCARD;
11997 }
11998
4/4
✓ Branch 0 taken 97303 times.
✓ Branch 1 taken 19967 times.
✓ Branch 2 taken 97291 times.
✓ Branch 3 taken 12 times.
117270 if (sc->stts_count && sc->tts_index < sc->tts_count)
11999 97291 pkt->duration = sc->tts_data[sc->tts_index].duration;
12000
3/4
✓ Branch 0 taken 4617 times.
✓ Branch 1 taken 112653 times.
✓ Branch 2 taken 4617 times.
✗ Branch 3 not taken.
117270 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
12001 4617 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
12002 } else {
12003
2/2
✓ Branch 0 taken 15903 times.
✓ Branch 1 taken 96750 times.
112653 if (pkt->duration == 0) {
12004 15903 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
12005
2/2
✓ Branch 0 taken 15811 times.
✓ Branch 1 taken 92 times.
15903 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
12006
2/2
✓ Branch 0 taken 15857 times.
✓ Branch 1 taken 46 times.
15903 if (next_dts >= pkt->dts)
12007 15857 pkt->duration = next_dts - pkt->dts;
12008 }
12009 112653 pkt->pts = pkt->dts;
12010 }
12011
12012
4/4
✓ Branch 0 taken 98501 times.
✓ Branch 1 taken 18769 times.
✓ Branch 2 taken 98423 times.
✓ Branch 3 taken 78 times.
117270 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && !mov->fragment.found_tfhd &&
12013
2/2
✓ Branch 1 taken 228 times.
✓ Branch 2 taken 98195 times.
98423 sc->current_sample >= ffstream(st)->nb_index_entries) {
12014 228 int64_t pts = av_rescale_q(pkt->pts, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12015 228 int64_t total = av_rescale_q(st->duration, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12016 228 int64_t duration = pkt->duration;
12017
12018
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 226 times.
228 if (st->duration < pkt->pts) {
12019 2 duration = 0;
12020 } else
12021 226 duration = FFMIN(duration, (uint64_t)st->duration - pkt->pts);
12022
12023 228 duration = av_rescale_q(duration, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12024
12025
2/2
✓ Branch 1 taken 189 times.
✓ Branch 2 taken 39 times.
228 if (!ffstream(st)->first_discard_sample)
12026 189 ffstream(st)->first_discard_sample = av_sat_add64(pts, duration);
12027
2/2
✓ Branch 1 taken 189 times.
✓ Branch 2 taken 39 times.
228 if (!ffstream(st)->last_discard_sample)
12028 189 ffstream(st)->last_discard_sample = total;
12029 }
12030
12031
4/4
✓ Branch 0 taken 97303 times.
✓ Branch 1 taken 19967 times.
✓ Branch 2 taken 97291 times.
✓ Branch 3 taken 12 times.
117270 if (sc->tts_data && sc->tts_index < sc->tts_count) {
12032 /* update tts context */
12033 97291 sc->tts_sample++;
12034
1/2
✓ Branch 0 taken 97291 times.
✗ Branch 1 not taken.
97291 if (sc->tts_index < sc->tts_count &&
12035
1/2
✓ Branch 0 taken 97291 times.
✗ Branch 1 not taken.
97291 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
12036 97291 sc->tts_index++;
12037 97291 sc->tts_sample = 0;
12038 }
12039 }
12040
12041
4/4
✓ Branch 0 taken 1055 times.
✓ Branch 1 taken 116215 times.
✓ Branch 2 taken 923 times.
✓ Branch 3 taken 132 times.
117270 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
12042 923 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
12043 923 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
12044
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 603 times.
923 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
12045 }
12046 117270 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
12047 117270 pkt->pos = sample->pos;
12048
12049 /* Multiple stsd handling. */
12050
2/2
✓ Branch 0 taken 113886 times.
✓ Branch 1 taken 3384 times.
117270 if (sc->stsc_data) {
12051
1/2
✓ Branch 0 taken 113886 times.
✗ Branch 1 not taken.
113886 if (sc->stsc_data[sc->stsc_index].id > 0 &&
12052
2/2
✓ Branch 0 taken 113843 times.
✓ Branch 1 taken 43 times.
113886 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
12053
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 113826 times.
113843 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
12054 17 int ret = mov_change_extradata(st, pkt);
12055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (ret < 0)
12056 return ret;
12057 }
12058
12059 /* Update the stsc index for the next sample */
12060 113886 sc->stsc_sample++;
12061
2/2
✓ Branch 1 taken 56987 times.
✓ Branch 2 taken 56899 times.
113886 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
12062
2/2
✓ Branch 1 taken 1214 times.
✓ Branch 2 taken 55773 times.
56987 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
12063 1214 sc->stsc_index++;
12064 1214 sc->stsc_sample = 0;
12065 }
12066 }
12067
12068 117270 return 0;
12069 }
12070
12071 108611 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
12072 {
12073 108611 MOVContext *mov = s->priv_data;
12074 MOVStreamContext *sc;
12075 AVIndexEntry *sample;
12076 108611 AVStream *st = NULL;
12077 108611 FFStream *avsti = NULL;
12078 int64_t current_index;
12079 int ret;
12080 int i;
12081 108611 mov->fc = s;
12082 9287 retry:
12083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117898 times.
117898 if (s->pb->pos == 0) {
12084
12085 // Discard current fragment index
12086 if (mov->frag_index.allocated_size > 0) {
12087 for(int i = 0; i < mov->frag_index.nb_items; i++) {
12088 av_freep(&mov->frag_index.item[i].stream_info);
12089 }
12090 av_freep(&mov->frag_index.item);
12091 mov->frag_index.nb_items = 0;
12092 mov->frag_index.allocated_size = 0;
12093 mov->frag_index.current = -1;
12094 mov->frag_index.complete = 0;
12095 }
12096
12097 for (i = 0; i < s->nb_streams; i++) {
12098 AVStream *avst = s->streams[i];
12099 MOVStreamContext *msc = avst->priv_data;
12100
12101 // Clear current sample
12102 mov_current_sample_set(msc, 0);
12103 msc->tts_index = 0;
12104
12105 // Discard current index entries
12106 avsti = ffstream(avst);
12107 if (avsti->index_entries_allocated_size > 0) {
12108 av_freep(&avsti->index_entries);
12109 avsti->index_entries_allocated_size = 0;
12110 avsti->nb_index_entries = 0;
12111 }
12112 }
12113
12114 if ((ret = mov_switch_root(s, -1, -1)) < 0)
12115 return ret;
12116 }
12117 117898 sample = mov_find_next_sample(s, &st);
12118
6/6
✓ Branch 0 taken 117315 times.
✓ Branch 1 taken 583 times.
✓ Branch 2 taken 652 times.
✓ Branch 3 taken 116663 times.
✓ Branch 4 taken 36 times.
✓ Branch 5 taken 616 times.
117898 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
12119
2/2
✓ Branch 0 taken 571 times.
✓ Branch 1 taken 48 times.
619 if (!mov->next_root_atom)
12120 571 return AVERROR_EOF;
12121
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 41 times.
48 if ((ret = mov_switch_root(s, mov->next_root_atom, -1)) < 0)
12122 7 return ret;
12123 41 goto retry;
12124 }
12125 117279 sc = st->priv_data;
12126 /* must be done just before reading, to avoid infinite loop on sample */
12127 117279 current_index = sc->current_index;
12128 117279 mov_current_sample_inc(sc);
12129
12130
2/2
✓ Branch 0 taken 616 times.
✓ Branch 1 taken 116663 times.
117279 if (mov->next_root_atom) {
12131 616 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
12132 616 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
12133 }
12134
12135
4/4
✓ Branch 0 taken 9256 times.
✓ Branch 1 taken 108023 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 9246 times.
117279 if (st->discard != AVDISCARD_ALL || sc->iamf) {
12136 108033 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
12137
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 108026 times.
108033 if (ret64 != sample->pos) {
12138 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
12139 sc->ffindex, sample->pos);
12140
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
12141 mov_current_sample_dec(sc);
12142
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
12143 7 return (int)ret64;
12144 }
12145 return AVERROR_INVALIDDATA;
12146 }
12147
12148
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 108026 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
108026 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
12149 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
12150 goto retry;
12151 }
12152
12153
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 108026 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
108026 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
12154 ret = get_eia608_packet(sc->pb, pkt, sample->size);
12155 #if CONFIG_IAMFDEC
12156
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 107944 times.
108026 else if (sc->iamf) {
12157 int64_t pts, dts, pos, duration;
12158 82 int flags, size = sample->size;
12159 82 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
12160 82 pts = pkt->pts; dts = pkt->dts;
12161 82 pos = pkt->pos; flags = pkt->flags;
12162 82 duration = pkt->duration;
12163
3/4
✓ Branch 0 taken 536 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 454 times.
✓ Branch 3 taken 82 times.
536 while (!ret && size > 0) {
12164 454 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
12165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 454 times.
454 if (ret < 0) {
12166 if (should_retry(sc->pb, ret))
12167 mov_current_sample_dec(sc);
12168 return ret;
12169 }
12170 454 size -= ret;
12171
12172
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 334 times.
454 if (pkt->flags & AV_PKT_FLAG_DISCARD) {
12173 120 av_packet_unref(pkt);
12174 120 ret = 0;
12175 120 continue;
12176 }
12177 334 pkt->pts = pts; pkt->dts = dts;
12178 334 pkt->pos = pos; pkt->flags |= flags;
12179 334 pkt->duration = duration;
12180 334 ret = ff_buffer_packet(s, pkt);
12181 }
12182
1/2
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
82 if (!ret)
12183 82 return FFERROR_REDO;
12184 }
12185 #endif
12186
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 107941 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
107947 else if (st->codecpar->codec_id == AV_CODEC_ID_APV && sample->size > 4) {
12187 3 uint32_t au_size = avio_rb32(sc->pb);
12188 3 int explode = !!(mov->fc->error_recognition & AV_EF_EXPLODE);
12189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (au_size > sample->size - 4) {
12190 av_log(s, explode ? AV_LOG_ERROR : AV_LOG_WARNING,
12191 "APV au_size %u exceeds sample body %d\n",
12192 au_size, sample->size - 4);
12193 if (explode)
12194 return AVERROR_INVALIDDATA;
12195 au_size = sample->size - 4;
12196 }
12197 3 ret = av_get_packet(sc->pb, pkt, au_size);
12198 } else
12199 107941 ret = av_get_packet(sc->pb, pkt, sample->size);
12200
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 107942 times.
107944 if (ret < 0) {
12201
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (should_retry(sc->pb, ret)) {
12202 mov_current_sample_dec(sc);
12203 }
12204 2 return ret;
12205 }
12206 #if CONFIG_DV_DEMUXER
12207
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 107942 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
107942 if (mov->dv_demux && sc->dv_audio_container) {
12208 ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
12209 av_packet_unref(pkt);
12210 if (ret < 0)
12211 return ret;
12212 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
12213 if (ret < 0)
12214 return ret;
12215 }
12216 #endif
12217
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 107924 times.
107942 if (sc->has_palette) {
12218 uint8_t *pal;
12219
12220 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
12221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
12222 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
12223 } else {
12224 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
12225 18 sc->has_palette = 0;
12226 }
12227 }
12228
4/6
✓ Branch 0 taken 329 times.
✓ Branch 1 taken 107613 times.
✓ Branch 3 taken 329 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 329 times.
✗ Branch 6 not taken.
107942 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
12229
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 329 times.
329 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
12230 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
12231 }
12232 }
12233
12234 117188 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
12235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117188 times.
117188 if (ret < 0)
12236 return ret;
12237
12238
2/2
✓ Branch 0 taken 9246 times.
✓ Branch 1 taken 107942 times.
117188 if (st->discard == AVDISCARD_ALL)
12239 9246 goto retry;
12240
12241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107942 times.
107942 if (mov->aax_mode)
12242 aax_filter(pkt->data, pkt->size, mov);
12243
12244 107942 ret = cenc_filter(mov, st, sc, pkt, current_index);
12245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107942 times.
107942 if (ret < 0) {
12246 return ret;
12247 }
12248
12249 107942 return 0;
12250 }
12251
12252 365 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
12253 {
12254 365 MOVContext *mov = s->priv_data;
12255 int index;
12256
12257
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 28 times.
365 if (!mov->frag_index.complete)
12258 337 return 0;
12259
12260 28 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
12261
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 24 times.
28 if (index < 0)
12262 4 index = 0;
12263
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (!mov->frag_index.item[index].headers_read)
12264 1 return mov_switch_root(s, -1, index);
12265
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (index + 1 < mov->frag_index.nb_items)
12266 27 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
12267
12268 27 return 0;
12269 }
12270
12271 static int is_open_key_sample(const MOVStreamContext *sc, int sample)
12272 {
12273 // TODO: a bisect search would scale much better
12274 for (int i = 0; i < sc->open_key_samples_count; i++) {
12275 const int oks = sc->open_key_samples[i];
12276 if (oks == sample)
12277 return 1;
12278 if (oks > sample) /* list is monotically increasing so we can stop early */
12279 break;
12280 }
12281 return 0;
12282 }
12283
12284 /*
12285 * Some key sample may be key frames but not IDR frames, so a random access to
12286 * them may not be allowed.
12287 */
12288 231 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
12289 {
12290 231 MOVStreamContext *sc = st->priv_data;
12291 231 FFStream *const sti = ffstream(st);
12292 int64_t key_sample_dts, key_sample_pts;
12293
12294
1/2
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
231 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
12295 231 return 1;
12296
12297 if (sample >= sc->sample_offsets_count)
12298 return 1;
12299
12300 av_assert0(sample >= 0);
12301 key_sample_dts = sti->index_entries[sample].timestamp;
12302 key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
12303
12304 /*
12305 * If the sample needs to be presented before an open key sample, they may
12306 * not be decodable properly, even though they come after in decoding
12307 * order.
12308 */
12309 if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
12310 return 0;
12311
12312 return 1;
12313 }
12314
12315 365 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
12316 {
12317 365 MOVStreamContext *sc = st->priv_data;
12318 365 FFStream *const sti = ffstream(st);
12319 int sample, time_sample, ret, requested_sample;
12320 int64_t next_ts;
12321 unsigned int i;
12322
12323 // Here we consider timestamp to be PTS, hence try to offset it so that we
12324 // can search over the DTS timeline.
12325 365 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
12326
12327 365 ret = mov_seek_fragment(s, st, timestamp);
12328
1/2
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
365 if (ret < 0)
12329 return ret;
12330
12331 for (;;) {
12332 365 sample = av_index_search_timestamp(st, timestamp, flags);
12333 365 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
12334
5/6
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 296 times.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
✓ Branch 5 taken 26 times.
365 if (sample < 0 && sti->nb_index_entries && timestamp < sti->index_entries[0].timestamp)
12335 43 sample = 0;
12336
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 339 times.
365 if (sample < 0) /* not sure what to do */
12337 26 return AVERROR_INVALIDDATA;
12338
12339
3/4
✓ Branch 0 taken 231 times.
✓ Branch 1 taken 108 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 231 times.
339 if (!sample || can_seek_to_key_sample(st, sample, timestamp))
12340 break;
12341
12342 next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
12343 requested_sample = av_index_search_timestamp(st, next_ts, flags);
12344 if (requested_sample < 0)
12345 return AVERROR_INVALIDDATA;
12346
12347 // If we've reached a different sample trying to find a good pts to
12348 // seek to, give up searching because we'll end up seeking back to
12349 // sample 0 on every seek.
12350 if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
12351 break;
12352
12353 timestamp = next_ts;
12354 }
12355
12356 339 mov_current_sample_set(sc, sample);
12357 339 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
12358 /* adjust time to sample index */
12359
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 125 times.
339 if (sc->tts_data) {
12360 214 time_sample = 0;
12361
1/2
✓ Branch 0 taken 60310 times.
✗ Branch 1 not taken.
60310 for (i = 0; i < sc->tts_count; i++) {
12362 60310 int next = time_sample + sc->tts_data[i].count;
12363
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 60096 times.
60310 if (next > sc->current_sample) {
12364 214 sc->tts_index = i;
12365 214 sc->tts_sample = sc->current_sample - time_sample;
12366 214 break;
12367 }
12368 60096 time_sample = next;
12369 }
12370 }
12371
12372 /* adjust stsd index */
12373
2/2
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 28 times.
339 if (sc->chunk_count) {
12374 311 time_sample = 0;
12375
1/2
✓ Branch 0 taken 383 times.
✗ Branch 1 not taken.
383 for (i = 0; i < sc->stsc_count; i++) {
12376 383 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
12377
2/2
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 72 times.
383 if (next > sc->current_sample) {
12378 311 sc->stsc_index = i;
12379 311 sc->stsc_sample = sc->current_sample - time_sample;
12380 311 break;
12381 }
12382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
12383 72 time_sample = next;
12384 }
12385 }
12386
12387 339 return sample;
12388 }
12389
12390 339 static int64_t mov_get_skip_samples(AVStream *st, int sample)
12391 {
12392 339 FFStream *const sti = ffstream(st);
12393 339 int64_t first_ts = sti->index_entries[0].timestamp;
12394 339 int64_t ts = sti->index_entries[sample].timestamp;
12395 int64_t off;
12396
12397
2/2
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 152 times.
339 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
12398 187 return 0;
12399
12400 /* compute skip samples according to stream initial_padding, seek ts and first ts */
12401 152 off = av_rescale_q(ts - first_ts, st->time_base,
12402 152 (AVRational){1, st->codecpar->sample_rate});
12403 152 return FFMAX(st->codecpar->initial_padding - off, 0);
12404 }
12405
12406 343 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
12407 {
12408 343 MOVContext *mc = s->priv_data;
12409 AVStream *st;
12410 FFStream *sti;
12411 int sample;
12412 int i;
12413
12414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 343 times.
343 if (stream_index >= s->nb_streams)
12415 return AVERROR_INVALIDDATA;
12416
12417 343 st = s->streams[stream_index];
12418 343 sti = ffstream(st);
12419 343 sample = mov_seek_stream(s, st, sample_time, flags);
12420
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 317 times.
343 if (sample < 0)
12421 26 return sample;
12422
12423
1/2
✓ Branch 0 taken 317 times.
✗ Branch 1 not taken.
317 if (mc->seek_individually) {
12424 /* adjust seek timestamp to found sample timestamp */
12425 317 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
12426 317 sti->skip_samples = mov_get_skip_samples(st, sample);
12427
12428
2/2
✓ Branch 0 taken 339 times.
✓ Branch 1 taken 317 times.
656 for (i = 0; i < s->nb_streams; i++) {
12429 339 AVStream *const st = s->streams[i];
12430 339 FFStream *const sti = ffstream(st);
12431 int64_t timestamp;
12432
12433
2/2
✓ Branch 0 taken 317 times.
✓ Branch 1 taken 22 times.
339 if (stream_index == i)
12434 317 continue;
12435
12436 22 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
12437 22 sample = mov_seek_stream(s, st, timestamp, flags);
12438
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (sample >= 0)
12439 22 sti->skip_samples = mov_get_skip_samples(st, sample);
12440 }
12441 } else {
12442 for (i = 0; i < s->nb_streams; i++) {
12443 MOVStreamContext *sc;
12444 st = s->streams[i];
12445 sc = st->priv_data;
12446 mov_current_sample_set(sc, 0);
12447 }
12448 while (1) {
12449 MOVStreamContext *sc;
12450 AVIndexEntry *entry = mov_find_next_sample(s, &st);
12451 if (!entry)
12452 return AVERROR_INVALIDDATA;
12453 sc = st->priv_data;
12454 if (sc->ffindex == stream_index && sc->current_sample == sample)
12455 break;
12456 mov_current_sample_inc(sc);
12457 }
12458 }
12459 317 return 0;
12460 }
12461
12462 #define OFFSET(x) offsetof(MOVContext, x)
12463 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
12464 static const AVOption mov_options[] = {
12465 {"use_absolute_path",
12466 "allow using absolute path when opening alias, this is a possible security issue",
12467 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
12468 0, 1, FLAGS},
12469 {"seek_streams_individually",
12470 "Seek each stream individually to the closest point",
12471 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
12472 0, 1, FLAGS},
12473 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
12474 0, 1, FLAGS},
12475 {"advanced_editlist",
12476 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
12477 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
12478 0, 1, FLAGS},
12479 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
12480 0, 1, FLAGS},
12481 {"use_mfra_for",
12482 "use mfra for fragment timestamps",
12483 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
12484 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
12485 .unit = "use_mfra_for"},
12486 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
12487 FLAGS, .unit = "use_mfra_for" },
12488 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
12489 FLAGS, .unit = "use_mfra_for" },
12490 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
12491 FLAGS, .unit = "use_mfra_for" },
12492 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
12493 0, 1, FLAGS},
12494 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
12495 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
12496 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
12497 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
12498 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
12499 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12500 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
12501 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12502 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
12503 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12504 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
12505 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
12506 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
12507 .flags = AV_OPT_FLAG_DECODING_PARAM },
12508 { "decryption_key", "The default media decryption key (hex)", OFFSET(decryption_default_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12509 { "decryption_keys", "The media decryption keys by KID (hex)", OFFSET(decryption_keys), AV_OPT_TYPE_DICT, .flags = AV_OPT_FLAG_DECODING_PARAM },
12510 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
12511 {.i64 = 0}, 0, 1, FLAGS },
12512 { "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 },
12513 { "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 },
12514
12515 { NULL },
12516 };
12517
12518 static const AVClass mov_class = {
12519 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
12520 .item_name = av_default_item_name,
12521 .option = mov_options,
12522 .version = LIBAVUTIL_VERSION_INT,
12523 };
12524
12525 const FFInputFormat ff_mov_demuxer = {
12526 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
12527 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
12528 .p.priv_class = &mov_class,
12529 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4v,m4b,ism,ismv,isma,f4v,avif,heic,heif",
12530 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
12531 .priv_data_size = sizeof(MOVContext),
12532 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
12533 .read_probe = mov_probe,
12534 .read_header = mov_read_header,
12535 .read_packet = mov_read_packet,
12536 .read_close = mov_read_close,
12537 .read_seek = mov_read_seek,
12538 };
12539