FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2026-09-18 09:24:57
Exec Total Coverage
Lines: 4787 7479 64.0%
Functions: 192 231 83.1%
Branches: 2746 5057 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 354724 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3598 {
3599 354724 return index < count - 1;
3600 }
3601
3602 /* Compute the samples value for the stsc entry at the given index. */
3603 57302 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 57104 times.
✓ Branch 2 taken 198 times.
57302 if (mov_stsc_index_valid(index, sc->stsc_count))
3608 57104 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 57302 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 117207 static void mov_current_sample_inc(MOVStreamContext *sc)
4458 {
4459 117207 sc->current_sample++;
4460 117207 sc->current_index++;
4461
2/2
✓ Branch 0 taken 71117 times.
✓ Branch 1 taken 46090 times.
117207 if (sc->index_ranges &&
4462
2/2
✓ Branch 0 taken 493 times.
✓ Branch 1 taken 70624 times.
71117 sc->current_index >= sc->current_index_range->end &&
4463
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 sc->current_index_range->end) {
4464 493 sc->current_index_range++;
4465 493 sc->current_index = sc->current_index_range->start;
4466 }
4467 117207 }
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
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if (count > atom.size / 8 || 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 = av_malloc_array(count + 1, sizeof(*c->meta_keys));
5738
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!c->meta_keys)
5739 return AVERROR(ENOMEM);
5740
5741 11 c->meta_keys[0] = NULL;
5742 11 c->meta_keys_count = 1;
5743
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i <= count; ++i) {
5744 58 uint32_t key_size = avio_rb32(pb);
5745 58 uint32_t type = avio_rl32(pb);
5746 58 c->meta_keys[i] = NULL;
5747 58 c->meta_keys_count = i + 1;
5748
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) {
5749 av_log(c->fc, AV_LOG_ERROR,
5750 "The key# %"PRIu32" in meta has invalid size:"
5751 "%"PRIu32"\n", i, key_size);
5752 return AVERROR_INVALIDDATA;
5753 }
5754 58 atom.size -= key_size;
5755 58 key_size -= 8;
5756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (type != MKTAG('m','d','t','a')) {
5757 avio_skip(pb, key_size);
5758 continue;
5759 }
5760 58 c->meta_keys[i] = av_malloc(key_size + 1);
5761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!c->meta_keys[i])
5762 return AVERROR(ENOMEM);
5763 58 int ret = ffio_read_size(pb, c->meta_keys[i], key_size);
5764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (ret < 0)
5765 return ret;
5766 58 c->meta_keys[i][key_size] = 0;
5767 }
5768
5769 11 return 0;
5770 }
5771
5772 80 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5773 {
5774 80 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5775 80 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5776 int i;
5777 80 int ret = 0;
5778 AVStream *st;
5779
5780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (c->fc->nb_streams < 1)
5781 return 0;
5782 80 st = c->fc->streams[c->fc->nb_streams-1];
5783
5784
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 80 times.
320 for (i = 0; i < 3; i++) {
5785 uint8_t **p;
5786 uint32_t len, tag;
5787
5788
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 240 times.
240 if (end - avio_tell(pb) <= 12)
5789 break;
5790
5791 240 len = avio_rb32(pb);
5792 240 tag = avio_rl32(pb);
5793 240 avio_skip(pb, 4); // flags
5794
5795
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))
5796 break;
5797 240 len -= 12;
5798
5799
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 160 times.
240 if (tag == MKTAG('m', 'e', 'a', 'n'))
5800 80 p = &mean;
5801
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 80 times.
160 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5802 80 p = &key;
5803
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) {
5804 80 avio_skip(pb, 4);
5805 80 len -= 4;
5806 80 p = &val;
5807 } else
5808 break;
5809
5810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (*p)
5811 break;
5812
5813 240 *p = av_malloc(len + 1);
5814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (!*p) {
5815 ret = AVERROR(ENOMEM);
5816 break;
5817 }
5818 240 ret = ffio_read_size(pb, *p, len);
5819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (ret < 0) {
5820 av_freep(p);
5821 break;
5822 }
5823 240 (*p)[len] = 0;
5824 }
5825
5826
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) {
5827
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 38 times.
80 if (strcmp(key, "iTunSMPB") == 0) {
5828 int64_t priming, remainder, samples;
5829
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 if (ff_itunes_parse_smpb(val, &priming, &remainder, &samples) >= 0) {
5830
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)
5831 42 st->codecpar->initial_padding = priming = av_rescale_q(priming, st->time_base,
5832 42 (AVRational){ 1, st->codecpar->sample_rate });
5833
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 if (remainder > 0) {
5834 42 int64_t duration = av_rescale_q(st->duration, st->time_base,
5835 42 (AVRational){ 1, st->codecpar->sample_rate });
5836 42 remainder = av_rescale_q(remainder, st->time_base,
5837 42 (AVRational){ 1, st->codecpar->sample_rate });
5838 42 samples = av_rescale_q(samples, st->time_base,
5839 42 (AVRational){ 1, st->codecpar->sample_rate });
5840
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) {
5841 42 ffstream(st)->first_discard_sample = duration - remainder;
5842 42 ffstream(st)->last_discard_sample = duration;
5843 }
5844 }
5845 42 av_log(c->fc, AV_LOG_DEBUG, "Parsed iTunSMPB: priming %"PRId64", "
5846 "remainder %"PRId64" samples %"PRId64"\n",
5847 priming, remainder, samples);
5848 }
5849 }
5850
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 if (strcmp(mean, "com.apple.iTunes") == 0 &&
5851
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 78 times.
80 strcmp(key, "DISCSUBTITLE") == 0) {
5852 2 av_dict_set(&c->fc->metadata, "disc_subtitle", val,
5853 AV_DICT_DONT_STRDUP_VAL);
5854 2 val = NULL;
5855 }
5856
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 10 times.
150 if (strcmp(key, "cdec") != 0) {
5857 70 av_dict_set(&c->fc->metadata, key, val,
5858 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5859 70 key = val = NULL;
5860 }
5861 } else {
5862 av_log(c->fc, AV_LOG_VERBOSE,
5863 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5864 }
5865
5866 80 avio_seek(pb, end, SEEK_SET);
5867 80 av_freep(&key);
5868 80 av_freep(&val);
5869 80 av_freep(&mean);
5870 80 return ret;
5871 }
5872
5873 43 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5874 {
5875 MOVStreamContext *sc;
5876 AVStream *st;
5877
5878 43 st = avformat_new_stream(c->fc, NULL);
5879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st)
5880 return AVERROR(ENOMEM);
5881 43 sc = av_mallocz(sizeof(MOVStreamContext));
5882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc)
5883 goto fail;
5884
5885 43 item->st = st;
5886 43 st->id = item->item_id;
5887 43 st->priv_data = sc;
5888 43 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5889 43 st->codecpar->codec_id = mov_codec_id(st, item->type);
5890 43 sc->id = st->id;
5891 43 sc->ffindex = st->index;
5892 43 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5893 43 st->time_base.num = st->time_base.den = 1;
5894 43 st->nb_frames = 1;
5895 43 sc->time_scale = 1;
5896 43 sc->pb = c->fc->pb;
5897 43 sc->pb_is_copied = 1;
5898 43 sc->refcount = 1;
5899
5900
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (item->name)
5901 43 av_dict_set(&st->metadata, "title", item->name, 0);
5902
5903 // Populate the necessary fields used by mov_build_index.
5904 43 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->stsc_data)
5906 goto fail;
5907 43 sc->stsc_count = 1;
5908 43 sc->stsc_data[0].first = 1;
5909 43 sc->stsc_data[0].count = 1;
5910 43 sc->stsc_data[0].id = 1;
5911 43 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->chunk_offsets)
5913 goto fail;
5914 43 sc->chunk_count = 1;
5915 43 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5916
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->stts_data)
5917 goto fail;
5918 43 sc->stts_count = 1;
5919 43 sc->stts_data[0].count = 1;
5920 // Not used for still images. But needed by mov_build_index.
5921 43 sc->stts_data[0].duration = 0;
5922
5923 43 return 0;
5924 fail:
5925 mov_free_stream_context(c->fc, st);
5926 ff_remove_stream(c->fc, st);
5927 item->st = NULL;
5928
5929 return AVERROR(ENOMEM);
5930 }
5931
5932 208 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5933 {
5934
1/2
✓ Branch 0 taken 610 times.
✗ Branch 1 not taken.
610 while (atom.size > 8) {
5935 uint32_t tag;
5936
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 610 times.
610 if (avio_feof(pb))
5937 return AVERROR_EOF;
5938 610 tag = avio_rl32(pb);
5939 610 atom.size -= 4;
5940
2/2
✓ Branch 0 taken 208 times.
✓ Branch 1 taken 402 times.
610 if (tag == MKTAG('h','d','l','r')) {
5941 208 avio_seek(pb, -8, SEEK_CUR);
5942 208 atom.size += 8;
5943 208 return mov_read_default(c, pb, atom);
5944 }
5945 }
5946 return 0;
5947 }
5948
5949 // return 1 when matrix is identity, 0 otherwise
5950 #define IS_MATRIX_IDENT(matrix) \
5951 ( (matrix)[0][0] == (1 << 16) && \
5952 (matrix)[1][1] == (1 << 16) && \
5953 (matrix)[2][2] == (1 << 30) && \
5954 !(matrix)[0][1] && !(matrix)[0][2] && \
5955 !(matrix)[1][0] && !(matrix)[1][2] && \
5956 !(matrix)[2][0] && !(matrix)[2][1])
5957
5958 712 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5959 {
5960 int i, j, e;
5961 int width;
5962 int height;
5963 int display_matrix[3][3];
5964 712 int res_display_matrix[3][3] = { { 0 } };
5965 AVStream *st;
5966 MOVStreamContext *sc;
5967 int version;
5968 int flags;
5969
5970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (c->fc->nb_streams < 1)
5971 return 0;
5972 712 st = c->fc->streams[c->fc->nb_streams-1];
5973 712 sc = st->priv_data;
5974
5975 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5976 // avoids corrupting AVStreams mapped to an earlier tkhd.
5977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 if (st->id != -1)
5978 return AVERROR_INVALIDDATA;
5979
5980 712 version = avio_r8(pb);
5981 712 flags = avio_rb24(pb);
5982 712 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5983
5984
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 699 times.
712 if (version == 1) {
5985 13 avio_rb64(pb);
5986 13 avio_rb64(pb);
5987 } else {
5988 699 avio_rb32(pb); /* creation time */
5989 699 avio_rb32(pb); /* modification time */
5990 }
5991 712 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5992 712 sc->id = st->id;
5993 712 avio_rb32(pb); /* reserved */
5994
5995 /* highlevel (considering edits) duration in movie timebase */
5996
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 699 times.
712 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5997 712 avio_rb32(pb); /* reserved */
5998 712 avio_rb32(pb); /* reserved */
5999
6000 712 avio_rb16(pb); /* layer */
6001 712 avio_rb16(pb); /* alternate group */
6002 712 avio_rb16(pb); /* volume */
6003 712 avio_rb16(pb); /* reserved */
6004
6005 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
6006 // they're kept in fixed point format through all calculations
6007 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
6008 // side data, but the scale factor is not needed to calculate aspect ratio
6009
2/2
✓ Branch 0 taken 2136 times.
✓ Branch 1 taken 712 times.
2848 for (i = 0; i < 3; i++) {
6010 2136 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
6011 2136 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
6012 2136 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
6013 }
6014
6015 712 width = avio_rb32(pb); // 16.16 fixed point track width
6016 712 height = avio_rb32(pb); // 16.16 fixed point track height
6017 712 sc->width = width >> 16;
6018 712 sc->height = height >> 16;
6019
6020 // apply the moov display matrix (after the tkhd one)
6021
2/2
✓ Branch 0 taken 2136 times.
✓ Branch 1 taken 712 times.
2848 for (i = 0; i < 3; i++) {
6022 2136 const int sh[3] = { 16, 16, 30 };
6023
2/2
✓ Branch 0 taken 6408 times.
✓ Branch 1 taken 2136 times.
8544 for (j = 0; j < 3; j++) {
6024
2/2
✓ Branch 0 taken 19224 times.
✓ Branch 1 taken 6408 times.
25632 for (e = 0; e < 3; e++) {
6025 19224 res_display_matrix[i][j] +=
6026 19224 ((int64_t) display_matrix[i][e] *
6027 19224 c->movie_display_matrix[e][j]) >> sh[e];
6028 }
6029 }
6030 }
6031
6032 // save the matrix when it is not the default identity
6033
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)) {
6034 9 av_freep(&sc->display_matrix);
6035 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
6036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
6037 return AVERROR(ENOMEM);
6038
6039
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
6040
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
6041 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
6042 }
6043
6044 // transform the display width/height according to the matrix
6045 // to keep the same scale, use [width height 1<<16]
6046
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) {
6047 double disp_transform[2];
6048
6049
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
6050 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
6051 16 sc->display_matrix[3 + i]);
6052
6053
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 &&
6054
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) &&
6055
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
6056 3 st->sample_aspect_ratio = av_d2q(
6057 3 disp_transform[0] / disp_transform[1],
6058 INT_MAX);
6059 }
6060 712 return 0;
6061 }
6062
6063 501 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6064 {
6065 501 MOVFragment *frag = &c->fragment;
6066 501 MOVTrackExt *trex = NULL;
6067 int flags, track_id, i;
6068 MOVFragmentStreamInfo * frag_stream_info;
6069
6070 501 avio_r8(pb); /* version */
6071 501 flags = avio_rb24(pb);
6072
6073 501 track_id = avio_rb32(pb);
6074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!track_id)
6075 return AVERROR_INVALIDDATA;
6076
1/2
✓ Branch 0 taken 560 times.
✗ Branch 1 not taken.
560 for (i = 0; i < c->trex_count; i++)
6077
2/2
✓ Branch 0 taken 501 times.
✓ Branch 1 taken 59 times.
560 if (c->trex_data[i].track_id == track_id) {
6078 501 trex = &c->trex_data[i];
6079 501 break;
6080 }
6081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!trex) {
6082 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
6083 return 0;
6084 }
6085 501 c->fragment.found_tfhd = 1;
6086 501 frag->track_id = track_id;
6087 501 set_frag_stream(&c->frag_index, track_id);
6088
6089 1002 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
6090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
1002 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
6091
2/2
✓ Branch 0 taken 428 times.
✓ Branch 1 taken 73 times.
501 frag->moof_offset : frag->implicit_offset;
6092
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;
6093
6094 1002 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
6095
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 435 times.
501 avio_rb32(pb) : trex->duration;
6096 1002 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
6097
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 440 times.
501 avio_rb32(pb) : trex->size;
6098 1002 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
6099
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 366 times.
501 avio_rb32(pb) : trex->flags;
6100 501 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
6101
6102 501 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6103
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (frag_stream_info) {
6104 501 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
6105 501 frag_stream_info->stsd_id = frag->stsd_id;
6106 }
6107 501 return 0;
6108 }
6109
6110 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6111 {
6112 unsigned i, num;
6113 void *new_tracks;
6114
6115 2 num = atom.size / 4;
6116
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
6117 return AVERROR(ENOMEM);
6118
6119 2 av_free(c->chapter_tracks);
6120 2 c->chapter_tracks = new_tracks;
6121 2 c->nb_chapter_tracks = num;
6122
6123
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++)
6124 2 c->chapter_tracks[i] = avio_rb32(pb);
6125
6126 2 c->nb_chapter_tracks = i;
6127
6128 2 return 0;
6129 }
6130
6131 29 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6132 {
6133 MOVTrackExt *trex;
6134 int err;
6135
6136
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))
6137 return AVERROR_INVALIDDATA;
6138
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
6139 sizeof(*c->trex_data))) < 0) {
6140 c->trex_count = 0;
6141 return err;
6142 }
6143
6144 29 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
6145
6146 29 trex = &c->trex_data[c->trex_count++];
6147 29 avio_r8(pb); /* version */
6148 29 avio_rb24(pb); /* flags */
6149 29 trex->track_id = avio_rb32(pb);
6150 29 trex->stsd_id = avio_rb32(pb);
6151 29 trex->duration = avio_rb32(pb);
6152 29 trex->size = avio_rb32(pb);
6153 29 trex->flags = avio_rb32(pb);
6154 29 return 0;
6155 }
6156
6157 428 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6158 {
6159 428 MOVFragment *frag = &c->fragment;
6160 428 AVStream *st = NULL;
6161 MOVStreamContext *sc;
6162 int version, i;
6163 MOVFragmentStreamInfo * frag_stream_info;
6164 int64_t base_media_decode_time;
6165
6166
1/2
✓ Branch 0 taken 455 times.
✗ Branch 1 not taken.
455 for (i = 0; i < c->fc->nb_streams; i++) {
6167 455 sc = c->fc->streams[i]->priv_data;
6168
2/2
✓ Branch 0 taken 428 times.
✓ Branch 1 taken 27 times.
455 if (sc->id == frag->track_id) {
6169 428 st = c->fc->streams[i];
6170 428 break;
6171 }
6172 }
6173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 428 times.
428 if (!st) {
6174 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
6175 return 0;
6176 }
6177 428 sc = st->priv_data;
6178
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)
6179 return 0;
6180 428 version = avio_r8(pb);
6181 428 avio_rb24(pb); /* flags */
6182
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 370 times.
428 if (version) {
6183 58 base_media_decode_time = avio_rb64(pb);
6184 } else {
6185 370 base_media_decode_time = avio_rb32(pb);
6186 }
6187
6188 428 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6189
1/2
✓ Branch 0 taken 428 times.
✗ Branch 1 not taken.
428 if (frag_stream_info)
6190 428 frag_stream_info->tfdt_dts = base_media_decode_time;
6191 428 sc->track_end = base_media_decode_time;
6192
6193 428 return 0;
6194 }
6195
6196 501 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6197 {
6198 501 MOVFragment *frag = &c->fragment;
6199 501 AVStream *st = NULL;
6200 501 FFStream *sti = NULL;
6201 MOVStreamContext *sc;
6202 MOVTimeToSample *tts_data;
6203 uint64_t offset;
6204 501 int64_t dts, pts = AV_NOPTS_VALUE;
6205 501 int data_offset = 0;
6206 501 unsigned entries, first_sample_flags = frag->flags;
6207 int flags, distance, i;
6208 501 int64_t prev_dts = AV_NOPTS_VALUE;
6209 501 int next_frag_index = -1, index_entry_pos;
6210 size_t requested_size;
6211 size_t old_allocated_size;
6212 AVIndexEntry *new_entries;
6213 MOVFragmentStreamInfo * frag_stream_info;
6214
6215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!frag->found_tfhd) {
6216 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
6217 return AVERROR_INVALIDDATA;
6218 }
6219
6220
1/2
✓ Branch 0 taken 560 times.
✗ Branch 1 not taken.
560 for (i = 0; i < c->fc->nb_streams; i++) {
6221 560 sc = c->fc->streams[i]->priv_data;
6222
2/2
✓ Branch 0 taken 501 times.
✓ Branch 1 taken 59 times.
560 if (sc->id == frag->track_id) {
6223 501 st = c->fc->streams[i];
6224 501 sti = ffstream(st);
6225 501 break;
6226 }
6227 }
6228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!st) {
6229 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
6230 return 0;
6231 }
6232 501 sc = st->priv_data;
6233
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)
6234 return 0;
6235
6236 // Find the next frag_index index that has a valid index_entry for
6237 // the current track_id.
6238 //
6239 // A valid index_entry means the trun for the fragment was read
6240 // and it's samples are in index_entries at the given position.
6241 // New index entries will be inserted before the index_entry found.
6242 501 index_entry_pos = sti->nb_index_entries;
6243
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++) {
6244 1634 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
6245
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) {
6246 next_frag_index = i;
6247 index_entry_pos = frag_stream_info->index_entry;
6248 break;
6249 }
6250 }
6251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 av_assert0(index_entry_pos <= sti->nb_index_entries);
6252
6253 501 avio_r8(pb); /* version */
6254 501 flags = avio_rb24(pb);
6255 501 entries = avio_rb32(pb);
6256 501 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
6257
6258
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))
6259 return AVERROR_INVALIDDATA;
6260
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
6261
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);
6262
6263 501 int entry_size = !!(flags & MOV_TRUN_SAMPLE_DURATION) * 4
6264 501 + !!(flags & MOV_TRUN_SAMPLE_SIZE) * 4
6265 501 + !!(flags & MOV_TRUN_SAMPLE_FLAGS) * 4
6266 501 + !!(flags & MOV_TRUN_SAMPLE_CTS) * 4;
6267 501 int64_t sample_data_size = avio_size(sc->pb);
6268 501 int64_t max_entries = INT64_MAX;
6269
6270
2/2
✓ Branch 0 taken 500 times.
✓ Branch 1 taken 1 times.
501 if (sample_data_size > 0)
6271 500 max_entries = sample_data_size - sti->nb_index_entries;
6272
2/2
✓ Branch 0 taken 475 times.
✓ Branch 1 taken 26 times.
501 if (entry_size) {
6273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 475 times.
475 int64_t size = sc->pb == pb ? sample_data_size : avio_size(pb);
6274 475 int64_t pos = avio_tell(pb);
6275 475 int64_t left = atom.size - 8 - !!(flags & MOV_TRUN_DATA_OFFSET) * 4
6276 475 - !!(flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) * 4;
6277
6278
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)
6279 474 left = FFMIN(left, size - pos);
6280 475 max_entries = FFMIN(max_entries, left / entry_size);
6281 }
6282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (entries > max_entries) {
6283 av_log(c->fc, AV_LOG_ERROR, "trun sample count %u exceeds the %"PRId64" "
6284 "samples the input can hold\n", entries, max_entries);
6285 return AVERROR_INVALIDDATA;
6286 }
6287
6288 501 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6289
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (frag_stream_info) {
6290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
6291 dts = frag_stream_info->next_trun_dts - sc->time_offset;
6292
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 498 times.
501 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
6293
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
6294 3 pts = frag_stream_info->first_tfra_pts;
6295 3 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
6296 ", using it for pts\n", pts);
6297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 498 times.
498 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
6298 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
6299 dts = frag_stream_info->first_tfra_pts;
6300 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
6301 ", using it for dts\n", pts);
6302 } else {
6303 498 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
6304 498 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
6305
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;
6306
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;
6307
6308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 498 times.
498 if (fallback_sidx) {
6309 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
6310 }
6311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 498 times.
498 if (fallback_tfdt) {
6312 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
6313 }
6314
6315
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) {
6316 425 dts = frag_stream_info->tfdt_dts - sc->time_offset;
6317 425 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
6318 ", using it for dts\n", dts);
6319
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) {
6320 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
6321 // pts = frag_stream_info->sidx_pts;
6322 dts = frag_stream_info->sidx_pts;
6323 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
6324 ", using it for dts\n", frag_stream_info->sidx_pts);
6325 } else {
6326 73 dts = sc->track_end - sc->time_offset;
6327 73 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
6328 ", using it for dts\n", dts);
6329 }
6330 }
6331 } else {
6332 dts = sc->track_end - sc->time_offset;
6333 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
6334 ", using it for dts\n", dts);
6335 }
6336 501 offset = frag->base_data_offset + data_offset;
6337 501 distance = 0;
6338 501 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
6339
6340 // realloc space for new index entries
6341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
6342 entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
6343 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
6344 }
6345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (entries == 0)
6346 return 0;
6347
6348 501 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
6349 501 new_entries = av_fast_realloc(sti->index_entries,
6350 &sti->index_entries_allocated_size,
6351 requested_size);
6352
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!new_entries)
6353 return AVERROR(ENOMEM);
6354 501 sti->index_entries= new_entries;
6355
6356 501 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
6357 501 old_allocated_size = sc->tts_allocated_size;
6358 501 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
6359 requested_size);
6360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!tts_data)
6361 return AVERROR(ENOMEM);
6362 501 sc->tts_data = tts_data;
6363
6364 // In case there were samples without time to sample entries, ensure they get
6365 // zero valued entries. This ensures clips which mix boxes with and
6366 // without time to sample entries don't pickup uninitialized data.
6367 501 memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0,
6368 501 sc->tts_allocated_size - old_allocated_size);
6369
6370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (index_entry_pos < sti->nb_index_entries) {
6371 // Make hole in index_entries and tts_data for new samples
6372 memmove(sti->index_entries + index_entry_pos + entries,
6373 sti->index_entries + index_entry_pos,
6374 sizeof(*sti->index_entries) *
6375 (sti->nb_index_entries - index_entry_pos));
6376 memmove(sc->tts_data + index_entry_pos + entries,
6377 sc->tts_data + index_entry_pos,
6378 sizeof(*sc->tts_data) * (sc->tts_count - index_entry_pos));
6379 if (index_entry_pos < sc->current_sample) {
6380 sc->current_sample += entries;
6381 }
6382 }
6383
6384 501 sti->nb_index_entries += entries;
6385 501 sc->tts_count = sti->nb_index_entries;
6386 501 sc->stts_count = sti->nb_index_entries;
6387
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 115 times.
501 if (flags & MOV_TRUN_SAMPLE_CTS)
6388 386 sc->ctts_count = sti->nb_index_entries;
6389
6390 // Record the index_entry position in frag_index of this fragment
6391
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (frag_stream_info) {
6392 501 frag_stream_info->index_entry = index_entry_pos;
6393
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (frag_stream_info->index_base < 0)
6394 501 frag_stream_info->index_base = index_entry_pos;
6395 }
6396
6397
2/2
✓ Branch 0 taken 473 times.
✓ Branch 1 taken 28 times.
501 if (index_entry_pos > 0)
6398 473 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6399
6400
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++) {
6401 8717 unsigned sample_size = frag->size;
6402
2/2
✓ Branch 0 taken 8216 times.
✓ Branch 1 taken 501 times.
8717 int sample_flags = i ? frag->flags : first_sample_flags;
6403 8717 unsigned sample_duration = frag->duration;
6404 8717 unsigned ctts_duration = 0;
6405 8717 int keyframe = 0;
6406 8717 int index_entry_flags = 0;
6407
6408
2/2
✓ Branch 0 taken 1684 times.
✓ Branch 1 taken 7033 times.
8717 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
6409
2/2
✓ Branch 0 taken 8659 times.
✓ Branch 1 taken 58 times.
8717 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
6410
2/2
✓ Branch 0 taken 981 times.
✓ Branch 1 taken 7736 times.
8717 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
6411
2/2
✓ Branch 0 taken 6576 times.
✓ Branch 1 taken 2141 times.
8717 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
6412
6413
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8716 times.
8717 if (sample_duration > c->max_stts_delta) {
6414 1 av_log(c->fc, AV_LOG_WARNING,
6415 "Too large sample duration %u in trun entry %u in st:%d. Clipping to 1.\n",
6416 sample_duration, i, st->index);
6417 1 sample_duration = 1;
6418 }
6419
6420 8717 mov_update_dts_shift(sc, ctts_duration, c->fc);
6421
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8714 times.
8717 if (pts != AV_NOPTS_VALUE) {
6422 3 dts = pts - sc->dts_shift;
6423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (flags & MOV_TRUN_SAMPLE_CTS) {
6424 dts -= ctts_duration;
6425 } else {
6426 3 dts -= sc->time_offset;
6427 }
6428 3 av_log(c->fc, AV_LOG_DEBUG,
6429 "pts %"PRId64" calculated dts %"PRId64
6430 " sc->dts_shift %d ctts.duration %d"
6431 " sc->time_offset %"PRId64
6432 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
6433 pts, dts,
6434 sc->dts_shift, ctts_duration,
6435 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
6436 3 pts = AV_NOPTS_VALUE;
6437 }
6438
6439 8717 keyframe =
6440 8717 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
6441 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
6442
2/2
✓ Branch 0 taken 648 times.
✓ Branch 1 taken 8069 times.
8717 if (keyframe) {
6443 648 distance = 0;
6444 648 index_entry_flags |= AVINDEX_KEYFRAME;
6445 }
6446 // Fragments can overlap in time. Discard overlapping frames after
6447 // decoding.
6448
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8693 times.
8717 if (prev_dts >= dts)
6449 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
6450
6451 8717 sti->index_entries[index_entry_pos].pos = offset;
6452 8717 sti->index_entries[index_entry_pos].timestamp = dts;
6453 8717 sti->index_entries[index_entry_pos].size = sample_size;
6454 8717 sti->index_entries[index_entry_pos].min_distance = distance;
6455 8717 sti->index_entries[index_entry_pos].flags = index_entry_flags;
6456
6457 8717 sc->tts_data[index_entry_pos].count = 1;
6458 8717 sc->tts_data[index_entry_pos].offset = ctts_duration;
6459 8717 sc->tts_data[index_entry_pos].duration = sample_duration;
6460 8717 index_entry_pos++;
6461
6462 8717 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
6463 "size %u, distance %d, keyframe %d\n", st->index,
6464 index_entry_pos, offset, dts, sample_size, distance, keyframe);
6465 8717 distance++;
6466
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8717 times.
8717 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
6467 return AVERROR_INVALIDDATA;
6468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8717 times.
8717 if (!sample_size)
6469 return AVERROR_INVALIDDATA;
6470 8717 dts += sample_duration;
6471 8717 offset += sample_size;
6472 8717 sc->data_size += sample_size;
6473
6474
1/2
✓ Branch 0 taken 8717 times.
✗ Branch 1 not taken.
8717 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
6475
1/2
✓ Branch 0 taken 8717 times.
✗ Branch 1 not taken.
8717 1 <= INT_MAX - sc->nb_frames_for_fps
6476 ) {
6477 8717 sc->duration_for_fps += sample_duration;
6478 8717 sc->nb_frames_for_fps ++;
6479 }
6480 }
6481
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (frag_stream_info)
6482 501 frag_stream_info->next_trun_dts = dts + sc->time_offset;
6483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (i < entries) {
6484 // EOF found before reading all entries. Fix the hole this would
6485 // leave in index_entries and tts_data
6486 int gap = entries - i;
6487 memmove(sti->index_entries + index_entry_pos,
6488 sti->index_entries + index_entry_pos + gap,
6489 sizeof(*sti->index_entries) *
6490 (sti->nb_index_entries - (index_entry_pos + gap)));
6491 memmove(sc->tts_data + index_entry_pos,
6492 sc->tts_data + index_entry_pos + gap,
6493 sizeof(*sc->tts_data) *
6494 (sc->tts_count - (index_entry_pos + gap)));
6495
6496 sti->nb_index_entries -= gap;
6497 sc->tts_count -= gap;
6498 if (index_entry_pos < sc->current_sample) {
6499 sc->current_sample -= gap;
6500 }
6501 entries = i;
6502 }
6503
6504 // The end of this new fragment may overlap in time with the start
6505 // of the next fragment in index_entries. Mark the samples in the next
6506 // fragment that overlap with AVINDEX_DISCARD_FRAME
6507 501 prev_dts = AV_NOPTS_VALUE;
6508
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (index_entry_pos > 0)
6509 501 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
6511 if (prev_dts < sti->index_entries[i].timestamp)
6512 break;
6513 sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6514 }
6515
6516 // If a hole was created to insert the new index_entries into,
6517 // the index_entry recorded for all subsequent moof must
6518 // be incremented by the number of entries inserted.
6519 501 fix_frag_index_entries(&c->frag_index, next_frag_index,
6520 501 frag->track_id, entries);
6521
6522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (pb->eof_reached) {
6523 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6524 return AVERROR_EOF;
6525 }
6526
6527 501 frag->implicit_offset = offset;
6528
6529 501 sc->track_end = dts + sc->time_offset;
6530
2/2
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 383 times.
501 if (st->duration < sc->track_end)
6531 118 st->duration = sc->track_end;
6532
6533 501 return 0;
6534 }
6535
6536 46 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6537 {
6538 46 int64_t stream_size = avio_size(pb);
6539 46 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6540 uint8_t version, is_complete;
6541 int64_t offadd;
6542 unsigned i, j, track_id, item_count;
6543 46 AVStream *st = NULL;
6544 46 AVStream *ref_st = NULL;
6545 46 MOVStreamContext *sc, *ref_sc = NULL;
6546 AVRational timescale;
6547
6548 46 version = avio_r8(pb);
6549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (version > 1) {
6550 avpriv_request_sample(c->fc, "sidx version %u", version);
6551 return 0;
6552 }
6553
6554 46 avio_rb24(pb); // flags
6555
6556 46 track_id = avio_rb32(pb); // Reference ID
6557
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 for (i = 0; i < c->fc->nb_streams; i++) {
6558 46 sc = c->fc->streams[i]->priv_data;
6559
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 if (sc->id == track_id) {
6560 46 st = c->fc->streams[i];
6561 46 break;
6562 }
6563 }
6564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!st) {
6565 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6566 return 0;
6567 }
6568
6569 46 sc = st->priv_data;
6570
6571 46 timescale = av_make_q(1, avio_rb32(pb));
6572
6573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (timescale.den <= 0) {
6574 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6575 return AVERROR_INVALIDDATA;
6576 }
6577
6578
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1 times.
46 if (version == 0) {
6579 45 pts = avio_rb32(pb);
6580 45 offadd= avio_rb32(pb);
6581 } else {
6582 1 pts = avio_rb64(pb);
6583 1 offadd= avio_rb64(pb);
6584 }
6585
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6586 return AVERROR_INVALIDDATA;
6587
6588 46 offset += (uint64_t)offadd;
6589
6590 46 avio_rb16(pb); // reserved
6591
6592 46 item_count = avio_rb16(pb);
6593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (item_count == 0)
6594 return AVERROR_INVALIDDATA;
6595
6596
2/2
✓ Branch 0 taken 372 times.
✓ Branch 1 taken 46 times.
418 for (i = 0; i < item_count; i++) {
6597 int index;
6598 MOVFragmentStreamInfo * frag_stream_info;
6599 372 uint32_t size = avio_rb32(pb);
6600 372 uint32_t duration = avio_rb32(pb);
6601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
372 if (size & 0x80000000) {
6602 avpriv_request_sample(c->fc, "sidx reference_type 1");
6603 return AVERROR_PATCHWELCOME;
6604 }
6605 372 avio_rb32(pb); // sap_flags
6606 372 timestamp = av_rescale_q(pts, timescale, st->time_base);
6607
6608 372 index = update_frag_index(c, offset);
6609 372 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6610
1/2
✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
372 if (frag_stream_info)
6611 372 frag_stream_info->sidx_pts = timestamp;
6612
6613
1/2
✓ Branch 1 taken 372 times.
✗ Branch 2 not taken.
372 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6614
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 372 times.
372 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6615 )
6616 return AVERROR_INVALIDDATA;
6617 372 offset += size;
6618 372 pts += duration;
6619 }
6620
6621 46 st->duration = sc->track_end = pts;
6622
6623 46 sc->has_sidx = 1;
6624
6625 // See if the remaining bytes are just an mfra which we can ignore.
6626 46 is_complete = offset == stream_size;
6627
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 ) {
6628 int64_t ret;
6629 38 int64_t original_pos = avio_tell(pb);
6630
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
38 if (!c->have_read_mfra_size) {
6631
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6632 return ret;
6633 3 c->mfra_size = avio_rb32(pb);
6634 3 c->have_read_mfra_size = 1;
6635
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6636 return ret;
6637 }
6638
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (offset == stream_size - c->mfra_size)
6639 is_complete = 1;
6640 }
6641
6642
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 39 times.
46 if (is_complete) {
6643 // Find first entry in fragment index that came from an sidx.
6644 // This will pretty much always be the first entry.
6645
2/2
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 7 times.
378 for (i = 0; i < c->frag_index.nb_items; i++) {
6646 371 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6647
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++) {
6648 MOVFragmentStreamInfo * si;
6649 7 si = &item->stream_info[j];
6650
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (si->sidx_pts != AV_NOPTS_VALUE) {
6651 7 ref_st = c->fc->streams[j];
6652 7 ref_sc = ref_st->priv_data;
6653 7 break;
6654 }
6655 }
6656 }
6657
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++) {
6658 7 st = c->fc->streams[i];
6659 7 sc = st->priv_data;
6660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sc->has_sidx) {
6661 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6662 }
6663 }
6664
6665
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (offadd == 0)
6666 7 c->frag_index.complete = 1;
6667 }
6668
6669 46 return 0;
6670 }
6671
6672 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6673 /* like the files created with Adobe Premiere 5.0, for samples see */
6674 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6675 296 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6676 {
6677 int err;
6678
6679
1/2
✓ Branch 0 taken 296 times.
✗ Branch 1 not taken.
296 if (atom.size < 8)
6680 296 return 0; /* continue */
6681 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6682 avio_skip(pb, atom.size - 4);
6683 return 0;
6684 }
6685 atom.type = avio_rl32(pb);
6686 atom.size -= 8;
6687 if (atom.type != MKTAG('m','d','a','t')) {
6688 avio_skip(pb, atom.size);
6689 return 0;
6690 }
6691 err = mov_read_mdat(c, pb, atom);
6692 return err;
6693 }
6694
6695 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6696 {
6697 #if CONFIG_ZLIB
6698 FFIOContext ctx;
6699 uint8_t *cmov_data;
6700 uint8_t *moov_data; /* uncompressed data */
6701 long cmov_len, moov_len;
6702 3 int ret = -1;
6703
6704 3 avio_rb32(pb); /* dcom atom */
6705
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6706 return AVERROR_INVALIDDATA;
6707
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6708 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6709 return AVERROR_INVALIDDATA;
6710 }
6711 3 avio_rb32(pb); /* cmvd atom */
6712
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6713 return AVERROR_INVALIDDATA;
6714 3 moov_len = avio_rb32(pb); /* uncompressed size */
6715 3 cmov_len = atom.size - 6 * 4;
6716
6717 3 cmov_data = av_malloc(cmov_len);
6718
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6719 return AVERROR(ENOMEM);
6720 3 moov_data = av_malloc(moov_len);
6721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6722 av_free(cmov_data);
6723 return AVERROR(ENOMEM);
6724 }
6725 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6727 goto free_and_return;
6728
6729 3 ret = AVERROR_INVALIDDATA;
6730
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)
6731 goto free_and_return;
6732 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6733 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6734 3 atom.type = MKTAG('m','o','o','v');
6735 3 atom.size = moov_len;
6736 3 ret = mov_read_default(c, &ctx.pub, atom);
6737 3 free_and_return:
6738 3 av_free(moov_data);
6739 3 av_free(cmov_data);
6740 3 return ret;
6741 #else
6742 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6743 return AVERROR(ENOSYS);
6744 #endif
6745 }
6746
6747 /* edit list atom */
6748 527 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6749 {
6750 MOVStreamContext *sc;
6751 int i, edit_count, version;
6752 int64_t elst_entry_size;
6753
6754
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)
6755 return 0;
6756 527 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6757
6758 527 version = avio_r8(pb); /* version */
6759 527 avio_rb24(pb); /* flags */
6760 527 edit_count = avio_rb32(pb); /* entries */
6761 527 atom.size -= 8;
6762
6763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 527 times.
527 elst_entry_size = version == 1 ? 20 : 12;
6764
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 526 times.
527 if (atom.size != edit_count * elst_entry_size) {
6765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6766 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6767 edit_count, atom.size + 8);
6768 return AVERROR_INVALIDDATA;
6769 } else {
6770 1 edit_count = atom.size / elst_entry_size;
6771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6772 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6773 }
6774 }
6775 }
6776
6777
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 527 times.
527 if (!edit_count)
6778 return 0;
6779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 527 times.
527 if (sc->elst_data)
6780 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6781 527 av_free(sc->elst_data);
6782 527 sc->elst_count = 0;
6783 527 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 527 times.
527 if (!sc->elst_data)
6785 return AVERROR(ENOMEM);
6786
6787 527 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6788
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++) {
6789 556 MOVElst *e = &sc->elst_data[i];
6790
6791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 556 times.
556 if (version == 1) {
6792 e->duration = avio_rb64(pb);
6793 e->time = avio_rb64(pb);
6794 atom.size -= 16;
6795 } else {
6796 556 e->duration = avio_rb32(pb); /* segment duration */
6797 556 e->time = (int32_t)avio_rb32(pb); /* media time */
6798 556 atom.size -= 8;
6799 }
6800 556 e->rate = avio_rb32(pb) / 65536.0;
6801 556 atom.size -= 4;
6802 556 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6803 556 e->duration, e->time, e->rate);
6804
6805
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 &&
6806 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6807 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6808 c->fc->nb_streams-1, i, e->time);
6809 return AVERROR_INVALIDDATA;
6810 }
6811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 556 times.
556 if (e->duration < 0) {
6812 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list duration=%"PRId64"\n",
6813 c->fc->nb_streams-1, i, e->duration);
6814 return AVERROR_INVALIDDATA;
6815 }
6816 }
6817 527 sc->elst_count = i;
6818
6819 527 return 0;
6820 }
6821
6822 18 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6823 {
6824 MOVStreamContext *sc;
6825 int err;
6826
6827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->fc->nb_streams < 1)
6828 return AVERROR_INVALIDDATA;
6829 18 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6830
6831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size % sizeof(uint32_t))
6832 return AVERROR_INVALIDDATA;
6833
6834 18 MovTref *tag = mov_add_tref_tag(sc, atom.type);
6835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!tag)
6836 return AVERROR(ENOMEM);
6837
6838 18 int nb_timecode_track = atom.size >> 2;
6839
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 18 times.
40 for (int i = 0; i < nb_timecode_track; i++) {
6840
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 if (avio_feof(pb))
6841 return AVERROR_INVALIDDATA;
6842 22 err = mov_add_tref_id(tag, avio_rb32(pb));
6843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (err < 0)
6844 return err;
6845 }
6846
6847 18 return 0;
6848 }
6849
6850 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6851 {
6852 AVStream *st;
6853 int version, color_range, color_primaries, color_trc, color_space;
6854
6855 if (c->fc->nb_streams < 1)
6856 return 0;
6857 st = c->fc->streams[c->fc->nb_streams - 1];
6858
6859 if (atom.size < 5) {
6860 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6861 return AVERROR_INVALIDDATA;
6862 }
6863
6864 version = avio_r8(pb);
6865 if (version != 1) {
6866 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6867 return 0;
6868 }
6869 avio_skip(pb, 3); /* flags */
6870
6871 avio_skip(pb, 2); /* profile + level */
6872 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6873 color_primaries = avio_r8(pb);
6874 color_trc = avio_r8(pb);
6875 color_space = avio_r8(pb);
6876 if (avio_rb16(pb)) /* codecIntializationDataSize */
6877 return AVERROR_INVALIDDATA;
6878
6879 if (!av_color_primaries_name(color_primaries))
6880 color_primaries = AVCOL_PRI_UNSPECIFIED;
6881 if (!av_color_transfer_name(color_trc))
6882 color_trc = AVCOL_TRC_UNSPECIFIED;
6883 if (!av_color_space_name(color_space))
6884 color_space = AVCOL_SPC_UNSPECIFIED;
6885
6886 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6887 st->codecpar->color_primaries = color_primaries;
6888 st->codecpar->color_trc = color_trc;
6889 st->codecpar->color_space = color_space;
6890
6891 return 0;
6892 }
6893
6894 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6895 {
6896 MOVStreamContext *sc;
6897 int i, version;
6898
6899 if (c->fc->nb_streams < 1)
6900 return AVERROR_INVALIDDATA;
6901
6902 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6903
6904 if (atom.size < 5) {
6905 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6906 return AVERROR_INVALIDDATA;
6907 }
6908
6909 version = avio_r8(pb);
6910 if (version) {
6911 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6912 return 0;
6913 }
6914 if (sc->mastering) {
6915 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6916 return 0;
6917 }
6918
6919 avio_skip(pb, 3); /* flags */
6920
6921 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6922 if (!sc->mastering)
6923 return AVERROR(ENOMEM);
6924
6925 for (i = 0; i < 3; i++) {
6926 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6927 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6928 }
6929 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6930 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6931
6932 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6933 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6934
6935 sc->mastering->has_primaries = 1;
6936 sc->mastering->has_luminance = 1;
6937
6938 return 0;
6939 }
6940
6941 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6942 {
6943 MOVStreamContext *sc;
6944 const int mapping[3] = {1, 2, 0};
6945 const int chroma_den = 50000;
6946 const int luma_den = 10000;
6947 int i;
6948
6949 if (c->fc->nb_streams < 1)
6950 return AVERROR_INVALIDDATA;
6951
6952 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6953
6954 if (atom.size < 24) {
6955 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6956 return AVERROR_INVALIDDATA;
6957 }
6958
6959 if (sc->mastering) {
6960 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6961 return 0;
6962 }
6963
6964 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6965 if (!sc->mastering)
6966 return AVERROR(ENOMEM);
6967
6968 for (i = 0; i < 3; i++) {
6969 const int j = mapping[i];
6970 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6971 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6972 }
6973 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6974 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6975
6976 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6977 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6978
6979 sc->mastering->has_luminance = 1;
6980 sc->mastering->has_primaries = 1;
6981
6982 return 0;
6983 }
6984
6985 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6986 {
6987 MOVStreamContext *sc;
6988 int version;
6989
6990 if (c->fc->nb_streams < 1)
6991 return AVERROR_INVALIDDATA;
6992
6993 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6994
6995 if (atom.size < 5) {
6996 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
6997 return AVERROR_INVALIDDATA;
6998 }
6999
7000 version = avio_r8(pb);
7001 if (version) {
7002 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
7003 return 0;
7004 }
7005 avio_skip(pb, 3); /* flags */
7006
7007 if (sc->coll){
7008 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
7009 return 0;
7010 }
7011
7012 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
7013 if (!sc->coll)
7014 return AVERROR(ENOMEM);
7015
7016 sc->coll->MaxCLL = avio_rb16(pb);
7017 sc->coll->MaxFALL = avio_rb16(pb);
7018
7019 return 0;
7020 }
7021
7022 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7023 {
7024 MOVStreamContext *sc;
7025
7026 if (c->fc->nb_streams < 1)
7027 return AVERROR_INVALIDDATA;
7028
7029 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7030
7031 if (atom.size < 4) {
7032 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
7033 return AVERROR_INVALIDDATA;
7034 }
7035
7036 if (sc->coll){
7037 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
7038 return 0;
7039 }
7040
7041 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
7042 if (!sc->coll)
7043 return AVERROR(ENOMEM);
7044
7045 sc->coll->MaxCLL = avio_rb16(pb);
7046 sc->coll->MaxFALL = avio_rb16(pb);
7047
7048 return 0;
7049 }
7050
7051 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7052 {
7053 MOVStreamContext *sc;
7054 4 const int illuminance_den = 10000;
7055 4 const int ambient_den = 50000;
7056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
7057 return AVERROR_INVALIDDATA;
7058 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
7060 av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
7061 return AVERROR_INVALIDDATA;
7062 }
7063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
7064 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
7065 return 0;
7066 }
7067 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
7068
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
7069 return AVERROR(ENOMEM);
7070 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
7071 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
7072 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
7073 4 return 0;
7074 }
7075
7076 3 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7077 {
7078 AVStream *st;
7079 MOVStreamContext *sc;
7080 enum AVStereo3DType type;
7081 int mode;
7082
7083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7084 return 0;
7085
7086 3 st = c->fc->streams[c->fc->nb_streams - 1];
7087 3 sc = st->priv_data;
7088
7089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 5) {
7090 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
7091 return AVERROR_INVALIDDATA;
7092 }
7093
7094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->stereo3d)
7095 return AVERROR_INVALIDDATA;
7096
7097 3 avio_skip(pb, 4); /* version + flags */
7098
7099 3 mode = avio_r8(pb);
7100
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
3 switch (mode) {
7101 1 case 0:
7102 1 type = AV_STEREO3D_2D;
7103 1 break;
7104 case 1:
7105 type = AV_STEREO3D_TOPBOTTOM;
7106 break;
7107 2 case 2:
7108 2 type = AV_STEREO3D_SIDEBYSIDE;
7109 2 break;
7110 default:
7111 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
7112 return 0;
7113 }
7114
7115 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7117 return AVERROR(ENOMEM);
7118
7119 3 sc->stereo3d->type = type;
7120 3 return 0;
7121 }
7122
7123 static int mov_read_pack(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7124 {
7125 AVStream *st;
7126 MOVStreamContext *sc;
7127 int size = 0;
7128 int64_t remaining;
7129 uint32_t tag = 0;
7130 enum AVStereo3DType type = AV_STEREO3D_2D;
7131
7132 if (c->fc->nb_streams < 1)
7133 return 0;
7134
7135 st = c->fc->streams[c->fc->nb_streams - 1];
7136 sc = st->priv_data;
7137
7138 remaining = atom.size;
7139 while (remaining > 0) {
7140 size = avio_rb32(pb);
7141 if (size < 8 || size > remaining ) {
7142 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in pack box\n");
7143 return AVERROR_INVALIDDATA;
7144 }
7145
7146 tag = avio_rl32(pb);
7147 switch (tag) {
7148 case MKTAG('p','k','i','n'): {
7149 if (size != 16) {
7150 av_log(c->fc, AV_LOG_ERROR, "Invalid size of pkin box: %d\n", size);
7151 return AVERROR_INVALIDDATA;
7152 }
7153 avio_skip(pb, 1); // version
7154 avio_skip(pb, 3); // flags
7155
7156 tag = avio_rl32(pb);
7157 switch (tag) {
7158 case MKTAG('s','i','d','e'):
7159 type = AV_STEREO3D_SIDEBYSIDE;
7160 break;
7161 case MKTAG('o','v','e','r'):
7162 type = AV_STEREO3D_TOPBOTTOM;
7163 break;
7164 case 0:
7165 // This means value will be set in another layer
7166 break;
7167 default:
7168 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pkin: %s\n",
7169 av_fourcc2str(tag));
7170 avio_skip(pb, size - 8);
7171 break;
7172 }
7173
7174 break;
7175 }
7176 default:
7177 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pack: %s\n",
7178 av_fourcc2str(tag));
7179 avio_skip(pb, size - 8);
7180 break;
7181 }
7182 remaining -= size;
7183 }
7184
7185 if (remaining != 0) {
7186 av_log(c->fc, AV_LOG_ERROR, "Broken pack box\n");
7187 return AVERROR_INVALIDDATA;
7188 }
7189
7190 if (type == AV_STEREO3D_2D)
7191 return 0;
7192
7193 if (!sc->stereo3d) {
7194 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7195 if (!sc->stereo3d)
7196 return AVERROR(ENOMEM);
7197 }
7198
7199 sc->stereo3d->type = type;
7200
7201 return 0;
7202 }
7203
7204 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7205 {
7206 AVStream *st;
7207 MOVStreamContext *sc;
7208 int size, version, layout;
7209 int32_t yaw, pitch, roll;
7210 1 uint32_t l = 0, t = 0, r = 0, b = 0;
7211 1 uint32_t tag, padding = 0;
7212 enum AVSphericalProjection projection;
7213
7214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
7215 return 0;
7216
7217 1 st = c->fc->streams[c->fc->nb_streams - 1];
7218 1 sc = st->priv_data;
7219
7220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
7221 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
7222 return AVERROR_INVALIDDATA;
7223 }
7224
7225 1 size = avio_rb32(pb);
7226
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)
7227 return AVERROR_INVALIDDATA;
7228
7229 1 tag = avio_rl32(pb);
7230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
7231 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
7232 return 0;
7233 }
7234 1 version = avio_r8(pb);
7235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7236 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7237 version);
7238 return 0;
7239 }
7240 1 avio_skip(pb, 3); /* flags */
7241 1 avio_skip(pb, size - 12); /* metadata_source */
7242
7243 1 size = avio_rb32(pb);
7244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7245 return AVERROR_INVALIDDATA;
7246
7247 1 tag = avio_rl32(pb);
7248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
7249 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
7250 return 0;
7251 }
7252
7253 1 size = avio_rb32(pb);
7254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7255 return AVERROR_INVALIDDATA;
7256
7257 1 tag = avio_rl32(pb);
7258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
7259 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
7260 return 0;
7261 }
7262 1 version = avio_r8(pb);
7263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7264 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7265 version);
7266 return 0;
7267 }
7268 1 avio_skip(pb, 3); /* flags */
7269
7270 /* 16.16 fixed point */
7271 1 yaw = avio_rb32(pb);
7272 1 pitch = avio_rb32(pb);
7273 1 roll = avio_rb32(pb);
7274
7275 1 size = avio_rb32(pb);
7276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7277 return AVERROR_INVALIDDATA;
7278
7279 1 tag = avio_rl32(pb);
7280 1 version = avio_r8(pb);
7281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7282 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7283 version);
7284 return 0;
7285 }
7286 1 avio_skip(pb, 3); /* flags */
7287
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
7288 case MKTAG('c','b','m','p'):
7289 layout = avio_rb32(pb);
7290 if (layout) {
7291 av_log(c->fc, AV_LOG_WARNING,
7292 "Unsupported cubemap layout %d\n", layout);
7293 return 0;
7294 }
7295 projection = AV_SPHERICAL_CUBEMAP;
7296 padding = avio_rb32(pb);
7297 break;
7298 1 case MKTAG('e','q','u','i'):
7299 1 t = avio_rb32(pb);
7300 1 b = avio_rb32(pb);
7301 1 l = avio_rb32(pb);
7302 1 r = avio_rb32(pb);
7303
7304
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) {
7305 av_log(c->fc, AV_LOG_ERROR,
7306 "Invalid bounding rectangle coordinates "
7307 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
7308 return AVERROR_INVALIDDATA;
7309 }
7310
7311
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)
7312 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
7313 else
7314 projection = AV_SPHERICAL_EQUIRECTANGULAR;
7315 1 break;
7316 default:
7317 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
7318 return 0;
7319 }
7320
7321 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
7323 return AVERROR(ENOMEM);
7324
7325 1 sc->spherical->projection = projection;
7326
7327 1 sc->spherical->yaw = yaw;
7328 1 sc->spherical->pitch = pitch;
7329 1 sc->spherical->roll = roll;
7330
7331 1 sc->spherical->padding = padding;
7332
7333 1 sc->spherical->bound_left = l;
7334 1 sc->spherical->bound_top = t;
7335 1 sc->spherical->bound_right = r;
7336 1 sc->spherical->bound_bottom = b;
7337
7338 1 return 0;
7339 }
7340
7341 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7342 {
7343 AVStream *st;
7344 MOVStreamContext *sc;
7345 int size;
7346 uint32_t tag;
7347 enum AVSphericalProjection projection;
7348
7349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7350 return 0;
7351
7352 3 st = c->fc->streams[c->fc->nb_streams - 1];
7353 3 sc = st->priv_data;
7354
7355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 16) {
7356 av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
7357 return AVERROR_INVALIDDATA;
7358 }
7359
7360 3 size = avio_rb32(pb);
7361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size < 16) {
7362 av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
7363 return AVERROR_INVALIDDATA;
7364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (size > 16) {
7365 av_log(c->fc, AV_LOG_WARNING, "Box has more bytes (%d) than prji box required (16) \n", size);
7366 }
7367
7368 3 tag = avio_rl32(pb);
7369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
7370 av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: %s\n",
7371 av_fourcc2str(tag));
7372 return AVERROR_INVALIDDATA;
7373 }
7374
7375 // version and flags, only support (0, 0)
7376 3 unsigned n = avio_rl32(pb);
7377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (n != 0) {
7378 av_log(c->fc, AV_LOG_ERROR, "prji version %u, flag %u are not supported\n",
7379 n & 0xFF, n >> 8);
7380 return AVERROR_PATCHWELCOME;
7381 }
7382
7383 3 tag = avio_rl32(pb);
7384
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) {
7385 3 case MKTAG('r','e','c','t'):
7386 3 projection = AV_SPHERICAL_RECTILINEAR;
7387 3 break;
7388 case MKTAG('e','q','u','i'):
7389 projection = AV_SPHERICAL_EQUIRECTANGULAR;
7390 break;
7391 case MKTAG('h','e','q','u'):
7392 projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
7393 break;
7394 case MKTAG('f','i','s','h'):
7395 projection = AV_SPHERICAL_FISHEYE;
7396 break;
7397 case MKTAG('p','r','i','m'):
7398 projection = AV_SPHERICAL_PARAMETRIC_IMMERSIVE;
7399 break;
7400 default:
7401 av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: %s\n", av_fourcc2str(tag));
7402 return AVERROR_INVALIDDATA;
7403 }
7404
7405 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
7407 return AVERROR(ENOMEM);
7408
7409 3 sc->spherical->projection = projection;
7410
7411 3 return 0;
7412 }
7413
7414 5 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7415 {
7416 AVStream *st;
7417 MOVStreamContext *sc;
7418 5 int size, flags = 0;
7419 int64_t remaining;
7420 5 uint32_t tag, baseline = 0;
7421 5 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
7422 5 enum AVStereo3DType type = AV_STEREO3D_2D;
7423 5 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
7424 5 AVRational horizontal_disparity_adjustment = { 0, 1 };
7425
7426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
7427 return 0;
7428
7429 5 st = c->fc->streams[c->fc->nb_streams - 1];
7430 5 sc = st->priv_data;
7431
7432 5 remaining = atom.size;
7433
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 while (remaining > 0) {
7434 11 size = avio_rb32(pb);
7435
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 ) {
7436 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
7437 return AVERROR_INVALIDDATA;
7438 }
7439
7440 11 tag = avio_rl32(pb);
7441
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) {
7442 5 case MKTAG('s','t','r','i'): {
7443 int has_right, has_left;
7444 uint8_t tmp;
7445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (size != 13) {
7446 av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
7447 return AVERROR_INVALIDDATA;
7448 }
7449 5 avio_skip(pb, 1); // version
7450 5 avio_skip(pb, 3); // flags
7451
7452 5 tmp = avio_r8(pb);
7453
7454 // eye_views_reversed
7455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (tmp & 8) {
7456 flags |= AV_STEREO3D_FLAG_INVERT;
7457 }
7458 // has_additional_views
7459 5 if (tmp & 4) {
7460 // skip...
7461 }
7462
7463 5 has_right = tmp & 2; // has_right_eye_view
7464 5 has_left = tmp & 1; // has_left_eye_view
7465
7466
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)
7467 5 view = AV_STEREO3D_VIEW_PACKED;
7468 else if (has_left)
7469 view = AV_STEREO3D_VIEW_LEFT;
7470 else if (has_right)
7471 view = AV_STEREO3D_VIEW_RIGHT;
7472
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)
7473 5 type = AV_STEREO3D_UNSPEC;
7474
7475 5 break;
7476 }
7477 case MKTAG('h','e','r','o'): {
7478 int tmp;
7479 if (size != 13) {
7480 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
7481 return AVERROR_INVALIDDATA;
7482 }
7483 avio_skip(pb, 1); // version
7484 avio_skip(pb, 3); // flags
7485
7486 tmp = avio_r8(pb);
7487 if (tmp == 0)
7488 primary_eye = AV_PRIMARY_EYE_NONE;
7489 else if (tmp == 1)
7490 primary_eye = AV_PRIMARY_EYE_LEFT;
7491 else if (tmp == 2)
7492 primary_eye = AV_PRIMARY_EYE_RIGHT;
7493 else
7494 av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
7495
7496 break;
7497 }
7498 3 case MKTAG('c','a','m','s'): {
7499 uint32_t subtag;
7500 int subsize;
7501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7502 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
7503 return AVERROR_INVALIDDATA;
7504 }
7505
7506 3 subsize = avio_rb32(pb);
7507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7508 av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
7509 return AVERROR_INVALIDDATA;
7510 }
7511
7512 3 subtag = avio_rl32(pb);
7513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
7514 av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got %s\n",
7515 av_fourcc2str(subtag));
7516 return AVERROR_INVALIDDATA;
7517 }
7518
7519 3 avio_skip(pb, 1); // version
7520 3 avio_skip(pb, 3); // flags
7521
7522 3 baseline = avio_rb32(pb);
7523
7524 3 break;
7525 }
7526 3 case MKTAG('c','m','f','y'): {
7527 uint32_t subtag;
7528 int subsize;
7529 int32_t adjustment;
7530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7531 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
7532 return AVERROR_INVALIDDATA;
7533 }
7534
7535 3 subsize = avio_rb32(pb);
7536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7537 av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
7538 return AVERROR_INVALIDDATA;
7539 }
7540
7541 3 subtag = avio_rl32(pb);
7542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
7543 av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got %s\n",
7544 av_fourcc2str(subtag));
7545 return AVERROR_INVALIDDATA;
7546 }
7547
7548 3 avio_skip(pb, 1); // version
7549 3 avio_skip(pb, 3); // flags
7550
7551 3 adjustment = (int32_t) avio_rb32(pb);
7552
7553 3 horizontal_disparity_adjustment.num = (int) adjustment;
7554 3 horizontal_disparity_adjustment.den = 10000;
7555
7556 3 break;
7557 }
7558 default:
7559 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: %s\n",
7560 av_fourcc2str(tag));
7561 avio_skip(pb, size - 8);
7562 break;
7563 }
7564 11 remaining -= size;
7565 }
7566
7567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (remaining != 0) {
7568 av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
7569 return AVERROR_INVALIDDATA;
7570 }
7571
7572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (type == AV_STEREO3D_2D)
7573 return 0;
7574
7575
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (!sc->stereo3d) {
7576 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7577
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7578 return AVERROR(ENOMEM);
7579 }
7580
7581 5 sc->stereo3d->flags = flags;
7582 /* eyes/stri only records packed vs single-eye, not SBS/TB. Keep a more
7583 * specific type already set by st3d. */
7584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (type != AV_STEREO3D_UNSPEC)
7585 sc->stereo3d->type = type;
7586
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 else if (sc->stereo3d->type == AV_STEREO3D_2D)
7587 3 sc->stereo3d->type = type;
7588 5 sc->stereo3d->view = view;
7589 5 sc->stereo3d->primary_eye = primary_eye;
7590 5 sc->stereo3d->baseline = baseline;
7591 5 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
7592
7593 5 return 0;
7594 }
7595
7596 5 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7597 {
7598 int size;
7599 int64_t remaining;
7600 uint32_t tag;
7601
7602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
7603 return 0;
7604
7605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (atom.size < 8) {
7606 av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
7607 return AVERROR_INVALIDDATA;
7608 }
7609
7610 5 remaining = atom.size;
7611
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5 times.
13 while (remaining > 0) {
7612 8 size = avio_rb32(pb);
7613
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 ) {
7614 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
7615 return AVERROR_INVALIDDATA;
7616 }
7617
7618 8 tag = avio_rl32(pb);
7619
2/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 switch (tag) {
7620 3 case MKTAG('p','r','o','j'): {
7621 3 MOVAtom proj = { tag, size - 8 };
7622 3 int ret = mov_read_vexu_proj(c, pb, proj);
7623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7624 return ret;
7625 3 break;
7626 }
7627 5 case MKTAG('e','y','e','s'): {
7628 5 MOVAtom eyes = { tag, size - 8 };
7629 5 int ret = mov_read_eyes(c, pb, eyes);
7630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
7631 return ret;
7632 5 break;
7633 }
7634 case MKTAG('p','a','c','k'): {
7635 MOVAtom pack = { tag, size - 8 };
7636 int ret = mov_read_pack(c, pb, pack);
7637 if (ret < 0)
7638 return ret;
7639 break;
7640 }
7641 default:
7642 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: %s\n",
7643 av_fourcc2str(tag));
7644 avio_skip(pb, size - 8);
7645 break;
7646 }
7647 8 remaining -= size;
7648 }
7649
7650
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (remaining != 0) {
7651 av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7652 return AVERROR_INVALIDDATA;
7653 }
7654
7655 5 return 0;
7656 }
7657
7658 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7659 {
7660 AVStream *st;
7661 MOVStreamContext *sc;
7662
7663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7664 return 0;
7665
7666 3 st = c->fc->streams[c->fc->nb_streams - 1];
7667 3 sc = st->priv_data;
7668
7669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7670 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7671 return AVERROR_INVALIDDATA;
7672 }
7673
7674
7675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7676 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7677 if (!sc->stereo3d)
7678 return AVERROR(ENOMEM);
7679 }
7680
7681 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7682 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7683
7684 3 return 0;
7685 }
7686
7687 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7688 {
7689 int ret = 0;
7690 uint8_t *buffer = av_malloc(len + 1);
7691 const char *val;
7692
7693 if (!buffer)
7694 return AVERROR(ENOMEM);
7695 buffer[len] = '\0';
7696
7697 ret = ffio_read_size(pb, buffer, len);
7698 if (ret < 0)
7699 goto out;
7700
7701 /* Check for mandatory keys and values, try to support XML as best-effort */
7702 if (!sc->spherical &&
7703 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7704 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7705 av_stristr(val, "true") &&
7706 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7707 av_stristr(val, "true") &&
7708 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7709 av_stristr(val, "equirectangular")) {
7710 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7711 if (!sc->spherical)
7712 goto out;
7713
7714 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7715
7716 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7717 enum AVStereo3DType mode;
7718
7719 if (av_stristr(buffer, "left-right"))
7720 mode = AV_STEREO3D_SIDEBYSIDE;
7721 else if (av_stristr(buffer, "top-bottom"))
7722 mode = AV_STEREO3D_TOPBOTTOM;
7723 else
7724 mode = AV_STEREO3D_2D;
7725
7726 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7727 if (!sc->stereo3d)
7728 goto out;
7729
7730 sc->stereo3d->type = mode;
7731 }
7732
7733 /* orientation */
7734 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7735 if (val)
7736 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7737 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7738 if (val)
7739 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7740 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7741 if (val)
7742 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7743 }
7744
7745 out:
7746 av_free(buffer);
7747 return ret;
7748 }
7749
7750 69 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7751 {
7752 AVStream *st;
7753 MOVStreamContext *sc;
7754 int64_t ret;
7755 AVUUID uuid;
7756 static const AVUUID uuid_isml_manifest = {
7757 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7758 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7759 };
7760 static const AVUUID uuid_xmp = {
7761 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7762 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7763 };
7764 static const AVUUID uuid_spherical = {
7765 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7766 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7767 };
7768
7769
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))
7770 return AVERROR_INVALIDDATA;
7771
7772
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 66 times.
69 if (c->fc->nb_streams < 1)
7773 3 return 0;
7774 66 st = c->fc->streams[c->fc->nb_streams - 1];
7775 66 sc = st->priv_data;
7776
7777 66 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
7779 return ret;
7780
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7781 uint8_t *buffer, *ptr;
7782 char *endptr;
7783 size_t len = atom.size - AV_UUID_LEN;
7784
7785 if (len < 4) {
7786 return AVERROR_INVALIDDATA;
7787 }
7788 ret = avio_skip(pb, 4); // zeroes
7789 len -= 4;
7790
7791 buffer = av_mallocz(len + 1);
7792 if (!buffer) {
7793 return AVERROR(ENOMEM);
7794 }
7795 ret = ffio_read_size(pb, buffer, len);
7796 if (ret < 0) {
7797 av_free(buffer);
7798 return ret;
7799 }
7800
7801 ptr = buffer;
7802 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7803 ptr += sizeof("systemBitrate=\"") - 1;
7804 c->bitrates_count++;
7805 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7806 if (!c->bitrates) {
7807 c->bitrates_count = 0;
7808 av_free(buffer);
7809 return AVERROR(ENOMEM);
7810 }
7811 errno = 0;
7812 ret = strtol(ptr, &endptr, 10);
7813 if (ret < 0 || errno || *endptr != '"') {
7814 c->bitrates[c->bitrates_count - 1] = 0;
7815 } else {
7816 c->bitrates[c->bitrates_count - 1] = ret;
7817 }
7818 }
7819
7820 av_free(buffer);
7821
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7822 uint8_t *buffer;
7823 size_t len = atom.size - AV_UUID_LEN;
7824 if (c->export_xmp) {
7825 buffer = av_mallocz(len + 1);
7826 if (!buffer) {
7827 return AVERROR(ENOMEM);
7828 }
7829 ret = ffio_read_size(pb, buffer, len);
7830 if (ret < 0) {
7831 av_free(buffer);
7832 return ret;
7833 }
7834 buffer[len] = '\0';
7835 av_dict_set(&c->fc->metadata, "xmp",
7836 buffer, AV_DICT_DONT_STRDUP_VAL);
7837 } else {
7838 // skip all uuid atom, which makes it fast for long uuid-xmp file
7839 ret = avio_skip(pb, len);
7840 if (ret < 0)
7841 return ret;
7842 }
7843
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7844 size_t len = atom.size - AV_UUID_LEN;
7845 ret = mov_parse_uuid_spherical(sc, pb, len);
7846 if (ret < 0)
7847 return ret;
7848 if (!sc->spherical)
7849 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7850 }
7851
7852 66 return 0;
7853 }
7854
7855 255 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7856 {
7857 int ret;
7858 uint8_t content[16];
7859
7860
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 115 times.
255 if (atom.size < 8)
7861 140 return 0;
7862
7863 115 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7864
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 115 times.
115 if (ret < 0)
7865 return ret;
7866
7867
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 70 times.
115 if ( !c->found_moov
7868
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 23 times.
45 && !c->found_mdat
7869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 && !memcmp(content, "Anevia\x1A\x1A", 8)
7870 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7871 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7872 }
7873
7874 115 return 0;
7875 }
7876
7877 42 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7878 {
7879 42 uint32_t format = avio_rl32(pb);
7880 MOVStreamContext *sc;
7881 enum AVCodecID id;
7882 AVStream *st;
7883
7884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (c->fc->nb_streams < 1)
7885 return 0;
7886 42 st = c->fc->streams[c->fc->nb_streams - 1];
7887 42 sc = st->priv_data;
7888
7889
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 31 times.
42 switch (sc->format)
7890 {
7891 11 case MKTAG('e','n','c','v'): // encrypted video
7892 case MKTAG('e','n','c','a'): // encrypted audio
7893 11 id = mov_codec_id(st, format);
7894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7895 st->codecpar->codec_id != id) {
7896 av_log(c->fc, AV_LOG_WARNING,
7897 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7898 (char*)&format, st->codecpar->codec_id);
7899 break;
7900 }
7901
7902 11 st->codecpar->codec_id = id;
7903 11 sc->format = format;
7904 11 break;
7905
7906 31 default:
7907
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (format != sc->format) {
7908 av_log(c->fc, AV_LOG_WARNING,
7909 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7910 (char*)&format, (char*)&sc->format);
7911 }
7912 31 break;
7913 }
7914
7915 42 return 0;
7916 }
7917
7918 /**
7919 * Gets the current encryption info and associated current stream context. If
7920 * we are parsing a track fragment, this will return the specific encryption
7921 * info for this fragment; otherwise this will return the global encryption
7922 * info for the current stream.
7923 */
7924 27 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7925 {
7926 MOVFragmentStreamInfo *frag_stream_info;
7927 AVStream *st;
7928 int i;
7929
7930 27 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7931
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 21 times.
27 if (frag_stream_info) {
7932
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 for (i = 0; i < c->fc->nb_streams; i++) {
7933 6 *sc = c->fc->streams[i]->priv_data;
7934
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if ((*sc)->id == frag_stream_info->id) {
7935 6 st = c->fc->streams[i];
7936 6 break;
7937 }
7938 }
7939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (i == c->fc->nb_streams)
7940 return 0;
7941 6 *sc = st->priv_data;
7942
7943
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (!frag_stream_info->encryption_index) {
7944 // If this stream isn't encrypted, don't create the index.
7945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(*sc)->cenc.default_encrypted_sample)
7946 return 0;
7947 2 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7948
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!frag_stream_info->encryption_index)
7949 return AVERROR(ENOMEM);
7950 }
7951 6 *encryption_index = frag_stream_info->encryption_index;
7952 6 return 1;
7953 } else {
7954 // No current track fragment, using stream level encryption info.
7955
7956
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (c->fc->nb_streams < 1)
7957 return 0;
7958 21 st = c->fc->streams[c->fc->nb_streams - 1];
7959 21 *sc = st->priv_data;
7960
7961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!(*sc)->cenc.encryption_index) {
7962 // If this stream isn't encrypted, don't create the index.
7963 if (!(*sc)->cenc.default_encrypted_sample)
7964 return 0;
7965 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7966 if (!(*sc)->cenc.encryption_index)
7967 return AVERROR(ENOMEM);
7968 }
7969
7970 21 *encryption_index = (*sc)->cenc.encryption_index;
7971 21 return 1;
7972 }
7973 }
7974
7975 195 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7976 {
7977 int i, ret;
7978 unsigned int subsample_count;
7979 AVSubsampleEncryptionInfo *subsamples;
7980
7981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!sc->cenc.default_encrypted_sample) {
7982 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7983 return AVERROR_INVALIDDATA;
7984 }
7985
7986
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) {
7987 195 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*sample)
7989 return AVERROR(ENOMEM);
7990 } else
7991 *sample = NULL;
7992
7993
1/2
✓ Branch 0 taken 195 times.
✗ Branch 1 not taken.
195 if (sc->cenc.per_sample_iv_size != 0) {
7994
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) {
7995 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
7996 av_encryption_info_free(*sample);
7997 *sample = NULL;
7998 return ret;
7999 }
8000 }
8001
8002
1/2
✓ Branch 0 taken 195 times.
✗ Branch 1 not taken.
195 if (use_subsamples) {
8003 195 subsample_count = avio_rb16(pb);
8004 195 av_free((*sample)->subsamples);
8005 195 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
8006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!(*sample)->subsamples) {
8007 av_encryption_info_free(*sample);
8008 *sample = NULL;
8009 return AVERROR(ENOMEM);
8010 }
8011
8012
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++) {
8013 272 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
8014 272 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
8015 }
8016
8017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (pb->eof_reached) {
8018 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
8019 av_encryption_info_free(*sample);
8020 *sample = NULL;
8021 return AVERROR_INVALIDDATA;
8022 }
8023 195 (*sample)->subsample_count = subsample_count;
8024 }
8025
8026 195 return 0;
8027 }
8028
8029 9 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8030 {
8031 AVEncryptionInfo **encrypted_samples;
8032 MOVEncryptionIndex *encryption_index;
8033 MOVStreamContext *sc;
8034 int use_subsamples, ret;
8035 9 unsigned int sample_count, i, alloc_size = 0;
8036
8037 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8039 return ret;
8040
8041
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (encryption_index->nb_encrypted_samples) {
8042 // This can happen if we have both saio/saiz and senc atoms.
8043 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
8044 2 return 0;
8045 }
8046
8047 7 avio_r8(pb); /* version */
8048 7 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
8049
8050 7 sample_count = avio_rb32(pb);
8051
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
8052 return AVERROR(ENOMEM);
8053
8054
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 7 times.
154 for (i = 0; i < sample_count; i++) {
8055 147 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
8056 147 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
8057 min_samples * sizeof(*encrypted_samples));
8058
1/2
✓ Branch 0 taken 147 times.
✗ Branch 1 not taken.
147 if (encrypted_samples) {
8059 147 encryption_index->encrypted_samples = encrypted_samples;
8060
8061 147 ret = mov_read_sample_encryption_info(
8062 147 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
8063 } else {
8064 ret = AVERROR(ENOMEM);
8065 }
8066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
147 if (pb->eof_reached) {
8067 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
8068 if (ret >= 0)
8069 av_encryption_info_free(encryption_index->encrypted_samples[i]);
8070 ret = AVERROR_INVALIDDATA;
8071 }
8072
8073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
147 if (ret < 0) {
8074 for (; i > 0; i--)
8075 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
8076 av_freep(&encryption_index->encrypted_samples);
8077 return ret;
8078 }
8079 }
8080 7 encryption_index->nb_encrypted_samples = sample_count;
8081
8082 7 return 0;
8083 }
8084
8085 2 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
8086 {
8087 AVEncryptionInfo **sample, **encrypted_samples;
8088 int64_t prev_pos;
8089 size_t sample_count, sample_info_size, i;
8090 2 int ret = 0;
8091 2 unsigned int alloc_size = 0;
8092
8093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->nb_encrypted_samples)
8094 return 0;
8095 2 sample_count = encryption_index->auxiliary_info_sample_count;
8096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count != 1) {
8097 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
8098 return AVERROR_PATCHWELCOME;
8099 }
8100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
8101 return AVERROR(ENOMEM);
8102
8103 2 prev_pos = avio_tell(pb);
8104
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
8105
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]) {
8106 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
8107 goto finish;
8108 }
8109
8110
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++) {
8111 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
8112 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
8113 min_samples * sizeof(*encrypted_samples));
8114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (!encrypted_samples) {
8115 ret = AVERROR(ENOMEM);
8116 goto finish;
8117 }
8118 48 encryption_index->encrypted_samples = encrypted_samples;
8119
8120 48 sample = &encryption_index->encrypted_samples[i];
8121 96 sample_info_size = encryption_index->auxiliary_info_default_size
8122 48 ? encryption_index->auxiliary_info_default_size
8123
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 : encryption_index->auxiliary_info_sizes[i];
8124
8125 48 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
8126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0)
8127 goto finish;
8128 }
8129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
8130 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
8131 ret = AVERROR_INVALIDDATA;
8132 } else {
8133 2 encryption_index->nb_encrypted_samples = sample_count;
8134 }
8135
8136 2 finish:
8137 2 avio_seek(pb, prev_pos, SEEK_SET);
8138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
8139 for (; i > 0; i--) {
8140 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
8141 }
8142 av_freep(&encryption_index->encrypted_samples);
8143 }
8144 2 return ret;
8145 }
8146
8147 9 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8148 {
8149 MOVEncryptionIndex *encryption_index;
8150 MOVStreamContext *sc;
8151 int ret;
8152 unsigned int sample_count, aux_info_type, aux_info_param;
8153
8154 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8156 return ret;
8157
8158
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (encryption_index->nb_encrypted_samples) {
8159 // This can happen if we have both saio/saiz and senc atoms.
8160 7 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
8161 7 return 0;
8162 }
8163
8164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_sample_count) {
8165 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
8166 return AVERROR_INVALIDDATA;
8167 }
8168
8169 2 avio_r8(pb); /* version */
8170
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
8171 aux_info_type = avio_rb32(pb);
8172 aux_info_param = avio_rb32(pb);
8173 if (sc->cenc.default_encrypted_sample) {
8174 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
8175 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
8176 return 0;
8177 }
8178 if (aux_info_param != 0) {
8179 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
8180 return 0;
8181 }
8182 } else {
8183 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8184 if ((aux_info_type == MKBETAG('c','e','n','c') ||
8185 aux_info_type == MKBETAG('c','e','n','s') ||
8186 aux_info_type == MKBETAG('c','b','c','1') ||
8187 aux_info_type == MKBETAG('c','b','c','s')) &&
8188 aux_info_param == 0) {
8189 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
8190 return AVERROR_INVALIDDATA;
8191 } else {
8192 return 0;
8193 }
8194 }
8195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
8196 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8197 return 0;
8198 }
8199
8200 2 encryption_index->auxiliary_info_default_size = avio_r8(pb);
8201 2 sample_count = avio_rb32(pb);
8202
8203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_default_size == 0) {
8204 if (sample_count == 0)
8205 return AVERROR_INVALIDDATA;
8206
8207 encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
8208 if (!encryption_index->auxiliary_info_sizes)
8209 return AVERROR(ENOMEM);
8210
8211 ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
8212 if (ret != sample_count) {
8213 av_freep(&encryption_index->auxiliary_info_sizes);
8214
8215 if (ret >= 0)
8216 ret = AVERROR_INVALIDDATA;
8217 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
8218 av_err2str(ret));
8219 return ret;
8220 }
8221 }
8222 2 encryption_index->auxiliary_info_sample_count = sample_count;
8223
8224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
8225 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
8226 }
8227
8228 2 return 0;
8229 }
8230
8231 9 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8232 {
8233 uint64_t *auxiliary_offsets;
8234 MOVEncryptionIndex *encryption_index;
8235 MOVStreamContext *sc;
8236 int i, ret;
8237 unsigned int version, entry_count, aux_info_type, aux_info_param;
8238 9 unsigned int alloc_size = 0;
8239
8240 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8242 return ret;
8243
8244
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (encryption_index->nb_encrypted_samples) {
8245 // This can happen if we have both saio/saiz and senc atoms.
8246 7 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
8247 7 return 0;
8248 }
8249
8250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
8251 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
8252 return AVERROR_INVALIDDATA;
8253 }
8254
8255 2 version = avio_r8(pb); /* version */
8256
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
8257 aux_info_type = avio_rb32(pb);
8258 aux_info_param = avio_rb32(pb);
8259 if (sc->cenc.default_encrypted_sample) {
8260 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
8261 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
8262 return 0;
8263 }
8264 if (aux_info_param != 0) {
8265 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
8266 return 0;
8267 }
8268 } else {
8269 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8270 if ((aux_info_type == MKBETAG('c','e','n','c') ||
8271 aux_info_type == MKBETAG('c','e','n','s') ||
8272 aux_info_type == MKBETAG('c','b','c','1') ||
8273 aux_info_type == MKBETAG('c','b','c','s')) &&
8274 aux_info_param == 0) {
8275 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
8276 return AVERROR_INVALIDDATA;
8277 } else {
8278 return 0;
8279 }
8280 }
8281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
8282 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8283 return 0;
8284 }
8285
8286 2 entry_count = avio_rb32(pb);
8287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
8288 return AVERROR(ENOMEM);
8289
8290
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++) {
8291
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);
8292 2 auxiliary_offsets = av_fast_realloc(
8293 2 encryption_index->auxiliary_offsets, &alloc_size,
8294 min_offsets * sizeof(*auxiliary_offsets));
8295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!auxiliary_offsets) {
8296 av_freep(&encryption_index->auxiliary_offsets);
8297 return AVERROR(ENOMEM);
8298 }
8299 2 encryption_index->auxiliary_offsets = auxiliary_offsets;
8300
8301
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version == 0) {
8302 2 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
8303 } else {
8304 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
8305 }
8306
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (c->frag_index.current >= 0) {
8307 2 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
8308 }
8309 }
8310
8311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
8312 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
8313 av_freep(&encryption_index->auxiliary_offsets);
8314 return AVERROR_INVALIDDATA;
8315 }
8316
8317 2 encryption_index->auxiliary_offsets_count = entry_count;
8318
8319
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (encryption_index->auxiliary_info_sample_count) {
8320 2 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
8321 }
8322
8323 return 0;
8324 }
8325
8326 4 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8327 {
8328 AVEncryptionInitInfo *info, *old_init_info;
8329 uint8_t **key_ids;
8330 AVStream *st;
8331 const AVPacketSideData *old_side_data;
8332 uint8_t *side_data, *extra_data;
8333 size_t side_data_size;
8334 4 int ret = 0;
8335 4 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
8336
8337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8338 return 0;
8339 4 st = c->fc->streams[c->fc->nb_streams-1];
8340
8341 4 version = avio_r8(pb); /* version */
8342 4 avio_rb24(pb); /* flags */
8343
8344 4 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
8345 /* key_id_size */ 16, /* data_size */ 0);
8346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info)
8347 return AVERROR(ENOMEM);
8348
8349
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
8350 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
8351 goto finish;
8352 }
8353
8354
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (version > 0) {
8355 4 kid_count = avio_rb32(pb);
8356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
8357 ret = AVERROR(ENOMEM);
8358 goto finish;
8359 }
8360
8361
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++) {
8362 4 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
8363 4 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
8364 min_kid_count * sizeof(*key_ids));
8365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!key_ids) {
8366 ret = AVERROR(ENOMEM);
8367 goto finish;
8368 }
8369 4 info->key_ids = key_ids;
8370
8371 4 info->key_ids[i] = av_mallocz(16);
8372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info->key_ids[i]) {
8373 ret = AVERROR(ENOMEM);
8374 goto finish;
8375 }
8376 4 info->num_key_ids = i + 1;
8377
8378
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
8379 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
8380 goto finish;
8381 }
8382 }
8383
8384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pb->eof_reached) {
8385 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
8386 ret = AVERROR_INVALIDDATA;
8387 goto finish;
8388 }
8389 }
8390
8391 4 extra_data_size = avio_rb32(pb);
8392 4 extra_data = av_malloc(extra_data_size);
8393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!extra_data) {
8394 ret = AVERROR(ENOMEM);
8395 goto finish;
8396 }
8397 4 ret = avio_read(pb, extra_data, extra_data_size);
8398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != extra_data_size) {
8399 av_free(extra_data);
8400
8401 if (ret >= 0)
8402 ret = AVERROR_INVALIDDATA;
8403 goto finish;
8404 }
8405
8406 4 av_freep(&info->data); // malloc(0) may still allocate something.
8407 4 info->data = extra_data;
8408 4 info->data_size = extra_data_size;
8409
8410 // If there is existing initialization data, append to the list.
8411 4 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
8412 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
8413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (old_side_data) {
8414 old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
8415 if (old_init_info) {
8416 // Append to the end of the list.
8417 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
8418 if (!cur->next) {
8419 cur->next = info;
8420 break;
8421 }
8422 }
8423 info = old_init_info;
8424 } else {
8425 // Assume existing side-data will be valid, so the only error we could get is OOM.
8426 ret = AVERROR(ENOMEM);
8427 goto finish;
8428 }
8429 }
8430
8431 4 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
8432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!side_data) {
8433 ret = AVERROR(ENOMEM);
8434 goto finish;
8435 }
8436
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
8437 4 &st->codecpar->nb_coded_side_data,
8438 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
8439 side_data, side_data_size, 0))
8440 av_free(side_data);
8441
8442 4 finish:
8443 4 av_encryption_init_info_free(info);
8444 4 return ret;
8445 }
8446
8447 11 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8448 {
8449 AVStream *st;
8450 MOVStreamContext *sc;
8451
8452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
8453 return 0;
8454 11 st = c->fc->streams[c->fc->nb_streams-1];
8455 11 sc = st->priv_data;
8456
8457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (sc->pseudo_stream_id != 0) {
8458 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
8459 return AVERROR_PATCHWELCOME;
8460 }
8461
8462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
8463 return AVERROR_INVALIDDATA;
8464
8465 11 avio_rb32(pb); /* version and flags */
8466
8467
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (!sc->cenc.default_encrypted_sample) {
8468 11 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.default_encrypted_sample) {
8470 return AVERROR(ENOMEM);
8471 }
8472 }
8473
8474 11 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
8475 11 return 0;
8476 }
8477
8478 11 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8479 {
8480 AVStream *st;
8481 MOVStreamContext *sc;
8482 unsigned int version, pattern, is_protected, iv_size;
8483
8484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
8485 return 0;
8486 11 st = c->fc->streams[c->fc->nb_streams-1];
8487 11 sc = st->priv_data;
8488
8489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (sc->pseudo_stream_id != 0) {
8490 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
8491 return AVERROR_PATCHWELCOME;
8492 }
8493
8494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.default_encrypted_sample) {
8495 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8496 if (!sc->cenc.default_encrypted_sample) {
8497 return AVERROR(ENOMEM);
8498 }
8499 }
8500
8501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 20)
8502 return AVERROR_INVALIDDATA;
8503
8504 11 version = avio_r8(pb); /* version */
8505 11 avio_rb24(pb); /* flags */
8506
8507 11 avio_r8(pb); /* reserved */
8508 11 pattern = avio_r8(pb);
8509
8510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (version > 0) {
8511 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
8512 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
8513 }
8514
8515 11 is_protected = avio_r8(pb);
8516
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) {
8517 // The whole stream should be by-default encrypted.
8518 11 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
8519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.encryption_index)
8520 return AVERROR(ENOMEM);
8521 }
8522 11 sc->cenc.per_sample_iv_size = avio_r8(pb);
8523
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 &&
8524 sc->cenc.per_sample_iv_size != 16) {
8525 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
8526 return AVERROR_INVALIDDATA;
8527 }
8528
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) {
8529 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
8530 return AVERROR_INVALIDDATA;
8531 }
8532
8533
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) {
8534 2 iv_size = avio_r8(pb);
8535
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) {
8536 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
8537 return AVERROR_INVALIDDATA;
8538 }
8539
8540
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) {
8541 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
8542 return AVERROR_INVALIDDATA;
8543 }
8544 }
8545
8546 11 return 0;
8547 }
8548
8549 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8550 {
8551 AVStream *st;
8552 int last, type, size, ret;
8553 uint8_t buf[4];
8554
8555 if (c->fc->nb_streams < 1)
8556 return 0;
8557 st = c->fc->streams[c->fc->nb_streams-1];
8558
8559 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
8560 return AVERROR_INVALIDDATA;
8561
8562 /* Check FlacSpecificBox version. */
8563 if (avio_r8(pb) != 0)
8564 return AVERROR_INVALIDDATA;
8565
8566 avio_rb24(pb); /* Flags */
8567
8568 if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
8569 av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
8570 return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
8571 }
8572 flac_parse_block_header(buf, &last, &type, &size);
8573
8574 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
8575 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
8576 return AVERROR_INVALIDDATA;
8577 }
8578
8579 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
8580 if (ret < 0)
8581 return ret;
8582
8583 if (!last)
8584 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
8585
8586 return 0;
8587 }
8588
8589 11 static int get_key_from_kid(uint8_t* out, int len, MOVContext *c, AVEncryptionInfo *sample) {
8590 AVDictionaryEntry *key_entry_hex;
8591 char kid_hex[16*2+1];
8592
8593
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) {
8594 av_log(c->fc, AV_LOG_ERROR, "invalid default decryption key length: got %d, expected %d\n", c->decryption_default_key_len, len);
8595 return -1;
8596 }
8597
8598
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
11 if (!c->decryption_keys) {
8599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 av_assert0(c->decryption_default_key);
8600 8 memcpy(out, c->decryption_default_key, len);
8601 8 return 0;
8602 }
8603
8604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sample->key_id_size != 16) {
8605 av_log(c->fc, AV_LOG_ERROR, "invalid key ID size: got %u, expected 16\n", sample->key_id_size);
8606 return -1;
8607 }
8608
8609 3 ff_data_to_hex(kid_hex, sample->key_id, 16, 1);
8610 3 key_entry_hex = av_dict_get(c->decryption_keys, kid_hex, NULL, AV_DICT_DONT_STRDUP_KEY|AV_DICT_DONT_STRDUP_VAL);
8611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!key_entry_hex) {
8612 if (!c->decryption_default_key) {
8613 av_log(c->fc, AV_LOG_ERROR, "unable to find KID %s\n", kid_hex);
8614 return -1;
8615 }
8616 memcpy(out, c->decryption_default_key, len);
8617 return 0;
8618 }
8619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (strlen(key_entry_hex->value) != len*2) {
8620 return -1;
8621 }
8622 3 ff_hex_to_data(out, key_entry_hex->value);
8623 3 return 0;
8624 }
8625
8626 341 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8627 {
8628 int i, ret;
8629 int bytes_of_protected_data;
8630 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8631
8632
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 330 times.
341 if (!sc->cenc.aes_ctr) {
8633 11 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0) {
8635 return ret;
8636 }
8637
8638 /* initialize the cipher */
8639 11 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.aes_ctr) {
8641 return AVERROR(ENOMEM);
8642 }
8643
8644 11 ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0) {
8646 return ret;
8647 }
8648 }
8649
8650 341 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8651
8652
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 245 times.
341 if (!sample->subsample_count) {
8653 /* decrypt the whole packet */
8654 96 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8655 96 return 0;
8656 }
8657
8658
2/2
✓ Branch 0 taken 321 times.
✓ Branch 1 taken 245 times.
566 for (i = 0; i < sample->subsample_count; i++) {
8659
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) {
8660 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8661 return AVERROR_INVALIDDATA;
8662 }
8663
8664 /* skip the clear bytes */
8665 321 input += sample->subsamples[i].bytes_of_clear_data;
8666 321 size -= sample->subsamples[i].bytes_of_clear_data;
8667
8668 /* decrypt the encrypted bytes */
8669
8670 321 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
8671 321 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
8672
8673 321 input += bytes_of_protected_data;
8674 321 size -= bytes_of_protected_data;
8675 }
8676
8677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
245 if (size > 0) {
8678 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8679 return AVERROR_INVALIDDATA;
8680 }
8681
8682 245 return 0;
8683 }
8684
8685 static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8686 {
8687 int i, ret;
8688 int num_of_encrypted_blocks;
8689 uint8_t iv[16];
8690 uint8_t decryption_key[16];
8691
8692 if (!sc->cenc.aes_ctx) {
8693 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8694 if (ret < 0) {
8695 return ret;
8696 }
8697
8698 /* initialize the cipher */
8699 sc->cenc.aes_ctx = av_aes_alloc();
8700 if (!sc->cenc.aes_ctx) {
8701 return AVERROR(ENOMEM);
8702 }
8703
8704 ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8705 if (ret < 0) {
8706 return ret;
8707 }
8708 }
8709
8710 memcpy(iv, sample->iv, 16);
8711
8712 /* whole-block full sample encryption */
8713 if (!sample->subsample_count) {
8714 /* decrypt the whole packet */
8715 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8716 return 0;
8717 }
8718
8719 for (i = 0; i < sample->subsample_count; i++) {
8720 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8721 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8722 return AVERROR_INVALIDDATA;
8723 }
8724
8725 if (sample->subsamples[i].bytes_of_protected_data % 16) {
8726 av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8727 return AVERROR_INVALIDDATA;
8728 }
8729
8730 /* skip the clear bytes */
8731 input += sample->subsamples[i].bytes_of_clear_data;
8732 size -= sample->subsamples[i].bytes_of_clear_data;
8733
8734 /* decrypt the encrypted bytes */
8735 num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8736 if (num_of_encrypted_blocks > 0) {
8737 av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8738 }
8739 input += sample->subsamples[i].bytes_of_protected_data;
8740 size -= sample->subsamples[i].bytes_of_protected_data;
8741 }
8742
8743 if (size > 0) {
8744 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8745 return AVERROR_INVALIDDATA;
8746 }
8747
8748 return 0;
8749 }
8750
8751 static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8752 {
8753 int i, ret, rem_bytes;
8754 uint8_t *data;
8755 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8756
8757 if (!sc->cenc.aes_ctr) {
8758 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8759 if (ret < 0) {
8760 return ret;
8761 }
8762
8763 /* initialize the cipher */
8764 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8765 if (!sc->cenc.aes_ctr) {
8766 return AVERROR(ENOMEM);
8767 }
8768
8769 ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8770 if (ret < 0) {
8771 return ret;
8772 }
8773 }
8774
8775 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8776
8777 /* whole-block full sample encryption */
8778 if (!sample->subsample_count) {
8779 /* decrypt the whole packet */
8780 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8781 return 0;
8782 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8783 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8784 return AVERROR_INVALIDDATA;
8785 }
8786
8787 for (i = 0; i < sample->subsample_count; i++) {
8788 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8789 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8790 return AVERROR_INVALIDDATA;
8791 }
8792
8793 /* skip the clear bytes */
8794 input += sample->subsamples[i].bytes_of_clear_data;
8795 size -= sample->subsamples[i].bytes_of_clear_data;
8796
8797 /* decrypt the encrypted bytes */
8798 data = input;
8799 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8800 while (rem_bytes > 0) {
8801 if (rem_bytes < 16*sample->crypt_byte_block) {
8802 break;
8803 }
8804 av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8805 data += 16*sample->crypt_byte_block;
8806 rem_bytes -= 16*sample->crypt_byte_block;
8807 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8808 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8809 }
8810 input += sample->subsamples[i].bytes_of_protected_data;
8811 size -= sample->subsamples[i].bytes_of_protected_data;
8812 }
8813
8814 if (size > 0) {
8815 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8816 return AVERROR_INVALIDDATA;
8817 }
8818
8819 return 0;
8820 }
8821
8822 static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8823 {
8824 int i, ret, rem_bytes;
8825 uint8_t iv[16];
8826 uint8_t *data;
8827 uint8_t decryption_key[16];
8828
8829 if (!sc->cenc.aes_ctx) {
8830 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8831 if (ret < 0) {
8832 return ret;
8833 }
8834
8835 /* initialize the cipher */
8836 sc->cenc.aes_ctx = av_aes_alloc();
8837 if (!sc->cenc.aes_ctx) {
8838 return AVERROR(ENOMEM);
8839 }
8840
8841 ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8842 if (ret < 0) {
8843 return ret;
8844 }
8845 }
8846
8847 /* whole-block full sample encryption */
8848 if (!sample->subsample_count) {
8849 /* decrypt the whole packet */
8850 memcpy(iv, sample->iv, 16);
8851 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8852 return 0;
8853 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8854 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8855 return AVERROR_INVALIDDATA;
8856 }
8857
8858 for (i = 0; i < sample->subsample_count; i++) {
8859 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8860 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8861 return AVERROR_INVALIDDATA;
8862 }
8863
8864 /* skip the clear bytes */
8865 input += sample->subsamples[i].bytes_of_clear_data;
8866 size -= sample->subsamples[i].bytes_of_clear_data;
8867
8868 /* decrypt the encrypted bytes */
8869 memcpy(iv, sample->iv, 16);
8870 data = input;
8871 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8872 while (rem_bytes > 0) {
8873 if (rem_bytes < 16*sample->crypt_byte_block) {
8874 break;
8875 }
8876 av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8877 data += 16*sample->crypt_byte_block;
8878 rem_bytes -= 16*sample->crypt_byte_block;
8879 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8880 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8881 }
8882 input += sample->subsamples[i].bytes_of_protected_data;
8883 size -= sample->subsamples[i].bytes_of_protected_data;
8884 }
8885
8886 if (size > 0) {
8887 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8888 return AVERROR_INVALIDDATA;
8889 }
8890
8891 return 0;
8892 }
8893
8894 341 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8895 {
8896
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) {
8897 341 return cenc_scheme_decrypt(c, sc, sample, input, size);
8898 } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8899 return cbc1_scheme_decrypt(c, sc, sample, input, size);
8900 } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8901 return cens_scheme_decrypt(c, sc, sample, input, size);
8902 } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8903 return cbcs_scheme_decrypt(c, sc, sample, input, size);
8904 } else {
8905 av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8906 return AVERROR_INVALIDDATA;
8907 }
8908 }
8909
8910 107869 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8911 {
8912 107869 int current = frag_index->current;
8913
8914
2/2
✓ Branch 0 taken 106884 times.
✓ Branch 1 taken 985 times.
107869 if (!frag_index->nb_items)
8915 106884 return NULL;
8916
8917 // Check frag_index->current is the right one for pkt. It can out of sync.
8918
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) {
8919
2/2
✓ Branch 0 taken 958 times.
✓ Branch 1 taken 27 times.
985 if (frag_index->item[current].moof_offset < pkt->pos &&
8920
2/2
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 346 times.
958 (current + 1 == frag_index->nb_items ||
8921
2/2
✓ Branch 0 taken 536 times.
✓ Branch 1 taken 76 times.
612 frag_index->item[current + 1].moof_offset > pkt->pos))
8922 882 return get_frag_stream_info(frag_index, current, id);
8923 }
8924
8925
8926
2/2
✓ Branch 0 taken 4557 times.
✓ Branch 1 taken 9 times.
4566 for (int i = 0; i < frag_index->nb_items; i++) {
8927
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 4463 times.
4557 if (frag_index->item[i].moof_offset > pkt->pos)
8928 94 break;
8929 4463 current = i;
8930 }
8931 103 frag_index->current = current;
8932 103 return get_frag_stream_info(frag_index, current, id);
8933 }
8934
8935 107869 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8936 {
8937 MOVFragmentStreamInfo *frag_stream_info;
8938 MOVEncryptionIndex *encryption_index;
8939 AVEncryptionInfo *encrypted_sample;
8940 int encrypted_index, ret;
8941
8942 107869 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8943 107869 encrypted_index = current_index;
8944 107869 encryption_index = NULL;
8945
2/2
✓ Branch 0 taken 985 times.
✓ Branch 1 taken 106884 times.
107869 if (frag_stream_info) {
8946 // Note this only supports encryption info in the first sample descriptor.
8947
2/2
✓ Branch 0 taken 937 times.
✓ Branch 1 taken 48 times.
985 if (frag_stream_info->stsd_id == 1) {
8948
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 889 times.
937 if (frag_stream_info->encryption_index) {
8949 48 encrypted_index = current_index - frag_stream_info->index_base;
8950 48 encryption_index = frag_stream_info->encryption_index;
8951 } else {
8952 889 encryption_index = sc->cenc.encryption_index;
8953 }
8954 }
8955 } else {
8956 106884 encryption_index = sc->cenc.encryption_index;
8957 }
8958
8959
2/2
✓ Branch 0 taken 341 times.
✓ Branch 1 taken 107528 times.
107869 if (encryption_index) {
8960
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 293 times.
341 if (encryption_index->auxiliary_info_sample_count &&
8961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8962 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8963 return AVERROR_INVALIDDATA;
8964 }
8965
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 293 times.
341 if (encryption_index->auxiliary_offsets_count &&
8966
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8967 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8968 return AVERROR_INVALIDDATA;
8969 }
8970
8971 341 encrypted_sample = NULL;
8972
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 245 times.
341 if (!encryption_index->nb_encrypted_samples) {
8973 // Full-sample encryption with default settings.
8974 96 encrypted_sample = sc->cenc.default_encrypted_sample;
8975
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) {
8976 // Per-sample setting override.
8977 245 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
245 if (!encrypted_sample) {
8979 encrypted_sample = sc->cenc.default_encrypted_sample;
8980 }
8981 }
8982
8983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
341 if (!encrypted_sample) {
8984 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8985 return AVERROR_INVALIDDATA;
8986 }
8987
8988
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) {
8989 341 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
8990 } else {
8991 size_t size;
8992 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
8993 if (!side_data)
8994 return AVERROR(ENOMEM);
8995 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
8996 if (ret < 0)
8997 av_free(side_data);
8998 return ret;
8999 }
9000 }
9001
9002 107528 return 0;
9003 }
9004
9005 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9006 {
9007 const int OPUS_SEEK_PREROLL_MS = 80;
9008 int ret;
9009 AVStream *st;
9010 size_t size;
9011 uint16_t pre_skip;
9012
9013 if (c->fc->nb_streams < 1)
9014 return 0;
9015 st = c->fc->streams[c->fc->nb_streams-1];
9016
9017 if ((uint64_t)atom.size > (1<<30) || atom.size < 11 || st->codecpar->extradata)
9018 return AVERROR_INVALIDDATA;
9019
9020 /* Check OpusSpecificBox version. */
9021 if (avio_r8(pb) != 0) {
9022 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
9023 return AVERROR_INVALIDDATA;
9024 }
9025
9026 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
9027 size = atom.size + 8;
9028
9029 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
9030 return ret;
9031
9032 AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
9033 AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
9034 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
9035 if ((ret = ffio_read_size(pb, st->codecpar->extradata + 9, size - 9)) < 0) {
9036 av_freep(&st->codecpar->extradata);
9037 st->codecpar->extradata_size = 0;
9038 return ret;
9039 }
9040
9041 /* OpusSpecificBox is stored in big-endian, but OpusHead is
9042 little-endian; aside from the preceding magic and version they're
9043 otherwise currently identical. Data after output gain at offset 16
9044 doesn't need to be bytewapped. */
9045 pre_skip = AV_RB16A(st->codecpar->extradata + 10);
9046 AV_WL16A(st->codecpar->extradata + 10, pre_skip);
9047 AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
9048 AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
9049
9050 st->codecpar->initial_padding = pre_skip;
9051 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
9052 (AVRational){1, 1000},
9053 (AVRational){1, 48000});
9054
9055 return 0;
9056 }
9057
9058 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9059 {
9060 AVStream *st;
9061 unsigned format_info;
9062 int channel_assignment, channel_assignment1, channel_assignment2;
9063 int ratebits;
9064 uint64_t chmask;
9065
9066 if (c->fc->nb_streams < 1)
9067 return 0;
9068 st = c->fc->streams[c->fc->nb_streams-1];
9069
9070 if (atom.size < 10)
9071 return AVERROR_INVALIDDATA;
9072
9073 format_info = avio_rb32(pb);
9074
9075 ratebits = (format_info >> 28) & 0xF;
9076 channel_assignment1 = (format_info >> 15) & 0x1F;
9077 channel_assignment2 = format_info & 0x1FFF;
9078 if (channel_assignment2)
9079 channel_assignment = channel_assignment2;
9080 else
9081 channel_assignment = channel_assignment1;
9082
9083 st->codecpar->frame_size = 40 << (ratebits & 0x7);
9084 st->codecpar->sample_rate = mlp_samplerate(ratebits);
9085
9086 av_channel_layout_uninit(&st->codecpar->ch_layout);
9087 chmask = truehd_layout(channel_assignment);
9088 av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
9089
9090 return 0;
9091 }
9092
9093 11 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9094 {
9095 AVStream *st;
9096 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
9097 int ret;
9098 11 int64_t read_size = atom.size;
9099
9100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
9101 return 0;
9102 11 st = c->fc->streams[c->fc->nb_streams-1];
9103
9104 // At most 24 bytes
9105 11 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
9106
9107
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
9108 return ret;
9109
9110 11 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
9111 }
9112
9113 7 static int mov_read_hvce(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9114 {
9115 AVStream *st;
9116 AVPacketSideData *sd;
9117 int ret;
9118
9119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (c->fc->nb_streams < 1)
9120 return 0;
9121 7 st = c->fc->streams[c->fc->nb_streams - 1];
9122
9123
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)
9124 return AVERROR_INVALIDDATA;
9125
9126 7 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
9127 7 &st->codecpar->nb_coded_side_data,
9128 AV_PKT_DATA_HEVC_CONF,
9129 7 atom.size, 0);
9130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sd)
9131 return AVERROR(ENOMEM);
9132
9133 7 ret = ffio_read_size(pb, sd->data, atom.size);
9134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
9135 return ret;
9136
9137 7 return 0;
9138 }
9139
9140 4 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9141 {
9142 AVStream *st;
9143 uint8_t *buf;
9144 int ret, old_size, num_arrays;
9145
9146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
9147 return 0;
9148 4 st = c->fc->streams[c->fc->nb_streams-1];
9149
9150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!st->codecpar->extradata_size)
9151 // TODO: handle lhvC when present before hvcC
9152 return 0;
9153
9154
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 ||
9155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 atom.size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
9156 return AVERROR_INVALIDDATA;
9157 }
9158
9159 4 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
9160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!buf)
9161 return AVERROR(ENOMEM);
9162 4 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
9163
9164 4 ret = ffio_read_size(pb, buf, atom.size);
9165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
9166 av_free(buf);
9167 av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
9168 return 0;
9169 }
9170
9171 4 num_arrays = buf[5];
9172 4 old_size = st->codecpar->extradata_size;
9173 4 atom.size -= 8 /* account for mov_realloc_extradata offsetting */
9174 + 6 /* lhvC bytes before the arrays*/;
9175
9176 4 ret = mov_realloc_extradata(st->codecpar, atom);
9177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
9178 av_free(buf);
9179 return ret;
9180 }
9181
9182 4 st->codecpar->extradata[22] += num_arrays;
9183 4 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
9184
9185 4 st->disposition |= AV_DISPOSITION_MULTILAYER;
9186
9187 4 av_free(buf);
9188 4 return 0;
9189 }
9190
9191 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9192 {
9193 4 AVFormatContext *ctx = c->fc;
9194 4 AVStream *st = NULL;
9195 AVBPrint scheme_buf, value_buf;
9196 4 int64_t scheme_str_len = 0, value_str_len = 0;
9197 4 int version, flags, ret = AVERROR_BUG;
9198 4 int64_t size = atom.size;
9199
9200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
9201 // 4 bytes for version + flags, 2x 1 byte for null
9202 return AVERROR_INVALIDDATA;
9203
9204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
9205 return 0;
9206 4 st = c->fc->streams[c->fc->nb_streams-1];
9207
9208 4 version = avio_r8(pb);
9209 4 flags = avio_rb24(pb);
9210 4 size -= 4;
9211
9212
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) {
9213 av_log(ctx, AV_LOG_ERROR,
9214 "Unsupported 'kind' box with version %d, flags: %x",
9215 version, flags);
9216 return AVERROR_INVALIDDATA;
9217 }
9218
9219 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
9220 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
9221
9222
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,
9223 size)) < 0) {
9224 ret = scheme_str_len;
9225 goto cleanup;
9226 }
9227
9228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
9229 // we need to have another string, even if nullptr.
9230 // we check with + 1 since we expect that if size was not hit,
9231 // an additional null was read.
9232 ret = AVERROR_INVALIDDATA;
9233 goto cleanup;
9234 }
9235
9236 4 size -= scheme_str_len + 1;
9237
9238
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,
9239 size)) < 0) {
9240 ret = value_str_len;
9241 goto cleanup;
9242 }
9243
9244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
9245 // in case of no trailing null, box is not valid.
9246 ret = AVERROR_INVALIDDATA;
9247 goto cleanup;
9248 }
9249
9250 4 av_log(ctx, AV_LOG_TRACE,
9251 "%s stream %d KindBox(scheme: %s, value: %s)\n",
9252 4 av_get_media_type_string(st->codecpar->codec_type),
9253 st->index,
9254 scheme_buf.str, value_buf.str);
9255
9256
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++) {
9257 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
9258
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
9259 continue;
9260
9261
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
9262 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
9263
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
9264 16 continue;
9265
9266 4 st->disposition |= value_map.disposition;
9267 }
9268 }
9269
9270 4 ret = 0;
9271
9272 4 cleanup:
9273
9274 4 av_bprint_finalize(&scheme_buf, NULL);
9275 4 av_bprint_finalize(&value_buf, NULL);
9276
9277 4 return ret;
9278 }
9279
9280 static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9281 {
9282 AVStream *st;
9283 AVChannelLayout ch_layout = { 0 };
9284 int ret, i, version, type;
9285 int ambisonic_order, channel_order, normalization, channel_count;
9286 int ambi_channels, non_diegetic_channels;
9287
9288 if (c->fc->nb_streams < 1)
9289 return 0;
9290
9291 st = c->fc->streams[c->fc->nb_streams - 1];
9292
9293 if (atom.size < 16) {
9294 av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
9295 return AVERROR_INVALIDDATA;
9296 }
9297
9298 version = avio_r8(pb);
9299 if (version) {
9300 av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
9301 return 0;
9302 }
9303
9304 type = avio_r8(pb);
9305 if (type & 0x7f) {
9306 av_log(c->fc, AV_LOG_WARNING,
9307 "Unsupported ambisonic type %d\n", type & 0x7f);
9308 return 0;
9309 }
9310 non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
9311
9312 ambisonic_order = avio_rb32(pb);
9313
9314 channel_order = avio_r8(pb);
9315 if (channel_order) {
9316 av_log(c->fc, AV_LOG_WARNING,
9317 "Unsupported channel_order %d\n", channel_order);
9318 return 0;
9319 }
9320
9321 normalization = avio_r8(pb);
9322 if (normalization) {
9323 av_log(c->fc, AV_LOG_WARNING,
9324 "Unsupported normalization %d\n", normalization);
9325 return 0;
9326 }
9327
9328 channel_count = avio_rb32(pb);
9329 if (ambisonic_order < 0 || ambisonic_order > 31 ||
9330 channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
9331 non_diegetic_channels)) {
9332 av_log(c->fc, AV_LOG_ERROR,
9333 "Invalid number of channels (%d / %d)\n",
9334 channel_count, ambisonic_order);
9335 return 0;
9336 }
9337 ambi_channels = channel_count - non_diegetic_channels;
9338
9339 ret = av_channel_layout_custom_init(&ch_layout, channel_count);
9340 if (ret < 0)
9341 return 0;
9342
9343 for (i = 0; i < channel_count; i++) {
9344 unsigned channel = avio_rb32(pb);
9345
9346 if (channel >= channel_count) {
9347 av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
9348 channel, ambisonic_order);
9349 av_channel_layout_uninit(&ch_layout);
9350 return 0;
9351 }
9352 if (channel >= ambi_channels)
9353 ch_layout.u.map[i].id = channel - ambi_channels;
9354 else
9355 ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
9356 }
9357
9358 ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
9359 if (ret < 0) {
9360 av_channel_layout_uninit(&ch_layout);
9361 return 0;
9362 }
9363
9364 av_channel_layout_uninit(&st->codecpar->ch_layout);
9365 st->codecpar->ch_layout = ch_layout;
9366
9367 return 0;
9368 }
9369
9370 static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9371 {
9372 AVStream *st;
9373 int version;
9374
9375 if (c->fc->nb_streams < 1)
9376 return 0;
9377
9378 st = c->fc->streams[c->fc->nb_streams - 1];
9379
9380 if (atom.size < 5) {
9381 av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
9382 return AVERROR_INVALIDDATA;
9383 }
9384
9385 version = avio_r8(pb);
9386 if (version) {
9387 av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
9388 return 0;
9389 }
9390
9391 st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
9392
9393 return 0;
9394 }
9395
9396 171 static int rb_size(AVIOContext *pb, int64_t *value, int size)
9397 {
9398
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 160 times.
171 if (size == 0)
9399 11 *value = 0;
9400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 else if (size == 1)
9401 *value = avio_r8(pb);
9402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 else if (size == 2)
9403 *value = avio_rb16(pb);
9404
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 else if (size == 4)
9405 160 *value = avio_rb32(pb);
9406 else if (size == 8) {
9407 *value = avio_rb64(pb);
9408 if (*value < 0)
9409 return -1;
9410 } else
9411 return -1;
9412 171 return size;
9413 }
9414
9415 18 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9416 {
9417 18 avio_rb32(pb); // version & flags.
9418 18 c->primary_item_id = avio_rb16(pb);
9419 18 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
9420 18 return atom.size;
9421 }
9422
9423 9 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9424 {
9425 9 c->idat_offset = avio_tell(pb);
9426 9 return 0;
9427 }
9428
9429 18 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9430 {
9431 HEIFItem **heif_item;
9432 int version, offset_size, length_size, base_offset_size, index_size;
9433 int item_count, extent_count;
9434 int64_t base_offset, extent_offset, extent_length;
9435 uint8_t value;
9436
9437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->found_iloc) {
9438 av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
9439 return 0;
9440 }
9441
9442 18 version = avio_r8(pb);
9443 18 avio_rb24(pb); // flags.
9444
9445 18 value = avio_r8(pb);
9446 18 offset_size = (value >> 4) & 0xF;
9447 18 length_size = value & 0xF;
9448 18 value = avio_r8(pb);
9449 18 base_offset_size = (value >> 4) & 0xF;
9450
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 7 times.
18 index_size = !version ? 0 : (value & 0xF);
9451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (index_size) {
9452 avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
9453 return AVERROR_PATCHWELCOME;
9454 }
9455
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9456
9457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (item_count > atom.size)
9458 return AVERROR_INVALIDDATA;
9459
9460 18 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
9461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!heif_item)
9462 return AVERROR(ENOMEM);
9463 18 c->heif_item = heif_item;
9464
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (item_count > c->nb_heif_item)
9465 18 memset(&c->heif_item[c->nb_heif_item], 0,
9466 18 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
9467 18 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
9468
9469 18 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
9470
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (int i = 0; i < item_count; i++) {
9471 57 HEIFItem *item = NULL;
9472
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9473
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 12 times.
57 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
9474 int j;
9475
9476
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (avio_feof(pb))
9477 return AVERROR_INVALIDDATA;
9478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (offset_type > 1) {
9479 avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
9480 return AVERROR_PATCHWELCOME;
9481 }
9482
9483 57 avio_rb16(pb); // data_reference_index.
9484
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (rb_size(pb, &base_offset, base_offset_size) < 0)
9485 return AVERROR_INVALIDDATA;
9486 57 extent_count = avio_rb16(pb);
9487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (extent_count > 1) {
9488 // For still AVIF images, we only support one extent item.
9489 avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
9490 return AVERROR_PATCHWELCOME;
9491 }
9492
9493
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 ||
9494 57 rb_size(pb, &extent_length, length_size) < 0 ||
9495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 base_offset > INT64_MAX - extent_offset)
9496 return AVERROR_INVALIDDATA;
9497
9498
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 for (j = 0; j < c->nb_heif_item; j++) {
9499 140 item = c->heif_item[j];
9500
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 83 times.
140 if (!item)
9501 57 item = c->heif_item[j] = av_mallocz(sizeof(*item));
9502
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
83 else if (item->item_id != item_id)
9503 83 continue;
9504 57 break;
9505 }
9506
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item)
9507 return AVERROR(ENOMEM);
9508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (j == c->nb_heif_item)
9509 return AVERROR_INVALIDDATA;
9510
9511 57 item->item_id = item_id;
9512
9513
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 48 times.
57 if (offset_type == 1)
9514 9 item->is_idat_relative = 1;
9515 57 item->extent_length = extent_length;
9516 57 item->extent_offset = base_offset + extent_offset;
9517 57 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, item->item_id %d, offset_type %d, "
9518 "extent_offset %"PRId64", extent_length %"PRId64"\n",
9519 i, item->item_id, offset_type, item->extent_offset, item->extent_length);
9520 }
9521
9522 18 c->found_iloc = 1;
9523 18 return atom.size;
9524 }
9525
9526 57 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9527 {
9528 57 HEIFItem *item = NULL;
9529 AVBPrint item_name;
9530 57 int64_t size = atom.size;
9531 uint32_t item_type;
9532 int item_id;
9533 int i, version, ret;
9534
9535 57 version = avio_r8(pb);
9536 57 avio_rb24(pb); // flags.
9537 57 size -= 4;
9538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (size < 0)
9539 return AVERROR_INVALIDDATA;
9540
9541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (version < 2) {
9542 avpriv_report_missing_feature(c->fc, "infe version < 2");
9543 avio_skip(pb, size);
9544 return 1;
9545 }
9546
9547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
9548 57 avio_rb16(pb); // item_protection_index
9549 57 item_type = avio_rl32(pb);
9550 57 size -= 8;
9551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (size < 1)
9552 return AVERROR_INVALIDDATA;
9553
9554 57 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
9555 57 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
9556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (ret < 0) {
9557 av_bprint_finalize(&item_name, NULL);
9558 return ret;
9559 }
9560
9561 57 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
9562 57 item_id, av_fourcc2str(item_type), item_name.str);
9563
9564 57 size -= ret + 1;
9565
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 55 times.
57 if (size > 0)
9566 2 avio_skip(pb, size);
9567
9568
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 for (i = 0; i < c->nb_heif_item; i++) {
9569 140 item = c->heif_item[i];
9570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (!item)
9571 item = c->heif_item[i] = av_mallocz(sizeof(*item));
9572
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 57 times.
140 else if (item->item_id != item_id)
9573 83 continue;
9574 57 break;
9575 }
9576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item) {
9577 av_bprint_finalize(&item_name, NULL);
9578 return AVERROR(ENOMEM);
9579 }
9580
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (i == c->nb_heif_item) {
9581 av_bprint_finalize(&item_name, NULL);
9582 return AVERROR_INVALIDDATA;
9583 }
9584
9585 57 av_freep(&item->name);
9586
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 1 times.
57 av_bprint_finalize(&item_name, ret ? &item->name : NULL);
9587 57 item->item_id = item_id;
9588 57 item->type = item_type;
9589
9590
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 14 times.
57 switch (item_type) {
9591 43 case MKTAG('a','v','0','1'):
9592 case MKTAG('j','p','e','g'):
9593 case MKTAG('h','v','c','1'):
9594 43 ret = heif_add_stream(c, item);
9595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
9596 return ret;
9597 43 break;
9598 }
9599
9600 57 return 0;
9601 }
9602
9603 18 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9604 {
9605 HEIFItem **heif_item;
9606 int entry_count;
9607 18 int version, got_stream = 0, ret, i;
9608
9609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->found_iinf) {
9610 av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
9611 return 0;
9612 }
9613
9614 18 version = avio_r8(pb);
9615 18 avio_rb24(pb); // flags.
9616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
9617
9618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (entry_count > atom.size)
9619 return AVERROR_INVALIDDATA;
9620
9621 18 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
9622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!heif_item)
9623 return AVERROR(ENOMEM);
9624 18 c->heif_item = heif_item;
9625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (entry_count > c->nb_heif_item)
9626 memset(&c->heif_item[c->nb_heif_item], 0,
9627 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
9628 18 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
9629
9630
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (i = 0; i < entry_count; i++) {
9631 MOVAtom infe;
9632
9633 57 infe.size = avio_rb32(pb) - 8;
9634 57 infe.type = avio_rl32(pb);
9635
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (avio_feof(pb)) {
9636 ret = AVERROR_INVALIDDATA;
9637 goto fail;
9638 }
9639 57 ret = mov_read_infe(c, pb, infe);
9640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (ret < 0)
9641 goto fail;
9642
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 if (!ret)
9643 57 got_stream = 1;
9644 }
9645
9646 18 c->found_iinf = got_stream;
9647 18 return 0;
9648 fail:
9649 for (; i >= 0; i--) {
9650 HEIFItem *item = c->heif_item[i];
9651
9652 if (!item)
9653 continue;
9654
9655 av_freep(&item->name);
9656 }
9657 return ret;
9658 }
9659
9660 9 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
9661 {
9662 9 HEIFItem *item = NULL;
9663 HEIFGrid *grid;
9664 int entries, i;
9665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9666 9 int ret = 0;
9667
9668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 for (int i = 0; i < c->nb_heif_grid; i++) {
9669 if (c->heif_grid[i].item->item_id == from_item_id) {
9670 av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
9671 "referencing the same Derived Image item\n");
9672 return AVERROR_INVALIDDATA;
9673 }
9674 }
9675
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 for (int i = 0; i < c->nb_heif_item; i++) {
9676
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)
9677 26 continue;
9678 9 item = c->heif_item[i];
9679
9680
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 switch (item->type) {
9681 9 case MKTAG('g','r','i','d'):
9682 case MKTAG('i','o','v','l'):
9683 9 break;
9684 default:
9685 avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
9686 av_fourcc2str(item->type));
9687 return 0;
9688 }
9689 9 break;
9690 }
9691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!item) {
9692 av_log(c->fc, AV_LOG_ERROR, "Missing grid information\n");
9693 return AVERROR_INVALIDDATA;
9694 }
9695
9696 9 entries = avio_rb16(pb);
9697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!entries) {
9698 av_log(c->fc, AV_LOG_ERROR,
9699 "Derived image item references no input images\n");
9700 return AVERROR_INVALIDDATA;
9701 }
9702
9703 9 grid = av_realloc_array(c->heif_grid, c->nb_heif_grid + 1U,
9704 sizeof(*c->heif_grid));
9705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!grid)
9706 return AVERROR(ENOMEM);
9707 9 c->heif_grid = grid;
9708 9 grid = &grid[c->nb_heif_grid];
9709
9710 9 grid->tile_id_list = av_malloc_array(entries, sizeof(*grid->tile_id_list));
9711 9 grid->tile_idx_list = av_calloc(entries, sizeof(*grid->tile_idx_list));
9712 9 grid->tile_item_list = av_calloc(entries, sizeof(*grid->tile_item_list));
9713
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) {
9714 ret = AVERROR(ENOMEM);
9715 goto fail;
9716 }
9717 /* 'to' item ids */
9718
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9 times.
37 for (i = 0; i < entries; i++) {
9719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 grid->tile_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
9720
9721
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if (avio_feof(pb)) {
9722 ret = AVERROR_INVALIDDATA;
9723 goto fail;
9724 }
9725 }
9726
9727 9 grid->nb_tiles = entries;
9728 9 grid->item = item;
9729 9 ++c->nb_heif_grid;
9730
9731 9 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
9732 from_item_id, entries);
9733
9734 9 return 0;
9735 fail:
9736 av_freep(&grid->tile_id_list);
9737 av_freep(&grid->tile_idx_list);
9738 av_freep(&grid->tile_item_list);
9739
9740 return ret;
9741 }
9742
9743 11 static int mov_read_iref_cdsc(MOVContext *c, AVIOContext *pb, uint32_t type, int version, uint32_t size)
9744 {
9745 11 HEIFItem *from_item = NULL;
9746 int entries;
9747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 int item_id_size = version ? 4 : 2;
9748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9749 11 const HEIFItemRef ref = { type, from_item_id };
9750
9751 11 from_item = get_heif_item(c, from_item_id);
9752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!from_item) {
9753 av_log(c->fc, AV_LOG_ERROR, "Missing stream referenced by thmb item\n");
9754 return AVERROR_INVALIDDATA;
9755 }
9756
9757 11 entries = avio_rb16(pb);
9758
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) {
9759 av_log(c->fc, AV_LOG_ERROR, "iref %s entry count %d exceeds the sub-box size\n",
9760 av_fourcc2str(type), entries);
9761 return AVERROR_INVALIDDATA;
9762 }
9763 /* 'to' item ids */
9764
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (int i = 0; i < entries; i++) {
9765
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));
9766
9767
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (avio_feof(pb))
9768 return AVERROR_INVALIDDATA;
9769
9770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!item) {
9771 av_log(c->fc, AV_LOG_WARNING, "Missing stream referenced by %s item\n",
9772 av_fourcc2str(type));
9773 continue;
9774 }
9775
9776
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (!av_dynarray2_add((void **)&item->iref_list, &item->nb_iref_list,
9777 sizeof(*item->iref_list), (const uint8_t *)&ref))
9778 return AVERROR(ENOMEM);
9779 }
9780
9781 11 av_log(c->fc, AV_LOG_TRACE, "%s: from_item_id %d, entries %d\n",
9782 11 av_fourcc2str(type), from_item_id, entries);
9783
9784 11 return 0;
9785 }
9786
9787 14 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9788 {
9789 14 int version = avio_r8(pb);
9790 int ret;
9791
9792 14 avio_rb24(pb); // flags
9793 14 atom.size -= 4;
9794
9795
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (version > 1) {
9796 av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
9797 return 0;
9798 }
9799
9800
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 14 times.
34 while (atom.size) {
9801 20 int64_t next = avio_tell(pb);
9802 20 uint32_t type, size = avio_rb32(pb);
9803
9804
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)
9805 return AVERROR_INVALIDDATA;
9806
9807 20 next += size;
9808 20 type = avio_rl32(pb);
9809
2/3
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
20 switch (type) {
9810 9 case MKTAG('d','i','m','g'):
9811 9 ret = mov_read_iref_dimg(c, pb, version);
9812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret < 0)
9813 return ret;
9814 20 break;
9815 11 case MKTAG('c','d','s','c'):
9816 case MKTAG('t','h','m','b'):
9817 11 ret = mov_read_iref_cdsc(c, pb, type, version, size - 8);
9818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0)
9819 return ret;
9820 11 break;
9821 default:
9822 av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
9823 av_fourcc2str(type), size);
9824 }
9825
9826 20 atom.size -= size;
9827 20 avio_seek(pb, next, SEEK_SET);
9828 }
9829 14 return 0;
9830 }
9831
9832 52 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9833 {
9834 HEIFItem *item;
9835 uint32_t width, height;
9836
9837 52 avio_r8(pb); /* version */
9838 52 avio_rb24(pb); /* flags */
9839 52 width = avio_rb32(pb);
9840 52 height = avio_rb32(pb);
9841
9842 52 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %"PRIu32", height %"PRIu32"\n",
9843 c->cur_item_id, width, height);
9844
9845
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) {
9846 av_log(c->fc, AV_LOG_ERROR, "Invalid ispe dimensions %"PRIu32"x%"PRIu32"\n",
9847 width, height);
9848 return AVERROR_INVALIDDATA;
9849 }
9850
9851 52 item = get_heif_item(c, c->cur_item_id);
9852
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 if (item) {
9853 52 item->width = width;
9854 52 item->height = height;
9855 }
9856
9857 52 return 0;
9858 }
9859
9860 8 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9861 {
9862 HEIFItem *item;
9863 int angle;
9864
9865 8 angle = avio_r8(pb) & 0x3;
9866
9867 8 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
9868 c->cur_item_id, angle);
9869
9870 8 item = get_heif_item(c, c->cur_item_id);
9871
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (item) {
9872 // angle * 90 specifies the angle (in anti-clockwise direction)
9873 // in units of degrees.
9874 8 item->rotation = angle * 90;
9875 }
9876
9877 8 return 0;
9878 }
9879
9880 6 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9881 {
9882 HEIFItem *item;
9883 int axis;
9884
9885 6 axis = avio_r8(pb) & 0x1;
9886
9887 6 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
9888 c->cur_item_id, axis);
9889
9890 6 item = get_heif_item(c, c->cur_item_id);
9891
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
9892 6 item->hflip = axis;
9893 6 item->vflip = !axis;
9894 }
9895
9896 6 return 0;
9897 }
9898
9899 18 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9900 {
9901 typedef struct MOVAtoms {
9902 FFIOContext b;
9903 uint32_t type;
9904 int64_t size;
9905 uint8_t *data;
9906 } MOVAtoms;
9907 18 MOVAtoms *atoms = NULL;
9908 MOVAtom a;
9909 unsigned count;
9910 18 int nb_atoms = 0;
9911 int version, flags;
9912 int ret;
9913
9914 18 a.size = avio_rb32(pb);
9915 18 a.type = avio_rl32(pb);
9916
9917
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'))
9918 return AVERROR_INVALIDDATA;
9919
9920 18 a.size -= 8;
9921
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 while (a.size >= 8) {
9922 80 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
9923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!ref) {
9924 ret = AVERROR(ENOMEM);
9925 goto fail;
9926 }
9927 80 ref->data = NULL;
9928 80 ref->size = avio_rb32(pb);
9929 80 ref->type = avio_rl32(pb);
9930
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)
9931 break;
9932 80 ref->data = av_malloc(ref->size);
9933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!ref->data) {
9934 ret = AVERROR_INVALIDDATA;
9935 goto fail;
9936 }
9937 80 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
9938 80 avio_seek(pb, -8, SEEK_CUR);
9939
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
80 if (avio_read(pb, ref->data, ref->size) != ref->size) {
9940 ret = AVERROR_INVALIDDATA;
9941 goto fail;
9942 }
9943 80 ffio_init_read_context(&ref->b, ref->data, ref->size);
9944 80 a.size -= ref->size;
9945 }
9946
9947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (a.size) {
9948 ret = AVERROR_INVALIDDATA;
9949 goto fail;
9950 }
9951
9952 18 a.size = avio_rb32(pb);
9953 18 a.type = avio_rl32(pb);
9954
9955
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')) {
9956 ret = AVERROR_INVALIDDATA;
9957 goto fail;
9958 }
9959
9960 18 version = avio_r8(pb);
9961 18 flags = avio_rb24(pb);
9962 18 count = avio_rb32(pb);
9963
9964
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 18 times.
70 for (int i = 0; i < count; i++) {
9965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9966 52 int assoc_count = avio_r8(pb);
9967
9968
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
52 if (avio_feof(pb)) {
9969 ret = AVERROR_INVALIDDATA;
9970 goto fail;
9971 }
9972
9973
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 52 times.
177 for (int j = 0; j < assoc_count; j++) {
9974 MOVAtoms *ref;
9975 125 int index = avio_r8(pb) & 0x7f;
9976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 if (flags & 1) {
9977 index <<= 8;
9978 index |= avio_r8(pb);
9979 }
9980
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) {
9981 ret = AVERROR_INVALIDDATA;
9982 goto fail;
9983 }
9984 125 ref = &atoms[--index];
9985
9986 125 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
9987 125 index + 1, item_id, av_fourcc2str(ref->type));
9988
9989 125 c->cur_item_id = item_id;
9990
9991 125 ret = mov_read_default(c, &ref->b.pub,
9992 125 (MOVAtom) { .size = ref->size,
9993 .type = MKTAG('i','p','c','o') });
9994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 if (ret < 0)
9995 goto fail;
9996 125 ffio_init_read_context(&ref->b, ref->data, ref->size);
9997 }
9998 }
9999
10000 18 ret = 0;
10001 18 fail:
10002 18 c->cur_item_id = -1;
10003
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 for (int i = 0; i < nb_atoms; i++)
10004 80 av_free(atoms[i].data);
10005 18 av_free(atoms);
10006
10007 18 return ret;
10008 }
10009
10010 static const MOVParseTableEntry mov_default_parse_table[] = {
10011 { MKTAG('A','C','L','R'), mov_read_aclr },
10012 { MKTAG('A','P','R','G'), mov_read_avid },
10013 { MKTAG('A','A','L','P'), mov_read_avid },
10014 { MKTAG('A','R','E','S'), mov_read_ares },
10015 { MKTAG('a','v','s','s'), mov_read_avss },
10016 { MKTAG('a','v','1','C'), mov_read_glbl },
10017 { MKTAG('c','h','p','l'), mov_read_chpl },
10018 { MKTAG('c','o','6','4'), mov_read_stco },
10019 { MKTAG('c','o','l','r'), mov_read_colr },
10020 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
10021 { MKTAG('d','i','n','f'), mov_read_default },
10022 { MKTAG('D','p','x','E'), mov_read_dpxe },
10023 { MKTAG('d','r','e','f'), mov_read_dref },
10024 { MKTAG('e','d','t','s'), mov_read_default },
10025 { MKTAG('e','l','s','t'), mov_read_elst },
10026 { MKTAG('e','n','d','a'), mov_read_enda },
10027 { MKTAG('f','i','e','l'), mov_read_fiel },
10028 { MKTAG('a','d','r','m'), mov_read_adrm },
10029 { MKTAG('f','t','y','p'), mov_read_ftyp },
10030 { MKTAG('g','l','b','l'), mov_read_glbl },
10031 { MKTAG('h','d','l','r'), mov_read_hdlr },
10032 { MKTAG('i','l','s','t'), mov_read_ilst },
10033 { MKTAG('j','p','2','h'), mov_read_jp2h },
10034 { MKTAG('m','d','a','t'), mov_read_mdat },
10035 { MKTAG('m','d','h','d'), mov_read_mdhd },
10036 { MKTAG('m','d','i','a'), mov_read_default },
10037 { MKTAG('m','e','t','a'), mov_read_meta },
10038 { MKTAG('m','i','n','f'), mov_read_default },
10039 { MKTAG('m','o','o','f'), mov_read_moof },
10040 { MKTAG('m','o','o','v'), mov_read_moov },
10041 { MKTAG('m','v','e','x'), mov_read_default },
10042 { MKTAG('m','v','h','d'), mov_read_mvhd },
10043 { MKTAG('S','M','I',' '), mov_read_svq3 },
10044 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
10045 { MKTAG('a','v','c','C'), mov_read_glbl },
10046 { MKTAG('p','a','s','p'), mov_read_pasp },
10047 { MKTAG('c','l','a','p'), mov_read_clap },
10048 { MKTAG('c','d','s','c'), mov_read_cdsc_rndr },
10049 { MKTAG('r','n','d','r'), mov_read_cdsc_rndr },
10050 { MKTAG('s','b','a','s'), mov_read_sbas },
10051 { MKTAG('v','d','e','p'), mov_read_vdep },
10052 { MKTAG('s','i','d','x'), mov_read_sidx },
10053 { MKTAG('s','t','b','l'), mov_read_default },
10054 { MKTAG('s','t','c','o'), mov_read_stco },
10055 { MKTAG('s','t','p','s'), mov_read_stps },
10056 { MKTAG('s','t','r','f'), mov_read_strf },
10057 { MKTAG('s','t','s','c'), mov_read_stsc },
10058 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
10059 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
10060 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
10061 { MKTAG('s','t','t','s'), mov_read_stts },
10062 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
10063 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
10064 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
10065 { MKTAG('t','f','d','t'), mov_read_tfdt },
10066 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
10067 { MKTAG('t','r','a','k'), mov_read_trak },
10068 { MKTAG('t','r','a','f'), mov_read_default },
10069 { MKTAG('t','r','e','f'), mov_read_default },
10070 { MKTAG('t','m','c','d'), mov_read_tmcd },
10071 { MKTAG('c','h','a','p'), mov_read_chap },
10072 { MKTAG('t','r','e','x'), mov_read_trex },
10073 { MKTAG('t','r','u','n'), mov_read_trun },
10074 { MKTAG('u','d','t','a'), mov_read_default },
10075 { MKTAG('w','a','v','e'), mov_read_wave },
10076 { MKTAG('e','s','d','s'), mov_read_esds },
10077 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
10078 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
10079 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
10080 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
10081 { MKTAG('w','f','e','x'), mov_read_wfex },
10082 { MKTAG('c','m','o','v'), mov_read_cmov },
10083 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
10084 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
10085 { MKTAG('d','v','c','1'), mov_read_dvc1 },
10086 { MKTAG('s','g','p','d'), mov_read_sgpd },
10087 { MKTAG('s','b','g','p'), mov_read_sbgp },
10088 { MKTAG('h','v','c','C'), mov_read_glbl },
10089 { MKTAG('v','v','c','C'), mov_read_glbl },
10090 { MKTAG('u','u','i','d'), mov_read_uuid },
10091 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
10092 { MKTAG('f','r','e','e'), mov_read_free },
10093 { MKTAG('-','-','-','-'), mov_read_custom },
10094 { MKTAG('s','i','n','f'), mov_read_default },
10095 { MKTAG('f','r','m','a'), mov_read_frma },
10096 { MKTAG('s','e','n','c'), mov_read_senc },
10097 { MKTAG('s','a','i','z'), mov_read_saiz },
10098 { MKTAG('s','a','i','o'), mov_read_saio },
10099 { MKTAG('p','s','s','h'), mov_read_pssh },
10100 { MKTAG('s','c','h','m'), mov_read_schm },
10101 { MKTAG('s','c','h','i'), mov_read_default },
10102 { MKTAG('t','e','n','c'), mov_read_tenc },
10103 { MKTAG('d','f','L','a'), mov_read_dfla },
10104 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
10105 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
10106 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
10107 { MKTAG('h','f','o','v'), mov_read_hfov },
10108 { MKTAG('d','O','p','s'), mov_read_dops },
10109 { MKTAG('d','m','l','p'), mov_read_dmlp },
10110 { MKTAG('S','m','D','m'), mov_read_smdm },
10111 { MKTAG('C','o','L','L'), mov_read_coll },
10112 { MKTAG('v','p','c','C'), mov_read_vpcc },
10113 { MKTAG('m','d','c','v'), mov_read_mdcv },
10114 { MKTAG('c','l','l','i'), mov_read_clli },
10115 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
10116 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
10117 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
10118 { MKTAG('h','v','c','E'), mov_read_hvce },
10119 { MKTAG('k','i','n','d'), mov_read_kind },
10120 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
10121 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
10122 { MKTAG('i','l','o','c'), mov_read_iloc },
10123 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
10124 { MKTAG('p','i','t','m'), mov_read_pitm },
10125 { MKTAG('e','v','c','C'), mov_read_glbl },
10126 { MKTAG('i','d','a','t'), mov_read_idat },
10127 { MKTAG('i','m','i','r'), mov_read_imir },
10128 { MKTAG('i','r','e','f'), mov_read_iref },
10129 { MKTAG('i','s','p','e'), mov_read_ispe },
10130 { MKTAG('i','r','o','t'), mov_read_irot },
10131 { MKTAG('i','p','r','p'), mov_read_iprp },
10132 { MKTAG('i','i','n','f'), mov_read_iinf },
10133 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
10134 { MKTAG('l','h','v','C'), mov_read_lhvc },
10135 { MKTAG('l','v','c','C'), mov_read_glbl },
10136 { MKTAG('a','p','v','C'), mov_read_glbl },
10137 #if CONFIG_IAMFDEC
10138 { MKTAG('i','a','c','b'), mov_read_iacb },
10139 #endif
10140 { MKTAG('s','r','a','t'), mov_read_srat },
10141 { 0, NULL }
10142 };
10143
10144 7799 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10145 {
10146 7799 int64_t total_size = 0;
10147 MOVAtom a;
10148 int i;
10149
10150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7799 times.
7799 if (c->atom_depth > 10) {
10151 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
10152 return AVERROR_INVALIDDATA;
10153 }
10154 7799 c->atom_depth ++;
10155
10156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7799 times.
7799 if (atom.size < 0)
10157 atom.size = INT64_MAX;
10158
2/2
✓ Branch 0 taken 22218 times.
✓ Branch 1 taken 7208 times.
29426 while (total_size <= atom.size - 8) {
10159 22218 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
10160 22218 a.size = avio_rb32(pb);
10161 22218 a.type = avio_rl32(pb);
10162
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 22211 times.
22218 if (avio_feof(pb))
10163 7 break;
10164
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) ||
10165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22211 times.
22211 a.type == MKTAG('h','o','o','v')) &&
10166 a.size >= 8 &&
10167 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
10168 uint32_t type;
10169 avio_skip(pb, 4);
10170 type = avio_rl32(pb);
10171 if (avio_feof(pb))
10172 break;
10173 avio_seek(pb, -8, SEEK_CUR);
10174 if (type == MKTAG('m','v','h','d') ||
10175 type == MKTAG('c','m','o','v')) {
10176 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
10177 a.type = MKTAG('m','o','o','v');
10178 }
10179 }
10180
2/2
✓ Branch 0 taken 18927 times.
✓ Branch 1 taken 3284 times.
22211 if (atom.type != MKTAG('r','o','o','t') &&
10181
2/2
✓ Branch 0 taken 17208 times.
✓ Branch 1 taken 1719 times.
18927 atom.type != MKTAG('m','o','o','v')) {
10182
1/2
✓ Branch 0 taken 17208 times.
✗ Branch 1 not taken.
17208 if (a.type == MKTAG('t','r','a','k') ||
10183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17208 times.
17208 a.type == MKTAG('m','d','a','t')) {
10184 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
10185 avio_skip(pb, -8);
10186 c->atom_depth --;
10187 584 return 0;
10188 }
10189 }
10190 22211 total_size += 8;
10191
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 */
10192 29 a.size = avio_rb64(pb) - 8;
10193 29 total_size += 8;
10194 }
10195 22211 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
10196 22211 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
10197
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 22206 times.
22211 if (a.size == 0) {
10198 5 a.size = atom.size - total_size + 8;
10199 }
10200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22211 times.
22211 if (a.size < 0)
10201 break;
10202 22211 a.size -= 8;
10203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22211 times.
22211 if (a.size < 0)
10204 break;
10205 22211 a.size = FFMIN(a.size, atom.size - total_size);
10206
10207
2/2
✓ Branch 0 taken 1061838 times.
✓ Branch 1 taken 2200 times.
1064038 for (i = 0; mov_default_parse_table[i].type; i++)
10208
2/2
✓ Branch 0 taken 20011 times.
✓ Branch 1 taken 1041827 times.
1061838 if (mov_default_parse_table[i].type == a.type) {
10209 20011 parse = mov_default_parse_table[i].parse;
10210 20011 break;
10211 }
10212
10213 // container is user data
10214
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') ||
10215
2/2
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 1650 times.
2021 atom.type == MKTAG('i','l','s','t')))
10216 550 parse = mov_read_udta_string;
10217
10218 // Supports parsing the QuickTime Metadata Keys.
10219 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
10220
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 &&
10221
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 atom.type == MKTAG('m','e','t','a') &&
10222
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 a.type == MKTAG('k','e','y','s') &&
10223
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 c->meta_keys_count == 0) {
10224 11 parse = mov_read_keys;
10225 }
10226
10227
2/2
✓ Branch 0 taken 1639 times.
✓ Branch 1 taken 20572 times.
22211 if (!parse) { /* skip leaf atoms data */
10228 1639 avio_skip(pb, a.size);
10229 } else {
10230 20572 int64_t start_pos = avio_tell(pb);
10231 int64_t left;
10232 20572 int err = parse(c, pb, a);
10233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20572 times.
20572 if (err < 0) {
10234 c->atom_depth --;
10235 return err;
10236 }
10237
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 &&
10238
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) ||
10239 3430 start_pos + a.size == avio_size(pb))) {
10240
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)
10241 15 c->next_root_atom = start_pos + a.size;
10242 584 c->atom_depth --;
10243 584 return 0;
10244 }
10245 19988 left = a.size - avio_tell(pb) + start_pos;
10246
2/2
✓ Branch 0 taken 1723 times.
✓ Branch 1 taken 18265 times.
19988 if (left > 0) /* skip garbage at atom end */
10247 1723 avio_skip(pb, left);
10248
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18263 times.
18265 else if (left < 0) {
10249 2 av_log(c->fc, AV_LOG_WARNING,
10250 "overread end of atom '%s' by %"PRId64" bytes\n",
10251 2 av_fourcc2str(a.type), -left);
10252 2 avio_seek(pb, left, SEEK_CUR);
10253 }
10254 }
10255
10256 21627 total_size += a.size;
10257 }
10258
10259
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)
10260 102 avio_skip(pb, atom.size - total_size);
10261
10262 7215 c->atom_depth --;
10263 7215 return 0;
10264 }
10265
10266 8043 static int mov_probe(const AVProbeData *p)
10267 {
10268 int64_t offset;
10269 uint32_t tag;
10270 8043 int score = 0;
10271 8043 int moov_offset = -1;
10272
10273 /* check file header */
10274 8043 offset = 0;
10275 9926 for (;;) {
10276 int64_t size;
10277 17969 int minsize = 8;
10278 /* ignore invalid offset */
10279
2/2
✓ Branch 0 taken 8043 times.
✓ Branch 1 taken 9926 times.
17969 if ((offset + 8ULL) > (unsigned int)p->buf_size)
10280 8043 break;
10281 9926 size = AV_RB32(p->buf + offset);
10282
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) {
10283 539 size = AV_RB64(p->buf+offset + 8);
10284 539 minsize = 16;
10285
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 9315 times.
9387 } else if (size == 0) {
10286 72 size = p->buf_size - offset;
10287 }
10288
2/2
✓ Branch 0 taken 410 times.
✓ Branch 1 taken 9516 times.
9926 if (size < minsize) {
10289 410 offset += 4;
10290 410 continue;
10291 }
10292 9516 tag = AV_RL32(p->buf + offset + 4);
10293
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) {
10294 /* check for obvious tags */
10295 153 case MKTAG('m','o','o','v'):
10296 153 moov_offset = offset + 4;
10297 av_fallthrough;
10298 1150 case MKTAG('m','d','a','t'):
10299 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
10300 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
10301 case MKTAG('f','t','y','p'):
10302
2/2
✓ Branch 0 taken 515 times.
✓ Branch 1 taken 635 times.
1150 if (tag == MKTAG('f','t','y','p') &&
10303
1/2
✓ Branch 0 taken 515 times.
✗ Branch 1 not taken.
515 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
10304
1/2
✓ Branch 0 taken 515 times.
✗ Branch 1 not taken.
515 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
10305
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 508 times.
515 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
10306 )) {
10307 7 score = FFMAX(score, 5);
10308 } else {
10309 1143 score = AVPROBE_SCORE_MAX;
10310 }
10311 1150 break;
10312 /* those are more common words, so rate then a bit less */
10313 427 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
10314 case MKTAG('w','i','d','e'):
10315 case MKTAG('f','r','e','e'):
10316 case MKTAG('j','u','n','k'):
10317 case MKTAG('p','i','c','t'):
10318 427 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
10319 427 break;
10320 case MKTAG(0x82,0x82,0x7f,0x7d):
10321 score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
10322 break;
10323 1 case MKTAG('s','k','i','p'):
10324 case MKTAG('u','u','i','d'):
10325 case MKTAG('p','r','f','l'):
10326 /* if we only find those cause probedata is too small at least rate them */
10327 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
10328 1 break;
10329 }
10330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9516 times.
9516 if (size > INT64_MAX - offset)
10331 break;
10332 9516 offset += size;
10333 }
10334
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) {
10335 /* moov atom in the header - we should make sure that this is not a
10336 * MOV-packed MPEG-PS */
10337 153 offset = moov_offset;
10338
10339
2/2
✓ Branch 0 taken 149640 times.
✓ Branch 1 taken 153 times.
149793 while (offset < (p->buf_size - 16)) { /* Sufficient space */
10340 /* We found an actual hdlr atom */
10341
2/2
✓ Branch 0 taken 163 times.
✓ Branch 1 taken 149477 times.
149640 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
10342
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 141 times.
163 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
10343
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
10344 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
10345 /* We found a media handler reference atom describing an
10346 * MPEG-PS-in-MOV, return a
10347 * low score to force expanding the probe window until
10348 * mpegps_probe finds what it needs */
10349 return 5;
10350 } else {
10351 /* Keep looking */
10352 149640 offset += 2;
10353 }
10354 }
10355 }
10356
10357 8043 return score;
10358 }
10359
10360 // must be done after parsing all trak because there's no order requirement
10361 2 static void mov_read_chapters(AVFormatContext *s)
10362 {
10363 2 MOVContext *mov = s->priv_data;
10364 MOVStreamContext *sc;
10365 int64_t cur_pos;
10366 int i, j;
10367 int chapter_track;
10368
10369
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
10370 2 AVStream *st = NULL;
10371 2 FFStream *sti = NULL;
10372 2 chapter_track = mov->chapter_tracks[j];
10373
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
10374 4 sc = mov->fc->streams[i]->priv_data;
10375
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
10376 2 st = s->streams[i];
10377 2 break;
10378 }
10379 }
10380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
10381 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
10382 continue;
10383 }
10384 2 sti = ffstream(st);
10385
10386 2 sc = st->priv_data;
10387 2 cur_pos = avio_tell(sc->pb);
10388
10389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
10390 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
10391 if (!st->attached_pic.data && sti->nb_index_entries) {
10392 // Retrieve the first frame, if possible
10393 AVIndexEntry *sample = &sti->index_entries[0];
10394 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10395 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
10396 goto finish;
10397 }
10398
10399 if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
10400 goto finish;
10401 }
10402 } else {
10403 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10404 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
10405 2 st->discard = AVDISCARD_ALL;
10406
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
10407 8 AVIndexEntry *sample = &sti->index_entries[i];
10408
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;
10409 uint8_t *title;
10410 uint16_t ch;
10411 int len, title_len;
10412
10413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
10414 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
10415 end = AV_NOPTS_VALUE;
10416 }
10417
10418
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10419 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
10420 goto finish;
10421 }
10422
10423 // the first two bytes are the length of the title
10424 8 len = avio_rb16(sc->pb);
10425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
10426 continue;
10427 8 title_len = 2*len + 1;
10428
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
10429 goto finish;
10430
10431 // The samples could theoretically be in any encoding if there's an encd
10432 // atom following, but in practice are only utf-8 or utf-16, distinguished
10433 // instead by the presence of a BOM
10434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
10435 title[0] = 0;
10436 } else {
10437 8 ch = avio_rb16(sc->pb);
10438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
10439 avio_get_str16be(sc->pb, len, title, title_len);
10440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
10441 avio_get_str16le(sc->pb, len, title, title_len);
10442 else {
10443 8 AV_WB16(title, ch);
10444
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)
10445 title[len] = 0;
10446 else
10447 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
10448 }
10449 }
10450
10451 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
10452 8 av_freep(&title);
10453 }
10454 }
10455 2 finish:
10456 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
10457 }
10458 2 }
10459
10460 19 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
10461 int64_t value, int flags)
10462 {
10463 AVTimecode tc;
10464 char buf[AV_TIMECODE_STR_SIZE];
10465 19 AVRational rate = st->avg_frame_rate;
10466 19 int ret = av_timecode_init(&tc, rate, flags, 0, s);
10467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
10468 return ret;
10469 19 av_dict_set(&st->metadata, "timecode",
10470 19 av_timecode_make_string(&tc, buf, value), 0);
10471 19 return 0;
10472 }
10473
10474 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
10475 {
10476 MOVStreamContext *sc = st->priv_data;
10477 FFStream *const sti = ffstream(st);
10478 char buf[AV_TIMECODE_STR_SIZE];
10479 int64_t cur_pos = avio_tell(sc->pb);
10480 int hh, mm, ss, ff, drop;
10481
10482 if (!sti->nb_index_entries)
10483 return -1;
10484
10485 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10486 avio_skip(s->pb, 13);
10487 hh = avio_r8(s->pb);
10488 mm = avio_r8(s->pb);
10489 ss = avio_r8(s->pb);
10490 drop = avio_r8(s->pb);
10491 ff = avio_r8(s->pb);
10492 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
10493 hh, mm, ss, drop ? ';' : ':', ff);
10494 av_dict_set(&st->metadata, "timecode", buf, 0);
10495
10496 avio_seek(sc->pb, cur_pos, SEEK_SET);
10497 return 0;
10498 }
10499
10500 19 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
10501 {
10502 19 MOVStreamContext *sc = st->priv_data;
10503 19 FFStream *const sti = ffstream(st);
10504 19 int flags = 0;
10505 19 int64_t cur_pos = avio_tell(sc->pb);
10506 int64_t value;
10507 19 AVRational tc_rate = st->avg_frame_rate;
10508 19 int tmcd_nb_frames = sc->tmcd_nb_frames;
10509 int rounded_tc_rate;
10510
10511
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!sti->nb_index_entries)
10512 return -1;
10513
10514
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)
10515 return -1;
10516
10517 19 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10518 19 value = avio_rb32(s->pb);
10519
10520
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 10 times.
19 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
10521
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
10522
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
10523
10524 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
10525 * not the case) and thus assume "frame number format" instead of QT one.
10526 * No sample with tmcd track can be found with a QT timecode at the moment,
10527 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
10528 * format). */
10529
10530 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
10531 * we multiply the frame number with the quotient.
10532 * See tickets #9492, #9710. */
10533 19 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
10534 /* Work around files where tmcd_nb_frames is rounded down from frame rate
10535 * instead of up. See ticket #5978. */
10536
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
10537
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
10538 10 tmcd_nb_frames = rounded_tc_rate;
10539 19 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
10540
10541 19 parse_timecode_in_framenum_format(s, st, value, flags);
10542
10543 19 avio_seek(sc->pb, cur_pos, SEEK_SET);
10544 19 return 0;
10545 }
10546
10547 1352 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
10548 int i;
10549
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;
10550
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 13 times.
208 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
10551 195 av_encryption_info_free((*index)->encrypted_samples[i]);
10552 }
10553 13 av_freep(&(*index)->encrypted_samples);
10554 13 av_freep(&(*index)->auxiliary_info_sizes);
10555 13 av_freep(&(*index)->auxiliary_offsets);
10556 13 av_freep(index);
10557 }
10558
10559 823 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
10560 {
10561 823 MOVStreamContext *sc = st->priv_data;
10562
10563
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) {
10564 52 st->priv_data = NULL;
10565 52 return;
10566 }
10567
10568 771 av_freep(&sc->tts_data);
10569
2/2
✓ Branch 0 taken 712 times.
✓ Branch 1 taken 771 times.
1483 for (int i = 0; i < sc->drefs_count; i++) {
10570 712 av_freep(&sc->drefs[i].path);
10571 712 av_freep(&sc->drefs[i].dir);
10572 }
10573 771 av_freep(&sc->drefs);
10574
10575 771 sc->drefs_count = 0;
10576
10577
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 755 times.
771 if (!sc->pb_is_copied)
10578 16 ff_format_io_close(s, &sc->pb);
10579
10580 771 sc->pb = NULL;
10581 771 av_freep(&sc->chunk_offsets);
10582 771 av_freep(&sc->stsc_data);
10583 771 av_freep(&sc->sample_sizes);
10584 771 av_freep(&sc->keyframes);
10585 771 av_freep(&sc->ctts_data);
10586 771 av_freep(&sc->stts_data);
10587 771 av_freep(&sc->sdtp_data);
10588 771 av_freep(&sc->stps_data);
10589 771 av_freep(&sc->elst_data);
10590 771 av_freep(&sc->rap_group);
10591 771 av_freep(&sc->sync_group);
10592 771 av_freep(&sc->sgpd_sync);
10593 771 av_freep(&sc->sample_offsets);
10594 771 av_freep(&sc->open_key_samples);
10595 771 av_freep(&sc->display_matrix);
10596 771 av_freep(&sc->index_ranges);
10597
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 771 times.
800 for (int i = 0; i < sc->nb_tref_tags; i++)
10598 29 av_freep(&sc->tref_tags[i].id);
10599 771 av_freep(&sc->tref_tags);
10600
10601
2/2
✓ Branch 0 taken 712 times.
✓ Branch 1 taken 59 times.
771 if (sc->extradata)
10602
2/2
✓ Branch 0 taken 729 times.
✓ Branch 1 taken 712 times.
1441 for (int i = 0; i < sc->stsd_count; i++)
10603 729 av_free(sc->extradata[i]);
10604 771 av_freep(&sc->extradata);
10605 771 av_freep(&sc->extradata_size);
10606
10607 771 mov_free_encryption_index(&sc->cenc.encryption_index);
10608 771 av_encryption_info_free(sc->cenc.default_encrypted_sample);
10609 771 av_aes_ctr_free(sc->cenc.aes_ctr);
10610
10611 771 av_freep(&sc->stereo3d);
10612 771 av_freep(&sc->spherical);
10613 771 av_freep(&sc->mastering);
10614 771 av_freep(&sc->coll);
10615 771 av_freep(&sc->ambient);
10616
10617 #if CONFIG_IAMFDEC
10618
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 759 times.
771 if (sc->iamf)
10619 12 ff_iamf_read_deinit(sc->iamf);
10620 #endif
10621 771 av_freep(&sc->iamf);
10622 }
10623
10624 608 static int mov_read_close(AVFormatContext *s)
10625 {
10626 608 MOVContext *mov = s->priv_data;
10627 int i, j;
10628
10629
2/2
✓ Branch 0 taken 823 times.
✓ Branch 1 taken 608 times.
1431 for (i = 0; i < s->nb_streams; i++) {
10630 823 AVStream *st = s->streams[i];
10631
10632 823 mov_free_stream_context(s, st);
10633 }
10634
10635 608 av_freep(&mov->dv_demux);
10636 608 avformat_free_context(mov->dv_fctx);
10637 608 mov->dv_fctx = NULL;
10638
10639
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 597 times.
608 if (mov->meta_keys) {
10640
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i < mov->meta_keys_count; i++) {
10641 58 av_freep(&mov->meta_keys[i]);
10642 }
10643 11 av_freep(&mov->meta_keys);
10644 }
10645
10646 608 av_freep(&mov->trex_data);
10647 608 av_freep(&mov->bitrates);
10648
10649
2/2
✓ Branch 0 taken 479 times.
✓ Branch 1 taken 608 times.
1087 for (i = 0; i < mov->frag_index.nb_items; i++) {
10650 479 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
10651
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++) {
10652 581 mov_free_encryption_index(&frag[j].encryption_index);
10653 }
10654 479 av_freep(&mov->frag_index.item[i].stream_info);
10655 }
10656 608 av_freep(&mov->frag_index.item);
10657
10658 608 av_freep(&mov->aes_decrypt);
10659 608 av_freep(&mov->chapter_tracks);
10660
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 608 times.
665 for (i = 0; i < mov->nb_heif_item; i++) {
10661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!mov->heif_item[i])
10662 continue;
10663 57 av_freep(&mov->heif_item[i]->name);
10664 57 av_freep(&mov->heif_item[i]->iref_list);
10665 57 av_freep(&mov->heif_item[i]->icc_profile);
10666 57 av_freep(&mov->heif_item[i]);
10667 }
10668 608 av_freep(&mov->heif_item);
10669
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 608 times.
617 for (i = 0; i < mov->nb_heif_grid; i++) {
10670 9 av_freep(&mov->heif_grid[i].tile_id_list);
10671 9 av_freep(&mov->heif_grid[i].tile_idx_list);
10672 9 av_freep(&mov->heif_grid[i].tile_item_list);
10673 }
10674 608 av_freep(&mov->heif_grid);
10675
10676 608 return 0;
10677 }
10678
10679 19 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
10680 {
10681 int i;
10682
10683
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 for (i = 0; i < s->nb_streams; i++) {
10684 19 AVStream *st = s->streams[i];
10685 19 MOVStreamContext *sc = st->priv_data;
10686 19 MovTref *tag = mov_find_tref_tag(sc, MKTAG('t','m','c','d'));
10687
10688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!tag)
10689 continue;
10690
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 if (mov_find_tref_id(tag, tmcd_id))
10691 19 return 1;
10692 }
10693 return 0;
10694 }
10695
10696 /* look for a tmcd track not referenced by any video track, and export it globally */
10697 608 static void export_orphan_timecode(AVFormatContext *s)
10698 {
10699 int i;
10700
10701
2/2
✓ Branch 0 taken 823 times.
✓ Branch 1 taken 608 times.
1431 for (i = 0; i < s->nb_streams; i++) {
10702 823 AVStream *st = s->streams[i];
10703
10704
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') &&
10705 19 !tmcd_is_referenced(s, st->id)) {
10706 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
10707 if (tcr) {
10708 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
10709 break;
10710 }
10711 }
10712 }
10713 608 }
10714
10715 3 static int read_tfra(MOVContext *mov, AVIOContext *f)
10716 {
10717 int version, fieldlength, i, j;
10718 3 int64_t pos = avio_tell(f);
10719 3 uint32_t size = avio_rb32(f);
10720 unsigned track_id, item_count;
10721
10722
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
10723 1 return 1;
10724 }
10725 2 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
10726
10727 2 version = avio_r8(f);
10728 2 avio_rb24(f);
10729 2 track_id = avio_rb32(f);
10730 2 fieldlength = avio_rb32(f);
10731 2 item_count = avio_rb32(f);
10732
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (i = 0; i < item_count; i++) {
10733 int64_t time, offset;
10734 int index;
10735 MOVFragmentStreamInfo * frag_stream_info;
10736
10737
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (avio_feof(f)) {
10738 return AVERROR_INVALIDDATA;
10739 }
10740
10741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1) {
10742 time = avio_rb64(f);
10743 offset = avio_rb64(f);
10744 } else {
10745 6 time = avio_rb32(f);
10746 6 offset = avio_rb32(f);
10747 }
10748
10749 // The first sample of each stream in a fragment is always a random
10750 // access sample. So it's entry in the tfra can be used as the
10751 // initial PTS of the fragment.
10752 6 index = update_frag_index(mov, offset);
10753 6 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
10754
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (frag_stream_info &&
10755
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
10756 6 frag_stream_info->first_tfra_pts = time;
10757
10758
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
10759 6 avio_r8(f);
10760
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
10761 6 avio_r8(f);
10762
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
10763 6 avio_r8(f);
10764 }
10765
10766 2 avio_seek(f, pos + size, SEEK_SET);
10767 2 return 0;
10768 }
10769
10770 1 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
10771 {
10772 1 int64_t stream_size = avio_size(f);
10773 1 int64_t original_pos = avio_tell(f);
10774 int64_t seek_ret;
10775 1 int ret = -1;
10776
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
10777 ret = seek_ret;
10778 goto fail;
10779 }
10780 1 c->mfra_size = avio_rb32(f);
10781 1 c->have_read_mfra_size = 1;
10782
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) {
10783 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
10784 goto fail;
10785 }
10786
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) {
10787 ret = seek_ret;
10788 goto fail;
10789 }
10790
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != c->mfra_size) {
10791 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
10792 goto fail;
10793 }
10794
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
10795 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
10796 goto fail;
10797 }
10798 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
10799 do {
10800 3 ret = read_tfra(c, f);
10801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
10802 goto fail;
10803
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 } while (!ret);
10804 1 ret = 0;
10805 1 c->frag_index.complete = 1;
10806 1 fail:
10807 1 seek_ret = avio_seek(f, original_pos, SEEK_SET);
10808
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (seek_ret < 0) {
10809 av_log(c->fc, AV_LOG_ERROR,
10810 "failed to seek back after looking for mfra\n");
10811 ret = seek_ret;
10812 }
10813 1 return ret;
10814 }
10815
10816 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10817 const HEIFItem *item)
10818 {
10819 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
10820 AV_PKT_DATA_ICC_PROFILE,
10821 item->icc_profile_size, 0);
10822 if (!sd)
10823 return AVERROR(ENOMEM);
10824
10825 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
10826
10827 return 0;
10828 }
10829
10830 6 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10831 const HEIFItem *item)
10832 {
10833 int32_t *matrix;
10834 6 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data,
10835 nb_coded_side_data,
10836 AV_PKT_DATA_DISPLAYMATRIX,
10837 9 * sizeof(*matrix), 0);
10838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sd)
10839 return AVERROR(ENOMEM);
10840
10841 6 matrix = (int32_t*)sd->data;
10842 /* rotation is in the counter-clockwise direction whereas
10843 * av_display_rotation_set() expects its argument to be
10844 * oriented clockwise, so we need to negate it. */
10845 6 av_display_rotation_set(matrix, -item->rotation);
10846 6 av_display_matrix_flip(matrix, item->hflip, item->vflip);
10847
10848 6 return 0;
10849 }
10850
10851 5 static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid,
10852 AVStreamGroupTileGrid *tile_grid)
10853 {
10854 5 MOVContext *c = s->priv_data;
10855 5 const HEIFItem *item = grid->item;
10856 5 int64_t coded_width = 0, coded_height = 0;
10857 5 int64_t offset = 0, pos = avio_tell(s->pb);
10858 5 int64_t x = 0, y = 0;
10859 5 int i = 0;
10860 int tile_rows, tile_cols;
10861 int flags, size;
10862
10863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10864 av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
10865 return AVERROR_PATCHWELCOME;
10866 }
10867
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (item->is_idat_relative) {
10868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!c->idat_offset) {
10869 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
10870 return AVERROR_INVALIDDATA;
10871 }
10872 5 offset = c->idat_offset;
10873 }
10874
10875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (offset > INT64_MAX - item->extent_offset)
10876 return AVERROR_INVALIDDATA;
10877
10878 5 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10879
10880 5 avio_r8(s->pb); /* version */
10881 5 flags = avio_r8(s->pb);
10882
10883 5 tile_rows = avio_r8(s->pb) + 1;
10884 5 tile_cols = avio_r8(s->pb) + 1;
10885 /* actual width and height of output image */
10886
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);
10887
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);
10888
10889 5 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
10890 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
10891
10892 5 avio_seek(s->pb, pos, SEEK_SET);
10893
10894 5 size = tile_rows * tile_cols;
10895 5 tile_grid->nb_tiles = grid->nb_tiles;
10896
10897
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (tile_grid->nb_tiles != size)
10898 return AVERROR_INVALIDDATA;
10899
10900
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < tile_cols; i++)
10901 10 coded_width += grid->tile_item_list[i]->width;
10902
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < size; i += tile_cols)
10903 10 coded_height += grid->tile_item_list[i]->height;
10904
10905
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)
10906 return AVERROR_INVALIDDATA;
10907
10908 5 tile_grid->coded_width = coded_width;
10909 5 tile_grid->coded_height = coded_height;
10910
10911 5 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!tile_grid->offsets)
10913 return AVERROR(ENOMEM);
10914
10915
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 while (y < tile_grid->coded_height) {
10916 10 int left_col = i;
10917
10918
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 while (x < tile_grid->coded_width) {
10919
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (i == tile_grid->nb_tiles)
10920 return AVERROR_INVALIDDATA;
10921
10922 20 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10923 20 tile_grid->offsets[i].horizontal = x;
10924 20 tile_grid->offsets[i].vertical = y;
10925
10926 20 x += grid->tile_item_list[i++]->width;
10927 }
10928
10929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (x > tile_grid->coded_width) {
10930 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10931 return AVERROR_INVALIDDATA;
10932 }
10933
10934 10 x = 0;
10935 10 y += grid->tile_item_list[left_col]->height;
10936 }
10937
10938
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) {
10939 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10940 return AVERROR_INVALIDDATA;
10941 }
10942
10943 5 return 0;
10944 }
10945
10946 4 static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid,
10947 AVStreamGroupTileGrid *tile_grid)
10948 {
10949 4 MOVContext *c = s->priv_data;
10950 4 const HEIFItem *item = grid->item;
10951 uint16_t canvas_fill_value[4];
10952 4 int64_t offset = 0, pos = avio_tell(s->pb);
10953 4 int ret = 0, flags;
10954
10955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10956 av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
10957 return AVERROR_PATCHWELCOME;
10958 }
10959
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
10960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
10961 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
10962 return AVERROR_INVALIDDATA;
10963 }
10964 4 offset = c->idat_offset;
10965 }
10966
10967
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (offset > INT64_MAX - item->extent_offset)
10968 return AVERROR_INVALIDDATA;
10969
10970 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10971
10972 4 avio_r8(s->pb); /* version */
10973 4 flags = avio_r8(s->pb);
10974
10975
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10976 16 canvas_fill_value[i] = avio_rb16(s->pb);
10977 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
10978 4 canvas_fill_value[0], canvas_fill_value[1],
10979 4 canvas_fill_value[2], canvas_fill_value[3]);
10980
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10981 16 tile_grid->background[i] = canvas_fill_value[i];
10982
10983 /* actual width and height of output image */
10984 4 tile_grid->width =
10985
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);
10986 4 tile_grid->height =
10987
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);
10988
10989 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
10990 tile_grid->width, tile_grid->height);
10991
10992 4 tile_grid->nb_tiles = grid->nb_tiles;
10993 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
10995 ret = AVERROR(ENOMEM);
10996 goto fail;
10997 }
10998
10999
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
11000 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
11001
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);
11002
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);
11003 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
11004 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
11005 8 i, tile_grid->offsets[i].idx,
11006 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
11007 }
11008
11009 4 fail:
11010 4 avio_seek(s->pb, pos, SEEK_SET);
11011
11012 4 return ret;
11013 }
11014
11015 2 static int mov_parse_exif_item(AVFormatContext *s,
11016 AVPacketSideData **coded_side_data, int *nb_coded_side_data,
11017 const HEIFItem *ref)
11018 {
11019 2 MOVContext *c = s->priv_data;
11020 AVPacketSideData *sd;
11021 2 AVExifMetadata ifd = { 0 };
11022 AVBufferRef *buf;
11023 2 int64_t offset = 0, pos = avio_tell(s->pb);
11024 2 unsigned orientation_id = av_exif_get_tag_id("Orientation");
11025 int err;
11026
11027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11028 av_log(c->fc, AV_LOG_WARNING, "Exif metadata with non seekable input\n");
11029 return AVERROR_PATCHWELCOME;
11030 }
11031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ref->is_idat_relative) {
11032 if (!c->idat_offset) {
11033 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the Exif metadata\n");
11034 return AVERROR_INVALIDDATA;
11035 }
11036 offset = c->idat_offset;
11037 }
11038
11039 2 buf = av_buffer_alloc(ref->extent_length);
11040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!buf)
11041 return AVERROR(ENOMEM);
11042
11043
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset > INT64_MAX - ref->extent_offset) {
11044 err = AVERROR(ENOMEM);
11045 goto fail;
11046 }
11047
11048 2 avio_seek(s->pb, ref->extent_offset + offset, SEEK_SET);
11049 2 err = avio_read(s->pb, buf->data, ref->extent_length);
11050
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != ref->extent_length) {
11051 if (err > 0)
11052 err = AVERROR_INVALIDDATA;
11053 goto fail;
11054 }
11055
11056 // HEIF spec states that Exif metadata is informative. The irot item property is
11057 // the normative source of rotation information. So we remove any Orientation tag
11058 // present in the Exif buffer.
11059 2 err = av_exif_parse_buffer(s, buf->data, ref->extent_length, &ifd, AV_EXIF_T_OFF);
11060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0) {
11061 av_log(s, AV_LOG_ERROR, "Unable to parse Exif metadata\n");
11062 goto fail;
11063 }
11064
11065 2 err = av_exif_remove_entry(s, &ifd, orientation_id, 0);
11066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11067 goto fail;
11068
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (!err)
11069 goto finish;
11070
11071 2 av_buffer_unref(&buf);
11072 2 err = av_exif_write(s, &ifd, &buf, AV_EXIF_T_OFF);
11073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11074 goto fail;
11075
11076 2 finish:
11077 2 offset = AV_RB32(buf->data) + 4;
11078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset >= buf->size) {
11079 err = AVERROR_INVALIDDATA;
11080 goto fail;
11081 }
11082 2 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
11083 2 AV_PKT_DATA_EXIF, buf->size - offset, 0);
11084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!sd) {
11085 err = AVERROR(ENOMEM);
11086 goto fail;
11087 }
11088 2 memcpy(sd->data, buf->data + offset, buf->size - offset);
11089
11090 2 err = 0;
11091 2 fail:
11092 2 av_buffer_unref(&buf);
11093 2 av_exif_free(&ifd);
11094 2 avio_seek(s->pb, pos, SEEK_SET);
11095
11096 2 return err;
11097 }
11098
11099 9 static int mov_parse_tiles(AVFormatContext *s)
11100 {
11101 9 MOVContext *mov = s->priv_data;
11102
11103
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for (int i = 0; i < mov->nb_heif_grid; i++) {
11104 9 AVStreamGroup *stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
11105 AVStreamGroupTileGrid *tile_grid;
11106 9 const HEIFGrid *grid = &mov->heif_grid[i];
11107 9 int err, loop = 1;
11108
11109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!stg)
11110 return AVERROR(ENOMEM);
11111
11112 9 stg->id = grid->item->item_id;
11113 9 tile_grid = stg->params.tile_grid;
11114
11115
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9 times.
37 for (int j = 0; j < grid->nb_tiles; j++) {
11116 28 int tile_id = grid->tile_id_list[j];
11117 int k;
11118
11119
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 for (k = 0; k < mov->nb_heif_item; k++) {
11120 60 HEIFItem *item = mov->heif_item[k];
11121 AVStream *st;
11122
11123
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)
11124 32 continue;
11125 28 st = item->st;
11126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!st) {
11127 av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
11128 "reference a stream\n",
11129 tile_id, grid->item->item_id);
11130 ff_remove_stream_group(s, stg);
11131 loop = 0;
11132 break;
11133 }
11134
11135 28 grid->tile_item_list[j] = item;
11136 28 grid->tile_idx_list[j] = stg->nb_streams;
11137
11138 28 err = avformat_stream_group_add_stream(stg, st);
11139
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 26 times.
28 if (err < 0) {
11140 int l;
11141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
11142 return err;
11143
11144
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_streams; l++)
11145
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->streams[l]->index == st->index)
11146 2 break;
11147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_streams);
11148 2 grid->tile_idx_list[j] = l;
11149 }
11150
11151
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 6 times.
28 if (item->item_id != mov->primary_item_id)
11152 22 st->disposition |= AV_DISPOSITION_DEPENDENT;
11153 28 break;
11154 }
11155
11156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (k == mov->nb_heif_item) {
11157 av_assert0(loop);
11158 av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
11159 "exist\n",
11160 tile_id, grid->item->item_id);
11161 ff_remove_stream_group(s, stg);
11162 loop = 0;
11163 }
11164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!loop)
11165 break;
11166 }
11167
11168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!loop)
11169 continue;
11170
11171
2/3
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
9 switch (grid->item->type) {
11172 5 case MKTAG('g','r','i','d'):
11173 5 err = read_image_grid(s, grid, tile_grid);
11174 5 break;
11175 4 case MKTAG('i','o','v','l'):
11176 4 err = read_image_iovl(s, grid, tile_grid);
11177 4 break;
11178 default:
11179 av_assert0(0);
11180 }
11181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err < 0)
11182 return err;
11183
11184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 for (int j = 0; j < grid->item->nb_iref_list; j++) {
11185 HEIFItem *ref = get_heif_item(mov, grid->item->iref_list[j].item_id);
11186
11187 av_assert0(ref);
11188 switch(ref->type) {
11189 case MKTAG('E','x','i','f'):
11190 err = mov_parse_exif_item(s, &tile_grid->coded_side_data,
11191 &tile_grid->nb_coded_side_data, ref);
11192 if (err < 0 && (s->error_recognition & AV_EF_EXPLODE))
11193 return err;
11194 break;
11195 default:
11196 break;
11197 }
11198 }
11199
11200 /* rotation */
11201
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) {
11202 err = set_display_matrix_from_item(&tile_grid->coded_side_data,
11203 &tile_grid->nb_coded_side_data, grid->item);
11204 if (err < 0)
11205 return err;
11206 }
11207
11208 /* ICC profile */
11209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (grid->item->icc_profile_size) {
11210 err = set_icc_profile_from_item(&tile_grid->coded_side_data,
11211 &tile_grid->nb_coded_side_data, grid->item);
11212 if (err < 0)
11213 return err;
11214 }
11215
11216
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (grid->item->name)
11217 9 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
11218
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 if (grid->item->item_id == mov->primary_item_id)
11219 5 stg->disposition |= AV_DISPOSITION_DEFAULT;
11220 }
11221
11222 9 return 0;
11223 }
11224
11225 18 static int mov_parse_heif_items(AVFormatContext *s)
11226 {
11227 18 MOVContext *mov = s->priv_data;
11228 int err;
11229
11230
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (int i = 0; i < mov->nb_heif_item; i++) {
11231 57 HEIFItem *item = mov->heif_item[i];
11232 MOVStreamContext *sc;
11233 AVStream *st;
11234 57 int64_t offset = 0;
11235
11236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item)
11237 continue;
11238
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 43 times.
57 if (!item->st) {
11239 14 continue;
11240 }
11241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (item->is_idat_relative) {
11242 if (!mov->idat_offset) {
11243 av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
11244 return AVERROR_INVALIDDATA;
11245 }
11246 offset = mov->idat_offset;
11247 }
11248
11249 43 st = item->st;
11250 43 sc = st->priv_data;
11251 43 st->codecpar->width = item->width;
11252 43 st->codecpar->height = item->height;
11253
11254 43 sc->sample_size = sc->stsz_sample_size = item->extent_length;
11255 43 sc->sample_count = 1;
11256
11257 43 err = sanity_checks(s, sc, st->index);
11258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (err)
11259 return AVERROR_INVALIDDATA;
11260
11261
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (offset > INT64_MAX - item->extent_offset)
11262 return AVERROR_INVALIDDATA;
11263
11264 43 sc->chunk_offsets[0] = item->extent_offset + offset;
11265
11266
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 30 times.
43 if (item->item_id == mov->primary_item_id)
11267 13 st->disposition |= AV_DISPOSITION_DEFAULT;
11268
11269
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 43 times.
54 for (int j = 0; j < item->nb_iref_list; j++) {
11270 11 HEIFItem *ref = get_heif_item(mov, item->iref_list[j].item_id);
11271
11272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 av_assert0(ref);
11273
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 switch(ref->type) {
11274 2 case MKTAG('E','x','i','f'):
11275 2 err = mov_parse_exif_item(s, &st->codecpar->coded_side_data,
11276 2 &st->codecpar->nb_coded_side_data, ref);
11277
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))
11278 return err;
11279 2 break;
11280 9 default:
11281 9 break;
11282 }
11283 }
11284
11285
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) {
11286 6 err = set_display_matrix_from_item(&st->codecpar->coded_side_data,
11287 6 &st->codecpar->nb_coded_side_data, item);
11288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
11289 return err;
11290 }
11291
11292 43 mov_build_index(mov, st);
11293 }
11294
11295
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (mov->nb_heif_grid) {
11296 9 err = mov_parse_tiles(s);
11297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err < 0)
11298 return err;
11299 }
11300
11301 18 return 0;
11302 }
11303
11304 608 static int mov_parse_tmcd_streams(AVFormatContext *s)
11305 {
11306 int err;
11307
11308
2/2
✓ Branch 0 taken 823 times.
✓ Branch 1 taken 608 times.
1431 for (int i = 0; i < s->nb_streams; i++) {
11309 AVStreamGroup *stg;
11310 const AVDictionaryEntry *tcr;
11311 823 AVStream *st = s->streams[i];
11312
11313
2/2
✓ Branch 0 taken 804 times.
✓ Branch 1 taken 19 times.
823 if (st->codecpar->codec_tag != MKTAG('t','m','c','d'))
11314 804 continue;
11315
11316 19 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TREF, NULL);
11317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!stg)
11318 return AVERROR(ENOMEM);
11319
11320 19 stg->id = st->id;
11321 19 tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
11322
11323
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 19 times.
80 for (int j = 0; j < s->nb_streams; j++) {
11324 61 AVStream *st2 = s->streams[j];
11325 61 MOVStreamContext *sc2 = st2->priv_data;
11326 61 MovTref *tag = mov_find_tref_tag(sc2, MKTAG('t','m','c','d'));
11327
11328
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 20 times.
61 if (!tag)
11329 41 continue;
11330
11331
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 20 times.
52 for (int k = 0; k < tag->nb_id; k++) {
11332
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 20 times.
32 if (tag->id[k] != st->id)
11333 12 continue;
11334
11335 20 err = avformat_stream_group_add_stream(stg, st2);
11336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (err < 0)
11337 return err;
11338
11339
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (tcr)
11340 20 av_dict_set(&st2->metadata, "timecode", tcr->value, AV_DICT_DONT_OVERWRITE);
11341 }
11342 }
11343
11344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!stg->nb_streams) {
11345 ff_remove_stream_group(s, stg);
11346 continue;
11347 }
11348
11349 19 err = avformat_stream_group_add_stream(stg, st);
11350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (err < 0)
11351 return err;
11352
11353 19 stg->params.tref->metadata_index = stg->nb_streams - 1;
11354 }
11355 608 export_orphan_timecode(s);
11356
11357 608 return 0;
11358 }
11359
11360 11 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
11361 uint32_t *tref_id, int nb_tref_id, int first_index)
11362 {
11363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!nb_tref_id)
11364 return NULL;
11365
11366
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 for (int i = first_index; i < s->nb_streams; i++)
11367
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 for (int j = 0; j < nb_tref_id; j++)
11368
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (s->streams[i]->index != st->index &&
11369
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 s->streams[i]->id == tref_id[j])
11370 11 return s->streams[i];
11371
11372 return NULL;
11373 }
11374
11375 608 static int mov_parse_cdsc_and_rndr_streams(AVFormatContext *s)
11376 {
11377 static const uint32_t tref_tags[] = {
11378 MKTAG('c','d','s','c'),
11379 MKTAG('r','n','d','r'),
11380 };
11381
11382 int err;
11383
11384 // Don't try to add a group if there's only one track
11385
2/2
✓ Branch 0 taken 492 times.
✓ Branch 1 taken 116 times.
608 if (s->nb_streams <= 1)
11386 492 return 0;
11387
11388
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 116 times.
447 for (int i = 0; i < s->nb_streams; i++) {
11389 331 AVStream *st = s->streams[i];
11390 331 MOVStreamContext *sc = st->priv_data;
11391
11392
2/2
✓ Branch 0 taken 662 times.
✓ Branch 1 taken 331 times.
993 for (int c = 0; c < FF_ARRAY_ELEMS(tref_tags); c++) {
11393 AVStreamGroup *stg;
11394 AVStream *st_ref;
11395 662 MovTref *tag = mov_find_tref_tag(sc, tref_tags[c]);
11396
11397
2/2
✓ Branch 0 taken 651 times.
✓ Branch 1 taken 11 times.
662 if (!tag)
11398 651 continue;
11399
11400 11 st_ref = mov_find_reference_track(s, st, tag->id, tag->nb_id, 0);
11401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!st_ref) {
11402 av_log(s, AV_LOG_WARNING, "Failed to find referenced stream\n");
11403 continue;
11404 }
11405
11406 11 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TREF, NULL);
11407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!stg)
11408 return AVERROR(ENOMEM);
11409
11410 11 stg->id = st_ref->id;
11411
11412 11 err = avformat_stream_group_add_stream(stg, st_ref);
11413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11414 return err;
11415
11416 11 err = avformat_stream_group_add_stream(stg, st);
11417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11418 return err;
11419
11420 11 stg->params.tref->metadata_index = stg->nb_streams - 1;
11421 }
11422 }
11423
11424 116 return 0;
11425 }
11426
11427 608 static int mov_parse_lcevc_streams(AVFormatContext *s)
11428 {
11429 int err;
11430
11431 // Don't try to add a group if there's only one track
11432
2/2
✓ Branch 0 taken 492 times.
✓ Branch 1 taken 116 times.
608 if (s->nb_streams <= 1)
11433 492 return 0;
11434
11435
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 116 times.
447 for (int i = 0; i < s->nb_streams; i++) {
11436 AVStreamGroup *stg;
11437 331 AVStream *st = s->streams[i];
11438 AVStream *st_base;
11439 331 MOVStreamContext *sc = st->priv_data;
11440 331 MovTref *tag = mov_find_tref_tag(sc, MKTAG('s','b','a','s'));
11441 331 int j = 0;
11442
11443 /* Find an enhancement stream. */
11444
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)
11445 331 continue;
11446
11447 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
11448 if (!stg)
11449 return AVERROR(ENOMEM);
11450
11451 stg->id = st->id;
11452 stg->params.layered_video->width = st->codecpar->width;
11453 stg->params.layered_video->height = st->codecpar->height;
11454
11455 while (st_base = mov_find_reference_track(s, st, tag->id, tag->nb_id, j)) {
11456 err = avformat_stream_group_add_stream(stg, st_base);
11457 if (err < 0)
11458 return err;
11459
11460 j = st_base->index + 1;
11461 }
11462 if (!j) {
11463 int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
11464 av_log(s, loglevel, "Failed to find base stream for LCEVC stream\n");
11465 ff_remove_stream_group(s, stg);
11466 if (s->error_recognition & AV_EF_EXPLODE)
11467 return AVERROR_INVALIDDATA;
11468 continue;
11469 }
11470
11471 err = avformat_stream_group_add_stream(stg, st);
11472 if (err < 0)
11473 return err;
11474
11475 stg->params.layered_video->el_index = stg->nb_streams - 1;
11476 }
11477
11478 116 return 0;
11479 }
11480
11481 608 static int mov_parse_dovi_streams(AVFormatContext *s)
11482 {
11483 int err;
11484
11485
2/2
✓ Branch 0 taken 492 times.
✓ Branch 1 taken 116 times.
608 if (s->nb_streams <= 1)
11486 492 return 0;
11487
11488 /* Identify legacy dual-track Dolby Vision profile 7 carriage per Annex
11489 * C of "Dolby Vision Streams Within the ISO Base Media File Format",
11490 * v2.7.1. The 'vdep' track reference type is shared with depth video
11491 * and multi-view dependencies. The spec-mandated DV-specific sample
11492 * entry combined with the dvcC configuration record disambiguates
11493 * those uses. */
11494
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 116 times.
447 for (int i = 0; i < s->nb_streams; i++) {
11495 AVStreamGroup *stg;
11496 331 AVStream *st = s->streams[i];
11497 AVStream *st_base;
11498 331 MOVStreamContext *sc = st->priv_data;
11499 331 MovTref *tag = mov_find_tref_tag(sc, MKTAG('v','d','e','p'));
11500 const AVPacketSideData *sd;
11501 const AVDOVIDecoderConfigurationRecord *dovi;
11502
11503
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)
11504 331 continue;
11505
11506 if (st->codecpar->codec_tag != MKTAG('d','v','h','e') &&
11507 st->codecpar->codec_tag != MKTAG('d','v','h','1'))
11508 continue;
11509
11510 sd = av_packet_side_data_get(st->codecpar->coded_side_data,
11511 st->codecpar->nb_coded_side_data,
11512 AV_PKT_DATA_DOVI_CONF);
11513 if (!sd)
11514 continue;
11515 dovi = (const AVDOVIDecoderConfigurationRecord *)sd->data;
11516
11517 /* EL track of a dual-track stream: rpu_present_flag = 1,
11518 * el_present_flag = 1, bl_present_flag = 0, dv_profile = 7. */
11519 if (dovi->dv_profile != 7 || !dovi->rpu_present_flag ||
11520 !dovi->el_present_flag || dovi->bl_present_flag)
11521 continue;
11522
11523 st_base = mov_find_reference_track(s, st, tag->id, tag->nb_id, 0);
11524 if (!st_base) {
11525 int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
11526 av_log(s, loglevel, "Failed to find base layer for Dolby Vision EL stream\n");
11527 if (s->error_recognition & AV_EF_EXPLODE)
11528 return AVERROR_INVALIDDATA;
11529 continue;
11530 }
11531
11532 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_DOLBY_VISION, NULL);
11533 if (!stg)
11534 return AVERROR(ENOMEM);
11535
11536 stg->id = st->id;
11537
11538 err = avformat_stream_group_add_stream(stg, st_base);
11539 if (err < 0)
11540 return err;
11541
11542 err = avformat_stream_group_add_stream(stg, st);
11543 if (err < 0)
11544 return err;
11545
11546 stg->params.layered_video->el_index = stg->nb_streams - 1;
11547 stg->params.layered_video->width = st_base->codecpar->width;
11548 stg->params.layered_video->height = st_base->codecpar->height;
11549 }
11550
11551 116 return 0;
11552 }
11553
11554 608 static void fix_stream_ids(AVFormatContext *s)
11555 {
11556 608 int highest_id = 0, lowest_iamf_id = INT_MAX;
11557
11558
2/2
✓ Branch 0 taken 823 times.
✓ Branch 1 taken 608 times.
1431 for (int i = 0; i < s->nb_streams; i++) {
11559 823 const AVStream *st = s->streams[i];
11560 823 const MOVStreamContext *sc = st->priv_data;
11561
2/2
✓ Branch 0 taken 759 times.
✓ Branch 1 taken 64 times.
823 if (!sc->iamf)
11562 759 highest_id = FFMAX(highest_id, st->id);
11563 }
11564
11565
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 608 times.
671 for (int i = 0; i < s->nb_stream_groups; i++) {
11566 63 AVStreamGroup *stg = s->stream_groups[i];
11567
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 12 times.
63 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
11568 51 continue;
11569
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_streams; j++) {
11570 64 AVStream *st = stg->streams[j];
11571 64 lowest_iamf_id = FFMIN(lowest_iamf_id, st->id);
11572 }
11573 }
11574
11575
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 8 times.
608 if (highest_id < lowest_iamf_id)
11576 600 return;
11577
11578 8 highest_id += !lowest_iamf_id;
11579
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++) {
11580 4 AVStreamGroup *stg = s->stream_groups[i];
11581
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
11582 2 continue;
11583
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_streams; j++) {
11584 14 AVStream *st = stg->streams[j];
11585 14 MOVStreamContext *sc = st->priv_data;
11586 14 st->id += highest_id;
11587 14 sc->iamf_stream_offset = highest_id;
11588 }
11589 }
11590 }
11591
11592 608 static int mov_read_header(AVFormatContext *s)
11593 {
11594 608 MOVContext *mov = s->priv_data;
11595 608 AVIOContext *pb = s->pb;
11596 int j, err;
11597 608 MOVAtom atom = { AV_RL32("root") };
11598 int i;
11599
11600 608 mov->fc = s;
11601 608 mov->trak_index = -1;
11602 608 mov->primary_item_id = -1;
11603 608 mov->cur_item_id = -1;
11604 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
11605
2/2
✓ Branch 0 taken 607 times.
✓ Branch 1 taken 1 times.
608 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
11606 607 atom.size = avio_size(pb);
11607 else
11608 1 atom.size = INT64_MAX;
11609
11610 /* check MOV header */
11611 do {
11612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if (mov->moov_retry)
11613 avio_seek(pb, 0, SEEK_SET);
11614
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 608 times.
608 if ((err = mov_read_default(mov, pb, atom)) < 0) {
11615 av_log(s, AV_LOG_ERROR, "error reading header\n");
11616 return err;
11617 }
11618 1215 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
11619
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++);
11620
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) {
11621 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
11622 return AVERROR_INVALIDDATA;
11623 }
11624 608 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
11625
11626
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) {
11627 18 err = mov_parse_heif_items(s);
11628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (err < 0)
11629 return err;
11630 }
11631 // prevent iloc and iinf boxes from being parsed while reading packets.
11632 // this is needed because an iinf box may have been parsed but ignored
11633 // for having old infe boxes which create no streams.
11634 608 mov->found_iloc = mov->found_iinf = 1;
11635
11636
2/2
✓ Branch 0 taken 607 times.
✓ Branch 1 taken 1 times.
608 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
11637
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)
11638 2 mov_read_chapters(s);
11639
2/2
✓ Branch 0 taken 822 times.
✓ Branch 1 taken 607 times.
1429 for (i = 0; i < s->nb_streams; i++)
11640
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 803 times.
822 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
11641 19 mov_read_timecode_track(s, s->streams[i]);
11642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 803 times.
803 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
11643 mov_read_rtmd_track(s, s->streams[i]);
11644 }
11645 }
11646
11647 /* Create metadata stream groups. */
11648 608 err = mov_parse_cdsc_and_rndr_streams(s);
11649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if (err < 0)
11650 return err;
11651
11652 /* copy timecode metadata from tmcd tracks to the related video streams */
11653 608 err = mov_parse_tmcd_streams(s);
11654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if (err < 0)
11655 return err;
11656
11657 /* Create LCEVC stream groups. */
11658 608 err = mov_parse_lcevc_streams(s);
11659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if (err < 0)
11660 return err;
11661
11662 /* Create Dolby Vision Profile 7 stream groups. */
11663 608 err = mov_parse_dovi_streams(s);
11664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if (err < 0)
11665 return err;
11666
11667
2/2
✓ Branch 0 taken 823 times.
✓ Branch 1 taken 608 times.
1431 for (i = 0; i < s->nb_streams; i++) {
11668 823 AVStream *st = s->streams[i];
11669 823 FFStream *const sti = ffstream(st);
11670 823 MOVStreamContext *sc = st->priv_data;
11671 823 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
11672 823 fix_timescale(mov, sc);
11673
11674 /* Set the primary extradata based on the first Sample if it doesn't reference the first stsd entry. */
11675
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 &&
11676
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) {
11677 3 sc->last_stsd_index = sc->stsc_data[0].id - 1;
11678 3 av_freep(&st->codecpar->extradata);
11679 3 st->codecpar->extradata_size = sc->extradata_size[sc->last_stsd_index];
11680
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (sc->extradata_size[sc->last_stsd_index]) {
11681 3 st->codecpar->extradata = av_mallocz(sc->extradata_size[sc->last_stsd_index] + AV_INPUT_BUFFER_PADDING_SIZE);
11682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata)
11683 return AVERROR(ENOMEM);
11684 3 memcpy(st->codecpar->extradata, sc->extradata[sc->last_stsd_index], sc->extradata_size[sc->last_stsd_index]);
11685 }
11686 }
11687
11688
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 485 times.
823 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
11689
2/2
✓ Branch 0 taken 151 times.
✓ Branch 1 taken 187 times.
338 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
11690 151 sti->skip_samples = st->codecpar->initial_padding;
11691 }
11692
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)
11693 369 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
11694 369 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
11695
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 811 times.
823 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
11696
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) {
11697 8 st->codecpar->width = sc->width;
11698 8 st->codecpar->height = sc->height;
11699 }
11700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
11701 st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
11702
11703 for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
11704 dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
11705
11706 err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
11707 if (err < 0)
11708 return err;
11709
11710 av_freep(&st->codecpar->extradata);
11711 st->codecpar->extradata_size = 0;
11712
11713 err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
11714 st->codecpar);
11715 if (err < 0)
11716 return err;
11717 }
11718 }
11719
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 822 times.
823 if (mov->handbrake_version &&
11720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
11721 st->codecpar->codec_id == AV_CODEC_ID_MP3) {
11722 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
11723 sti->need_parsing = AVSTREAM_PARSE_FULL;
11724 }
11725 }
11726
11727
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) {
11728
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 20 times.
49 for (i = 0; i < s->nb_streams; i++) {
11729 29 AVStream *st = s->streams[i];
11730 29 MOVStreamContext *sc = st->priv_data;
11731
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 4 times.
29 if (sc->duration_for_fps > 0) {
11732 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
11733 25 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
11734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (st->codecpar->bit_rate == INT64_MIN) {
11735 av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
11736 sc->data_size, sc->time_scale);
11737 st->codecpar->bit_rate = 0;
11738 if (s->error_recognition & AV_EF_EXPLODE)
11739 return AVERROR_INVALIDDATA;
11740 }
11741 }
11742 }
11743 }
11744
11745
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++) {
11746 if (mov->bitrates[i]) {
11747 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
11748 }
11749 }
11750
11751 608 ff_rfps_calculate(s);
11752
11753
2/2
✓ Branch 0 taken 823 times.
✓ Branch 1 taken 608 times.
1431 for (i = 0; i < s->nb_streams; i++) {
11754 823 AVStream *st = s->streams[i];
11755 823 MOVStreamContext *sc = st->priv_data;
11756
11757
3/3
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 428 times.
✓ Branch 2 taken 57 times.
823 switch (st->codecpar->codec_type) {
11758 338 case AVMEDIA_TYPE_AUDIO:
11759 338 err = ff_replaygain_export(st, s->metadata);
11760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
338 if (err < 0)
11761 return err;
11762 338 break;
11763 428 case AVMEDIA_TYPE_VIDEO:
11764
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 420 times.
428 if (sc->display_matrix) {
11765
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,
11766 AV_PKT_DATA_DISPLAYMATRIX,
11767 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
11768 return AVERROR(ENOMEM);
11769
11770 8 sc->display_matrix = NULL;
11771 }
11772
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 422 times.
428 if (sc->stereo3d) {
11773
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,
11774 AV_PKT_DATA_STEREO3D,
11775 6 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
11776 return AVERROR(ENOMEM);
11777
11778 6 sc->stereo3d = NULL;
11779 }
11780
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 424 times.
428 if (sc->spherical) {
11781
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,
11782 AV_PKT_DATA_SPHERICAL,
11783 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
11784 return AVERROR(ENOMEM);
11785
11786 4 sc->spherical = NULL;
11787 }
11788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 428 times.
428 if (sc->mastering) {
11789 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11790 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
11791 (uint8_t *)sc->mastering, sc->mastering_size, 0))
11792 return AVERROR(ENOMEM);
11793
11794 sc->mastering = NULL;
11795 }
11796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 428 times.
428 if (sc->coll) {
11797 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11798 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
11799 (uint8_t *)sc->coll, sc->coll_size, 0))
11800 return AVERROR(ENOMEM);
11801
11802 sc->coll = NULL;
11803 }
11804
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 424 times.
428 if (sc->ambient) {
11805
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,
11806 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
11807 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
11808 return AVERROR(ENOMEM);
11809
11810 4 sc->ambient = NULL;
11811 }
11812 428 break;
11813 }
11814 }
11815
11816 608 fix_stream_ids(s);
11817
11818 608 ff_configure_buffers_for_index(s, AV_TIME_BASE);
11819
11820
2/2
✓ Branch 0 taken 479 times.
✓ Branch 1 taken 608 times.
1087 for (i = 0; i < mov->frag_index.nb_items; i++)
11821
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)
11822 469 mov->frag_index.item[i].headers_read = 1;
11823
11824 608 return 0;
11825 }
11826
11827 117827 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
11828 {
11829 117827 AVIndexEntry *sample = NULL;
11830 117827 int64_t best_dts = INT64_MAX;
11831 int i;
11832 117827 MOVContext *mov = s->priv_data;
11833
3/4
✓ Branch 0 taken 117827 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 117782 times.
117827 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
11834
2/2
✓ Branch 0 taken 152012 times.
✓ Branch 1 taken 117827 times.
269839 for (i = 0; i < s->nb_streams; i++) {
11835 152012 AVStream *avst = s->streams[i];
11836 152012 FFStream *const avsti = ffstream(avst);
11837 152012 MOVStreamContext *msc = avst->priv_data;
11838
4/4
✓ Branch 0 taken 142489 times.
✓ Branch 1 taken 9523 times.
✓ Branch 2 taken 138975 times.
✓ Branch 3 taken 3514 times.
152012 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
11839 138975 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
11840 138975 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
11841
2/2
✓ Branch 0 taken 123609 times.
✓ Branch 1 taken 15366 times.
138975 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
11842 138975 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
11843
3/6
✓ Branch 0 taken 21732 times.
✓ Branch 1 taken 117243 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 21732 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
138975 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
11844
1/2
✓ Branch 0 taken 21732 times.
✗ Branch 1 not taken.
21732 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
11845
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 21732 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 21732 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 21732 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19527 times.
✓ Branch 9 taken 2205 times.
21732 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
11846
4/4
✓ Branch 0 taken 11398 times.
✓ Branch 1 taken 8129 times.
✓ Branch 2 taken 2205 times.
✓ Branch 3 taken 11398 times.
21732 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
11847
3/4
✓ Branch 0 taken 762 times.
✓ Branch 1 taken 1443 times.
✓ Branch 2 taken 762 times.
✗ Branch 3 not taken.
2205 (dtsdiff > AV_TIME_BASE && dts < best_dts && mov->interleaved_read)))))) {
11848 126134 sample = current_sample;
11849 126134 best_dts = dts;
11850 126134 *st = avst;
11851 }
11852 }
11853 }
11854 117827 return sample;
11855 }
11856
11857 9 static int should_retry(AVIOContext *pb, int error_code) {
11858
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))
11859 9 return 0;
11860
11861 return 1;
11862 }
11863
11864 49 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
11865 {
11866 int ret;
11867 49 MOVContext *mov = s->priv_data;
11868
11869
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)
11870 1 target = mov->frag_index.item[index].moof_offset;
11871
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) {
11872 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
11873 return AVERROR_INVALIDDATA;
11874 }
11875
11876 49 mov->next_root_atom = 0;
11877
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)
11878 48 index = search_frag_moof_offset(&mov->frag_index, target);
11879
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 &&
11880
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 mov->frag_index.item[index].moof_offset == target) {
11881
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 4 times.
42 if (index + 1 < mov->frag_index.nb_items)
11882 38 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11883
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 6 times.
42 if (mov->frag_index.item[index].headers_read)
11884 36 return 0;
11885 6 mov->frag_index.item[index].headers_read = 1;
11886 }
11887
11888 13 mov->found_mdat = 0;
11889
11890 13 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
11891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (ret < 0)
11892 return ret;
11893
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 6 times.
13 if (avio_feof(s->pb))
11894 7 return AVERROR_EOF;
11895 6 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
11896
11897 6 return 1;
11898 }
11899
11900 17 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
11901 {
11902 17 MOVStreamContext *sc = st->priv_data;
11903 uint8_t *side, *extradata;
11904 int extradata_size;
11905
11906 /* Save the current index. */
11907 17 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
11908
11909 /* Notify the decoder that extradata changed. */
11910 17 extradata_size = sc->extradata_size[sc->last_stsd_index];
11911 17 extradata = sc->extradata[sc->last_stsd_index];
11912
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) {
11913 14 side = av_packet_new_side_data(pkt,
11914 AV_PKT_DATA_NEW_EXTRADATA,
11915 extradata_size);
11916
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!side)
11917 return AVERROR(ENOMEM);
11918 14 memcpy(side, extradata, extradata_size);
11919 }
11920
11921 17 return 0;
11922 }
11923
11924 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
11925 {
11926 /* We can't make assumptions about the structure of the payload,
11927 because it may include multiple cdat and cdt2 samples. */
11928 const uint32_t cdat = AV_RB32("cdat");
11929 const uint32_t cdt2 = AV_RB32("cdt2");
11930 int ret, out_size = 0;
11931
11932 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
11933 if (src_size < 10)
11934 return AVERROR_INVALIDDATA;
11935
11936 /* avoid an int overflow: */
11937 if ((src_size - 8) / 2 >= INT_MAX / 3)
11938 return AVERROR_INVALIDDATA;
11939
11940 ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
11941 if (ret < 0)
11942 return ret;
11943
11944 /* parse and re-format the c608 payload in one pass. */
11945 while (src_size >= 10) {
11946 const uint32_t atom_size = avio_rb32(pb);
11947 const uint32_t atom_type = avio_rb32(pb);
11948 const uint32_t data_size = atom_size - 8;
11949 const uint8_t cc_field =
11950 atom_type == cdat ? 1 :
11951 atom_type == cdt2 ? 2 :
11952 0;
11953
11954 /* account for bytes consumed for atom size and type. */
11955 src_size -= 8;
11956
11957 /* make sure the data size stays within the buffer boundaries. */
11958 if (data_size < 2 || data_size > src_size) {
11959 ret = AVERROR_INVALIDDATA;
11960 break;
11961 }
11962
11963 /* make sure the data size is consistent with N byte pairs. */
11964 if (data_size % 2 != 0) {
11965 ret = AVERROR_INVALIDDATA;
11966 break;
11967 }
11968
11969 if (!cc_field) {
11970 /* neither cdat or cdt2 ... skip it */
11971 avio_skip(pb, data_size);
11972 src_size -= data_size;
11973 continue;
11974 }
11975
11976 for (uint32_t i = 0; i < data_size; i += 2) {
11977 pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
11978 pkt->data[out_size + 1] = avio_r8(pb);
11979 pkt->data[out_size + 2] = avio_r8(pb);
11980 out_size += 3;
11981 src_size -= 2;
11982 }
11983 }
11984
11985 if (src_size > 0)
11986 /* skip any remaining unread portion of the input payload */
11987 avio_skip(pb, src_size);
11988
11989 av_shrink_packet(pkt, out_size);
11990 return ret;
11991 }
11992
11993 117198 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
11994 int64_t current_index, AVPacket *pkt)
11995 {
11996 117198 MOVContext *mov = s->priv_data;
11997 117198 MOVStreamContext *sc = st->priv_data;
11998
11999 117198 pkt->stream_index = sc->ffindex;
12000 117198 pkt->dts = sample->timestamp;
12001
2/2
✓ Branch 0 taken 297 times.
✓ Branch 1 taken 116901 times.
117198 if (sample->flags & AVINDEX_DISCARD_FRAME) {
12002 297 pkt->flags |= AV_PKT_FLAG_DISCARD;
12003 }
12004
4/4
✓ Branch 0 taken 97301 times.
✓ Branch 1 taken 19897 times.
✓ Branch 2 taken 97289 times.
✓ Branch 3 taken 12 times.
117198 if (sc->stts_count && sc->tts_index < sc->tts_count)
12005 97289 pkt->duration = sc->tts_data[sc->tts_index].duration;
12006
3/4
✓ Branch 0 taken 4624 times.
✓ Branch 1 taken 112574 times.
✓ Branch 2 taken 4624 times.
✗ Branch 3 not taken.
117198 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
12007 4624 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
12008 } else {
12009
2/2
✓ Branch 0 taken 15833 times.
✓ Branch 1 taken 96741 times.
112574 if (pkt->duration == 0) {
12010 15833 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
12011
2/2
✓ Branch 0 taken 15741 times.
✓ Branch 1 taken 92 times.
15833 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
12012
2/2
✓ Branch 0 taken 15787 times.
✓ Branch 1 taken 46 times.
15833 if (next_dts >= pkt->dts)
12013 15787 pkt->duration = next_dts - pkt->dts;
12014 }
12015 112574 pkt->pts = pkt->dts;
12016 }
12017
12018
4/4
✓ Branch 0 taken 98424 times.
✓ Branch 1 taken 18774 times.
✓ Branch 2 taken 98346 times.
✓ Branch 3 taken 78 times.
117198 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && !mov->fragment.found_tfhd &&
12019
2/2
✓ Branch 1 taken 228 times.
✓ Branch 2 taken 98118 times.
98346 sc->current_sample >= ffstream(st)->nb_index_entries) {
12020 228 int64_t pts = av_rescale_q(pkt->pts, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12021 228 int64_t total = av_rescale_q(st->duration, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12022 228 int64_t duration = pkt->duration;
12023
12024
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 226 times.
228 if (st->duration < pkt->pts) {
12025 2 duration = 0;
12026 } else
12027 226 duration = FFMIN(duration, (uint64_t)st->duration - pkt->pts);
12028
12029 228 duration = av_rescale_q(duration, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12030
12031
2/2
✓ Branch 1 taken 189 times.
✓ Branch 2 taken 39 times.
228 if (!ffstream(st)->first_discard_sample)
12032 189 ffstream(st)->first_discard_sample = av_sat_add64(pts, duration);
12033
2/2
✓ Branch 1 taken 189 times.
✓ Branch 2 taken 39 times.
228 if (!ffstream(st)->last_discard_sample)
12034 189 ffstream(st)->last_discard_sample = total;
12035 }
12036
12037
4/4
✓ Branch 0 taken 97301 times.
✓ Branch 1 taken 19897 times.
✓ Branch 2 taken 97289 times.
✓ Branch 3 taken 12 times.
117198 if (sc->tts_data && sc->tts_index < sc->tts_count) {
12038 /* update tts context */
12039 97289 sc->tts_sample++;
12040
1/2
✓ Branch 0 taken 97289 times.
✗ Branch 1 not taken.
97289 if (sc->tts_index < sc->tts_count &&
12041
1/2
✓ Branch 0 taken 97289 times.
✗ Branch 1 not taken.
97289 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
12042 97289 sc->tts_index++;
12043 97289 sc->tts_sample = 0;
12044 }
12045 }
12046
12047
4/4
✓ Branch 0 taken 1055 times.
✓ Branch 1 taken 116143 times.
✓ Branch 2 taken 923 times.
✓ Branch 3 taken 132 times.
117198 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
12048 923 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
12049 923 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
12050
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;
12051 }
12052 117198 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
12053 117198 pkt->pos = sample->pos;
12054
12055 /* Multiple stsd handling. */
12056
2/2
✓ Branch 0 taken 113814 times.
✓ Branch 1 taken 3384 times.
117198 if (sc->stsc_data) {
12057
1/2
✓ Branch 0 taken 113814 times.
✗ Branch 1 not taken.
113814 if (sc->stsc_data[sc->stsc_index].id > 0 &&
12058
2/2
✓ Branch 0 taken 113771 times.
✓ Branch 1 taken 43 times.
113814 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
12059
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 113754 times.
113771 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
12060 17 int ret = mov_change_extradata(st, pkt);
12061
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (ret < 0)
12062 return ret;
12063 }
12064
12065 /* Update the stsc index for the next sample */
12066 113814 sc->stsc_sample++;
12067
2/2
✓ Branch 1 taken 56919 times.
✓ Branch 2 taken 56895 times.
113814 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
12068
2/2
✓ Branch 1 taken 1215 times.
✓ Branch 2 taken 55704 times.
56919 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
12069 1215 sc->stsc_index++;
12070 1215 sc->stsc_sample = 0;
12071 }
12072 }
12073
12074 117198 return 0;
12075 }
12076
12077 108539 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
12078 {
12079 108539 MOVContext *mov = s->priv_data;
12080 MOVStreamContext *sc;
12081 AVIndexEntry *sample;
12082 108539 AVStream *st = NULL;
12083 108539 FFStream *avsti = NULL;
12084 int64_t current_index;
12085 int ret;
12086 int i;
12087 108539 mov->fc = s;
12088 9288 retry:
12089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117827 times.
117827 if (s->pb->pos == 0) {
12090
12091 // Discard current fragment index
12092 if (mov->frag_index.allocated_size > 0) {
12093 for(int i = 0; i < mov->frag_index.nb_items; i++) {
12094 av_freep(&mov->frag_index.item[i].stream_info);
12095 }
12096 av_freep(&mov->frag_index.item);
12097 mov->frag_index.nb_items = 0;
12098 mov->frag_index.allocated_size = 0;
12099 mov->frag_index.current = -1;
12100 mov->frag_index.complete = 0;
12101 }
12102
12103 for (i = 0; i < s->nb_streams; i++) {
12104 AVStream *avst = s->streams[i];
12105 MOVStreamContext *msc = avst->priv_data;
12106
12107 // Clear current sample
12108 mov_current_sample_set(msc, 0);
12109 msc->tts_index = 0;
12110
12111 // Discard current index entries
12112 avsti = ffstream(avst);
12113 if (avsti->index_entries_allocated_size > 0) {
12114 av_freep(&avsti->index_entries);
12115 avsti->index_entries_allocated_size = 0;
12116 avsti->nb_index_entries = 0;
12117 }
12118 }
12119
12120 if ((ret = mov_switch_root(s, -1, -1)) < 0)
12121 return ret;
12122 }
12123 117827 sample = mov_find_next_sample(s, &st);
12124
6/6
✓ Branch 0 taken 117243 times.
✓ Branch 1 taken 584 times.
✓ Branch 2 taken 652 times.
✓ Branch 3 taken 116591 times.
✓ Branch 4 taken 36 times.
✓ Branch 5 taken 616 times.
117827 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
12125
2/2
✓ Branch 0 taken 572 times.
✓ Branch 1 taken 48 times.
620 if (!mov->next_root_atom)
12126 572 return AVERROR_EOF;
12127
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)
12128 7 return ret;
12129 41 goto retry;
12130 }
12131 117207 sc = st->priv_data;
12132 /* must be done just before reading, to avoid infinite loop on sample */
12133 117207 current_index = sc->current_index;
12134 117207 mov_current_sample_inc(sc);
12135
12136
2/2
✓ Branch 0 taken 616 times.
✓ Branch 1 taken 116591 times.
117207 if (mov->next_root_atom) {
12137 616 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
12138 616 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
12139 }
12140
12141
4/4
✓ Branch 0 taken 9257 times.
✓ Branch 1 taken 107950 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 9247 times.
117207 if (st->discard != AVDISCARD_ALL || sc->iamf) {
12142 107960 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
12143
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 107953 times.
107960 if (ret64 != sample->pos) {
12144 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
12145 sc->ffindex, sample->pos);
12146
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
12147 mov_current_sample_dec(sc);
12148
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
12149 7 return (int)ret64;
12150 }
12151 return AVERROR_INVALIDDATA;
12152 }
12153
12154
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 107953 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
107953 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
12155 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
12156 goto retry;
12157 }
12158
12159
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 107953 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
107953 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
12160 ret = get_eia608_packet(sc->pb, pkt, sample->size);
12161 #if CONFIG_IAMFDEC
12162
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 107871 times.
107953 else if (sc->iamf) {
12163 int64_t pts, dts, pos, duration;
12164 82 int flags, size = sample->size;
12165 82 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
12166 82 pts = pkt->pts; dts = pkt->dts;
12167 82 pos = pkt->pos; flags = pkt->flags;
12168 82 duration = pkt->duration;
12169
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) {
12170 454 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
12171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 454 times.
454 if (ret < 0) {
12172 if (should_retry(sc->pb, ret))
12173 mov_current_sample_dec(sc);
12174 return ret;
12175 }
12176 454 size -= ret;
12177
12178
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 334 times.
454 if (pkt->flags & AV_PKT_FLAG_DISCARD) {
12179 120 av_packet_unref(pkt);
12180 120 ret = 0;
12181 120 continue;
12182 }
12183 334 pkt->pts = pts; pkt->dts = dts;
12184 334 pkt->pos = pos; pkt->flags |= flags;
12185 334 pkt->duration = duration;
12186 334 ret = ff_buffer_packet(s, pkt);
12187 }
12188
1/2
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
82 if (!ret)
12189 82 return FFERROR_REDO;
12190 }
12191 #endif
12192
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 107868 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
107874 else if (st->codecpar->codec_id == AV_CODEC_ID_APV && sample->size > 4) {
12193 3 uint32_t au_size = avio_rb32(sc->pb);
12194 3 int explode = !!(mov->fc->error_recognition & AV_EF_EXPLODE);
12195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (au_size > sample->size - 4) {
12196 av_log(s, explode ? AV_LOG_ERROR : AV_LOG_WARNING,
12197 "APV au_size %u exceeds sample body %d\n",
12198 au_size, sample->size - 4);
12199 if (explode)
12200 return AVERROR_INVALIDDATA;
12201 au_size = sample->size - 4;
12202 }
12203 3 ret = av_get_packet(sc->pb, pkt, au_size);
12204 } else
12205 107868 ret = av_get_packet(sc->pb, pkt, sample->size);
12206
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 107869 times.
107871 if (ret < 0) {
12207
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (should_retry(sc->pb, ret)) {
12208 mov_current_sample_dec(sc);
12209 }
12210 2 return ret;
12211 }
12212 #if CONFIG_DV_DEMUXER
12213
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 107869 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
107869 if (mov->dv_demux && sc->dv_audio_container) {
12214 ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
12215 av_packet_unref(pkt);
12216 if (ret < 0)
12217 return ret;
12218 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
12219 if (ret < 0)
12220 return ret;
12221 }
12222 #endif
12223
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 107851 times.
107869 if (sc->has_palette) {
12224 uint8_t *pal;
12225
12226 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
12227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
12228 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
12229 } else {
12230 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
12231 18 sc->has_palette = 0;
12232 }
12233 }
12234
4/6
✓ Branch 0 taken 329 times.
✓ Branch 1 taken 107540 times.
✓ Branch 3 taken 329 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 329 times.
✗ Branch 6 not taken.
107869 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
12235
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 329 times.
329 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
12236 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
12237 }
12238 }
12239
12240 117116 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
12241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117116 times.
117116 if (ret < 0)
12242 return ret;
12243
12244
2/2
✓ Branch 0 taken 9247 times.
✓ Branch 1 taken 107869 times.
117116 if (st->discard == AVDISCARD_ALL)
12245 9247 goto retry;
12246
12247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107869 times.
107869 if (mov->aax_mode)
12248 aax_filter(pkt->data, pkt->size, mov);
12249
12250 107869 ret = cenc_filter(mov, st, sc, pkt, current_index);
12251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107869 times.
107869 if (ret < 0) {
12252 return ret;
12253 }
12254
12255 107869 return 0;
12256 }
12257
12258 365 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
12259 {
12260 365 MOVContext *mov = s->priv_data;
12261 int index;
12262
12263
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 28 times.
365 if (!mov->frag_index.complete)
12264 337 return 0;
12265
12266 28 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
12267
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 24 times.
28 if (index < 0)
12268 4 index = 0;
12269
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (!mov->frag_index.item[index].headers_read)
12270 1 return mov_switch_root(s, -1, index);
12271
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (index + 1 < mov->frag_index.nb_items)
12272 27 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
12273
12274 27 return 0;
12275 }
12276
12277 static int is_open_key_sample(const MOVStreamContext *sc, int sample)
12278 {
12279 // TODO: a bisect search would scale much better
12280 for (int i = 0; i < sc->open_key_samples_count; i++) {
12281 const int oks = sc->open_key_samples[i];
12282 if (oks == sample)
12283 return 1;
12284 if (oks > sample) /* list is monotically increasing so we can stop early */
12285 break;
12286 }
12287 return 0;
12288 }
12289
12290 /*
12291 * Some key sample may be key frames but not IDR frames, so a random access to
12292 * them may not be allowed.
12293 */
12294 231 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
12295 {
12296 231 MOVStreamContext *sc = st->priv_data;
12297 231 FFStream *const sti = ffstream(st);
12298 int64_t key_sample_dts, key_sample_pts;
12299
12300
1/2
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
231 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
12301 231 return 1;
12302
12303 if (sample >= sc->sample_offsets_count)
12304 return 1;
12305
12306 av_assert0(sample >= 0);
12307 key_sample_dts = sti->index_entries[sample].timestamp;
12308 key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
12309
12310 /*
12311 * If the sample needs to be presented before an open key sample, they may
12312 * not be decodable properly, even though they come after in decoding
12313 * order.
12314 */
12315 if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
12316 return 0;
12317
12318 return 1;
12319 }
12320
12321 365 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
12322 {
12323 365 MOVStreamContext *sc = st->priv_data;
12324 365 FFStream *const sti = ffstream(st);
12325 int sample, time_sample, ret, requested_sample;
12326 int64_t next_ts;
12327 unsigned int i;
12328
12329 // Here we consider timestamp to be PTS, hence try to offset it so that we
12330 // can search over the DTS timeline.
12331 365 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
12332
12333 365 ret = mov_seek_fragment(s, st, timestamp);
12334
1/2
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
365 if (ret < 0)
12335 return ret;
12336
12337 for (;;) {
12338 365 sample = av_index_search_timestamp(st, timestamp, flags);
12339 365 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
12340
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)
12341 43 sample = 0;
12342
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 339 times.
365 if (sample < 0) /* not sure what to do */
12343 26 return AVERROR_INVALIDDATA;
12344
12345
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))
12346 break;
12347
12348 next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
12349 requested_sample = av_index_search_timestamp(st, next_ts, flags);
12350 if (requested_sample < 0)
12351 return AVERROR_INVALIDDATA;
12352
12353 // If we've reached a different sample trying to find a good pts to
12354 // seek to, give up searching because we'll end up seeking back to
12355 // sample 0 on every seek.
12356 if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
12357 break;
12358
12359 timestamp = next_ts;
12360 }
12361
12362 339 mov_current_sample_set(sc, sample);
12363 339 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
12364 /* adjust time to sample index */
12365
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 125 times.
339 if (sc->tts_data) {
12366 214 time_sample = 0;
12367
1/2
✓ Branch 0 taken 60310 times.
✗ Branch 1 not taken.
60310 for (i = 0; i < sc->tts_count; i++) {
12368 60310 int next = time_sample + sc->tts_data[i].count;
12369
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 60096 times.
60310 if (next > sc->current_sample) {
12370 214 sc->tts_index = i;
12371 214 sc->tts_sample = sc->current_sample - time_sample;
12372 214 break;
12373 }
12374 60096 time_sample = next;
12375 }
12376 }
12377
12378 /* adjust stsd index */
12379
2/2
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 28 times.
339 if (sc->chunk_count) {
12380 311 time_sample = 0;
12381
1/2
✓ Branch 0 taken 383 times.
✗ Branch 1 not taken.
383 for (i = 0; i < sc->stsc_count; i++) {
12382 383 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
12383
2/2
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 72 times.
383 if (next > sc->current_sample) {
12384 311 sc->stsc_index = i;
12385 311 sc->stsc_sample = sc->current_sample - time_sample;
12386 311 break;
12387 }
12388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
12389 72 time_sample = next;
12390 }
12391 }
12392
12393 339 return sample;
12394 }
12395
12396 339 static int64_t mov_get_skip_samples(AVStream *st, int sample)
12397 {
12398 339 FFStream *const sti = ffstream(st);
12399 339 int64_t first_ts = sti->index_entries[0].timestamp;
12400 339 int64_t ts = sti->index_entries[sample].timestamp;
12401 int64_t off;
12402
12403
2/2
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 152 times.
339 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
12404 187 return 0;
12405
12406 /* compute skip samples according to stream initial_padding, seek ts and first ts */
12407 152 off = av_rescale_q(ts - first_ts, st->time_base,
12408 152 (AVRational){1, st->codecpar->sample_rate});
12409 152 return FFMAX(st->codecpar->initial_padding - off, 0);
12410 }
12411
12412 343 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
12413 {
12414 343 MOVContext *mc = s->priv_data;
12415 AVStream *st;
12416 FFStream *sti;
12417 int sample;
12418 int i;
12419
12420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 343 times.
343 if (stream_index >= s->nb_streams)
12421 return AVERROR_INVALIDDATA;
12422
12423 343 st = s->streams[stream_index];
12424 343 sti = ffstream(st);
12425 343 sample = mov_seek_stream(s, st, sample_time, flags);
12426
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 317 times.
343 if (sample < 0)
12427 26 return sample;
12428
12429
1/2
✓ Branch 0 taken 317 times.
✗ Branch 1 not taken.
317 if (mc->seek_individually) {
12430 /* adjust seek timestamp to found sample timestamp */
12431 317 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
12432 317 sti->skip_samples = mov_get_skip_samples(st, sample);
12433
12434
2/2
✓ Branch 0 taken 339 times.
✓ Branch 1 taken 317 times.
656 for (i = 0; i < s->nb_streams; i++) {
12435 339 AVStream *const st = s->streams[i];
12436 339 FFStream *const sti = ffstream(st);
12437 int64_t timestamp;
12438
12439
2/2
✓ Branch 0 taken 317 times.
✓ Branch 1 taken 22 times.
339 if (stream_index == i)
12440 317 continue;
12441
12442 22 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
12443 22 sample = mov_seek_stream(s, st, timestamp, flags);
12444
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (sample >= 0)
12445 22 sti->skip_samples = mov_get_skip_samples(st, sample);
12446 }
12447 } else {
12448 for (i = 0; i < s->nb_streams; i++) {
12449 MOVStreamContext *sc;
12450 st = s->streams[i];
12451 sc = st->priv_data;
12452 mov_current_sample_set(sc, 0);
12453 }
12454 while (1) {
12455 MOVStreamContext *sc;
12456 AVIndexEntry *entry = mov_find_next_sample(s, &st);
12457 if (!entry)
12458 return AVERROR_INVALIDDATA;
12459 sc = st->priv_data;
12460 if (sc->ffindex == stream_index && sc->current_sample == sample)
12461 break;
12462 mov_current_sample_inc(sc);
12463 }
12464 }
12465 317 return 0;
12466 }
12467
12468 #define OFFSET(x) offsetof(MOVContext, x)
12469 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
12470 static const AVOption mov_options[] = {
12471 {"use_absolute_path",
12472 "allow using absolute path when opening alias, this is a possible security issue",
12473 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
12474 0, 1, FLAGS},
12475 {"seek_streams_individually",
12476 "Seek each stream individually to the closest point",
12477 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
12478 0, 1, FLAGS},
12479 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
12480 0, 1, FLAGS},
12481 {"advanced_editlist",
12482 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
12483 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
12484 0, 1, FLAGS},
12485 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
12486 0, 1, FLAGS},
12487 {"use_mfra_for",
12488 "use mfra for fragment timestamps",
12489 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
12490 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
12491 .unit = "use_mfra_for"},
12492 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
12493 FLAGS, .unit = "use_mfra_for" },
12494 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
12495 FLAGS, .unit = "use_mfra_for" },
12496 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
12497 FLAGS, .unit = "use_mfra_for" },
12498 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
12499 0, 1, FLAGS},
12500 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
12501 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
12502 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
12503 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
12504 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
12505 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12506 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
12507 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12508 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
12509 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12510 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
12511 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
12512 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
12513 .flags = AV_OPT_FLAG_DECODING_PARAM },
12514 { "decryption_key", "The default media decryption key (hex)", OFFSET(decryption_default_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12515 { "decryption_keys", "The media decryption keys by KID (hex)", OFFSET(decryption_keys), AV_OPT_TYPE_DICT, .flags = AV_OPT_FLAG_DECODING_PARAM },
12516 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
12517 {.i64 = 0}, 0, 1, FLAGS },
12518 { "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 },
12519 { "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 },
12520
12521 { NULL },
12522 };
12523
12524 static const AVClass mov_class = {
12525 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
12526 .item_name = av_default_item_name,
12527 .option = mov_options,
12528 .version = LIBAVUTIL_VERSION_INT,
12529 };
12530
12531 const FFInputFormat ff_mov_demuxer = {
12532 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
12533 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
12534 .p.priv_class = &mov_class,
12535 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4v,m4b,ism,ismv,isma,f4v,avif,heic,heif",
12536 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
12537 .priv_data_size = sizeof(MOVContext),
12538 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
12539 .read_probe = mov_probe,
12540 .read_header = mov_read_header,
12541 .read_packet = mov_read_packet,
12542 .read_close = mov_read_close,
12543 .read_seek = mov_read_seek,
12544 };
12545