FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2026-09-26 20:14:34
Exec Total Coverage
Lines: 4802 7501 64.0%
Functions: 193 232 83.2%
Branches: 2750 5065 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 405 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
172 char *dst, int dstlen)
173 {
174 405 char *p = dst;
175 405 char *end = dst+dstlen-1;
176 int i;
177
178
2/2
✓ Branch 0 taken 3392 times.
✓ Branch 1 taken 405 times.
3797 for (i = 0; i < len; i++) {
179 3392 uint8_t t, c = avio_r8(pb);
180
181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3392 times.
3392 if (p >= end)
182 ✗ continue;
183
184
2/2
✓ Branch 0 taken 3384 times.
✓ Branch 1 taken 8 times.
3392 if (c < 0x80)
185 3384 *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 405 *p = 0;
190 405 return p - dst;
191 }
192
193 /**
194 * Get the requested item.
195 */
196 169 static HEIFItem *get_heif_item(MOVContext *c, unsigned id)
197 {
198 169 HEIFItem *item = NULL;
199
200
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 15 times.
383 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 169 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 290 static AVStream *get_curr_st(MOVContext *c)
216 {
217 290 AVStream *st = NULL;
218 HEIFItem *item;
219
220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 290 times.
290 if (c->fc->nb_streams < 1)
221 ✗ return NULL;
222
223
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 49 times.
290 if (c->cur_item_id == -1)
224 241 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 633 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
348 {
349 633 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
350 633 char key2[32], language[4] = {0};
351 633 char *str = NULL;
352 633 const char *key = NULL;
353 633 uint16_t langcode = 0;
354 633 uint32_t data_type = 0, str_size_alloc;
355 uint64_t str_size;
356 633 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
357 633 int raw = 0;
358 633 int num = 0;
359 AVDictionary **metadata;
360
361
3/4
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 580 times.
✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
633 if (c->trak_index >= 0 && c->trak_index < c->fc->nb_streams)
362 53 metadata = &c->fc->streams[c->trak_index]->metadata;
363 else
364 580 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 238 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 75 times.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✓ Branch 73 taken 3 times.
✓ Branch 74 taken 5 times.
633 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 75 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 435 times.
✓ Branch 1 taken 205 times.
✓ Branch 2 taken 435 times.
✗ Branch 3 not taken.
1059 if (c->itunes_metadata && atom.size > 8) {
460 435 int data_size = avio_rb32(pb);
461 435 int tag = avio_rl32(pb);
462
3/6
✓ Branch 0 taken 435 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 435 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 435 times.
✗ Branch 5 not taken.
435 if (tag == MKTAG('d','a','t','a') && data_size <= atom.size && data_size >= 16) {
463 435 data_type = avio_rb32(pb); // type
464 435 avio_rb32(pb); // unknown
465 435 str_size = data_size - 16;
466 435 atom.size -= 16;
467
468
5/6
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 278 times.
✓ Branch 2 taken 104 times.
✓ Branch 3 taken 53 times.
✓ Branch 4 taken 104 times.
✗ Branch 5 not taken.
435 if (!key && c->found_hdlr_mdta && c->meta_keys) {
469 104 uint32_t index = av_bswap32(atom.type); // BE number has been read as LE
470
2/4
✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104 times.
✗ Branch 3 not taken.
104 if (index < c->meta_keys_count && index > 0) {
471 104 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 419 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 382 times.
✓ Branch 3 taken 37 times.
435 if (atom.type == MKTAG('c', 'o', 'v', 'r') ||
479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 382 times.
382 (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 175 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 55 times.
✓ Branch 3 taken 120 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 55 times.
✓ Branch 6 taken 120 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 109 times.
✓ Branch 9 taken 11 times.
205 } 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 96 str_size = atom.size;
504
505
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 619 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
619 if (c->export_all && !key) {
506 ✗ key = av_fourcc_make_string(tmp_key, atom.type);
507 }
508
509
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 497 times.
619 if (!key)
510 122 return 0;
511
2/4
✓ Branch 0 taken 497 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 497 times.
497 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 72 times.
✓ Branch 1 taken 425 times.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
497 num = (data_type >= 21 && data_type <= 23);
517
4/4
✓ Branch 0 taken 425 times.
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 414 times.
✓ Branch 3 taken 11 times.
497 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
518 497 str = av_mallocz(str_size_alloc);
519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 497 times.
497 if (!str)
520 ✗ return AVERROR(ENOMEM);
521
522
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 423 times.
497 if (parse)
523 74 parse(c, pb, str_size, key);
524 else {
525
8/10
✓ Branch 0 taken 412 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 412 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 108 times.
✓ Branch 5 taken 304 times.
✓ Branch 6 taken 91 times.
✓ Branch 7 taken 17 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 91 times.
423 if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
526 17 mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
527
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 404 times.
406 } 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 404 times.
404 } 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 40 times.
✓ Branch 1 taken 364 times.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
444 } else if (data_type == 23 && str_size >= 4) { // BE float32
560 40 float val = av_int2float(avio_rb32(pb));
561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 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 364 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
364 } 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 364 int ret = ffio_read_size(pb, str, str_size);
577
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 364 times.
364 if (ret < 0) {
578 ✗ av_free(str);
579 ✗ return ret;
580 }
581 364 str[str_size] = 0;
582 }
583 423 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
584
4/4
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 115 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 304 times.
423 if (c->itunes_metadata && av_dict_get(*metadata, key, NULL, 0))
585 4 av_dict_set(metadata, key, ";", AV_DICT_APPEND);
586
2/2
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 115 times.
423 av_dict_set(metadata, key, str, c->itunes_metadata ? AV_DICT_APPEND : 0);
587
4/4
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 319 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 67 times.
423 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 140 times.
✓ Branch 1 taken 283 times.
423 if (!strcmp(key, "encoder")) {
592 int major, minor, micro;
593
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 139 times.
140 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 423 atom.size -= str_size;
599 423 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 308 times.
✓ Branch 1 taken 115 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 308 times.
423 if (c->itunes_metadata && atom.size > 8)
608 ✗ goto retry;
609 }
610
611 497 av_freep(&str);
612 497 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 729 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 729 times.
729 if (c->fc->nb_streams < 1)
661 ✗ return 0;
662 729 st = c->fc->streams[c->fc->nb_streams-1];
663 729 sc = st->priv_data;
664
665 729 avio_rb32(pb); // version + flags
666 729 entries = avio_rb32(pb);
667
1/2
✓ Branch 0 taken 729 times.
✗ Branch 1 not taken.
729 if (!entries ||
668
1/2
✓ Branch 0 taken 729 times.
✗ Branch 1 not taken.
729 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 entries >= UINT_MAX / sizeof(*sc->drefs))
670 ✗ return AVERROR_INVALIDDATA;
671
672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 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 729 av_free(sc->drefs);
678 729 sc->drefs_count = 0;
679 729 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 if (!sc->drefs)
681 ✗ return AVERROR(ENOMEM);
682 729 sc->drefs_count = entries;
683
684
2/2
✓ Branch 0 taken 729 times.
✓ Branch 1 taken 729 times.
1458 for (i = 0; i < entries; i++) {
685 729 MOVDref *dref = &sc->drefs[i];
686 729 uint32_t size = avio_rb32(pb);
687 729 int64_t next = avio_tell(pb);
688
689
3/6
✓ Branch 0 taken 729 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 729 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 729 times.
729 if (size < 12 || next < 0 || next > INT64_MAX - size)
690 ✗ return AVERROR_INVALIDDATA;
691
692 729 next += size - 4;
693
694 729 dref->type = avio_rl32(pb);
695 729 avio_rb32(pb); // version + flags
696
697
3/4
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 577 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 152 times.
729 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 729 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
789 dref->type, size);
790 729 entries--;
791 729 i--;
792 }
793 729 avio_seek(pb, next, SEEK_SET);
794 }
795 729 return 0;
796 }
797
798 1343 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 1343 avio_r8(pb); /* version */
808 1343 avio_rb24(pb); /* flags */
809
810 /* component type */
811 1343 ctype = avio_rl32(pb);
812 1343 type = avio_rl32(pb); /* component subtype */
813
814 1343 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
815 1343 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
816
817
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 1133 times.
1343 if (c->trak_index < 0) { // meta not inside a trak
818
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 196 times.
210 if (type == MKTAG('m','d','t','a')) {
819 14 c->found_hdlr_mdta = 1;
820 }
821 210 return 0;
822 }
823
824 1133 st = c->fc->streams[c->fc->nb_streams-1];
825
826
2/2
✓ Branch 0 taken 373 times.
✓ Branch 1 taken 760 times.
1133 if (type == MKTAG('v','i','d','e'))
827 373 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
828
2/2
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 470 times.
760 else if (type == MKTAG('s','o','u','n'))
829 290 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 else if (type == MKTAG('m','1','a',' '))
831 ✗ st->codecpar->codec_id = AV_CODEC_ID_MP2;
832
2/4
✓ Branch 0 taken 470 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 470 times.
470 else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
833 ✗ st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
834
835 1133 avio_rb32(pb); /* component manufacture */
836 1133 avio_rb32(pb); /* component flags */
837 1133 avio_rb32(pb); /* component flags mask */
838
839 1133 title_size = atom.size - 24;
840
2/2
✓ Branch 0 taken 1127 times.
✓ Branch 1 taken 6 times.
1133 if (title_size > 0) {
841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1127 times.
1127 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
842 ✗ return AVERROR_INVALIDDATA;
843 1127 title_str = av_malloc(title_size + 1); /* Add null terminator */
844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1127 times.
1127 if (!title_str)
845 ✗ return AVERROR(ENOMEM);
846
847 1127 ret = ffio_read_size(pb, title_str, title_size);
848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1127 times.
1127 if (ret < 0) {
849 ✗ av_freep(&title_str);
850 ✗ return ret;
851 }
852 1127 title_str[title_size] = 0;
853
2/2
✓ Branch 0 taken 1063 times.
✓ Branch 1 taken 64 times.
1127 if (title_str[0]) {
854
4/4
✓ Branch 0 taken 778 times.
✓ Branch 1 taken 285 times.
✓ Branch 2 taken 776 times.
✓ Branch 3 taken 2 times.
1063 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 1063 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
857 }
858 1127 av_freep(&title_str);
859 }
860
861 1133 return 0;
862 }
863
864 198 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
865 {
866 198 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 21 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1368 {
1369 AVStream *st;
1370 HEIFItem *item;
1371 AVPacketSideData *sd;
1372 21 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 21 item = get_heif_item(c, c->cur_item_id);
1378 21 st = get_curr_st(c);
1379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!st)
1380 ✗ return 0;
1381
1382 21 width = st->codecpar->width;
1383 21 height = st->codecpar->height;
1384
4/6
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
21 if ((!width || !height) && item) {
1385 6 width = item->width;
1386 6 height = item->height;
1387 }
1388
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
21 if (!width || !height) {
1389 ✗ err = AVERROR_INVALIDDATA;
1390 ✗ goto fail;
1391 }
1392
1393 21 aperture_width.num = avio_rb32(pb);
1394 21 aperture_width.den = avio_rb32(pb);
1395 21 aperture_height.num = avio_rb32(pb);
1396 21 aperture_height.den = avio_rb32(pb);
1397
1398 21 horiz_off.num = avio_rb32(pb);
1399 21 horiz_off.den = avio_rb32(pb);
1400 21 vert_off.num = avio_rb32(pb);
1401 21 vert_off.den = avio_rb32(pb);
1402
1403
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
21 if (aperture_width.num < 0 || aperture_width.den < 0 ||
1404
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
21 aperture_height.num < 0 || aperture_height.den < 0 ||
1405
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
21 horiz_off.den < 0 || vert_off.den < 0) {
1406 ✗ err = AVERROR_INVALIDDATA;
1407 ✗ goto fail;
1408 }
1409
3/4
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
39 if ((av_cmp_q((AVRational) { width, 1 }, aperture_width) < 0) ||
1410 18 (av_cmp_q((AVRational) { height, 1 }, aperture_height) < 0)) {
1411 3 err = AVERROR_INVALIDDATA;
1412 3 goto fail;
1413 }
1414 18 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 18 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1420 18 pc_x = av_add_q(pc_x, horiz_off);
1421 18 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1422 18 pc_y = av_add_q(pc_y, vert_off);
1423
1424 18 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1425 18 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1426 18 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1427 18 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1428
1429 18 left = av_q2d(av_sub_q(pc_x, aperture_width));
1430 18 right = av_q2d(av_add_q(pc_x, aperture_width));
1431 18 top = av_q2d(av_sub_q(pc_y, aperture_height));
1432 18 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1433
1434
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (bottom > (height - 1) ||
1435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 right > (width - 1)) {
1436 ✗ err = AVERROR_INVALIDDATA;
1437 ✗ goto fail;
1438 }
1439
1440 18 bottom = height - 1 - bottom;
1441 18 right = width - 1 - right;
1442
1443
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
18 if (!(left | right | top | bottom))
1444 6 return 0;
1445
1446
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if ((left + right) >= width ||
1447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 (top + bottom) >= height) {
1448 ✗ err = AVERROR_INVALIDDATA;
1449 ✗ goto fail;
1450 }
1451
1452 12 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1453 12 &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 12 times.
12 if (!sd)
1457 ✗ return AVERROR(ENOMEM);
1458
1459 12 AV_WL32A(sd->data, top);
1460 12 AV_WL32A(sd->data + 4, bottom);
1461 12 AV_WL32A(sd->data + 8, left);
1462 12 AV_WL32A(sd->data + 12, right);
1463
1464 15 fail:
1465
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 12 times.
15 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 15 return err;
1473 }
1474
1475 /* This atom overrides any previously set aspect ratio */
1476 106 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1477 {
1478 106 const int num = avio_rb32(pb);
1479 106 const int den = avio_rb32(pb);
1480 AVStream *st;
1481 MOVStreamContext *sc;
1482
1483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
106 if (c->fc->nb_streams < 1)
1484 ✗ return 0;
1485 106 st = c->fc->streams[c->fc->nb_streams-1];
1486 106 sc = st->priv_data;
1487
1488 106 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1489
1490
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 2 times.
106 if (den != 0) {
1491 104 sc->h_spacing = num;
1492 104 sc->v_spacing = den;
1493 }
1494 106 return 0;
1495 }
1496
1497 /* this atom contains actual media data */
1498 1071 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1499 {
1500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1071 times.
1071 if (atom.size == 0) /* wrong one (MP4) */
1501 ✗ return 0;
1502 1071 c->found_mdat=1;
1503 1071 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 553 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 553 uint8_t type[5] = {0};
1654 553 int ret = ffio_read_size(pb, type, 4);
1655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 553 times.
553 if (ret < 0)
1656 ✗ return ret;
1657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 553 times.
553 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 308 times.
✓ Branch 1 taken 245 times.
553 if (strcmp(type, "qt "))
1665 308 c->isom = 1;
1666 553 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1667 553 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1668 553 minor_ver = avio_rb32(pb); /* minor version */
1669 553 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1670
1671 553 comp_brand_size = atom.size - 8;
1672
2/4
✓ Branch 0 taken 553 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 553 times.
553 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1673 ✗ return AVERROR_INVALIDDATA;
1674 553 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 553 times.
553 if (!comp_brands_str)
1676 ✗ return AVERROR(ENOMEM);
1677
1678 553 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 553 times.
553 if (ret < 0) {
1680 ✗ av_freep(&comp_brands_str);
1681 ✗ return ret;
1682 }
1683 553 comp_brands_str[comp_brand_size] = 0;
1684 553 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 553 times.
553 if (!strcmp(type, "aaxc")) {
1689 ✗ mov_aaxc_crypto(c);
1690 }
1691
1692 553 return 0;
1693 }
1694
1695 /* this atom should contain all header atoms */
1696 598 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 598 times.
598 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 598 times.
598 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 598 c->found_moov=1;
1711 598 return 0; /* now go for mdat */
1712 }
1713
1714 3210 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 3210 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3210 times.
3210 if (index < 0 || index >= frag_index->nb_items)
1723 ✗ return NULL;
1724 3210 item = &frag_index->item[index];
1725
1/2
✓ Branch 0 taken 3394 times.
✗ Branch 1 not taken.
3394 for (i = 0; i < item->nb_stream_info; i++)
1726
2/2
✓ Branch 0 taken 3210 times.
✓ Branch 1 taken 184 times.
3394 if (item->stream_info[i].id == id)
1727 3210 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 1324 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 1309 times.
1324 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 1309 time = avio_rb32(pb);
1984 1309 avio_rb32(pb); /* modification time */
1985
4/4
✓ Branch 0 taken 643 times.
✓ Branch 1 taken 666 times.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 581 times.
1309 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 649 times.
✓ Branch 1 taken 675 times.
1324 if (time) {
1991 649 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1992
1993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 649 times.
649 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 649 ff_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1999 }
2000 }
2001
2002 729 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2003 {
2004 AVStream *st;
2005 MOVStreamContext *sc;
2006 int version;
2007 729 char language[4] = {0};
2008 unsigned lang;
2009
2010
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 if (c->fc->nb_streams < 1)
2011 ✗ return 0;
2012 729 st = c->fc->streams[c->fc->nb_streams-1];
2013 729 sc = st->priv_data;
2014
2015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 if (sc->time_scale) {
2016 ✗ av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
2017 ✗ return AVERROR_INVALIDDATA;
2018 }
2019
2020 729 version = avio_r8(pb);
2021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 if (version > 1) {
2022 ✗ avpriv_request_sample(c->fc, "Version %d", version);
2023 ✗ return AVERROR_PATCHWELCOME;
2024 }
2025 729 avio_rb24(pb); /* flags */
2026 729 mov_metadata_creation_time(c, pb, &st->metadata, version);
2027
2028 729 sc->time_scale = avio_rb32(pb);
2029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 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 716 times.
729 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
2034
2035
6/6
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 716 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 716 times.
✓ Branch 5 taken 4 times.
729 if ((version == 1 && st->duration == UINT64_MAX) ||
2036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 716 times.
716 (version != 1 && st->duration == UINT32_MAX)) {
2037 9 st->duration = 0;
2038 }
2039
2040 729 lang = avio_rb16(pb); /* language */
2041
2/2
✓ Branch 1 taken 555 times.
✓ Branch 2 taken 174 times.
729 if (ff_mov_lang_to_iso639(lang, language))
2042 555 av_dict_set(&st->metadata, "language", language, 0);
2043 729 avio_rb16(pb); /* quality */
2044
2045 729 return 0;
2046 }
2047
2048 595 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2049 {
2050 int i;
2051 595 int version = avio_r8(pb); /* version */
2052 595 avio_rb24(pb); /* flags */
2053
2054 595 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
2055 595 c->time_scale = avio_rb32(pb); /* time scale */
2056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 595 times.
595 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 595 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 593 times.
595 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
2063 595 avio_rb32(pb); /* preferred scale */
2064
2065 595 avio_rb16(pb); /* preferred volume */
2066
2067 595 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 1785 times.
✓ Branch 1 taken 595 times.
2380 for (i = 0; i < 3; i++) {
2071 1785 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
2072 1785 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
2073 1785 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
2074 }
2075
2076 595 avio_rb32(pb); /* preview time */
2077 595 avio_rb32(pb); /* preview duration */
2078 595 avio_rb32(pb); /* poster time */
2079 595 avio_rb32(pb); /* selection time */
2080 595 avio_rb32(pb); /* selection duration */
2081 595 avio_rb32(pb); /* current time */
2082 595 avio_rb32(pb); /* next track ID */
2083
2084 595 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 58 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2203 {
2204 AVStream *st;
2205 58 HEIFItem *item = NULL;
2206 58 char color_parameter_type[5] = { 0 };
2207 uint16_t color_primaries, color_trc, color_matrix;
2208 int ret;
2209
2210 58 st = get_curr_st(c);
2211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!st) {
2212 ✗ item = get_heif_item(c, c->cur_item_id);
2213 ✗ if (!item)
2214 ✗ return 0;
2215 }
2216
2217 58 ret = ffio_read_size(pb, color_parameter_type, 4);
2218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (ret < 0)
2219 ✗ return ret;
2220
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 22 times.
58 if (strncmp(color_parameter_type, "nclx", 4) &&
2221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 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 58 times.
58 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 58 times.
✗ Branch 1 not taken.
58 } else if (st) {
2259 58 color_primaries = avio_rb16(pb);
2260 58 color_trc = avio_rb16(pb);
2261 58 color_matrix = avio_rb16(pb);
2262
2263 58 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 36 times.
58 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 58 times.
58 if (!av_color_primaries_name(color_primaries))
2277 ✗ color_primaries = AVCOL_PRI_UNSPECIFIED;
2278
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if (!av_color_transfer_name(color_trc))
2279 ✗ color_trc = AVCOL_TRC_UNSPECIFIED;
2280
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if (!av_color_space_name(color_matrix))
2281 ✗ color_matrix = AVCOL_SPC_UNSPECIFIED;
2282
2283 58 st->codecpar->color_primaries = color_primaries;
2284 58 st->codecpar->color_trc = color_trc;
2285 58 st->codecpar->color_space = color_matrix;
2286 58 av_log(c->fc, AV_LOG_TRACE, "\n");
2287 }
2288 58 return 0;
2289 }
2290
2291 122 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2292 {
2293 AVStream *st;
2294 unsigned mov_field_order;
2295 122 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2296
2297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 122 times.
122 if (c->fc->nb_streams < 1) // will happen with jp2 files
2298 ✗ return 0;
2299 122 st = c->fc->streams[c->fc->nb_streams-1];
2300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 122 times.
122 if (atom.size < 2)
2301 ✗ return AVERROR_INVALIDDATA;
2302 122 mov_field_order = avio_rb16(pb);
2303
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 25 times.
122 if ((mov_field_order & 0xFF00) == 0x0100)
2304 97 decoded_field_order = AV_FIELD_PROGRESSIVE;
2305
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 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 23 times.
✗ Branch 4 not taken.
25 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 23 case 0x0E: decoded_field_order = AV_FIELD_BT;
2314 23 break;
2315 }
2316 }
2317
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 122 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
122 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 122 st->codecpar->field_order = decoded_field_order;
2321
2322 122 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 200 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2581 {
2582 AVStream *st;
2583 int ret;
2584
2585 200 st = get_curr_st(c);
2586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 if (!st)
2587 ✗ return 0;
2588
2589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 if ((uint64_t)atom.size > (1<<30))
2590 ✗ return AVERROR_INVALIDDATA;
2591
2592
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 199 times.
200 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 196 times.
✓ Branch 1 taken 4 times.
200 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 196 unsigned size = avio_rb32(pb);
2601 196 unsigned type = avio_rl32(pb);
2602
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 196 times.
196 if (avio_feof(pb))
2603 ✗ return AVERROR_INVALIDDATA;
2604 196 avio_seek(pb, -8, SEEK_CUR);
2605
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 186 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
196 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 190 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
190 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 190 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
190 if (ret < 0)
2614 ✗ return ret;
2615
3/4
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 117 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 73 times.
190 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 190 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 70 static int mov_find_tref_id(const MovTref *tag, uint32_t id)
2652 {
2653
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 42 times.
100 for (int i = 0; i < tag->nb_id; i++) {
2654
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 30 times.
58 if (tag->id[i] == id)
2655 28 return 1;
2656 }
2657 42 return 0;
2658 }
2659
2660 42 static int mov_add_tref_id(MovTref *tag, uint32_t id)
2661 {
2662 42 int ret = mov_find_tref_id(tag, id);
2663
2664
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 if (!ret) {
2665 42 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 42 times.
42 if (!tmp)
2667 ✗ return AVERROR(ENOMEM);
2668 42 tag->id = tmp;
2669 42 tag->id[tag->nb_id++] = id;
2670 }
2671
2672 42 return 0;
2673 }
2674
2675 1550 static MovTref *mov_find_tref_tag(const MOVStreamContext *sc, uint32_t name)
2676 {
2677
2/2
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 1482 times.
1667 for (int i = 0; i < sc->nb_tref_tags; i++) {
2678 185 MovTref *entry = &sc->tref_tags[i];
2679
2680
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 117 times.
185 if (entry->name == name)
2681 68 return entry;
2682 }
2683 1482 return NULL;
2684 }
2685
2686 32 static MovTref *mov_add_tref_tag(MOVStreamContext *sc, uint32_t name)
2687 {
2688 32 MovTref *tag = mov_find_tref_tag(sc, name);
2689
2690
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (!tag) {
2691 32 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 32 times.
32 if (!tmp)
2694 ✗ return NULL;
2695 32 sc->tref_tags = tmp;
2696 32 tag = &sc->tref_tags[sc->nb_tref_tags++];
2697 32 *tag = (MovTref){ .name = name };
2698 }
2699
2700 32 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 729 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 729 times.
729 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 729 times.
729 if (c->fc->nb_streams < 1)
2831 ✗ return 0;
2832 729 st = c->fc->streams[c->fc->nb_streams-1];
2833 729 sc = st->priv_data;
2834
2835 729 avio_r8(pb); /* version */
2836 729 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 729 entries = avio_rb32(pb);
2841 729 entries =
2842
2/2
✓ Branch 0 taken 724 times.
✓ Branch 1 taken 5 times.
729 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 699 times.
729 if (!entries)
2847 30 return 0;
2848
2849
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 699 times.
699 if (sc->chunk_offsets) {
2850 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2851 ✗ return 0;
2852 }
2853
2854 699 av_free(sc->chunk_offsets);
2855 699 sc->chunk_count = 0;
2856 699 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 699 times.
699 if (!sc->chunk_offsets)
2858 ✗ return AVERROR(ENOMEM);
2859 699 sc->chunk_count = entries;
2860
2861
2/2
✓ Branch 0 taken 695 times.
✓ Branch 1 taken 4 times.
699 if (atom.type == MKTAG('s','t','c','o'))
2862
3/4
✓ Branch 0 taken 43951 times.
✓ Branch 1 taken 695 times.
✓ Branch 2 taken 43951 times.
✗ Branch 3 not taken.
44646 for (i = 0; i < entries && !pb->eof_reached; i++)
2863 43951 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 699 sc->chunk_count = i;
2876
2877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 699 times.
699 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 699 return 0;
2883 }
2884
2885 799 static int mov_codec_id(AVStream *st, uint32_t format)
2886 {
2887 799 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2888
2889
2/2
✓ Branch 0 taken 532 times.
✓ Branch 1 taken 267 times.
799 if (id <= 0 &&
2890
2/2
✓ Branch 0 taken 529 times.
✓ Branch 1 taken 3 times.
532 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 529 times.
529 (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 357 times.
✓ Branch 1 taken 442 times.
✓ Branch 2 taken 270 times.
✓ Branch 3 taken 87 times.
799 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2895 270 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2896
3/4
✓ Branch 0 taken 509 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 509 times.
✗ Branch 3 not taken.
529 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2897 /* skip old ASF MPEG-4 tag */
2898
2/2
✓ Branch 0 taken 505 times.
✓ Branch 1 taken 4 times.
509 format && format != MKTAG('m','p','4','s')) {
2899 505 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2900
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 427 times.
505 if (id <= 0)
2901 78 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2902
2/2
✓ Branch 0 taken 431 times.
✓ Branch 1 taken 74 times.
505 if (id > 0)
2903 431 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2904
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 62 times.
74 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 62 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2908
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 6 times.
62 if (id <= 0) {
2909
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 4 times.
108 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2910
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 4 times.
108 AV_CODEC_ID_TTML : id;
2911 }
2912
2913
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 48 times.
62 if (id > 0)
2914 14 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2915 else
2916 48 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2917 }
2918 }
2919
2920 799 st->codecpar->codec_tag = format;
2921
2922 799 return id;
2923 }
2924
2925 388 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2926 AVStream *st, MOVStreamContext *sc)
2927 {
2928 388 uint8_t codec_name[32] = { 0 };
2929 int64_t stsd_start;
2930 unsigned int len;
2931 388 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 388 stsd_start = avio_tell(pb) - 16;
2936
2937
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 261 times.
388 if (c->isom) {
2938 127 avio_skip(pb, 2); /* pre_defined */
2939 127 avio_skip(pb, 2); /* reserved */
2940 127 avio_skip(pb, 12); /* pre_defined */
2941 } else {
2942 261 avio_rb16(pb); /* version */
2943 261 avio_rb16(pb); /* revision level */
2944 261 id = avio_rl32(pb); /* vendor */
2945 261 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2946 261 avio_rb32(pb); /* temporal quality */
2947 261 avio_rb32(pb); /* spatial quality */
2948 }
2949
2950 388 st->codecpar->width = avio_rb16(pb); /* width */
2951 388 st->codecpar->height = avio_rb16(pb); /* height */
2952
2953 388 avio_rb32(pb); /* horiz resolution */
2954 388 avio_rb32(pb); /* vert resolution */
2955 388 avio_rb32(pb); /* data size, always 0 */
2956 388 avio_rb16(pb); /* frames per samples */
2957
2958 388 len = avio_r8(pb); /* codec name, pascal string */
2959
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 387 times.
388 if (len > 31)
2960 1 len = 31;
2961 388 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2962
2/2
✓ Branch 0 taken 385 times.
✓ Branch 1 taken 3 times.
388 if (len < 31)
2963 385 avio_skip(pb, 31 - len);
2964
2965
2/2
✓ Branch 0 taken 295 times.
✓ Branch 1 taken 93 times.
388 if (codec_name[0])
2966 295 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 388 times.
388 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 388 times.
388 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 388 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2980
2981 388 avio_seek(pb, stsd_start, SEEK_SET);
2982
2983
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 370 times.
388 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 388 }
2988
2989 290 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2990 AVStream *st, MOVStreamContext *sc)
2991 {
2992 int bits_per_sample, flags;
2993 290 uint16_t version = avio_rb16(pb);
2994 290 uint32_t id = 0;
2995 290 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 200 times.
✓ Branch 1 taken 90 times.
290 if (c->isom)
2999 200 avio_skip(pb, 6); /* reserved */
3000 else {
3001 90 avio_rb16(pb); /* revision level */
3002 90 id = avio_rl32(pb); /* vendor */
3003 90 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
3004 }
3005
3006 290 channel_count = avio_rb16(pb);
3007
3008 290 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3009 290 st->codecpar->ch_layout.nb_channels = channel_count;
3010 290 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
3011 290 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
3012
3013 290 sc->audio_cid = avio_rb16(pb);
3014 290 avio_rb16(pb); /* packet size = 0 */
3015
3016 290 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
3017
3018 // Read QT version 1 fields. In version 0 these do not exist.
3019 290 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
3020
3/4
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 200 times.
✗ Branch 3 not taken.
290 if (!c->isom ||
3021
1/2
✓ Branch 0 taken 200 times.
✗ Branch 1 not taken.
200 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
3022
4/4
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 191 times.
200 (sc->stsd_version == 0 && version > 0)) {
3023
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 42 times.
94 if (version == 1) {
3024 52 sc->samples_per_frame = avio_rb32(pb);
3025 52 avio_rb32(pb); /* bytes per packet */
3026 52 sc->bytes_per_frame = avio_rb32(pb);
3027 52 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 56 times.
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 25 times.
94 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 65 times.
65 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 290 times.
290 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 24 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 243 times.
290 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 24 case AV_CODEC_ID_PCM_S16LE:
3070 case AV_CODEC_ID_PCM_S16BE:
3071
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 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 22 times.
22 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 22 times.
22 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 24 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 243 default:
3100 243 break;
3101 }
3102
3103 290 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
3104
3/4
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 237 times.
✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
290 if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->ch_layout.nb_channels <= INT_MAX) {
3105 53 st->codecpar->bits_per_coded_sample = bits_per_sample;
3106 53 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
3107 }
3108 290 }
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 52 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 28 times.
✓ Branch 1 taken 24 times.
52 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
3133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if ((int)size != size)
3134 ✗ return AVERROR(ENOMEM);
3135
3136 28 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
3137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
3138 ✗ return ret;
3139
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (size > 16) {
3140 28 MOVStreamContext *tmcd_ctx = st->priv_data;
3141 int val;
3142 28 val = AV_RB32(st->codecpar->extradata + 4);
3143 28 tmcd_ctx->tmcd_flags = val;
3144 28 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
3145 28 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
3146 28 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
3147
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 18 times.
28 if (size > 30) {
3148 10 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
3149 10 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
3150
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 if (format == AV_RB32("name") && (int64_t)size >= (int64_t)len + 18) {
3151 10 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
3152
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 if (str_size > 0 && size >= (int)str_size + 30 &&
3153
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 st->codecpar->extradata[30] /* Don't add empty string */) {
3154 10 char *reel_name = av_malloc(str_size + 1);
3155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!reel_name)
3156 ✗ return AVERROR(ENOMEM);
3157 10 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
3158 10 reel_name[str_size] = 0; /* Add null terminator */
3159 10 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 52 return 0;
3197 }
3198
3199 729 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
3200 AVStream *st, MOVStreamContext *sc)
3201 {
3202 729 FFStream *const sti = ffstream(st);
3203
3204
2/2
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 439 times.
729 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
3205
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 290 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
290 !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 552 times.
729 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 552 default:
3298 552 break;
3299 }
3300 729 return 0;
3301 }
3302
3303 746 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 729 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 16 times.
746 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 745 return 0;
3327 }
3328
3329 745 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 655 times.
745 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 655 default:
3344 655 break;
3345 }
3346
3347 745 return 0;
3348 }
3349
3350 729 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 729 times.
729 av_assert0 (c->fc->nb_streams >= 1);
3357 729 st = c->fc->streams[c->fc->nb_streams-1];
3358 729 sc = st->priv_data;
3359
3360 729 for (pseudo_stream_id = 0;
3361
3/4
✓ Branch 0 taken 746 times.
✓ Branch 1 taken 729 times.
✓ Branch 2 taken 746 times.
✗ Branch 3 not taken.
1475 pseudo_stream_id < entries && !pb->eof_reached;
3362 746 pseudo_stream_id++) {
3363 //Parsing Sample description table
3364 enum AVCodecID id;
3365 746 int ret, dref_id = 1;
3366 746 MOVAtom a = { AV_RL32("stsd") };
3367 746 int64_t start_pos = avio_tell(pb);
3368 746 int64_t size = avio_rb32(pb); /* size */
3369 746 uint32_t format = avio_rl32(pb); /* data format */
3370
3371
1/2
✓ Branch 0 taken 746 times.
✗ Branch 1 not taken.
746 if (size >= 16) {
3372 746 avio_rb32(pb); /* reserved */
3373 746 avio_rb16(pb); /* reserved */
3374 746 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 745 times.
746 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3382 746 size - (avio_tell(pb) - start_pos))) {
3383 1 sc->stsd_count++;
3384 1 continue;
3385 }
3386
3387
2/2
✓ Branch 0 taken 729 times.
✓ Branch 1 taken 16 times.
745 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
3388 745 sc->dref_id= dref_id;
3389 745 sc->format = format;
3390
3391 745 id = mov_codec_id(st, format);
3392
3393 745 av_log(c->fc, AV_LOG_TRACE,
3394 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3395 745 av_fourcc2str(format), st->codecpar->codec_type);
3396
3397 745 st->codecpar->codec_id = id;
3398
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 357 times.
745 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3399 388 mov_parse_stsd_video(c, pb, st, sc);
3400
2/2
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 67 times.
357 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3401 290 mov_parse_stsd_audio(c, pb, st, sc);
3402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 290 times.
290 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 290 times.
290 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 52 times.
67 } 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 52 ret = mov_parse_stsd_data(c, pb, st, sc,
3415 52 size - (avio_tell(pb) - start_pos));
3416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (ret < 0)
3417 ✗ return ret;
3418 }
3419 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3420 745 a.size = size - (avio_tell(pb) - start_pos);
3421
2/2
✓ Branch 0 taken 577 times.
✓ Branch 1 taken 168 times.
745 if (a.size > 8) {
3422
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 577 times.
577 if ((ret = mov_read_default(c, pb, a)) < 0)
3423 ✗ return ret;
3424
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 167 times.
168 } else if (a.size > 0)
3425 1 avio_skip(pb, a.size);
3426
3427 745 ret = mov_finalize_stsd_entry(c, st);
3428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 745 times.
745 if (ret < 0)
3429 ✗ return ret;
3430
3431
3/4
✓ Branch 0 taken 745 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 439 times.
✓ Branch 3 taken 306 times.
745 if (sc->extradata && st->codecpar->extradata) {
3432 439 int extra_size = st->codecpar->extradata_size;
3433
3434 /* Move the current stream extradata to the stream context one. */
3435 439 sc->extradata_size[pseudo_stream_id] = extra_size;
3436 439 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3437 439 st->codecpar->extradata = NULL;
3438 439 st->codecpar->extradata_size = 0;
3439 }
3440 745 sc->stsd_count++;
3441 }
3442
3443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 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 729 return 0;
3449 }
3450
3451 729 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 729 times.
729 if (c->fc->nb_streams < 1)
3458 ✗ return 0;
3459 729 st = c->fc->streams[c->fc->nb_streams - 1];
3460 729 sc = st->priv_data;
3461
3462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 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 729 sc->stsd_version = avio_r8(pb);
3469 729 avio_rb24(pb); /* flags */
3470 729 entries = avio_rb32(pb);
3471
3472 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3473
3/6
✓ Branch 0 taken 729 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 729 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 729 times.
729 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 729 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 if (!sc->extradata)
3481 ✗ return AVERROR(ENOMEM);
3482
3483 729 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 if (!sc->extradata_size) {
3485 ✗ ret = AVERROR(ENOMEM);
3486 ✗ goto fail;
3487 }
3488
3489 729 ret = ff_mov_read_stsd_entries(c, pb, entries);
3490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 if (ret < 0)
3491 ✗ goto fail;
3492
3493 /* Restore back the primary extradata. */
3494 729 av_freep(&st->codecpar->extradata);
3495 729 st->codecpar->extradata_size = sc->extradata_size[0];
3496
2/2
✓ Branch 0 taken 424 times.
✓ Branch 1 taken 305 times.
729 if (sc->extradata_size[0]) {
3497 424 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 424 times.
424 if (!st->codecpar->extradata)
3499 ✗ return AVERROR(ENOMEM);
3500 424 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3501 }
3502
3503 729 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 729 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 729 times.
729 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 729 times.
729 if (c->fc->nb_streams < 1)
3529 ✗ return 0;
3530 729 st = c->fc->streams[c->fc->nb_streams-1];
3531 729 sc = st->priv_data;
3532
3533 729 avio_r8(pb); /* version */
3534 729 avio_rb24(pb); /* flags */
3535
3536 729 entries = avio_rb32(pb);
3537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 if ((uint64_t)entries * 12 + 4 > atom.size)
3538 ✗ return AVERROR_INVALIDDATA;
3539
3540 729 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 700 times.
729 if (!entries)
3543 29 return 0;
3544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 700 times.
700 if (sc->stsc_data) {
3545 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3546 ✗ return 0;
3547 }
3548 700 av_free(sc->stsc_data);
3549 700 sc->stsc_count = 0;
3550 700 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 700 times.
700 if (!sc->stsc_data)
3552 ✗ return AVERROR(ENOMEM);
3553
3554
3/4
✓ Branch 0 taken 3927 times.
✓ Branch 1 taken 700 times.
✓ Branch 2 taken 3927 times.
✗ Branch 3 not taken.
4627 for (i = 0; i < entries && !pb->eof_reached; i++) {
3555 3927 sc->stsc_data[i].first = avio_rb32(pb);
3556 3927 sc->stsc_data[i].count = avio_rb32(pb);
3557 3927 sc->stsc_data[i].id = avio_rb32(pb);
3558 }
3559
3560 700 sc->stsc_count = i;
3561
2/2
✓ Branch 0 taken 3927 times.
✓ Branch 1 taken 700 times.
4627 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3562 3927 int64_t first_min = i + 1;
3563
5/6
✓ Branch 0 taken 3227 times.
✓ Branch 1 taken 700 times.
✓ Branch 2 taken 3227 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3227 times.
✓ Branch 5 taken 700 times.
3927 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 3927 times.
✗ Branch 1 not taken.
3927 sc->stsc_data[i].first < first_min ||
3566
1/2
✓ Branch 0 taken 3927 times.
✗ Branch 1 not taken.
3927 sc->stsc_data[i].count < 1 ||
3567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3927 times.
3927 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 700 times.
700 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 700 return 0;
3595 }
3596
3597 354710 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3598 {
3599 354710 return index < count - 1;
3600 }
3601
3602 /* Compute the samples value for the stsc entry at the given index. */
3603 57202 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 57004 times.
✓ Branch 2 taken 198 times.
57202 if (mov_stsc_index_valid(index, sc->stsc_count))
3608 57004 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 57202 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 182 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 182 times.
182 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 182 times.
182 if (c->fc->nb_streams < 1)
3672 ✗ return 0;
3673 182 st = c->fc->streams[c->fc->nb_streams-1];
3674 182 sti = ffstream(st);
3675 182 sc = st->priv_data;
3676
3677 182 avio_r8(pb); /* version */
3678 182 avio_rb24(pb); /* flags */
3679
3680 182 entries = avio_rb32(pb);
3681
3682 182 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3683
3684
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 168 times.
182 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 168 times.
168 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 168 times.
168 if (entries >= UINT_MAX / sizeof(int))
3693 ✗ return AVERROR_INVALIDDATA;
3694 168 av_freep(&sc->keyframes);
3695 168 sc->keyframe_count = 0;
3696 168 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
168 if (!sc->keyframes)
3698 ✗ return AVERROR(ENOMEM);
3699
3700
3/4
✓ Branch 0 taken 5768 times.
✓ Branch 1 taken 168 times.
✓ Branch 2 taken 5768 times.
✗ Branch 3 not taken.
5936 for (i = 0; i < entries && !pb->eof_reached; i++) {
3701 5768 sc->keyframes[i] = avio_rb32(pb);
3702 }
3703
3704 168 sc->keyframe_count = i;
3705
3706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
168 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 168 return 0;
3712 }
3713
3714 729 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 729 times.
729 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 729 times.
729 if (c->fc->nb_streams < 1)
3729 ✗ return 0;
3730 729 st = c->fc->streams[c->fc->nb_streams-1];
3731 729 sc = st->priv_data;
3732
3733 729 avio_r8(pb); /* version */
3734 729 avio_rb24(pb); /* flags */
3735
3736
1/2
✓ Branch 0 taken 729 times.
✗ Branch 1 not taken.
729 if (atom.type == MKTAG('s','t','s','z')) {
3737 729 sample_size = avio_rb32(pb);
3738
2/2
✓ Branch 0 taken 683 times.
✓ Branch 1 taken 46 times.
729 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3739 683 sc->sample_size = sample_size;
3740 729 sc->stsz_sample_size = sample_size;
3741 729 field_size = 32;
3742 } else {
3743 ✗ sample_size = 0;
3744 ✗ avio_rb24(pb); /* reserved */
3745 ✗ field_size = avio_r8(pb);
3746 }
3747 729 entries = avio_rb32(pb);
3748
3749 729 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3750
3751 729 sc->sample_count = entries;
3752
2/2
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 495 times.
729 if (sample_size)
3753 234 return 0;
3754
3755
4/8
✓ Branch 0 taken 495 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 495 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 495 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 495 times.
495 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 465 times.
495 if (!entries)
3761 30 return 0;
3762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 465 times.
465 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 465 times.
465 if (sc->sample_sizes)
3765 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3766 465 av_free(sc->sample_sizes);
3767 465 sc->sample_count = 0;
3768 465 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 465 times.
465 if (!sc->sample_sizes)
3770 ✗ return AVERROR(ENOMEM);
3771
3772 465 num_bytes = (entries*field_size+4)>>3;
3773
3774 465 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 465 times.
465 if (!buf) {
3776 ✗ av_freep(&sc->sample_sizes);
3777 ✗ return AVERROR(ENOMEM);
3778 }
3779
3780 465 ret = ffio_read_size(pb, buf, num_bytes);
3781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 465 times.
465 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 465 init_get_bits(&gb, buf, 8*num_bytes);
3789
3790
2/2
✓ Branch 0 taken 239932 times.
✓ Branch 1 taken 465 times.
240397 for (i = 0; i < entries; i++) {
3791 239932 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 239932 times.
239932 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 239932 sc->data_size += sc->sample_sizes[i];
3798 }
3799
3800 465 sc->sample_count = i;
3801
3802 465 av_free(buf);
3803
3804 465 return 0;
3805 }
3806
3807 729 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3808 {
3809 AVStream *st;
3810 MOVStreamContext *sc;
3811 unsigned int i, entries;
3812 729 int64_t duration = 0;
3813 729 int64_t total_sample_count = 0;
3814 729 int64_t current_dts = 0;
3815 729 int64_t corrected_dts = 0;
3816
3817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 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 729 times.
729 if (c->fc->nb_streams < 1)
3823 ✗ return 0;
3824 729 st = c->fc->streams[c->fc->nb_streams-1];
3825 729 sc = st->priv_data;
3826
3827 729 avio_r8(pb); /* version */
3828 729 avio_rb24(pb); /* flags */
3829 729 entries = avio_rb32(pb);
3830
3831 729 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3832 729 c->fc->nb_streams-1, entries);
3833
3834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 if (sc->stts_data)
3835 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3836 729 av_freep(&sc->stts_data);
3837 729 sc->stts_count = 0;
3838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3839 ✗ return AVERROR(ENOMEM);
3840
3841
3/4
✓ Branch 0 taken 3122 times.
✓ Branch 1 taken 729 times.
✓ Branch 2 taken 3122 times.
✗ Branch 3 not taken.
3851 for (i = 0; i < entries && !pb->eof_reached; i++) {
3842 unsigned int sample_duration;
3843 unsigned int sample_count;
3844 3122 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3845 3122 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 3122 times.
3122 if (!stts_data) {
3848 ✗ av_freep(&sc->stts_data);
3849 ✗ sc->stts_count = 0;
3850 ✗ return AVERROR(ENOMEM);
3851 }
3852 3122 sc->stts_count = min_entries;
3853 3122 sc->stts_data = stts_data;
3854
3855 3122 sample_count = avio_rb32(pb);
3856 3122 sample_duration = avio_rb32(pb);
3857
3858 3122 sc->stts_data[i].count= sample_count;
3859 3122 sc->stts_data[i].duration= sample_duration;
3860
3861 3122 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 3121 times.
3122 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 3121 corrected_dts += sample_duration * (uint64_t)sample_count;
3876 }
3877
3878 3122 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3879
3880
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 3100 times.
3122 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 3122 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3888 3122 total_sample_count+=sc->stts_data[i].count;
3889 }
3890
3891 729 sc->stts_count = i;
3892
3893
2/2
✓ Branch 0 taken 699 times.
✓ Branch 1 taken 30 times.
729 if (duration > 0 &&
3894
1/2
✓ Branch 0 taken 699 times.
✗ Branch 1 not taken.
699 duration <= INT64_MAX - sc->duration_for_fps &&
3895
1/2
✓ Branch 0 taken 699 times.
✗ Branch 1 not taken.
699 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3896 699 sc->duration_for_fps += duration;
3897 699 sc->nb_frames_for_fps += total_sample_count;
3898 }
3899
3900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 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 729 st->nb_frames= total_sample_count;
3906
2/2
✓ Branch 0 taken 699 times.
✓ Branch 1 taken 30 times.
729 if (duration)
3907 699 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 699 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
729 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 729 sc->track_end = duration;
3924 729 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 13827 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3966 {
3967
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 12691 times.
13827 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 13827 }
3975
3976 83 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3977 {
3978 AVStream *st;
3979 MOVStreamContext *sc;
3980 83 unsigned int i, entries, ctts_count = 0;
3981
3982
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 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 83 times.
83 if (c->fc->nb_streams < 1)
3988 ✗ return 0;
3989 83 st = c->fc->streams[c->fc->nb_streams-1];
3990 83 sc = st->priv_data;
3991
3992 83 avio_r8(pb); /* version */
3993 83 avio_rb24(pb); /* flags */
3994 83 entries = avio_rb32(pb);
3995
3996 83 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 79 times.
83 if (!entries)
3999 4 return 0;
4000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
4001 ✗ return AVERROR_INVALIDDATA;
4002 79 av_freep(&sc->ctts_data);
4003 79 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 79 times.
79 if (!sc->ctts_data)
4005 ✗ return AVERROR(ENOMEM);
4006
4007
3/4
✓ Branch 0 taken 5256 times.
✓ Branch 1 taken 79 times.
✓ Branch 2 taken 5256 times.
✗ Branch 3 not taken.
5335 for (i = 0; i < entries && !pb->eof_reached; i++) {
4008 MOVCtts *ctts_data;
4009 5256 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
4010 5256 const size_t requested_size =
4011 5256 min_size_needed > sc->ctts_allocated_size ?
4012
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5256 times.
5256 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
4013 min_size_needed;
4014 5256 int count = avio_rb32(pb);
4015 5256 int duration = avio_rb32(pb);
4016
4017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5256 times.
5256 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 5256 times.
5256 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
4025 ✗ return AVERROR(ENOMEM);
4026
4027 5256 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 5256 times.
5256 if (!ctts_data)
4030 ✗ return AVERROR(ENOMEM);
4031
4032 5256 sc->ctts_data = ctts_data;
4033
4034 5256 ctts_data[ctts_count].count = count;
4035 5256 ctts_data[ctts_count].offset = duration;
4036 5256 ctts_count++;
4037
4038 5256 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
4039 count, duration);
4040
4041
2/2
✓ Branch 0 taken 5110 times.
✓ Branch 1 taken 146 times.
5256 if (i+2<entries)
4042 5110 mov_update_dts_shift(sc, duration, c->fc);
4043 }
4044
4045 79 sc->ctts_count = ctts_count;
4046
4047
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 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 79 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
4053
4054 79 return 0;
4055 }
4056
4057 52 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 52 times.
52 if (c->fc->nb_streams < 1)
4068 ✗ return 0;
4069 52 st = c->fc->streams[c->fc->nb_streams - 1];
4070 52 sc = st->priv_data;
4071
4072 52 version = avio_r8(pb); /* version */
4073 52 avio_rb24(pb); /* flags */
4074 52 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 47 times.
✓ Branch 1 taken 5 times.
52 if (grouping_type != MKTAG('s','y','n','c'))
4081 47 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 48 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 48 times.
48 if (c->fc->nb_streams < 1)
4127 ✗ return 0;
4128 48 st = c->fc->streams[c->fc->nb_streams-1];
4129 48 sc = st->priv_data;
4130
4131 48 version = avio_r8(pb); /* version */
4132 48 avio_rb24(pb); /* flags */
4133 48 grouping_type = avio_rl32(pb);
4134
4135
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 47 times.
48 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 42 times.
47 } 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 42 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 1111 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 541 times.
✓ Branch 1 taken 570 times.
1111 if (edit_list_index == msc->elst_count) {
4185 541 return 0;
4186 }
4187 570 *edit_list_media_time = msc->elst_data[edit_list_index].time;
4188 570 *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 570 times.
570 if (global_timescale == 0) {
4192 ✗ avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
4193 ✗ return 0;
4194 }
4195 570 *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 570 times.
570 if (*edit_list_duration + (uint64_t)*edit_list_media_time > INT64_MAX)
4199 ✗ *edit_list_duration = 0;
4200
4201 570 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 570 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 570 MOVStreamContext *msc = st->priv_data;
4235 570 FFStream *const sti = ffstream(st);
4236 570 AVIndexEntry *e_keep = sti->index_entries;
4237 570 int nb_keep = sti->nb_index_entries;
4238 570 int64_t i = 0;
4239
4240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 570 times.
570 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 561 times.
570 if (msc->dts_shift > 0) {
4246 9 timestamp_pts -= msc->dts_shift;
4247 }
4248
4249 570 sti->index_entries = e_old;
4250 570 sti->nb_index_entries = nb_old;
4251 570 *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 569 times.
✓ Branch 1 taken 1 times.
570 if (*index >= 0) {
4255
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 541 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
569 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 87 times.
✓ Branch 1 taken 483 times.
✓ Branch 2 taken 86 times.
✓ Branch 3 taken 1 times.
570 if (msc->ctts_count && *index >= 0) {
4267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
86 av_assert0(tts_index);
4268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
86 av_assert0(tts_sample);
4269 // Find out the ctts_index for the found frame.
4270 86 *tts_index = 0;
4271 86 *tts_sample = 0;
4272
2/2
✓ Branch 0 taken 215 times.
✓ Branch 1 taken 86 times.
301 for (int64_t index_tts_count = 0; index_tts_count < *index; index_tts_count++) {
4273
1/2
✓ Branch 0 taken 215 times.
✗ Branch 1 not taken.
215 if (*tts_index < tts_count) {
4274 215 (*tts_sample)++;
4275
1/2
✓ Branch 0 taken 215 times.
✗ Branch 1 not taken.
215 if (tts_data[*tts_index].count == *tts_sample) {
4276 215 (*tts_index)++;
4277 215 *tts_sample = 0;
4278 }
4279 }
4280 }
4281
4282
4/6
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 97 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 97 times.
✗ Branch 5 not taken.
104 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 84 times.
✓ Branch 1 taken 13 times.
97 if ((e_old[*index].timestamp + tts_data[*tts_index].offset) <= timestamp_pts &&
4287
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 5 times.
84 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
4288 79 break;
4289 }
4290
4291 18 (*index)--;
4292
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (*tts_sample == 0) {
4293 18 (*tts_index)--;
4294
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 7 times.
18 if (*tts_index >= 0)
4295 11 *tts_sample = tts_data[*tts_index].count - 1;
4296 } else {
4297 ✗ (*tts_sample)--;
4298 }
4299 }
4300 }
4301
4302 /* restore AVStream state*/
4303 570 sti->index_entries = e_keep;
4304 570 sti->nb_index_entries = nb_keep;
4305
2/2
✓ Branch 0 taken 562 times.
✓ Branch 1 taken 8 times.
570 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 361462 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
4320 int size, int distance, int flags)
4321 {
4322 361462 FFStream *const sti = ffstream(st);
4323 AVIndexEntry *entries, *ie;
4324 361462 int64_t index = -1;
4325 361462 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 361462 const size_t requested_size =
4330 361462 min_size_needed > sti->index_entries_allocated_size ?
4331
2/2
✓ Branch 0 taken 2407 times.
✓ Branch 1 taken 359055 times.
361462 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 361462 times.
361462 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
4335 ✗ return -1;
4336
4337 361462 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 361462 times.
361462 if (!entries)
4341 ✗ return -1;
4342
4343 361462 sti->index_entries = entries;
4344
4345 361462 index = sti->nb_index_entries++;
4346 361462 ie= &entries[index];
4347
4348 361462 ie->pos = pos;
4349 361462 ie->timestamp = timestamp;
4350 361462 ie->min_distance= distance;
4351 361462 ie->size= size;
4352 361462 ie->flags = flags;
4353 361462 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 49 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 49 FFStream *const sti = ffstream(st);
4364 49 int i = 0;
4365
2/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
49 av_assert0(end_index >= 0 && end_index <= sti->nb_index_entries);
4366
2/2
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 49 times.
243 for (i = 0; i < frame_duration_buffer_size; i++) {
4367 194 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4368 194 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4369 }
4370 49 }
4371
4372 196214 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 196214 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4377 196214 const size_t requested_size =
4378 196214 min_size_needed > *allocated_size ?
4379
2/2
✓ Branch 0 taken 1708 times.
✓ Branch 1 taken 194506 times.
196214 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4380 min_size_needed;
4381
4382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196214 times.
196214 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4383 ✗ return -1;
4384
4385 196214 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4386
4387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196214 times.
196214 if (!tts_buf_new)
4388 ✗ return -1;
4389
4390 196214 *tts_data = tts_buf_new;
4391
4392 196214 tts_buf_new[*tts_count].count = count;
4393 196214 tts_buf_new[*tts_count].offset = offset;
4394 196214 tts_buf_new[*tts_count].duration = duration;
4395
4396 196214 *tts_count = (*tts_count) + 1;
4397 196214 return 0;
4398 }
4399
4400 #define MAX_REORDER_DELAY 16
4401 742 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4402 {
4403 742 MOVStreamContext *msc = st->priv_data;
4404 742 FFStream *const sti = ffstream(st);
4405 742 int ctts_ind = 0;
4406 742 int ctts_sample = 0;
4407 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4408 742 int buf_start = 0;
4409 int j, r, num_swaps;
4410
4411
2/2
✓ Branch 0 taken 12614 times.
✓ Branch 1 taken 742 times.
13356 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4412 12614 pts_buf[j] = INT64_MIN;
4413
4414
3/4
✓ Branch 0 taken 742 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
✓ Branch 3 taken 663 times.
742 if (st->codecpar->video_delay <= 0 && msc->ctts_count &&
4415
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 28 times.
79 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 742 }
4456
4457 117267 static void mov_current_sample_inc(MOVStreamContext *sc)
4458 {
4459 117267 sc->current_sample++;
4460 117267 sc->current_index++;
4461
2/2
✓ Branch 0 taken 71225 times.
✓ Branch 1 taken 46042 times.
117267 if (sc->index_ranges &&
4462
2/2
✓ Branch 0 taken 497 times.
✓ Branch 1 taken 70728 times.
71225 sc->current_index >= sc->current_index_range->end &&
4463
1/2
✓ Branch 0 taken 497 times.
✗ Branch 1 not taken.
497 sc->current_index_range->end) {
4464 497 sc->current_index_range++;
4465 497 sc->current_index = sc->current_index_range->start;
4466 }
4467 117267 }
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 742 static void mov_fix_index(MOVContext *mov, AVStream *st)
4510 {
4511 742 MOVStreamContext *msc = st->priv_data;
4512 742 FFStream *const sti = ffstream(st);
4513 742 AVIndexEntry *e_old = sti->index_entries;
4514 742 int nb_old = sti->nb_index_entries;
4515 742 const AVIndexEntry *e_old_end = e_old + nb_old;
4516 742 const AVIndexEntry *current = NULL;
4517 742 MOVTimeToSample *tts_data_old = msc->tts_data;
4518 742 int64_t tts_index_old = 0;
4519 742 int64_t tts_sample_old = 0;
4520 742 int64_t tts_count_old = msc->tts_count;
4521 742 int64_t edit_list_media_time = 0;
4522 742 int64_t edit_list_duration = 0;
4523 742 int64_t frame_duration = 0;
4524 742 int64_t edit_list_dts_counter = 0;
4525 742 int64_t edit_list_dts_entry_end = 0;
4526 742 int64_t edit_list_start_tts_sample = 0;
4527 int64_t curr_cts;
4528 742 int64_t curr_ctts = 0;
4529 742 int64_t empty_edits_sum_duration = 0;
4530 742 int64_t edit_list_index = 0;
4531 int64_t index;
4532 int flags;
4533 742 int64_t start_dts = 0;
4534 742 int64_t edit_list_start_encountered = 0;
4535 742 int64_t search_timestamp = 0;
4536 742 int64_t* frame_duration_buffer = NULL;
4537 742 int num_discarded_begin = 0;
4538 742 int first_non_zero_audio_edit = -1;
4539 742 int packet_skip_samples = 0;
4540 742 MOVIndexRange *current_index_range = NULL;
4541 742 int found_keyframe_after_edit = 0;
4542 742 int found_non_empty_edit = 0;
4543
4544
4/6
✓ Branch 0 taken 541 times.
✓ Branch 1 taken 201 times.
✓ Branch 2 taken 541 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 541 times.
742 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
4545 201 return;
4546 }
4547
4548 // allocate the index ranges array
4549 541 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 541 times.
541 if (!msc->index_ranges) {
4552 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4553 ✗ return;
4554 }
4555 541 msc->current_index_range = msc->index_ranges;
4556
4557 // Clean AVStream from traces of old index
4558 541 sti->index_entries = NULL;
4559 541 sti->index_entries_allocated_size = 0;
4560 541 sti->nb_index_entries = 0;
4561
4562 // Clean time to sample fields of MOVStreamContext
4563 541 msc->tts_data = NULL;
4564 541 msc->tts_count = 0;
4565 541 msc->tts_index = 0;
4566 541 msc->tts_sample = 0;
4567 541 msc->tts_allocated_size = 0;
4568
4569 // Reinitialize min_corrected_pts so that it can be computed again.
4570 541 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 532 times.
541 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 541 start_dts = edit_list_dts_entry_end;
4580
4581
2/2
✓ Branch 0 taken 570 times.
✓ Branch 1 taken 541 times.
1652 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
4582 1111 &edit_list_duration, mov->time_scale)) {
4583 570 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 570 edit_list_index++;
4586 570 edit_list_dts_counter = edit_list_dts_entry_end;
4587 570 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 570 times.
570 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 570 num_discarded_begin = 0;
4594
4/4
✓ Branch 0 taken 545 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 541 times.
570 if (!found_non_empty_edit && edit_list_media_time == -1) {
4595 4 empty_edits_sum_duration += edit_list_duration;
4596 4 continue;
4597 }
4598 566 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 163 times.
✓ Branch 1 taken 403 times.
566 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4603
1/2
✓ Branch 0 taken 163 times.
✗ Branch 1 not taken.
163 if (first_non_zero_audio_edit < 0) {
4604 163 first_non_zero_audio_edit = 1;
4605 } else {
4606 ✗ first_non_zero_audio_edit = 0;
4607 }
4608
4609
1/2
✓ Branch 0 taken 163 times.
✗ Branch 1 not taken.
163 if (first_non_zero_audio_edit > 0)
4610 163 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 566 search_timestamp = edit_list_media_time;
4618
2/2
✓ Branch 0 taken 163 times.
✓ Branch 1 taken 403 times.
566 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 163 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 562 times.
566 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 566 current = e_old + index;
4641 566 edit_list_start_tts_sample = tts_sample_old;
4642
4643 // Iterate over index and arrange it according to edit list
4644 566 edit_list_start_encountered = 0;
4645 566 found_keyframe_after_edit = 0;
4646
2/2
✓ Branch 0 taken 361462 times.
✓ Branch 1 taken 144 times.
361606 for (; current < e_old_end; current++, index++) {
4647 // check if frame outside edit list mark it for discard
4648 722924 frame_duration = (current + 1 < e_old_end) ?
4649
2/2
✓ Branch 0 taken 360929 times.
✓ Branch 1 taken 533 times.
361462 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4650
4651 361462 flags = current->flags;
4652
4653 // frames (pts) before or after edit list
4654 361462 curr_cts = current->timestamp + msc->dts_shift;
4655 361462 curr_ctts = 0;
4656
4657
4/4
✓ Branch 0 taken 196226 times.
✓ Branch 1 taken 165236 times.
✓ Branch 2 taken 196214 times.
✓ Branch 3 taken 12 times.
361462 if (tts_data_old && tts_index_old < tts_count_old) {
4658 196214 curr_ctts = tts_data_old[tts_index_old].offset;
4659 196214 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 196214 curr_cts += curr_ctts;
4662 196214 tts_sample_old++;
4663
1/2
✓ Branch 0 taken 196214 times.
✗ Branch 1 not taken.
196214 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196214 times.
196214 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4665 &msc->tts_allocated_size,
4666 196214 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4667 196214 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 196214 tts_index_old++;
4675 196214 tts_sample_old = 0;
4676 196214 edit_list_start_tts_sample = 0;
4677 }
4678 }
4679
4680
4/4
✓ Branch 0 taken 361239 times.
✓ Branch 1 taken 223 times.
✓ Branch 2 taken 158 times.
✓ Branch 3 taken 361081 times.
361462 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
4681
4/4
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 259 times.
✓ Branch 2 taken 78 times.
✓ Branch 3 taken 44 times.
381 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
4682
4/6
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 53 times.
✓ Branch 4 taken 25 times.
✗ Branch 5 not taken.
78 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 356 flags |= AVINDEX_DISCARD_FRAME;
4703 356 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 196 times.
✓ Branch 1 taken 160 times.
356 if (edit_list_start_encountered == 0) {
4706 196 num_discarded_begin++;
4707
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 196 times.
196 if (av_reallocp_array(&frame_duration_buffer, num_discarded_begin,
4708 sizeof(*frame_duration_buffer)) < 0) {
4709 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4710 ✗ break;
4711 }
4712 196 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4713
4714 // Increment skip_samples for the first non-zero audio edit list
4715
3/4
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 97 times.
✗ Branch 3 not taken.
196 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4716
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 44 times.
97 first_non_zero_audio_edit > 0 && st->codecpar->codec_id != AV_CODEC_ID_VORBIS) {
4717 53 sti->skip_samples += frame_duration;
4718 }
4719 }
4720 }
4721 } else {
4722
2/2
✓ Branch 0 taken 540 times.
✓ Branch 1 taken 360541 times.
361081 if (msc->min_corrected_pts < 0) {
4723 540 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4724 } else {
4725 360541 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4726 }
4727
2/2
✓ Branch 0 taken 539 times.
✓ Branch 1 taken 360542 times.
361081 if (edit_list_start_encountered == 0) {
4728 539 edit_list_start_encountered = 1;
4729 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4730 // discarded packets.
4731
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 505 times.
539 if (frame_duration_buffer) {
4732 34 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4733 frame_duration_buffer, num_discarded_begin);
4734 34 av_freep(&frame_duration_buffer);
4735 }
4736 }
4737 }
4738
4739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 361462 times.
361462 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
4740 361462 current->min_distance, flags) == -1) {
4741 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4742 ✗ break;
4743 }
4744
4745 // Update the index ranges array
4746
4/4
✓ Branch 0 taken 360921 times.
✓ Branch 1 taken 541 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 360898 times.
361462 if (!current_index_range || index != current_index_range->end) {
4747 564 current_index_range = current_index_range ? current_index_range + 1
4748
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 541 times.
564 : msc->index_ranges;
4749 564 current_index_range->start = index;
4750 }
4751 361462 current_index_range->end = index + 1;
4752
4753 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4754
2/2
✓ Branch 0 taken 361266 times.
✓ Branch 1 taken 196 times.
361462 if (edit_list_start_encountered > 0) {
4755 361266 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4756 }
4757
4758 // Break when found first key frame after edit entry completion
4759
2/2
✓ Branch 0 taken 761 times.
✓ Branch 1 taken 360701 times.
361462 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
4760
4/4
✓ Branch 0 taken 318 times.
✓ Branch 1 taken 443 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 317 times.
761 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
4761
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 411 times.
444 if (msc->ctts_count) {
4762 // If we have CTTS and this is the first keyframe after edit elist,
4763 // wait for one more, because there might be trailing B-frames after this I-frame
4764 // that do belong to the edit.
4765
3/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 11 times.
33 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO && found_keyframe_after_edit == 0) {
4766 22 found_keyframe_after_edit = 1;
4767 22 continue;
4768 }
4769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (tts_sample_old != 0) {
4770 ✗ if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4771 &msc->tts_allocated_size,
4772 ✗ tts_sample_old - edit_list_start_tts_sample,
4773 ✗ tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4774 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4775 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4776 ✗ tts_data_old[tts_index_old].offset);
4777 ✗ break;
4778 }
4779 }
4780 }
4781 422 break;
4782 }
4783 }
4784 }
4785 // If there are empty edits, then msc->min_corrected_pts might be positive
4786 // intentionally. So we subtract the sum duration of empty edits here.
4787 541 msc->min_corrected_pts -= empty_edits_sum_duration;
4788
4789 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4790 // dts by that amount to make the first pts zero.
4791
2/2
✓ Branch 0 taken 327 times.
✓ Branch 1 taken 214 times.
541 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4792
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 266 times.
327 if (msc->min_corrected_pts > 0) {
4793 61 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4794
2/2
✓ Branch 0 taken 3310 times.
✓ Branch 1 taken 61 times.
3371 for (int i = 0; i < sti->nb_index_entries; ++i)
4795 3310 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4796 }
4797 }
4798 // Start time should be equal to zero or the duration of any empty edits.
4799 541 st->start_time = empty_edits_sum_duration;
4800
4801 // Update av stream length, if it ends up shorter than the track's media duration
4802 541 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4803 541 st->codecpar->initial_padding = sti->skip_samples;
4804
4805 // Free the old index and the old CTTS structures
4806 541 av_free(e_old);
4807 541 av_free(tts_data_old);
4808 541 av_freep(&frame_duration_buffer);
4809
4810 // Null terminate the index ranges array
4811 541 current_index_range = current_index_range ? current_index_range + 1
4812
1/2
✓ Branch 0 taken 541 times.
✗ Branch 1 not taken.
541 : msc->index_ranges;
4813 541 current_index_range->start = 0;
4814 541 current_index_range->end = 0;
4815 541 msc->current_index = msc->index_ranges[0].start;
4816 }
4817
4818 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4819 {
4820
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4821
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == nal_unit_type)
4822 5 return i + 1;
4823 ✗ return 0;
4824 }
4825
4826 772 static int build_open_gop_key_points(AVStream *st)
4827 {
4828 int k;
4829 772 int sample_id = 0;
4830 uint32_t cra_index;
4831 772 MOVStreamContext *sc = st->priv_data;
4832
4833
4/4
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 703 times.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 5 times.
772 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count)
4834 767 return 0;
4835
4836 /* Build an unrolled index of the samples */
4837 5 sc->sample_offsets_count = 0;
4838
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4840 ✗ return AVERROR(ENOMEM);
4841 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4842 }
4843 5 av_freep(&sc->sample_offsets);
4844 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4846 ✗ return AVERROR(ENOMEM);
4847 5 k = 0;
4848
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4849
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4850 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4851
4852 /* The following HEVC NAL type reveal the use of open GOP sync points
4853 * (TODO: BLA types may also be concerned) */
4854 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4856 ✗ return 0;
4857
4858 /* Build a list of open-GOP key samples */
4859 5 sc->open_key_samples_count = 0;
4860
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4861
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4862
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)
4863 ✗ return AVERROR(ENOMEM);
4864 11 sc->open_key_samples_count += sc->sync_group[i].count;
4865 }
4866 5 av_freep(&sc->open_key_samples);
4867 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4869 ✗ return AVERROR(ENOMEM);
4870 5 k = 0;
4871
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4872 28 const MOVSbgp *sg = &sc->sync_group[i];
4873
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4874
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4875 11 sc->open_key_samples[k++] = sample_id;
4876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4877 ✗ return AVERROR_PATCHWELCOME;
4878 28 sample_id += sg->count;
4879 }
4880
4881 /* Identify the minimal time step between samples */
4882 5 sc->min_sample_duration = UINT_MAX;
4883
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4884 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4885
4886 5 return 0;
4887 }
4888
4889 #define MOV_MERGE_CTTS 1
4890 #define MOV_MERGE_STTS 2
4891 /*
4892 * Merge stts and ctts arrays into a new combined array.
4893 * stts_count and ctts_count may be left untouched as they will be
4894 * used to check for the presence of either of them.
4895 */
4896 742 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4897 {
4898 742 MOVStreamContext *sc = st->priv_data;
4899
3/4
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 663 times.
✓ Branch 2 taken 79 times.
✗ Branch 3 not taken.
742 int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS);
4900
3/4
✓ Branch 0 taken 742 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 671 times.
✓ Branch 3 taken 71 times.
742 int stts = sc->stts_data && (flags & MOV_MERGE_STTS);
4901 742 int idx = 0;
4902
4903
3/4
✓ Branch 0 taken 663 times.
✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 663 times.
742 if (!sc->ctts_data && !sc->stts_data)
4904 ✗ return 0;
4905 // Expand time to sample entries such that we have a 1-1 mapping with samples
4906
2/4
✓ Branch 0 taken 742 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 742 times.
742 if (!sc->sample_count || sc->sample_count >= UINT_MAX / sizeof(*sc->tts_data))
4907 ✗ return -1;
4908
4909
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 663 times.
742 if (ctts) {
4910 158 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4911 79 sc->sample_count * sizeof(*sc->tts_data));
4912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (!sc->tts_data)
4913 ✗ return -1;
4914
4915 79 memset(sc->tts_data, 0, sc->tts_allocated_size);
4916
4917
2/2
✓ Branch 0 taken 5256 times.
✓ Branch 1 taken 79 times.
5335 for (int i = 0; i < sc->ctts_count &&
4918
1/2
✓ Branch 0 taken 5256 times.
✗ Branch 1 not taken.
10512 idx < sc->sample_count; i++)
4919
2/2
✓ Branch 0 taken 139472 times.
✓ Branch 1 taken 5256 times.
144728 for (int j = 0; j < sc->ctts_data[i].count &&
4920
1/2
✓ Branch 0 taken 139472 times.
✗ Branch 1 not taken.
139472 idx < sc->sample_count; j++) {
4921 139472 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4922 139472 sc->tts_data[idx++].count = 1;
4923 }
4924
4925 79 sc->tts_count = idx;
4926 } else
4927 663 sc->ctts_count = 0;
4928 742 av_freep(&sc->ctts_data);
4929 742 sc->ctts_allocated_size = 0;
4930
4931 742 idx = 0;
4932
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 71 times.
742 if (stts) {
4933 671 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4934 671 sc->sample_count * sizeof(*sc->tts_data));
4935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 671 times.
671 if (!tts_data)
4936 ✗ return -1;
4937
4938
2/2
✓ Branch 0 taken 592 times.
✓ Branch 1 taken 79 times.
671 if (!sc->tts_data)
4939 592 memset(tts_data, 0, sc->tts_allocated_size);
4940 671 sc->tts_data = tts_data;
4941
4942
2/2
✓ Branch 0 taken 3094 times.
✓ Branch 1 taken 671 times.
3765 for (int i = 0; i < sc->stts_count &&
4943
1/2
✓ Branch 0 taken 3094 times.
✗ Branch 1 not taken.
6188 idx < sc->sample_count; i++)
4944
2/2
✓ Branch 0 taken 249255 times.
✓ Branch 1 taken 3094 times.
252349 for (int j = 0; j < sc->stts_data[i].count &&
4945
1/2
✓ Branch 0 taken 249255 times.
✗ Branch 1 not taken.
249255 idx < sc->sample_count; j++) {
4946 249255 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4947 249255 sc->tts_data[idx++].count = 1;
4948 }
4949
4950 671 sc->tts_count = FFMAX(sc->tts_count, idx);
4951 } else
4952 71 sc->stts_count = 0;
4953 742 av_freep(&sc->stts_data);
4954 742 sc->stts_allocated_size = 0;
4955
4956 742 return 0;
4957 }
4958
4959 772 static void mov_build_index(MOVContext *mov, AVStream *st)
4960 {
4961 772 MOVStreamContext *sc = st->priv_data;
4962 772 FFStream *const sti = ffstream(st);
4963 int64_t current_offset;
4964 772 int64_t current_dts = 0;
4965 772 unsigned int stts_index = 0;
4966 772 unsigned int stsc_index = 0;
4967 772 unsigned int stss_index = 0;
4968 772 unsigned int stps_index = 0;
4969 unsigned int i, j;
4970 772 uint64_t stream_size = 0;
4971
4972 772 int ret = build_open_gop_key_points(st);
4973
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 772 times.
772 if (ret < 0)
4974 ✗ return;
4975
4976
2/2
✓ Branch 0 taken 544 times.
✓ Branch 1 taken 228 times.
772 if (sc->elst_count) {
4977 544 int i, edit_start_index = 0, multiple_edits = 0;
4978 544 int64_t empty_duration = 0; // empty duration of the first edit list entry
4979 544 int64_t start_time = 0; // start time of the media
4980
4981
2/2
✓ Branch 0 taken 573 times.
✓ Branch 1 taken 544 times.
1117 for (i = 0; i < sc->elst_count; i++) {
4982 573 const MOVElst *e = &sc->elst_data[i];
4983
4/4
✓ Branch 0 taken 544 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 540 times.
573 if (i == 0 && e->time == -1) {
4984 /* if empty, the first entry is the start time of the stream
4985 * relative to the presentation itself */
4986 4 empty_duration = e->duration;
4987 4 edit_start_index = 1;
4988
3/4
✓ Branch 0 taken 544 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 544 times.
✗ Branch 3 not taken.
569 } else if (i == edit_start_index && e->time >= 0) {
4989 544 start_time = e->time;
4990 } else {
4991 25 multiple_edits = 1;
4992 }
4993 }
4994
4995
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 537 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
544 if (multiple_edits && !mov->advanced_editlist) {
4996 ✗ if (mov->advanced_editlist_autodisabled)
4997 ✗ av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4998 "not supported in fragmented MP4 files\n");
4999 else
5000 ✗ av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
5001 "Use -advanced_editlist to correctly decode otherwise "
5002 "a/v desync might occur\n");
5003 }
5004
5005 /* adjust first dts according to edit list */
5006
5/6
✓ Branch 0 taken 540 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 116 times.
✓ Branch 3 taken 424 times.
✓ Branch 4 taken 120 times.
✗ Branch 5 not taken.
544 if ((empty_duration || start_time) && mov->time_scale > 0) {
5007
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 116 times.
120 if (empty_duration)
5008 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
5009
5010
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 120 times.
120 if (av_sat_sub64(start_time, empty_duration) != start_time - (uint64_t)empty_duration)
5011 ✗ av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
5012
5013 120 sc->time_offset = start_time - (uint64_t)empty_duration;
5014 120 sc->min_corrected_pts = start_time;
5015
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 119 times.
120 if (!mov->advanced_editlist)
5016 1 current_dts = -av_clip64(sc->time_offset, -INT64_MAX, INT64_MAX);
5017 }
5018
5019
4/4
✓ Branch 0 taken 537 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 534 times.
544 if (!multiple_edits && !mov->advanced_editlist &&
5020
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)
5021 ✗ st->codecpar->initial_padding = av_rescale_q(start_time, st->time_base,
5022 ✗ (AVRational){1, st->codecpar->sample_rate});
5023 }
5024
5025 /* only use old uncompressed audio chunk demuxing when stts specifies it */
5026
2/2
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 482 times.
772 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
5027
5/6
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 241 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 170 times.
✓ Branch 5 taken 71 times.
961 sc->stts_count == 1 && sc->stts_data && sc->stts_data[0].duration == 1)) {
5028 701 unsigned int current_sample = 0;
5029 701 unsigned int stts_sample = 0;
5030 unsigned int sample_size;
5031 701 unsigned int distance = 0;
5032 701 unsigned int rap_group_index = 0;
5033 701 unsigned int rap_group_sample = 0;
5034
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 700 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
701 int rap_group_present = sc->rap_group_count && sc->rap_group;
5035
4/8
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 533 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 168 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 533 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
701 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
5036
5037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 701 times.
701 av_assert0(sc->dts_shift >= 0);
5038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 701 times.
701 if (current_dts < INT64_MIN + sc->dts_shift)
5039 ✗ return;
5040 701 current_dts -= sc->dts_shift;
5041
4/6
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 671 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 671 times.
701 if (!sc->sample_count || sti->nb_index_entries || sc->tts_count)
5042 30 return;
5043
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 671 times.
671 if (sc->sample_count >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
5044 ✗ return;
5045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 671 times.
671 if (av_reallocp_array(&sti->index_entries,
5046 671 sti->nb_index_entries + sc->sample_count,
5047 sizeof(*sti->index_entries)) < 0) {
5048 ✗ sti->nb_index_entries = 0;
5049 ✗ return;
5050 }
5051 671 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
5052
5053 671 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
5054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 671 times.
671 if (ret < 0)
5055 ✗ return;
5056
5057
2/2
✓ Branch 0 taken 174767 times.
✓ Branch 1 taken 671 times.
175438 for (i = 0; i < sc->chunk_count; i++) {
5058
2/2
✓ Branch 0 taken 174096 times.
✓ Branch 1 taken 671 times.
174767 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
5059 174767 current_offset = sc->chunk_offsets[i];
5060
2/2
✓ Branch 1 taken 8723 times.
✓ Branch 2 taken 168600 times.
177323 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
5061
2/2
✓ Branch 0 taken 2556 times.
✓ Branch 1 taken 6167 times.
8723 i + 1 == sc->stsc_data[stsc_index + 1].first)
5062 2556 stsc_index++;
5063
5064
4/6
✓ Branch 0 taken 174767 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7422 times.
✓ Branch 3 taken 167345 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7422 times.
174767 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
5065 ✗ sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
5066 ✗ av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
5067 ✗ sc->stsz_sample_size = sc->sample_size;
5068 }
5069
3/4
✓ Branch 0 taken 7422 times.
✓ Branch 1 taken 167345 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7422 times.
174767 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
5070 ✗ av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
5071 ✗ sc->stsz_sample_size = sc->sample_size;
5072 }
5073
5074
2/2
✓ Branch 0 taken 249255 times.
✓ Branch 1 taken 174767 times.
424022 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
5075 249255 int keyframe = 0;
5076
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249255 times.
249255 if (current_sample >= sc->sample_count) {
5077 ✗ av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
5078 ✗ return;
5079 }
5080
5081
6/6
✓ Branch 0 taken 239544 times.
✓ Branch 1 taken 9711 times.
✓ Branch 2 taken 153391 times.
✓ Branch 3 taken 86153 times.
✓ Branch 4 taken 5768 times.
✓ Branch 5 taken 147623 times.
249255 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
5082 91921 keyframe = 1;
5083
2/2
✓ Branch 0 taken 5600 times.
✓ Branch 1 taken 86321 times.
91921 if (stss_index + 1 < sc->keyframe_count)
5084 5600 stss_index++;
5085
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 157334 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
157334 } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
5086 ✗ keyframe = 1;
5087 ✗ if (stps_index + 1 < sc->stps_count)
5088 ✗ stps_index++;
5089 }
5090
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 249067 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
249255 if (rap_group_present && rap_group_index < sc->rap_group_count) {
5091
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
5092 2 keyframe = 1;
5093
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
5094 4 rap_group_sample = 0;
5095 4 rap_group_index++;
5096 }
5097 }
5098
2/2
✓ Branch 0 taken 9711 times.
✓ Branch 1 taken 239544 times.
249255 if (sc->keyframe_absent
5099
1/2
✓ Branch 0 taken 9711 times.
✗ Branch 1 not taken.
9711 && !sc->stps_count
5100
1/2
✓ Branch 0 taken 9711 times.
✗ Branch 1 not taken.
9711 && !rap_group_present
5101
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)))
5102 8839 keyframe = 1;
5103
2/2
✓ Branch 0 taken 100760 times.
✓ Branch 1 taken 148495 times.
249255 if (keyframe)
5104 100760 distance = 0;
5105
2/2
✓ Branch 0 taken 9323 times.
✓ Branch 1 taken 239932 times.
249255 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
5106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249255 times.
249255 if (current_offset > INT64_MAX - sample_size) {
5107 ✗ av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
5108 current_offset,
5109 sample_size);
5110 ✗ return;
5111 }
5112
5113
2/2
✓ Branch 0 taken 249158 times.
✓ Branch 1 taken 97 times.
249255 if (sc->pseudo_stream_id == -1 ||
5114
2/2
✓ Branch 0 taken 249156 times.
✓ Branch 1 taken 2 times.
249158 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
5115 AVIndexEntry *e;
5116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249253 times.
249253 if (sample_size > 0x3FFFFFFF) {
5117 ✗ av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
5118 ✗ return;
5119 }
5120 249253 e = &sti->index_entries[sti->nb_index_entries++];
5121 249253 e->pos = current_offset;
5122 249253 e->timestamp = current_dts;
5123 249253 e->size = sample_size;
5124 249253 e->min_distance = distance;
5125 249253 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
5126 249253 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
5127 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
5128 current_offset, current_dts, sample_size, distance, keyframe);
5129
4/4
✓ Branch 0 taken 156320 times.
✓ Branch 1 taken 92933 times.
✓ Branch 2 taken 11687 times.
✓ Branch 3 taken 144633 times.
249253 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries < 100)
5130 11687 ff_rfps_add_frame(mov->fc, st, current_dts);
5131 }
5132
5133 249255 current_offset += sample_size;
5134 249255 stream_size += sample_size;
5135
5136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249255 times.
249255 if (current_dts > INT64_MAX - sc->tts_data[stts_index].duration)
5137 ✗ return;
5138 249255 current_dts += sc->tts_data[stts_index].duration;
5139
5140 249255 distance++;
5141 249255 stts_sample++;
5142 249255 current_sample++;
5143
3/4
✓ Branch 0 taken 248584 times.
✓ Branch 1 taken 671 times.
✓ Branch 2 taken 248584 times.
✗ Branch 3 not taken.
249255 if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) {
5144 248584 stts_sample = 0;
5145 248584 stts_index++;
5146 }
5147 }
5148 }
5149
2/2
✓ Branch 0 taken 628 times.
✓ Branch 1 taken 43 times.
671 if (st->duration > 0)
5150 628 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
5151 } else {
5152 71 unsigned chunk_samples, total = 0;
5153
5154
2/4
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 71 times.
71 if (!sc->chunk_count || sc->tts_count)
5155 ✗ return;
5156
5157 // compute total chunk count
5158
2/2
✓ Branch 0 taken 742 times.
✓ Branch 1 taken 71 times.
813 for (i = 0; i < sc->stsc_count; i++) {
5159 unsigned count, chunk_count;
5160
5161 742 chunk_samples = sc->stsc_data[i].count;
5162
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 71 times.
742 if (i != sc->stsc_count - 1 &&
5163
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) {
5164 ✗ av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
5165 ✗ return;
5166 }
5167
5168
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 667 times.
742 if (sc->samples_per_frame >= 160) { // gsm
5169 75 count = chunk_samples / sc->samples_per_frame;
5170
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 136 times.
667 } else if (sc->samples_per_frame > 1) {
5171 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
5172 531 count = (chunk_samples+samples-1) / samples;
5173 } else {
5174 136 count = (chunk_samples+1023) / 1024;
5175 }
5176
5177
2/2
✓ Branch 1 taken 671 times.
✓ Branch 2 taken 71 times.
742 if (mov_stsc_index_valid(i, sc->stsc_count))
5178 671 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
5179 else
5180 71 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
5181 742 total += chunk_count * count;
5182 }
5183
5184 71 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
5185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
5186 ✗ return;
5187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (av_reallocp_array(&sti->index_entries,
5188 71 sti->nb_index_entries + total,
5189 sizeof(*sti->index_entries)) < 0) {
5190 ✗ sti->nb_index_entries = 0;
5191 ✗ return;
5192 }
5193 71 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
5194
5195 // populate index
5196
2/2
✓ Branch 0 taken 5563 times.
✓ Branch 1 taken 71 times.
5634 for (i = 0; i < sc->chunk_count; i++) {
5197 5563 current_offset = sc->chunk_offsets[i];
5198
2/2
✓ Branch 1 taken 5399 times.
✓ Branch 2 taken 164 times.
5563 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
5199
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 4728 times.
5399 i + 1 == sc->stsc_data[stsc_index + 1].first)
5200 671 stsc_index++;
5201 5563 chunk_samples = sc->stsc_data[stsc_index].count;
5202
5203
2/2
✓ Branch 0 taken 165283 times.
✓ Branch 1 taken 5563 times.
170846 while (chunk_samples > 0) {
5204 AVIndexEntry *e;
5205 unsigned size, samples;
5206
5207
3/4
✓ Branch 0 taken 23921 times.
✓ Branch 1 taken 141362 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 23921 times.
165283 if (sc->samples_per_frame > 1 && !sc->bytes_per_frame) {
5208 ✗ avpriv_request_sample(mov->fc,
5209 "Zero bytes per frame, but %d samples per frame",
5210 sc->samples_per_frame);
5211 ✗ return;
5212 }
5213
5214
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 150925 times.
165283 if (sc->samples_per_frame >= 160) { // gsm
5215 14358 samples = sc->samples_per_frame;
5216 14358 size = sc->bytes_per_frame;
5217 } else {
5218
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 141362 times.
150925 if (sc->samples_per_frame > 1) {
5219 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
5220 sc->samples_per_frame, chunk_samples);
5221 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
5222 } else {
5223 141362 samples = FFMIN(1024, chunk_samples);
5224 141362 size = samples * sc->sample_size;
5225 }
5226 }
5227
5228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165283 times.
165283 if (sti->nb_index_entries >= total) {
5229 ✗ av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
5230 ✗ return;
5231 }
5232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165283 times.
165283 if (size > 0x3FFFFFFF) {
5233 ✗ av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
5234 ✗ return;
5235 }
5236 165283 e = &sti->index_entries[sti->nb_index_entries++];
5237 165283 e->pos = current_offset;
5238 165283 e->timestamp = current_dts;
5239 165283 e->size = size;
5240 165283 e->min_distance = 0;
5241 165283 e->flags = AVINDEX_KEYFRAME;
5242 165283 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
5243 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
5244 size, samples);
5245
5246 165283 current_offset += size;
5247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165283 times.
165283 if (current_dts > INT64_MAX - samples)
5248 ✗ return;
5249 165283 current_dts += samples;
5250 165283 chunk_samples -= samples;
5251 }
5252 }
5253
5254 71 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
5255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (ret < 0)
5256 ✗ return;
5257 }
5258
5259
2/4
✓ Branch 0 taken 742 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 742 times.
✗ Branch 3 not taken.
742 if (!mov->ignore_editlist && mov->advanced_editlist) {
5260 // Fix index according to edit lists.
5261 742 mov_fix_index(mov, st);
5262 }
5263
5264 // Update start time of the stream.
5265
5/6
✓ Branch 0 taken 201 times.
✓ Branch 1 taken 541 times.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 130 times.
✓ Branch 4 taken 71 times.
✗ Branch 5 not taken.
742 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) {
5266 71 st->start_time = av_sat_add64(sti->index_entries[0].timestamp, sc->dts_shift);
5267
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 if (sc->tts_data) {
5268 71 st->start_time = av_sat_add64(st->start_time, sc->tts_data[0].offset);
5269 }
5270 }
5271
5272 742 mov_estimate_video_delay(mov, st);
5273 }
5274
5275 typedef struct MOVPresentationSample {
5276 int index;
5277 int64_t pts;
5278 } MOVPresentationSample;
5279
5280 12202 static int mov_compare_presentation_samples(const void *a, const void *b)
5281 {
5282 12202 const MOVPresentationSample *sa = a;
5283 12202 const MOVPresentationSample *sb = b;
5284
5285
2/2
✓ Branch 0 taken 12198 times.
✓ Branch 1 taken 4 times.
12202 if (sa->pts != sb->pts)
5286 12198 return (sa->pts > sb->pts) - (sa->pts < sb->pts);
5287 4 return (sa->index > sb->index) - (sa->index < sb->index);
5288 }
5289
5290 /*
5291 * Set sample durations from adjacent presentation timestamps.
5292 */
5293 729 static void mov_update_sample_durations(MOVContext *mov, AVStream *st)
5294 {
5295 729 MOVStreamContext *sc = st->priv_data;
5296 729 FFStream *const sti = ffstream(st);
5297 729 MOVPresentationSample *samples = NULL;
5298 729 MOVTimeToSample *tts_data = NULL;
5299 729 unsigned int tts_index = 0, tts_sample = 0;
5300 729 int count = sti->nb_index_entries;
5301
5302 /* A single STTS entry describes a fixed sample delta. */
5303
2/2
✓ Branch 0 taken 373 times.
✓ Branch 1 taken 356 times.
729 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
5304
4/4
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 298 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 63 times.
373 !sc->ctts_count || sc->stts_count < 2 ||
5305
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 ||
5306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 count >= UINT_MAX / sizeof(*tts_data))
5307 717 return;
5308
5309 12 samples = av_malloc_array(count, sizeof(*samples));
5310 12 tts_data = av_malloc_array(count, sizeof(*tts_data));
5311
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)
5312 ✗ goto fail;
5313
5314
2/2
✓ Branch 0 taken 2654 times.
✓ Branch 1 taken 12 times.
2666 for (int i = 0; i < count; i++) {
5315 int64_t dts, offset;
5316
5317
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)
5318 ✗ goto fail;
5319
5320 2654 tts_data[i] = sc->tts_data[tts_index];
5321 2654 tts_data[i].count = 1;
5322
5323 2654 dts = sti->index_entries[i].timestamp;
5324 2654 offset = (int64_t)sc->dts_shift + tts_data[i].offset;
5325
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 ||
5326
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) ||
5327 ✗ (offset < 0 && dts < INT64_MIN - offset))
5328 ✗ goto fail;
5329
5330 2654 samples[i].index = i;
5331 2654 samples[i].pts = dts + offset;
5332
5333
1/2
✓ Branch 0 taken 2654 times.
✗ Branch 1 not taken.
2654 if (++tts_sample == sc->tts_data[tts_index].count) {
5334 2654 tts_index++;
5335 2654 tts_sample = 0;
5336 }
5337 }
5338
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)
5339 ✗ goto fail;
5340
5341 12 qsort(samples, count, sizeof(*samples), mov_compare_presentation_samples);
5342
5343
2/2
✓ Branch 0 taken 2624 times.
✓ Branch 1 taken 10 times.
2634 for (int i = 0; i + 1 < count; i++) {
5344 uint64_t duration;
5345
5346
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2622 times.
2624 if (samples[i].pts >= samples[i + 1].pts)
5347 2 goto fail;
5348
5349 /*
5350 * In VFR streams with reordered frames, STTS deltas follow decode
5351 * order while AVPacket.duration follows presentation order. CTTS
5352 * may produce presentation intervals that cannot be obtained by
5353 * merely permuting the STTS deltas, so derive each known duration
5354 * from adjacent PTS.
5355 */
5356 2622 duration = (uint64_t)samples[i + 1].pts - samples[i].pts;
5357
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)
5358 ✗ goto fail;
5359
5360 2622 tts_data[samples[i].index].duration = (unsigned int)duration;
5361 }
5362
5363 10 av_log(mov->fc, AV_LOG_DEBUG,
5364 "Updated sample durations in presentation order for stream %d\n",
5365 st->index);
5366
5367 10 av_freep(&sc->tts_data);
5368 10 sc->tts_data = tts_data;
5369 10 sc->tts_count = count;
5370 10 sc->tts_allocated_size = count * sizeof(*tts_data);
5371 10 tts_data = NULL;
5372
5373 12 fail:
5374 12 av_free(samples);
5375 12 av_free(tts_data);
5376 }
5377
5378 ✗ static int test_same_origin(const char *src, const char *ref) {
5379 char src_proto[64];
5380 char ref_proto[64];
5381 char src_auth[256];
5382 char ref_auth[256];
5383 char src_host[256];
5384 char ref_host[256];
5385 ✗ int src_port=-1;
5386 ✗ int ref_port=-1;
5387
5388 ✗ av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
5389 ✗ av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
5390
5391 ✗ if (strlen(src) == 0) {
5392 ✗ return -1;
5393 ✗ } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
5394 ✗ strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
5395 ✗ strlen(src_host) + 1 >= sizeof(src_host) ||
5396 ✗ strlen(ref_host) + 1 >= sizeof(ref_host)) {
5397 ✗ return 0;
5398 ✗ } else if (strcmp(src_proto, ref_proto) ||
5399 ✗ strcmp(src_auth, ref_auth) ||
5400 ✗ strcmp(src_host, ref_host) ||
5401 ✗ src_port != ref_port) {
5402 ✗ return 0;
5403 } else
5404 ✗ return 1;
5405 }
5406
5407 ✗ static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
5408 {
5409 /* try relative path, we do not try the absolute because it can leak information about our
5410 system to an attacker */
5411 ✗ if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
5412 char filename[1025];
5413 const char *src_path;
5414 int i, l;
5415
5416 /* find a source dir */
5417 ✗ src_path = strrchr(src, '/');
5418 ✗ if (src_path)
5419 ✗ src_path++;
5420 else
5421 ✗ src_path = src;
5422
5423 /* find a next level down to target */
5424 ✗ for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
5425 ✗ if (ref->path[l] == '/') {
5426 ✗ if (i == ref->nlvl_to - 1)
5427 ✗ break;
5428 else
5429 ✗ i++;
5430 }
5431
5432 /* compose filename if next level down to target was found */
5433 ✗ if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
5434 ✗ memcpy(filename, src, src_path - src);
5435 ✗ filename[src_path - src] = 0;
5436
5437 ✗ for (i = 1; i < ref->nlvl_from; i++)
5438 ✗ av_strlcat(filename, "../", sizeof(filename));
5439
5440 ✗ av_strlcat(filename, ref->path + l + 1, sizeof(filename));
5441 ✗ if (!c->use_absolute_path) {
5442 ✗ int same_origin = test_same_origin(src, filename);
5443
5444 ✗ if (!same_origin) {
5445 ✗ av_log(c->fc, AV_LOG_ERROR,
5446 "Reference with mismatching origin, %s not tried for security reasons, "
5447 "set demuxer option use_absolute_path to allow it anyway\n",
5448 ref->path);
5449 ✗ return AVERROR(ENOENT);
5450 }
5451
5452 ✗ if (strstr(ref->path + l + 1, "..") ||
5453 ✗ strstr(ref->path + l + 1, ":") ||
5454 ✗ (ref->nlvl_from > 1 && same_origin < 0) ||
5455 ✗ (filename[0] == '/' && src_path == src))
5456 ✗ return AVERROR(ENOENT);
5457 }
5458
5459 ✗ if (strlen(filename) + 1 == sizeof(filename))
5460 ✗ return AVERROR(ENOENT);
5461 ✗ if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5462 ✗ return 0;
5463 }
5464 ✗ } else if (c->use_absolute_path) {
5465 ✗ av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5466 "this is a possible security issue\n");
5467 ✗ if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5468 ✗ return 0;
5469 } else {
5470 ✗ av_log(c->fc, AV_LOG_ERROR,
5471 "Absolute path %s not tried for security reasons, "
5472 "set demuxer option use_absolute_path to allow absolute paths\n",
5473 ref->path);
5474 }
5475
5476 ✗ return AVERROR(ENOENT);
5477 }
5478
5479 1569 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5480 {
5481
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1553 times.
1569 if (sc->time_scale <= 0) {
5482 16 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5483 16 sc->time_scale = c->time_scale;
5484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (sc->time_scale <= 0)
5485 ✗ sc->time_scale = 1;
5486 }
5487 1569 }
5488
5489 #if CONFIG_IAMFDEC
5490 12 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5491 {
5492 12 const MOVStreamContext *sc = st->priv_data;
5493 12 const IAMFContext *iamf = &sc->iamf->iamf;
5494
5495
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5496 12 const AVStreamGroup *stg = NULL;
5497
5498
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5499
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)
5500 12 stg = c->fc->stream_groups[j];
5501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 av_assert0(stg);
5502
5503
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_streams; j++) {
5504 64 const FFStream *sti = cffstream(st);
5505 64 AVStream *out = stg->streams[j];
5506 64 FFStream *out_sti = ffstream(stg->streams[j]);
5507
5508 64 out->codecpar->bit_rate = 0;
5509
5510
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 52 times.
64 if (out == st)
5511 12 continue;
5512
5513 52 out->time_base = st->time_base;
5514 52 out->start_time = st->start_time;
5515 52 out->duration = st->duration;
5516 52 out->nb_frames = st->nb_frames;
5517 52 out->discard = st->discard;
5518
5519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 av_assert0(!out_sti->index_entries);
5520 52 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (!out_sti->index_entries)
5522 ✗ return AVERROR(ENOMEM);
5523
5524 52 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5525 52 out_sti->nb_index_entries = sti->nb_index_entries;
5526 52 out_sti->skip_samples = sti->skip_samples;
5527 52 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5528 }
5529 }
5530
5531 12 return 0;
5532 }
5533 #endif
5534
5535 772 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5536 {
5537
4/6
✓ Branch 0 taken 742 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 742 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 742 times.
✗ Branch 5 not taken.
772 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5538
3/4
✓ Branch 0 taken 465 times.
✓ Branch 1 taken 277 times.
✓ Branch 2 taken 465 times.
✗ Branch 3 not taken.
742 (!sc->sample_size && !sc->sample_count))) ||
5539
3/4
✓ Branch 0 taken 742 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 742 times.
✗ Branch 3 not taken.
772 (sc->sample_count && (!sc->chunk_count ||
5540
3/4
✓ Branch 0 taken 465 times.
✓ Branch 1 taken 277 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 465 times.
742 (!sc->sample_size && !sc->sample_sizes)))) {
5541 ✗ av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5542 index);
5543 ✗ return 1;
5544 }
5545
5546
3/4
✓ Branch 0 taken 742 times.
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 742 times.
772 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
5547 ✗ av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5548 index);
5549 ✗ return 2;
5550 }
5551 772 return 0;
5552 }
5553
5554 729 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5555 {
5556 AVStream *st;
5557 MOVStreamContext *sc;
5558 int ret;
5559
5560 729 st = avformat_new_stream(c->fc, NULL);
5561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 if (!st) return AVERROR(ENOMEM);
5562 729 st->id = -1;
5563 729 sc = av_mallocz(sizeof(MOVStreamContext));
5564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 if (!sc) return AVERROR(ENOMEM);
5565
5566 729 st->priv_data = sc;
5567 729 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5568 729 sc->ffindex = st->index;
5569 729 c->trak_index = st->index;
5570 729 sc->refcount = 1;
5571
5572
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 729 times.
729 if ((ret = mov_read_default(c, pb, atom)) < 0)
5573 ✗ return ret;
5574
5575 729 c->trak_index = -1;
5576
5577 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5578 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5579
5/6
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 699 times.
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 29 times.
729 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
5580 1 sc->stsc_count = 0;
5581 1 av_freep(&sc->stsc_data);
5582 }
5583
5584 729 ret = sanity_checks(c->fc, sc, st->index);
5585
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 if (ret)
5586 ✗ return ret > 1 ? AVERROR_INVALIDDATA : 0;
5587
5588 729 fix_timescale(c, sc);
5589
5590 729 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5591
5592 /*
5593 * Advanced edit list support does not work with fragemented MP4s, which
5594 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5595 * In these files, trun atoms may be streamed in.
5596 */
5597
4/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 699 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 9 times.
729 if (!sc->stts_count && c->advanced_editlist) {
5598
5599 21 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5600 "MP4. disabling.\n");
5601 21 c->advanced_editlist = 0;
5602 21 c->advanced_editlist_autodisabled = 1;
5603 }
5604
5605 729 mov_build_index(c, st);
5606 /*
5607 * Fragment samples are appended later by mov_read_trun() and are not
5608 * covered by this non-fragmented track update.
5609 */
5610 729 mov_update_sample_durations(c, st);
5611
5612 #if CONFIG_IAMFDEC
5613
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 717 times.
729 if (sc->iamf) {
5614 12 ret = mov_update_iamf_streams(c, st);
5615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
5616 ✗ return ret;
5617 }
5618 #endif
5619
5620
3/4
✓ Branch 0 taken 728 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 728 times.
729 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
5621 ✗ MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5622 ✗ if (c->enable_drefs) {
5623 ✗ if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5624 ✗ av_log(c->fc, AV_LOG_ERROR,
5625 "stream %d, error opening alias: path='%s', dir='%s', "
5626 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5627 ✗ st->index, dref->path, dref->dir, dref->filename,
5628 ✗ dref->volume, dref->nlvl_from, dref->nlvl_to);
5629 } else {
5630 ✗ av_log(c->fc, AV_LOG_WARNING,
5631 "Skipped opening external track: "
5632 "stream %d, alias: path='%s', dir='%s', "
5633 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5634 "Set enable_drefs to allow this.\n",
5635 ✗ st->index, dref->path, dref->dir, dref->filename,
5636 ✗ dref->volume, dref->nlvl_from, dref->nlvl_to);
5637 }
5638 } else {
5639 729 sc->pb = c->fc->pb;
5640 729 sc->pb_is_copied = 1;
5641 }
5642
5643
2/2
✓ Branch 0 taken 373 times.
✓ Branch 1 taken 356 times.
729 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5644
3/4
✓ Branch 0 taken 355 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 355 times.
✗ Branch 3 not taken.
373 int stts_constant = sc->stts_count && sc->tts_count;
5645
3/4
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 280 times.
✓ Branch 2 taken 93 times.
✗ Branch 3 not taken.
373 if (sc->h_spacing && sc->v_spacing)
5646 93 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5647 93 sc->h_spacing, sc->v_spacing, INT_MAX);
5648
4/6
✓ Branch 0 taken 277 times.
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 277 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 277 times.
✗ Branch 5 not taken.
373 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
5649
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 &&
5650
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)) {
5651 ✗ av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5652 ✗ (int64_t)st->codecpar->height * sc->width,
5653 ✗ (int64_t)st->codecpar->width * sc->height, INT_MAX);
5654 }
5655
5656 #if FF_API_R_FRAME_RATE
5657
4/4
✓ Branch 0 taken 156109 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 155754 times.
✓ Branch 3 taken 355 times.
156127 for (unsigned int i = 1; sc->stts_count && i + 1 < sc->tts_count; i++) {
5658
2/2
✓ Branch 0 taken 153259 times.
✓ Branch 1 taken 2495 times.
155754 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5659 153259 continue;
5660 2495 stts_constant = 0;
5661 }
5662
2/2
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 37 times.
373 if (stts_constant)
5663 336 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5664 336 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5665 #endif
5666 }
5667
5668 #if CONFIG_H261_DECODER || CONFIG_H263_DECODER || CONFIG_MPEG4_DECODER
5669
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 699 times.
729 switch (st->codecpar->codec_id) {
5670 #if CONFIG_H261_DECODER
5671 30 case AV_CODEC_ID_H261:
5672 #endif
5673 #if CONFIG_H263_DECODER
5674 case AV_CODEC_ID_H263:
5675 #endif
5676 #if CONFIG_MPEG4_DECODER
5677 case AV_CODEC_ID_MPEG4:
5678 #endif
5679 30 st->codecpar->width = 0; /* let decoder init width/height */
5680 30 st->codecpar->height= 0;
5681 30 break;
5682 }
5683 #endif
5684
5685 // If the duration of the mp3 packets is not constant, then they could need a parser
5686
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 726 times.
729 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5687
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 && sc->time_scale == st->codecpar->sample_rate) {
5688 3 int stts_constant = 1;
5689
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++) {
5690
1/2
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
365 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5691 365 continue;
5692 ✗ stts_constant = 0;
5693 }
5694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!stts_constant)
5695 ✗ ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5696 }
5697 /* Do not need those anymore. */
5698 729 av_freep(&sc->chunk_offsets);
5699 729 av_freep(&sc->sample_sizes);
5700 729 av_freep(&sc->keyframes);
5701 729 av_freep(&sc->stps_data);
5702 729 av_freep(&sc->elst_data);
5703 729 av_freep(&sc->rap_group);
5704 729 av_freep(&sc->sync_group);
5705 729 av_freep(&sc->sgpd_sync);
5706
5707 729 return 0;
5708 }
5709
5710 194 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5711 {
5712 int ret;
5713 194 c->itunes_metadata = 1;
5714 194 ret = mov_read_default(c, pb, atom);
5715 194 c->itunes_metadata = 0;
5716 194 return ret;
5717 }
5718
5719 14 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5720 {
5721 uint32_t count;
5722 uint32_t i;
5723
5724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (atom.size < 8)
5725 ✗ return 0;
5726
5727 14 avio_skip(pb, 4);
5728 14 count = avio_rb32(pb);
5729 14 atom.size -= 8;
5730
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
14 if (count > atom.size / 8 || count >= UINT_MAX / sizeof(*c->meta_keys)) {
5731 ✗ av_log(c->fc, AV_LOG_ERROR,
5732 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5733 ✗ return AVERROR_INVALIDDATA;
5734 }
5735
5736 14 c->meta_keys = av_malloc_array(count + 1, sizeof(*c->meta_keys));
5737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!c->meta_keys)
5738 ✗ return AVERROR(ENOMEM);
5739
5740 14 c->meta_keys[0] = NULL;
5741 14 c->meta_keys_count = 1;
5742
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 14 times.
114 for (i = 1; i <= count; ++i) {
5743 100 uint32_t key_size = avio_rb32(pb);
5744 100 uint32_t type = avio_rl32(pb);
5745 100 c->meta_keys[i] = NULL;
5746 100 c->meta_keys_count = i + 1;
5747
2/4
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 100 times.
100 if (key_size < 8 || key_size > atom.size) {
5748 ✗ av_log(c->fc, AV_LOG_ERROR,
5749 "The key# %"PRIu32" in meta has invalid size:"
5750 "%"PRIu32"\n", i, key_size);
5751 ✗ return AVERROR_INVALIDDATA;
5752 }
5753 100 atom.size -= key_size;
5754 100 key_size -= 8;
5755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (type != MKTAG('m','d','t','a')) {
5756 ✗ avio_skip(pb, key_size);
5757 ✗ continue;
5758 }
5759 100 c->meta_keys[i] = av_malloc(key_size + 1);
5760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (!c->meta_keys[i])
5761 ✗ return AVERROR(ENOMEM);
5762 100 int ret = ffio_read_size(pb, c->meta_keys[i], key_size);
5763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (ret < 0)
5764 ✗ return ret;
5765 100 c->meta_keys[i][key_size] = 0;
5766 }
5767
5768 14 return 0;
5769 }
5770
5771 80 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5772 {
5773 80 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5774 80 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5775 int i;
5776 80 int ret = 0;
5777 AVStream *st;
5778
5779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (c->fc->nb_streams < 1)
5780 ✗ return 0;
5781 80 st = c->fc->streams[c->fc->nb_streams-1];
5782
5783
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 80 times.
320 for (i = 0; i < 3; i++) {
5784 uint8_t **p;
5785 uint32_t len, tag;
5786
5787
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 240 times.
240 if (end - avio_tell(pb) <= 12)
5788 ✗ break;
5789
5790 240 len = avio_rb32(pb);
5791 240 tag = avio_rl32(pb);
5792 240 avio_skip(pb, 4); // flags
5793
5794
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))
5795 break;
5796 240 len -= 12;
5797
5798
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 160 times.
240 if (tag == MKTAG('m', 'e', 'a', 'n'))
5799 80 p = &mean;
5800
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 80 times.
160 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5801 80 p = &key;
5802
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) {
5803 80 avio_skip(pb, 4);
5804 80 len -= 4;
5805 80 p = &val;
5806 } else
5807 break;
5808
5809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (*p)
5810 ✗ break;
5811
5812 240 *p = av_malloc(len + 1);
5813
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (!*p) {
5814 ✗ ret = AVERROR(ENOMEM);
5815 ✗ break;
5816 }
5817 240 ret = ffio_read_size(pb, *p, len);
5818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (ret < 0) {
5819 ✗ av_freep(p);
5820 ✗ break;
5821 }
5822 240 (*p)[len] = 0;
5823 }
5824
5825
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) {
5826
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 38 times.
80 if (strcmp(key, "iTunSMPB") == 0) {
5827 int64_t priming, remainder, samples;
5828
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 if (ff_itunes_parse_smpb(val, &priming, &remainder, &samples) >= 0) {
5829
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)
5830 42 st->codecpar->initial_padding = priming = av_rescale_q(priming, st->time_base,
5831 42 (AVRational){ 1, st->codecpar->sample_rate });
5832
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 if (remainder > 0) {
5833 42 int64_t duration = av_rescale_q(st->duration, st->time_base,
5834 42 (AVRational){ 1, st->codecpar->sample_rate });
5835 42 remainder = av_rescale_q(remainder, st->time_base,
5836 42 (AVRational){ 1, st->codecpar->sample_rate });
5837 42 samples = av_rescale_q(samples, st->time_base,
5838 42 (AVRational){ 1, st->codecpar->sample_rate });
5839
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) {
5840 42 ffstream(st)->first_discard_sample = duration - remainder;
5841 42 ffstream(st)->last_discard_sample = duration;
5842 }
5843 }
5844 42 av_log(c->fc, AV_LOG_DEBUG, "Parsed iTunSMPB: priming %"PRId64", "
5845 "remainder %"PRId64" samples %"PRId64"\n",
5846 priming, remainder, samples);
5847 }
5848 }
5849
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 if (strcmp(mean, "com.apple.iTunes") == 0 &&
5850
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 78 times.
80 strcmp(key, "DISCSUBTITLE") == 0) {
5851 2 av_dict_set(&c->fc->metadata, "disc_subtitle", val,
5852 AV_DICT_DONT_STRDUP_VAL);
5853 2 val = NULL;
5854 }
5855
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 10 times.
150 if (strcmp(key, "cdec") != 0) {
5856 70 av_dict_set(&c->fc->metadata, key, val,
5857 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5858 70 key = val = NULL;
5859 }
5860 } else {
5861 ✗ av_log(c->fc, AV_LOG_VERBOSE,
5862 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5863 }
5864
5865 80 avio_seek(pb, end, SEEK_SET);
5866 80 av_freep(&key);
5867 80 av_freep(&val);
5868 80 av_freep(&mean);
5869 80 return ret;
5870 }
5871
5872 43 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5873 {
5874 MOVStreamContext *sc;
5875 AVStream *st;
5876
5877 43 st = avformat_new_stream(c->fc, NULL);
5878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st)
5879 ✗ return AVERROR(ENOMEM);
5880 43 sc = av_mallocz(sizeof(MOVStreamContext));
5881
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc)
5882 ✗ goto fail;
5883
5884 43 item->st = st;
5885 43 st->id = item->item_id;
5886 43 st->priv_data = sc;
5887 43 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5888 43 st->codecpar->codec_id = mov_codec_id(st, item->type);
5889 43 sc->id = st->id;
5890 43 sc->ffindex = st->index;
5891 43 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5892 43 st->time_base.num = st->time_base.den = 1;
5893 43 st->nb_frames = 1;
5894 43 sc->time_scale = 1;
5895 43 sc->pb = c->fc->pb;
5896 43 sc->pb_is_copied = 1;
5897 43 sc->refcount = 1;
5898
5899
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (item->name)
5900 43 av_dict_set(&st->metadata, "title", item->name, 0);
5901
5902 // Populate the necessary fields used by mov_build_index.
5903 43 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->stsc_data)
5905 ✗ goto fail;
5906 43 sc->stsc_count = 1;
5907 43 sc->stsc_data[0].first = 1;
5908 43 sc->stsc_data[0].count = 1;
5909 43 sc->stsc_data[0].id = 1;
5910 43 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->chunk_offsets)
5912 ✗ goto fail;
5913 43 sc->chunk_count = 1;
5914 43 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->stts_data)
5916 ✗ goto fail;
5917 43 sc->stts_count = 1;
5918 43 sc->stts_data[0].count = 1;
5919 // Not used for still images. But needed by mov_build_index.
5920 43 sc->stts_data[0].duration = 0;
5921
5922 43 return 0;
5923 ✗ fail:
5924 ✗ mov_free_stream_context(c->fc, st);
5925 ✗ ff_remove_stream(c->fc, st);
5926 ✗ item->st = NULL;
5927
5928 ✗ return AVERROR(ENOMEM);
5929 }
5930
5931 216 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5932 {
5933
1/2
✓ Branch 0 taken 628 times.
✗ Branch 1 not taken.
628 while (atom.size > 8) {
5934 uint32_t tag;
5935
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 628 times.
628 if (avio_feof(pb))
5936 ✗ return AVERROR_EOF;
5937 628 tag = avio_rl32(pb);
5938 628 atom.size -= 4;
5939
2/2
✓ Branch 0 taken 216 times.
✓ Branch 1 taken 412 times.
628 if (tag == MKTAG('h','d','l','r')) {
5940 216 avio_seek(pb, -8, SEEK_CUR);
5941 216 atom.size += 8;
5942 216 return mov_read_default(c, pb, atom);
5943 }
5944 }
5945 ✗ return 0;
5946 }
5947
5948 // return 1 when matrix is identity, 0 otherwise
5949 #define IS_MATRIX_IDENT(matrix) \
5950 ( (matrix)[0][0] == (1 << 16) && \
5951 (matrix)[1][1] == (1 << 16) && \
5952 (matrix)[2][2] == (1 << 30) && \
5953 !(matrix)[0][1] && !(matrix)[0][2] && \
5954 !(matrix)[1][0] && !(matrix)[1][2] && \
5955 !(matrix)[2][0] && !(matrix)[2][1])
5956
5957 729 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5958 {
5959 int i, j, e;
5960 int width;
5961 int height;
5962 int display_matrix[3][3];
5963 729 int res_display_matrix[3][3] = { { 0 } };
5964 AVStream *st;
5965 MOVStreamContext *sc;
5966 int version;
5967 int flags;
5968
5969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 if (c->fc->nb_streams < 1)
5970 ✗ return 0;
5971 729 st = c->fc->streams[c->fc->nb_streams-1];
5972 729 sc = st->priv_data;
5973
5974 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5975 // avoids corrupting AVStreams mapped to an earlier tkhd.
5976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 if (st->id != -1)
5977 ✗ return AVERROR_INVALIDDATA;
5978
5979 729 version = avio_r8(pb);
5980 729 flags = avio_rb24(pb);
5981 729 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5982
5983
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 716 times.
729 if (version == 1) {
5984 13 avio_rb64(pb);
5985 13 avio_rb64(pb);
5986 } else {
5987 716 avio_rb32(pb); /* creation time */
5988 716 avio_rb32(pb); /* modification time */
5989 }
5990 729 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5991 729 sc->id = st->id;
5992 729 avio_rb32(pb); /* reserved */
5993
5994 /* highlevel (considering edits) duration in movie timebase */
5995
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 716 times.
729 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5996 729 avio_rb32(pb); /* reserved */
5997 729 avio_rb32(pb); /* reserved */
5998
5999 729 avio_rb16(pb); /* layer */
6000 729 avio_rb16(pb); /* alternate group */
6001 729 avio_rb16(pb); /* volume */
6002 729 avio_rb16(pb); /* reserved */
6003
6004 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
6005 // they're kept in fixed point format through all calculations
6006 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
6007 // side data, but the scale factor is not needed to calculate aspect ratio
6008
2/2
✓ Branch 0 taken 2187 times.
✓ Branch 1 taken 729 times.
2916 for (i = 0; i < 3; i++) {
6009 2187 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
6010 2187 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
6011 2187 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
6012 }
6013
6014 729 width = avio_rb32(pb); // 16.16 fixed point track width
6015 729 height = avio_rb32(pb); // 16.16 fixed point track height
6016 729 sc->width = width >> 16;
6017 729 sc->height = height >> 16;
6018
6019 // apply the moov display matrix (after the tkhd one)
6020
2/2
✓ Branch 0 taken 2187 times.
✓ Branch 1 taken 729 times.
2916 for (i = 0; i < 3; i++) {
6021 2187 const int sh[3] = { 16, 16, 30 };
6022
2/2
✓ Branch 0 taken 6561 times.
✓ Branch 1 taken 2187 times.
8748 for (j = 0; j < 3; j++) {
6023
2/2
✓ Branch 0 taken 19683 times.
✓ Branch 1 taken 6561 times.
26244 for (e = 0; e < 3; e++) {
6024 19683 res_display_matrix[i][j] +=
6025 19683 ((int64_t) display_matrix[i][e] *
6026 19683 c->movie_display_matrix[e][j]) >> sh[e];
6027 }
6028 }
6029 }
6030
6031 // save the matrix when it is not the default identity
6032
10/18
✓ Branch 0 taken 720 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 720 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 720 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 720 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 720 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 720 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 720 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 720 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 720 times.
729 if (!IS_MATRIX_IDENT(res_display_matrix)) {
6033 9 av_freep(&sc->display_matrix);
6034 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
6035
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
6036 ✗ return AVERROR(ENOMEM);
6037
6038
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
6039
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
6040 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
6041 }
6042
6043 // transform the display width/height according to the matrix
6044 // to keep the same scale, use [width height 1<<16]
6045
5/6
✓ Branch 0 taken 392 times.
✓ Branch 1 taken 337 times.
✓ Branch 2 taken 392 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 384 times.
729 if (width && height && sc->display_matrix) {
6046 double disp_transform[2];
6047
6048
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
6049 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
6050 16 sc->display_matrix[3 + i]);
6051
6052
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 &&
6053
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) &&
6054
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
6055 3 st->sample_aspect_ratio = av_d2q(
6056 3 disp_transform[0] / disp_transform[1],
6057 INT_MAX);
6058 }
6059 729 return 0;
6060 }
6061
6062 501 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6063 {
6064 501 MOVFragment *frag = &c->fragment;
6065 501 MOVTrackExt *trex = NULL;
6066 int flags, track_id, i;
6067 MOVFragmentStreamInfo * frag_stream_info;
6068
6069 501 avio_r8(pb); /* version */
6070 501 flags = avio_rb24(pb);
6071
6072 501 track_id = avio_rb32(pb);
6073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!track_id)
6074 ✗ return AVERROR_INVALIDDATA;
6075
1/2
✓ Branch 0 taken 560 times.
✗ Branch 1 not taken.
560 for (i = 0; i < c->trex_count; i++)
6076
2/2
✓ Branch 0 taken 501 times.
✓ Branch 1 taken 59 times.
560 if (c->trex_data[i].track_id == track_id) {
6077 501 trex = &c->trex_data[i];
6078 501 break;
6079 }
6080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!trex) {
6081 ✗ av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
6082 ✗ return 0;
6083 }
6084 501 c->fragment.found_tfhd = 1;
6085 501 frag->track_id = track_id;
6086 501 set_frag_stream(&c->frag_index, track_id);
6087
6088 1002 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
6089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
1002 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
6090
2/2
✓ Branch 0 taken 428 times.
✓ Branch 1 taken 73 times.
501 frag->moof_offset : frag->implicit_offset;
6091
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;
6092
6093 1002 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
6094
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 435 times.
501 avio_rb32(pb) : trex->duration;
6095 1002 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
6096
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 440 times.
501 avio_rb32(pb) : trex->size;
6097 1002 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
6098
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 366 times.
501 avio_rb32(pb) : trex->flags;
6099 501 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
6100
6101 501 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6102
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (frag_stream_info) {
6103 501 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
6104 501 frag_stream_info->stsd_id = frag->stsd_id;
6105 }
6106 501 return 0;
6107 }
6108
6109 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6110 {
6111 unsigned i, num;
6112 void *new_tracks;
6113
6114 2 num = atom.size / 4;
6115
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
6116 ✗ return AVERROR(ENOMEM);
6117
6118 2 av_free(c->chapter_tracks);
6119 2 c->chapter_tracks = new_tracks;
6120 2 c->nb_chapter_tracks = num;
6121
6122
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++)
6123 2 c->chapter_tracks[i] = avio_rb32(pb);
6124
6125 2 c->nb_chapter_tracks = i;
6126
6127 2 return 0;
6128 }
6129
6130 29 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6131 {
6132 MOVTrackExt *trex;
6133 int err;
6134
6135
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))
6136 ✗ return AVERROR_INVALIDDATA;
6137
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
6138 sizeof(*c->trex_data))) < 0) {
6139 ✗ c->trex_count = 0;
6140 ✗ return err;
6141 }
6142
6143 29 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
6144
6145 29 trex = &c->trex_data[c->trex_count++];
6146 29 avio_r8(pb); /* version */
6147 29 avio_rb24(pb); /* flags */
6148 29 trex->track_id = avio_rb32(pb);
6149 29 trex->stsd_id = avio_rb32(pb);
6150 29 trex->duration = avio_rb32(pb);
6151 29 trex->size = avio_rb32(pb);
6152 29 trex->flags = avio_rb32(pb);
6153 29 return 0;
6154 }
6155
6156 428 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6157 {
6158 428 MOVFragment *frag = &c->fragment;
6159 428 AVStream *st = NULL;
6160 MOVStreamContext *sc;
6161 int version, i;
6162 MOVFragmentStreamInfo * frag_stream_info;
6163 int64_t base_media_decode_time;
6164
6165
1/2
✓ Branch 0 taken 455 times.
✗ Branch 1 not taken.
455 for (i = 0; i < c->fc->nb_streams; i++) {
6166 455 sc = c->fc->streams[i]->priv_data;
6167
2/2
✓ Branch 0 taken 428 times.
✓ Branch 1 taken 27 times.
455 if (sc->id == frag->track_id) {
6168 428 st = c->fc->streams[i];
6169 428 break;
6170 }
6171 }
6172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 428 times.
428 if (!st) {
6173 ✗ av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
6174 ✗ return 0;
6175 }
6176 428 sc = st->priv_data;
6177
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)
6178 ✗ return 0;
6179 428 version = avio_r8(pb);
6180 428 avio_rb24(pb); /* flags */
6181
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 370 times.
428 if (version) {
6182 58 base_media_decode_time = avio_rb64(pb);
6183 } else {
6184 370 base_media_decode_time = avio_rb32(pb);
6185 }
6186
6187 428 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6188
1/2
✓ Branch 0 taken 428 times.
✗ Branch 1 not taken.
428 if (frag_stream_info)
6189 428 frag_stream_info->tfdt_dts = base_media_decode_time;
6190 428 sc->track_end = base_media_decode_time;
6191
6192 428 return 0;
6193 }
6194
6195 501 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6196 {
6197 501 MOVFragment *frag = &c->fragment;
6198 501 AVStream *st = NULL;
6199 501 FFStream *sti = NULL;
6200 MOVStreamContext *sc;
6201 MOVTimeToSample *tts_data;
6202 uint64_t offset;
6203 501 int64_t dts, pts = AV_NOPTS_VALUE;
6204 501 int data_offset = 0;
6205 501 unsigned entries, first_sample_flags = frag->flags;
6206 int flags, distance, i;
6207 501 int64_t prev_dts = AV_NOPTS_VALUE;
6208 501 int next_frag_index = -1, index_entry_pos;
6209 size_t requested_size;
6210 size_t old_allocated_size;
6211 AVIndexEntry *new_entries;
6212 MOVFragmentStreamInfo * frag_stream_info;
6213
6214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!frag->found_tfhd) {
6215 ✗ av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
6216 ✗ return AVERROR_INVALIDDATA;
6217 }
6218
6219
1/2
✓ Branch 0 taken 560 times.
✗ Branch 1 not taken.
560 for (i = 0; i < c->fc->nb_streams; i++) {
6220 560 sc = c->fc->streams[i]->priv_data;
6221
2/2
✓ Branch 0 taken 501 times.
✓ Branch 1 taken 59 times.
560 if (sc->id == frag->track_id) {
6222 501 st = c->fc->streams[i];
6223 501 sti = ffstream(st);
6224 501 break;
6225 }
6226 }
6227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!st) {
6228 ✗ av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
6229 ✗ return 0;
6230 }
6231 501 sc = st->priv_data;
6232
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)
6233 ✗ return 0;
6234
6235 // Find the next frag_index index that has a valid index_entry for
6236 // the current track_id.
6237 //
6238 // A valid index_entry means the trun for the fragment was read
6239 // and it's samples are in index_entries at the given position.
6240 // New index entries will be inserted before the index_entry found.
6241 501 index_entry_pos = sti->nb_index_entries;
6242
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++) {
6243 1634 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
6244
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) {
6245 ✗ next_frag_index = i;
6246 ✗ index_entry_pos = frag_stream_info->index_entry;
6247 ✗ break;
6248 }
6249 }
6250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 av_assert0(index_entry_pos <= sti->nb_index_entries);
6251
6252 501 avio_r8(pb); /* version */
6253 501 flags = avio_rb24(pb);
6254 501 entries = avio_rb32(pb);
6255 501 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
6256
6257
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))
6258 ✗ return AVERROR_INVALIDDATA;
6259
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
6260
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);
6261
6262 501 int entry_size = !!(flags & MOV_TRUN_SAMPLE_DURATION) * 4
6263 501 + !!(flags & MOV_TRUN_SAMPLE_SIZE) * 4
6264 501 + !!(flags & MOV_TRUN_SAMPLE_FLAGS) * 4
6265 501 + !!(flags & MOV_TRUN_SAMPLE_CTS) * 4;
6266 501 int64_t sample_data_size = avio_size(sc->pb);
6267 501 int64_t max_entries = INT64_MAX;
6268
6269
2/2
✓ Branch 0 taken 500 times.
✓ Branch 1 taken 1 times.
501 if (sample_data_size > 0)
6270 500 max_entries = sample_data_size - sti->nb_index_entries;
6271
2/2
✓ Branch 0 taken 475 times.
✓ Branch 1 taken 26 times.
501 if (entry_size) {
6272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 475 times.
475 int64_t size = sc->pb == pb ? sample_data_size : avio_size(pb);
6273 475 int64_t pos = avio_tell(pb);
6274 475 int64_t left = atom.size - 8 - !!(flags & MOV_TRUN_DATA_OFFSET) * 4
6275 475 - !!(flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) * 4;
6276
6277
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)
6278 474 left = FFMIN(left, size - pos);
6279 475 max_entries = FFMIN(max_entries, left / entry_size);
6280 }
6281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (entries > max_entries) {
6282 ✗ av_log(c->fc, AV_LOG_ERROR, "trun sample count %u exceeds the %"PRId64" "
6283 "samples the input can hold\n", entries, max_entries);
6284 ✗ return AVERROR_INVALIDDATA;
6285 }
6286
6287 501 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6288
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (frag_stream_info) {
6289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
6290 ✗ dts = frag_stream_info->next_trun_dts - sc->time_offset;
6291
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 498 times.
501 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
6292
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
6293 3 pts = frag_stream_info->first_tfra_pts;
6294 3 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
6295 ", using it for pts\n", pts);
6296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 498 times.
498 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
6297 ✗ c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
6298 ✗ dts = frag_stream_info->first_tfra_pts;
6299 ✗ av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
6300 ", using it for dts\n", pts);
6301 } else {
6302 498 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
6303 498 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
6304
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;
6305
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;
6306
6307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 498 times.
498 if (fallback_sidx) {
6308 ✗ av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
6309 }
6310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 498 times.
498 if (fallback_tfdt) {
6311 ✗ av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
6312 }
6313
6314
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) {
6315 425 dts = frag_stream_info->tfdt_dts - sc->time_offset;
6316 425 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
6317 ", using it for dts\n", dts);
6318
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) {
6319 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
6320 // pts = frag_stream_info->sidx_pts;
6321 ✗ dts = frag_stream_info->sidx_pts;
6322 ✗ av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
6323 ", using it for dts\n", frag_stream_info->sidx_pts);
6324 } else {
6325 73 dts = sc->track_end - sc->time_offset;
6326 73 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
6327 ", using it for dts\n", dts);
6328 }
6329 }
6330 } else {
6331 ✗ dts = sc->track_end - sc->time_offset;
6332 ✗ av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
6333 ", using it for dts\n", dts);
6334 }
6335 501 offset = frag->base_data_offset + data_offset;
6336 501 distance = 0;
6337 501 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
6338
6339 // realloc space for new index entries
6340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
6341 ✗ entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
6342 ✗ av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
6343 }
6344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (entries == 0)
6345 ✗ return 0;
6346
6347 501 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
6348 501 new_entries = av_fast_realloc(sti->index_entries,
6349 &sti->index_entries_allocated_size,
6350 requested_size);
6351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!new_entries)
6352 ✗ return AVERROR(ENOMEM);
6353 501 sti->index_entries= new_entries;
6354
6355 501 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
6356 501 old_allocated_size = sc->tts_allocated_size;
6357 501 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
6358 requested_size);
6359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (!tts_data)
6360 ✗ return AVERROR(ENOMEM);
6361 501 sc->tts_data = tts_data;
6362
6363 // In case there were samples without time to sample entries, ensure they get
6364 // zero valued entries. This ensures clips which mix boxes with and
6365 // without time to sample entries don't pickup uninitialized data.
6366 501 memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0,
6367 501 sc->tts_allocated_size - old_allocated_size);
6368
6369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (index_entry_pos < sti->nb_index_entries) {
6370 // Make hole in index_entries and tts_data for new samples
6371 ✗ memmove(sti->index_entries + index_entry_pos + entries,
6372 ✗ sti->index_entries + index_entry_pos,
6373 sizeof(*sti->index_entries) *
6374 ✗ (sti->nb_index_entries - index_entry_pos));
6375 ✗ memmove(sc->tts_data + index_entry_pos + entries,
6376 ✗ sc->tts_data + index_entry_pos,
6377 ✗ sizeof(*sc->tts_data) * (sc->tts_count - index_entry_pos));
6378 ✗ if (index_entry_pos < sc->current_sample) {
6379 ✗ sc->current_sample += entries;
6380 }
6381 }
6382
6383 501 sti->nb_index_entries += entries;
6384 501 sc->tts_count = sti->nb_index_entries;
6385 501 sc->stts_count = sti->nb_index_entries;
6386
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 115 times.
501 if (flags & MOV_TRUN_SAMPLE_CTS)
6387 386 sc->ctts_count = sti->nb_index_entries;
6388
6389 // Record the index_entry position in frag_index of this fragment
6390
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (frag_stream_info) {
6391 501 frag_stream_info->index_entry = index_entry_pos;
6392
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (frag_stream_info->index_base < 0)
6393 501 frag_stream_info->index_base = index_entry_pos;
6394 }
6395
6396
2/2
✓ Branch 0 taken 473 times.
✓ Branch 1 taken 28 times.
501 if (index_entry_pos > 0)
6397 473 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6398
6399
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++) {
6400 8717 unsigned sample_size = frag->size;
6401
2/2
✓ Branch 0 taken 8216 times.
✓ Branch 1 taken 501 times.
8717 int sample_flags = i ? frag->flags : first_sample_flags;
6402 8717 unsigned sample_duration = frag->duration;
6403 8717 unsigned ctts_duration = 0;
6404 8717 int keyframe = 0;
6405 8717 int index_entry_flags = 0;
6406
6407
2/2
✓ Branch 0 taken 1684 times.
✓ Branch 1 taken 7033 times.
8717 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
6408
2/2
✓ Branch 0 taken 8659 times.
✓ Branch 1 taken 58 times.
8717 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
6409
2/2
✓ Branch 0 taken 981 times.
✓ Branch 1 taken 7736 times.
8717 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
6410
2/2
✓ Branch 0 taken 6576 times.
✓ Branch 1 taken 2141 times.
8717 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
6411
6412
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8716 times.
8717 if (sample_duration > c->max_stts_delta) {
6413 1 av_log(c->fc, AV_LOG_WARNING,
6414 "Too large sample duration %u in trun entry %u in st:%d. Clipping to 1.\n",
6415 sample_duration, i, st->index);
6416 1 sample_duration = 1;
6417 }
6418
6419 8717 mov_update_dts_shift(sc, ctts_duration, c->fc);
6420
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8714 times.
8717 if (pts != AV_NOPTS_VALUE) {
6421 3 dts = pts - sc->dts_shift;
6422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (flags & MOV_TRUN_SAMPLE_CTS) {
6423 ✗ dts -= ctts_duration;
6424 } else {
6425 3 dts -= sc->time_offset;
6426 }
6427 3 av_log(c->fc, AV_LOG_DEBUG,
6428 "pts %"PRId64" calculated dts %"PRId64
6429 " sc->dts_shift %d ctts.duration %d"
6430 " sc->time_offset %"PRId64
6431 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
6432 pts, dts,
6433 sc->dts_shift, ctts_duration,
6434 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
6435 3 pts = AV_NOPTS_VALUE;
6436 }
6437
6438 8717 keyframe =
6439 8717 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
6440 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
6441
2/2
✓ Branch 0 taken 648 times.
✓ Branch 1 taken 8069 times.
8717 if (keyframe) {
6442 648 distance = 0;
6443 648 index_entry_flags |= AVINDEX_KEYFRAME;
6444 }
6445 // Fragments can overlap in time. Discard overlapping frames after
6446 // decoding.
6447
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8693 times.
8717 if (prev_dts >= dts)
6448 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
6449
6450 8717 sti->index_entries[index_entry_pos].pos = offset;
6451 8717 sti->index_entries[index_entry_pos].timestamp = dts;
6452 8717 sti->index_entries[index_entry_pos].size = sample_size;
6453 8717 sti->index_entries[index_entry_pos].min_distance = distance;
6454 8717 sti->index_entries[index_entry_pos].flags = index_entry_flags;
6455
6456 8717 sc->tts_data[index_entry_pos].count = 1;
6457 8717 sc->tts_data[index_entry_pos].offset = ctts_duration;
6458 8717 sc->tts_data[index_entry_pos].duration = sample_duration;
6459 8717 index_entry_pos++;
6460
6461 8717 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
6462 "size %u, distance %d, keyframe %d\n", st->index,
6463 index_entry_pos, offset, dts, sample_size, distance, keyframe);
6464 8717 distance++;
6465
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8717 times.
8717 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
6466 ✗ return AVERROR_INVALIDDATA;
6467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8717 times.
8717 if (!sample_size)
6468 ✗ return AVERROR_INVALIDDATA;
6469 8717 dts += sample_duration;
6470 8717 offset += sample_size;
6471 8717 sc->data_size += sample_size;
6472
6473
1/2
✓ Branch 0 taken 8717 times.
✗ Branch 1 not taken.
8717 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
6474
1/2
✓ Branch 0 taken 8717 times.
✗ Branch 1 not taken.
8717 1 <= INT_MAX - sc->nb_frames_for_fps
6475 ) {
6476 8717 sc->duration_for_fps += sample_duration;
6477 8717 sc->nb_frames_for_fps ++;
6478 }
6479 }
6480
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (frag_stream_info)
6481 501 frag_stream_info->next_trun_dts = dts + sc->time_offset;
6482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (i < entries) {
6483 // EOF found before reading all entries. Fix the hole this would
6484 // leave in index_entries and tts_data
6485 ✗ int gap = entries - i;
6486 ✗ memmove(sti->index_entries + index_entry_pos,
6487 ✗ sti->index_entries + index_entry_pos + gap,
6488 sizeof(*sti->index_entries) *
6489 ✗ (sti->nb_index_entries - (index_entry_pos + gap)));
6490 ✗ memmove(sc->tts_data + index_entry_pos,
6491 ✗ sc->tts_data + index_entry_pos + gap,
6492 sizeof(*sc->tts_data) *
6493 ✗ (sc->tts_count - (index_entry_pos + gap)));
6494
6495 ✗ sti->nb_index_entries -= gap;
6496 ✗ sc->tts_count -= gap;
6497 ✗ if (index_entry_pos < sc->current_sample) {
6498 ✗ sc->current_sample -= gap;
6499 }
6500 ✗ entries = i;
6501 }
6502
6503 // The end of this new fragment may overlap in time with the start
6504 // of the next fragment in index_entries. Mark the samples in the next
6505 // fragment that overlap with AVINDEX_DISCARD_FRAME
6506 501 prev_dts = AV_NOPTS_VALUE;
6507
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (index_entry_pos > 0)
6508 501 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
6510 ✗ if (prev_dts < sti->index_entries[i].timestamp)
6511 ✗ break;
6512 ✗ sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6513 }
6514
6515 // If a hole was created to insert the new index_entries into,
6516 // the index_entry recorded for all subsequent moof must
6517 // be incremented by the number of entries inserted.
6518 501 fix_frag_index_entries(&c->frag_index, next_frag_index,
6519 501 frag->track_id, entries);
6520
6521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 if (pb->eof_reached) {
6522 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6523 ✗ return AVERROR_EOF;
6524 }
6525
6526 501 frag->implicit_offset = offset;
6527
6528 501 sc->track_end = dts + sc->time_offset;
6529
2/2
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 383 times.
501 if (st->duration < sc->track_end)
6530 118 st->duration = sc->track_end;
6531
6532 501 return 0;
6533 }
6534
6535 46 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6536 {
6537 46 int64_t stream_size = avio_size(pb);
6538 46 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6539 uint8_t version, is_complete;
6540 int64_t offadd;
6541 unsigned i, j, track_id, item_count;
6542 46 AVStream *st = NULL;
6543 46 AVStream *ref_st = NULL;
6544 46 MOVStreamContext *sc, *ref_sc = NULL;
6545 AVRational timescale;
6546
6547 46 version = avio_r8(pb);
6548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (version > 1) {
6549 ✗ avpriv_request_sample(c->fc, "sidx version %u", version);
6550 ✗ return 0;
6551 }
6552
6553 46 avio_rb24(pb); // flags
6554
6555 46 track_id = avio_rb32(pb); // Reference ID
6556
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 for (i = 0; i < c->fc->nb_streams; i++) {
6557 46 sc = c->fc->streams[i]->priv_data;
6558
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 if (sc->id == track_id) {
6559 46 st = c->fc->streams[i];
6560 46 break;
6561 }
6562 }
6563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!st) {
6564 ✗ av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6565 ✗ return 0;
6566 }
6567
6568 46 sc = st->priv_data;
6569
6570 46 timescale = av_make_q(1, avio_rb32(pb));
6571
6572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (timescale.den <= 0) {
6573 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6574 ✗ return AVERROR_INVALIDDATA;
6575 }
6576
6577
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1 times.
46 if (version == 0) {
6578 45 pts = avio_rb32(pb);
6579 45 offadd= avio_rb32(pb);
6580 } else {
6581 1 pts = avio_rb64(pb);
6582 1 offadd= avio_rb64(pb);
6583 }
6584
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6585 ✗ return AVERROR_INVALIDDATA;
6586
6587 46 offset += (uint64_t)offadd;
6588
6589 46 avio_rb16(pb); // reserved
6590
6591 46 item_count = avio_rb16(pb);
6592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (item_count == 0)
6593 ✗ return AVERROR_INVALIDDATA;
6594
6595
2/2
✓ Branch 0 taken 372 times.
✓ Branch 1 taken 46 times.
418 for (i = 0; i < item_count; i++) {
6596 int index;
6597 MOVFragmentStreamInfo * frag_stream_info;
6598 372 uint32_t size = avio_rb32(pb);
6599 372 uint32_t duration = avio_rb32(pb);
6600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
372 if (size & 0x80000000) {
6601 ✗ avpriv_request_sample(c->fc, "sidx reference_type 1");
6602 ✗ return AVERROR_PATCHWELCOME;
6603 }
6604 372 avio_rb32(pb); // sap_flags
6605 372 timestamp = av_rescale_q(pts, timescale, st->time_base);
6606
6607 372 index = update_frag_index(c, offset);
6608 372 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6609
1/2
✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
372 if (frag_stream_info)
6610 372 frag_stream_info->sidx_pts = timestamp;
6611
6612
1/2
✓ Branch 1 taken 372 times.
✗ Branch 2 not taken.
372 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6613
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 372 times.
372 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6614 )
6615 ✗ return AVERROR_INVALIDDATA;
6616 372 offset += size;
6617 372 pts += duration;
6618 }
6619
6620 46 st->duration = sc->track_end = pts;
6621
6622 46 sc->has_sidx = 1;
6623
6624 // See if the remaining bytes are just an mfra which we can ignore.
6625 46 is_complete = offset == stream_size;
6626
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 ) {
6627 int64_t ret;
6628 38 int64_t original_pos = avio_tell(pb);
6629
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
38 if (!c->have_read_mfra_size) {
6630
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6631 ✗ return ret;
6632 3 c->mfra_size = avio_rb32(pb);
6633 3 c->have_read_mfra_size = 1;
6634
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6635 ✗ return ret;
6636 }
6637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (offset == stream_size - c->mfra_size)
6638 ✗ is_complete = 1;
6639 }
6640
6641
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 39 times.
46 if (is_complete) {
6642 // Find first entry in fragment index that came from an sidx.
6643 // This will pretty much always be the first entry.
6644
2/2
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 7 times.
378 for (i = 0; i < c->frag_index.nb_items; i++) {
6645 371 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6646
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++) {
6647 MOVFragmentStreamInfo * si;
6648 7 si = &item->stream_info[j];
6649
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (si->sidx_pts != AV_NOPTS_VALUE) {
6650 7 ref_st = c->fc->streams[j];
6651 7 ref_sc = ref_st->priv_data;
6652 7 break;
6653 }
6654 }
6655 }
6656
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++) {
6657 7 st = c->fc->streams[i];
6658 7 sc = st->priv_data;
6659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sc->has_sidx) {
6660 ✗ st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6661 }
6662 }
6663
6664
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (offadd == 0)
6665 7 c->frag_index.complete = 1;
6666 }
6667
6668 46 return 0;
6669 }
6670
6671 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6672 /* like the files created with Adobe Premiere 5.0, for samples see */
6673 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6674 299 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6675 {
6676 int err;
6677
6678
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 if (atom.size < 8)
6679 299 return 0; /* continue */
6680 ✗ if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6681 ✗ avio_skip(pb, atom.size - 4);
6682 ✗ return 0;
6683 }
6684 ✗ atom.type = avio_rl32(pb);
6685 ✗ atom.size -= 8;
6686 ✗ if (atom.type != MKTAG('m','d','a','t')) {
6687 ✗ avio_skip(pb, atom.size);
6688 ✗ return 0;
6689 }
6690 ✗ err = mov_read_mdat(c, pb, atom);
6691 ✗ return err;
6692 }
6693
6694 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6695 {
6696 #if CONFIG_ZLIB
6697 FFIOContext ctx;
6698 uint8_t *cmov_data;
6699 uint8_t *moov_data; /* uncompressed data */
6700 long cmov_len, moov_len;
6701 3 int ret = -1;
6702
6703 3 avio_rb32(pb); /* dcom atom */
6704
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6705 ✗ return AVERROR_INVALIDDATA;
6706
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6707 ✗ av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6708 ✗ return AVERROR_INVALIDDATA;
6709 }
6710 3 avio_rb32(pb); /* cmvd atom */
6711
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6712 ✗ return AVERROR_INVALIDDATA;
6713 3 moov_len = avio_rb32(pb); /* uncompressed size */
6714 3 cmov_len = atom.size - 6 * 4;
6715
6716 3 cmov_data = av_malloc(cmov_len);
6717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6718 ✗ return AVERROR(ENOMEM);
6719 3 moov_data = av_malloc(moov_len);
6720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6721 ✗ av_free(cmov_data);
6722 ✗ return AVERROR(ENOMEM);
6723 }
6724 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6726 ✗ goto free_and_return;
6727
6728 3 ret = AVERROR_INVALIDDATA;
6729
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)
6730 ✗ goto free_and_return;
6731 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6732 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6733 3 atom.type = MKTAG('m','o','o','v');
6734 3 atom.size = moov_len;
6735 3 ret = mov_read_default(c, &ctx.pub, atom);
6736 3 free_and_return:
6737 3 av_free(moov_data);
6738 3 av_free(cmov_data);
6739 3 return ret;
6740 #else
6741 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6742 return AVERROR(ENOSYS);
6743 #endif
6744 }
6745
6746 /* edit list atom */
6747 544 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6748 {
6749 MOVStreamContext *sc;
6750 int i, edit_count, version;
6751 int64_t elst_entry_size;
6752
6753
2/4
✓ Branch 0 taken 544 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 544 times.
544 if (c->fc->nb_streams < 1 || c->ignore_editlist)
6754 ✗ return 0;
6755 544 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6756
6757 544 version = avio_r8(pb); /* version */
6758 544 avio_rb24(pb); /* flags */
6759 544 edit_count = avio_rb32(pb); /* entries */
6760 544 atom.size -= 8;
6761
6762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 544 times.
544 elst_entry_size = version == 1 ? 20 : 12;
6763
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 543 times.
544 if (atom.size != edit_count * elst_entry_size) {
6764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6765 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6766 ✗ edit_count, atom.size + 8);
6767 ✗ return AVERROR_INVALIDDATA;
6768 } else {
6769 1 edit_count = atom.size / elst_entry_size;
6770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6771 ✗ av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6772 }
6773 }
6774 }
6775
6776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 544 times.
544 if (!edit_count)
6777 ✗ return 0;
6778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 544 times.
544 if (sc->elst_data)
6779 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6780 544 av_free(sc->elst_data);
6781 544 sc->elst_count = 0;
6782 544 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 544 times.
544 if (!sc->elst_data)
6784 ✗ return AVERROR(ENOMEM);
6785
6786 544 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6787
4/6
✓ Branch 0 taken 573 times.
✓ Branch 1 taken 544 times.
✓ Branch 2 taken 573 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 573 times.
✗ Branch 5 not taken.
1117 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
6788 573 MOVElst *e = &sc->elst_data[i];
6789
6790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 573 times.
573 if (version == 1) {
6791 ✗ e->duration = avio_rb64(pb);
6792 ✗ e->time = avio_rb64(pb);
6793 ✗ atom.size -= 16;
6794 } else {
6795 573 e->duration = avio_rb32(pb); /* segment duration */
6796 573 e->time = (int32_t)avio_rb32(pb); /* media time */
6797 573 atom.size -= 8;
6798 }
6799 573 e->rate = avio_rb32(pb) / 65536.0;
6800 573 atom.size -= 4;
6801 573 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6802 573 e->duration, e->time, e->rate);
6803
6804
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 569 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
573 if (e->time < 0 && e->time != -1 &&
6805 ✗ c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6806 ✗ av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6807 ✗ c->fc->nb_streams-1, i, e->time);
6808 ✗ return AVERROR_INVALIDDATA;
6809 }
6810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 573 times.
573 if (e->duration < 0) {
6811 ✗ av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list duration=%"PRId64"\n",
6812 ✗ c->fc->nb_streams-1, i, e->duration);
6813 ✗ return AVERROR_INVALIDDATA;
6814 }
6815 }
6816 544 sc->elst_count = i;
6817
6818 544 return 0;
6819 }
6820
6821 21 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6822 {
6823 MOVStreamContext *sc;
6824 int err;
6825
6826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (c->fc->nb_streams < 1)
6827 ✗ return AVERROR_INVALIDDATA;
6828 21 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6829
6830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (atom.size % sizeof(uint32_t))
6831 ✗ return AVERROR_INVALIDDATA;
6832
6833 21 MovTref *tag = mov_add_tref_tag(sc, atom.type);
6834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!tag)
6835 ✗ return AVERROR(ENOMEM);
6836
6837 21 int nb_timecode_track = atom.size >> 2;
6838
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 21 times.
52 for (int i = 0; i < nb_timecode_track; i++) {
6839
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 if (avio_feof(pb))
6840 ✗ return AVERROR_INVALIDDATA;
6841 31 err = mov_add_tref_id(tag, avio_rb32(pb));
6842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (err < 0)
6843 ✗ return err;
6844 }
6845
6846 21 return 0;
6847 }
6848
6849 ✗ static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6850 {
6851 AVStream *st;
6852 int version, color_range, color_primaries, color_trc, color_space;
6853
6854 ✗ if (c->fc->nb_streams < 1)
6855 ✗ return 0;
6856 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
6857
6858 ✗ if (atom.size < 5) {
6859 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6860 ✗ return AVERROR_INVALIDDATA;
6861 }
6862
6863 ✗ version = avio_r8(pb);
6864 ✗ if (version != 1) {
6865 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6866 ✗ return 0;
6867 }
6868 ✗ avio_skip(pb, 3); /* flags */
6869
6870 ✗ avio_skip(pb, 2); /* profile + level */
6871 ✗ color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6872 ✗ color_primaries = avio_r8(pb);
6873 ✗ color_trc = avio_r8(pb);
6874 ✗ color_space = avio_r8(pb);
6875 ✗ if (avio_rb16(pb)) /* codecIntializationDataSize */
6876 ✗ return AVERROR_INVALIDDATA;
6877
6878 ✗ if (!av_color_primaries_name(color_primaries))
6879 ✗ color_primaries = AVCOL_PRI_UNSPECIFIED;
6880 ✗ if (!av_color_transfer_name(color_trc))
6881 ✗ color_trc = AVCOL_TRC_UNSPECIFIED;
6882 ✗ if (!av_color_space_name(color_space))
6883 ✗ color_space = AVCOL_SPC_UNSPECIFIED;
6884
6885 ✗ st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6886 ✗ st->codecpar->color_primaries = color_primaries;
6887 ✗ st->codecpar->color_trc = color_trc;
6888 ✗ st->codecpar->color_space = color_space;
6889
6890 ✗ return 0;
6891 }
6892
6893 ✗ static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6894 {
6895 MOVStreamContext *sc;
6896 int i, version;
6897
6898 ✗ if (c->fc->nb_streams < 1)
6899 ✗ return AVERROR_INVALIDDATA;
6900
6901 ✗ sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6902
6903 ✗ if (atom.size < 5) {
6904 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6905 ✗ return AVERROR_INVALIDDATA;
6906 }
6907
6908 ✗ version = avio_r8(pb);
6909 ✗ if (version) {
6910 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6911 ✗ return 0;
6912 }
6913 ✗ if (sc->mastering) {
6914 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6915 ✗ return 0;
6916 }
6917
6918 ✗ avio_skip(pb, 3); /* flags */
6919
6920 ✗ sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6921 ✗ if (!sc->mastering)
6922 ✗ return AVERROR(ENOMEM);
6923
6924 ✗ for (i = 0; i < 3; i++) {
6925 ✗ sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6926 ✗ sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6927 }
6928 ✗ sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6929 ✗ sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6930
6931 ✗ sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6932 ✗ sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6933
6934 ✗ sc->mastering->has_primaries = 1;
6935 ✗ sc->mastering->has_luminance = 1;
6936
6937 ✗ return 0;
6938 }
6939
6940 ✗ static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6941 {
6942 MOVStreamContext *sc;
6943 ✗ const int mapping[3] = {1, 2, 0};
6944 ✗ const int chroma_den = 50000;
6945 ✗ const int luma_den = 10000;
6946 int i;
6947
6948 ✗ if (c->fc->nb_streams < 1)
6949 ✗ return AVERROR_INVALIDDATA;
6950
6951 ✗ sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6952
6953 ✗ if (atom.size < 24) {
6954 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6955 ✗ return AVERROR_INVALIDDATA;
6956 }
6957
6958 ✗ if (sc->mastering) {
6959 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6960 ✗ return 0;
6961 }
6962
6963 ✗ sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6964 ✗ if (!sc->mastering)
6965 ✗ return AVERROR(ENOMEM);
6966
6967 ✗ for (i = 0; i < 3; i++) {
6968 ✗ const int j = mapping[i];
6969 ✗ sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6970 ✗ sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6971 }
6972 ✗ sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6973 ✗ sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6974
6975 ✗ sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6976 ✗ sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6977
6978 ✗ sc->mastering->has_luminance = 1;
6979 ✗ sc->mastering->has_primaries = 1;
6980
6981 ✗ return 0;
6982 }
6983
6984 ✗ static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6985 {
6986 MOVStreamContext *sc;
6987 int version;
6988
6989 ✗ if (c->fc->nb_streams < 1)
6990 ✗ return AVERROR_INVALIDDATA;
6991
6992 ✗ sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6993
6994 ✗ if (atom.size < 5) {
6995 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
6996 ✗ return AVERROR_INVALIDDATA;
6997 }
6998
6999 ✗ version = avio_r8(pb);
7000 ✗ if (version) {
7001 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
7002 ✗ return 0;
7003 }
7004 ✗ avio_skip(pb, 3); /* flags */
7005
7006 ✗ if (sc->coll){
7007 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
7008 ✗ return 0;
7009 }
7010
7011 ✗ sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
7012 ✗ if (!sc->coll)
7013 ✗ return AVERROR(ENOMEM);
7014
7015 ✗ sc->coll->MaxCLL = avio_rb16(pb);
7016 ✗ sc->coll->MaxFALL = avio_rb16(pb);
7017
7018 ✗ return 0;
7019 }
7020
7021 ✗ static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7022 {
7023 MOVStreamContext *sc;
7024
7025 ✗ if (c->fc->nb_streams < 1)
7026 ✗ return AVERROR_INVALIDDATA;
7027
7028 ✗ sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7029
7030 ✗ if (atom.size < 4) {
7031 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
7032 ✗ return AVERROR_INVALIDDATA;
7033 }
7034
7035 ✗ if (sc->coll){
7036 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
7037 ✗ return 0;
7038 }
7039
7040 ✗ sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
7041 ✗ if (!sc->coll)
7042 ✗ return AVERROR(ENOMEM);
7043
7044 ✗ sc->coll->MaxCLL = avio_rb16(pb);
7045 ✗ sc->coll->MaxFALL = avio_rb16(pb);
7046
7047 ✗ return 0;
7048 }
7049
7050 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7051 {
7052 MOVStreamContext *sc;
7053 4 const int illuminance_den = 10000;
7054 4 const int ambient_den = 50000;
7055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
7056 ✗ return AVERROR_INVALIDDATA;
7057 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7058
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
7059 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
7060 ✗ return AVERROR_INVALIDDATA;
7061 }
7062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
7063 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
7064 ✗ return 0;
7065 }
7066 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
7067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
7068 ✗ return AVERROR(ENOMEM);
7069 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
7070 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
7071 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
7072 4 return 0;
7073 }
7074
7075 3 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7076 {
7077 AVStream *st;
7078 MOVStreamContext *sc;
7079 enum AVStereo3DType type;
7080 int mode;
7081
7082
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7083 ✗ return 0;
7084
7085 3 st = c->fc->streams[c->fc->nb_streams - 1];
7086 3 sc = st->priv_data;
7087
7088
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 5) {
7089 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
7090 ✗ return AVERROR_INVALIDDATA;
7091 }
7092
7093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->stereo3d)
7094 ✗ return AVERROR_INVALIDDATA;
7095
7096 3 avio_skip(pb, 4); /* version + flags */
7097
7098 3 mode = avio_r8(pb);
7099
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
3 switch (mode) {
7100 1 case 0:
7101 1 type = AV_STEREO3D_2D;
7102 1 break;
7103 ✗ case 1:
7104 ✗ type = AV_STEREO3D_TOPBOTTOM;
7105 ✗ break;
7106 2 case 2:
7107 2 type = AV_STEREO3D_SIDEBYSIDE;
7108 2 break;
7109 ✗ default:
7110 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
7111 ✗ return 0;
7112 }
7113
7114 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7116 ✗ return AVERROR(ENOMEM);
7117
7118 3 sc->stereo3d->type = type;
7119 3 return 0;
7120 }
7121
7122 ✗ static int mov_read_pack(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7123 {
7124 AVStream *st;
7125 MOVStreamContext *sc;
7126 ✗ int size = 0;
7127 int64_t remaining;
7128 ✗ uint32_t tag = 0;
7129 ✗ enum AVStereo3DType type = AV_STEREO3D_2D;
7130
7131 ✗ if (c->fc->nb_streams < 1)
7132 ✗ return 0;
7133
7134 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
7135 ✗ sc = st->priv_data;
7136
7137 ✗ remaining = atom.size;
7138 ✗ while (remaining > 0) {
7139 ✗ size = avio_rb32(pb);
7140 ✗ if (size < 8 || size > remaining ) {
7141 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid child size in pack box\n");
7142 ✗ return AVERROR_INVALIDDATA;
7143 }
7144
7145 ✗ tag = avio_rl32(pb);
7146 ✗ switch (tag) {
7147 ✗ case MKTAG('p','k','i','n'): {
7148 ✗ if (size != 16) {
7149 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of pkin box: %d\n", size);
7150 ✗ return AVERROR_INVALIDDATA;
7151 }
7152 ✗ avio_skip(pb, 1); // version
7153 ✗ avio_skip(pb, 3); // flags
7154
7155 ✗ tag = avio_rl32(pb);
7156 ✗ switch (tag) {
7157 ✗ case MKTAG('s','i','d','e'):
7158 ✗ type = AV_STEREO3D_SIDEBYSIDE;
7159 ✗ break;
7160 ✗ case MKTAG('o','v','e','r'):
7161 ✗ type = AV_STEREO3D_TOPBOTTOM;
7162 ✗ break;
7163 ✗ case 0:
7164 // This means value will be set in another layer
7165 ✗ break;
7166 ✗ default:
7167 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pkin: %s\n",
7168 ✗ av_fourcc2str(tag));
7169 ✗ avio_skip(pb, size - 8);
7170 ✗ break;
7171 }
7172
7173 ✗ break;
7174 }
7175 ✗ default:
7176 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pack: %s\n",
7177 ✗ av_fourcc2str(tag));
7178 ✗ avio_skip(pb, size - 8);
7179 ✗ break;
7180 }
7181 ✗ remaining -= size;
7182 }
7183
7184 ✗ if (remaining != 0) {
7185 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken pack box\n");
7186 ✗ return AVERROR_INVALIDDATA;
7187 }
7188
7189 ✗ if (type == AV_STEREO3D_2D)
7190 ✗ return 0;
7191
7192 ✗ if (!sc->stereo3d) {
7193 ✗ sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7194 ✗ if (!sc->stereo3d)
7195 ✗ return AVERROR(ENOMEM);
7196 }
7197
7198 ✗ sc->stereo3d->type = type;
7199
7200 ✗ return 0;
7201 }
7202
7203 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7204 {
7205 AVStream *st;
7206 MOVStreamContext *sc;
7207 int size, version, layout;
7208 int32_t yaw, pitch, roll;
7209 1 uint32_t l = 0, t = 0, r = 0, b = 0;
7210 1 uint32_t tag, padding = 0;
7211 enum AVSphericalProjection projection;
7212
7213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
7214 ✗ return 0;
7215
7216 1 st = c->fc->streams[c->fc->nb_streams - 1];
7217 1 sc = st->priv_data;
7218
7219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
7220 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
7221 ✗ return AVERROR_INVALIDDATA;
7222 }
7223
7224 1 size = avio_rb32(pb);
7225
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)
7226 ✗ return AVERROR_INVALIDDATA;
7227
7228 1 tag = avio_rl32(pb);
7229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
7230 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
7231 ✗ return 0;
7232 }
7233 1 version = avio_r8(pb);
7234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7235 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7236 version);
7237 ✗ return 0;
7238 }
7239 1 avio_skip(pb, 3); /* flags */
7240 1 avio_skip(pb, size - 12); /* metadata_source */
7241
7242 1 size = avio_rb32(pb);
7243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7244 ✗ return AVERROR_INVALIDDATA;
7245
7246 1 tag = avio_rl32(pb);
7247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
7248 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
7249 ✗ return 0;
7250 }
7251
7252 1 size = avio_rb32(pb);
7253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7254 ✗ return AVERROR_INVALIDDATA;
7255
7256 1 tag = avio_rl32(pb);
7257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
7258 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
7259 ✗ return 0;
7260 }
7261 1 version = avio_r8(pb);
7262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7263 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7264 version);
7265 ✗ return 0;
7266 }
7267 1 avio_skip(pb, 3); /* flags */
7268
7269 /* 16.16 fixed point */
7270 1 yaw = avio_rb32(pb);
7271 1 pitch = avio_rb32(pb);
7272 1 roll = avio_rb32(pb);
7273
7274 1 size = avio_rb32(pb);
7275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7276 ✗ return AVERROR_INVALIDDATA;
7277
7278 1 tag = avio_rl32(pb);
7279 1 version = avio_r8(pb);
7280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7281 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7282 version);
7283 ✗ return 0;
7284 }
7285 1 avio_skip(pb, 3); /* flags */
7286
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
7287 ✗ case MKTAG('c','b','m','p'):
7288 ✗ layout = avio_rb32(pb);
7289 ✗ if (layout) {
7290 ✗ av_log(c->fc, AV_LOG_WARNING,
7291 "Unsupported cubemap layout %d\n", layout);
7292 ✗ return 0;
7293 }
7294 ✗ projection = AV_SPHERICAL_CUBEMAP;
7295 ✗ padding = avio_rb32(pb);
7296 ✗ break;
7297 1 case MKTAG('e','q','u','i'):
7298 1 t = avio_rb32(pb);
7299 1 b = avio_rb32(pb);
7300 1 l = avio_rb32(pb);
7301 1 r = avio_rb32(pb);
7302
7303
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) {
7304 ✗ av_log(c->fc, AV_LOG_ERROR,
7305 "Invalid bounding rectangle coordinates "
7306 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
7307 ✗ return AVERROR_INVALIDDATA;
7308 }
7309
7310
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)
7311 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
7312 else
7313 ✗ projection = AV_SPHERICAL_EQUIRECTANGULAR;
7314 1 break;
7315 ✗ default:
7316 ✗ av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
7317 ✗ return 0;
7318 }
7319
7320 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
7322 ✗ return AVERROR(ENOMEM);
7323
7324 1 sc->spherical->projection = projection;
7325
7326 1 sc->spherical->yaw = yaw;
7327 1 sc->spherical->pitch = pitch;
7328 1 sc->spherical->roll = roll;
7329
7330 1 sc->spherical->padding = padding;
7331
7332 1 sc->spherical->bound_left = l;
7333 1 sc->spherical->bound_top = t;
7334 1 sc->spherical->bound_right = r;
7335 1 sc->spherical->bound_bottom = b;
7336
7337 1 return 0;
7338 }
7339
7340 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7341 {
7342 AVStream *st;
7343 MOVStreamContext *sc;
7344 int size;
7345 uint32_t tag;
7346 enum AVSphericalProjection projection;
7347
7348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7349 ✗ return 0;
7350
7351 3 st = c->fc->streams[c->fc->nb_streams - 1];
7352 3 sc = st->priv_data;
7353
7354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 16) {
7355 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
7356 ✗ return AVERROR_INVALIDDATA;
7357 }
7358
7359 3 size = avio_rb32(pb);
7360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size < 16) {
7361 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
7362 ✗ return AVERROR_INVALIDDATA;
7363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (size > 16) {
7364 ✗ av_log(c->fc, AV_LOG_WARNING, "Box has more bytes (%d) than prji box required (16) \n", size);
7365 }
7366
7367 3 tag = avio_rl32(pb);
7368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
7369 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: %s\n",
7370 ✗ av_fourcc2str(tag));
7371 ✗ return AVERROR_INVALIDDATA;
7372 }
7373
7374 // version and flags, only support (0, 0)
7375 3 unsigned n = avio_rl32(pb);
7376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (n != 0) {
7377 ✗ av_log(c->fc, AV_LOG_ERROR, "prji version %u, flag %u are not supported\n",
7378 n & 0xFF, n >> 8);
7379 ✗ return AVERROR_PATCHWELCOME;
7380 }
7381
7382 3 tag = avio_rl32(pb);
7383
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) {
7384 3 case MKTAG('r','e','c','t'):
7385 3 projection = AV_SPHERICAL_RECTILINEAR;
7386 3 break;
7387 ✗ case MKTAG('e','q','u','i'):
7388 ✗ projection = AV_SPHERICAL_EQUIRECTANGULAR;
7389 ✗ break;
7390 ✗ case MKTAG('h','e','q','u'):
7391 ✗ projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
7392 ✗ break;
7393 ✗ case MKTAG('f','i','s','h'):
7394 ✗ projection = AV_SPHERICAL_FISHEYE;
7395 ✗ break;
7396 ✗ case MKTAG('p','r','i','m'):
7397 ✗ projection = AV_SPHERICAL_PARAMETRIC_IMMERSIVE;
7398 ✗ break;
7399 ✗ default:
7400 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: %s\n", av_fourcc2str(tag));
7401 ✗ return AVERROR_INVALIDDATA;
7402 }
7403
7404 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
7406 ✗ return AVERROR(ENOMEM);
7407
7408 3 sc->spherical->projection = projection;
7409
7410 3 return 0;
7411 }
7412
7413 5 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7414 {
7415 AVStream *st;
7416 MOVStreamContext *sc;
7417 5 int size, flags = 0;
7418 int64_t remaining;
7419 5 uint32_t tag, baseline = 0;
7420 5 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
7421 5 enum AVStereo3DType type = AV_STEREO3D_2D;
7422 5 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
7423 5 AVRational horizontal_disparity_adjustment = { 0, 1 };
7424
7425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
7426 ✗ return 0;
7427
7428 5 st = c->fc->streams[c->fc->nb_streams - 1];
7429 5 sc = st->priv_data;
7430
7431 5 remaining = atom.size;
7432
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 while (remaining > 0) {
7433 11 size = avio_rb32(pb);
7434
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 ) {
7435 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
7436 ✗ return AVERROR_INVALIDDATA;
7437 }
7438
7439 11 tag = avio_rl32(pb);
7440
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) {
7441 5 case MKTAG('s','t','r','i'): {
7442 int has_right, has_left;
7443 uint8_t tmp;
7444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (size != 13) {
7445 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
7446 ✗ return AVERROR_INVALIDDATA;
7447 }
7448 5 avio_skip(pb, 1); // version
7449 5 avio_skip(pb, 3); // flags
7450
7451 5 tmp = avio_r8(pb);
7452
7453 // eye_views_reversed
7454
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (tmp & 8) {
7455 ✗ flags |= AV_STEREO3D_FLAG_INVERT;
7456 }
7457 // has_additional_views
7458 5 if (tmp & 4) {
7459 // skip...
7460 }
7461
7462 5 has_right = tmp & 2; // has_right_eye_view
7463 5 has_left = tmp & 1; // has_left_eye_view
7464
7465
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)
7466 5 view = AV_STEREO3D_VIEW_PACKED;
7467 ✗ else if (has_left)
7468 ✗ view = AV_STEREO3D_VIEW_LEFT;
7469 ✗ else if (has_right)
7470 ✗ view = AV_STEREO3D_VIEW_RIGHT;
7471
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)
7472 5 type = AV_STEREO3D_UNSPEC;
7473
7474 5 break;
7475 }
7476 ✗ case MKTAG('h','e','r','o'): {
7477 int tmp;
7478 ✗ if (size != 13) {
7479 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
7480 ✗ return AVERROR_INVALIDDATA;
7481 }
7482 ✗ avio_skip(pb, 1); // version
7483 ✗ avio_skip(pb, 3); // flags
7484
7485 ✗ tmp = avio_r8(pb);
7486 ✗ if (tmp == 0)
7487 ✗ primary_eye = AV_PRIMARY_EYE_NONE;
7488 ✗ else if (tmp == 1)
7489 ✗ primary_eye = AV_PRIMARY_EYE_LEFT;
7490 ✗ else if (tmp == 2)
7491 ✗ primary_eye = AV_PRIMARY_EYE_RIGHT;
7492 else
7493 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
7494
7495 ✗ break;
7496 }
7497 3 case MKTAG('c','a','m','s'): {
7498 uint32_t subtag;
7499 int subsize;
7500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7501 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
7502 ✗ return AVERROR_INVALIDDATA;
7503 }
7504
7505 3 subsize = avio_rb32(pb);
7506
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7507 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
7508 ✗ return AVERROR_INVALIDDATA;
7509 }
7510
7511 3 subtag = avio_rl32(pb);
7512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
7513 ✗ av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got %s\n",
7514 ✗ av_fourcc2str(subtag));
7515 ✗ return AVERROR_INVALIDDATA;
7516 }
7517
7518 3 avio_skip(pb, 1); // version
7519 3 avio_skip(pb, 3); // flags
7520
7521 3 baseline = avio_rb32(pb);
7522
7523 3 break;
7524 }
7525 3 case MKTAG('c','m','f','y'): {
7526 uint32_t subtag;
7527 int subsize;
7528 int32_t adjustment;
7529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7530 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
7531 ✗ return AVERROR_INVALIDDATA;
7532 }
7533
7534 3 subsize = avio_rb32(pb);
7535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7536 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
7537 ✗ return AVERROR_INVALIDDATA;
7538 }
7539
7540 3 subtag = avio_rl32(pb);
7541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
7542 ✗ av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got %s\n",
7543 ✗ av_fourcc2str(subtag));
7544 ✗ return AVERROR_INVALIDDATA;
7545 }
7546
7547 3 avio_skip(pb, 1); // version
7548 3 avio_skip(pb, 3); // flags
7549
7550 3 adjustment = (int32_t) avio_rb32(pb);
7551
7552 3 horizontal_disparity_adjustment.num = (int) adjustment;
7553 3 horizontal_disparity_adjustment.den = 10000;
7554
7555 3 break;
7556 }
7557 ✗ default:
7558 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: %s\n",
7559 ✗ av_fourcc2str(tag));
7560 ✗ avio_skip(pb, size - 8);
7561 ✗ break;
7562 }
7563 11 remaining -= size;
7564 }
7565
7566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (remaining != 0) {
7567 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
7568 ✗ return AVERROR_INVALIDDATA;
7569 }
7570
7571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (type == AV_STEREO3D_2D)
7572 ✗ return 0;
7573
7574
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (!sc->stereo3d) {
7575 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7577 ✗ return AVERROR(ENOMEM);
7578 }
7579
7580 5 sc->stereo3d->flags = flags;
7581 /* eyes/stri only records packed vs single-eye, not SBS/TB. Keep a more
7582 * specific type already set by st3d. */
7583
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (type != AV_STEREO3D_UNSPEC)
7584 ✗ sc->stereo3d->type = type;
7585
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 else if (sc->stereo3d->type == AV_STEREO3D_2D)
7586 3 sc->stereo3d->type = type;
7587 5 sc->stereo3d->view = view;
7588 5 sc->stereo3d->primary_eye = primary_eye;
7589 5 sc->stereo3d->baseline = baseline;
7590 5 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
7591
7592 5 return 0;
7593 }
7594
7595 5 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7596 {
7597 int size;
7598 int64_t remaining;
7599 uint32_t tag;
7600
7601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
7602 ✗ return 0;
7603
7604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (atom.size < 8) {
7605 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
7606 ✗ return AVERROR_INVALIDDATA;
7607 }
7608
7609 5 remaining = atom.size;
7610
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5 times.
13 while (remaining > 0) {
7611 8 size = avio_rb32(pb);
7612
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 ) {
7613 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
7614 ✗ return AVERROR_INVALIDDATA;
7615 }
7616
7617 8 tag = avio_rl32(pb);
7618
2/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 switch (tag) {
7619 3 case MKTAG('p','r','o','j'): {
7620 3 MOVAtom proj = { tag, size - 8 };
7621 3 int ret = mov_read_vexu_proj(c, pb, proj);
7622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7623 ✗ return ret;
7624 3 break;
7625 }
7626 5 case MKTAG('e','y','e','s'): {
7627 5 MOVAtom eyes = { tag, size - 8 };
7628 5 int ret = mov_read_eyes(c, pb, eyes);
7629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
7630 ✗ return ret;
7631 5 break;
7632 }
7633 ✗ case MKTAG('p','a','c','k'): {
7634 ✗ MOVAtom pack = { tag, size - 8 };
7635 ✗ int ret = mov_read_pack(c, pb, pack);
7636 ✗ if (ret < 0)
7637 ✗ return ret;
7638 ✗ break;
7639 }
7640 ✗ default:
7641 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: %s\n",
7642 ✗ av_fourcc2str(tag));
7643 ✗ avio_skip(pb, size - 8);
7644 ✗ break;
7645 }
7646 8 remaining -= size;
7647 }
7648
7649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (remaining != 0) {
7650 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7651 ✗ return AVERROR_INVALIDDATA;
7652 }
7653
7654 5 return 0;
7655 }
7656
7657 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7658 {
7659 AVStream *st;
7660 MOVStreamContext *sc;
7661
7662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7663 ✗ return 0;
7664
7665 3 st = c->fc->streams[c->fc->nb_streams - 1];
7666 3 sc = st->priv_data;
7667
7668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7669 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7670 ✗ return AVERROR_INVALIDDATA;
7671 }
7672
7673
7674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7675 ✗ sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7676 ✗ if (!sc->stereo3d)
7677 ✗ return AVERROR(ENOMEM);
7678 }
7679
7680 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7681 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7682
7683 3 return 0;
7684 }
7685
7686 ✗ static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7687 {
7688 ✗ int ret = 0;
7689 ✗ uint8_t *buffer = av_malloc(len + 1);
7690 const char *val;
7691
7692 ✗ if (!buffer)
7693 ✗ return AVERROR(ENOMEM);
7694 ✗ buffer[len] = '\0';
7695
7696 ✗ ret = ffio_read_size(pb, buffer, len);
7697 ✗ if (ret < 0)
7698 ✗ goto out;
7699
7700 /* Check for mandatory keys and values, try to support XML as best-effort */
7701 ✗ if (!sc->spherical &&
7702 ✗ av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7703 ✗ (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7704 ✗ av_stristr(val, "true") &&
7705 ✗ (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7706 ✗ av_stristr(val, "true") &&
7707 ✗ (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7708 ✗ av_stristr(val, "equirectangular")) {
7709 ✗ sc->spherical = av_spherical_alloc(&sc->spherical_size);
7710 ✗ if (!sc->spherical)
7711 ✗ goto out;
7712
7713 ✗ sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7714
7715 ✗ if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7716 enum AVStereo3DType mode;
7717
7718 ✗ if (av_stristr(buffer, "left-right"))
7719 ✗ mode = AV_STEREO3D_SIDEBYSIDE;
7720 ✗ else if (av_stristr(buffer, "top-bottom"))
7721 ✗ mode = AV_STEREO3D_TOPBOTTOM;
7722 else
7723 ✗ mode = AV_STEREO3D_2D;
7724
7725 ✗ sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7726 ✗ if (!sc->stereo3d)
7727 ✗ goto out;
7728
7729 ✗ sc->stereo3d->type = mode;
7730 }
7731
7732 /* orientation */
7733 ✗ val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7734 ✗ if (val)
7735 ✗ sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7736 ✗ val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7737 ✗ if (val)
7738 ✗ sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7739 ✗ val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7740 ✗ if (val)
7741 ✗ sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7742 }
7743
7744 ✗ out:
7745 ✗ av_free(buffer);
7746 ✗ return ret;
7747 }
7748
7749 69 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7750 {
7751 AVStream *st;
7752 MOVStreamContext *sc;
7753 int64_t ret;
7754 AVUUID uuid;
7755 static const AVUUID uuid_isml_manifest = {
7756 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7757 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7758 };
7759 static const AVUUID uuid_xmp = {
7760 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7761 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7762 };
7763 static const AVUUID uuid_spherical = {
7764 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7765 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7766 };
7767
7768
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))
7769 ✗ return AVERROR_INVALIDDATA;
7770
7771
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 66 times.
69 if (c->fc->nb_streams < 1)
7772 3 return 0;
7773 66 st = c->fc->streams[c->fc->nb_streams - 1];
7774 66 sc = st->priv_data;
7775
7776 66 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7777
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
7778 ✗ return ret;
7779
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7780 uint8_t *buffer, *ptr;
7781 char *endptr;
7782 ✗ size_t len = atom.size - AV_UUID_LEN;
7783
7784 ✗ if (len < 4) {
7785 ✗ return AVERROR_INVALIDDATA;
7786 }
7787 ✗ ret = avio_skip(pb, 4); // zeroes
7788 ✗ len -= 4;
7789
7790 ✗ buffer = av_mallocz(len + 1);
7791 ✗ if (!buffer) {
7792 ✗ return AVERROR(ENOMEM);
7793 }
7794 ✗ ret = ffio_read_size(pb, buffer, len);
7795 ✗ if (ret < 0) {
7796 ✗ av_free(buffer);
7797 ✗ return ret;
7798 }
7799
7800 ✗ ptr = buffer;
7801 ✗ while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7802 ✗ ptr += sizeof("systemBitrate=\"") - 1;
7803 ✗ c->bitrates_count++;
7804 ✗ c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7805 ✗ if (!c->bitrates) {
7806 ✗ c->bitrates_count = 0;
7807 ✗ av_free(buffer);
7808 ✗ return AVERROR(ENOMEM);
7809 }
7810 ✗ errno = 0;
7811 ✗ ret = strtol(ptr, &endptr, 10);
7812 ✗ if (ret < 0 || errno || *endptr != '"') {
7813 ✗ c->bitrates[c->bitrates_count - 1] = 0;
7814 } else {
7815 ✗ c->bitrates[c->bitrates_count - 1] = ret;
7816 }
7817 }
7818
7819 ✗ av_free(buffer);
7820
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7821 uint8_t *buffer;
7822 ✗ size_t len = atom.size - AV_UUID_LEN;
7823 ✗ if (c->export_xmp) {
7824 ✗ buffer = av_mallocz(len + 1);
7825 ✗ if (!buffer) {
7826 ✗ return AVERROR(ENOMEM);
7827 }
7828 ✗ ret = ffio_read_size(pb, buffer, len);
7829 ✗ if (ret < 0) {
7830 ✗ av_free(buffer);
7831 ✗ return ret;
7832 }
7833 ✗ buffer[len] = '\0';
7834 ✗ av_dict_set(&c->fc->metadata, "xmp",
7835 buffer, AV_DICT_DONT_STRDUP_VAL);
7836 } else {
7837 // skip all uuid atom, which makes it fast for long uuid-xmp file
7838 ✗ ret = avio_skip(pb, len);
7839 ✗ if (ret < 0)
7840 ✗ return ret;
7841 }
7842
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7843 ✗ size_t len = atom.size - AV_UUID_LEN;
7844 ✗ ret = mov_parse_uuid_spherical(sc, pb, len);
7845 ✗ if (ret < 0)
7846 ✗ return ret;
7847 ✗ if (!sc->spherical)
7848 ✗ av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7849 }
7850
7851 66 return 0;
7852 }
7853
7854 260 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7855 {
7856 int ret;
7857 uint8_t content[16];
7858
7859
2/2
✓ Branch 0 taken 142 times.
✓ Branch 1 taken 118 times.
260 if (atom.size < 8)
7860 142 return 0;
7861
7862 118 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (ret < 0)
7864 ✗ return ret;
7865
7866
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 73 times.
118 if ( !c->found_moov
7867
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 23 times.
45 && !c->found_mdat
7868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 && !memcmp(content, "Anevia\x1A\x1A", 8)
7869 ✗ && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7870 ✗ c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7871 }
7872
7873 118 return 0;
7874 }
7875
7876 42 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7877 {
7878 42 uint32_t format = avio_rl32(pb);
7879 MOVStreamContext *sc;
7880 enum AVCodecID id;
7881 AVStream *st;
7882
7883
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (c->fc->nb_streams < 1)
7884 ✗ return 0;
7885 42 st = c->fc->streams[c->fc->nb_streams - 1];
7886 42 sc = st->priv_data;
7887
7888
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 31 times.
42 switch (sc->format)
7889 {
7890 11 case MKTAG('e','n','c','v'): // encrypted video
7891 case MKTAG('e','n','c','a'): // encrypted audio
7892 11 id = mov_codec_id(st, format);
7893
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7894 ✗ st->codecpar->codec_id != id) {
7895 ✗ av_log(c->fc, AV_LOG_WARNING,
7896 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7897 ✗ (char*)&format, st->codecpar->codec_id);
7898 ✗ break;
7899 }
7900
7901 11 st->codecpar->codec_id = id;
7902 11 sc->format = format;
7903 11 break;
7904
7905 31 default:
7906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (format != sc->format) {
7907 ✗ av_log(c->fc, AV_LOG_WARNING,
7908 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7909 ✗ (char*)&format, (char*)&sc->format);
7910 }
7911 31 break;
7912 }
7913
7914 42 return 0;
7915 }
7916
7917 /**
7918 * Gets the current encryption info and associated current stream context. If
7919 * we are parsing a track fragment, this will return the specific encryption
7920 * info for this fragment; otherwise this will return the global encryption
7921 * info for the current stream.
7922 */
7923 27 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7924 {
7925 MOVFragmentStreamInfo *frag_stream_info;
7926 AVStream *st;
7927 int i;
7928
7929 27 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7930
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 21 times.
27 if (frag_stream_info) {
7931
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 for (i = 0; i < c->fc->nb_streams; i++) {
7932 6 *sc = c->fc->streams[i]->priv_data;
7933
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if ((*sc)->id == frag_stream_info->id) {
7934 6 st = c->fc->streams[i];
7935 6 break;
7936 }
7937 }
7938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (i == c->fc->nb_streams)
7939 ✗ return 0;
7940 6 *sc = st->priv_data;
7941
7942
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (!frag_stream_info->encryption_index) {
7943 // If this stream isn't encrypted, don't create the index.
7944
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(*sc)->cenc.default_encrypted_sample)
7945 ✗ return 0;
7946 2 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!frag_stream_info->encryption_index)
7948 ✗ return AVERROR(ENOMEM);
7949 }
7950 6 *encryption_index = frag_stream_info->encryption_index;
7951 6 return 1;
7952 } else {
7953 // No current track fragment, using stream level encryption info.
7954
7955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (c->fc->nb_streams < 1)
7956 ✗ return 0;
7957 21 st = c->fc->streams[c->fc->nb_streams - 1];
7958 21 *sc = st->priv_data;
7959
7960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!(*sc)->cenc.encryption_index) {
7961 // If this stream isn't encrypted, don't create the index.
7962 ✗ if (!(*sc)->cenc.default_encrypted_sample)
7963 ✗ return 0;
7964 ✗ (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7965 ✗ if (!(*sc)->cenc.encryption_index)
7966 ✗ return AVERROR(ENOMEM);
7967 }
7968
7969 21 *encryption_index = (*sc)->cenc.encryption_index;
7970 21 return 1;
7971 }
7972 }
7973
7974 195 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7975 {
7976 int i, ret;
7977 unsigned int subsample_count;
7978 AVSubsampleEncryptionInfo *subsamples;
7979
7980
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!sc->cenc.default_encrypted_sample) {
7981 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7982 ✗ return AVERROR_INVALIDDATA;
7983 }
7984
7985
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) {
7986 195 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*sample)
7988 ✗ return AVERROR(ENOMEM);
7989 } else
7990 ✗ *sample = NULL;
7991
7992
1/2
✓ Branch 0 taken 195 times.
✗ Branch 1 not taken.
195 if (sc->cenc.per_sample_iv_size != 0) {
7993
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) {
7994 ✗ av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
7995 ✗ av_encryption_info_free(*sample);
7996 ✗ *sample = NULL;
7997 ✗ return ret;
7998 }
7999 }
8000
8001
1/2
✓ Branch 0 taken 195 times.
✗ Branch 1 not taken.
195 if (use_subsamples) {
8002 195 subsample_count = avio_rb16(pb);
8003 195 av_free((*sample)->subsamples);
8004 195 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
8005
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!(*sample)->subsamples) {
8006 ✗ av_encryption_info_free(*sample);
8007 ✗ *sample = NULL;
8008 ✗ return AVERROR(ENOMEM);
8009 }
8010
8011
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++) {
8012 272 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
8013 272 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
8014 }
8015
8016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (pb->eof_reached) {
8017 ✗ av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
8018 ✗ av_encryption_info_free(*sample);
8019 ✗ *sample = NULL;
8020 ✗ return AVERROR_INVALIDDATA;
8021 }
8022 195 (*sample)->subsample_count = subsample_count;
8023 }
8024
8025 195 return 0;
8026 }
8027
8028 9 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8029 {
8030 AVEncryptionInfo **encrypted_samples;
8031 MOVEncryptionIndex *encryption_index;
8032 MOVStreamContext *sc;
8033 int use_subsamples, ret;
8034 9 unsigned int sample_count, i, alloc_size = 0;
8035
8036 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8038 ✗ return ret;
8039
8040
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (encryption_index->nb_encrypted_samples) {
8041 // This can happen if we have both saio/saiz and senc atoms.
8042 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
8043 2 return 0;
8044 }
8045
8046 7 avio_r8(pb); /* version */
8047 7 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
8048
8049 7 sample_count = avio_rb32(pb);
8050
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
8051 ✗ return AVERROR(ENOMEM);
8052
8053
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 7 times.
154 for (i = 0; i < sample_count; i++) {
8054 147 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
8055 147 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
8056 min_samples * sizeof(*encrypted_samples));
8057
1/2
✓ Branch 0 taken 147 times.
✗ Branch 1 not taken.
147 if (encrypted_samples) {
8058 147 encryption_index->encrypted_samples = encrypted_samples;
8059
8060 147 ret = mov_read_sample_encryption_info(
8061 147 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
8062 } else {
8063 ✗ ret = AVERROR(ENOMEM);
8064 }
8065
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
147 if (pb->eof_reached) {
8066 ✗ av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
8067 ✗ if (ret >= 0)
8068 ✗ av_encryption_info_free(encryption_index->encrypted_samples[i]);
8069 ✗ ret = AVERROR_INVALIDDATA;
8070 }
8071
8072
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
147 if (ret < 0) {
8073 ✗ for (; i > 0; i--)
8074 ✗ av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
8075 ✗ av_freep(&encryption_index->encrypted_samples);
8076 ✗ return ret;
8077 }
8078 }
8079 7 encryption_index->nb_encrypted_samples = sample_count;
8080
8081 7 return 0;
8082 }
8083
8084 2 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
8085 {
8086 AVEncryptionInfo **sample, **encrypted_samples;
8087 int64_t prev_pos;
8088 size_t sample_count, sample_info_size, i;
8089 2 int ret = 0;
8090 2 unsigned int alloc_size = 0;
8091
8092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->nb_encrypted_samples)
8093 ✗ return 0;
8094 2 sample_count = encryption_index->auxiliary_info_sample_count;
8095
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count != 1) {
8096 ✗ av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
8097 ✗ return AVERROR_PATCHWELCOME;
8098 }
8099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
8100 ✗ return AVERROR(ENOMEM);
8101
8102 2 prev_pos = avio_tell(pb);
8103
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
8104
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]) {
8105 ✗ av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
8106 ✗ goto finish;
8107 }
8108
8109
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++) {
8110 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
8111 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
8112 min_samples * sizeof(*encrypted_samples));
8113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (!encrypted_samples) {
8114 ✗ ret = AVERROR(ENOMEM);
8115 ✗ goto finish;
8116 }
8117 48 encryption_index->encrypted_samples = encrypted_samples;
8118
8119 48 sample = &encryption_index->encrypted_samples[i];
8120 96 sample_info_size = encryption_index->auxiliary_info_default_size
8121 48 ? encryption_index->auxiliary_info_default_size
8122
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 : encryption_index->auxiliary_info_sizes[i];
8123
8124 48 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
8125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0)
8126 ✗ goto finish;
8127 }
8128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
8129 ✗ av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
8130 ✗ ret = AVERROR_INVALIDDATA;
8131 } else {
8132 2 encryption_index->nb_encrypted_samples = sample_count;
8133 }
8134
8135 2 finish:
8136 2 avio_seek(pb, prev_pos, SEEK_SET);
8137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
8138 ✗ for (; i > 0; i--) {
8139 ✗ av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
8140 }
8141 ✗ av_freep(&encryption_index->encrypted_samples);
8142 }
8143 2 return ret;
8144 }
8145
8146 9 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8147 {
8148 MOVEncryptionIndex *encryption_index;
8149 MOVStreamContext *sc;
8150 int ret;
8151 unsigned int sample_count, aux_info_type, aux_info_param;
8152
8153 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8155 ✗ return ret;
8156
8157
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (encryption_index->nb_encrypted_samples) {
8158 // This can happen if we have both saio/saiz and senc atoms.
8159 7 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
8160 7 return 0;
8161 }
8162
8163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_sample_count) {
8164 ✗ av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
8165 ✗ return AVERROR_INVALIDDATA;
8166 }
8167
8168 2 avio_r8(pb); /* version */
8169
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
8170 ✗ aux_info_type = avio_rb32(pb);
8171 ✗ aux_info_param = avio_rb32(pb);
8172 ✗ if (sc->cenc.default_encrypted_sample) {
8173 ✗ if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
8174 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
8175 ✗ return 0;
8176 }
8177 ✗ if (aux_info_param != 0) {
8178 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
8179 ✗ return 0;
8180 }
8181 } else {
8182 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8183 ✗ if ((aux_info_type == MKBETAG('c','e','n','c') ||
8184 ✗ aux_info_type == MKBETAG('c','e','n','s') ||
8185 ✗ aux_info_type == MKBETAG('c','b','c','1') ||
8186 ✗ aux_info_type == MKBETAG('c','b','c','s')) &&
8187 aux_info_param == 0) {
8188 ✗ av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
8189 ✗ return AVERROR_INVALIDDATA;
8190 } else {
8191 ✗ return 0;
8192 }
8193 }
8194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
8195 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8196 ✗ return 0;
8197 }
8198
8199 2 encryption_index->auxiliary_info_default_size = avio_r8(pb);
8200 2 sample_count = avio_rb32(pb);
8201
8202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_default_size == 0) {
8203 ✗ if (sample_count == 0)
8204 ✗ return AVERROR_INVALIDDATA;
8205
8206 ✗ encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
8207 ✗ if (!encryption_index->auxiliary_info_sizes)
8208 ✗ return AVERROR(ENOMEM);
8209
8210 ✗ ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
8211 ✗ if (ret != sample_count) {
8212 ✗ av_freep(&encryption_index->auxiliary_info_sizes);
8213
8214 ✗ if (ret >= 0)
8215 ✗ ret = AVERROR_INVALIDDATA;
8216 ✗ av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
8217 ✗ av_err2str(ret));
8218 ✗ return ret;
8219 }
8220 }
8221 2 encryption_index->auxiliary_info_sample_count = sample_count;
8222
8223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
8224 ✗ return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
8225 }
8226
8227 2 return 0;
8228 }
8229
8230 9 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8231 {
8232 uint64_t *auxiliary_offsets;
8233 MOVEncryptionIndex *encryption_index;
8234 MOVStreamContext *sc;
8235 int i, ret;
8236 unsigned int version, entry_count, aux_info_type, aux_info_param;
8237 9 unsigned int alloc_size = 0;
8238
8239 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8241 ✗ return ret;
8242
8243
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (encryption_index->nb_encrypted_samples) {
8244 // This can happen if we have both saio/saiz and senc atoms.
8245 7 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
8246 7 return 0;
8247 }
8248
8249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
8250 ✗ av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
8251 ✗ return AVERROR_INVALIDDATA;
8252 }
8253
8254 2 version = avio_r8(pb); /* version */
8255
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
8256 ✗ aux_info_type = avio_rb32(pb);
8257 ✗ aux_info_param = avio_rb32(pb);
8258 ✗ if (sc->cenc.default_encrypted_sample) {
8259 ✗ if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
8260 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
8261 ✗ return 0;
8262 }
8263 ✗ if (aux_info_param != 0) {
8264 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
8265 ✗ return 0;
8266 }
8267 } else {
8268 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8269 ✗ if ((aux_info_type == MKBETAG('c','e','n','c') ||
8270 ✗ aux_info_type == MKBETAG('c','e','n','s') ||
8271 ✗ aux_info_type == MKBETAG('c','b','c','1') ||
8272 ✗ aux_info_type == MKBETAG('c','b','c','s')) &&
8273 aux_info_param == 0) {
8274 ✗ av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
8275 ✗ return AVERROR_INVALIDDATA;
8276 } else {
8277 ✗ return 0;
8278 }
8279 }
8280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
8281 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8282 ✗ return 0;
8283 }
8284
8285 2 entry_count = avio_rb32(pb);
8286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
8287 ✗ return AVERROR(ENOMEM);
8288
8289
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++) {
8290
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);
8291 2 auxiliary_offsets = av_fast_realloc(
8292 2 encryption_index->auxiliary_offsets, &alloc_size,
8293 min_offsets * sizeof(*auxiliary_offsets));
8294
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!auxiliary_offsets) {
8295 ✗ av_freep(&encryption_index->auxiliary_offsets);
8296 ✗ return AVERROR(ENOMEM);
8297 }
8298 2 encryption_index->auxiliary_offsets = auxiliary_offsets;
8299
8300
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version == 0) {
8301 2 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
8302 } else {
8303 ✗ encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
8304 }
8305
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (c->frag_index.current >= 0) {
8306 2 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
8307 }
8308 }
8309
8310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
8311 ✗ av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
8312 ✗ av_freep(&encryption_index->auxiliary_offsets);
8313 ✗ return AVERROR_INVALIDDATA;
8314 }
8315
8316 2 encryption_index->auxiliary_offsets_count = entry_count;
8317
8318
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (encryption_index->auxiliary_info_sample_count) {
8319 2 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
8320 }
8321
8322 ✗ return 0;
8323 }
8324
8325 4 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8326 {
8327 AVEncryptionInitInfo *info, *old_init_info;
8328 uint8_t **key_ids;
8329 AVStream *st;
8330 const AVPacketSideData *old_side_data;
8331 uint8_t *side_data, *extra_data;
8332 size_t side_data_size;
8333 4 int ret = 0;
8334 4 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
8335
8336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8337 ✗ return 0;
8338 4 st = c->fc->streams[c->fc->nb_streams-1];
8339
8340 4 version = avio_r8(pb); /* version */
8341 4 avio_rb24(pb); /* flags */
8342
8343 4 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
8344 /* key_id_size */ 16, /* data_size */ 0);
8345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info)
8346 ✗ return AVERROR(ENOMEM);
8347
8348
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
8349 ✗ av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
8350 ✗ goto finish;
8351 }
8352
8353
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (version > 0) {
8354 4 kid_count = avio_rb32(pb);
8355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
8356 ✗ ret = AVERROR(ENOMEM);
8357 ✗ goto finish;
8358 }
8359
8360
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++) {
8361 4 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
8362 4 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
8363 min_kid_count * sizeof(*key_ids));
8364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!key_ids) {
8365 ✗ ret = AVERROR(ENOMEM);
8366 ✗ goto finish;
8367 }
8368 4 info->key_ids = key_ids;
8369
8370 4 info->key_ids[i] = av_mallocz(16);
8371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info->key_ids[i]) {
8372 ✗ ret = AVERROR(ENOMEM);
8373 ✗ goto finish;
8374 }
8375 4 info->num_key_ids = i + 1;
8376
8377
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
8378 ✗ av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
8379 ✗ goto finish;
8380 }
8381 }
8382
8383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pb->eof_reached) {
8384 ✗ av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
8385 ✗ ret = AVERROR_INVALIDDATA;
8386 ✗ goto finish;
8387 }
8388 }
8389
8390 4 extra_data_size = avio_rb32(pb);
8391 4 extra_data = av_malloc(extra_data_size);
8392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!extra_data) {
8393 ✗ ret = AVERROR(ENOMEM);
8394 ✗ goto finish;
8395 }
8396 4 ret = avio_read(pb, extra_data, extra_data_size);
8397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != extra_data_size) {
8398 ✗ av_free(extra_data);
8399
8400 ✗ if (ret >= 0)
8401 ✗ ret = AVERROR_INVALIDDATA;
8402 ✗ goto finish;
8403 }
8404
8405 4 av_freep(&info->data); // malloc(0) may still allocate something.
8406 4 info->data = extra_data;
8407 4 info->data_size = extra_data_size;
8408
8409 // If there is existing initialization data, append to the list.
8410 4 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
8411 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
8412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (old_side_data) {
8413 ✗ old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
8414 ✗ if (old_init_info) {
8415 // Append to the end of the list.
8416 ✗ for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
8417 ✗ if (!cur->next) {
8418 ✗ cur->next = info;
8419 ✗ break;
8420 }
8421 }
8422 ✗ info = old_init_info;
8423 } else {
8424 // Assume existing side-data will be valid, so the only error we could get is OOM.
8425 ✗ ret = AVERROR(ENOMEM);
8426 ✗ goto finish;
8427 }
8428 }
8429
8430 4 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
8431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!side_data) {
8432 ✗ ret = AVERROR(ENOMEM);
8433 ✗ goto finish;
8434 }
8435
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
8436 4 &st->codecpar->nb_coded_side_data,
8437 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
8438 side_data, side_data_size, 0))
8439 ✗ av_free(side_data);
8440
8441 4 finish:
8442 4 av_encryption_init_info_free(info);
8443 4 return ret;
8444 }
8445
8446 11 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8447 {
8448 AVStream *st;
8449 MOVStreamContext *sc;
8450
8451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
8452 ✗ return 0;
8453 11 st = c->fc->streams[c->fc->nb_streams-1];
8454 11 sc = st->priv_data;
8455
8456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (sc->pseudo_stream_id != 0) {
8457 ✗ av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
8458 ✗ return AVERROR_PATCHWELCOME;
8459 }
8460
8461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
8462 ✗ return AVERROR_INVALIDDATA;
8463
8464 11 avio_rb32(pb); /* version and flags */
8465
8466
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (!sc->cenc.default_encrypted_sample) {
8467 11 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.default_encrypted_sample) {
8469 ✗ return AVERROR(ENOMEM);
8470 }
8471 }
8472
8473 11 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
8474 11 return 0;
8475 }
8476
8477 11 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8478 {
8479 AVStream *st;
8480 MOVStreamContext *sc;
8481 unsigned int version, pattern, is_protected, iv_size;
8482
8483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
8484 ✗ return 0;
8485 11 st = c->fc->streams[c->fc->nb_streams-1];
8486 11 sc = st->priv_data;
8487
8488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (sc->pseudo_stream_id != 0) {
8489 ✗ av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
8490 ✗ return AVERROR_PATCHWELCOME;
8491 }
8492
8493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.default_encrypted_sample) {
8494 ✗ sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8495 ✗ if (!sc->cenc.default_encrypted_sample) {
8496 ✗ return AVERROR(ENOMEM);
8497 }
8498 }
8499
8500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 20)
8501 ✗ return AVERROR_INVALIDDATA;
8502
8503 11 version = avio_r8(pb); /* version */
8504 11 avio_rb24(pb); /* flags */
8505
8506 11 avio_r8(pb); /* reserved */
8507 11 pattern = avio_r8(pb);
8508
8509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (version > 0) {
8510 ✗ sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
8511 ✗ sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
8512 }
8513
8514 11 is_protected = avio_r8(pb);
8515
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) {
8516 // The whole stream should be by-default encrypted.
8517 11 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
8518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.encryption_index)
8519 ✗ return AVERROR(ENOMEM);
8520 }
8521 11 iv_size = avio_r8(pb);
8522
3/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
11 if (iv_size != 0 && iv_size != 8 && iv_size != 16) {
8523 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
8524 ✗ return AVERROR_INVALIDDATA;
8525 }
8526 11 sc->cenc.per_sample_iv_size = iv_size;
8527
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) {
8528 ✗ av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
8529 ✗ return AVERROR_INVALIDDATA;
8530 }
8531
8532
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) {
8533 2 iv_size = avio_r8(pb);
8534
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) {
8535 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
8536 ✗ return AVERROR_INVALIDDATA;
8537 }
8538
8539
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) {
8540 ✗ av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
8541 ✗ return AVERROR_INVALIDDATA;
8542 }
8543 }
8544
8545 11 return 0;
8546 }
8547
8548 ✗ static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8549 {
8550 AVStream *st;
8551 int last, type, size, ret;
8552 uint8_t buf[4];
8553
8554 ✗ if (c->fc->nb_streams < 1)
8555 ✗ return 0;
8556 ✗ st = c->fc->streams[c->fc->nb_streams-1];
8557
8558 ✗ if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
8559 ✗ return AVERROR_INVALIDDATA;
8560
8561 /* Check FlacSpecificBox version. */
8562 ✗ if (avio_r8(pb) != 0)
8563 ✗ return AVERROR_INVALIDDATA;
8564
8565 ✗ avio_rb24(pb); /* Flags */
8566
8567 ✗ if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
8568 ✗ av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
8569 ✗ return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
8570 }
8571 ✗ flac_parse_block_header(buf, &last, &type, &size);
8572
8573 ✗ if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
8574 ✗ av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
8575 ✗ return AVERROR_INVALIDDATA;
8576 }
8577
8578 ✗ ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
8579 ✗ if (ret < 0)
8580 ✗ return ret;
8581
8582 ✗ if (!last)
8583 ✗ av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
8584
8585 ✗ return 0;
8586 }
8587
8588 11 static int get_key_from_kid(uint8_t* out, int len, MOVContext *c, AVEncryptionInfo *sample) {
8589 AVDictionaryEntry *key_entry_hex;
8590 char kid_hex[16*2+1];
8591
8592
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) {
8593 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid default decryption key length: got %d, expected %d\n", c->decryption_default_key_len, len);
8594 ✗ return -1;
8595 }
8596
8597
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
11 if (!c->decryption_keys) {
8598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 av_assert0(c->decryption_default_key);
8599 8 memcpy(out, c->decryption_default_key, len);
8600 8 return 0;
8601 }
8602
8603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sample->key_id_size != 16) {
8604 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid key ID size: got %u, expected 16\n", sample->key_id_size);
8605 ✗ return -1;
8606 }
8607
8608 3 ff_data_to_hex(kid_hex, sample->key_id, 16, 1);
8609 3 key_entry_hex = av_dict_get(c->decryption_keys, kid_hex, NULL, AV_DICT_DONT_STRDUP_KEY|AV_DICT_DONT_STRDUP_VAL);
8610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!key_entry_hex) {
8611 ✗ if (!c->decryption_default_key) {
8612 ✗ av_log(c->fc, AV_LOG_ERROR, "unable to find KID %s\n", kid_hex);
8613 ✗ return -1;
8614 }
8615 ✗ memcpy(out, c->decryption_default_key, len);
8616 ✗ return 0;
8617 }
8618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (strlen(key_entry_hex->value) != len*2) {
8619 ✗ return -1;
8620 }
8621 3 ff_hex_to_data(out, key_entry_hex->value);
8622 3 return 0;
8623 }
8624
8625 341 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8626 {
8627 int i, ret;
8628 int bytes_of_protected_data;
8629 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8630
8631
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 330 times.
341 if (!sc->cenc.aes_ctr) {
8632 11 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0) {
8634 ✗ return ret;
8635 }
8636
8637 /* initialize the cipher */
8638 11 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8639
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.aes_ctr) {
8640 ✗ return AVERROR(ENOMEM);
8641 }
8642
8643 11 ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8644
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0) {
8645 ✗ return ret;
8646 }
8647 }
8648
8649 341 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8650
8651
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 245 times.
341 if (!sample->subsample_count) {
8652 /* decrypt the whole packet */
8653 96 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8654 96 return 0;
8655 }
8656
8657
2/2
✓ Branch 0 taken 321 times.
✓ Branch 1 taken 245 times.
566 for (i = 0; i < sample->subsample_count; i++) {
8658
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) {
8659 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8660 ✗ return AVERROR_INVALIDDATA;
8661 }
8662
8663 /* skip the clear bytes */
8664 321 input += sample->subsamples[i].bytes_of_clear_data;
8665 321 size -= sample->subsamples[i].bytes_of_clear_data;
8666
8667 /* decrypt the encrypted bytes */
8668
8669 321 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
8670 321 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
8671
8672 321 input += bytes_of_protected_data;
8673 321 size -= bytes_of_protected_data;
8674 }
8675
8676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
245 if (size > 0) {
8677 ✗ av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8678 ✗ return AVERROR_INVALIDDATA;
8679 }
8680
8681 245 return 0;
8682 }
8683
8684 ✗ static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8685 {
8686 int i, ret;
8687 int num_of_encrypted_blocks;
8688 uint8_t iv[16];
8689 uint8_t decryption_key[16];
8690
8691 ✗ if (!sc->cenc.aes_ctx) {
8692 ✗ ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8693 ✗ if (ret < 0) {
8694 ✗ return ret;
8695 }
8696
8697 /* initialize the cipher */
8698 ✗ sc->cenc.aes_ctx = av_aes_alloc();
8699 ✗ if (!sc->cenc.aes_ctx) {
8700 ✗ return AVERROR(ENOMEM);
8701 }
8702
8703 ✗ ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8704 ✗ if (ret < 0) {
8705 ✗ return ret;
8706 }
8707 }
8708
8709 ✗ memcpy(iv, sample->iv, 16);
8710
8711 /* whole-block full sample encryption */
8712 ✗ if (!sample->subsample_count) {
8713 /* decrypt the whole packet */
8714 ✗ av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8715 ✗ return 0;
8716 }
8717
8718 ✗ for (i = 0; i < sample->subsample_count; i++) {
8719 ✗ if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8720 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8721 ✗ return AVERROR_INVALIDDATA;
8722 }
8723
8724 ✗ if (sample->subsamples[i].bytes_of_protected_data % 16) {
8725 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8726 ✗ return AVERROR_INVALIDDATA;
8727 }
8728
8729 /* skip the clear bytes */
8730 ✗ input += sample->subsamples[i].bytes_of_clear_data;
8731 ✗ size -= sample->subsamples[i].bytes_of_clear_data;
8732
8733 /* decrypt the encrypted bytes */
8734 ✗ num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8735 ✗ if (num_of_encrypted_blocks > 0) {
8736 ✗ av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8737 }
8738 ✗ input += sample->subsamples[i].bytes_of_protected_data;
8739 ✗ size -= sample->subsamples[i].bytes_of_protected_data;
8740 }
8741
8742 ✗ if (size > 0) {
8743 ✗ av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8744 ✗ return AVERROR_INVALIDDATA;
8745 }
8746
8747 ✗ return 0;
8748 }
8749
8750 ✗ static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8751 {
8752 int i, ret, rem_bytes;
8753 uint8_t *data;
8754 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8755
8756 ✗ if (!sc->cenc.aes_ctr) {
8757 ✗ ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8758 ✗ if (ret < 0) {
8759 ✗ return ret;
8760 }
8761
8762 /* initialize the cipher */
8763 ✗ sc->cenc.aes_ctr = av_aes_ctr_alloc();
8764 ✗ if (!sc->cenc.aes_ctr) {
8765 ✗ return AVERROR(ENOMEM);
8766 }
8767
8768 ✗ ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8769 ✗ if (ret < 0) {
8770 ✗ return ret;
8771 }
8772 }
8773
8774 ✗ av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8775
8776 /* whole-block full sample encryption */
8777 ✗ if (!sample->subsample_count) {
8778 /* decrypt the whole packet */
8779 ✗ av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8780 ✗ return 0;
8781 ✗ } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8782 ✗ av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8783 ✗ return AVERROR_INVALIDDATA;
8784 }
8785
8786 ✗ for (i = 0; i < sample->subsample_count; i++) {
8787 ✗ if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8788 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8789 ✗ return AVERROR_INVALIDDATA;
8790 }
8791
8792 /* skip the clear bytes */
8793 ✗ input += sample->subsamples[i].bytes_of_clear_data;
8794 ✗ size -= sample->subsamples[i].bytes_of_clear_data;
8795
8796 /* decrypt the encrypted bytes */
8797 ✗ data = input;
8798 ✗ rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8799 ✗ while (rem_bytes > 0) {
8800 ✗ if (rem_bytes < 16*sample->crypt_byte_block) {
8801 ✗ break;
8802 }
8803 ✗ av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8804 ✗ data += 16*sample->crypt_byte_block;
8805 ✗ rem_bytes -= 16*sample->crypt_byte_block;
8806 ✗ data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8807 ✗ rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8808 }
8809 ✗ input += sample->subsamples[i].bytes_of_protected_data;
8810 ✗ size -= sample->subsamples[i].bytes_of_protected_data;
8811 }
8812
8813 ✗ if (size > 0) {
8814 ✗ av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8815 ✗ return AVERROR_INVALIDDATA;
8816 }
8817
8818 ✗ return 0;
8819 }
8820
8821 ✗ static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8822 {
8823 int i, ret, rem_bytes;
8824 uint8_t iv[16];
8825 uint8_t *data;
8826 uint8_t decryption_key[16];
8827
8828 ✗ if (!sc->cenc.aes_ctx) {
8829 ✗ ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8830 ✗ if (ret < 0) {
8831 ✗ return ret;
8832 }
8833
8834 /* initialize the cipher */
8835 ✗ sc->cenc.aes_ctx = av_aes_alloc();
8836 ✗ if (!sc->cenc.aes_ctx) {
8837 ✗ return AVERROR(ENOMEM);
8838 }
8839
8840 ✗ ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8841 ✗ if (ret < 0) {
8842 ✗ return ret;
8843 }
8844 }
8845
8846 /* whole-block full sample encryption */
8847 ✗ if (!sample->subsample_count) {
8848 /* decrypt the whole packet */
8849 ✗ memcpy(iv, sample->iv, 16);
8850 ✗ av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8851 ✗ return 0;
8852 ✗ } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8853 ✗ av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8854 ✗ return AVERROR_INVALIDDATA;
8855 }
8856
8857 ✗ for (i = 0; i < sample->subsample_count; i++) {
8858 ✗ if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8859 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8860 ✗ return AVERROR_INVALIDDATA;
8861 }
8862
8863 /* skip the clear bytes */
8864 ✗ input += sample->subsamples[i].bytes_of_clear_data;
8865 ✗ size -= sample->subsamples[i].bytes_of_clear_data;
8866
8867 /* decrypt the encrypted bytes */
8868 ✗ memcpy(iv, sample->iv, 16);
8869 ✗ data = input;
8870 ✗ rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8871 ✗ while (rem_bytes > 0) {
8872 ✗ if (rem_bytes < 16*sample->crypt_byte_block) {
8873 ✗ break;
8874 }
8875 ✗ av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8876 ✗ data += 16*sample->crypt_byte_block;
8877 ✗ rem_bytes -= 16*sample->crypt_byte_block;
8878 ✗ data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8879 ✗ rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8880 }
8881 ✗ input += sample->subsamples[i].bytes_of_protected_data;
8882 ✗ size -= sample->subsamples[i].bytes_of_protected_data;
8883 }
8884
8885 ✗ if (size > 0) {
8886 ✗ av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8887 ✗ return AVERROR_INVALIDDATA;
8888 }
8889
8890 ✗ return 0;
8891 }
8892
8893 341 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8894 {
8895
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) {
8896 341 return cenc_scheme_decrypt(c, sc, sample, input, size);
8897 ✗ } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8898 ✗ return cbc1_scheme_decrypt(c, sc, sample, input, size);
8899 ✗ } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8900 ✗ return cens_scheme_decrypt(c, sc, sample, input, size);
8901 ✗ } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8902 ✗ return cbcs_scheme_decrypt(c, sc, sample, input, size);
8903 } else {
8904 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8905 ✗ return AVERROR_INVALIDDATA;
8906 }
8907 }
8908
8909 107951 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8910 {
8911 107951 int current = frag_index->current;
8912
8913
2/2
✓ Branch 0 taken 106972 times.
✓ Branch 1 taken 979 times.
107951 if (!frag_index->nb_items)
8914 106972 return NULL;
8915
8916 // Check frag_index->current is the right one for pkt. It can out of sync.
8917
2/4
✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 979 times.
✗ Branch 3 not taken.
979 if (current >= 0 && current < frag_index->nb_items) {
8918
2/2
✓ Branch 0 taken 952 times.
✓ Branch 1 taken 27 times.
979 if (frag_index->item[current].moof_offset < pkt->pos &&
8919
2/2
✓ Branch 0 taken 606 times.
✓ Branch 1 taken 346 times.
952 (current + 1 == frag_index->nb_items ||
8920
2/2
✓ Branch 0 taken 530 times.
✓ Branch 1 taken 76 times.
606 frag_index->item[current + 1].moof_offset > pkt->pos))
8921 876 return get_frag_stream_info(frag_index, current, id);
8922 }
8923
8924
8925
2/2
✓ Branch 0 taken 4557 times.
✓ Branch 1 taken 9 times.
4566 for (int i = 0; i < frag_index->nb_items; i++) {
8926
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 4463 times.
4557 if (frag_index->item[i].moof_offset > pkt->pos)
8927 94 break;
8928 4463 current = i;
8929 }
8930 103 frag_index->current = current;
8931 103 return get_frag_stream_info(frag_index, current, id);
8932 }
8933
8934 107951 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8935 {
8936 MOVFragmentStreamInfo *frag_stream_info;
8937 MOVEncryptionIndex *encryption_index;
8938 AVEncryptionInfo *encrypted_sample;
8939 int encrypted_index, ret;
8940
8941 107951 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8942 107951 encrypted_index = current_index;
8943 107951 encryption_index = NULL;
8944
2/2
✓ Branch 0 taken 979 times.
✓ Branch 1 taken 106972 times.
107951 if (frag_stream_info) {
8945 // Note this only supports encryption info in the first sample descriptor.
8946
2/2
✓ Branch 0 taken 931 times.
✓ Branch 1 taken 48 times.
979 if (frag_stream_info->stsd_id == 1) {
8947
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 883 times.
931 if (frag_stream_info->encryption_index) {
8948 48 encrypted_index = current_index - frag_stream_info->index_base;
8949 48 encryption_index = frag_stream_info->encryption_index;
8950 } else {
8951 883 encryption_index = sc->cenc.encryption_index;
8952 }
8953 }
8954 } else {
8955 106972 encryption_index = sc->cenc.encryption_index;
8956 }
8957
8958
2/2
✓ Branch 0 taken 341 times.
✓ Branch 1 taken 107610 times.
107951 if (encryption_index) {
8959
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 293 times.
341 if (encryption_index->auxiliary_info_sample_count &&
8960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8961 ✗ av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8962 ✗ return AVERROR_INVALIDDATA;
8963 }
8964
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 293 times.
341 if (encryption_index->auxiliary_offsets_count &&
8965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8966 ✗ av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8967 ✗ return AVERROR_INVALIDDATA;
8968 }
8969
8970 341 encrypted_sample = NULL;
8971
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 245 times.
341 if (!encryption_index->nb_encrypted_samples) {
8972 // Full-sample encryption with default settings.
8973 96 encrypted_sample = sc->cenc.default_encrypted_sample;
8974
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) {
8975 // Per-sample setting override.
8976 245 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
245 if (!encrypted_sample) {
8978 ✗ encrypted_sample = sc->cenc.default_encrypted_sample;
8979 }
8980 }
8981
8982
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
341 if (!encrypted_sample) {
8983 ✗ av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8984 ✗ return AVERROR_INVALIDDATA;
8985 }
8986
8987
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) {
8988 341 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
8989 } else {
8990 size_t size;
8991 ✗ uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
8992 ✗ if (!side_data)
8993 ✗ return AVERROR(ENOMEM);
8994 ✗ ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
8995 ✗ if (ret < 0)
8996 ✗ av_free(side_data);
8997 ✗ return ret;
8998 }
8999 }
9000
9001 107610 return 0;
9002 }
9003
9004 ✗ static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9005 {
9006 ✗ const int OPUS_SEEK_PREROLL_MS = 80;
9007 int ret;
9008 AVStream *st;
9009 size_t size;
9010 uint16_t pre_skip;
9011
9012 ✗ if (c->fc->nb_streams < 1)
9013 ✗ return 0;
9014 ✗ st = c->fc->streams[c->fc->nb_streams-1];
9015
9016 ✗ if ((uint64_t)atom.size > (1<<30) || atom.size < 11 || st->codecpar->extradata)
9017 ✗ return AVERROR_INVALIDDATA;
9018
9019 /* Check OpusSpecificBox version. */
9020 ✗ if (avio_r8(pb) != 0) {
9021 ✗ av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
9022 ✗ return AVERROR_INVALIDDATA;
9023 }
9024
9025 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
9026 ✗ size = atom.size + 8;
9027
9028 ✗ if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
9029 ✗ return ret;
9030
9031 ✗ AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
9032 ✗ AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
9033 ✗ AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
9034 ✗ if ((ret = ffio_read_size(pb, st->codecpar->extradata + 9, size - 9)) < 0) {
9035 ✗ av_freep(&st->codecpar->extradata);
9036 ✗ st->codecpar->extradata_size = 0;
9037 ✗ return ret;
9038 }
9039
9040 /* OpusSpecificBox is stored in big-endian, but OpusHead is
9041 little-endian; aside from the preceding magic and version they're
9042 otherwise currently identical. Data after output gain at offset 16
9043 doesn't need to be bytewapped. */
9044 ✗ pre_skip = AV_RB16A(st->codecpar->extradata + 10);
9045 ✗ AV_WL16A(st->codecpar->extradata + 10, pre_skip);
9046 ✗ AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
9047 ✗ AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
9048
9049 ✗ st->codecpar->initial_padding = pre_skip;
9050 ✗ st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
9051 ✗ (AVRational){1, 1000},
9052 ✗ (AVRational){1, 48000});
9053
9054 ✗ return 0;
9055 }
9056
9057 ✗ static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9058 {
9059 AVStream *st;
9060 unsigned format_info;
9061 int channel_assignment, channel_assignment1, channel_assignment2;
9062 int ratebits;
9063 uint64_t chmask;
9064
9065 ✗ if (c->fc->nb_streams < 1)
9066 ✗ return 0;
9067 ✗ st = c->fc->streams[c->fc->nb_streams-1];
9068
9069 ✗ if (atom.size < 10)
9070 ✗ return AVERROR_INVALIDDATA;
9071
9072 ✗ format_info = avio_rb32(pb);
9073
9074 ✗ ratebits = (format_info >> 28) & 0xF;
9075 ✗ channel_assignment1 = (format_info >> 15) & 0x1F;
9076 ✗ channel_assignment2 = format_info & 0x1FFF;
9077 ✗ if (channel_assignment2)
9078 ✗ channel_assignment = channel_assignment2;
9079 else
9080 ✗ channel_assignment = channel_assignment1;
9081
9082 ✗ st->codecpar->frame_size = 40 << (ratebits & 0x7);
9083 ✗ st->codecpar->sample_rate = mlp_samplerate(ratebits);
9084
9085 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
9086 ✗ chmask = truehd_layout(channel_assignment);
9087 ✗ av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
9088
9089 ✗ return 0;
9090 }
9091
9092 11 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9093 {
9094 AVStream *st;
9095 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
9096 int ret;
9097 11 int64_t read_size = atom.size;
9098
9099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
9100 ✗ return 0;
9101 11 st = c->fc->streams[c->fc->nb_streams-1];
9102
9103 // At most 24 bytes
9104 11 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
9105
9106
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
9107 ✗ return ret;
9108
9109 11 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
9110 }
9111
9112 7 static int mov_read_hvce(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9113 {
9114 AVStream *st;
9115 AVPacketSideData *sd;
9116 int ret;
9117
9118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (c->fc->nb_streams < 1)
9119 ✗ return 0;
9120 7 st = c->fc->streams[c->fc->nb_streams - 1];
9121
9122
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)
9123 ✗ return AVERROR_INVALIDDATA;
9124
9125 7 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
9126 7 &st->codecpar->nb_coded_side_data,
9127 AV_PKT_DATA_HEVC_CONF,
9128 7 atom.size, 0);
9129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sd)
9130 ✗ return AVERROR(ENOMEM);
9131
9132 7 ret = ffio_read_size(pb, sd->data, atom.size);
9133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
9134 ✗ return ret;
9135
9136 7 return 0;
9137 }
9138
9139 4 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9140 {
9141 AVStream *st;
9142 uint8_t *buf;
9143 int ret, old_size, num_arrays;
9144
9145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
9146 ✗ return 0;
9147 4 st = c->fc->streams[c->fc->nb_streams-1];
9148
9149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!st->codecpar->extradata_size)
9150 // TODO: handle lhvC when present before hvcC
9151 ✗ return 0;
9152
9153
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 ||
9154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 atom.size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
9155 ✗ return AVERROR_INVALIDDATA;
9156 }
9157
9158 4 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
9159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!buf)
9160 ✗ return AVERROR(ENOMEM);
9161 4 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
9162
9163 4 ret = ffio_read_size(pb, buf, atom.size);
9164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
9165 ✗ av_free(buf);
9166 ✗ av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
9167 ✗ return 0;
9168 }
9169
9170 4 num_arrays = buf[5];
9171 4 old_size = st->codecpar->extradata_size;
9172 4 atom.size -= 8 /* account for mov_realloc_extradata offsetting */
9173 + 6 /* lhvC bytes before the arrays*/;
9174
9175 4 ret = mov_realloc_extradata(st->codecpar, atom);
9176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
9177 ✗ av_free(buf);
9178 ✗ return ret;
9179 }
9180
9181 4 st->codecpar->extradata[22] += num_arrays;
9182 4 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
9183
9184 4 st->disposition |= AV_DISPOSITION_MULTILAYER;
9185
9186 4 av_free(buf);
9187 4 return 0;
9188 }
9189
9190 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9191 {
9192 4 AVFormatContext *ctx = c->fc;
9193 4 AVStream *st = NULL;
9194 AVBPrint scheme_buf, value_buf;
9195 4 int64_t scheme_str_len = 0, value_str_len = 0;
9196 4 int version, flags, ret = AVERROR_BUG;
9197 4 int64_t size = atom.size;
9198
9199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
9200 // 4 bytes for version + flags, 2x 1 byte for null
9201 ✗ return AVERROR_INVALIDDATA;
9202
9203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
9204 ✗ return 0;
9205 4 st = c->fc->streams[c->fc->nb_streams-1];
9206
9207 4 version = avio_r8(pb);
9208 4 flags = avio_rb24(pb);
9209 4 size -= 4;
9210
9211
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) {
9212 ✗ av_log(ctx, AV_LOG_ERROR,
9213 "Unsupported 'kind' box with version %d, flags: %x",
9214 version, flags);
9215 ✗ return AVERROR_INVALIDDATA;
9216 }
9217
9218 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
9219 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
9220
9221
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,
9222 size)) < 0) {
9223 ✗ ret = scheme_str_len;
9224 ✗ goto cleanup;
9225 }
9226
9227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
9228 // we need to have another string, even if nullptr.
9229 // we check with + 1 since we expect that if size was not hit,
9230 // an additional null was read.
9231 ✗ ret = AVERROR_INVALIDDATA;
9232 ✗ goto cleanup;
9233 }
9234
9235 4 size -= scheme_str_len + 1;
9236
9237
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,
9238 size)) < 0) {
9239 ✗ ret = value_str_len;
9240 ✗ goto cleanup;
9241 }
9242
9243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
9244 // in case of no trailing null, box is not valid.
9245 ✗ ret = AVERROR_INVALIDDATA;
9246 ✗ goto cleanup;
9247 }
9248
9249 4 av_log(ctx, AV_LOG_TRACE,
9250 "%s stream %d KindBox(scheme: %s, value: %s)\n",
9251 4 av_get_media_type_string(st->codecpar->codec_type),
9252 st->index,
9253 scheme_buf.str, value_buf.str);
9254
9255
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++) {
9256 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
9257
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
9258 ✗ continue;
9259
9260
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
9261 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
9262
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
9263 16 continue;
9264
9265 4 st->disposition |= value_map.disposition;
9266 }
9267 }
9268
9269 4 ret = 0;
9270
9271 4 cleanup:
9272
9273 4 av_bprint_finalize(&scheme_buf, NULL);
9274 4 av_bprint_finalize(&value_buf, NULL);
9275
9276 4 return ret;
9277 }
9278
9279 ✗ static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9280 {
9281 AVStream *st;
9282 ✗ AVChannelLayout ch_layout = { 0 };
9283 int ret, i, version, type;
9284 int ambisonic_order, channel_order, normalization, channel_count;
9285 int ambi_channels, non_diegetic_channels;
9286
9287 ✗ if (c->fc->nb_streams < 1)
9288 ✗ return 0;
9289
9290 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
9291
9292 ✗ if (atom.size < 16) {
9293 ✗ av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
9294 ✗ return AVERROR_INVALIDDATA;
9295 }
9296
9297 ✗ version = avio_r8(pb);
9298 ✗ if (version) {
9299 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
9300 ✗ return 0;
9301 }
9302
9303 ✗ type = avio_r8(pb);
9304 ✗ if (type & 0x7f) {
9305 ✗ av_log(c->fc, AV_LOG_WARNING,
9306 "Unsupported ambisonic type %d\n", type & 0x7f);
9307 ✗ return 0;
9308 }
9309 ✗ non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
9310
9311 ✗ ambisonic_order = avio_rb32(pb);
9312
9313 ✗ channel_order = avio_r8(pb);
9314 ✗ if (channel_order) {
9315 ✗ av_log(c->fc, AV_LOG_WARNING,
9316 "Unsupported channel_order %d\n", channel_order);
9317 ✗ return 0;
9318 }
9319
9320 ✗ normalization = avio_r8(pb);
9321 ✗ if (normalization) {
9322 ✗ av_log(c->fc, AV_LOG_WARNING,
9323 "Unsupported normalization %d\n", normalization);
9324 ✗ return 0;
9325 }
9326
9327 ✗ channel_count = avio_rb32(pb);
9328 ✗ if (ambisonic_order < 0 || ambisonic_order > 31 ||
9329 ✗ channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
9330 non_diegetic_channels)) {
9331 ✗ av_log(c->fc, AV_LOG_ERROR,
9332 "Invalid number of channels (%d / %d)\n",
9333 channel_count, ambisonic_order);
9334 ✗ return 0;
9335 }
9336 ✗ ambi_channels = channel_count - non_diegetic_channels;
9337
9338 ✗ ret = av_channel_layout_custom_init(&ch_layout, channel_count);
9339 ✗ if (ret < 0)
9340 ✗ return 0;
9341
9342 ✗ for (i = 0; i < channel_count; i++) {
9343 ✗ unsigned channel = avio_rb32(pb);
9344
9345 ✗ if (channel >= channel_count) {
9346 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
9347 channel, ambisonic_order);
9348 ✗ av_channel_layout_uninit(&ch_layout);
9349 ✗ return 0;
9350 }
9351 ✗ if (channel >= ambi_channels)
9352 ✗ ch_layout.u.map[i].id = channel - ambi_channels;
9353 else
9354 ✗ ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
9355 }
9356
9357 ✗ ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
9358 ✗ if (ret < 0) {
9359 ✗ av_channel_layout_uninit(&ch_layout);
9360 ✗ return 0;
9361 }
9362
9363 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
9364 ✗ st->codecpar->ch_layout = ch_layout;
9365
9366 ✗ return 0;
9367 }
9368
9369 ✗ static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9370 {
9371 AVStream *st;
9372 int version;
9373
9374 ✗ if (c->fc->nb_streams < 1)
9375 ✗ return 0;
9376
9377 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
9378
9379 ✗ if (atom.size < 5) {
9380 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
9381 ✗ return AVERROR_INVALIDDATA;
9382 }
9383
9384 ✗ version = avio_r8(pb);
9385 ✗ if (version) {
9386 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
9387 ✗ return 0;
9388 }
9389
9390 ✗ st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
9391
9392 ✗ return 0;
9393 }
9394
9395 171 static int rb_size(AVIOContext *pb, int64_t *value, int size)
9396 {
9397
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 160 times.
171 if (size == 0)
9398 11 *value = 0;
9399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 else if (size == 1)
9400 ✗ *value = avio_r8(pb);
9401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 else if (size == 2)
9402 ✗ *value = avio_rb16(pb);
9403
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 else if (size == 4)
9404 160 *value = avio_rb32(pb);
9405 ✗ else if (size == 8) {
9406 ✗ *value = avio_rb64(pb);
9407 ✗ if (*value < 0)
9408 ✗ return -1;
9409 } else
9410 ✗ return -1;
9411 171 return size;
9412 }
9413
9414 18 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9415 {
9416 18 avio_rb32(pb); // version & flags.
9417 18 c->primary_item_id = avio_rb16(pb);
9418 18 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
9419 18 return atom.size;
9420 }
9421
9422 9 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9423 {
9424 9 c->idat_offset = avio_tell(pb);
9425 9 return 0;
9426 }
9427
9428 18 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9429 {
9430 HEIFItem **heif_item;
9431 int version, offset_size, length_size, base_offset_size, index_size;
9432 int item_count, extent_count;
9433 int64_t base_offset, extent_offset, extent_length;
9434 uint8_t value;
9435
9436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->found_iloc) {
9437 ✗ av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
9438 ✗ return 0;
9439 }
9440
9441 18 version = avio_r8(pb);
9442 18 avio_rb24(pb); // flags.
9443
9444 18 value = avio_r8(pb);
9445 18 offset_size = (value >> 4) & 0xF;
9446 18 length_size = value & 0xF;
9447 18 value = avio_r8(pb);
9448 18 base_offset_size = (value >> 4) & 0xF;
9449
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 7 times.
18 index_size = !version ? 0 : (value & 0xF);
9450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (index_size) {
9451 ✗ avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
9452 ✗ return AVERROR_PATCHWELCOME;
9453 }
9454
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9455
9456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (item_count > atom.size)
9457 ✗ return AVERROR_INVALIDDATA;
9458
9459 18 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
9460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!heif_item)
9461 ✗ return AVERROR(ENOMEM);
9462 18 c->heif_item = heif_item;
9463
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (item_count > c->nb_heif_item)
9464 18 memset(&c->heif_item[c->nb_heif_item], 0,
9465 18 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
9466 18 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
9467
9468 18 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
9469
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (int i = 0; i < item_count; i++) {
9470 57 HEIFItem *item = NULL;
9471
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9472
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 12 times.
57 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
9473 int j;
9474
9475
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (avio_feof(pb))
9476 ✗ return AVERROR_INVALIDDATA;
9477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (offset_type > 1) {
9478 ✗ avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
9479 ✗ return AVERROR_PATCHWELCOME;
9480 }
9481
9482 57 avio_rb16(pb); // data_reference_index.
9483
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (rb_size(pb, &base_offset, base_offset_size) < 0)
9484 ✗ return AVERROR_INVALIDDATA;
9485 57 extent_count = avio_rb16(pb);
9486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (extent_count > 1) {
9487 // For still AVIF images, we only support one extent item.
9488 ✗ avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
9489 ✗ return AVERROR_PATCHWELCOME;
9490 }
9491
9492
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 ||
9493 57 rb_size(pb, &extent_length, length_size) < 0 ||
9494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 base_offset > INT64_MAX - extent_offset)
9495 ✗ return AVERROR_INVALIDDATA;
9496
9497
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 for (j = 0; j < c->nb_heif_item; j++) {
9498 140 item = c->heif_item[j];
9499
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 83 times.
140 if (!item)
9500 57 item = c->heif_item[j] = av_mallocz(sizeof(*item));
9501
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
83 else if (item->item_id != item_id)
9502 83 continue;
9503 57 break;
9504 }
9505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item)
9506 ✗ return AVERROR(ENOMEM);
9507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (j == c->nb_heif_item)
9508 ✗ return AVERROR_INVALIDDATA;
9509
9510 57 item->item_id = item_id;
9511
9512
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 48 times.
57 if (offset_type == 1)
9513 9 item->is_idat_relative = 1;
9514 57 item->extent_length = extent_length;
9515 57 item->extent_offset = base_offset + extent_offset;
9516 57 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, item->item_id %d, offset_type %d, "
9517 "extent_offset %"PRId64", extent_length %"PRId64"\n",
9518 i, item->item_id, offset_type, item->extent_offset, item->extent_length);
9519 }
9520
9521 18 c->found_iloc = 1;
9522 18 return atom.size;
9523 }
9524
9525 57 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9526 {
9527 57 HEIFItem *item = NULL;
9528 AVBPrint item_name;
9529 57 int64_t size = atom.size;
9530 uint32_t item_type;
9531 int item_id;
9532 int i, version, ret;
9533
9534 57 version = avio_r8(pb);
9535 57 avio_rb24(pb); // flags.
9536 57 size -= 4;
9537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (size < 0)
9538 ✗ return AVERROR_INVALIDDATA;
9539
9540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (version < 2) {
9541 ✗ avpriv_report_missing_feature(c->fc, "infe version < 2");
9542 ✗ avio_skip(pb, size);
9543 ✗ return 1;
9544 }
9545
9546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
9547 57 avio_rb16(pb); // item_protection_index
9548 57 item_type = avio_rl32(pb);
9549 57 size -= 8;
9550
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (size < 1)
9551 ✗ return AVERROR_INVALIDDATA;
9552
9553 57 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
9554 57 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
9555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (ret < 0) {
9556 ✗ av_bprint_finalize(&item_name, NULL);
9557 ✗ return ret;
9558 }
9559
9560 57 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
9561 57 item_id, av_fourcc2str(item_type), item_name.str);
9562
9563 57 size -= ret + 1;
9564
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 55 times.
57 if (size > 0)
9565 2 avio_skip(pb, size);
9566
9567
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 for (i = 0; i < c->nb_heif_item; i++) {
9568 140 item = c->heif_item[i];
9569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (!item)
9570 ✗ item = c->heif_item[i] = av_mallocz(sizeof(*item));
9571
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 57 times.
140 else if (item->item_id != item_id)
9572 83 continue;
9573 57 break;
9574 }
9575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item) {
9576 ✗ av_bprint_finalize(&item_name, NULL);
9577 ✗ return AVERROR(ENOMEM);
9578 }
9579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (i == c->nb_heif_item) {
9580 ✗ av_bprint_finalize(&item_name, NULL);
9581 ✗ return AVERROR_INVALIDDATA;
9582 }
9583
9584 57 av_freep(&item->name);
9585
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 1 times.
57 av_bprint_finalize(&item_name, ret ? &item->name : NULL);
9586 57 item->item_id = item_id;
9587 57 item->type = item_type;
9588
9589
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 14 times.
57 switch (item_type) {
9590 43 case MKTAG('a','v','0','1'):
9591 case MKTAG('j','p','e','g'):
9592 case MKTAG('h','v','c','1'):
9593 43 ret = heif_add_stream(c, item);
9594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
9595 ✗ return ret;
9596 43 break;
9597 }
9598
9599 57 return 0;
9600 }
9601
9602 18 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9603 {
9604 HEIFItem **heif_item;
9605 int entry_count;
9606 18 int version, got_stream = 0, ret, i;
9607
9608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->found_iinf) {
9609 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
9610 ✗ return 0;
9611 }
9612
9613 18 version = avio_r8(pb);
9614 18 avio_rb24(pb); // flags.
9615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
9616
9617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (entry_count > atom.size)
9618 ✗ return AVERROR_INVALIDDATA;
9619
9620 18 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
9621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!heif_item)
9622 ✗ return AVERROR(ENOMEM);
9623 18 c->heif_item = heif_item;
9624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (entry_count > c->nb_heif_item)
9625 ✗ memset(&c->heif_item[c->nb_heif_item], 0,
9626 ✗ sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
9627 18 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
9628
9629
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (i = 0; i < entry_count; i++) {
9630 MOVAtom infe;
9631
9632 57 infe.size = avio_rb32(pb) - 8;
9633 57 infe.type = avio_rl32(pb);
9634
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (avio_feof(pb)) {
9635 ✗ ret = AVERROR_INVALIDDATA;
9636 ✗ goto fail;
9637 }
9638 57 ret = mov_read_infe(c, pb, infe);
9639
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (ret < 0)
9640 ✗ goto fail;
9641
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 if (!ret)
9642 57 got_stream = 1;
9643 }
9644
9645 18 c->found_iinf = got_stream;
9646 18 return 0;
9647 ✗ fail:
9648 ✗ for (; i >= 0; i--) {
9649 ✗ HEIFItem *item = c->heif_item[i];
9650
9651 ✗ if (!item)
9652 ✗ continue;
9653
9654 ✗ av_freep(&item->name);
9655 }
9656 ✗ return ret;
9657 }
9658
9659 9 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
9660 {
9661 9 HEIFItem *item = NULL;
9662 HEIFGrid *grid;
9663 int entries, i;
9664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9665 9 int ret = 0;
9666
9667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 for (int i = 0; i < c->nb_heif_grid; i++) {
9668 ✗ if (c->heif_grid[i].item->item_id == from_item_id) {
9669 ✗ av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
9670 "referencing the same Derived Image item\n");
9671 ✗ return AVERROR_INVALIDDATA;
9672 }
9673 }
9674
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 for (int i = 0; i < c->nb_heif_item; i++) {
9675
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)
9676 26 continue;
9677 9 item = c->heif_item[i];
9678
9679
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 switch (item->type) {
9680 9 case MKTAG('g','r','i','d'):
9681 case MKTAG('i','o','v','l'):
9682 9 break;
9683 ✗ default:
9684 ✗ avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
9685 ✗ av_fourcc2str(item->type));
9686 ✗ return 0;
9687 }
9688 9 break;
9689 }
9690
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!item) {
9691 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing grid information\n");
9692 ✗ return AVERROR_INVALIDDATA;
9693 }
9694
9695 9 entries = avio_rb16(pb);
9696
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!entries) {
9697 ✗ av_log(c->fc, AV_LOG_ERROR,
9698 "Derived image item references no input images\n");
9699 ✗ return AVERROR_INVALIDDATA;
9700 }
9701
9702 9 grid = av_realloc_array(c->heif_grid, c->nb_heif_grid + 1U,
9703 sizeof(*c->heif_grid));
9704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!grid)
9705 ✗ return AVERROR(ENOMEM);
9706 9 c->heif_grid = grid;
9707 9 grid = &grid[c->nb_heif_grid];
9708
9709 9 grid->tile_id_list = av_malloc_array(entries, sizeof(*grid->tile_id_list));
9710 9 grid->tile_idx_list = av_calloc(entries, sizeof(*grid->tile_idx_list));
9711 9 grid->tile_item_list = av_calloc(entries, sizeof(*grid->tile_item_list));
9712
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) {
9713 ✗ ret = AVERROR(ENOMEM);
9714 ✗ goto fail;
9715 }
9716 /* 'to' item ids */
9717
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9 times.
37 for (i = 0; i < entries; i++) {
9718
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 grid->tile_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
9719
9720
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if (avio_feof(pb)) {
9721 ✗ ret = AVERROR_INVALIDDATA;
9722 ✗ goto fail;
9723 }
9724 }
9725
9726 9 grid->nb_tiles = entries;
9727 9 grid->item = item;
9728 9 ++c->nb_heif_grid;
9729
9730 9 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
9731 from_item_id, entries);
9732
9733 9 return 0;
9734 ✗ fail:
9735 ✗ av_freep(&grid->tile_id_list);
9736 ✗ av_freep(&grid->tile_idx_list);
9737 ✗ av_freep(&grid->tile_item_list);
9738
9739 ✗ return ret;
9740 }
9741
9742 11 static int mov_read_iref_cdsc(MOVContext *c, AVIOContext *pb, uint32_t type, int version, uint32_t size)
9743 {
9744 11 HEIFItem *from_item = NULL;
9745 int entries;
9746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 int item_id_size = version ? 4 : 2;
9747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9748 11 const HEIFItemRef ref = { type, from_item_id };
9749
9750 11 from_item = get_heif_item(c, from_item_id);
9751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!from_item) {
9752 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing stream referenced by thmb item\n");
9753 ✗ return AVERROR_INVALIDDATA;
9754 }
9755
9756 11 entries = avio_rb16(pb);
9757
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) {
9758 ✗ av_log(c->fc, AV_LOG_ERROR, "iref %s entry count %d exceeds the sub-box size\n",
9759 ✗ av_fourcc2str(type), entries);
9760 ✗ return AVERROR_INVALIDDATA;
9761 }
9762 /* 'to' item ids */
9763
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (int i = 0; i < entries; i++) {
9764
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));
9765
9766
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (avio_feof(pb))
9767 ✗ return AVERROR_INVALIDDATA;
9768
9769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!item) {
9770 ✗ av_log(c->fc, AV_LOG_WARNING, "Missing stream referenced by %s item\n",
9771 ✗ av_fourcc2str(type));
9772 ✗ continue;
9773 }
9774
9775
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (!av_dynarray2_add((void **)&item->iref_list, &item->nb_iref_list,
9776 sizeof(*item->iref_list), (const uint8_t *)&ref))
9777 ✗ return AVERROR(ENOMEM);
9778 }
9779
9780 11 av_log(c->fc, AV_LOG_TRACE, "%s: from_item_id %d, entries %d\n",
9781 11 av_fourcc2str(type), from_item_id, entries);
9782
9783 11 return 0;
9784 }
9785
9786 14 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9787 {
9788 14 int version = avio_r8(pb);
9789 int ret;
9790
9791 14 avio_rb24(pb); // flags
9792 14 atom.size -= 4;
9793
9794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (version > 1) {
9795 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
9796 ✗ return 0;
9797 }
9798
9799
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 14 times.
34 while (atom.size) {
9800 20 int64_t next = avio_tell(pb);
9801 20 uint32_t type, size = avio_rb32(pb);
9802
9803
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)
9804 ✗ return AVERROR_INVALIDDATA;
9805
9806 20 next += size;
9807 20 type = avio_rl32(pb);
9808
2/3
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
20 switch (type) {
9809 9 case MKTAG('d','i','m','g'):
9810 9 ret = mov_read_iref_dimg(c, pb, version);
9811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret < 0)
9812 ✗ return ret;
9813 20 break;
9814 11 case MKTAG('c','d','s','c'):
9815 case MKTAG('t','h','m','b'):
9816 11 ret = mov_read_iref_cdsc(c, pb, type, version, size - 8);
9817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0)
9818 ✗ return ret;
9819 11 break;
9820 ✗ default:
9821 ✗ av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
9822 ✗ av_fourcc2str(type), size);
9823 }
9824
9825 20 atom.size -= size;
9826 20 avio_seek(pb, next, SEEK_SET);
9827 }
9828 14 return 0;
9829 }
9830
9831 52 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9832 {
9833 HEIFItem *item;
9834 uint32_t width, height;
9835
9836 52 avio_r8(pb); /* version */
9837 52 avio_rb24(pb); /* flags */
9838 52 width = avio_rb32(pb);
9839 52 height = avio_rb32(pb);
9840
9841 52 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %"PRIu32", height %"PRIu32"\n",
9842 c->cur_item_id, width, height);
9843
9844
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) {
9845 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid ispe dimensions %"PRIu32"x%"PRIu32"\n",
9846 width, height);
9847 ✗ return AVERROR_INVALIDDATA;
9848 }
9849
9850 52 item = get_heif_item(c, c->cur_item_id);
9851
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 if (item) {
9852 52 item->width = width;
9853 52 item->height = height;
9854 }
9855
9856 52 return 0;
9857 }
9858
9859 8 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9860 {
9861 HEIFItem *item;
9862 int angle;
9863
9864 8 angle = avio_r8(pb) & 0x3;
9865
9866 8 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
9867 c->cur_item_id, angle);
9868
9869 8 item = get_heif_item(c, c->cur_item_id);
9870
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (item) {
9871 // angle * 90 specifies the angle (in anti-clockwise direction)
9872 // in units of degrees.
9873 8 item->rotation = angle * 90;
9874 }
9875
9876 8 return 0;
9877 }
9878
9879 6 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9880 {
9881 HEIFItem *item;
9882 int axis;
9883
9884 6 axis = avio_r8(pb) & 0x1;
9885
9886 6 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
9887 c->cur_item_id, axis);
9888
9889 6 item = get_heif_item(c, c->cur_item_id);
9890
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
9891 6 item->hflip = axis;
9892 6 item->vflip = !axis;
9893 }
9894
9895 6 return 0;
9896 }
9897
9898 18 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9899 {
9900 typedef struct MOVAtoms {
9901 FFIOContext b;
9902 uint32_t type;
9903 int64_t size;
9904 uint8_t *data;
9905 } MOVAtoms;
9906 18 MOVAtoms *atoms = NULL;
9907 MOVAtom a;
9908 unsigned count;
9909 18 int nb_atoms = 0;
9910 int version, flags;
9911 int ret;
9912
9913 18 a.size = avio_rb32(pb);
9914 18 a.type = avio_rl32(pb);
9915
9916
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'))
9917 ✗ return AVERROR_INVALIDDATA;
9918
9919 18 a.size -= 8;
9920
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 while (a.size >= 8) {
9921 80 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
9922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!ref) {
9923 ✗ ret = AVERROR(ENOMEM);
9924 ✗ goto fail;
9925 }
9926 80 ref->data = NULL;
9927 80 ref->size = avio_rb32(pb);
9928 80 ref->type = avio_rl32(pb);
9929
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)
9930 break;
9931 80 ref->data = av_malloc(ref->size);
9932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!ref->data) {
9933 ✗ ret = AVERROR_INVALIDDATA;
9934 ✗ goto fail;
9935 }
9936 80 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
9937 80 avio_seek(pb, -8, SEEK_CUR);
9938
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
80 if (avio_read(pb, ref->data, ref->size) != ref->size) {
9939 ✗ ret = AVERROR_INVALIDDATA;
9940 ✗ goto fail;
9941 }
9942 80 ffio_init_read_context(&ref->b, ref->data, ref->size);
9943 80 a.size -= ref->size;
9944 }
9945
9946
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (a.size) {
9947 ✗ ret = AVERROR_INVALIDDATA;
9948 ✗ goto fail;
9949 }
9950
9951 18 a.size = avio_rb32(pb);
9952 18 a.type = avio_rl32(pb);
9953
9954
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')) {
9955 ✗ ret = AVERROR_INVALIDDATA;
9956 ✗ goto fail;
9957 }
9958
9959 18 version = avio_r8(pb);
9960 18 flags = avio_rb24(pb);
9961 18 count = avio_rb32(pb);
9962
9963
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 18 times.
70 for (int i = 0; i < count; i++) {
9964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9965 52 int assoc_count = avio_r8(pb);
9966
9967
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
52 if (avio_feof(pb)) {
9968 ✗ ret = AVERROR_INVALIDDATA;
9969 ✗ goto fail;
9970 }
9971
9972
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 52 times.
177 for (int j = 0; j < assoc_count; j++) {
9973 MOVAtoms *ref;
9974 125 int index = avio_r8(pb) & 0x7f;
9975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 if (flags & 1) {
9976 ✗ index <<= 8;
9977 ✗ index |= avio_r8(pb);
9978 }
9979
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) {
9980 ✗ ret = AVERROR_INVALIDDATA;
9981 ✗ goto fail;
9982 }
9983 125 ref = &atoms[--index];
9984
9985 125 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
9986 125 index + 1, item_id, av_fourcc2str(ref->type));
9987
9988 125 c->cur_item_id = item_id;
9989
9990 125 ret = mov_read_default(c, &ref->b.pub,
9991 125 (MOVAtom) { .size = ref->size,
9992 .type = MKTAG('i','p','c','o') });
9993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 if (ret < 0)
9994 ✗ goto fail;
9995 125 ffio_init_read_context(&ref->b, ref->data, ref->size);
9996 }
9997 }
9998
9999 18 ret = 0;
10000 18 fail:
10001 18 c->cur_item_id = -1;
10002
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 for (int i = 0; i < nb_atoms; i++)
10003 80 av_free(atoms[i].data);
10004 18 av_free(atoms);
10005
10006 18 return ret;
10007 }
10008
10009 373 static int mov_read_vmhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10010 {
10011 373 avio_rb32(pb); // version & flags
10012 373 uint16_t graphics_mode = avio_rb16(pb);
10013 // ignored: opcolor[3]
10014
10015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 373 times.
373 if (c->fc->nb_streams < 1)
10016 ✗ return 0;
10017 373 AVStream *st = c->fc->streams[c->fc->nb_streams - 1];
10018
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 373 times.
373 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
10019 ✗ return 0;
10020
10021
2/4
✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
373 switch (graphics_mode) {
10022 372 case MOV_GRAPHICS_MODE_COPY:
10023 case MOV_GRAPHICS_MODE_DITHER_COPY:
10024 372 st->codecpar->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
10025 372 break;
10026 ✗ case MOV_GRAPHICS_MODE_STRAIGHT_ALPHA:
10027 ✗ st->codecpar->alpha_mode = AVALPHA_MODE_STRAIGHT;
10028 ✗ break;
10029 ✗ case MOV_GRAPHICS_MODE_PREMUL_BLACK_ALPHA:
10030 ✗ st->codecpar->alpha_mode = AVALPHA_MODE_PREMULTIPLIED;
10031 ✗ break;
10032 1 default:
10033 1 st->codecpar->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
10034 1 av_log(c->fc, AV_LOG_WARNING, "Unhandled graphics mode: 0x%x\n",
10035 graphics_mode);
10036 1 break;
10037 }
10038
10039 373 return 0;
10040 }
10041
10042 static const MOVParseTableEntry mov_default_parse_table[] = {
10043 { MKTAG('A','C','L','R'), mov_read_aclr },
10044 { MKTAG('A','P','R','G'), mov_read_avid },
10045 { MKTAG('A','A','L','P'), mov_read_avid },
10046 { MKTAG('A','R','E','S'), mov_read_ares },
10047 { MKTAG('a','v','s','s'), mov_read_avss },
10048 { MKTAG('a','v','1','C'), mov_read_glbl },
10049 { MKTAG('c','h','p','l'), mov_read_chpl },
10050 { MKTAG('c','o','6','4'), mov_read_stco },
10051 { MKTAG('c','o','l','r'), mov_read_colr },
10052 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
10053 { MKTAG('d','i','n','f'), mov_read_default },
10054 { MKTAG('D','p','x','E'), mov_read_dpxe },
10055 { MKTAG('d','r','e','f'), mov_read_dref },
10056 { MKTAG('e','d','t','s'), mov_read_default },
10057 { MKTAG('e','l','s','t'), mov_read_elst },
10058 { MKTAG('e','n','d','a'), mov_read_enda },
10059 { MKTAG('f','i','e','l'), mov_read_fiel },
10060 { MKTAG('a','d','r','m'), mov_read_adrm },
10061 { MKTAG('f','t','y','p'), mov_read_ftyp },
10062 { MKTAG('g','l','b','l'), mov_read_glbl },
10063 { MKTAG('h','d','l','r'), mov_read_hdlr },
10064 { MKTAG('i','l','s','t'), mov_read_ilst },
10065 { MKTAG('j','p','2','h'), mov_read_jp2h },
10066 { MKTAG('m','d','a','t'), mov_read_mdat },
10067 { MKTAG('m','d','h','d'), mov_read_mdhd },
10068 { MKTAG('m','d','i','a'), mov_read_default },
10069 { MKTAG('m','e','t','a'), mov_read_meta },
10070 { MKTAG('m','i','n','f'), mov_read_default },
10071 { MKTAG('m','o','o','f'), mov_read_moof },
10072 { MKTAG('m','o','o','v'), mov_read_moov },
10073 { MKTAG('m','v','e','x'), mov_read_default },
10074 { MKTAG('m','v','h','d'), mov_read_mvhd },
10075 { MKTAG('S','M','I',' '), mov_read_svq3 },
10076 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
10077 { MKTAG('a','v','c','C'), mov_read_glbl },
10078 { MKTAG('p','a','s','p'), mov_read_pasp },
10079 { MKTAG('c','l','a','p'), mov_read_clap },
10080 { MKTAG('c','d','s','c'), mov_read_cdsc_rndr },
10081 { MKTAG('r','n','d','r'), mov_read_cdsc_rndr },
10082 { MKTAG('s','b','a','s'), mov_read_sbas },
10083 { MKTAG('v','d','e','p'), mov_read_vdep },
10084 { MKTAG('s','i','d','x'), mov_read_sidx },
10085 { MKTAG('s','t','b','l'), mov_read_default },
10086 { MKTAG('s','t','c','o'), mov_read_stco },
10087 { MKTAG('s','t','p','s'), mov_read_stps },
10088 { MKTAG('s','t','r','f'), mov_read_strf },
10089 { MKTAG('s','t','s','c'), mov_read_stsc },
10090 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
10091 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
10092 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
10093 { MKTAG('s','t','t','s'), mov_read_stts },
10094 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
10095 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
10096 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
10097 { MKTAG('t','f','d','t'), mov_read_tfdt },
10098 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
10099 { MKTAG('t','r','a','k'), mov_read_trak },
10100 { MKTAG('t','r','a','f'), mov_read_default },
10101 { MKTAG('t','r','e','f'), mov_read_default },
10102 { MKTAG('t','m','c','d'), mov_read_tmcd },
10103 { MKTAG('c','h','a','p'), mov_read_chap },
10104 { MKTAG('t','r','e','x'), mov_read_trex },
10105 { MKTAG('t','r','u','n'), mov_read_trun },
10106 { MKTAG('u','d','t','a'), mov_read_default },
10107 { MKTAG('w','a','v','e'), mov_read_wave },
10108 { MKTAG('e','s','d','s'), mov_read_esds },
10109 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
10110 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
10111 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
10112 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
10113 { MKTAG('w','f','e','x'), mov_read_wfex },
10114 { MKTAG('c','m','o','v'), mov_read_cmov },
10115 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
10116 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
10117 { MKTAG('d','v','c','1'), mov_read_dvc1 },
10118 { MKTAG('s','g','p','d'), mov_read_sgpd },
10119 { MKTAG('s','b','g','p'), mov_read_sbgp },
10120 { MKTAG('h','v','c','C'), mov_read_glbl },
10121 { MKTAG('v','v','c','C'), mov_read_glbl },
10122 { MKTAG('u','u','i','d'), mov_read_uuid },
10123 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
10124 { MKTAG('f','r','e','e'), mov_read_free },
10125 { MKTAG('-','-','-','-'), mov_read_custom },
10126 { MKTAG('s','i','n','f'), mov_read_default },
10127 { MKTAG('f','r','m','a'), mov_read_frma },
10128 { MKTAG('s','e','n','c'), mov_read_senc },
10129 { MKTAG('s','a','i','z'), mov_read_saiz },
10130 { MKTAG('s','a','i','o'), mov_read_saio },
10131 { MKTAG('p','s','s','h'), mov_read_pssh },
10132 { MKTAG('s','c','h','m'), mov_read_schm },
10133 { MKTAG('s','c','h','i'), mov_read_default },
10134 { MKTAG('t','e','n','c'), mov_read_tenc },
10135 { MKTAG('d','f','L','a'), mov_read_dfla },
10136 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
10137 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
10138 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
10139 { MKTAG('h','f','o','v'), mov_read_hfov },
10140 { MKTAG('d','O','p','s'), mov_read_dops },
10141 { MKTAG('d','m','l','p'), mov_read_dmlp },
10142 { MKTAG('S','m','D','m'), mov_read_smdm },
10143 { MKTAG('C','o','L','L'), mov_read_coll },
10144 { MKTAG('v','p','c','C'), mov_read_vpcc },
10145 { MKTAG('m','d','c','v'), mov_read_mdcv },
10146 { MKTAG('c','l','l','i'), mov_read_clli },
10147 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
10148 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
10149 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
10150 { MKTAG('h','v','c','E'), mov_read_hvce },
10151 { MKTAG('k','i','n','d'), mov_read_kind },
10152 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
10153 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
10154 { MKTAG('i','l','o','c'), mov_read_iloc },
10155 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
10156 { MKTAG('p','i','t','m'), mov_read_pitm },
10157 { MKTAG('e','v','c','C'), mov_read_glbl },
10158 { MKTAG('i','d','a','t'), mov_read_idat },
10159 { MKTAG('i','m','i','r'), mov_read_imir },
10160 { MKTAG('i','r','e','f'), mov_read_iref },
10161 { MKTAG('i','s','p','e'), mov_read_ispe },
10162 { MKTAG('i','r','o','t'), mov_read_irot },
10163 { MKTAG('i','p','r','p'), mov_read_iprp },
10164 { MKTAG('i','i','n','f'), mov_read_iinf },
10165 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
10166 { MKTAG('l','h','v','C'), mov_read_lhvc },
10167 { MKTAG('l','v','c','C'), mov_read_glbl },
10168 { MKTAG('a','p','v','C'), mov_read_glbl },
10169 #if CONFIG_IAMFDEC
10170 { MKTAG('i','a','c','b'), mov_read_iacb },
10171 #endif
10172 { MKTAG('s','r','a','t'), mov_read_srat },
10173 { MKTAG('v','m','h','d'), mov_read_vmhd },
10174 { 0, NULL }
10175 };
10176
10177 7955 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10178 {
10179 7955 int64_t total_size = 0;
10180 MOVAtom a;
10181 int i;
10182
10183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7955 times.
7955 if (c->atom_depth > 10) {
10184 ✗ av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
10185 ✗ return AVERROR_INVALIDDATA;
10186 }
10187 7955 c->atom_depth ++;
10188
10189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7955 times.
7955 if (atom.size < 0)
10190 ✗ atom.size = INT64_MAX;
10191
2/2
✓ Branch 0 taken 22716 times.
✓ Branch 1 taken 7359 times.
30075 while (total_size <= atom.size - 8) {
10192 22716 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
10193 22716 a.size = avio_rb32(pb);
10194 22716 a.type = avio_rl32(pb);
10195
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 22709 times.
22716 if (avio_feof(pb))
10196 7 break;
10197
3/4
✓ Branch 0 taken 260 times.
✓ Branch 1 taken 22449 times.
✓ Branch 2 taken 260 times.
✗ Branch 3 not taken.
22709 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
10198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22709 times.
22709 a.type == MKTAG('h','o','o','v')) &&
10199 ✗ a.size >= 8 &&
10200 ✗ c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
10201 uint32_t type;
10202 ✗ avio_skip(pb, 4);
10203 ✗ type = avio_rl32(pb);
10204 ✗ if (avio_feof(pb))
10205 ✗ break;
10206 ✗ avio_seek(pb, -8, SEEK_CUR);
10207 ✗ if (type == MKTAG('m','v','h','d') ||
10208 type == MKTAG('c','m','o','v')) {
10209 ✗ av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
10210 ✗ a.type = MKTAG('m','o','o','v');
10211 }
10212 }
10213
2/2
✓ Branch 0 taken 19402 times.
✓ Branch 1 taken 3307 times.
22709 if (atom.type != MKTAG('r','o','o','t') &&
10214
2/2
✓ Branch 0 taken 17653 times.
✓ Branch 1 taken 1749 times.
19402 atom.type != MKTAG('m','o','o','v')) {
10215
1/2
✓ Branch 0 taken 17653 times.
✗ Branch 1 not taken.
17653 if (a.type == MKTAG('t','r','a','k') ||
10216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17653 times.
17653 a.type == MKTAG('m','d','a','t')) {
10217 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
10218 ✗ avio_skip(pb, -8);
10219 ✗ c->atom_depth --;
10220 589 return 0;
10221 }
10222 }
10223 22709 total_size += 8;
10224
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 22680 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
22709 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
10225 29 a.size = avio_rb64(pb) - 8;
10226 29 total_size += 8;
10227 }
10228 22709 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
10229 22709 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
10230
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 22704 times.
22709 if (a.size == 0) {
10231 5 a.size = atom.size - total_size + 8;
10232 }
10233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22709 times.
22709 if (a.size < 0)
10234 ✗ break;
10235 22709 a.size -= 8;
10236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22709 times.
22709 if (a.size < 0)
10237 ✗ break;
10238 22709 a.size = FFMIN(a.size, atom.size - total_size);
10239
10240
2/2
✓ Branch 0 taken 1092277 times.
✓ Branch 1 taken 1940 times.
1094217 for (i = 0; mov_default_parse_table[i].type; i++)
10241
2/2
✓ Branch 0 taken 20769 times.
✓ Branch 1 taken 1071508 times.
1092277 if (mov_default_parse_table[i].type == a.type) {
10242 20769 parse = mov_default_parse_table[i].parse;
10243 20769 break;
10244 }
10245
10246 // container is user data
10247
4/4
✓ Branch 0 taken 1940 times.
✓ Branch 1 taken 20769 times.
✓ Branch 2 taken 1740 times.
✓ Branch 3 taken 200 times.
22709 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
10248
2/2
✓ Branch 0 taken 433 times.
✓ Branch 1 taken 1307 times.
1740 atom.type == MKTAG('i','l','s','t')))
10249 633 parse = mov_read_udta_string;
10250
10251 // Supports parsing the QuickTime Metadata Keys.
10252 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
10253
4/4
✓ Branch 0 taken 1307 times.
✓ Branch 1 taken 21402 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 1293 times.
22709 if (!parse && c->found_hdlr_mdta &&
10254
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 atom.type == MKTAG('m','e','t','a') &&
10255
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 a.type == MKTAG('k','e','y','s') &&
10256
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 c->meta_keys_count == 0) {
10257 14 parse = mov_read_keys;
10258 }
10259
10260
2/2
✓ Branch 0 taken 1293 times.
✓ Branch 1 taken 21416 times.
22709 if (!parse) { /* skip leaf atoms data */
10261 1293 avio_skip(pb, a.size);
10262 } else {
10263 21416 int64_t start_pos = avio_tell(pb);
10264 int64_t left;
10265 21416 int err = parse(c, pb, a);
10266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21416 times.
21416 if (err < 0) {
10267 ✗ c->atom_depth --;
10268 ✗ return err;
10269 }
10270
5/6
✓ Branch 0 taken 3876 times.
✓ Branch 1 taken 17540 times.
✓ Branch 2 taken 3450 times.
✓ Branch 3 taken 426 times.
✓ Branch 4 taken 3450 times.
✗ Branch 5 not taken.
21416 if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos &&
10271
7/8
✓ Branch 0 taken 3449 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3449 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3435 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 574 times.
✓ Branch 7 taken 2861 times.
6885 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
10272 3435 start_pos + a.size == avio_size(pb))) {
10273
5/6
✓ Branch 0 taken 588 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 588 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 574 times.
589 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
10274 15 c->next_root_atom = start_pos + a.size;
10275 589 c->atom_depth --;
10276 589 return 0;
10277 }
10278 20827 left = a.size - avio_tell(pb) + start_pos;
10279
2/2
✓ Branch 0 taken 2144 times.
✓ Branch 1 taken 18683 times.
20827 if (left > 0) /* skip garbage at atom end */
10280 2144 avio_skip(pb, left);
10281
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18681 times.
18683 else if (left < 0) {
10282 2 av_log(c->fc, AV_LOG_WARNING,
10283 "overread end of atom '%s' by %"PRId64" bytes\n",
10284 2 av_fourcc2str(a.type), -left);
10285 2 avio_seek(pb, left, SEEK_CUR);
10286 }
10287 }
10288
10289 22120 total_size += a.size;
10290 }
10291
10292
4/4
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 7236 times.
✓ Branch 2 taken 123 times.
✓ Branch 3 taken 7 times.
7366 if (total_size < atom.size && atom.size < 0x7ffff)
10293 123 avio_skip(pb, atom.size - total_size);
10294
10295 7366 c->atom_depth --;
10296 7366 return 0;
10297 }
10298
10299 8071 static int mov_probe(const AVProbeData *p)
10300 {
10301 int64_t offset;
10302 uint32_t tag;
10303 8071 int score = 0;
10304 8071 int moov_offset = -1;
10305
10306 /* check file header */
10307 8071 offset = 0;
10308 9963 for (;;) {
10309 int64_t size;
10310 18034 int minsize = 8;
10311 /* ignore invalid offset */
10312
2/2
✓ Branch 0 taken 8071 times.
✓ Branch 1 taken 9963 times.
18034 if ((offset + 8ULL) > (unsigned int)p->buf_size)
10313 8071 break;
10314 9963 size = AV_RB32(p->buf + offset);
10315
3/4
✓ Branch 0 taken 541 times.
✓ Branch 1 taken 9422 times.
✓ Branch 2 taken 541 times.
✗ Branch 3 not taken.
9963 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
10316 541 size = AV_RB64(p->buf+offset + 8);
10317 541 minsize = 16;
10318
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 9350 times.
9422 } else if (size == 0) {
10319 72 size = p->buf_size - offset;
10320 }
10321
2/2
✓ Branch 0 taken 411 times.
✓ Branch 1 taken 9552 times.
9963 if (size < minsize) {
10322 411 offset += 4;
10323 411 continue;
10324 }
10325 9552 tag = AV_RL32(p->buf + offset + 4);
10326
5/6
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 1004 times.
✓ Branch 2 taken 429 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7961 times.
9552 switch(tag) {
10327 /* check for obvious tags */
10328 157 case MKTAG('m','o','o','v'):
10329 157 moov_offset = offset + 4;
10330 av_fallthrough;
10331 1161 case MKTAG('m','d','a','t'):
10332 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
10333 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
10334 case MKTAG('f','t','y','p'):
10335
2/2
✓ Branch 0 taken 520 times.
✓ Branch 1 taken 641 times.
1161 if (tag == MKTAG('f','t','y','p') &&
10336
1/2
✓ Branch 0 taken 520 times.
✗ Branch 1 not taken.
520 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
10337
1/2
✓ Branch 0 taken 520 times.
✗ Branch 1 not taken.
520 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
10338
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 513 times.
520 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
10339 )) {
10340 7 score = FFMAX(score, 5);
10341 } else {
10342 1154 score = AVPROBE_SCORE_MAX;
10343 }
10344 1161 break;
10345 /* those are more common words, so rate then a bit less */
10346 429 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
10347 case MKTAG('w','i','d','e'):
10348 case MKTAG('f','r','e','e'):
10349 case MKTAG('j','u','n','k'):
10350 case MKTAG('p','i','c','t'):
10351 429 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
10352 429 break;
10353 ✗ case MKTAG(0x82,0x82,0x7f,0x7d):
10354 ✗ score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
10355 ✗ break;
10356 1 case MKTAG('s','k','i','p'):
10357 case MKTAG('u','u','i','d'):
10358 case MKTAG('p','r','f','l'):
10359 /* if we only find those cause probedata is too small at least rate them */
10360 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
10361 1 break;
10362 }
10363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9552 times.
9552 if (size > INT64_MAX - offset)
10364 ✗ break;
10365 9552 offset += size;
10366 }
10367
4/4
✓ Branch 0 taken 567 times.
✓ Branch 1 taken 7504 times.
✓ Branch 2 taken 157 times.
✓ Branch 3 taken 410 times.
8071 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
10368 /* moov atom in the header - we should make sure that this is not a
10369 * MOV-packed MPEG-PS */
10370 157 offset = moov_offset;
10371
10372
2/2
✓ Branch 0 taken 153634 times.
✓ Branch 1 taken 157 times.
153791 while (offset < (p->buf_size - 16)) { /* Sufficient space */
10373 /* We found an actual hdlr atom */
10374
2/2
✓ Branch 0 taken 173 times.
✓ Branch 1 taken 153461 times.
153634 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
10375
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 148 times.
173 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
10376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
10377 ✗ av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
10378 /* We found a media handler reference atom describing an
10379 * MPEG-PS-in-MOV, return a
10380 * low score to force expanding the probe window until
10381 * mpegps_probe finds what it needs */
10382 ✗ return 5;
10383 } else {
10384 /* Keep looking */
10385 153634 offset += 2;
10386 }
10387 }
10388 }
10389
10390 8071 return score;
10391 }
10392
10393 // must be done after parsing all trak because there's no order requirement
10394 2 static void mov_read_chapters(AVFormatContext *s)
10395 {
10396 2 MOVContext *mov = s->priv_data;
10397 MOVStreamContext *sc;
10398 int64_t cur_pos;
10399 int i, j;
10400 int chapter_track;
10401
10402
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
10403 2 AVStream *st = NULL;
10404 2 FFStream *sti = NULL;
10405 2 chapter_track = mov->chapter_tracks[j];
10406
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
10407 4 sc = mov->fc->streams[i]->priv_data;
10408
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
10409 2 st = s->streams[i];
10410 2 break;
10411 }
10412 }
10413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
10414 ✗ av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
10415 ✗ continue;
10416 }
10417 2 sti = ffstream(st);
10418
10419 2 sc = st->priv_data;
10420 2 cur_pos = avio_tell(sc->pb);
10421
10422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
10423 ✗ st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
10424 ✗ if (!st->attached_pic.data && sti->nb_index_entries) {
10425 // Retrieve the first frame, if possible
10426 ✗ AVIndexEntry *sample = &sti->index_entries[0];
10427 ✗ if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10428 ✗ av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
10429 ✗ goto finish;
10430 }
10431
10432 ✗ if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
10433 ✗ goto finish;
10434 }
10435 } else {
10436 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10437 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
10438 2 st->discard = AVDISCARD_ALL;
10439
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
10440 8 AVIndexEntry *sample = &sti->index_entries[i];
10441
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;
10442 uint8_t *title;
10443 uint16_t ch;
10444 int len, title_len;
10445
10446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
10447 ✗ av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
10448 ✗ end = AV_NOPTS_VALUE;
10449 }
10450
10451
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10452 ✗ av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
10453 ✗ goto finish;
10454 }
10455
10456 // the first two bytes are the length of the title
10457 8 len = avio_rb16(sc->pb);
10458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
10459 ✗ continue;
10460 8 title_len = 2*len + 1;
10461
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
10462 ✗ goto finish;
10463
10464 // The samples could theoretically be in any encoding if there's an encd
10465 // atom following, but in practice are only utf-8 or utf-16, distinguished
10466 // instead by the presence of a BOM
10467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
10468 ✗ title[0] = 0;
10469 } else {
10470 8 ch = avio_rb16(sc->pb);
10471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
10472 ✗ avio_get_str16be(sc->pb, len, title, title_len);
10473
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
10474 ✗ avio_get_str16le(sc->pb, len, title, title_len);
10475 else {
10476 8 AV_WB16(title, ch);
10477
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)
10478 ✗ title[len] = 0;
10479 else
10480 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
10481 }
10482 }
10483
10484 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
10485 8 av_freep(&title);
10486 }
10487 }
10488 2 finish:
10489 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
10490 }
10491 2 }
10492
10493 28 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
10494 int64_t value, int flags)
10495 {
10496 AVTimecode tc;
10497 char buf[AV_TIMECODE_STR_SIZE];
10498 28 AVRational rate = st->avg_frame_rate;
10499 28 int ret = av_timecode_init(&tc, rate, flags, 0, s);
10500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
10501 ✗ return ret;
10502 28 av_dict_set(&st->metadata, "timecode",
10503 28 av_timecode_make_string(&tc, buf, value), 0);
10504 28 return 0;
10505 }
10506
10507 ✗ static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
10508 {
10509 ✗ MOVStreamContext *sc = st->priv_data;
10510 ✗ FFStream *const sti = ffstream(st);
10511 char buf[AV_TIMECODE_STR_SIZE];
10512 ✗ int64_t cur_pos = avio_tell(sc->pb);
10513 int hh, mm, ss, ff, drop;
10514
10515 ✗ if (!sti->nb_index_entries)
10516 ✗ return -1;
10517
10518 ✗ avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10519 ✗ avio_skip(s->pb, 13);
10520 ✗ hh = avio_r8(s->pb);
10521 ✗ mm = avio_r8(s->pb);
10522 ✗ ss = avio_r8(s->pb);
10523 ✗ drop = avio_r8(s->pb);
10524 ✗ ff = avio_r8(s->pb);
10525 ✗ snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
10526 hh, mm, ss, drop ? ';' : ':', ff);
10527 ✗ av_dict_set(&st->metadata, "timecode", buf, 0);
10528
10529 ✗ avio_seek(sc->pb, cur_pos, SEEK_SET);
10530 ✗ return 0;
10531 }
10532
10533 28 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
10534 {
10535 28 MOVStreamContext *sc = st->priv_data;
10536 28 FFStream *const sti = ffstream(st);
10537 28 int flags = 0;
10538 28 int64_t cur_pos = avio_tell(sc->pb);
10539 int64_t value;
10540 28 AVRational tc_rate = st->avg_frame_rate;
10541 28 int tmcd_nb_frames = sc->tmcd_nb_frames;
10542 int rounded_tc_rate;
10543
10544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!sti->nb_index_entries)
10545 ✗ return -1;
10546
10547
3/6
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 28 times.
28 if (!tc_rate.num || !tc_rate.den || !tmcd_nb_frames)
10548 ✗ return -1;
10549
10550 28 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10551 28 value = avio_rb32(s->pb);
10552
10553
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 10 times.
28 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
10554
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
10555
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
10556
10557 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
10558 * not the case) and thus assume "frame number format" instead of QT one.
10559 * No sample with tmcd track can be found with a QT timecode at the moment,
10560 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
10561 * format). */
10562
10563 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
10564 * we multiply the frame number with the quotient.
10565 * See tickets #9492, #9710. */
10566 28 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
10567 /* Work around files where tmcd_nb_frames is rounded down from frame rate
10568 * instead of up. See ticket #5978. */
10569
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 18 times.
28 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
10570
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
10571 10 tmcd_nb_frames = rounded_tc_rate;
10572 28 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
10573
10574 28 parse_timecode_in_framenum_format(s, st, value, flags);
10575
10576 28 avio_seek(sc->pb, cur_pos, SEEK_SET);
10577 28 return 0;
10578 }
10579
10580 1369 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
10581 int i;
10582
3/4
✓ Branch 0 taken 1369 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1356 times.
✓ Branch 3 taken 13 times.
1369 if (!index || !*index) return;
10583
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 13 times.
208 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
10584 195 av_encryption_info_free((*index)->encrypted_samples[i]);
10585 }
10586 13 av_freep(&(*index)->encrypted_samples);
10587 13 av_freep(&(*index)->auxiliary_info_sizes);
10588 13 av_freep(&(*index)->auxiliary_offsets);
10589 13 av_freep(index);
10590 }
10591
10592 840 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
10593 {
10594 840 MOVStreamContext *sc = st->priv_data;
10595
10596
3/4
✓ Branch 0 taken 840 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 788 times.
840 if (!sc || --sc->refcount) {
10597 52 st->priv_data = NULL;
10598 52 return;
10599 }
10600
10601 788 av_freep(&sc->tts_data);
10602
2/2
✓ Branch 0 taken 729 times.
✓ Branch 1 taken 788 times.
1517 for (int i = 0; i < sc->drefs_count; i++) {
10603 729 av_freep(&sc->drefs[i].path);
10604 729 av_freep(&sc->drefs[i].dir);
10605 }
10606 788 av_freep(&sc->drefs);
10607
10608 788 sc->drefs_count = 0;
10609
10610
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 772 times.
788 if (!sc->pb_is_copied)
10611 16 ff_format_io_close(s, &sc->pb);
10612
10613 788 sc->pb = NULL;
10614 788 av_freep(&sc->chunk_offsets);
10615 788 av_freep(&sc->stsc_data);
10616 788 av_freep(&sc->sample_sizes);
10617 788 av_freep(&sc->keyframes);
10618 788 av_freep(&sc->ctts_data);
10619 788 av_freep(&sc->stts_data);
10620 788 av_freep(&sc->sdtp_data);
10621 788 av_freep(&sc->stps_data);
10622 788 av_freep(&sc->elst_data);
10623 788 av_freep(&sc->rap_group);
10624 788 av_freep(&sc->sync_group);
10625 788 av_freep(&sc->sgpd_sync);
10626 788 av_freep(&sc->sample_offsets);
10627 788 av_freep(&sc->open_key_samples);
10628 788 av_freep(&sc->display_matrix);
10629 788 av_freep(&sc->index_ranges);
10630
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 788 times.
820 for (int i = 0; i < sc->nb_tref_tags; i++)
10631 32 av_freep(&sc->tref_tags[i].id);
10632 788 av_freep(&sc->tref_tags);
10633
10634
2/2
✓ Branch 0 taken 729 times.
✓ Branch 1 taken 59 times.
788 if (sc->extradata)
10635
2/2
✓ Branch 0 taken 746 times.
✓ Branch 1 taken 729 times.
1475 for (int i = 0; i < sc->stsd_count; i++)
10636 746 av_free(sc->extradata[i]);
10637 788 av_freep(&sc->extradata);
10638 788 av_freep(&sc->extradata_size);
10639
10640 788 mov_free_encryption_index(&sc->cenc.encryption_index);
10641 788 av_encryption_info_free(sc->cenc.default_encrypted_sample);
10642 788 av_aes_ctr_free(sc->cenc.aes_ctr);
10643
10644 788 av_freep(&sc->stereo3d);
10645 788 av_freep(&sc->spherical);
10646 788 av_freep(&sc->mastering);
10647 788 av_freep(&sc->coll);
10648 788 av_freep(&sc->ambient);
10649
10650 #if CONFIG_IAMFDEC
10651
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 776 times.
788 if (sc->iamf)
10652 12 ff_iamf_read_deinit(sc->iamf);
10653 #endif
10654 788 av_freep(&sc->iamf);
10655 }
10656
10657 613 static int mov_read_close(AVFormatContext *s)
10658 {
10659 613 MOVContext *mov = s->priv_data;
10660 int i, j;
10661
10662
2/2
✓ Branch 0 taken 840 times.
✓ Branch 1 taken 613 times.
1453 for (i = 0; i < s->nb_streams; i++) {
10663 840 AVStream *st = s->streams[i];
10664
10665 840 mov_free_stream_context(s, st);
10666 }
10667
10668 613 av_freep(&mov->dv_demux);
10669 613 avformat_free_context(mov->dv_fctx);
10670 613 mov->dv_fctx = NULL;
10671
10672
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 599 times.
613 if (mov->meta_keys) {
10673
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 14 times.
114 for (i = 1; i < mov->meta_keys_count; i++) {
10674 100 av_freep(&mov->meta_keys[i]);
10675 }
10676 14 av_freep(&mov->meta_keys);
10677 }
10678
10679 613 av_freep(&mov->trex_data);
10680 613 av_freep(&mov->bitrates);
10681
10682
2/2
✓ Branch 0 taken 479 times.
✓ Branch 1 taken 613 times.
1092 for (i = 0; i < mov->frag_index.nb_items; i++) {
10683 479 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
10684
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++) {
10685 581 mov_free_encryption_index(&frag[j].encryption_index);
10686 }
10687 479 av_freep(&mov->frag_index.item[i].stream_info);
10688 }
10689 613 av_freep(&mov->frag_index.item);
10690
10691 613 av_freep(&mov->aes_decrypt);
10692 613 av_freep(&mov->chapter_tracks);
10693
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 613 times.
670 for (i = 0; i < mov->nb_heif_item; i++) {
10694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!mov->heif_item[i])
10695 ✗ continue;
10696 57 av_freep(&mov->heif_item[i]->name);
10697 57 av_freep(&mov->heif_item[i]->iref_list);
10698 57 av_freep(&mov->heif_item[i]->icc_profile);
10699 57 av_freep(&mov->heif_item[i]);
10700 }
10701 613 av_freep(&mov->heif_item);
10702
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 613 times.
622 for (i = 0; i < mov->nb_heif_grid; i++) {
10703 9 av_freep(&mov->heif_grid[i].tile_id_list);
10704 9 av_freep(&mov->heif_grid[i].tile_idx_list);
10705 9 av_freep(&mov->heif_grid[i].tile_item_list);
10706 }
10707 613 av_freep(&mov->heif_grid);
10708
10709 613 return 0;
10710 }
10711
10712 28 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
10713 {
10714 int i;
10715
10716
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 for (i = 0; i < s->nb_streams; i++) {
10717 28 AVStream *st = s->streams[i];
10718 28 MOVStreamContext *sc = st->priv_data;
10719 28 MovTref *tag = mov_find_tref_tag(sc, MKTAG('t','m','c','d'));
10720
10721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!tag)
10722 ✗ continue;
10723
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 if (mov_find_tref_id(tag, tmcd_id))
10724 28 return 1;
10725 }
10726 ✗ return 0;
10727 }
10728
10729 /* look for a tmcd track not referenced by any video track, and export it globally */
10730 613 static void export_orphan_timecode(AVFormatContext *s)
10731 {
10732 int i;
10733
10734
2/2
✓ Branch 0 taken 840 times.
✓ Branch 1 taken 613 times.
1453 for (i = 0; i < s->nb_streams; i++) {
10735 840 AVStream *st = s->streams[i];
10736
10737
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 812 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
868 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
10738 28 !tmcd_is_referenced(s, st->id)) {
10739 ✗ AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
10740 ✗ if (tcr) {
10741 ✗ av_dict_set(&s->metadata, "timecode", tcr->value, 0);
10742 ✗ break;
10743 }
10744 }
10745 }
10746 613 }
10747
10748 3 static int read_tfra(MOVContext *mov, AVIOContext *f)
10749 {
10750 int version, fieldlength, i, j;
10751 3 int64_t pos = avio_tell(f);
10752 3 uint32_t size = avio_rb32(f);
10753 unsigned track_id, item_count;
10754
10755
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
10756 1 return 1;
10757 }
10758 2 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
10759
10760 2 version = avio_r8(f);
10761 2 avio_rb24(f);
10762 2 track_id = avio_rb32(f);
10763 2 fieldlength = avio_rb32(f);
10764 2 item_count = avio_rb32(f);
10765
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (i = 0; i < item_count; i++) {
10766 int64_t time, offset;
10767 int index;
10768 MOVFragmentStreamInfo * frag_stream_info;
10769
10770
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (avio_feof(f)) {
10771 ✗ return AVERROR_INVALIDDATA;
10772 }
10773
10774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1) {
10775 ✗ time = avio_rb64(f);
10776 ✗ offset = avio_rb64(f);
10777 } else {
10778 6 time = avio_rb32(f);
10779 6 offset = avio_rb32(f);
10780 }
10781
10782 // The first sample of each stream in a fragment is always a random
10783 // access sample. So it's entry in the tfra can be used as the
10784 // initial PTS of the fragment.
10785 6 index = update_frag_index(mov, offset);
10786 6 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
10787
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (frag_stream_info &&
10788
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
10789 6 frag_stream_info->first_tfra_pts = time;
10790
10791
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
10792 6 avio_r8(f);
10793
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
10794 6 avio_r8(f);
10795
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
10796 6 avio_r8(f);
10797 }
10798
10799 2 avio_seek(f, pos + size, SEEK_SET);
10800 2 return 0;
10801 }
10802
10803 1 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
10804 {
10805 1 int64_t stream_size = avio_size(f);
10806 1 int64_t original_pos = avio_tell(f);
10807 int64_t seek_ret;
10808 1 int ret = -1;
10809
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
10810 ✗ ret = seek_ret;
10811 ✗ goto fail;
10812 }
10813 1 c->mfra_size = avio_rb32(f);
10814 1 c->have_read_mfra_size = 1;
10815
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) {
10816 ✗ av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
10817 ✗ goto fail;
10818 }
10819
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) {
10820 ✗ ret = seek_ret;
10821 ✗ goto fail;
10822 }
10823
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != c->mfra_size) {
10824 ✗ av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
10825 ✗ goto fail;
10826 }
10827
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
10828 ✗ av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
10829 ✗ goto fail;
10830 }
10831 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
10832 do {
10833 3 ret = read_tfra(c, f);
10834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
10835 ✗ goto fail;
10836
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 } while (!ret);
10837 1 ret = 0;
10838 1 c->frag_index.complete = 1;
10839 1 fail:
10840 1 seek_ret = avio_seek(f, original_pos, SEEK_SET);
10841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (seek_ret < 0) {
10842 ✗ av_log(c->fc, AV_LOG_ERROR,
10843 "failed to seek back after looking for mfra\n");
10844 ✗ ret = seek_ret;
10845 }
10846 1 return ret;
10847 }
10848
10849 ✗ static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10850 const HEIFItem *item)
10851 {
10852 ✗ AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
10853 AV_PKT_DATA_ICC_PROFILE,
10854 ✗ item->icc_profile_size, 0);
10855 ✗ if (!sd)
10856 ✗ return AVERROR(ENOMEM);
10857
10858 ✗ memcpy(sd->data, item->icc_profile, item->icc_profile_size);
10859
10860 ✗ return 0;
10861 }
10862
10863 6 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10864 const HEIFItem *item)
10865 {
10866 int32_t *matrix;
10867 6 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data,
10868 nb_coded_side_data,
10869 AV_PKT_DATA_DISPLAYMATRIX,
10870 9 * sizeof(*matrix), 0);
10871
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sd)
10872 ✗ return AVERROR(ENOMEM);
10873
10874 6 matrix = (int32_t*)sd->data;
10875 /* rotation is in the counter-clockwise direction whereas
10876 * av_display_rotation_set() expects its argument to be
10877 * oriented clockwise, so we need to negate it. */
10878 6 av_display_rotation_set(matrix, -item->rotation);
10879 6 av_display_matrix_flip(matrix, item->hflip, item->vflip);
10880
10881 6 return 0;
10882 }
10883
10884 5 static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid,
10885 AVStreamGroupTileGrid *tile_grid)
10886 {
10887 5 MOVContext *c = s->priv_data;
10888 5 const HEIFItem *item = grid->item;
10889 5 int64_t coded_width = 0, coded_height = 0;
10890 5 int64_t offset = 0, pos = avio_tell(s->pb);
10891 5 int64_t x = 0, y = 0;
10892 5 int i = 0;
10893 int tile_rows, tile_cols;
10894 int flags, size;
10895
10896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10897 ✗ av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
10898 ✗ return AVERROR_PATCHWELCOME;
10899 }
10900
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (item->is_idat_relative) {
10901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!c->idat_offset) {
10902 ✗ av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
10903 ✗ return AVERROR_INVALIDDATA;
10904 }
10905 5 offset = c->idat_offset;
10906 }
10907
10908
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (offset > INT64_MAX - item->extent_offset)
10909 ✗ return AVERROR_INVALIDDATA;
10910
10911 5 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10912
10913 5 avio_r8(s->pb); /* version */
10914 5 flags = avio_r8(s->pb);
10915
10916 5 tile_rows = avio_r8(s->pb) + 1;
10917 5 tile_cols = avio_r8(s->pb) + 1;
10918 /* actual width and height of output image */
10919
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);
10920
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);
10921
10922 5 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
10923 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
10924
10925 5 avio_seek(s->pb, pos, SEEK_SET);
10926
10927 5 size = tile_rows * tile_cols;
10928 5 tile_grid->nb_tiles = grid->nb_tiles;
10929
10930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (tile_grid->nb_tiles != size)
10931 ✗ return AVERROR_INVALIDDATA;
10932
10933
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < tile_cols; i++)
10934 10 coded_width += grid->tile_item_list[i]->width;
10935
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < size; i += tile_cols)
10936 10 coded_height += grid->tile_item_list[i]->height;
10937
10938
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)
10939 ✗ return AVERROR_INVALIDDATA;
10940
10941 5 tile_grid->coded_width = coded_width;
10942 5 tile_grid->coded_height = coded_height;
10943
10944 5 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!tile_grid->offsets)
10946 ✗ return AVERROR(ENOMEM);
10947
10948
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 while (y < tile_grid->coded_height) {
10949 10 int left_col = i;
10950
10951
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 while (x < tile_grid->coded_width) {
10952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (i == tile_grid->nb_tiles)
10953 ✗ return AVERROR_INVALIDDATA;
10954
10955 20 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10956 20 tile_grid->offsets[i].horizontal = x;
10957 20 tile_grid->offsets[i].vertical = y;
10958
10959 20 x += grid->tile_item_list[i++]->width;
10960 }
10961
10962
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (x > tile_grid->coded_width) {
10963 ✗ av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10964 ✗ return AVERROR_INVALIDDATA;
10965 }
10966
10967 10 x = 0;
10968 10 y += grid->tile_item_list[left_col]->height;
10969 }
10970
10971
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) {
10972 ✗ av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10973 ✗ return AVERROR_INVALIDDATA;
10974 }
10975
10976 5 return 0;
10977 }
10978
10979 4 static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid,
10980 AVStreamGroupTileGrid *tile_grid)
10981 {
10982 4 MOVContext *c = s->priv_data;
10983 4 const HEIFItem *item = grid->item;
10984 uint16_t canvas_fill_value[4];
10985 4 int64_t offset = 0, pos = avio_tell(s->pb);
10986 4 int ret = 0, flags;
10987
10988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10989 ✗ av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
10990 ✗ return AVERROR_PATCHWELCOME;
10991 }
10992
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
10993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
10994 ✗ av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
10995 ✗ return AVERROR_INVALIDDATA;
10996 }
10997 4 offset = c->idat_offset;
10998 }
10999
11000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (offset > INT64_MAX - item->extent_offset)
11001 ✗ return AVERROR_INVALIDDATA;
11002
11003 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
11004
11005 4 avio_r8(s->pb); /* version */
11006 4 flags = avio_r8(s->pb);
11007
11008
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
11009 16 canvas_fill_value[i] = avio_rb16(s->pb);
11010 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
11011 4 canvas_fill_value[0], canvas_fill_value[1],
11012 4 canvas_fill_value[2], canvas_fill_value[3]);
11013
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
11014 16 tile_grid->background[i] = canvas_fill_value[i];
11015
11016 /* actual width and height of output image */
11017 4 tile_grid->width =
11018
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);
11019 4 tile_grid->height =
11020
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);
11021
11022 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
11023 tile_grid->width, tile_grid->height);
11024
11025 4 tile_grid->nb_tiles = grid->nb_tiles;
11026 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
11027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
11028 ✗ ret = AVERROR(ENOMEM);
11029 ✗ goto fail;
11030 }
11031
11032
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
11033 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
11034
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);
11035
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);
11036 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
11037 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
11038 8 i, tile_grid->offsets[i].idx,
11039 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
11040 }
11041
11042 4 fail:
11043 4 avio_seek(s->pb, pos, SEEK_SET);
11044
11045 4 return ret;
11046 }
11047
11048 2 static int mov_parse_exif_item(AVFormatContext *s,
11049 AVPacketSideData **coded_side_data, int *nb_coded_side_data,
11050 const HEIFItem *ref)
11051 {
11052 2 MOVContext *c = s->priv_data;
11053 AVPacketSideData *sd;
11054 2 AVExifMetadata ifd = { 0 };
11055 AVBufferRef *buf;
11056 2 int64_t offset = 0, pos = avio_tell(s->pb);
11057 2 unsigned orientation_id = av_exif_get_tag_id("Orientation");
11058 int err;
11059
11060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11061 ✗ av_log(c->fc, AV_LOG_WARNING, "Exif metadata with non seekable input\n");
11062 ✗ return AVERROR_PATCHWELCOME;
11063 }
11064
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ref->is_idat_relative) {
11065 ✗ if (!c->idat_offset) {
11066 ✗ av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the Exif metadata\n");
11067 ✗ return AVERROR_INVALIDDATA;
11068 }
11069 ✗ offset = c->idat_offset;
11070 }
11071
11072 2 buf = av_buffer_alloc(ref->extent_length);
11073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!buf)
11074 ✗ return AVERROR(ENOMEM);
11075
11076
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset > INT64_MAX - ref->extent_offset) {
11077 ✗ err = AVERROR(ENOMEM);
11078 ✗ goto fail;
11079 }
11080
11081 2 avio_seek(s->pb, ref->extent_offset + offset, SEEK_SET);
11082 2 err = avio_read(s->pb, buf->data, ref->extent_length);
11083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != ref->extent_length) {
11084 ✗ if (err > 0)
11085 ✗ err = AVERROR_INVALIDDATA;
11086 ✗ goto fail;
11087 }
11088
11089 // HEIF spec states that Exif metadata is informative. The irot item property is
11090 // the normative source of rotation information. So we remove any Orientation tag
11091 // present in the Exif buffer.
11092 2 err = av_exif_parse_buffer(s, buf->data, ref->extent_length, &ifd, AV_EXIF_T_OFF);
11093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0) {
11094 ✗ av_log(s, AV_LOG_ERROR, "Unable to parse Exif metadata\n");
11095 ✗ goto fail;
11096 }
11097
11098 2 err = av_exif_remove_entry(s, &ifd, orientation_id, 0);
11099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11100 ✗ goto fail;
11101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (!err)
11102 ✗ goto finish;
11103
11104 2 av_buffer_unref(&buf);
11105 2 err = av_exif_write(s, &ifd, &buf, AV_EXIF_T_OFF);
11106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11107 ✗ goto fail;
11108
11109 2 finish:
11110 2 offset = AV_RB32(buf->data) + 4;
11111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset >= buf->size) {
11112 ✗ err = AVERROR_INVALIDDATA;
11113 ✗ goto fail;
11114 }
11115 2 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
11116 2 AV_PKT_DATA_EXIF, buf->size - offset, 0);
11117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!sd) {
11118 ✗ err = AVERROR(ENOMEM);
11119 ✗ goto fail;
11120 }
11121 2 memcpy(sd->data, buf->data + offset, buf->size - offset);
11122
11123 2 err = 0;
11124 2 fail:
11125 2 av_buffer_unref(&buf);
11126 2 av_exif_free(&ifd);
11127 2 avio_seek(s->pb, pos, SEEK_SET);
11128
11129 2 return err;
11130 }
11131
11132 9 static int mov_parse_tiles(AVFormatContext *s)
11133 {
11134 9 MOVContext *mov = s->priv_data;
11135
11136
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for (int i = 0; i < mov->nb_heif_grid; i++) {
11137 9 AVStreamGroup *stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
11138 AVStreamGroupTileGrid *tile_grid;
11139 9 const HEIFGrid *grid = &mov->heif_grid[i];
11140 9 int err, loop = 1;
11141
11142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!stg)
11143 ✗ return AVERROR(ENOMEM);
11144
11145 9 stg->id = grid->item->item_id;
11146 9 tile_grid = stg->params.tile_grid;
11147
11148
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9 times.
37 for (int j = 0; j < grid->nb_tiles; j++) {
11149 28 int tile_id = grid->tile_id_list[j];
11150 int k;
11151
11152
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 for (k = 0; k < mov->nb_heif_item; k++) {
11153 60 HEIFItem *item = mov->heif_item[k];
11154 AVStream *st;
11155
11156
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)
11157 32 continue;
11158 28 st = item->st;
11159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!st) {
11160 ✗ av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
11161 "reference a stream\n",
11162 ✗ tile_id, grid->item->item_id);
11163 ✗ ff_remove_stream_group(s, stg);
11164 ✗ loop = 0;
11165 ✗ break;
11166 }
11167
11168 28 grid->tile_item_list[j] = item;
11169 28 grid->tile_idx_list[j] = stg->nb_streams;
11170
11171 28 err = avformat_stream_group_add_stream(stg, st);
11172
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 26 times.
28 if (err < 0) {
11173 int l;
11174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
11175 ✗ return err;
11176
11177
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_streams; l++)
11178
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->streams[l]->index == st->index)
11179 2 break;
11180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_streams);
11181 2 grid->tile_idx_list[j] = l;
11182 }
11183
11184
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 6 times.
28 if (item->item_id != mov->primary_item_id)
11185 22 st->disposition |= AV_DISPOSITION_DEPENDENT;
11186 28 break;
11187 }
11188
11189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (k == mov->nb_heif_item) {
11190 ✗ av_assert0(loop);
11191 ✗ av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
11192 "exist\n",
11193 ✗ tile_id, grid->item->item_id);
11194 ✗ ff_remove_stream_group(s, stg);
11195 ✗ loop = 0;
11196 }
11197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!loop)
11198 ✗ break;
11199 }
11200
11201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!loop)
11202 ✗ continue;
11203
11204
2/3
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
9 switch (grid->item->type) {
11205 5 case MKTAG('g','r','i','d'):
11206 5 err = read_image_grid(s, grid, tile_grid);
11207 5 break;
11208 4 case MKTAG('i','o','v','l'):
11209 4 err = read_image_iovl(s, grid, tile_grid);
11210 4 break;
11211 ✗ default:
11212 ✗ av_assert0(0);
11213 }
11214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err < 0)
11215 ✗ return err;
11216
11217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 for (int j = 0; j < grid->item->nb_iref_list; j++) {
11218 ✗ HEIFItem *ref = get_heif_item(mov, grid->item->iref_list[j].item_id);
11219
11220 ✗ av_assert0(ref);
11221 ✗ switch(ref->type) {
11222 ✗ case MKTAG('E','x','i','f'):
11223 ✗ err = mov_parse_exif_item(s, &tile_grid->coded_side_data,
11224 &tile_grid->nb_coded_side_data, ref);
11225 ✗ if (err < 0 && (s->error_recognition & AV_EF_EXPLODE))
11226 ✗ return err;
11227 ✗ break;
11228 ✗ default:
11229 ✗ break;
11230 }
11231 }
11232
11233 /* rotation */
11234
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) {
11235 ✗ err = set_display_matrix_from_item(&tile_grid->coded_side_data,
11236 ✗ &tile_grid->nb_coded_side_data, grid->item);
11237 ✗ if (err < 0)
11238 ✗ return err;
11239 }
11240
11241 /* ICC profile */
11242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (grid->item->icc_profile_size) {
11243 ✗ err = set_icc_profile_from_item(&tile_grid->coded_side_data,
11244 ✗ &tile_grid->nb_coded_side_data, grid->item);
11245 ✗ if (err < 0)
11246 ✗ return err;
11247 }
11248
11249
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (grid->item->name)
11250 9 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
11251
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 if (grid->item->item_id == mov->primary_item_id)
11252 5 stg->disposition |= AV_DISPOSITION_DEFAULT;
11253 }
11254
11255 9 return 0;
11256 }
11257
11258 18 static int mov_parse_heif_items(AVFormatContext *s)
11259 {
11260 18 MOVContext *mov = s->priv_data;
11261 int err;
11262
11263
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (int i = 0; i < mov->nb_heif_item; i++) {
11264 57 HEIFItem *item = mov->heif_item[i];
11265 MOVStreamContext *sc;
11266 AVStream *st;
11267 57 int64_t offset = 0;
11268
11269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item)
11270 ✗ continue;
11271
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 43 times.
57 if (!item->st) {
11272 14 continue;
11273 }
11274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (item->is_idat_relative) {
11275 ✗ if (!mov->idat_offset) {
11276 ✗ av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
11277 ✗ return AVERROR_INVALIDDATA;
11278 }
11279 ✗ offset = mov->idat_offset;
11280 }
11281
11282 43 st = item->st;
11283 43 sc = st->priv_data;
11284 43 st->codecpar->width = item->width;
11285 43 st->codecpar->height = item->height;
11286
11287 43 sc->sample_size = sc->stsz_sample_size = item->extent_length;
11288 43 sc->sample_count = 1;
11289
11290 43 err = sanity_checks(s, sc, st->index);
11291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (err)
11292 ✗ return AVERROR_INVALIDDATA;
11293
11294
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (offset > INT64_MAX - item->extent_offset)
11295 ✗ return AVERROR_INVALIDDATA;
11296
11297 43 sc->chunk_offsets[0] = item->extent_offset + offset;
11298
11299
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 30 times.
43 if (item->item_id == mov->primary_item_id)
11300 13 st->disposition |= AV_DISPOSITION_DEFAULT;
11301
11302
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 43 times.
54 for (int j = 0; j < item->nb_iref_list; j++) {
11303 11 HEIFItem *ref = get_heif_item(mov, item->iref_list[j].item_id);
11304
11305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 av_assert0(ref);
11306
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 switch(ref->type) {
11307 2 case MKTAG('E','x','i','f'):
11308 2 err = mov_parse_exif_item(s, &st->codecpar->coded_side_data,
11309 2 &st->codecpar->nb_coded_side_data, ref);
11310
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))
11311 ✗ return err;
11312 2 break;
11313 9 default:
11314 9 break;
11315 }
11316 }
11317
11318
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) {
11319 6 err = set_display_matrix_from_item(&st->codecpar->coded_side_data,
11320 6 &st->codecpar->nb_coded_side_data, item);
11321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
11322 ✗ return err;
11323 }
11324
11325 43 mov_build_index(mov, st);
11326 }
11327
11328
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (mov->nb_heif_grid) {
11329 9 err = mov_parse_tiles(s);
11330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err < 0)
11331 ✗ return err;
11332 }
11333
11334 18 return 0;
11335 }
11336
11337 613 static int mov_parse_tmcd_streams(AVFormatContext *s)
11338 {
11339 int err;
11340
11341
2/2
✓ Branch 0 taken 840 times.
✓ Branch 1 taken 613 times.
1453 for (int i = 0; i < s->nb_streams; i++) {
11342 AVStreamGroup *stg;
11343 const AVDictionaryEntry *tcr;
11344 840 AVStream *st = s->streams[i];
11345
11346
2/2
✓ Branch 0 taken 812 times.
✓ Branch 1 taken 28 times.
840 if (st->codecpar->codec_tag != MKTAG('t','m','c','d'))
11347 812 continue;
11348
11349 28 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TREF, NULL);
11350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!stg)
11351 ✗ return AVERROR(ENOMEM);
11352
11353 28 stg->id = st->id;
11354 28 tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
11355
11356
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 28 times.
134 for (int j = 0; j < s->nb_streams; j++) {
11357 106 AVStream *st2 = s->streams[j];
11358 106 MOVStreamContext *sc2 = st2->priv_data;
11359 106 MovTref *tag = mov_find_tref_tag(sc2, MKTAG('t','m','c','d'));
11360
11361
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 29 times.
106 if (!tag)
11362 77 continue;
11363
11364
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 29 times.
88 for (int k = 0; k < tag->nb_id; k++) {
11365
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 29 times.
59 if (tag->id[k] != st->id)
11366 30 continue;
11367
11368 29 err = avformat_stream_group_add_stream(stg, st2);
11369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (err < 0)
11370 ✗ return err;
11371
11372
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (tcr)
11373 29 av_dict_set(&st2->metadata, "timecode", tcr->value, AV_DICT_DONT_OVERWRITE);
11374 }
11375 }
11376
11377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!stg->nb_streams) {
11378 ✗ ff_remove_stream_group(s, stg);
11379 ✗ continue;
11380 }
11381
11382 28 err = avformat_stream_group_add_stream(stg, st);
11383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (err < 0)
11384 ✗ return err;
11385
11386 28 stg->params.tref->metadata_index = stg->nb_streams - 1;
11387 }
11388 613 export_orphan_timecode(s);
11389
11390 613 return 0;
11391 }
11392
11393 11 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
11394 uint32_t *tref_id, int nb_tref_id, int first_index)
11395 {
11396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!nb_tref_id)
11397 ✗ return NULL;
11398
11399
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 for (int i = first_index; i < s->nb_streams; i++)
11400
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 for (int j = 0; j < nb_tref_id; j++)
11401
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (s->streams[i]->index != st->index &&
11402
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 s->streams[i]->id == tref_id[j])
11403 11 return s->streams[i];
11404
11405 ✗ return NULL;
11406 }
11407
11408 613 static int mov_parse_cdsc_and_rndr_streams(AVFormatContext *s)
11409 {
11410 static const uint32_t tref_tags[] = {
11411 MKTAG('c','d','s','c'),
11412 MKTAG('r','n','d','r'),
11413 };
11414
11415 int err;
11416
11417 // Don't try to add a group if there's only one track
11418
2/2
✓ Branch 0 taken 494 times.
✓ Branch 1 taken 119 times.
613 if (s->nb_streams <= 1)
11419 494 return 0;
11420
11421
2/2
✓ Branch 0 taken 346 times.
✓ Branch 1 taken 119 times.
465 for (int i = 0; i < s->nb_streams; i++) {
11422 346 AVStream *st = s->streams[i];
11423 346 MOVStreamContext *sc = st->priv_data;
11424
11425
2/2
✓ Branch 0 taken 692 times.
✓ Branch 1 taken 346 times.
1038 for (int c = 0; c < FF_ARRAY_ELEMS(tref_tags); c++) {
11426 AVStreamGroup *stg;
11427 AVStream *st_ref;
11428 692 MovTref *tag = mov_find_tref_tag(sc, tref_tags[c]);
11429
11430
2/2
✓ Branch 0 taken 681 times.
✓ Branch 1 taken 11 times.
692 if (!tag)
11431 681 continue;
11432
11433 11 st_ref = mov_find_reference_track(s, st, tag->id, tag->nb_id, 0);
11434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!st_ref) {
11435 ✗ av_log(s, AV_LOG_WARNING, "Failed to find referenced stream\n");
11436 ✗ continue;
11437 }
11438
11439 11 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TREF, NULL);
11440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!stg)
11441 ✗ return AVERROR(ENOMEM);
11442
11443 11 stg->id = st_ref->id;
11444
11445 11 err = avformat_stream_group_add_stream(stg, st_ref);
11446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11447 ✗ return err;
11448
11449 11 err = avformat_stream_group_add_stream(stg, st);
11450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11451 ✗ return err;
11452
11453 11 stg->params.tref->metadata_index = stg->nb_streams - 1;
11454 }
11455 }
11456
11457 119 return 0;
11458 }
11459
11460 613 static int mov_parse_lcevc_streams(AVFormatContext *s)
11461 {
11462 int err;
11463
11464 // Don't try to add a group if there's only one track
11465
2/2
✓ Branch 0 taken 494 times.
✓ Branch 1 taken 119 times.
613 if (s->nb_streams <= 1)
11466 494 return 0;
11467
11468
2/2
✓ Branch 0 taken 346 times.
✓ Branch 1 taken 119 times.
465 for (int i = 0; i < s->nb_streams; i++) {
11469 AVStreamGroup *stg;
11470 346 AVStream *st = s->streams[i];
11471 AVStream *st_base;
11472 346 MOVStreamContext *sc = st->priv_data;
11473 346 MovTref *tag = mov_find_tref_tag(sc, MKTAG('s','b','a','s'));
11474 346 int j = 0;
11475
11476 /* Find an enhancement stream. */
11477
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 346 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
346 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC || !tag)
11478 346 continue;
11479
11480 ✗ stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
11481 ✗ if (!stg)
11482 ✗ return AVERROR(ENOMEM);
11483
11484 ✗ stg->id = st->id;
11485 ✗ stg->params.layered_video->width = st->codecpar->width;
11486 ✗ stg->params.layered_video->height = st->codecpar->height;
11487
11488 ✗ while (st_base = mov_find_reference_track(s, st, tag->id, tag->nb_id, j)) {
11489 ✗ err = avformat_stream_group_add_stream(stg, st_base);
11490 ✗ if (err < 0)
11491 ✗ return err;
11492
11493 ✗ j = st_base->index + 1;
11494 }
11495 ✗ if (!j) {
11496 ✗ int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
11497 ✗ av_log(s, loglevel, "Failed to find base stream for LCEVC stream\n");
11498 ✗ ff_remove_stream_group(s, stg);
11499 ✗ if (s->error_recognition & AV_EF_EXPLODE)
11500 ✗ return AVERROR_INVALIDDATA;
11501 ✗ continue;
11502 }
11503
11504 ✗ err = avformat_stream_group_add_stream(stg, st);
11505 ✗ if (err < 0)
11506 ✗ return err;
11507
11508 ✗ stg->params.layered_video->el_index = stg->nb_streams - 1;
11509 }
11510
11511 119 return 0;
11512 }
11513
11514 613 static int mov_parse_dovi_streams(AVFormatContext *s)
11515 {
11516 int err;
11517
11518
2/2
✓ Branch 0 taken 494 times.
✓ Branch 1 taken 119 times.
613 if (s->nb_streams <= 1)
11519 494 return 0;
11520
11521 /* Identify legacy dual-track Dolby Vision profile 7 carriage per Annex
11522 * C of "Dolby Vision Streams Within the ISO Base Media File Format",
11523 * v2.7.1. The 'vdep' track reference type is shared with depth video
11524 * and multi-view dependencies. The spec-mandated DV-specific sample
11525 * entry combined with the dvcC configuration record disambiguates
11526 * those uses. */
11527
2/2
✓ Branch 0 taken 346 times.
✓ Branch 1 taken 119 times.
465 for (int i = 0; i < s->nb_streams; i++) {
11528 AVStreamGroup *stg;
11529 346 AVStream *st = s->streams[i];
11530 AVStream *st_base;
11531 346 MOVStreamContext *sc = st->priv_data;
11532 346 MovTref *tag = mov_find_tref_tag(sc, MKTAG('v','d','e','p'));
11533 const AVPacketSideData *sd;
11534 const AVDOVIDecoderConfigurationRecord *dovi;
11535
11536
3/4
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 304 times.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
346 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !tag)
11537 346 continue;
11538
11539 ✗ if (st->codecpar->codec_tag != MKTAG('d','v','h','e') &&
11540 ✗ st->codecpar->codec_tag != MKTAG('d','v','h','1'))
11541 ✗ continue;
11542
11543 ✗ sd = av_packet_side_data_get(st->codecpar->coded_side_data,
11544 ✗ st->codecpar->nb_coded_side_data,
11545 AV_PKT_DATA_DOVI_CONF);
11546 ✗ if (!sd)
11547 ✗ continue;
11548 ✗ dovi = (const AVDOVIDecoderConfigurationRecord *)sd->data;
11549
11550 /* EL track of a dual-track stream: rpu_present_flag = 1,
11551 * el_present_flag = 1, bl_present_flag = 0, dv_profile = 7. */
11552 ✗ if (dovi->dv_profile != 7 || !dovi->rpu_present_flag ||
11553 ✗ !dovi->el_present_flag || dovi->bl_present_flag)
11554 ✗ continue;
11555
11556 ✗ st_base = mov_find_reference_track(s, st, tag->id, tag->nb_id, 0);
11557 ✗ if (!st_base) {
11558 ✗ int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
11559 ✗ av_log(s, loglevel, "Failed to find base layer for Dolby Vision EL stream\n");
11560 ✗ if (s->error_recognition & AV_EF_EXPLODE)
11561 ✗ return AVERROR_INVALIDDATA;
11562 ✗ continue;
11563 }
11564
11565 ✗ stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_DOLBY_VISION, NULL);
11566 ✗ if (!stg)
11567 ✗ return AVERROR(ENOMEM);
11568
11569 ✗ stg->id = st->id;
11570
11571 ✗ err = avformat_stream_group_add_stream(stg, st_base);
11572 ✗ if (err < 0)
11573 ✗ return err;
11574
11575 ✗ err = avformat_stream_group_add_stream(stg, st);
11576 ✗ if (err < 0)
11577 ✗ return err;
11578
11579 ✗ stg->params.layered_video->el_index = stg->nb_streams - 1;
11580 ✗ stg->params.layered_video->width = st_base->codecpar->width;
11581 ✗ stg->params.layered_video->height = st_base->codecpar->height;
11582 }
11583
11584 119 return 0;
11585 }
11586
11587 613 static void fix_stream_ids(AVFormatContext *s)
11588 {
11589 613 int highest_id = 0, lowest_iamf_id = INT_MAX;
11590
11591
2/2
✓ Branch 0 taken 840 times.
✓ Branch 1 taken 613 times.
1453 for (int i = 0; i < s->nb_streams; i++) {
11592 840 const AVStream *st = s->streams[i];
11593 840 const MOVStreamContext *sc = st->priv_data;
11594
2/2
✓ Branch 0 taken 776 times.
✓ Branch 1 taken 64 times.
840 if (!sc->iamf)
11595 776 highest_id = FFMAX(highest_id, st->id);
11596 }
11597
11598
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 613 times.
685 for (int i = 0; i < s->nb_stream_groups; i++) {
11599 72 AVStreamGroup *stg = s->stream_groups[i];
11600
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 12 times.
72 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
11601 60 continue;
11602
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_streams; j++) {
11603 64 AVStream *st = stg->streams[j];
11604 64 lowest_iamf_id = FFMIN(lowest_iamf_id, st->id);
11605 }
11606 }
11607
11608
2/2
✓ Branch 0 taken 605 times.
✓ Branch 1 taken 8 times.
613 if (highest_id < lowest_iamf_id)
11609 605 return;
11610
11611 8 highest_id += !lowest_iamf_id;
11612
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++) {
11613 4 AVStreamGroup *stg = s->stream_groups[i];
11614
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
11615 2 continue;
11616
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_streams; j++) {
11617 14 AVStream *st = stg->streams[j];
11618 14 MOVStreamContext *sc = st->priv_data;
11619 14 st->id += highest_id;
11620 14 sc->iamf_stream_offset = highest_id;
11621 }
11622 }
11623 }
11624
11625 613 static int mov_read_header(AVFormatContext *s)
11626 {
11627 613 MOVContext *mov = s->priv_data;
11628 613 AVIOContext *pb = s->pb;
11629 int j, err;
11630 613 MOVAtom atom = { AV_RL32("root") };
11631 int i;
11632
11633 613 mov->fc = s;
11634 613 mov->trak_index = -1;
11635 613 mov->primary_item_id = -1;
11636 613 mov->cur_item_id = -1;
11637 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
11638
2/2
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 1 times.
613 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
11639 612 atom.size = avio_size(pb);
11640 else
11641 1 atom.size = INT64_MAX;
11642
11643 /* check MOV header */
11644 do {
11645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 613 times.
613 if (mov->moov_retry)
11646 ✗ avio_seek(pb, 0, SEEK_SET);
11647
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 613 times.
613 if ((err = mov_read_default(mov, pb, atom)) < 0) {
11648 ✗ av_log(s, AV_LOG_ERROR, "error reading header\n");
11649 ✗ return err;
11650 }
11651 1225 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
11652
6/10
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 594 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.
613 !mov->found_moov && (!mov->found_iloc || !mov->found_iinf) && !mov->moov_retry++);
11653
3/6
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 595 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
613 if (!mov->found_moov && !mov->found_iloc && !mov->found_iinf) {
11654 ✗ av_log(s, AV_LOG_ERROR, "moov atom not found\n");
11655 ✗ return AVERROR_INVALIDDATA;
11656 }
11657 613 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
11658
11659
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 595 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
613 if (mov->found_iloc && mov->found_iinf) {
11660 18 err = mov_parse_heif_items(s);
11661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (err < 0)
11662 ✗ return err;
11663 }
11664 // prevent iloc and iinf boxes from being parsed while reading packets.
11665 // this is needed because an iinf box may have been parsed but ignored
11666 // for having old infe boxes which create no streams.
11667 613 mov->found_iloc = mov->found_iinf = 1;
11668
11669
2/2
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 1 times.
613 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
11670
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 610 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
612 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
11671 2 mov_read_chapters(s);
11672
2/2
✓ Branch 0 taken 839 times.
✓ Branch 1 taken 612 times.
1451 for (i = 0; i < s->nb_streams; i++)
11673
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 811 times.
839 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
11674 28 mov_read_timecode_track(s, s->streams[i]);
11675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 811 times.
811 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
11676 ✗ mov_read_rtmd_track(s, s->streams[i]);
11677 }
11678 }
11679
11680 /* Create metadata stream groups. */
11681 613 err = mov_parse_cdsc_and_rndr_streams(s);
11682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 613 times.
613 if (err < 0)
11683 ✗ return err;
11684
11685 /* copy timecode metadata from tmcd tracks to the related video streams */
11686 613 err = mov_parse_tmcd_streams(s);
11687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 613 times.
613 if (err < 0)
11688 ✗ return err;
11689
11690 /* Create LCEVC stream groups. */
11691 613 err = mov_parse_lcevc_streams(s);
11692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 613 times.
613 if (err < 0)
11693 ✗ return err;
11694
11695 /* Create Dolby Vision Profile 7 stream groups. */
11696 613 err = mov_parse_dovi_streams(s);
11697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 613 times.
613 if (err < 0)
11698 ✗ return err;
11699
11700
2/2
✓ Branch 0 taken 840 times.
✓ Branch 1 taken 613 times.
1453 for (i = 0; i < s->nb_streams; i++) {
11701 840 AVStream *st = s->streams[i];
11702 840 FFStream *const sti = ffstream(st);
11703 840 MOVStreamContext *sc = st->priv_data;
11704 840 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
11705 840 fix_timescale(mov, sc);
11706
11707 /* Set the primary extradata based on the first Sample if it doesn't reference the first stsd entry. */
11708
6/6
✓ Branch 0 taken 794 times.
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 751 times.
✓ Branch 3 taken 43 times.
✓ Branch 4 taken 687 times.
✓ Branch 5 taken 64 times.
840 if (sc->stsc_count && sc->extradata_size && !sc->iamf &&
11709
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 684 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
687 sc->stsc_data[0].id > 1 && sc->stsc_data[0].id <= sc->stsd_count) {
11710 3 sc->last_stsd_index = sc->stsc_data[0].id - 1;
11711 3 av_freep(&st->codecpar->extradata);
11712 3 st->codecpar->extradata_size = sc->extradata_size[sc->last_stsd_index];
11713
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (sc->extradata_size[sc->last_stsd_index]) {
11714 3 st->codecpar->extradata = av_mallocz(sc->extradata_size[sc->last_stsd_index] + AV_INPUT_BUFFER_PADDING_SIZE);
11715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata)
11716 ✗ return AVERROR(ENOMEM);
11717 3 memcpy(st->codecpar->extradata, sc->extradata[sc->last_stsd_index], sc->extradata_size[sc->last_stsd_index]);
11718 }
11719 }
11720
11721
2/2
✓ Branch 0 taken 342 times.
✓ Branch 1 taken 498 times.
840 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
11722
2/2
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 190 times.
342 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
11723 152 sti->skip_samples = st->codecpar->initial_padding;
11724 }
11725
5/6
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 408 times.
✓ Branch 2 taken 373 times.
✓ Branch 3 taken 59 times.
✓ Branch 4 taken 373 times.
✗ Branch 5 not taken.
840 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
11726 373 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
11727 373 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
11728
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 828 times.
840 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
11729
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) {
11730 8 st->codecpar->width = sc->width;
11731 8 st->codecpar->height = sc->height;
11732 }
11733
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
11734 ✗ st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
11735
11736 ✗ for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
11737 ✗ dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
11738
11739 ✗ err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
11740 ✗ if (err < 0)
11741 ✗ return err;
11742
11743 ✗ av_freep(&st->codecpar->extradata);
11744 ✗ st->codecpar->extradata_size = 0;
11745
11746 ✗ err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
11747 st->codecpar);
11748 ✗ if (err < 0)
11749 ✗ return err;
11750 }
11751 }
11752
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 839 times.
840 if (mov->handbrake_version &&
11753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
11754 ✗ st->codecpar->codec_id == AV_CODEC_ID_MP3) {
11755 ✗ av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
11756 ✗ sti->need_parsing = AVSTREAM_PARSE_FULL;
11757 }
11758 }
11759
11760
3/4
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 593 times.
613 if (mov->trex_data || mov->use_mfra_for > 0) {
11761
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 20 times.
49 for (i = 0; i < s->nb_streams; i++) {
11762 29 AVStream *st = s->streams[i];
11763 29 MOVStreamContext *sc = st->priv_data;
11764
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 4 times.
29 if (sc->duration_for_fps > 0) {
11765 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
11766 25 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
11767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (st->codecpar->bit_rate == INT64_MIN) {
11768 ✗ av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
11769 sc->data_size, sc->time_scale);
11770 ✗ st->codecpar->bit_rate = 0;
11771 ✗ if (s->error_recognition & AV_EF_EXPLODE)
11772 ✗ return AVERROR_INVALIDDATA;
11773 }
11774 }
11775 }
11776 }
11777
11778
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 613 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
613 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
11779 ✗ if (mov->bitrates[i]) {
11780 ✗ s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
11781 }
11782 }
11783
11784 613 ff_rfps_calculate(s);
11785
11786
2/2
✓ Branch 0 taken 840 times.
✓ Branch 1 taken 613 times.
1453 for (i = 0; i < s->nb_streams; i++) {
11787 840 AVStream *st = s->streams[i];
11788 840 MOVStreamContext *sc = st->priv_data;
11789
11790
3/3
✓ Branch 0 taken 342 times.
✓ Branch 1 taken 432 times.
✓ Branch 2 taken 66 times.
840 switch (st->codecpar->codec_type) {
11791 342 case AVMEDIA_TYPE_AUDIO:
11792 342 err = ff_replaygain_export(st, s->metadata);
11793
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 342 times.
342 if (err < 0)
11794 ✗ return err;
11795 342 break;
11796 432 case AVMEDIA_TYPE_VIDEO:
11797
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 424 times.
432 if (sc->display_matrix) {
11798
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,
11799 AV_PKT_DATA_DISPLAYMATRIX,
11800 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
11801 ✗ return AVERROR(ENOMEM);
11802
11803 8 sc->display_matrix = NULL;
11804 }
11805
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 426 times.
432 if (sc->stereo3d) {
11806
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,
11807 AV_PKT_DATA_STEREO3D,
11808 6 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
11809 ✗ return AVERROR(ENOMEM);
11810
11811 6 sc->stereo3d = NULL;
11812 }
11813
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 428 times.
432 if (sc->spherical) {
11814
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,
11815 AV_PKT_DATA_SPHERICAL,
11816 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
11817 ✗ return AVERROR(ENOMEM);
11818
11819 4 sc->spherical = NULL;
11820 }
11821
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 432 times.
432 if (sc->mastering) {
11822 ✗ if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11823 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
11824 ✗ (uint8_t *)sc->mastering, sc->mastering_size, 0))
11825 ✗ return AVERROR(ENOMEM);
11826
11827 ✗ sc->mastering = NULL;
11828 }
11829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 432 times.
432 if (sc->coll) {
11830 ✗ if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11831 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
11832 ✗ (uint8_t *)sc->coll, sc->coll_size, 0))
11833 ✗ return AVERROR(ENOMEM);
11834
11835 ✗ sc->coll = NULL;
11836 }
11837
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 428 times.
432 if (sc->ambient) {
11838
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,
11839 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
11840 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
11841 ✗ return AVERROR(ENOMEM);
11842
11843 4 sc->ambient = NULL;
11844 }
11845 432 break;
11846 }
11847 }
11848
11849 613 fix_stream_ids(s);
11850
11851 613 ff_configure_buffers_for_index(s, AV_TIME_BASE);
11852
11853
2/2
✓ Branch 0 taken 479 times.
✓ Branch 1 taken 613 times.
1092 for (i = 0; i < mov->frag_index.nb_items; i++)
11854
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)
11855 469 mov->frag_index.item[i].headers_read = 1;
11856
11857 613 return 0;
11858 }
11859
11860 117888 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
11861 {
11862 117888 AVIndexEntry *sample = NULL;
11863 117888 int64_t best_dts = INT64_MAX;
11864 int i;
11865 117888 MOVContext *mov = s->priv_data;
11866
3/4
✓ Branch 0 taken 117888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 117843 times.
117888 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
11867
2/2
✓ Branch 0 taken 151905 times.
✓ Branch 1 taken 117888 times.
269793 for (i = 0; i < s->nb_streams; i++) {
11868 151905 AVStream *avst = s->streams[i];
11869 151905 FFStream *const avsti = ffstream(avst);
11870 151905 MOVStreamContext *msc = avst->priv_data;
11871
4/4
✓ Branch 0 taken 142390 times.
✓ Branch 1 taken 9515 times.
✓ Branch 2 taken 138878 times.
✓ Branch 3 taken 3512 times.
151905 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
11872 138878 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
11873 138878 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
11874
2/2
✓ Branch 0 taken 123613 times.
✓ Branch 1 taken 15265 times.
138878 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
11875 138878 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
11876
3/6
✓ Branch 0 taken 21575 times.
✓ Branch 1 taken 117303 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 21575 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
138878 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
11877
1/2
✓ Branch 0 taken 21575 times.
✗ Branch 1 not taken.
21575 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
11878
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 21575 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 21575 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 21575 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19382 times.
✓ Branch 9 taken 2193 times.
21575 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
11879
4/4
✓ Branch 0 taken 11276 times.
✓ Branch 1 taken 8106 times.
✓ Branch 2 taken 2193 times.
✓ Branch 3 taken 11276 times.
21575 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
11880
3/4
✓ Branch 0 taken 761 times.
✓ Branch 1 taken 1432 times.
✓ Branch 2 taken 761 times.
✗ Branch 3 not taken.
2193 (dtsdiff > AV_TIME_BASE && dts < best_dts && mov->interleaved_read)))))) {
11881 126170 sample = current_sample;
11882 126170 best_dts = dts;
11883 126170 *st = avst;
11884 }
11885 }
11886 }
11887 117888 return sample;
11888 }
11889
11890 9 static int should_retry(AVIOContext *pb, int error_code) {
11891
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))
11892 9 return 0;
11893
11894 ✗ return 1;
11895 }
11896
11897 49 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
11898 {
11899 int ret;
11900 49 MOVContext *mov = s->priv_data;
11901
11902
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)
11903 1 target = mov->frag_index.item[index].moof_offset;
11904
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) {
11905 ✗ av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
11906 ✗ return AVERROR_INVALIDDATA;
11907 }
11908
11909 49 mov->next_root_atom = 0;
11910
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)
11911 48 index = search_frag_moof_offset(&mov->frag_index, target);
11912
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 &&
11913
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 mov->frag_index.item[index].moof_offset == target) {
11914
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 4 times.
42 if (index + 1 < mov->frag_index.nb_items)
11915 38 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11916
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 6 times.
42 if (mov->frag_index.item[index].headers_read)
11917 36 return 0;
11918 6 mov->frag_index.item[index].headers_read = 1;
11919 }
11920
11921 13 mov->found_mdat = 0;
11922
11923 13 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
11924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (ret < 0)
11925 ✗ return ret;
11926
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 6 times.
13 if (avio_feof(s->pb))
11927 7 return AVERROR_EOF;
11928 6 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
11929
11930 6 return 1;
11931 }
11932
11933 17 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
11934 {
11935 17 MOVStreamContext *sc = st->priv_data;
11936 uint8_t *side, *extradata;
11937 int extradata_size;
11938
11939 /* Save the current index. */
11940 17 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
11941
11942 /* Notify the decoder that extradata changed. */
11943 17 extradata_size = sc->extradata_size[sc->last_stsd_index];
11944 17 extradata = sc->extradata[sc->last_stsd_index];
11945
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) {
11946 14 side = av_packet_new_side_data(pkt,
11947 AV_PKT_DATA_NEW_EXTRADATA,
11948 extradata_size);
11949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!side)
11950 ✗ return AVERROR(ENOMEM);
11951 14 memcpy(side, extradata, extradata_size);
11952 }
11953
11954 17 return 0;
11955 }
11956
11957 ✗ static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
11958 {
11959 /* We can't make assumptions about the structure of the payload,
11960 because it may include multiple cdat and cdt2 samples. */
11961 ✗ const uint32_t cdat = AV_RB32("cdat");
11962 ✗ const uint32_t cdt2 = AV_RB32("cdt2");
11963 ✗ int ret, out_size = 0;
11964
11965 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
11966 ✗ if (src_size < 10)
11967 ✗ return AVERROR_INVALIDDATA;
11968
11969 /* avoid an int overflow: */
11970 ✗ if ((src_size - 8) / 2 >= INT_MAX / 3)
11971 ✗ return AVERROR_INVALIDDATA;
11972
11973 ✗ ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
11974 ✗ if (ret < 0)
11975 ✗ return ret;
11976
11977 /* parse and re-format the c608 payload in one pass. */
11978 ✗ while (src_size >= 10) {
11979 ✗ const uint32_t atom_size = avio_rb32(pb);
11980 ✗ const uint32_t atom_type = avio_rb32(pb);
11981 ✗ const uint32_t data_size = atom_size - 8;
11982 ✗ const uint8_t cc_field =
11983 atom_type == cdat ? 1 :
11984 atom_type == cdt2 ? 2 :
11985 0;
11986
11987 /* account for bytes consumed for atom size and type. */
11988 ✗ src_size -= 8;
11989
11990 /* make sure the data size stays within the buffer boundaries. */
11991 ✗ if (data_size < 2 || data_size > src_size) {
11992 ✗ ret = AVERROR_INVALIDDATA;
11993 ✗ break;
11994 }
11995
11996 /* make sure the data size is consistent with N byte pairs. */
11997 ✗ if (data_size % 2 != 0) {
11998 ✗ ret = AVERROR_INVALIDDATA;
11999 ✗ break;
12000 }
12001
12002 ✗ if (!cc_field) {
12003 /* neither cdat or cdt2 ... skip it */
12004 ✗ avio_skip(pb, data_size);
12005 ✗ src_size -= data_size;
12006 ✗ continue;
12007 }
12008
12009 ✗ for (uint32_t i = 0; i < data_size; i += 2) {
12010 ✗ pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
12011 ✗ pkt->data[out_size + 1] = avio_r8(pb);
12012 ✗ pkt->data[out_size + 2] = avio_r8(pb);
12013 ✗ out_size += 3;
12014 ✗ src_size -= 2;
12015 }
12016 }
12017
12018 ✗ if (src_size > 0)
12019 /* skip any remaining unread portion of the input payload */
12020 ✗ avio_skip(pb, src_size);
12021
12022 ✗ av_shrink_packet(pkt, out_size);
12023 ✗ return ret;
12024 }
12025
12026 117258 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
12027 int64_t current_index, AVPacket *pkt)
12028 {
12029 117258 MOVContext *mov = s->priv_data;
12030 117258 MOVStreamContext *sc = st->priv_data;
12031
12032 117258 pkt->stream_index = sc->ffindex;
12033 117258 pkt->dts = sample->timestamp;
12034
2/2
✓ Branch 0 taken 299 times.
✓ Branch 1 taken 116959 times.
117258 if (sample->flags & AVINDEX_DISCARD_FRAME) {
12035 299 pkt->flags |= AV_PKT_FLAG_DISCARD;
12036 }
12037
4/4
✓ Branch 0 taken 97403 times.
✓ Branch 1 taken 19855 times.
✓ Branch 2 taken 97391 times.
✓ Branch 3 taken 12 times.
117258 if (sc->stts_count && sc->tts_index < sc->tts_count)
12038 97391 pkt->duration = sc->tts_data[sc->tts_index].duration;
12039
3/4
✓ Branch 0 taken 4617 times.
✓ Branch 1 taken 112641 times.
✓ Branch 2 taken 4617 times.
✗ Branch 3 not taken.
117258 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
12040 4617 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
12041 } else {
12042
2/2
✓ Branch 0 taken 15801 times.
✓ Branch 1 taken 96840 times.
112641 if (pkt->duration == 0) {
12043 15801 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
12044
2/2
✓ Branch 0 taken 15706 times.
✓ Branch 1 taken 95 times.
15801 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
12045
2/2
✓ Branch 0 taken 15755 times.
✓ Branch 1 taken 46 times.
15801 if (next_dts >= pkt->dts)
12046 15755 pkt->duration = next_dts - pkt->dts;
12047 }
12048 112641 pkt->pts = pkt->dts;
12049 }
12050
12051
4/4
✓ Branch 0 taken 98565 times.
✓ Branch 1 taken 18693 times.
✓ Branch 2 taken 98487 times.
✓ Branch 3 taken 78 times.
117258 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && !mov->fragment.found_tfhd &&
12052
2/2
✓ Branch 1 taken 232 times.
✓ Branch 2 taken 98255 times.
98487 sc->current_sample >= ffstream(st)->nb_index_entries) {
12053 232 int64_t pts = av_rescale_q(pkt->pts, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12054 232 int64_t total = av_rescale_q(st->duration, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12055 232 int64_t duration = pkt->duration;
12056
12057
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 230 times.
232 if (st->duration < pkt->pts) {
12058 2 duration = 0;
12059 } else
12060 230 duration = FFMIN(duration, (uint64_t)st->duration - pkt->pts);
12061
12062 232 duration = av_rescale_q(duration, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12063
12064
2/2
✓ Branch 1 taken 193 times.
✓ Branch 2 taken 39 times.
232 if (!ffstream(st)->first_discard_sample)
12065 193 ffstream(st)->first_discard_sample = av_sat_add64(pts, duration);
12066
2/2
✓ Branch 1 taken 193 times.
✓ Branch 2 taken 39 times.
232 if (!ffstream(st)->last_discard_sample)
12067 193 ffstream(st)->last_discard_sample = total;
12068 }
12069
12070
4/4
✓ Branch 0 taken 97403 times.
✓ Branch 1 taken 19855 times.
✓ Branch 2 taken 97391 times.
✓ Branch 3 taken 12 times.
117258 if (sc->tts_data && sc->tts_index < sc->tts_count) {
12071 /* update tts context */
12072 97391 sc->tts_sample++;
12073
1/2
✓ Branch 0 taken 97391 times.
✗ Branch 1 not taken.
97391 if (sc->tts_index < sc->tts_count &&
12074
1/2
✓ Branch 0 taken 97391 times.
✗ Branch 1 not taken.
97391 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
12075 97391 sc->tts_index++;
12076 97391 sc->tts_sample = 0;
12077 }
12078 }
12079
12080
4/4
✓ Branch 0 taken 1043 times.
✓ Branch 1 taken 116215 times.
✓ Branch 2 taken 911 times.
✓ Branch 3 taken 132 times.
117258 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
12081 911 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
12082 911 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
12083
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 597 times.
911 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
12084 }
12085 117258 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
12086 117258 pkt->pos = sample->pos;
12087
12088 /* Multiple stsd handling. */
12089
2/2
✓ Branch 0 taken 113880 times.
✓ Branch 1 taken 3378 times.
117258 if (sc->stsc_data) {
12090
1/2
✓ Branch 0 taken 113880 times.
✗ Branch 1 not taken.
113880 if (sc->stsc_data[sc->stsc_index].id > 0 &&
12091
2/2
✓ Branch 0 taken 113837 times.
✓ Branch 1 taken 43 times.
113880 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
12092
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 113820 times.
113837 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
12093 17 int ret = mov_change_extradata(st, pkt);
12094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (ret < 0)
12095 ✗ return ret;
12096 }
12097
12098 /* Update the stsc index for the next sample */
12099 113880 sc->stsc_sample++;
12100
2/2
✓ Branch 1 taken 56819 times.
✓ Branch 2 taken 57061 times.
113880 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
12101
2/2
✓ Branch 1 taken 1212 times.
✓ Branch 2 taken 55607 times.
56819 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
12102 1212 sc->stsc_index++;
12103 1212 sc->stsc_sample = 0;
12104 }
12105 }
12106
12107 117258 return 0;
12108 }
12109
12110 108622 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
12111 {
12112 108622 MOVContext *mov = s->priv_data;
12113 MOVStreamContext *sc;
12114 AVIndexEntry *sample;
12115 108622 AVStream *st = NULL;
12116 108622 FFStream *avsti = NULL;
12117 int64_t current_index;
12118 int ret;
12119 int i;
12120 108622 mov->fc = s;
12121 9266 retry:
12122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117888 times.
117888 if (s->pb->pos == 0) {
12123
12124 // Discard current fragment index
12125 ✗ if (mov->frag_index.allocated_size > 0) {
12126 ✗ for(int i = 0; i < mov->frag_index.nb_items; i++) {
12127 ✗ av_freep(&mov->frag_index.item[i].stream_info);
12128 }
12129 ✗ av_freep(&mov->frag_index.item);
12130 ✗ mov->frag_index.nb_items = 0;
12131 ✗ mov->frag_index.allocated_size = 0;
12132 ✗ mov->frag_index.current = -1;
12133 ✗ mov->frag_index.complete = 0;
12134 }
12135
12136 ✗ for (i = 0; i < s->nb_streams; i++) {
12137 ✗ AVStream *avst = s->streams[i];
12138 ✗ MOVStreamContext *msc = avst->priv_data;
12139
12140 // Clear current sample
12141 ✗ mov_current_sample_set(msc, 0);
12142 ✗ msc->tts_index = 0;
12143
12144 // Discard current index entries
12145 ✗ avsti = ffstream(avst);
12146 ✗ if (avsti->index_entries_allocated_size > 0) {
12147 ✗ av_freep(&avsti->index_entries);
12148 ✗ avsti->index_entries_allocated_size = 0;
12149 ✗ avsti->nb_index_entries = 0;
12150 }
12151 }
12152
12153 ✗ if ((ret = mov_switch_root(s, -1, -1)) < 0)
12154 ✗ return ret;
12155 }
12156 117888 sample = mov_find_next_sample(s, &st);
12157
6/6
✓ Branch 0 taken 117303 times.
✓ Branch 1 taken 585 times.
✓ Branch 2 taken 646 times.
✓ Branch 3 taken 116657 times.
✓ Branch 4 taken 36 times.
✓ Branch 5 taken 610 times.
117888 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
12158
2/2
✓ Branch 0 taken 573 times.
✓ Branch 1 taken 48 times.
621 if (!mov->next_root_atom)
12159 573 return AVERROR_EOF;
12160
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)
12161 7 return ret;
12162 41 goto retry;
12163 }
12164 117267 sc = st->priv_data;
12165 /* must be done just before reading, to avoid infinite loop on sample */
12166 117267 current_index = sc->current_index;
12167 117267 mov_current_sample_inc(sc);
12168
12169
2/2
✓ Branch 0 taken 610 times.
✓ Branch 1 taken 116657 times.
117267 if (mov->next_root_atom) {
12170 610 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
12171 610 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
12172 }
12173
12174
4/4
✓ Branch 0 taken 9235 times.
✓ Branch 1 taken 108032 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 9225 times.
117267 if (st->discard != AVDISCARD_ALL || sc->iamf) {
12175 108042 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
12176
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 108035 times.
108042 if (ret64 != sample->pos) {
12177 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
12178 sc->ffindex, sample->pos);
12179
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
12180 ✗ mov_current_sample_dec(sc);
12181
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
12182 7 return (int)ret64;
12183 }
12184 ✗ return AVERROR_INVALIDDATA;
12185 }
12186
12187
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 108035 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
108035 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
12188 ✗ av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
12189 ✗ goto retry;
12190 }
12191
12192
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 108035 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
108035 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
12193 ✗ ret = get_eia608_packet(sc->pb, pkt, sample->size);
12194 #if CONFIG_IAMFDEC
12195
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 107953 times.
108035 else if (sc->iamf) {
12196 int64_t pts, dts, pos, duration;
12197 82 int flags, size = sample->size;
12198 82 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
12199 82 pts = pkt->pts; dts = pkt->dts;
12200 82 pos = pkt->pos; flags = pkt->flags;
12201 82 duration = pkt->duration;
12202
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) {
12203 454 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
12204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 454 times.
454 if (ret < 0) {
12205 ✗ if (should_retry(sc->pb, ret))
12206 ✗ mov_current_sample_dec(sc);
12207 ✗ return ret;
12208 }
12209 454 size -= ret;
12210
12211
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 334 times.
454 if (pkt->flags & AV_PKT_FLAG_DISCARD) {
12212 120 av_packet_unref(pkt);
12213 120 ret = 0;
12214 120 continue;
12215 }
12216 334 pkt->pts = pts; pkt->dts = dts;
12217 334 pkt->pos = pos; pkt->flags |= flags;
12218 334 pkt->duration = duration;
12219 334 ret = ff_buffer_packet(s, pkt);
12220 }
12221
1/2
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
82 if (!ret)
12222 82 return FFERROR_REDO;
12223 }
12224 #endif
12225
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 107950 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
107956 else if (st->codecpar->codec_id == AV_CODEC_ID_APV && sample->size > 4) {
12226 3 uint32_t au_size = avio_rb32(sc->pb);
12227 3 int explode = !!(mov->fc->error_recognition & AV_EF_EXPLODE);
12228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (au_size > sample->size - 4) {
12229 ✗ av_log(s, explode ? AV_LOG_ERROR : AV_LOG_WARNING,
12230 "APV au_size %u exceeds sample body %d\n",
12231 ✗ au_size, sample->size - 4);
12232 ✗ if (explode)
12233 ✗ return AVERROR_INVALIDDATA;
12234 ✗ au_size = sample->size - 4;
12235 }
12236 3 ret = av_get_packet(sc->pb, pkt, au_size);
12237 } else
12238 107950 ret = av_get_packet(sc->pb, pkt, sample->size);
12239
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 107951 times.
107953 if (ret < 0) {
12240
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (should_retry(sc->pb, ret)) {
12241 ✗ mov_current_sample_dec(sc);
12242 }
12243 2 return ret;
12244 }
12245 #if CONFIG_DV_DEMUXER
12246
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 107951 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
107951 if (mov->dv_demux && sc->dv_audio_container) {
12247 ✗ ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
12248 ✗ av_packet_unref(pkt);
12249 ✗ if (ret < 0)
12250 ✗ return ret;
12251 ✗ ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
12252 ✗ if (ret < 0)
12253 ✗ return ret;
12254 }
12255 #endif
12256
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 107933 times.
107951 if (sc->has_palette) {
12257 uint8_t *pal;
12258
12259 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
12260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
12261 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
12262 } else {
12263 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
12264 18 sc->has_palette = 0;
12265 }
12266 }
12267
4/6
✓ Branch 0 taken 329 times.
✓ Branch 1 taken 107622 times.
✓ Branch 3 taken 329 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 329 times.
✗ Branch 6 not taken.
107951 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
12268
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 329 times.
329 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
12269 ✗ ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
12270 }
12271 }
12272
12273 117176 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
12274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117176 times.
117176 if (ret < 0)
12275 ✗ return ret;
12276
12277
2/2
✓ Branch 0 taken 9225 times.
✓ Branch 1 taken 107951 times.
117176 if (st->discard == AVDISCARD_ALL)
12278 9225 goto retry;
12279
12280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107951 times.
107951 if (mov->aax_mode)
12281 ✗ aax_filter(pkt->data, pkt->size, mov);
12282
12283 107951 ret = cenc_filter(mov, st, sc, pkt, current_index);
12284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107951 times.
107951 if (ret < 0) {
12285 ✗ return ret;
12286 }
12287
12288 107951 return 0;
12289 }
12290
12291 365 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
12292 {
12293 365 MOVContext *mov = s->priv_data;
12294 int index;
12295
12296
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 28 times.
365 if (!mov->frag_index.complete)
12297 337 return 0;
12298
12299 28 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
12300
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 24 times.
28 if (index < 0)
12301 4 index = 0;
12302
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (!mov->frag_index.item[index].headers_read)
12303 1 return mov_switch_root(s, -1, index);
12304
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (index + 1 < mov->frag_index.nb_items)
12305 27 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
12306
12307 27 return 0;
12308 }
12309
12310 ✗ static int is_open_key_sample(const MOVStreamContext *sc, int sample)
12311 {
12312 // TODO: a bisect search would scale much better
12313 ✗ for (int i = 0; i < sc->open_key_samples_count; i++) {
12314 ✗ const int oks = sc->open_key_samples[i];
12315 ✗ if (oks == sample)
12316 ✗ return 1;
12317 ✗ if (oks > sample) /* list is monotically increasing so we can stop early */
12318 ✗ break;
12319 }
12320 ✗ return 0;
12321 }
12322
12323 /*
12324 * Some key sample may be key frames but not IDR frames, so a random access to
12325 * them may not be allowed.
12326 */
12327 231 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
12328 {
12329 231 MOVStreamContext *sc = st->priv_data;
12330 231 FFStream *const sti = ffstream(st);
12331 int64_t key_sample_dts, key_sample_pts;
12332
12333
1/2
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
231 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
12334 231 return 1;
12335
12336 ✗ if (sample >= sc->sample_offsets_count)
12337 ✗ return 1;
12338
12339 ✗ av_assert0(sample >= 0);
12340 ✗ key_sample_dts = sti->index_entries[sample].timestamp;
12341 ✗ key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
12342
12343 /*
12344 * If the sample needs to be presented before an open key sample, they may
12345 * not be decodable properly, even though they come after in decoding
12346 * order.
12347 */
12348 ✗ if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
12349 ✗ return 0;
12350
12351 ✗ return 1;
12352 }
12353
12354 365 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
12355 {
12356 365 MOVStreamContext *sc = st->priv_data;
12357 365 FFStream *const sti = ffstream(st);
12358 int sample, time_sample, ret, requested_sample;
12359 int64_t next_ts;
12360 unsigned int i;
12361
12362 // Here we consider timestamp to be PTS, hence try to offset it so that we
12363 // can search over the DTS timeline.
12364 365 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
12365
12366 365 ret = mov_seek_fragment(s, st, timestamp);
12367
1/2
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
365 if (ret < 0)
12368 ✗ return ret;
12369
12370 for (;;) {
12371 365 sample = av_index_search_timestamp(st, timestamp, flags);
12372 365 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
12373
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)
12374 43 sample = 0;
12375
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 339 times.
365 if (sample < 0) /* not sure what to do */
12376 26 return AVERROR_INVALIDDATA;
12377
12378
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))
12379 break;
12380
12381 ✗ next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
12382 ✗ requested_sample = av_index_search_timestamp(st, next_ts, flags);
12383 ✗ if (requested_sample < 0)
12384 ✗ return AVERROR_INVALIDDATA;
12385
12386 // If we've reached a different sample trying to find a good pts to
12387 // seek to, give up searching because we'll end up seeking back to
12388 // sample 0 on every seek.
12389 ✗ if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
12390 ✗ break;
12391
12392 ✗ timestamp = next_ts;
12393 }
12394
12395 339 mov_current_sample_set(sc, sample);
12396 339 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
12397 /* adjust time to sample index */
12398
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 125 times.
339 if (sc->tts_data) {
12399 214 time_sample = 0;
12400
1/2
✓ Branch 0 taken 60310 times.
✗ Branch 1 not taken.
60310 for (i = 0; i < sc->tts_count; i++) {
12401 60310 int next = time_sample + sc->tts_data[i].count;
12402
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 60096 times.
60310 if (next > sc->current_sample) {
12403 214 sc->tts_index = i;
12404 214 sc->tts_sample = sc->current_sample - time_sample;
12405 214 break;
12406 }
12407 60096 time_sample = next;
12408 }
12409 }
12410
12411 /* adjust stsd index */
12412
2/2
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 28 times.
339 if (sc->chunk_count) {
12413 311 time_sample = 0;
12414
1/2
✓ Branch 0 taken 383 times.
✗ Branch 1 not taken.
383 for (i = 0; i < sc->stsc_count; i++) {
12415 383 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
12416
2/2
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 72 times.
383 if (next > sc->current_sample) {
12417 311 sc->stsc_index = i;
12418 311 sc->stsc_sample = sc->current_sample - time_sample;
12419 311 break;
12420 }
12421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
12422 72 time_sample = next;
12423 }
12424 }
12425
12426 339 return sample;
12427 }
12428
12429 339 static int64_t mov_get_skip_samples(AVStream *st, int sample)
12430 {
12431 339 FFStream *const sti = ffstream(st);
12432 339 int64_t first_ts = sti->index_entries[0].timestamp;
12433 339 int64_t ts = sti->index_entries[sample].timestamp;
12434 int64_t off;
12435
12436
2/2
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 152 times.
339 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
12437 187 return 0;
12438
12439 /* compute skip samples according to stream initial_padding, seek ts and first ts */
12440 152 off = av_rescale_q(ts - first_ts, st->time_base,
12441 152 (AVRational){1, st->codecpar->sample_rate});
12442 152 return FFMAX(st->codecpar->initial_padding - off, 0);
12443 }
12444
12445 343 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
12446 {
12447 343 MOVContext *mc = s->priv_data;
12448 AVStream *st;
12449 FFStream *sti;
12450 int sample;
12451 int i;
12452
12453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 343 times.
343 if (stream_index >= s->nb_streams)
12454 ✗ return AVERROR_INVALIDDATA;
12455
12456 343 st = s->streams[stream_index];
12457 343 sti = ffstream(st);
12458 343 sample = mov_seek_stream(s, st, sample_time, flags);
12459
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 317 times.
343 if (sample < 0)
12460 26 return sample;
12461
12462
1/2
✓ Branch 0 taken 317 times.
✗ Branch 1 not taken.
317 if (mc->seek_individually) {
12463 /* adjust seek timestamp to found sample timestamp */
12464 317 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
12465 317 sti->skip_samples = mov_get_skip_samples(st, sample);
12466
12467
2/2
✓ Branch 0 taken 339 times.
✓ Branch 1 taken 317 times.
656 for (i = 0; i < s->nb_streams; i++) {
12468 339 AVStream *const st = s->streams[i];
12469 339 FFStream *const sti = ffstream(st);
12470 int64_t timestamp;
12471
12472
2/2
✓ Branch 0 taken 317 times.
✓ Branch 1 taken 22 times.
339 if (stream_index == i)
12473 317 continue;
12474
12475 22 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
12476 22 sample = mov_seek_stream(s, st, timestamp, flags);
12477
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (sample >= 0)
12478 22 sti->skip_samples = mov_get_skip_samples(st, sample);
12479 }
12480 } else {
12481 ✗ for (i = 0; i < s->nb_streams; i++) {
12482 MOVStreamContext *sc;
12483 ✗ st = s->streams[i];
12484 ✗ sc = st->priv_data;
12485 ✗ mov_current_sample_set(sc, 0);
12486 }
12487 ✗ while (1) {
12488 MOVStreamContext *sc;
12489 ✗ AVIndexEntry *entry = mov_find_next_sample(s, &st);
12490 ✗ if (!entry)
12491 ✗ return AVERROR_INVALIDDATA;
12492 ✗ sc = st->priv_data;
12493 ✗ if (sc->ffindex == stream_index && sc->current_sample == sample)
12494 ✗ break;
12495 ✗ mov_current_sample_inc(sc);
12496 }
12497 }
12498 317 return 0;
12499 }
12500
12501 #define OFFSET(x) offsetof(MOVContext, x)
12502 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
12503 static const AVOption mov_options[] = {
12504 {"use_absolute_path",
12505 "allow using absolute path when opening alias, this is a possible security issue",
12506 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
12507 0, 1, FLAGS},
12508 {"seek_streams_individually",
12509 "Seek each stream individually to the closest point",
12510 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
12511 0, 1, FLAGS},
12512 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
12513 0, 1, FLAGS},
12514 {"advanced_editlist",
12515 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
12516 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
12517 0, 1, FLAGS},
12518 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
12519 0, 1, FLAGS},
12520 {"use_mfra_for",
12521 "use mfra for fragment timestamps",
12522 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
12523 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
12524 .unit = "use_mfra_for"},
12525 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
12526 FLAGS, .unit = "use_mfra_for" },
12527 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
12528 FLAGS, .unit = "use_mfra_for" },
12529 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
12530 FLAGS, .unit = "use_mfra_for" },
12531 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
12532 0, 1, FLAGS},
12533 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
12534 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
12535 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
12536 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
12537 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
12538 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12539 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
12540 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12541 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
12542 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12543 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
12544 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
12545 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
12546 .flags = AV_OPT_FLAG_DECODING_PARAM },
12547 { "decryption_key", "The default media decryption key (hex)", OFFSET(decryption_default_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12548 { "decryption_keys", "The media decryption keys by KID (hex)", OFFSET(decryption_keys), AV_OPT_TYPE_DICT, .flags = AV_OPT_FLAG_DECODING_PARAM },
12549 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
12550 {.i64 = 0}, 0, 1, FLAGS },
12551 { "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 },
12552 { "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 },
12553
12554 { NULL },
12555 };
12556
12557 static const AVClass mov_class = {
12558 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
12559 .item_name = av_default_item_name,
12560 .option = mov_options,
12561 .version = LIBAVUTIL_VERSION_INT,
12562 };
12563
12564 const FFInputFormat ff_mov_demuxer = {
12565 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
12566 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
12567 .p.priv_class = &mov_class,
12568 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4v,m4b,ism,ismv,isma,f4v,avif,heic,heif",
12569 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
12570 .priv_data_size = sizeof(MOVContext),
12571 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
12572 .read_probe = mov_probe,
12573 .read_header = mov_read_header,
12574 .read_packet = mov_read_packet,
12575 .read_close = mov_read_close,
12576 .read_seek = mov_read_seek,
12577 };
12578