FFmpeg coverage


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