FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2026-09-28 11:37:26
Exec Total Coverage
Lines: 4821 7525 64.1%
Functions: 194 233 83.3%
Branches: 2756 5077 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/mpegaudiodata.h"
60 #include "libavcodec/mpegaudiodecheader.h"
61 #include "libavcodec/mlp_parse.h"
62 #include "avformat.h"
63 #include "internal.h"
64 #include "avio_internal.h"
65 #include "demux.h"
66 #include "dvdclut.h"
67 #include "iamf_parse.h"
68 #include "iamf_reader.h"
69 #include "dovi_isom.h"
70 #include "riff.h"
71 #include "isom.h"
72 #include "libavcodec/get_bits.h"
73 #include "id3v1.h"
74 #include "mov_chan.h"
75 #include "replaygain.h"
76
77 #if CONFIG_ZLIB
78 #include <zlib.h>
79 #endif
80
81 #include "qtpalette.h"
82
83 /* those functions parse an atom */
84 /* links atom IDs to parse functions */
85 typedef struct MOVParseTableEntry {
86 uint32_t type;
87 int (*parse)(MOVContext *ctx, AVIOContext *pb, MOVAtom atom);
88 } MOVParseTableEntry;
89
90 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom);
91 static int mov_read_mfra(MOVContext *c, AVIOContext *f);
92 static void mov_free_stream_context(AVFormatContext *s, AVStream *st);
93
94 32 static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
95 unsigned len, const char *key)
96 {
97 char buf[16];
98
99 32 short current, total = 0;
100 32 avio_rb16(pb); // unknown
101 32 current = avio_rb16(pb);
102
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (len >= 6)
103 32 total = avio_rb16(pb);
104
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 25 times.
32 if (!total)
105 7 snprintf(buf, sizeof(buf), "%d", current);
106 else
107 25 snprintf(buf, sizeof(buf), "%d/%d", current, total);
108 32 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
109 32 av_dict_set(&c->fc->metadata, key, buf, 0);
110
111 32 return 0;
112 }
113
114 ✗ static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
115 unsigned len, const char *key)
116 {
117 /* bypass padding bytes */
118 ✗ avio_r8(pb);
119 ✗ avio_r8(pb);
120 ✗ avio_r8(pb);
121
122 ✗ c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
123 ✗ av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
124
125 ✗ return 0;
126 }
127
128 30 static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
129 unsigned len, const char *key)
130 {
131 30 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
132 30 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
133
134 30 return 0;
135 }
136
137 12 static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
138 unsigned len, const char *key)
139 {
140 short genre;
141
142 12 avio_r8(pb); // unknown
143
144 12 genre = avio_r8(pb);
145
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)
146 ✗ return 0;
147 12 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
148 12 av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
149
150 12 return 0;
151 }
152
153 static const uint32_t mac_to_unicode[128] = {
154 0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
155 0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
156 0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,
157 0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,
158 0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,
159 0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,
160 0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,
161 0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,
162 0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,
163 0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,
164 0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,
165 0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,
166 0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,
167 0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,
168 0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,
169 0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7,
170 };
171
172 405 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
173 char *dst, int dstlen)
174 {
175 405 char *p = dst;
176 405 char *end = dst+dstlen-1;
177 int i;
178
179
2/2
✓ Branch 0 taken 3392 times.
✓ Branch 1 taken 405 times.
3797 for (i = 0; i < len; i++) {
180 3392 uint8_t t, c = avio_r8(pb);
181
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3392 times.
3392 if (p >= end)
183 ✗ continue;
184
185
2/2
✓ Branch 0 taken 3384 times.
✓ Branch 1 taken 8 times.
3392 if (c < 0x80)
186 3384 *p++ = c;
187
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 else if (p < end)
188
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;);
189 }
190 405 *p = 0;
191 405 return p - dst;
192 }
193
194 /**
195 * Get the requested item.
196 */
197 169 static HEIFItem *get_heif_item(MOVContext *c, unsigned id)
198 {
199 169 HEIFItem *item = NULL;
200
201
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 15 times.
383 for (int i = 0; i < c->nb_heif_item; i++) {
202
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)
203 214 continue;
204
205 154 item = c->heif_item[i];
206 154 break;
207 }
208
209 169 return item;
210 }
211
212 /**
213 * Get the current stream in the parsing process. This can either be the
214 * latest stream added to the context, or the stream referenced by an item.
215 */
216 290 static AVStream *get_curr_st(MOVContext *c)
217 {
218 290 AVStream *st = NULL;
219 HEIFItem *item;
220
221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 290 times.
290 if (c->fc->nb_streams < 1)
222 ✗ return NULL;
223
224
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 49 times.
290 if (c->cur_item_id == -1)
225 241 return c->fc->streams[c->fc->nb_streams-1];
226
227 49 item = get_heif_item(c, c->cur_item_id);
228
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 if (item)
229 49 st = item->st;
230
231 49 return st;
232 }
233
234 16 static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
235 {
236 AVStream *st;
237 MOVStreamContext *sc;
238 enum AVCodecID id;
239 int ret;
240
241
2/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
16 switch (type) {
242 9 case 0xd: id = AV_CODEC_ID_MJPEG; break;
243 7 case 0xe: id = AV_CODEC_ID_PNG; break;
244 ✗ case 0x1b: id = AV_CODEC_ID_BMP; break;
245 ✗ default:
246 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown cover type: 0x%x.\n", type);
247 ✗ avio_skip(pb, len);
248 ✗ return 0;
249 }
250
251 16 sc = av_mallocz(sizeof(*sc));
252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!sc)
253 ✗ return AVERROR(ENOMEM);
254 16 ret = ff_add_attached_pic(c->fc, NULL, pb, NULL, len);
255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0) {
256 ✗ av_free(sc);
257 ✗ return ret;
258 }
259 16 st = c->fc->streams[c->fc->nb_streams - 1];
260 16 st->priv_data = sc;
261 16 sc->id = st->id;
262 16 sc->refcount = 1;
263
264
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) {
265
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 9 times.
16 if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
266 7 id = AV_CODEC_ID_PNG;
267 } else {
268 9 id = AV_CODEC_ID_MJPEG;
269 }
270 }
271 16 st->codecpar->codec_id = id;
272
273 16 return 0;
274 }
275
276 // 3GPP TS 26.244
277 ✗ static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
278 {
279 ✗ char language[4] = { 0 };
280 char buf[200], place[100];
281 ✗ uint16_t langcode = 0;
282 double longitude, latitude, altitude;
283 ✗ const char *key = "location";
284
285 ✗ if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) {
286 ✗ av_log(c->fc, AV_LOG_ERROR, "loci too short\n");
287 ✗ return AVERROR_INVALIDDATA;
288 }
289
290 ✗ avio_skip(pb, 4); // version+flags
291 ✗ langcode = avio_rb16(pb);
292 ✗ ff_mov_lang_to_iso639(langcode, language);
293 ✗ len -= 6;
294
295 ✗ len -= avio_get_str(pb, len, place, sizeof(place));
296 ✗ if (len < 1) {
297 ✗ av_log(c->fc, AV_LOG_ERROR, "place name too long\n");
298 ✗ return AVERROR_INVALIDDATA;
299 }
300 ✗ avio_skip(pb, 1); // role
301 ✗ len -= 1;
302
303 ✗ if (len < 12) {
304 ✗ av_log(c->fc, AV_LOG_ERROR,
305 "loci too short (%u bytes left, need at least %d)\n", len, 12);
306 ✗ return AVERROR_INVALIDDATA;
307 }
308 ✗ longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
309 ✗ latitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
310 ✗ altitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
311
312 // Try to output in the same format as the ?xyz field
313 ✗ snprintf(buf, sizeof(buf), "%+08.4f%+09.4f", latitude, longitude);
314 ✗ if (altitude)
315 ✗ av_strlcatf(buf, sizeof(buf), "%+f", altitude);
316 ✗ av_strlcatf(buf, sizeof(buf), "/%s", place);
317
318 ✗ if (*language && strcmp(language, "und")) {
319 char key2[16];
320 ✗ snprintf(key2, sizeof(key2), "%s-%s", key, language);
321 ✗ av_dict_set(&c->fc->metadata, key2, buf, 0);
322 }
323 ✗ c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
324 ✗ return av_dict_set(&c->fc->metadata, key, buf, 0);
325 }
326
327 ✗ static int mov_metadata_hmmt(MOVContext *c, AVIOContext *pb, unsigned len)
328 {
329 int i, n_hmmt;
330
331 ✗ if (len < 2)
332 ✗ return 0;
333 ✗ if (c->ignore_chapters)
334 ✗ return 0;
335
336 ✗ n_hmmt = avio_rb32(pb);
337 ✗ if (n_hmmt > len / 4)
338 ✗ return AVERROR_INVALIDDATA;
339 ✗ for (i = 0; i < n_hmmt && !pb->eof_reached; i++) {
340 ✗ int moment_time = avio_rb32(pb);
341 ✗ avpriv_new_chapter(c->fc, i, av_make_q(1, 1000), moment_time, AV_NOPTS_VALUE, NULL);
342 }
343 ✗ if (avio_feof(pb))
344 ✗ return AVERROR_INVALIDDATA;
345 ✗ return 0;
346 }
347
348 633 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
349 {
350 633 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
351 633 char key2[32], language[4] = {0};
352 633 char *str = NULL;
353 633 const char *key = NULL;
354 633 uint16_t langcode = 0;
355 633 uint32_t data_type = 0, str_size_alloc;
356 uint64_t str_size;
357 633 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
358 633 int raw = 0;
359 633 int num = 0;
360 AVDictionary **metadata;
361
362
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)
363 53 metadata = &c->fc->streams[c->trak_index]->metadata;
364 else
365 580 metadata = &c->fc->metadata;
366
367
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) {
368 3 case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break;
369 3 case MKTAG( '@','P','R','Q'): key = "quicktime_version"; raw = 1; break;
370 2 case MKTAG( 'X','M','P','_'):
371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->export_xmp) { key = "xmp"; raw = 1; } break;
372 16 case MKTAG( 'a','A','R','T'): key = "album_artist"; break;
373 ✗ case MKTAG( 'a','k','I','D'): key = "account_type";
374 ✗ parse = mov_metadata_int8_no_padding; break;
375 ✗ case MKTAG( 'a','p','I','D'): key = "account_id"; break;
376 ✗ case MKTAG( 'c','a','t','g'): key = "category"; break;
377 15 case MKTAG( 'c','p','i','l'): key = "compilation";
378 15 parse = mov_metadata_int8_no_padding; break;
379 2 case MKTAG( 'c','p','r','t'): key = "copyright"; break;
380 ✗ case MKTAG( 'd','e','s','c'): key = "description"; break;
381 16 case MKTAG( 'd','i','s','k'): key = "disc";
382 16 parse = mov_metadata_track_or_disc_number; break;
383 ✗ case MKTAG( 'e','g','i','d'): key = "episode_uid";
384 ✗ parse = mov_metadata_int8_no_padding; break;
385 ✗ case MKTAG( 'F','I','R','M'): key = "firmware"; raw = 1; break;
386 12 case MKTAG( 'g','n','r','e'): key = "genre";
387 12 parse = mov_metadata_gnre; break;
388 ✗ case MKTAG( 'h','d','v','d'): key = "hd_video";
389 ✗ parse = mov_metadata_int8_no_padding; break;
390 ✗ case MKTAG( 'H','M','M','T'):
391 ✗ return mov_metadata_hmmt(c, pb, atom.size);
392 ✗ case MKTAG( 'k','e','y','w'): key = "keywords"; break;
393 ✗ case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
394 ✗ case MKTAG( 'l','o','c','i'):
395 ✗ return mov_metadata_loci(c, pb, atom.size);
396 ✗ case MKTAG( 'm','a','n','u'): key = "make"; break;
397 ✗ case MKTAG( 'm','o','d','l'): key = "model"; break;
398 5 case MKTAG( 'n','a','m','e'): key = "name"; break;
399 ✗ case MKTAG( 'p','c','s','t'): key = "podcast";
400 ✗ parse = mov_metadata_int8_no_padding; break;
401 15 case MKTAG( 'p','g','a','p'): key = "gapless_playback";
402 15 parse = mov_metadata_int8_no_padding; break;
403 ✗ case MKTAG( 'p','u','r','d'): key = "purchase_date"; break;
404 ✗ case MKTAG( 'r','t','n','g'): key = "rating";
405 ✗ parse = mov_metadata_int8_no_padding; break;
406 ✗ case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break;
407 ✗ case MKTAG( 's','o','a','l'): key = "sort_album"; break;
408 ✗ case MKTAG( 's','o','a','r'): key = "sort_artist"; break;
409 ✗ case MKTAG( 's','o','c','o'): key = "sort_composer"; break;
410 ✗ case MKTAG( 's','o','n','m'): key = "sort_name"; break;
411 ✗ case MKTAG( 's','o','s','n'): key = "sort_show"; break;
412 ✗ case MKTAG( 's','t','i','k'): key = "media_type";
413 ✗ parse = mov_metadata_int8_no_padding; break;
414 16 case MKTAG( 't','r','k','n'): key = "track";
415 16 parse = mov_metadata_track_or_disc_number; break;
416 ✗ case MKTAG( 't','v','e','n'): key = "episode_id"; break;
417 ✗ case MKTAG( 't','v','e','s'): key = "episode_sort";
418 ✗ parse = mov_metadata_int8_bypass_padding; break;
419 ✗ case MKTAG( 't','v','n','n'): key = "network"; break;
420 ✗ case MKTAG( 't','v','s','h'): key = "show"; break;
421 ✗ case MKTAG( 't','v','s','n'): key = "season_number";
422 ✗ parse = mov_metadata_int8_bypass_padding; break;
423 21 case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
424 ✗ case MKTAG(0xa9,'P','R','D'): key = "producer"; break;
425 20 case MKTAG(0xa9,'a','l','b'): key = "album"; break;
426 3 case MKTAG(0xa9,'a','u','t'): key = "artist"; break;
427 ✗ case MKTAG(0xa9,'c','h','p'): key = "chapter"; break;
428 12 case MKTAG(0xa9,'c','m','t'): key = "comment"; break;
429 ✗ case MKTAG(0xa9,'c','o','m'): key = "composer"; break;
430 4 case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
431 20 case MKTAG(0xa9,'d','a','y'): key = "date"; break;
432 ✗ case MKTAG(0xa9,'d','i','r'): key = "director"; break;
433 ✗ case MKTAG(0xa9,'d','i','s'): key = "disclaimer"; break;
434 ✗ case MKTAG(0xa9,'e','d','1'): key = "edit_date"; break;
435 2 case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
436 ✗ case MKTAG(0xa9,'f','m','t'): key = "original_format"; break;
437 5 case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
438 ✗ case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
439 ✗ case MKTAG(0xa9,'h','s','t'): key = "host_computer"; break;
440 ✗ case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
441 ✗ case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
442 5 case MKTAG(0xa9,'m','a','k'): key = "make"; break;
443 5 case MKTAG(0xa9,'m','o','d'): key = "model"; break;
444 47 case MKTAG(0xa9,'n','a','m'): key = "title"; break;
445 ✗ case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break;
446 ✗ case MKTAG(0xa9,'p','r','d'): key = "producer"; break;
447 ✗ case MKTAG(0xa9,'p','r','f'): key = "performers"; break;
448 ✗ case MKTAG(0xa9,'r','e','q'): key = "playback_requirements"; break;
449 ✗ case MKTAG(0xa9,'s','r','c'): key = "original_source"; break;
450 ✗ case MKTAG(0xa9,'s','t','3'): key = "subtitle"; break;
451 63 case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
452 75 case MKTAG(0xa9,'t','o','o'): key = "encoder"; break;
453 ✗ case MKTAG(0xa9,'t','r','k'): key = "track"; break;
454 ✗ case MKTAG(0xa9,'u','r','l'): key = "URL"; break;
455 ✗ case MKTAG(0xa9,'w','r','n'): key = "warning"; break;
456 3 case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
457 5 case MKTAG(0xa9,'x','y','z'): key = "location"; break;
458 }
459 7 retry:
460
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) {
461 435 int data_size = avio_rb32(pb);
462 435 int tag = avio_rl32(pb);
463
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) {
464 435 data_type = avio_rb32(pb); // type
465 435 avio_rb32(pb); // unknown
466 435 str_size = data_size - 16;
467 435 atom.size -= 16;
468
469
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) {
470 104 uint32_t index = av_bswap32(atom.type); // BE number has been read as LE
471
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) {
472 104 key = c->meta_keys[index];
473 ✗ } else if (atom.type != MKTAG('c', 'o', 'v', 'r')) {
474 ✗ av_log(c->fc, AV_LOG_WARNING,
475 "The index of 'data' is out of range: %"PRId32" < 1 or >= %d.\n",
476 index, c->meta_keys_count);
477 }
478 }
479
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') ||
480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 382 times.
382 (key && !strcmp(key, "com.apple.quicktime.artwork"))) {
481 16 int ret = mov_read_covr(c, pb, data_type, str_size);
482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0) {
483 ✗ av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
484 ✗ return ret;
485 }
486 16 atom.size -= str_size;
487
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (atom.size > 8)
488 2 goto retry;
489 14 return ret;
490 }
491 ✗ } else return 0;
492
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) {
493 109 str_size = avio_rb16(pb); // string length
494
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 104 times.
109 if (str_size > atom.size) {
495 5 raw = 1;
496 5 avio_seek(pb, -2, SEEK_CUR);
497 5 av_log(c->fc, AV_LOG_WARNING, "UDTA parsing failed retrying raw\n");
498 5 goto retry;
499 }
500 104 langcode = avio_rb16(pb);
501 104 ff_mov_lang_to_iso639(langcode, language);
502 104 atom.size -= 4;
503 } else
504 96 str_size = atom.size;
505
506
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) {
507 ✗ key = av_fourcc_make_string(tmp_key, atom.type);
508 }
509
510
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 497 times.
619 if (!key)
511 122 return 0;
512
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)
513 ✗ return AVERROR_INVALIDDATA;
514
515 // Allocates enough space if data_type is a int32 or float32 number, otherwise
516 // worst-case requirement for output string in case of utf8 coded input
517
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);
518
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;
519 497 str = av_mallocz(str_size_alloc);
520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 497 times.
497 if (!str)
521 ✗ return AVERROR(ENOMEM);
522
523
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 423 times.
497 if (parse)
524 74 parse(c, pb, str_size, key);
525 else {
526
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
527 17 mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
528
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 404 times.
406 } else if (data_type == 21) { // BE signed integer, variable size
529 2 int val = 0;
530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (str_size == 1)
531 ✗ val = (int8_t)avio_r8(pb);
532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 2)
533 ✗ val = (int16_t)avio_rb16(pb);
534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 3)
535 ✗ val = ((int32_t)(avio_rb24(pb)<<8))>>8;
536
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (str_size == 4)
537 2 val = (int32_t)avio_rb32(pb);
538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
539 ✗ av_log(c->fc, AV_LOG_ERROR,
540 "Failed to store the number (%d) in string.\n", val);
541 ✗ av_free(str);
542 ✗ return AVERROR_INVALIDDATA;
543 }
544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 404 times.
404 } else if (data_type == 22) { // BE unsigned integer, variable size
545 ✗ unsigned int val = 0;
546 ✗ if (str_size == 1)
547 ✗ val = avio_r8(pb);
548 ✗ else if (str_size == 2)
549 ✗ val = avio_rb16(pb);
550 ✗ else if (str_size == 3)
551 ✗ val = avio_rb24(pb);
552 ✗ else if (str_size == 4)
553 ✗ val = avio_rb32(pb);
554 ✗ if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
555 ✗ av_log(c->fc, AV_LOG_ERROR,
556 "Failed to store the number (%u) in string.\n", val);
557 ✗ av_free(str);
558 ✗ return AVERROR_INVALIDDATA;
559 }
560
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
561 40 float val = av_int2float(avio_rb32(pb));
562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
563 ✗ av_log(c->fc, AV_LOG_ERROR,
564 "Failed to store the float32 number (%f) in string.\n", val);
565 ✗ av_free(str);
566 ✗ return AVERROR_INVALIDDATA;
567 }
568
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) {
569 // data_type can be 0 if not set at all above. data_type 1 means
570 // UTF8 and 4 means "UTF8 sort". For any other type (UTF16 or e.g.
571 // a picture), don't return it blindly in a string that is supposed
572 // to be UTF8 text.
573 ✗ av_log(c->fc, AV_LOG_WARNING, "Skipping unhandled metadata %s of type %"PRIu32"\n", key, data_type);
574 ✗ av_free(str);
575 ✗ return 0;
576 } else {
577 364 int ret = ffio_read_size(pb, str, str_size);
578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 364 times.
364 if (ret < 0) {
579 ✗ av_free(str);
580 ✗ return ret;
581 }
582 364 str[str_size] = 0;
583 }
584 423 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
585
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))
586 4 av_dict_set(metadata, key, ";", AV_DICT_APPEND);
587
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);
588
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")) {
589 37 snprintf(key2, sizeof(key2), "%s-%s", key, language);
590 37 av_dict_set(metadata, key2, str, 0);
591 }
592
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 283 times.
423 if (!strcmp(key, "encoder")) {
593 int major, minor, micro;
594
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 139 times.
140 if (sscanf(str, "HandBrake %d.%d.%d", &major, &minor, &micro) == 3) {
595 1 c->handbrake_version = 1000000*major + 1000*minor + micro;
596 }
597 }
598
599 423 atom.size -= str_size;
600 423 av_freep(&str);
601
602 // Read remaining data atoms for multi-valued iTunes tags (e.g. multiple
603 // artists stored as multiple data atoms within one tag atom), consistent
604 // with the existing covr path.
605 // Note: multiple sibling tag atoms with the same key (e.g. three separate
606 // ©ART atoms under ilst) are handled by the AV_DICT_APPEND logic above,
607 // since mov_read_udta_string() is called once per tag atom.
608
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)
609 ✗ goto retry;
610 }
611
612 497 av_freep(&str);
613 497 return 0;
614 }
615
616 12 static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
617 {
618 int64_t start;
619 int i, nb_chapters, str_len, version;
620 char str[256+1];
621 int ret;
622
623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->ignore_chapters)
624 ✗ return 0;
625
626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if ((atom.size -= 5) < 0)
627 ✗ return 0;
628
629 12 version = avio_r8(pb);
630 12 avio_rb24(pb);
631
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (version)
632 12 avio_rb32(pb); // ???
633 12 nb_chapters = avio_r8(pb);
634
635
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
30 for (i = 0; i < nb_chapters; i++) {
636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size < 9)
637 ✗ return 0;
638
639 18 start = avio_rb64(pb);
640 18 str_len = avio_r8(pb);
641
642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if ((atom.size -= 9+str_len) < 0)
643 ✗ return 0;
644
645 18 ret = ffio_read_size(pb, str, str_len);
646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (ret < 0)
647 ✗ return ret;
648 18 str[str_len] = 0;
649 18 avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
650 }
651 12 return 0;
652 }
653
654 #define MIN_DATA_ENTRY_BOX_SIZE 12
655 734 static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
656 {
657 AVStream *st;
658 MOVStreamContext *sc;
659 int entries, i, j;
660
661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (c->fc->nb_streams < 1)
662 ✗ return 0;
663 734 st = c->fc->streams[c->fc->nb_streams-1];
664 734 sc = st->priv_data;
665
666 734 avio_rb32(pb); // version + flags
667 734 entries = avio_rb32(pb);
668
1/2
✓ Branch 0 taken 734 times.
✗ Branch 1 not taken.
734 if (!entries ||
669
1/2
✓ Branch 0 taken 734 times.
✗ Branch 1 not taken.
734 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
670
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 entries >= UINT_MAX / sizeof(*sc->drefs))
671 ✗ return AVERROR_INVALIDDATA;
672
673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 for (i = 0; i < sc->drefs_count; i++) {
674 ✗ MOVDref *dref = &sc->drefs[i];
675 ✗ av_freep(&dref->path);
676 ✗ av_freep(&dref->dir);
677 }
678 734 av_free(sc->drefs);
679 734 sc->drefs_count = 0;
680 734 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (!sc->drefs)
682 ✗ return AVERROR(ENOMEM);
683 734 sc->drefs_count = entries;
684
685
2/2
✓ Branch 0 taken 734 times.
✓ Branch 1 taken 734 times.
1468 for (i = 0; i < entries; i++) {
686 734 MOVDref *dref = &sc->drefs[i];
687 734 uint32_t size = avio_rb32(pb);
688 734 int64_t next = avio_tell(pb);
689
690
3/6
✓ Branch 0 taken 734 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 734 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 734 times.
734 if (size < 12 || next < 0 || next > INT64_MAX - size)
691 ✗ return AVERROR_INVALIDDATA;
692
693 734 next += size - 4;
694
695 734 dref->type = avio_rl32(pb);
696 734 avio_rb32(pb); // version + flags
697
698
3/4
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 582 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 152 times.
734 if (dref->type == MKTAG('a','l','i','s') && size > 150) {
699 /* macintosh alias record */
700 uint16_t volume_len, len;
701 int16_t type;
702 int ret;
703
704 ✗ avio_skip(pb, 10);
705
706 ✗ volume_len = avio_r8(pb);
707 ✗ volume_len = FFMIN(volume_len, 27);
708 ✗ ret = ffio_read_size(pb, dref->volume, 27);
709 ✗ if (ret < 0)
710 ✗ return ret;
711 ✗ dref->volume[volume_len] = 0;
712 ✗ av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
713
714 ✗ avio_skip(pb, 12);
715
716 ✗ len = avio_r8(pb);
717 ✗ len = FFMIN(len, 63);
718 ✗ ret = ffio_read_size(pb, dref->filename, 63);
719 ✗ if (ret < 0)
720 ✗ return ret;
721 ✗ dref->filename[len] = 0;
722 ✗ av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
723
724 ✗ avio_skip(pb, 16);
725
726 /* read next level up_from_alias/down_to_target */
727 ✗ dref->nlvl_from = avio_rb16(pb);
728 ✗ dref->nlvl_to = avio_rb16(pb);
729 ✗ av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
730 ✗ dref->nlvl_from, dref->nlvl_to);
731
732 ✗ avio_skip(pb, 16);
733
734 ✗ for (type = 0; type != -1 && avio_tell(pb) < next; ) {
735 ✗ if (avio_feof(pb))
736 ✗ return AVERROR_EOF;
737 ✗ type = avio_rb16(pb);
738 ✗ len = avio_rb16(pb);
739 ✗ av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
740 ✗ if (len&1)
741 ✗ len += 1;
742 ✗ if (type == 2) { // absolute path
743 ✗ av_free(dref->path);
744 ✗ dref->path = av_mallocz(len+1);
745 ✗ if (!dref->path)
746 ✗ return AVERROR(ENOMEM);
747
748 ✗ ret = ffio_read_size(pb, dref->path, len);
749 ✗ if (ret < 0) {
750 ✗ av_freep(&dref->path);
751 ✗ return ret;
752 }
753 ✗ if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
754 ✗ len -= volume_len;
755 ✗ memmove(dref->path, dref->path+volume_len, len);
756 ✗ dref->path[len] = 0;
757 }
758 // trim string of any ending zeros
759 ✗ for (j = len - 1; j >= 0; j--) {
760 ✗ if (dref->path[j] == 0)
761 ✗ len--;
762 else
763 ✗ break;
764 }
765 ✗ for (j = 0; j < len; j++)
766 ✗ if (dref->path[j] == ':' || dref->path[j] == 0)
767 ✗ dref->path[j] = '/';
768 ✗ av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
769 ✗ } else if (type == 0) { // directory name
770 ✗ av_free(dref->dir);
771 ✗ dref->dir = av_malloc(len+1);
772 ✗ if (!dref->dir)
773 ✗ return AVERROR(ENOMEM);
774
775 ✗ ret = ffio_read_size(pb, dref->dir, len);
776 ✗ if (ret < 0) {
777 ✗ av_freep(&dref->dir);
778 ✗ return ret;
779 }
780 ✗ dref->dir[len] = 0;
781 ✗ for (j = 0; j < len; j++)
782 ✗ if (dref->dir[j] == ':')
783 ✗ dref->dir[j] = '/';
784 ✗ av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
785 } else
786 ✗ avio_skip(pb, len);
787 }
788 } else {
789 734 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
790 dref->type, size);
791 734 entries--;
792 734 i--;
793 }
794 734 avio_seek(pb, next, SEEK_SET);
795 }
796 734 return 0;
797 }
798
799 1353 static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
800 {
801 AVStream *st;
802 uint32_t type;
803 uint32_t ctype;
804 int64_t title_size;
805 char *title_str;
806 int ret;
807
808 1353 avio_r8(pb); /* version */
809 1353 avio_rb24(pb); /* flags */
810
811 /* component type */
812 1353 ctype = avio_rl32(pb);
813 1353 type = avio_rl32(pb); /* component subtype */
814
815 1353 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
816 1353 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
817
818
2/2
✓ Branch 0 taken 215 times.
✓ Branch 1 taken 1138 times.
1353 if (c->trak_index < 0) { // meta not inside a trak
819
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 201 times.
215 if (type == MKTAG('m','d','t','a')) {
820 14 c->found_hdlr_mdta = 1;
821 }
822 215 return 0;
823 }
824
825 1138 st = c->fc->streams[c->fc->nb_streams-1];
826
827
2/2
✓ Branch 0 taken 373 times.
✓ Branch 1 taken 765 times.
1138 if (type == MKTAG('v','i','d','e'))
828 373 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
829
2/2
✓ Branch 0 taken 295 times.
✓ Branch 1 taken 470 times.
765 else if (type == MKTAG('s','o','u','n'))
830 295 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 else if (type == MKTAG('m','1','a',' '))
832 ✗ st->codecpar->codec_id = AV_CODEC_ID_MP2;
833
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')))
834 ✗ st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
835
836 1138 avio_rb32(pb); /* component manufacture */
837 1138 avio_rb32(pb); /* component flags */
838 1138 avio_rb32(pb); /* component flags mask */
839
840 1138 title_size = atom.size - 24;
841
2/2
✓ Branch 0 taken 1132 times.
✓ Branch 1 taken 6 times.
1138 if (title_size > 0) {
842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1132 times.
1132 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
843 ✗ return AVERROR_INVALIDDATA;
844 1132 title_str = av_malloc(title_size + 1); /* Add null terminator */
845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1132 times.
1132 if (!title_str)
846 ✗ return AVERROR(ENOMEM);
847
848 1132 ret = ffio_read_size(pb, title_str, title_size);
849
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1132 times.
1132 if (ret < 0) {
850 ✗ av_freep(&title_str);
851 ✗ return ret;
852 }
853 1132 title_str[title_size] = 0;
854
2/2
✓ Branch 0 taken 1068 times.
✓ Branch 1 taken 64 times.
1132 if (title_str[0]) {
855
4/4
✓ Branch 0 taken 778 times.
✓ Branch 1 taken 290 times.
✓ Branch 2 taken 776 times.
✓ Branch 3 taken 2 times.
1068 int off = (!c->isom && title_str[0] == title_size - 1);
856 // flag added so as to not set stream handler name if already set from mdia->hdlr
857 1068 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
858 }
859 1132 av_freep(&title_str);
860 }
861
862 1138 return 0;
863 }
864
865 198 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
866 {
867 198 return ff_mov_read_esds(c->fc, pb);
868 }
869
870 8 static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
871 {
872 AVStream *st;
873 AVPacketSideData *sd;
874 enum AVAudioServiceType *ast;
875 int ac3info, acmod, lfeon, bsmod;
876 uint64_t mask;
877
878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (c->fc->nb_streams < 1)
879 ✗ return 0;
880 8 st = c->fc->streams[c->fc->nb_streams-1];
881
882 8 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
883 8 &st->codecpar->nb_coded_side_data,
884 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
885 sizeof(*ast), 0);
886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!sd)
887 ✗ return AVERROR(ENOMEM);
888
889 8 ast = (enum AVAudioServiceType*)sd->data;
890 8 ac3info = avio_rb24(pb);
891 8 bsmod = (ac3info >> 14) & 0x7;
892 8 acmod = (ac3info >> 11) & 0x7;
893 8 lfeon = (ac3info >> 10) & 0x1;
894
895 8 mask = ff_ac3_channel_layout_tab[acmod];
896
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (lfeon)
897 1 mask |= AV_CH_LOW_FREQUENCY;
898 8 av_channel_layout_uninit(&st->codecpar->ch_layout);
899 8 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
900
901 8 *ast = bsmod;
902
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)
903 ✗ *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
904
905 8 return 0;
906 }
907
908 #if CONFIG_IAMFDEC
909 12 static int mov_read_iacb(MOVContext *c, AVIOContext *pb, MOVAtom atom)
910 {
911 AVStream *st;
912 MOVStreamContext *sc;
913 FFIOContext b;
914 AVIOContext *descriptor_pb;
915 AVDictionary *metadata;
916 IAMFContext *iamf;
917 int64_t start_time, duration;
918 unsigned descriptors_size;
919 int nb_frames, disposition;
920 int version, ret;
921
922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (atom.size < 5)
923 ✗ return AVERROR_INVALIDDATA;
924
925
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->fc->nb_streams < 1)
926 ✗ return 0;
927
928 12 version = avio_r8(pb);
929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (version != 1) {
930 ✗ av_log(c->fc, AV_LOG_ERROR, "%s configurationVersion %d",
931 version < 1 ? "invalid" : "unsupported", version);
932 ✗ return AVERROR_INVALIDDATA;
933 }
934
935 12 descriptors_size = ffio_read_leb(pb);
936
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)
937 ✗ return AVERROR_INVALIDDATA;
938
939 12 st = c->fc->streams[c->fc->nb_streams - 1];
940 12 sc = st->priv_data;
941
942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->extradata) {
943 ✗ av_log(c->fc, AV_LOG_WARNING, "ignoring iacb\n");
944 ✗ return 0;
945 }
946
947 12 sc->iamf = av_mallocz(sizeof(*sc->iamf));
948
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!sc->iamf)
949 ✗ return AVERROR(ENOMEM);
950 12 iamf = &sc->iamf->iamf;
951
952 12 ret = ff_alloc_extradata(st->codecpar, descriptors_size);
953
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
954 ✗ return ret;
955
956 12 ret = avio_read(pb, st->codecpar->extradata, descriptors_size);
957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret != descriptors_size)
958 ✗ return ret < 0 ? ret : AVERROR_INVALIDDATA;
959
960 12 ffio_init_read_context(&b, st->codecpar->extradata, descriptors_size);
961 12 descriptor_pb = &b.pub;
962
963 12 ret = ff_iamfdec_read_descriptors(iamf, descriptor_pb, descriptors_size, c->fc);
964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
965 ✗ return ret;
966
967 12 metadata = st->metadata;
968 12 st->metadata = NULL;
969 12 start_time = st->start_time;
970 12 nb_frames = st->nb_frames;
971 12 duration = st->duration;
972 12 disposition = st->disposition;
973
974
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_audio_elements; i++) {
975 12 IAMFAudioElement *audio_element = iamf->audio_elements[i];
976 const AVIAMFAudioElement *element;
977 AVStreamGroup *stg =
978 12 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, NULL);
979
980
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!stg) {
981 ✗ ret = AVERROR(ENOMEM);
982 ✗ goto fail;
983 }
984
985 12 av_iamf_audio_element_free(&stg->params.iamf_audio_element);
986 12 stg->id = audio_element->audio_element_id;
987 /* Transfer ownership */
988 12 element = stg->params.iamf_audio_element = audio_element->element;
989 12 audio_element->element = NULL;
990
991
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < audio_element->nb_substreams; j++) {
992 64 IAMFSubStream *substream = &audio_element->substreams[j];
993 AVStream *stream;
994
995
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) {
996
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
12 if (audio_element->layers[0].substream_count != 1)
997 2 disposition &= ~AV_DISPOSITION_DEFAULT;
998 12 stream = st;
999 } else
1000 52 stream = avformat_new_stream(c->fc, NULL);
1001
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (!stream) {
1002 ✗ ret = AVERROR(ENOMEM);
1003 ✗ goto fail;
1004 }
1005
1006 64 stream->start_time = start_time;
1007 64 stream->nb_frames = nb_frames;
1008 64 stream->duration = duration;
1009 64 stream->disposition = disposition;
1010
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 12 times.
64 if (stream != st) {
1011 52 stream->priv_data = sc;
1012 52 sc->refcount++;
1013 }
1014
1015
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 56 times.
64 if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
1016 8 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1017
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) {
1018 52 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1019
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 6 times.
52 if (audio_element->layers[0].substream_count == 1)
1020 46 stream->disposition &= ~AV_DISPOSITION_DEFAULT;
1021 }
1022
1023 64 ret = avcodec_parameters_copy(stream->codecpar, substream->codecpar);
1024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
1025 ✗ goto fail;
1026
1027 64 stream->id = substream->audio_substream_id;
1028
1029 64 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
1030
1031 64 ret = avformat_stream_group_add_stream(stg, stream);
1032
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
1033 ✗ goto fail;
1034 }
1035
1036 12 ret = av_dict_copy(&stg->metadata, metadata, 0);
1037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1038 ✗ goto fail;
1039 }
1040
1041
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1042 12 IAMFMixPresentation *mix_presentation = iamf->mix_presentations[i];
1043 12 const AVIAMFMixPresentation *mix = mix_presentation->cmix;
1044 AVStreamGroup *stg =
1045 12 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, NULL);
1046
1047
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!stg) {
1048 ✗ ret = AVERROR(ENOMEM);
1049 ✗ goto fail;
1050 }
1051
1052 12 av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
1053 12 stg->id = mix_presentation->mix_presentation_id;
1054 /* Transfer ownership */
1055 12 stg->params.iamf_mix_presentation = mix_presentation->mix;
1056 12 mix_presentation->mix = NULL;
1057
1058
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 12 times.
26 for (int j = 0; j < mix->nb_submixes; j++) {
1059 14 const AVIAMFSubmix *submix = mix->submixes[j];
1060
1061
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
28 for (int k = 0; k < submix->nb_elements; k++) {
1062 14 const AVIAMFSubmixElement *submix_element = submix->elements[k];
1063 14 const AVStreamGroup *audio_element = NULL;
1064
1065
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 for (int l = 0; l < c->fc->nb_stream_groups; l++)
1066
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 &&
1067
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 c->fc->stream_groups[l]->id == submix_element->audio_element_id) {
1068 14 audio_element = c->fc->stream_groups[l];
1069 14 break;
1070 }
1071
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 av_assert0(audio_element);
1072
1073
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 14 times.
80 for (int l = 0; l < audio_element->nb_streams; l++) {
1074 66 ret = avformat_stream_group_add_stream(stg, audio_element->streams[l]);
1075
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))
1076 ✗ goto fail;
1077 }
1078 }
1079 }
1080
1081 12 ret = av_dict_copy(&stg->metadata, metadata, 0);
1082
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1083 ✗ goto fail;
1084 }
1085
1086 12 ret = 0;
1087 12 fail:
1088 12 av_dict_free(&metadata);
1089
1090 12 return ret;
1091 }
1092 #endif
1093
1094 5 static int mov_read_srat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1095 {
1096 AVStream *st;
1097 int32_t sample_rate;
1098
1099
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)
1100 ✗ return 0;
1101
1102 5 st = c->fc->streams[c->fc->nb_streams-1];
1103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
1104 ✗ av_log(c->fc, AV_LOG_WARNING, "'srat' within non-audio sample entry, skip\n");
1105 ✗ return 0;
1106 }
1107
1108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!c->isom) {
1109 ✗ av_log(c->fc, AV_LOG_WARNING, "'srat' within non-isom, skip\n");
1110 ✗ return 0;
1111 }
1112
1113 5 avio_skip(pb, 4); // version+flags
1114 5 sample_rate = avio_rb32(pb);
1115
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (sample_rate > 0) {
1116 5 av_log(c->fc, AV_LOG_DEBUG,
1117 "overwrite sample rate from %d to %d by 'srat'\n",
1118 5 st->codecpar->sample_rate, sample_rate);
1119 5 st->codecpar->sample_rate = sample_rate;
1120 } else {
1121 ✗ av_log(c->fc, AV_LOG_WARNING,
1122 "ignore invalid sample rate %d in 'srat'\n", sample_rate);
1123 }
1124
1125 5 return 0;
1126 }
1127
1128 4 static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1129 {
1130 AVStream *st;
1131 AVPacketSideData *sd;
1132 enum AVAudioServiceType *ast;
1133 int eac3info, acmod, lfeon, bsmod;
1134 uint64_t mask;
1135
1136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
1137 ✗ return 0;
1138 4 st = c->fc->streams[c->fc->nb_streams-1];
1139
1140 4 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1141 4 &st->codecpar->nb_coded_side_data,
1142 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
1143 sizeof(*ast), 0);
1144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sd)
1145 ✗ return AVERROR(ENOMEM);
1146
1147 4 ast = (enum AVAudioServiceType*)sd->data;
1148
1149 /* No need to parse fields for additional independent substreams and its
1150 * associated dependent substreams since libavcodec's E-AC-3 decoder
1151 * does not support them yet. */
1152 4 avio_rb16(pb); /* data_rate and num_ind_sub */
1153 4 eac3info = avio_rb24(pb);
1154 4 bsmod = (eac3info >> 12) & 0x1f;
1155 4 acmod = (eac3info >> 9) & 0x7;
1156 4 lfeon = (eac3info >> 8) & 0x1;
1157
1158 4 mask = ff_ac3_channel_layout_tab[acmod];
1159
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (lfeon)
1160 1 mask |= AV_CH_LOW_FREQUENCY;
1161 4 av_channel_layout_uninit(&st->codecpar->ch_layout);
1162 4 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
1163
1164 4 *ast = bsmod;
1165
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)
1166 ✗ *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
1167
1168 4 return 0;
1169 }
1170
1171 /* Maps the DTS `StreamConstruction` field (ETSI TS 102 114 Table E-2) to the
1172 * coarse FFmpeg DTS profile enum. Extension-substream XLL maps to HD_MA;
1173 * extension-substream XXCH, X96, or XBR maps to HD_HRA; core-substream XCH or
1174 * XXCH maps to ES; core-substream X96 maps to 96/24; a core component alone
1175 * maps to DTS; and extension-substream LBR maps to Express. Value 0 (undefined)
1176 * and values outside 1..21 map to AV_PROFILE_UNKNOWN. */
1177 ✗ static int mov_dts_stream_construction_to_profile(unsigned int sc)
1178 {
1179 static const int profile[22] = {
1180 [ 1] = AV_PROFILE_DTS, /* core Core */
1181 [ 2] = AV_PROFILE_DTS_ES, /* core Core + core XCH */
1182 [ 3] = AV_PROFILE_DTS_ES, /* core Core + core XXCH */
1183 [ 4] = AV_PROFILE_DTS_96_24, /* core Core + core X96 */
1184 [ 5] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XXCH */
1185 [ 6] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XBR */
1186 [ 7] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XCH + ext XBR */
1187 [ 8] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XXCH + ext XBR */
1188 [ 9] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XXCH + ext XBR */
1189 [10] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext X96 */
1190 [11] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XCH + ext X96 */
1191 [12] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XXCH + ext X96 */
1192 [13] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XXCH + ext X96 */
1193 [14] = AV_PROFILE_DTS_HD_MA, /* core Core + ext XLL */
1194 [15] = AV_PROFILE_DTS_HD_MA, /* core Core + core XCH + ext XLL */
1195 [16] = AV_PROFILE_DTS_HD_MA, /* core Core + core X96 + ext XLL */
1196 [17] = AV_PROFILE_DTS_HD_MA, /* ext XLL */
1197 [18] = AV_PROFILE_DTS_EXPRESS, /* ext LBR */
1198 [19] = AV_PROFILE_DTS, /* ext Core */
1199 [20] = AV_PROFILE_DTS_HD_HRA, /* ext Core + ext XXCH */
1200 [21] = AV_PROFILE_DTS_HD_MA, /* ext Core + ext XLL */
1201 };
1202 ✗ if (!sc || sc > 21)
1203 ✗ return AV_PROFILE_UNKNOWN;
1204 ✗ return profile[sc];
1205 }
1206
1207 /* Maps the 16-bit DTS `ChannelLayout` bitmask (ETSI TS 102 114 Table E-5) to an
1208 * ffmpeg channel mask. Pair bits follow Table 7-10 / DCA_SPEAKER_PAIR_*;
1209 * LwRw (0x0400) and LssRss (0x0800) must not collapse onto SIDE like LsRs. */
1210 ✗ static uint64_t mov_dts_channel_layout_to_mask(unsigned int code)
1211 {
1212 static const struct { unsigned int dts; uint64_t av; } map[] = {
1213 { 0x0001, AV_CH_FRONT_CENTER },
1214 { 0x0002, AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT },
1215 { 0x0004, AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT },
1216 { 0x0008, AV_CH_LOW_FREQUENCY },
1217 { 0x0010, AV_CH_BACK_CENTER },
1218 { 0x0020, AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT },
1219 { 0x0040, AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT },
1220 { 0x0080, AV_CH_TOP_FRONT_CENTER },
1221 { 0x0100, AV_CH_TOP_CENTER },
1222 { 0x0200, AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER },
1223 { 0x0400, AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT },
1224 { 0x0800, AV_CH_SIDE_SURROUND_LEFT | AV_CH_SIDE_SURROUND_RIGHT },
1225 { 0x1000, AV_CH_LOW_FREQUENCY_2 },
1226 { 0x2000, AV_CH_TOP_SIDE_LEFT | AV_CH_TOP_SIDE_RIGHT },
1227 { 0x4000, AV_CH_TOP_BACK_CENTER },
1228 { 0x8000, AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT },
1229 };
1230 ✗ uint64_t mask = 0;
1231 int i;
1232 ✗ for (i = 0; i < FF_ARRAY_ELEMS(map); i++)
1233 ✗ if (code & map[i].dts)
1234 ✗ mask |= map[i].av;
1235 ✗ return mask;
1236 }
1237
1238 ✗ static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1239 {
1240 #define DDTS_SIZE 20
1241 uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
1242 ✗ AVStream *st = NULL;
1243 ✗ uint32_t frame_duration_code = 0;
1244 ✗ uint32_t channel_layout_code = 0;
1245 uint64_t channel_layout_mask;
1246 unsigned int stream_construction;
1247 unsigned int representation_type;
1248 GetBitContext gb;
1249 int ret;
1250
1251 ✗ if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
1252 ✗ return ret;
1253
1254 ✗ init_get_bits(&gb, buf, 8 * DDTS_SIZE);
1255
1256 ✗ if (c->fc->nb_streams < 1) {
1257 ✗ return 0;
1258 }
1259 ✗ st = c->fc->streams[c->fc->nb_streams-1];
1260
1261 ✗ st->codecpar->sample_rate = get_bits_long(&gb, 32);
1262 ✗ if (st->codecpar->sample_rate <= 0) {
1263 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
1264 ✗ return AVERROR_INVALIDDATA;
1265 }
1266 ✗ skip_bits_long(&gb, 32); /* max bitrate */
1267 ✗ st->codecpar->bit_rate = get_bits_long(&gb, 32);
1268 ✗ st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
1269 ✗ frame_duration_code = get_bits(&gb, 2);
1270 ✗ stream_construction = get_bits(&gb, 5); /* Table E-2 - profile source */
1271 ✗ skip_bits(&gb, 1); /* CoreLFEPresent */
1272 ✗ skip_bits(&gb, 6); /* CoreLayout */
1273 ✗ skip_bits(&gb, 14); /* CoreSize */
1274 ✗ skip_bits(&gb, 1); /* StereoDownmix */
1275 ✗ representation_type = get_bits(&gb, 3);
1276 ✗ channel_layout_code = get_bits(&gb, 16);
1277
1278 ✗ st->codecpar->frame_size =
1279 ✗ (frame_duration_code == 0) ? 512 :
1280 ✗ (frame_duration_code == 1) ? 1024 :
1281 ✗ (frame_duration_code == 2) ? 2048 :
1282 ✗ (frame_duration_code == 3) ? 4096 : 0;
1283
1284 /* Publish StreamConstruction as codecpar->profile, including for encrypted
1285 * tracks where frame headers cannot be inspected. */
1286 ✗ st->codecpar->profile = mov_dts_stream_construction_to_profile(stream_construction);
1287
1288 ✗ channel_layout_mask = mov_dts_channel_layout_to_mask(channel_layout_code);
1289 ✗ if (channel_layout_mask) {
1290 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
1291 ✗ av_channel_layout_from_mask(&st->codecpar->ch_layout, channel_layout_mask);
1292 ✗ } else if (representation_type == 2 || representation_type == 3) {
1293 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
1294 ✗ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
1295 }
1296
1297 ✗ return 0;
1298 }
1299
1300 50 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1301 {
1302 AVStream *st;
1303
1304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (c->fc->nb_streams < 1)
1305 ✗ return 0;
1306 50 st = c->fc->streams[c->fc->nb_streams-1];
1307
1308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (atom.size < 16)
1309 ✗ return 0;
1310
1311 /* skip version and flags */
1312 50 avio_skip(pb, 4);
1313
1314 50 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
1315
1316 50 return 0;
1317 }
1318
1319 5 static int mov_read_chnl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1320 {
1321 5 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
1322 int version, flags;
1323 int ret;
1324 AVStream *st;
1325
1326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
1327 ✗ return 0;
1328 5 st = c->fc->streams[c->fc->nb_streams-1];
1329
1330 5 version = avio_r8(pb);
1331 5 flags = avio_rb24(pb);
1332
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) {
1333 ✗ av_log(c->fc, AV_LOG_WARNING,
1334 "Unsupported 'chnl' box with version %d, flags: %#x\n",
1335 version, flags);
1336 ✗ return 0;
1337 }
1338
1339 5 ret = ff_mov_read_chnl(c->fc, pb, st, version);
1340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0) {
1341 ✗ avio_seek(pb, end, SEEK_SET);
1342 ✗ return 0;
1343 }
1344
1345
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_tell(pb) != end) {
1346 ✗ av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data inside chnl\n",
1347 ✗ end - avio_tell(pb));
1348 ✗ avio_seek(pb, end, SEEK_SET);
1349 }
1350 5 return ret;
1351 }
1352
1353 2 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1354 {
1355 AVStream *st;
1356 int ret;
1357
1358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
1359 ✗ return 0;
1360 2 st = c->fc->streams[c->fc->nb_streams-1];
1361
1362
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)
1363 ✗ av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
1364
1365 2 return ret;
1366 }
1367
1368 21 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1369 {
1370 AVStream *st;
1371 HEIFItem *item;
1372 AVPacketSideData *sd;
1373 21 int width, height, err = 0;
1374 AVRational aperture_width, aperture_height, horiz_off, vert_off;
1375 AVRational pc_x, pc_y;
1376 uint64_t top, bottom, left, right;
1377
1378 21 item = get_heif_item(c, c->cur_item_id);
1379 21 st = get_curr_st(c);
1380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!st)
1381 ✗ return 0;
1382
1383 21 width = st->codecpar->width;
1384 21 height = st->codecpar->height;
1385
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) {
1386 6 width = item->width;
1387 6 height = item->height;
1388 }
1389
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
21 if (!width || !height) {
1390 ✗ err = AVERROR_INVALIDDATA;
1391 ✗ goto fail;
1392 }
1393
1394 21 aperture_width.num = avio_rb32(pb);
1395 21 aperture_width.den = avio_rb32(pb);
1396 21 aperture_height.num = avio_rb32(pb);
1397 21 aperture_height.den = avio_rb32(pb);
1398
1399 21 horiz_off.num = avio_rb32(pb);
1400 21 horiz_off.den = avio_rb32(pb);
1401 21 vert_off.num = avio_rb32(pb);
1402 21 vert_off.den = avio_rb32(pb);
1403
1404
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 ||
1405
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 ||
1406
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) {
1407 ✗ err = AVERROR_INVALIDDATA;
1408 ✗ goto fail;
1409 }
1410
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) ||
1411 18 (av_cmp_q((AVRational) { height, 1 }, aperture_height) < 0)) {
1412 3 err = AVERROR_INVALIDDATA;
1413 3 goto fail;
1414 }
1415 18 av_log(c->fc, AV_LOG_TRACE, "clap: apertureWidth %d/%d, apertureHeight %d/%d "
1416 "horizOff %d/%d vertOff %d/%d\n",
1417 aperture_width.num, aperture_width.den, aperture_height.num, aperture_height.den,
1418 horiz_off.num, horiz_off.den, vert_off.num, vert_off.den);
1419
1420 18 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1421 18 pc_x = av_add_q(pc_x, horiz_off);
1422 18 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1423 18 pc_y = av_add_q(pc_y, vert_off);
1424
1425 18 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1426 18 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1427 18 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1428 18 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1429
1430 18 left = av_q2d(av_sub_q(pc_x, aperture_width));
1431 18 right = av_q2d(av_add_q(pc_x, aperture_width));
1432 18 top = av_q2d(av_sub_q(pc_y, aperture_height));
1433 18 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1434
1435
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (bottom > (height - 1) ||
1436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 right > (width - 1)) {
1437 ✗ err = AVERROR_INVALIDDATA;
1438 ✗ goto fail;
1439 }
1440
1441 18 bottom = height - 1 - bottom;
1442 18 right = width - 1 - right;
1443
1444
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
18 if (!(left | right | top | bottom))
1445 6 return 0;
1446
1447
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if ((left + right) >= width ||
1448
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 (top + bottom) >= height) {
1449 ✗ err = AVERROR_INVALIDDATA;
1450 ✗ goto fail;
1451 }
1452
1453 12 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1454 12 &st->codecpar->nb_coded_side_data,
1455 AV_PKT_DATA_FRAME_CROPPING,
1456 sizeof(uint32_t) * 4, 0);
1457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!sd)
1458 ✗ return AVERROR(ENOMEM);
1459
1460 12 AV_WL32A(sd->data, top);
1461 12 AV_WL32A(sd->data + 4, bottom);
1462 12 AV_WL32A(sd->data + 8, left);
1463 12 AV_WL32A(sd->data + 12, right);
1464
1465 15 fail:
1466
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 12 times.
15 if (err < 0) {
1467 3 int explode = !!(c->fc->error_recognition & AV_EF_EXPLODE);
1468
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");
1469
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!explode)
1470 3 err = 0;
1471 }
1472
1473 15 return err;
1474 }
1475
1476 /* This atom overrides any previously set aspect ratio */
1477 106 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1478 {
1479 106 const int num = avio_rb32(pb);
1480 106 const int den = avio_rb32(pb);
1481 AVStream *st;
1482 MOVStreamContext *sc;
1483
1484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
106 if (c->fc->nb_streams < 1)
1485 ✗ return 0;
1486 106 st = c->fc->streams[c->fc->nb_streams-1];
1487 106 sc = st->priv_data;
1488
1489 106 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1490
1491
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 2 times.
106 if (den != 0) {
1492 104 sc->h_spacing = num;
1493 104 sc->v_spacing = den;
1494 }
1495 106 return 0;
1496 }
1497
1498 /* this atom contains actual media data */
1499 1076 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1500 {
1501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1076 times.
1076 if (atom.size == 0) /* wrong one (MP4) */
1502 ✗ return 0;
1503 1076 c->found_mdat=1;
1504 1076 return 0; /* now go for moov */
1505 }
1506
1507 #define DRM_BLOB_SIZE 56
1508
1509 ✗ static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1510 {
1511 uint8_t intermediate_key[20];
1512 uint8_t intermediate_iv[20];
1513 uint8_t input[64];
1514 uint8_t output[64];
1515 uint8_t file_checksum[20];
1516 uint8_t calculated_checksum[20];
1517 char checksum_string[2 * sizeof(file_checksum) + 1];
1518 struct AVSHA *sha;
1519 int i;
1520 ✗ int ret = 0;
1521 ✗ uint8_t *activation_bytes = c->activation_bytes;
1522 ✗ uint8_t *fixed_key = c->audible_fixed_key;
1523
1524 ✗ c->aax_mode = 1;
1525
1526 ✗ sha = av_sha_alloc();
1527 ✗ if (!sha)
1528 ✗ return AVERROR(ENOMEM);
1529 ✗ av_free(c->aes_decrypt);
1530 ✗ c->aes_decrypt = av_aes_alloc();
1531 ✗ if (!c->aes_decrypt) {
1532 ✗ ret = AVERROR(ENOMEM);
1533 ✗ goto fail;
1534 }
1535
1536 /* drm blob processing */
1537 ✗ avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1538 ✗ avio_read(pb, input, DRM_BLOB_SIZE);
1539 ✗ avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1540 ✗ ret = ffio_read_size(pb, file_checksum, 20);
1541 ✗ if (ret < 0)
1542 ✗ goto fail;
1543
1544 // required by external tools
1545 ✗ ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1);
1546 ✗ av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string);
1547
1548 /* verify activation data */
1549 ✗ if (!activation_bytes) {
1550 ✗ av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1551 ✗ ret = 0; /* allow ffprobe to continue working on .aax files */
1552 ✗ goto fail;
1553 }
1554 ✗ if (c->activation_bytes_size != 4) {
1555 ✗ av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1556 ✗ ret = AVERROR(EINVAL);
1557 ✗ goto fail;
1558 }
1559
1560 /* verify fixed key */
1561 ✗ if (c->audible_fixed_key_size != 16) {
1562 ✗ av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1563 ✗ ret = AVERROR(EINVAL);
1564 ✗ goto fail;
1565 }
1566
1567 /* AAX (and AAX+) key derivation */
1568 ✗ av_sha_init(sha, 160);
1569 ✗ av_sha_update(sha, fixed_key, 16);
1570 ✗ av_sha_update(sha, activation_bytes, 4);
1571 ✗ av_sha_final(sha, intermediate_key);
1572 ✗ av_sha_init(sha, 160);
1573 ✗ av_sha_update(sha, fixed_key, 16);
1574 ✗ av_sha_update(sha, intermediate_key, 20);
1575 ✗ av_sha_update(sha, activation_bytes, 4);
1576 ✗ av_sha_final(sha, intermediate_iv);
1577 ✗ av_sha_init(sha, 160);
1578 ✗ av_sha_update(sha, intermediate_key, 16);
1579 ✗ av_sha_update(sha, intermediate_iv, 16);
1580 ✗ av_sha_final(sha, calculated_checksum);
1581 ✗ if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1582 ✗ av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1583 ✗ ret = AVERROR_INVALIDDATA;
1584 ✗ goto fail;
1585 }
1586 ✗ av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1587 ✗ av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1588 ✗ for (i = 0; i < 4; i++) {
1589 // file data (in output) is stored in big-endian mode
1590 ✗ if (activation_bytes[i] != output[3 - i]) { // critical error
1591 ✗ av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1592 ✗ ret = AVERROR_INVALIDDATA;
1593 ✗ goto fail;
1594 }
1595 }
1596 ✗ memcpy(c->file_key, output + 8, 16);
1597 ✗ memcpy(input, output + 26, 16);
1598 ✗ av_sha_init(sha, 160);
1599 ✗ av_sha_update(sha, input, 16);
1600 ✗ av_sha_update(sha, c->file_key, 16);
1601 ✗ av_sha_update(sha, fixed_key, 16);
1602 ✗ av_sha_final(sha, c->file_iv);
1603
1604 ✗ fail:
1605 ✗ av_free(sha);
1606
1607 ✗ return ret;
1608 }
1609
1610 ✗ static int mov_aaxc_crypto(MOVContext *c)
1611 {
1612 ✗ if (c->audible_key_size != 16) {
1613 ✗ av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n");
1614 ✗ return AVERROR(EINVAL);
1615 }
1616
1617 ✗ if (c->audible_iv_size != 16) {
1618 ✗ av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n");
1619 ✗ return AVERROR(EINVAL);
1620 }
1621
1622 ✗ c->aes_decrypt = av_aes_alloc();
1623 ✗ if (!c->aes_decrypt) {
1624 ✗ return AVERROR(ENOMEM);
1625 }
1626
1627 ✗ memcpy(c->file_key, c->audible_key, 16);
1628 ✗ memcpy(c->file_iv, c->audible_iv, 16);
1629 ✗ c->aax_mode = 1;
1630
1631 ✗ return 0;
1632 }
1633
1634 // Audible AAX (and AAX+) bytestream decryption
1635 ✗ static int aax_filter(uint8_t *input, int size, MOVContext *c)
1636 {
1637 ✗ int blocks = 0;
1638 unsigned char iv[16];
1639
1640 ✗ memcpy(iv, c->file_iv, 16); // iv is overwritten
1641 ✗ blocks = size >> 4; // trailing bytes are not encrypted!
1642 ✗ av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1643 ✗ av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1644
1645 ✗ return 0;
1646 }
1647
1648 /* read major brand, minor version and compatible brands and store them as metadata */
1649 558 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1650 {
1651 uint32_t minor_ver;
1652 int comp_brand_size;
1653 char* comp_brands_str;
1654 558 uint8_t type[5] = {0};
1655 558 int ret = ffio_read_size(pb, type, 4);
1656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 558 times.
558 if (ret < 0)
1657 ✗ return ret;
1658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 558 times.
558 if (c->fc->nb_streams) {
1659 ✗ if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1660 ✗ return AVERROR_INVALIDDATA;
1661 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate FTYP\n");
1662 ✗ return 0;
1663 }
1664
1665
2/2
✓ Branch 0 taken 313 times.
✓ Branch 1 taken 245 times.
558 if (strcmp(type, "qt "))
1666 313 c->isom = 1;
1667 558 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1668 558 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1669 558 minor_ver = avio_rb32(pb); /* minor version */
1670 558 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1671
1672 558 comp_brand_size = atom.size - 8;
1673
2/4
✓ Branch 0 taken 558 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 558 times.
558 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1674 ✗ return AVERROR_INVALIDDATA;
1675 558 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 558 times.
558 if (!comp_brands_str)
1677 ✗ return AVERROR(ENOMEM);
1678
1679 558 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 558 times.
558 if (ret < 0) {
1681 ✗ av_freep(&comp_brands_str);
1682 ✗ return ret;
1683 }
1684 558 comp_brands_str[comp_brand_size] = 0;
1685 558 av_dict_set(&c->fc->metadata, "compatible_brands",
1686 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1687
1688 // Logic for handling Audible's .aaxc files
1689
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 558 times.
558 if (!strcmp(type, "aaxc")) {
1690 ✗ mov_aaxc_crypto(c);
1691 }
1692
1693 558 return 0;
1694 }
1695
1696 /* this atom should contain all header atoms */
1697 603 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1698 {
1699 int ret;
1700
1701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 603 times.
603 if (c->found_moov) {
1702 ✗ av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1703 ✗ avio_skip(pb, atom.size);
1704 ✗ return 0;
1705 }
1706
1707
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 603 times.
603 if ((ret = mov_read_default(c, pb, atom)) < 0)
1708 ✗ return ret;
1709 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1710 /* so we don't parse the whole file if over a network */
1711 603 c->found_moov=1;
1712 603 return 0; /* now go for mdat */
1713 }
1714
1715 3224 static MOVFragmentStreamInfo * get_frag_stream_info(
1716 MOVFragmentIndex *frag_index,
1717 int index,
1718 int id)
1719 {
1720 int i;
1721 MOVFragmentIndexItem * item;
1722
1723
2/4
✓ Branch 0 taken 3224 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3224 times.
3224 if (index < 0 || index >= frag_index->nb_items)
1724 ✗ return NULL;
1725 3224 item = &frag_index->item[index];
1726
1/2
✓ Branch 0 taken 3408 times.
✗ Branch 1 not taken.
3408 for (i = 0; i < item->nb_stream_info; i++)
1727
2/2
✓ Branch 0 taken 3224 times.
✓ Branch 1 taken 184 times.
3408 if (item->stream_info[i].id == id)
1728 3224 return &item->stream_info[i];
1729
1730 // This shouldn't happen
1731 ✗ return NULL;
1732 }
1733
1734 504 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1735 {
1736 int i;
1737 MOVFragmentIndexItem * item;
1738
1739
1/2
✓ Branch 0 taken 504 times.
✗ Branch 1 not taken.
504 if (frag_index->current < 0 ||
1740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
504 frag_index->current >= frag_index->nb_items)
1741 ✗ return;
1742
1743 504 item = &frag_index->item[frag_index->current];
1744
1/2
✓ Branch 0 taken 563 times.
✗ Branch 1 not taken.
563 for (i = 0; i < item->nb_stream_info; i++)
1745
2/2
✓ Branch 0 taken 504 times.
✓ Branch 1 taken 59 times.
563 if (item->stream_info[i].id == id) {
1746 504 item->current = i;
1747 504 return;
1748 }
1749
1750 // id not found. This shouldn't happen.
1751 ✗ item->current = -1;
1752 }
1753
1754 1466 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1755 MOVFragmentIndex *frag_index)
1756 {
1757 MOVFragmentIndexItem *item;
1758
1/2
✓ Branch 0 taken 1466 times.
✗ Branch 1 not taken.
1466 if (frag_index->current < 0 ||
1759
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 1445 times.
1466 frag_index->current >= frag_index->nb_items)
1760 21 return NULL;
1761
1762 1445 item = &frag_index->item[frag_index->current];
1763
2/4
✓ Branch 0 taken 1445 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1445 times.
✗ Branch 3 not taken.
1445 if (item->current >= 0 && item->current < item->nb_stream_info)
1764 1445 return &item->stream_info[item->current];
1765
1766 // This shouldn't happen
1767 ✗ return NULL;
1768 }
1769
1770 907 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1771 {
1772 int a, b, m;
1773 int64_t moof_offset;
1774
1775 // Optimize for appending new entries
1776
2/2
✓ Branch 0 taken 885 times.
✓ Branch 1 taken 22 times.
907 if (!frag_index->nb_items ||
1777
2/2
✓ Branch 0 taken 465 times.
✓ Branch 1 taken 420 times.
885 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1778 487 return frag_index->nb_items;
1779
1780 420 a = -1;
1781 420 b = frag_index->nb_items;
1782
1783
2/2
✓ Branch 0 taken 2680 times.
✓ Branch 1 taken 420 times.
3100 while (b - a > 1) {
1784 2680 m = (a + b) >> 1;
1785 2680 moof_offset = frag_index->item[m].moof_offset;
1786
2/2
✓ Branch 0 taken 750 times.
✓ Branch 1 taken 1930 times.
2680 if (moof_offset >= offset)
1787 750 b = m;
1788
2/2
✓ Branch 0 taken 2348 times.
✓ Branch 1 taken 332 times.
2680 if (moof_offset <= offset)
1789 2348 a = m;
1790 }
1791 420 return b;
1792 }
1793
1794 7 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1795 {
1796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 av_assert0(frag_stream_info);
1797
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1798 ✗ return frag_stream_info->sidx_pts;
1799
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1800 4 return frag_stream_info->first_tfra_pts;
1801 3 return frag_stream_info->tfdt_dts;
1802 }
1803
1804 226 static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1805 MOVFragmentIndex *frag_index, int index)
1806 {
1807 MOVFragmentStreamInfo * frag_stream_info;
1808 226 MOVStreamContext *sc = dst_st->priv_data;
1809 int64_t timestamp;
1810 int i, j;
1811
1812 // If the stream is referenced by any sidx, limit the search
1813 // to fragments that referenced this stream in the sidx
1814
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 7 times.
226 if (sc->has_sidx) {
1815 219 frag_stream_info = get_frag_stream_info(frag_index, index, sc->id);
1816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!frag_stream_info)
1817 ✗ return AV_NOPTS_VALUE;
1818
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1819 219 return frag_stream_info->sidx_pts;
1820 ✗ if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1821 ✗ return frag_stream_info->first_tfra_pts;
1822 ✗ return frag_stream_info->sidx_pts;
1823 }
1824
1825
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++) {
1826
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)
1827 5 continue;
1828 7 AVStream *frag_stream = NULL;
1829 7 frag_stream_info = &frag_index->item[index].stream_info[i];
1830
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
21 for (j = 0; j < s->nb_streams; j++) {
1831 14 MOVStreamContext *sc2 = s->streams[j]->priv_data;
1832
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (sc2->id == frag_stream_info->id)
1833 7 frag_stream = s->streams[j];
1834 }
1835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!frag_stream) {
1836 ✗ av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1837 ✗ continue;
1838 }
1839 7 timestamp = get_stream_info_time(frag_stream_info);
1840
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (timestamp != AV_NOPTS_VALUE)
1841 4 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1842 }
1843 3 return AV_NOPTS_VALUE;
1844 }
1845
1846 28 static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1847 AVStream *st, int64_t timestamp)
1848 {
1849 int a, b, m, m0;
1850 int64_t frag_time;
1851
1852 28 a = -1;
1853 28 b = frag_index->nb_items;
1854
1855
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 28 times.
252 while (b - a > 1) {
1856 224 m0 = m = (a + b) >> 1;
1857
1858
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 &&
1859 226 (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
1860 3 m++;
1861
1862
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)
1863 95 a = m;
1864 else
1865 129 b = m0;
1866 }
1867
1868 28 return a;
1869 }
1870
1871 859 static int update_frag_index(MOVContext *c, int64_t offset)
1872 {
1873 int index, i;
1874 MOVFragmentIndexItem * item;
1875 MOVFragmentStreamInfo * frag_stream_info;
1876
1877 // If moof_offset already exists in frag_index, return index to it
1878 859 index = search_frag_moof_offset(&c->frag_index, offset);
1879
2/2
✓ Branch 0 taken 379 times.
✓ Branch 1 taken 480 times.
859 if (index < c->frag_index.nb_items &&
1880
2/2
✓ Branch 0 taken 377 times.
✓ Branch 1 taken 2 times.
379 c->frag_index.item[index].moof_offset == offset)
1881 377 return index;
1882
1883 // offset is not yet in frag index.
1884 // Insert new item at index (sorted by moof offset)
1885 482 item = av_fast_realloc(c->frag_index.item,
1886 482 &c->frag_index.allocated_size,
1887 482 (c->frag_index.nb_items + 1) *
1888 sizeof(*c->frag_index.item));
1889
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 482 times.
482 if (!item)
1890 ✗ return -1;
1891 482 c->frag_index.item = item;
1892
1893 482 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1894 sizeof(*item->stream_info));
1895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 482 times.
482 if (!frag_stream_info)
1896 ✗ return -1;
1897
1898
2/2
✓ Branch 0 taken 584 times.
✓ Branch 1 taken 482 times.
1066 for (i = 0; i < c->fc->nb_streams; i++) {
1899 // Avoid building frag index if streams lack track id.
1900 584 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 584 times.
584 if (sc->id < 0) {
1902 ✗ av_free(frag_stream_info);
1903 ✗ return AVERROR_INVALIDDATA;
1904 }
1905
1906 584 frag_stream_info[i].id = sc->id;
1907 584 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1908 584 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1909 584 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1910 584 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1911 584 frag_stream_info[i].index_base = -1;
1912 584 frag_stream_info[i].index_entry = -1;
1913 584 frag_stream_info[i].encryption_index = NULL;
1914 584 frag_stream_info[i].stsd_id = -1;
1915 }
1916
1917
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 480 times.
482 if (index < c->frag_index.nb_items)
1918 2 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1919 2 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1920
1921 482 item = &c->frag_index.item[index];
1922 482 item->headers_read = 0;
1923 482 item->current = 0;
1924 482 item->nb_stream_info = c->fc->nb_streams;
1925 482 item->moof_offset = offset;
1926 482 item->stream_info = frag_stream_info;
1927 482 c->frag_index.nb_items++;
1928
1929 482 return index;
1930 }
1931
1932 504 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1933 int id, int entries)
1934 {
1935 int i;
1936 MOVFragmentStreamInfo * frag_stream_info;
1937
1938
1/2
✓ Branch 0 taken 504 times.
✗ Branch 1 not taken.
504 if (index < 0)
1939 504 return;
1940 ✗ for (i = index; i < frag_index->nb_items; i++) {
1941 ✗ frag_stream_info = get_frag_stream_info(frag_index, i, id);
1942 ✗ if (frag_stream_info && frag_stream_info->index_entry >= 0)
1943 ✗ frag_stream_info->index_entry += entries;
1944 }
1945 }
1946
1947 478 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1948 {
1949 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1950 478 c->fragment.found_tfhd = 0;
1951
1952
4/4
✓ Branch 0 taken 476 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 475 times.
478 if (!c->has_looked_for_mfra && c->use_mfra_for > 0) {
1953 1 c->has_looked_for_mfra = 1;
1954
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1955 int ret;
1956 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1957 "for a mfra\n");
1958
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((ret = mov_read_mfra(c, pb)) < 0) {
1959 ✗ av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1960 "read the mfra (may be a live ismv)\n");
1961 }
1962 } else {
1963 ✗ av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1964 "seekable, can not look for mfra\n");
1965 }
1966 }
1967 478 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1968 478 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1969 478 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1970 478 return mov_read_default(c, pb, atom);
1971 }
1972
1973 1334 static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version)
1974 {
1975 int64_t time;
1976
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1319 times.
1334 if (version == 1) {
1977 15 time = avio_rb64(pb);
1978 15 avio_rb64(pb);
1979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (time < 0) {
1980 ✗ av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n");
1981 ✗ return;
1982 }
1983 } else {
1984 1319 time = avio_rb32(pb);
1985 1319 avio_rb32(pb); /* modification time */
1986
4/4
✓ Branch 0 taken 649 times.
✓ Branch 1 taken 670 times.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 587 times.
1319 if (time > 0 && time < 2082844800) {
1987 62 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1988 62 time += 2082844800;
1989 }
1990 }
1991
2/2
✓ Branch 0 taken 655 times.
✓ Branch 1 taken 679 times.
1334 if (time) {
1992 655 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1993
1994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 655 times.
655 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1995 ✗ av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n");
1996 ✗ return;
1997 }
1998
1999 655 ff_dict_set_timestamp(metadata, "creation_time", time * 1000000);
2000 }
2001 }
2002
2003 734 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2004 {
2005 AVStream *st;
2006 MOVStreamContext *sc;
2007 int version;
2008 734 char language[4] = {0};
2009 unsigned lang;
2010
2011
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (c->fc->nb_streams < 1)
2012 ✗ return 0;
2013 734 st = c->fc->streams[c->fc->nb_streams-1];
2014 734 sc = st->priv_data;
2015
2016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (sc->time_scale) {
2017 ✗ av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
2018 ✗ return AVERROR_INVALIDDATA;
2019 }
2020
2021 734 version = avio_r8(pb);
2022
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (version > 1) {
2023 ✗ avpriv_request_sample(c->fc, "Version %d", version);
2024 ✗ return AVERROR_PATCHWELCOME;
2025 }
2026 734 avio_rb24(pb); /* flags */
2027 734 mov_metadata_creation_time(c, pb, &st->metadata, version);
2028
2029 734 sc->time_scale = avio_rb32(pb);
2030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (sc->time_scale <= 0) {
2031 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
2032 ✗ sc->time_scale = 1;
2033 }
2034
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 721 times.
734 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
2035
2036
6/6
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 721 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 721 times.
✓ Branch 5 taken 4 times.
734 if ((version == 1 && st->duration == UINT64_MAX) ||
2037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 721 times.
721 (version != 1 && st->duration == UINT32_MAX)) {
2038 9 st->duration = 0;
2039 }
2040
2041 734 lang = avio_rb16(pb); /* language */
2042
2/2
✓ Branch 1 taken 560 times.
✓ Branch 2 taken 174 times.
734 if (ff_mov_lang_to_iso639(lang, language))
2043 560 av_dict_set(&st->metadata, "language", language, 0);
2044 734 avio_rb16(pb); /* quality */
2045
2046 734 return 0;
2047 }
2048
2049 600 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2050 {
2051 int i;
2052 600 int version = avio_r8(pb); /* version */
2053 600 avio_rb24(pb); /* flags */
2054
2055 600 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
2056 600 c->time_scale = avio_rb32(pb); /* time scale */
2057
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 600 times.
600 if (c->time_scale <= 0) {
2058 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
2059 ✗ c->time_scale = 1;
2060 }
2061 600 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
2062
2063
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 598 times.
600 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
2064 600 avio_rb32(pb); /* preferred scale */
2065
2066 600 avio_rb16(pb); /* preferred volume */
2067
2068 600 avio_skip(pb, 10); /* reserved */
2069
2070 /* movie display matrix, store it in main context and use it later on */
2071
2/2
✓ Branch 0 taken 1800 times.
✓ Branch 1 taken 600 times.
2400 for (i = 0; i < 3; i++) {
2072 1800 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
2073 1800 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
2074 1800 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
2075 }
2076
2077 600 avio_rb32(pb); /* preview time */
2078 600 avio_rb32(pb); /* preview duration */
2079 600 avio_rb32(pb); /* poster time */
2080 600 avio_rb32(pb); /* selection time */
2081 600 avio_rb32(pb); /* selection duration */
2082 600 avio_rb32(pb); /* current time */
2083 600 avio_rb32(pb); /* next track ID */
2084
2085 600 return 0;
2086 }
2087
2088 7 static void set_last_stream_little_endian(AVFormatContext *fc)
2089 {
2090 AVStream *st;
2091
2092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (fc->nb_streams < 1)
2093 ✗ return;
2094 7 st = fc->streams[fc->nb_streams-1];
2095
2096
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) {
2097 5 case AV_CODEC_ID_PCM_S16BE:
2098 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2099 5 break;
2100 1 case AV_CODEC_ID_PCM_S24BE:
2101 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
2102 1 break;
2103 ✗ case AV_CODEC_ID_PCM_S32BE:
2104 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
2105 ✗ break;
2106 1 case AV_CODEC_ID_PCM_F32BE:
2107 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
2108 1 break;
2109 ✗ case AV_CODEC_ID_PCM_F64BE:
2110 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
2111 ✗ break;
2112 ✗ default:
2113 ✗ break;
2114 }
2115 }
2116
2117 5 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2118 {
2119 5 int little_endian = avio_rb16(pb) & 0xFF;
2120 5 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
2121
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (little_endian == 1)
2122 1 set_last_stream_little_endian(c->fc);
2123 5 return 0;
2124 }
2125
2126 6 static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2127 {
2128 int format_flags;
2129 int version, flags;
2130 int pcm_sample_size;
2131 6 AVFormatContext *fc = c->fc;
2132 AVStream *st;
2133 MOVStreamContext *sc;
2134
2135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 6) {
2136 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n");
2137 ✗ return AVERROR_INVALIDDATA;
2138 }
2139
2140 6 version = avio_r8(pb);
2141 6 flags = avio_rb24(pb);
2142
2143
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) {
2144 ✗ av_log(c->fc, AV_LOG_ERROR,
2145 "Unsupported 'pcmC' box with version %d, flags: %x",
2146 version, flags);
2147 ✗ return AVERROR_INVALIDDATA;
2148 }
2149
2150 6 format_flags = avio_r8(pb);
2151 6 pcm_sample_size = avio_r8(pb);
2152
2153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fc->nb_streams < 1)
2154 ✗ return AVERROR_INVALIDDATA;
2155
2156 6 st = fc->streams[fc->nb_streams - 1];
2157 6 sc = st->priv_data;
2158
2159
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (sc->format == MOV_MP4_FPCM_TAG) {
2160
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (pcm_sample_size) {
2161 1 case 32:
2162 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE;
2163 1 break;
2164 ✗ case 64:
2165 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE;
2166 ✗ break;
2167 ✗ default:
2168 ✗ av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2169 pcm_sample_size,
2170 ✗ av_fourcc2str(sc->format));
2171 ✗ return AVERROR_INVALIDDATA;
2172 }
2173
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (sc->format == MOV_MP4_IPCM_TAG) {
2174
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 switch (pcm_sample_size) {
2175 5 case 16:
2176 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2177 5 break;
2178 ✗ case 24:
2179 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
2180 ✗ break;
2181 ✗ case 32:
2182 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
2183 ✗ break;
2184 ✗ default:
2185 ✗ av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2186 pcm_sample_size,
2187 ✗ av_fourcc2str(sc->format));
2188 ✗ return AVERROR_INVALIDDATA;
2189 }
2190 } else {
2191 ✗ av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n",
2192 ✗ av_fourcc2str(sc->format));
2193 ✗ return AVERROR_INVALIDDATA;
2194 }
2195
2196
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
2197 6 set_last_stream_little_endian(c->fc);
2198 6 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2199
2200 6 return 0;
2201 }
2202
2203 58 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2204 {
2205 AVStream *st;
2206 58 HEIFItem *item = NULL;
2207 58 char color_parameter_type[5] = { 0 };
2208 uint16_t color_primaries, color_trc, color_matrix;
2209 int ret;
2210
2211 58 st = get_curr_st(c);
2212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!st) {
2213 ✗ item = get_heif_item(c, c->cur_item_id);
2214 ✗ if (!item)
2215 ✗ return 0;
2216 }
2217
2218 58 ret = ffio_read_size(pb, color_parameter_type, 4);
2219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (ret < 0)
2220 ✗ return ret;
2221
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 22 times.
58 if (strncmp(color_parameter_type, "nclx", 4) &&
2222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 strncmp(color_parameter_type, "nclc", 4) &&
2223 ✗ strncmp(color_parameter_type, "prof", 4)) {
2224 ✗ av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
2225 color_parameter_type);
2226 ✗ return 0;
2227 }
2228
2229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!strncmp(color_parameter_type, "prof", 4)) {
2230 AVPacketSideData *sd;
2231 uint8_t *icc_profile;
2232 ✗ if (st) {
2233 ✗ sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
2234 ✗ &st->codecpar->nb_coded_side_data,
2235 AV_PKT_DATA_ICC_PROFILE,
2236 ✗ atom.size - 4, 0);
2237 ✗ if (!sd)
2238 ✗ return AVERROR(ENOMEM);
2239 ✗ icc_profile = sd->data;
2240 } else {
2241 ✗ if (c->heif_icc_profile_items >= c->fc->max_streams) {
2242 ✗ av_log(c->fc, AV_LOG_WARNING,
2243 "HEIF ICC profile copies exceed cap %d; ignoring further items\n",
2244 ✗ c->fc->max_streams);
2245 ✗ return 0;
2246 }
2247 ✗ av_freep(&item->icc_profile);
2248 ✗ icc_profile = item->icc_profile = av_malloc(atom.size - 4);
2249 ✗ if (!icc_profile) {
2250 ✗ item->icc_profile_size = 0;
2251 ✗ return AVERROR(ENOMEM);
2252 }
2253 ✗ item->icc_profile_size = atom.size - 4;
2254 ✗ c->heif_icc_profile_items++;
2255 }
2256 ✗ ret = ffio_read_size(pb, icc_profile, atom.size - 4);
2257 ✗ if (ret < 0)
2258 ✗ return ret;
2259
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 } else if (st) {
2260 58 color_primaries = avio_rb16(pb);
2261 58 color_trc = avio_rb16(pb);
2262 58 color_matrix = avio_rb16(pb);
2263
2264 58 av_log(c->fc, AV_LOG_TRACE,
2265 "%s: pri %d trc %d matrix %d",
2266 color_parameter_type, color_primaries, color_trc, color_matrix);
2267
2268
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 36 times.
58 if (!strncmp(color_parameter_type, "nclx", 4)) {
2269 22 uint8_t color_range = avio_r8(pb) >> 7;
2270 22 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2271
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 20 times.
22 if (color_range)
2272 2 st->codecpar->color_range = AVCOL_RANGE_JPEG;
2273 else
2274 20 st->codecpar->color_range = AVCOL_RANGE_MPEG;
2275 }
2276
2277
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if (!av_color_primaries_name(color_primaries))
2278 ✗ color_primaries = AVCOL_PRI_UNSPECIFIED;
2279
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if (!av_color_transfer_name(color_trc))
2280 ✗ color_trc = AVCOL_TRC_UNSPECIFIED;
2281
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if (!av_color_space_name(color_matrix))
2282 ✗ color_matrix = AVCOL_SPC_UNSPECIFIED;
2283
2284 58 st->codecpar->color_primaries = color_primaries;
2285 58 st->codecpar->color_trc = color_trc;
2286 58 st->codecpar->color_space = color_matrix;
2287 58 av_log(c->fc, AV_LOG_TRACE, "\n");
2288 }
2289 58 return 0;
2290 }
2291
2292 122 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2293 {
2294 AVStream *st;
2295 unsigned mov_field_order;
2296 122 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2297
2298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 122 times.
122 if (c->fc->nb_streams < 1) // will happen with jp2 files
2299 ✗ return 0;
2300 122 st = c->fc->streams[c->fc->nb_streams-1];
2301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 122 times.
122 if (atom.size < 2)
2302 ✗ return AVERROR_INVALIDDATA;
2303 122 mov_field_order = avio_rb16(pb);
2304
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 25 times.
122 if ((mov_field_order & 0xFF00) == 0x0100)
2305 97 decoded_field_order = AV_FIELD_PROGRESSIVE;
2306
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 else if ((mov_field_order & 0xFF00) == 0x0200) {
2307
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) {
2308 1 case 0x01: decoded_field_order = AV_FIELD_TT;
2309 1 break;
2310 ✗ case 0x06: decoded_field_order = AV_FIELD_BB;
2311 ✗ break;
2312 1 case 0x09: decoded_field_order = AV_FIELD_TB;
2313 1 break;
2314 23 case 0x0E: decoded_field_order = AV_FIELD_BT;
2315 23 break;
2316 }
2317 }
2318
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) {
2319 ✗ av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
2320 }
2321 122 st->codecpar->field_order = decoded_field_order;
2322
2323 122 return 0;
2324 }
2325
2326 69 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
2327 {
2328 69 int err = 0;
2329 69 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
2330
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)
2331 ✗ return AVERROR_INVALIDDATA;
2332
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
69 if ((err = av_reallocp(&par->extradata, size)) < 0) {
2333 ✗ par->extradata_size = 0;
2334 ✗ return err;
2335 }
2336 69 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
2337 69 return 0;
2338 }
2339
2340 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
2341 65 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2342 AVCodecParameters *par, uint8_t *buf)
2343 {
2344 65 int64_t result = atom.size;
2345 int err;
2346
2347 65 AV_WB32(buf , atom.size + 8);
2348 65 AV_WL32(buf + 4, atom.type);
2349 65 err = ffio_read_size(pb, buf + 8, atom.size);
2350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (err < 0) {
2351 ✗ par->extradata_size -= atom.size;
2352 ✗ return err;
2353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 } else if (err < atom.size) {
2354 ✗ av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
2355 ✗ par->extradata_size -= atom.size - err;
2356 ✗ result = err;
2357 }
2358 65 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2359 65 return result;
2360 }
2361
2362 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
2363 58 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2364 enum AVCodecID codec_id)
2365 {
2366 AVStream *st;
2367 uint64_t original_size;
2368 int err;
2369
2370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (c->fc->nb_streams < 1) // will happen with jp2 files
2371 ✗ return 0;
2372 58 st = c->fc->streams[c->fc->nb_streams-1];
2373
2374
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
58 if (st->codecpar->codec_id != codec_id)
2375 19 return 0; /* unexpected codec_id - don't mess with extradata */
2376
2377 39 original_size = st->codecpar->extradata_size;
2378 39 err = mov_realloc_extradata(st->codecpar, atom);
2379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err)
2380 ✗ return err;
2381
2382 39 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
2383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err < 0)
2384 ✗ return err;
2385 39 return 0; // Note: this is the original behavior to ignore truncation.
2386 }
2387
2388 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
2389 16 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2390 {
2391 16 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
2392 }
2393
2394 ✗ static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2395 {
2396 ✗ return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS);
2397 }
2398
2399 ✗ static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2400 {
2401 ✗ return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
2402 }
2403
2404 ✗ static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2405 {
2406 ✗ return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
2407 }
2408
2409 19 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2410 {
2411 19 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
2412
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!ret)
2413 19 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
2414 19 return ret;
2415 }
2416
2417 ✗ static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2418 {
2419 ✗ int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
2420
2421 ✗ if (!ret && c->fc->nb_streams >= 1) {
2422 ✗ AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2423 ✗ if (par->extradata_size >= 40) {
2424 ✗ par->height = AV_RB16(&par->extradata[36]);
2425 ✗ par->width = AV_RB16(&par->extradata[38]);
2426 }
2427 }
2428 ✗ return ret;
2429 }
2430
2431 16 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2432 {
2433
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (c->fc->nb_streams >= 1) {
2434 16 AVStream *const st = c->fc->streams[c->fc->nb_streams - 1];
2435 16 FFStream *const sti = ffstream(st);
2436 16 AVCodecParameters *par = st->codecpar;
2437
2438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
2439 ✗ par->codec_id == AV_CODEC_ID_H264 &&
2440 ✗ atom.size > 11) {
2441 int cid;
2442 ✗ avio_skip(pb, 10);
2443 ✗ cid = avio_rb16(pb);
2444 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
2445 ✗ if (cid == 0xd4d || cid == 0xd4e)
2446 ✗ par->width = 1440;
2447 ✗ return 0;
2448
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
2449
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
2450
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
2451
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 atom.size >= 24) {
2452 int num, den;
2453 13 avio_skip(pb, 12);
2454 13 num = avio_rb32(pb);
2455 13 den = avio_rb32(pb);
2456
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)
2457 ✗ return 0;
2458
2/3
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
13 switch (avio_rb32(pb)) {
2459 12 case 2:
2460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (den >= INT_MAX / 2)
2461 ✗ return 0;
2462 12 den *= 2;
2463 av_fallthrough;
2464 13 case 1:
2465 13 sti->display_aspect_ratio = (AVRational){ num, den };
2466 av_fallthrough;
2467 13 default:
2468 13 return 0;
2469 }
2470 }
2471 }
2472
2473 3 return mov_read_avid(c, pb, atom);
2474 }
2475
2476 26 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2477 {
2478 26 int ret = 0;
2479 26 int length = 0;
2480 uint64_t original_size;
2481
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (c->fc->nb_streams >= 1) {
2482 26 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (par->codec_id == AV_CODEC_ID_H264)
2484 ✗ return 0;
2485
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (atom.size == 16) {
2486 26 original_size = par->extradata_size;
2487 26 ret = mov_realloc_extradata(par, atom);
2488
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!ret) {
2489 26 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
2490
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (length == atom.size) {
2491 26 const uint8_t range_value = par->extradata[original_size + 19];
2492
1/3
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
26 switch (range_value) {
2493 26 case 1:
2494 26 par->color_range = AVCOL_RANGE_MPEG;
2495 26 break;
2496 ✗ case 2:
2497 ✗ par->color_range = AVCOL_RANGE_JPEG;
2498 ✗ break;
2499 ✗ default:
2500 ✗ av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
2501 ✗ break;
2502 }
2503 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
2504 } else {
2505 /* For some reason the whole atom was not added to the extradata */
2506 ✗ av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
2507 }
2508 } else {
2509 ✗ av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
2510 }
2511 } else {
2512 ✗ av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
2513 }
2514 }
2515
2516 26 return ret;
2517 }
2518
2519 4 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2520 {
2521 4 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
2522 }
2523
2524 33 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2525 {
2526 AVStream *st;
2527 int ret;
2528
2529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (c->fc->nb_streams < 1)
2530 ✗ return 0;
2531 33 st = c->fc->streams[c->fc->nb_streams-1];
2532
2533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if ((uint64_t)atom.size > (1<<30))
2534 ✗ return AVERROR_INVALIDDATA;
2535
2536
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 2 times.
33 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2537
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
2539 // pass all frma atom to codec, needed at least for QDMC and QDM2
2540 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2542 ✗ return ret;
2543
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 } else if (atom.size > 8) { /* to read frma, esds atoms */
2544
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) {
2545 uint64_t buffer;
2546 10 ret = ffio_ensure_seekback(pb, 8);
2547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2548 ✗ return ret;
2549 10 buffer = avio_rb64(pb);
2550 10 atom.size -= 8;
2551
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
2552
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 <= atom.size
2553
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 >= 8) {
2554 10 avio_skip(pb, -8);
2555 10 atom.size += 8;
2556 ✗ } else if (!st->codecpar->extradata_size) {
2557 #define ALAC_EXTRADATA_SIZE 36
2558 ✗ st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
2559 ✗ if (!st->codecpar->extradata)
2560 ✗ return AVERROR(ENOMEM);
2561 ✗ st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
2562 ✗ AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
2563 ✗ AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
2564 ✗ AV_WB64(st->codecpar->extradata + 12, buffer);
2565 ✗ avio_read(pb, st->codecpar->extradata + 20, 16);
2566 ✗ avio_skip(pb, atom.size - 24);
2567 ✗ return 0;
2568 }
2569 }
2570
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 if ((ret = mov_read_default(c, pb, atom)) < 0)
2571 ✗ return ret;
2572 } else
2573 ✗ avio_skip(pb, atom.size);
2574 33 return 0;
2575 }
2576
2577 /**
2578 * This function reads atom content and puts data in extradata without tag
2579 * nor size unlike mov_read_extradata.
2580 */
2581 200 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2582 {
2583 AVStream *st;
2584 int ret;
2585
2586 200 st = get_curr_st(c);
2587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 if (!st)
2588 ✗ return 0;
2589
2590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 if ((uint64_t)atom.size > (1<<30))
2591 ✗ return AVERROR_INVALIDDATA;
2592
2593
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 199 times.
200 if (atom.type == MKTAG('v','v','c','C')) {
2594 1 avio_skip(pb, 4);
2595 1 atom.size -= 4;
2596 }
2597
2598
2/2
✓ Branch 0 taken 196 times.
✓ Branch 1 taken 4 times.
200 if (atom.size >= 10) {
2599 // Broken files created by legacy versions of libavformat will
2600 // wrap a whole fiel atom inside of a glbl atom.
2601 196 unsigned size = avio_rb32(pb);
2602 196 unsigned type = avio_rl32(pb);
2603
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 196 times.
196 if (avio_feof(pb))
2604 ✗ return AVERROR_INVALIDDATA;
2605 196 avio_seek(pb, -8, SEEK_CUR);
2606
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)
2607 10 return mov_read_default(c, pb, atom);
2608 }
2609
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) {
2610 ✗ av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
2611 ✗ return 0;
2612 }
2613 190 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2614
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
190 if (ret < 0)
2615 ✗ return ret;
2616
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'))
2617 /* HEVC-based Dolby Vision derived from hvc1.
2618 Happens to match with an identifier
2619 previously utilized for DV. Thus, if we have
2620 the hvcC extradata box available as specified,
2621 set codec to HEVC */
2622 ✗ st->codecpar->codec_id = AV_CODEC_ID_HEVC;
2623
2624 190 return 0;
2625 }
2626
2627 2 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2628 {
2629 AVStream *st;
2630 uint8_t profile_level;
2631 int ret;
2632
2633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
2634 ✗ return 0;
2635 2 st = c->fc->streams[c->fc->nb_streams-1];
2636
2637
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)
2638 ✗ return AVERROR_INVALIDDATA;
2639
2640 2 profile_level = avio_r8(pb);
2641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((profile_level & 0xf0) != 0xc0)
2642 ✗ return 0;
2643
2644 2 avio_seek(pb, 6, SEEK_CUR);
2645 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
2646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2647 ✗ return ret;
2648
2649 2 return 0;
2650 }
2651
2652 70 static int mov_find_tref_id(const MovTref *tag, uint32_t id)
2653 {
2654
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 42 times.
100 for (int i = 0; i < tag->nb_id; i++) {
2655
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 30 times.
58 if (tag->id[i] == id)
2656 28 return 1;
2657 }
2658 42 return 0;
2659 }
2660
2661 42 static int mov_add_tref_id(MovTref *tag, uint32_t id)
2662 {
2663 42 int ret = mov_find_tref_id(tag, id);
2664
2665
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 if (!ret) {
2666 42 uint32_t *tmp = av_realloc_array(tag->id, tag->nb_id + 1, sizeof(*tag->id));
2667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!tmp)
2668 ✗ return AVERROR(ENOMEM);
2669 42 tag->id = tmp;
2670 42 tag->id[tag->nb_id++] = id;
2671 }
2672
2673 42 return 0;
2674 }
2675
2676 1550 static MovTref *mov_find_tref_tag(const MOVStreamContext *sc, uint32_t name)
2677 {
2678
2/2
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 1482 times.
1667 for (int i = 0; i < sc->nb_tref_tags; i++) {
2679 185 MovTref *entry = &sc->tref_tags[i];
2680
2681
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 117 times.
185 if (entry->name == name)
2682 68 return entry;
2683 }
2684 1482 return NULL;
2685 }
2686
2687 32 static MovTref *mov_add_tref_tag(MOVStreamContext *sc, uint32_t name)
2688 {
2689 32 MovTref *tag = mov_find_tref_tag(sc, name);
2690
2691
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (!tag) {
2692 32 MovTref *tmp = av_realloc_array(sc->tref_tags, sc->nb_tref_tags + 1,
2693 sizeof(*sc->tref_tags));
2694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!tmp)
2695 ✗ return NULL;
2696 32 sc->tref_tags = tmp;
2697 32 tag = &sc->tref_tags[sc->nb_tref_tags++];
2698 32 *tag = (MovTref){ .name = name };
2699 }
2700
2701 32 return tag;
2702 }
2703
2704 11 static int mov_read_cdsc_rndr(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2705 {
2706 AVStream* st;
2707 MOVStreamContext* sc;
2708
2709
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
2710 ✗ return 0;
2711
2712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size > 4) {
2713 ✗ av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type cdsc/rndr is supported\n");
2714 ✗ return AVERROR_PATCHWELCOME;
2715 }
2716
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 4)
2717 ✗ return AVERROR_INVALIDDATA;
2718
2719 11 st = get_curr_st(c);
2720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!st)
2721 ✗ return AVERROR_INVALIDDATA;
2722 11 sc = st->priv_data;
2723
2724 11 MovTref *tag = mov_add_tref_tag(sc, atom.type);
2725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!tag)
2726 ✗ return AVERROR(ENOMEM);
2727
2728 11 int ret = mov_add_tref_id(tag, avio_rb32(pb));
2729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0)
2730 ✗ return ret;
2731
2732 11 return 0;
2733 }
2734
2735 ✗ static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2736 {
2737 AVStream* st;
2738 MOVStreamContext* sc;
2739
2740 ✗ if (c->fc->nb_streams < 1)
2741 ✗ return 0;
2742
2743 /* For SBAS this should be fine - though beware if someone implements a
2744 * tref atom processor that doesn't drop down to default then this may
2745 * be lost. */
2746 ✗ if (atom.size > 4) {
2747 ✗ av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2748 ✗ return AVERROR_PATCHWELCOME;
2749 }
2750 ✗ if (atom.size < 4)
2751 ✗ return AVERROR_INVALIDDATA;
2752
2753 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
2754 ✗ sc = st->priv_data;
2755
2756 ✗ MovTref *tag = mov_add_tref_tag(sc, atom.type);
2757 ✗ if (!tag)
2758 ✗ return AVERROR(ENOMEM);
2759
2760 ✗ int ret = mov_add_tref_id(tag, avio_rb32(pb));
2761 ✗ if (ret < 0)
2762 ✗ return ret;
2763
2764 ✗ return 0;
2765 }
2766
2767 ✗ static int mov_read_vdep(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2768 {
2769 AVStream* st;
2770 MOVStreamContext* sc;
2771
2772 ✗ if (c->fc->nb_streams < 1)
2773 ✗ return 0;
2774
2775 ✗ if (atom.size > 4)
2776 ✗ av_log(c->fc, AV_LOG_WARNING, "More than one vdep reference is not supported.\n");
2777 ✗ if (atom.size < 4)
2778 ✗ return AVERROR_INVALIDDATA;
2779
2780 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
2781 ✗ sc = st->priv_data;
2782
2783 ✗ MovTref *tag = mov_add_tref_tag(sc, atom.type);
2784 ✗ if (!tag)
2785 ✗ return AVERROR(ENOMEM);
2786
2787 ✗ int ret = mov_add_tref_id(tag, avio_rb32(pb));
2788 ✗ if (ret < 0)
2789 ✗ return ret;
2790
2791 ✗ return 0;
2792 }
2793
2794 /**
2795 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2796 * but can have extradata appended at the end after the 40 bytes belonging
2797 * to the struct.
2798 */
2799 ✗ static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2800 {
2801 AVStream *st;
2802 int ret;
2803
2804 ✗ if (c->fc->nb_streams < 1)
2805 ✗ return 0;
2806 ✗ if (atom.size <= 40)
2807 ✗ return 0;
2808 ✗ st = c->fc->streams[c->fc->nb_streams-1];
2809
2810 ✗ if ((uint64_t)atom.size > (1<<30))
2811 ✗ return AVERROR_INVALIDDATA;
2812
2813 ✗ avio_skip(pb, 40);
2814 ✗ ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
2815 ✗ if (ret < 0)
2816 ✗ return ret;
2817
2818 ✗ return 0;
2819 }
2820
2821 734 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2822 {
2823 AVStream *st;
2824 MOVStreamContext *sc;
2825 unsigned int i, entries;
2826
2827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (c->trak_index < 0) {
2828 ✗ av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
2829 ✗ return 0;
2830 }
2831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (c->fc->nb_streams < 1)
2832 ✗ return 0;
2833 734 st = c->fc->streams[c->fc->nb_streams-1];
2834 734 sc = st->priv_data;
2835
2836 734 avio_r8(pb); /* version */
2837 734 avio_rb24(pb); /* flags */
2838
2839 // Clamp allocation size for `chunk_offsets` -- don't throw an error for an
2840 // invalid count since the EOF path doesn't throw either.
2841 734 entries = avio_rb32(pb);
2842 734 entries =
2843
2/2
✓ Branch 0 taken 729 times.
✓ Branch 1 taken 5 times.
734 FFMIN(entries,
2844 FFMAX(0, (atom.size - 8) /
2845 (atom.type == MKTAG('s', 't', 'c', 'o') ? 4 : 8)));
2846
2847
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 701 times.
734 if (!entries)
2848 33 return 0;
2849
2850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 701 times.
701 if (sc->chunk_offsets) {
2851 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2852 ✗ return 0;
2853 }
2854
2855 701 av_free(sc->chunk_offsets);
2856 701 sc->chunk_count = 0;
2857 701 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 701 times.
701 if (!sc->chunk_offsets)
2859 ✗ return AVERROR(ENOMEM);
2860 701 sc->chunk_count = entries;
2861
2862
2/2
✓ Branch 0 taken 697 times.
✓ Branch 1 taken 4 times.
701 if (atom.type == MKTAG('s','t','c','o'))
2863
3/4
✓ Branch 0 taken 43953 times.
✓ Branch 1 taken 697 times.
✓ Branch 2 taken 43953 times.
✗ Branch 3 not taken.
44650 for (i = 0; i < entries && !pb->eof_reached; i++)
2864 43953 sc->chunk_offsets[i] = avio_rb32(pb);
2865
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (atom.type == MKTAG('c','o','6','4'))
2866
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++) {
2867 136336 sc->chunk_offsets[i] = avio_rb64(pb);
2868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136336 times.
136336 if (sc->chunk_offsets[i] < 0) {
2869 ✗ av_log(c->fc, AV_LOG_WARNING, "Impossible chunk_offset\n");
2870 ✗ sc->chunk_offsets[i] = 0;
2871 }
2872 }
2873 else
2874 ✗ return AVERROR_INVALIDDATA;
2875
2876 701 sc->chunk_count = i;
2877
2878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 701 times.
701 if (pb->eof_reached) {
2879 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2880 ✗ return AVERROR_EOF;
2881 }
2882
2883 701 return 0;
2884 }
2885
2886 804 static int mov_codec_id(AVStream *st, uint32_t format)
2887 {
2888 804 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2889
2890
2/2
✓ Branch 0 taken 532 times.
✓ Branch 1 taken 272 times.
804 if (id <= 0 &&
2891
2/2
✓ Branch 0 taken 529 times.
✓ Branch 1 taken 3 times.
532 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2892
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 529 times.
529 (format & 0xFFFF) == 'T' + ('S' << 8)))
2893 3 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2894
2895
4/4
✓ Branch 0 taken 362 times.
✓ Branch 1 taken 442 times.
✓ Branch 2 taken 275 times.
✓ Branch 3 taken 87 times.
804 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2896 275 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2897
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 &&
2898 /* skip old ASF MPEG-4 tag */
2899
2/2
✓ Branch 0 taken 505 times.
✓ Branch 1 taken 4 times.
509 format && format != MKTAG('m','p','4','s')) {
2900 505 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2901
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 427 times.
505 if (id <= 0)
2902 78 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2903
2/2
✓ Branch 0 taken 431 times.
✓ Branch 1 taken 74 times.
505 if (id > 0)
2904 431 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2905
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 62 times.
74 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2906
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
12 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2907
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2908 62 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2909
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 6 times.
62 if (id <= 0) {
2910
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 4 times.
108 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2911
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 4 times.
108 AV_CODEC_ID_TTML : id;
2912 }
2913
2914
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 48 times.
62 if (id > 0)
2915 14 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2916 else
2917 48 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2918 }
2919 }
2920
2921 804 st->codecpar->codec_tag = format;
2922
2923 804 return id;
2924 }
2925
2926 388 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2927 AVStream *st, MOVStreamContext *sc)
2928 {
2929 388 uint8_t codec_name[32] = { 0 };
2930 int64_t stsd_start;
2931 unsigned int len;
2932 388 uint32_t id = 0;
2933
2934 /* The first 16 bytes of the video sample description are already
2935 * read in ff_mov_read_stsd_entries() */
2936 388 stsd_start = avio_tell(pb) - 16;
2937
2938
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 261 times.
388 if (c->isom) {
2939 127 avio_skip(pb, 2); /* pre_defined */
2940 127 avio_skip(pb, 2); /* reserved */
2941 127 avio_skip(pb, 12); /* pre_defined */
2942 } else {
2943 261 avio_rb16(pb); /* version */
2944 261 avio_rb16(pb); /* revision level */
2945 261 id = avio_rl32(pb); /* vendor */
2946 261 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2947 261 avio_rb32(pb); /* temporal quality */
2948 261 avio_rb32(pb); /* spatial quality */
2949 }
2950
2951 388 st->codecpar->width = avio_rb16(pb); /* width */
2952 388 st->codecpar->height = avio_rb16(pb); /* height */
2953
2954 388 avio_rb32(pb); /* horiz resolution */
2955 388 avio_rb32(pb); /* vert resolution */
2956 388 avio_rb32(pb); /* data size, always 0 */
2957 388 avio_rb16(pb); /* frames per samples */
2958
2959 388 len = avio_r8(pb); /* codec name, pascal string */
2960
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 387 times.
388 if (len > 31)
2961 1 len = 31;
2962 388 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2963
2/2
✓ Branch 0 taken 385 times.
✓ Branch 1 taken 3 times.
388 if (len < 31)
2964 385 avio_skip(pb, 31 - len);
2965
2966
2/2
✓ Branch 0 taken 295 times.
✓ Branch 1 taken 93 times.
388 if (codec_name[0])
2967 295 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2968
2969 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2970
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)) {
2971 ✗ st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2972 ✗ st->codecpar->width &= ~1;
2973 ✗ st->codecpar->height &= ~1;
2974 }
2975 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2977 ✗ !strncmp(codec_name, "Sorenson H263", 13))
2978 ✗ st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2979
2980 388 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2981
2982 388 avio_seek(pb, stsd_start, SEEK_SET);
2983
2984
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 370 times.
388 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2985 18 st->codecpar->bits_per_coded_sample &= 0x1F;
2986 18 sc->has_palette = 1;
2987 }
2988 388 }
2989
2990 295 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2991 AVStream *st, MOVStreamContext *sc)
2992 {
2993 int bits_per_sample, flags;
2994 295 uint16_t version = avio_rb16(pb);
2995 295 uint32_t id = 0;
2996 295 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2997 int channel_count;
2998
2999
2/2
✓ Branch 0 taken 205 times.
✓ Branch 1 taken 90 times.
295 if (c->isom)
3000 205 avio_skip(pb, 6); /* reserved */
3001 else {
3002 90 avio_rb16(pb); /* revision level */
3003 90 id = avio_rl32(pb); /* vendor */
3004 90 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
3005 }
3006
3007 295 channel_count = avio_rb16(pb);
3008
3009 295 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3010 295 st->codecpar->ch_layout.nb_channels = channel_count;
3011 295 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
3012 295 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
3013
3014 295 sc->audio_cid = avio_rb16(pb);
3015 295 avio_rb16(pb); /* packet size = 0 */
3016
3017 295 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
3018
3019 // Read QT version 1 fields. In version 0 these do not exist.
3020 295 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
3021
3/4
✓ Branch 0 taken 205 times.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 205 times.
✗ Branch 3 not taken.
295 if (!c->isom ||
3022
1/2
✓ Branch 0 taken 205 times.
✗ Branch 1 not taken.
205 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
3023
4/4
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 196 times.
205 (sc->stsd_version == 0 && version > 0)) {
3024
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 42 times.
94 if (version == 1) {
3025 52 sc->samples_per_frame = avio_rb32(pb);
3026 52 avio_rb32(pb); /* bytes per packet */
3027 52 sc->bytes_per_frame = avio_rb32(pb);
3028 52 avio_rb32(pb); /* bytes per sample */
3029
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 38 times.
42 } else if (version == 2) {
3030 4 avio_rb32(pb); /* sizeof struct only */
3031 4 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
3032 4 channel_count = avio_rb32(pb);
3033 4 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3034 4 st->codecpar->ch_layout.nb_channels = channel_count;
3035 4 avio_rb32(pb); /* always 0x7F000000 */
3036 4 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
3037
3038 4 flags = avio_rb32(pb); /* lpcm format specific flag */
3039 4 sc->bytes_per_frame = avio_rb32(pb);
3040 4 sc->samples_per_frame = avio_rb32(pb);
3041
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
3042 ✗ st->codecpar->codec_id =
3043 ✗ ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
3044 flags);
3045 }
3046
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)) {
3047 /* can't correctly handle variable sized packet as audio unit */
3048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 switch (st->codecpar->codec_id) {
3049 ✗ case AV_CODEC_ID_MP2:
3050 case AV_CODEC_ID_MP3:
3051 ✗ ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
3052 ✗ break;
3053 }
3054 }
3055 }
3056
3057
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 295 times.
295 if (sc->format == 0) {
3058 ✗ if (st->codecpar->bits_per_coded_sample == 8)
3059 ✗ st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
3060 ✗ else if (st->codecpar->bits_per_coded_sample == 16)
3061 ✗ st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
3062 }
3063
3064
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 248 times.
295 switch (st->codecpar->codec_id) {
3065 7 case AV_CODEC_ID_PCM_S8:
3066 case AV_CODEC_ID_PCM_U8:
3067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
3068 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
3069 7 break;
3070 24 case AV_CODEC_ID_PCM_S16LE:
3071 case AV_CODEC_ID_PCM_S16BE:
3072
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 if (st->codecpar->bits_per_coded_sample == 8)
3073 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
3074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 else if (st->codecpar->bits_per_coded_sample == 24)
3075 ✗ st->codecpar->codec_id =
3076 ✗ st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
3077 ✗ AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
3078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 else if (st->codecpar->bits_per_coded_sample == 32)
3079 ✗ st->codecpar->codec_id =
3080 ✗ st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
3081 ✗ AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
3082 24 break;
3083 /* set values for old format before stsd version 1 appeared */
3084 2 case AV_CODEC_ID_MACE3:
3085 2 sc->samples_per_frame = 6;
3086 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
3087 2 break;
3088 8 case AV_CODEC_ID_MACE6:
3089 8 sc->samples_per_frame = 6;
3090 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
3091 8 break;
3092 5 case AV_CODEC_ID_ADPCM_IMA_QT:
3093 5 sc->samples_per_frame = 64;
3094 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
3095 5 break;
3096 1 case AV_CODEC_ID_GSM:
3097 1 sc->samples_per_frame = 160;
3098 1 sc->bytes_per_frame = 33;
3099 1 break;
3100 248 default:
3101 248 break;
3102 }
3103
3104 295 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
3105
3/4
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 242 times.
✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
295 if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->ch_layout.nb_channels <= INT_MAX) {
3106 53 st->codecpar->bits_per_coded_sample = bits_per_sample;
3107 53 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
3108 }
3109 295 }
3110
3111 15 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
3112 AVStream *st, MOVStreamContext *sc,
3113 int64_t size)
3114 {
3115 // ttxt stsd contains display flags, justification, background
3116 // color, fonts, and default styles, so fake an atom to read it
3117 15 MOVAtom fake_atom = { .size = size };
3118 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
3119 // in extradata unlike stpp MP4 TTML.
3120
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
3121
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
15 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
3122 11 mov_read_glbl(c, pb, fake_atom);
3123 15 st->codecpar->width = sc->width;
3124 15 st->codecpar->height = sc->height;
3125 15 }
3126
3127 52 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
3128 AVStream *st, MOVStreamContext *sc,
3129 int64_t size)
3130 {
3131 int ret;
3132
3133
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 24 times.
52 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
3134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if ((int)size != size)
3135 ✗ return AVERROR(ENOMEM);
3136
3137 28 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
3138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
3139 ✗ return ret;
3140
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (size > 16) {
3141 28 MOVStreamContext *tmcd_ctx = st->priv_data;
3142 int val;
3143 28 val = AV_RB32(st->codecpar->extradata + 4);
3144 28 tmcd_ctx->tmcd_flags = val;
3145 28 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
3146 28 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
3147 28 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
3148
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 18 times.
28 if (size > 30) {
3149 10 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
3150 10 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
3151
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) {
3152 10 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
3153
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 &&
3154
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 st->codecpar->extradata[30] /* Don't add empty string */) {
3155 10 char *reel_name = av_malloc(str_size + 1);
3156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!reel_name)
3157 ✗ return AVERROR(ENOMEM);
3158 10 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
3159 10 reel_name[str_size] = 0; /* Add null terminator */
3160 10 av_dict_set(&st->metadata, "reel_name", reel_name,
3161 AV_DICT_DONT_STRDUP_VAL);
3162 }
3163 }
3164 }
3165 }
3166
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 } else if (st->codecpar->codec_id == AV_CODEC_ID_ITUT_T35) {
3167 2 int t35_identifier_length = avio_r8(pb);
3168
3169
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)
3170 ✗ return AVERROR_INVALIDDATA;
3171
3172 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, t35_identifier_length);
3173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
3174 ✗ return ret;
3175
3176 2 int hrsd_len = size - t35_identifier_length - 1;
3177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (hrsd_len > 0) {
3178 ✗ uint8_t *hrsd_str = av_malloc(hrsd_len + 1);
3179 ✗ if (!hrsd_str)
3180 ✗ return AVERROR(ENOMEM);
3181
3182 ✗ ret = ffio_read_size(pb, hrsd_str, hrsd_len);
3183 ✗ if (ret < 0) {
3184 ✗ av_free(hrsd_str);
3185 ✗ return ret;
3186 }
3187 ✗ if (hrsd_str[0]) {
3188 ✗ hrsd_str[hrsd_len] = 0;
3189 ✗ ret = av_dict_set(&st->metadata, "description", hrsd_str, AV_DICT_DONT_OVERWRITE);
3190 }
3191 ✗ av_free(hrsd_str);
3192 }
3193 } else {
3194 /* other codec type, just skip (rtp, mp4s ...) */
3195 22 avio_skip(pb, size);
3196 }
3197 52 return 0;
3198 }
3199
3200 734 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
3201 AVStream *st, MOVStreamContext *sc)
3202 {
3203 734 FFStream *const sti = ffstream(st);
3204
3205
2/2
✓ Branch 0 taken 295 times.
✓ Branch 1 taken 439 times.
734 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
3206
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 295 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
295 !st->codecpar->sample_rate && sc->time_scale > 1)
3207 ✗ st->codecpar->sample_rate = sc->time_scale;
3208
3209 /* special codec parameters handling */
3210
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 557 times.
734 switch (st->codecpar->codec_id) {
3211 #if CONFIG_DV_DEMUXER
3212 ✗ case AV_CODEC_ID_DVAUDIO:
3213 ✗ if (c->dv_fctx) {
3214 ✗ avpriv_request_sample(c->fc, "multiple DV audio streams");
3215 ✗ return AVERROR(ENOSYS);
3216 }
3217
3218 ✗ c->dv_fctx = avformat_alloc_context();
3219 ✗ if (!c->dv_fctx) {
3220 ✗ av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
3221 ✗ return AVERROR(ENOMEM);
3222 }
3223 ✗ c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
3224 ✗ if (!c->dv_demux) {
3225 ✗ av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
3226 ✗ return AVERROR(ENOMEM);
3227 }
3228 ✗ sc->dv_audio_container = 1;
3229 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
3230 ✗ break;
3231 #endif
3232 /* no ifdef since parameters are always those */
3233 ✗ case AV_CODEC_ID_QCELP:
3234 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
3235 ✗ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3236 // force sample rate for qcelp when not stored in mov
3237 ✗ if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
3238 ✗ st->codecpar->sample_rate = 8000;
3239 // FIXME: Why is the following needed for some files?
3240 ✗ sc->samples_per_frame = 160;
3241 ✗ if (!sc->bytes_per_frame)
3242 ✗ sc->bytes_per_frame = 35;
3243 ✗ break;
3244 ✗ case AV_CODEC_ID_AMR_NB:
3245 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
3246 ✗ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3247 /* force sample rate for amr, stsd in 3gp does not store sample rate */
3248 ✗ st->codecpar->sample_rate = 8000;
3249 ✗ break;
3250 11 case AV_CODEC_ID_AMR_WB:
3251 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
3252 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3253 11 st->codecpar->sample_rate = 16000;
3254 11 break;
3255 3 case AV_CODEC_ID_MP2:
3256 case AV_CODEC_ID_MP3:
3257 /* force type after stsd for m1a hdlr */
3258 3 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
3259 3 break;
3260 15 case AV_CODEC_ID_GSM:
3261 case AV_CODEC_ID_ADPCM_MS:
3262 case AV_CODEC_ID_ADPCM_IMA_WAV:
3263 case AV_CODEC_ID_ILBC:
3264 case AV_CODEC_ID_MACE3:
3265 case AV_CODEC_ID_MACE6:
3266 case AV_CODEC_ID_QDM2:
3267 15 st->codecpar->block_align = sc->bytes_per_frame;
3268 15 break;
3269 16 case AV_CODEC_ID_ALAC:
3270
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
3271 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
3272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
3273 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
3274 ✗ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3275 ✗ st->codecpar->ch_layout.nb_channels = channel_count;
3276 }
3277 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
3278 }
3279 16 break;
3280 14 case AV_CODEC_ID_AC3:
3281 case AV_CODEC_ID_EAC3:
3282 case AV_CODEC_ID_MPEG1VIDEO:
3283 case AV_CODEC_ID_VC1:
3284 case AV_CODEC_ID_VP8:
3285 case AV_CODEC_ID_VP9:
3286 14 sti->need_parsing = AVSTREAM_PARSE_FULL;
3287 14 break;
3288 118 case AV_CODEC_ID_PRORES_RAW:
3289 case AV_CODEC_ID_PRORES:
3290 case AV_CODEC_ID_APV:
3291 case AV_CODEC_ID_EVC:
3292 case AV_CODEC_ID_LCEVC:
3293 case AV_CODEC_ID_AV1:
3294 /* field_order detection of H264 requires parsing */
3295 case AV_CODEC_ID_H264:
3296 118 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3297 118 break;
3298 557 default:
3299 557 break;
3300 }
3301 734 return 0;
3302 }
3303
3304 751 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
3305 int codec_tag, int format,
3306 int64_t size)
3307 {
3308
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 734 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 16 times.
751 if (codec_tag &&
3309 1 (codec_tag != format &&
3310 // AVID 1:1 samples with differing data format and codec tag exist
3311
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")) &&
3312 // prores is allowed to have differing data format and codec tag
3313
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") &&
3314 // so is dv (sigh)
3315
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") &&
3316
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
3317 : codec_tag != MKTAG('j','p','e','g')))) {
3318 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3319 * export it as a separate AVStream but this needs a few changes
3320 * in the MOV demuxer, patch welcome. */
3321
3322 1 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3323 1 avio_skip(pb, size);
3324 1 return 1;
3325 }
3326
3327 750 return 0;
3328 }
3329
3330 750 static int mov_finalize_stsd_entry(MOVContext *c, AVStream *st)
3331 {
3332 int ret;
3333
3334 /* special codec parameters handling */
3335
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 660 times.
750 switch (st->codecpar->codec_id) {
3336 90 case AV_CODEC_ID_H264:
3337 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
3338
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)) {
3339 ✗ ret = ff_generate_avci_extradata(st);
3340 ✗ if (ret < 0)
3341 ✗ return ret;
3342 }
3343 90 break;
3344 660 default:
3345 660 break;
3346 }
3347
3348 750 return 0;
3349 }
3350
3351 734 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3352 {
3353 AVStream *st;
3354 MOVStreamContext *sc;
3355 int pseudo_stream_id;
3356
3357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 av_assert0 (c->fc->nb_streams >= 1);
3358 734 st = c->fc->streams[c->fc->nb_streams-1];
3359 734 sc = st->priv_data;
3360
3361 734 for (pseudo_stream_id = 0;
3362
3/4
✓ Branch 0 taken 751 times.
✓ Branch 1 taken 734 times.
✓ Branch 2 taken 751 times.
✗ Branch 3 not taken.
1485 pseudo_stream_id < entries && !pb->eof_reached;
3363 751 pseudo_stream_id++) {
3364 //Parsing Sample description table
3365 enum AVCodecID id;
3366 751 int ret, dref_id = 1;
3367 751 MOVAtom a = { AV_RL32("stsd") };
3368 751 int64_t start_pos = avio_tell(pb);
3369 751 int64_t size = avio_rb32(pb); /* size */
3370 751 uint32_t format = avio_rl32(pb); /* data format */
3371
3372
1/2
✓ Branch 0 taken 751 times.
✗ Branch 1 not taken.
751 if (size >= 16) {
3373 751 avio_rb32(pb); /* reserved */
3374 751 avio_rb16(pb); /* reserved */
3375 751 dref_id = avio_rb16(pb);
3376 ✗ } else if (size <= 7) {
3377 ✗ av_log(c->fc, AV_LOG_ERROR,
3378 "invalid size %"PRId64" in stsd\n", size);
3379 ✗ return AVERROR_INVALIDDATA;
3380 }
3381
3382
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 750 times.
751 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3383 751 size - (avio_tell(pb) - start_pos))) {
3384 1 sc->stsd_count++;
3385 1 continue;
3386 }
3387
3388
2/2
✓ Branch 0 taken 734 times.
✓ Branch 1 taken 16 times.
750 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
3389 750 sc->dref_id= dref_id;
3390 750 sc->format = format;
3391
3392 750 id = mov_codec_id(st, format);
3393
3394 750 av_log(c->fc, AV_LOG_TRACE,
3395 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3396 750 av_fourcc2str(format), st->codecpar->codec_type);
3397
3398 750 st->codecpar->codec_id = id;
3399
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 362 times.
750 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3400 388 mov_parse_stsd_video(c, pb, st, sc);
3401
2/2
✓ Branch 0 taken 295 times.
✓ Branch 1 taken 67 times.
362 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3402 295 mov_parse_stsd_audio(c, pb, st, sc);
3403
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 295 times.
295 if (st->codecpar->sample_rate < 0) {
3404 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3405 ✗ return AVERROR_INVALIDDATA;
3406 }
3407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 295 times.
295 if (st->codecpar->ch_layout.nb_channels < 0) {
3408 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3409 ✗ return AVERROR_INVALIDDATA;
3410 }
3411
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 52 times.
67 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3412 15 mov_parse_stsd_subtitle(c, pb, st, sc,
3413 15 size - (avio_tell(pb) - start_pos));
3414 } else {
3415 52 ret = mov_parse_stsd_data(c, pb, st, sc,
3416 52 size - (avio_tell(pb) - start_pos));
3417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (ret < 0)
3418 ✗ return ret;
3419 }
3420 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3421 750 a.size = size - (avio_tell(pb) - start_pos);
3422
2/2
✓ Branch 0 taken 582 times.
✓ Branch 1 taken 168 times.
750 if (a.size > 8) {
3423
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 582 times.
582 if ((ret = mov_read_default(c, pb, a)) < 0)
3424 ✗ return ret;
3425
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 167 times.
168 } else if (a.size > 0)
3426 1 avio_skip(pb, a.size);
3427
3428 750 ret = mov_finalize_stsd_entry(c, st);
3429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 750 times.
750 if (ret < 0)
3430 ✗ return ret;
3431
3432
3/4
✓ Branch 0 taken 750 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 444 times.
✓ Branch 3 taken 306 times.
750 if (sc->extradata && st->codecpar->extradata) {
3433 444 int extra_size = st->codecpar->extradata_size;
3434
3435 /* Move the current stream extradata to the stream context one. */
3436 444 sc->extradata_size[pseudo_stream_id] = extra_size;
3437 444 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3438 444 st->codecpar->extradata = NULL;
3439 444 st->codecpar->extradata_size = 0;
3440 }
3441 750 sc->stsd_count++;
3442 }
3443
3444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (pb->eof_reached) {
3445 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3446 ✗ return AVERROR_EOF;
3447 }
3448
3449 734 return 0;
3450 }
3451
3452 734 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3453 {
3454 AVStream *st;
3455 MOVStreamContext *sc;
3456 int ret, entries;
3457
3458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (c->fc->nb_streams < 1)
3459 ✗ return 0;
3460 734 st = c->fc->streams[c->fc->nb_streams - 1];
3461 734 sc = st->priv_data;
3462
3463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (sc->extradata) {
3464 ✗ av_log(c->fc, AV_LOG_ERROR,
3465 "Duplicate stsd found in this track.\n");
3466 ✗ return AVERROR_INVALIDDATA;
3467 }
3468
3469 734 sc->stsd_version = avio_r8(pb);
3470 734 avio_rb24(pb); /* flags */
3471 734 entries = avio_rb32(pb);
3472
3473 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3474
3/6
✓ Branch 0 taken 734 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 734 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 734 times.
734 if (entries <= 0 || entries > atom.size / 8 || entries > 1024) {
3475 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3476 ✗ return AVERROR_INVALIDDATA;
3477 }
3478
3479 /* Prepare space for hosting multiple extradata. */
3480 734 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (!sc->extradata)
3482 ✗ return AVERROR(ENOMEM);
3483
3484 734 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (!sc->extradata_size) {
3486 ✗ ret = AVERROR(ENOMEM);
3487 ✗ goto fail;
3488 }
3489
3490 734 ret = ff_mov_read_stsd_entries(c, pb, entries);
3491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (ret < 0)
3492 ✗ goto fail;
3493
3494 /* Restore back the primary extradata. */
3495 734 av_freep(&st->codecpar->extradata);
3496 734 st->codecpar->extradata_size = sc->extradata_size[0];
3497
2/2
✓ Branch 0 taken 429 times.
✓ Branch 1 taken 305 times.
734 if (sc->extradata_size[0]) {
3498 429 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 429 times.
429 if (!st->codecpar->extradata)
3500 ✗ return AVERROR(ENOMEM);
3501 429 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3502 }
3503
3504 734 return mov_finalize_stsd_codec(c, pb, st, sc);
3505 ✗ fail:
3506 ✗ if (sc->extradata) {
3507 int j;
3508 ✗ for (j = 0; j < sc->stsd_count; j++)
3509 ✗ av_freep(&sc->extradata[j]);
3510 }
3511
3512 ✗ sc->stsd_count = 0;
3513 ✗ av_freep(&sc->extradata);
3514 ✗ av_freep(&sc->extradata_size);
3515 ✗ return ret;
3516 }
3517
3518 734 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3519 {
3520 AVStream *st;
3521 MOVStreamContext *sc;
3522 unsigned int i, entries;
3523
3524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (c->trak_index < 0) {
3525 ✗ av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3526 ✗ return 0;
3527 }
3528
3529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (c->fc->nb_streams < 1)
3530 ✗ return 0;
3531 734 st = c->fc->streams[c->fc->nb_streams-1];
3532 734 sc = st->priv_data;
3533
3534 734 avio_r8(pb); /* version */
3535 734 avio_rb24(pb); /* flags */
3536
3537 734 entries = avio_rb32(pb);
3538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if ((uint64_t)entries * 12 + 4 > atom.size)
3539 ✗ return AVERROR_INVALIDDATA;
3540
3541 734 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3542
3543
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 702 times.
734 if (!entries)
3544 32 return 0;
3545
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 702 times.
702 if (sc->stsc_data) {
3546 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3547 ✗ return 0;
3548 }
3549 702 av_free(sc->stsc_data);
3550 702 sc->stsc_count = 0;
3551 702 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 702 times.
702 if (!sc->stsc_data)
3553 ✗ return AVERROR(ENOMEM);
3554
3555
3/4
✓ Branch 0 taken 3929 times.
✓ Branch 1 taken 702 times.
✓ Branch 2 taken 3929 times.
✗ Branch 3 not taken.
4631 for (i = 0; i < entries && !pb->eof_reached; i++) {
3556 3929 sc->stsc_data[i].first = avio_rb32(pb);
3557 3929 sc->stsc_data[i].count = avio_rb32(pb);
3558 3929 sc->stsc_data[i].id = avio_rb32(pb);
3559 }
3560
3561 702 sc->stsc_count = i;
3562
2/2
✓ Branch 0 taken 3929 times.
✓ Branch 1 taken 702 times.
4631 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3563 3929 int64_t first_min = i + 1;
3564
5/6
✓ Branch 0 taken 3227 times.
✓ Branch 1 taken 702 times.
✓ Branch 2 taken 3227 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3227 times.
✓ Branch 5 taken 702 times.
3929 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
3565
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) ||
3566
1/2
✓ Branch 0 taken 3929 times.
✗ Branch 1 not taken.
3929 sc->stsc_data[i].first < first_min ||
3567
1/2
✓ Branch 0 taken 3929 times.
✗ Branch 1 not taken.
3929 sc->stsc_data[i].count < 1 ||
3568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3929 times.
3929 sc->stsc_data[i].id < 1) {
3569 ✗ 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);
3570 ✗ if (i+1 >= sc->stsc_count) {
3571 ✗ if (sc->stsc_data[i].count == 0 && i > 0) {
3572 ✗ sc->stsc_count --;
3573 ✗ continue;
3574 }
3575 ✗ sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3576 ✗ if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3577 ✗ sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3578 ✗ sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3579 ✗ sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3580 ✗ continue;
3581 }
3582 ✗ av_assert0(sc->stsc_data[i+1].first >= 2);
3583 // We replace this entry by the next valid
3584 ✗ sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3585 ✗ sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3586 ✗ sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3587 }
3588 }
3589
3590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 702 times.
702 if (pb->eof_reached) {
3591 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3592 ✗ return AVERROR_EOF;
3593 }
3594
3595 702 return 0;
3596 }
3597
3598 354725 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3599 {
3600 354725 return index < count - 1;
3601 }
3602
3603 /* Compute the samples value for the stsc entry at the given index. */
3604 57207 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3605 {
3606 int chunk_count;
3607
3608
2/2
✓ Branch 1 taken 57009 times.
✓ Branch 2 taken 198 times.
57207 if (mov_stsc_index_valid(index, sc->stsc_count))
3609 57009 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3610 else {
3611 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3613 198 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3614 }
3615
3616 57207 return sc->stsc_data[index].count * (int64_t)chunk_count;
3617 }
3618
3619 ✗ static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3620 {
3621 AVStream *st;
3622 MOVStreamContext *sc;
3623 unsigned i, entries;
3624
3625 ✗ if (c->trak_index < 0) {
3626 ✗ av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3627 ✗ return 0;
3628 }
3629
3630 ✗ if (c->fc->nb_streams < 1)
3631 ✗ return 0;
3632 ✗ st = c->fc->streams[c->fc->nb_streams-1];
3633 ✗ sc = st->priv_data;
3634
3635 ✗ avio_rb32(pb); // version + flags
3636
3637 ✗ entries = avio_rb32(pb);
3638 ✗ if (sc->stps_data)
3639 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3640 ✗ av_free(sc->stps_data);
3641 ✗ sc->stps_count = 0;
3642 ✗ sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3643 ✗ if (!sc->stps_data)
3644 ✗ return AVERROR(ENOMEM);
3645
3646 ✗ for (i = 0; i < entries && !pb->eof_reached; i++) {
3647 ✗ sc->stps_data[i] = avio_rb32(pb);
3648 }
3649
3650 ✗ sc->stps_count = i;
3651
3652 ✗ if (pb->eof_reached) {
3653 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3654 ✗ return AVERROR_EOF;
3655 }
3656
3657 ✗ return 0;
3658 }
3659
3660 184 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3661 {
3662 AVStream *st;
3663 FFStream *sti;
3664 MOVStreamContext *sc;
3665 unsigned int i, entries;
3666
3667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
184 if (c->trak_index < 0) {
3668 ✗ av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3669 ✗ return 0;
3670 }
3671
3672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
184 if (c->fc->nb_streams < 1)
3673 ✗ return 0;
3674 184 st = c->fc->streams[c->fc->nb_streams-1];
3675 184 sti = ffstream(st);
3676 184 sc = st->priv_data;
3677
3678 184 avio_r8(pb); /* version */
3679 184 avio_rb24(pb); /* flags */
3680
3681 184 entries = avio_rb32(pb);
3682
3683 184 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3684
3685
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 170 times.
184 if (!entries) {
3686 14 sc->keyframe_absent = 1;
3687
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)
3688 ✗ sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3689 14 return 0;
3690 }
3691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170 times.
170 if (sc->keyframes)
3692 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170 times.
170 if (entries >= UINT_MAX / sizeof(int))
3694 ✗ return AVERROR_INVALIDDATA;
3695 170 av_freep(&sc->keyframes);
3696 170 sc->keyframe_count = 0;
3697 170 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170 times.
170 if (!sc->keyframes)
3699 ✗ return AVERROR(ENOMEM);
3700
3701
3/4
✓ Branch 0 taken 5770 times.
✓ Branch 1 taken 170 times.
✓ Branch 2 taken 5770 times.
✗ Branch 3 not taken.
5940 for (i = 0; i < entries && !pb->eof_reached; i++) {
3702 5770 sc->keyframes[i] = avio_rb32(pb);
3703 }
3704
3705 170 sc->keyframe_count = i;
3706
3707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170 times.
170 if (pb->eof_reached) {
3708 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3709 ✗ return AVERROR_EOF;
3710 }
3711
3712 170 return 0;
3713 }
3714
3715 734 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3716 {
3717 AVStream *st;
3718 MOVStreamContext *sc;
3719 unsigned int i, entries, sample_size, field_size, num_bytes;
3720 GetBitContext gb;
3721 unsigned char* buf;
3722 int ret;
3723
3724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (c->trak_index < 0) {
3725 ✗ av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3726 ✗ return 0;
3727 }
3728
3729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (c->fc->nb_streams < 1)
3730 ✗ return 0;
3731 734 st = c->fc->streams[c->fc->nb_streams-1];
3732 734 sc = st->priv_data;
3733
3734 734 avio_r8(pb); /* version */
3735 734 avio_rb24(pb); /* flags */
3736
3737
1/2
✓ Branch 0 taken 734 times.
✗ Branch 1 not taken.
734 if (atom.type == MKTAG('s','t','s','z')) {
3738 734 sample_size = avio_rb32(pb);
3739
2/2
✓ Branch 0 taken 688 times.
✓ Branch 1 taken 46 times.
734 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3740 688 sc->sample_size = sample_size;
3741 734 sc->stsz_sample_size = sample_size;
3742 734 field_size = 32;
3743 } else {
3744 ✗ sample_size = 0;
3745 ✗ avio_rb24(pb); /* reserved */
3746 ✗ field_size = avio_r8(pb);
3747 }
3748 734 entries = avio_rb32(pb);
3749
3750 734 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3751
3752 734 sc->sample_count = entries;
3753
2/2
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 500 times.
734 if (sample_size)
3754 234 return 0;
3755
3756
4/8
✓ Branch 0 taken 500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 500 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 500 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 500 times.
500 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
3757 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3758 ✗ return AVERROR_INVALIDDATA;
3759 }
3760
3761
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 467 times.
500 if (!entries)
3762 33 return 0;
3763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 467 times.
467 if (entries >= (INT_MAX - 4 - 8 * AV_INPUT_BUFFER_PADDING_SIZE) / field_size)
3764 ✗ return AVERROR_INVALIDDATA;
3765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 467 times.
467 if (sc->sample_sizes)
3766 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3767 467 av_free(sc->sample_sizes);
3768 467 sc->sample_count = 0;
3769 467 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 467 times.
467 if (!sc->sample_sizes)
3771 ✗ return AVERROR(ENOMEM);
3772
3773 467 num_bytes = (entries*field_size+4)>>3;
3774
3775 467 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 467 times.
467 if (!buf) {
3777 ✗ av_freep(&sc->sample_sizes);
3778 ✗ return AVERROR(ENOMEM);
3779 }
3780
3781 467 ret = ffio_read_size(pb, buf, num_bytes);
3782
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 467 times.
467 if (ret < 0) {
3783 ✗ av_freep(&sc->sample_sizes);
3784 ✗ av_free(buf);
3785 ✗ av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3786 ✗ return 0;
3787 }
3788
3789 467 init_get_bits(&gb, buf, 8*num_bytes);
3790
3791
2/2
✓ Branch 0 taken 239940 times.
✓ Branch 1 taken 467 times.
240407 for (i = 0; i < entries; i++) {
3792 239940 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3793
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 239940 times.
239940 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3794 ✗ av_free(buf);
3795 ✗ av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3796 ✗ return AVERROR_INVALIDDATA;
3797 }
3798 239940 sc->data_size += sc->sample_sizes[i];
3799 }
3800
3801 467 sc->sample_count = i;
3802
3803 467 av_free(buf);
3804
3805 467 return 0;
3806 }
3807
3808 734 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3809 {
3810 AVStream *st;
3811 MOVStreamContext *sc;
3812 unsigned int i, entries;
3813 734 int64_t duration = 0;
3814 734 int64_t total_sample_count = 0;
3815 734 int64_t current_dts = 0;
3816 734 int64_t corrected_dts = 0;
3817
3818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (c->trak_index < 0) {
3819 ✗ av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3820 ✗ return 0;
3821 }
3822
3823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (c->fc->nb_streams < 1)
3824 ✗ return 0;
3825 734 st = c->fc->streams[c->fc->nb_streams-1];
3826 734 sc = st->priv_data;
3827
3828 734 avio_r8(pb); /* version */
3829 734 avio_rb24(pb); /* flags */
3830 734 entries = avio_rb32(pb);
3831
3832 734 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3833 734 c->fc->nb_streams-1, entries);
3834
3835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (sc->stts_data)
3836 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3837 734 av_freep(&sc->stts_data);
3838 734 sc->stts_count = 0;
3839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3840 ✗ return AVERROR(ENOMEM);
3841
3842
3/4
✓ Branch 0 taken 3124 times.
✓ Branch 1 taken 734 times.
✓ Branch 2 taken 3124 times.
✗ Branch 3 not taken.
3858 for (i = 0; i < entries && !pb->eof_reached; i++) {
3843 unsigned int sample_duration;
3844 unsigned int sample_count;
3845 3124 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3846 3124 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3847 min_entries * sizeof(*sc->stts_data));
3848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3124 times.
3124 if (!stts_data) {
3849 ✗ av_freep(&sc->stts_data);
3850 ✗ sc->stts_count = 0;
3851 ✗ return AVERROR(ENOMEM);
3852 }
3853 3124 sc->stts_count = min_entries;
3854 3124 sc->stts_data = stts_data;
3855
3856 3124 sample_count = avio_rb32(pb);
3857 3124 sample_duration = avio_rb32(pb);
3858
3859 3124 sc->stts_data[i].count= sample_count;
3860 3124 sc->stts_data[i].duration= sample_duration;
3861
3862 3124 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3863 sample_count, sample_duration);
3864
3865 /* STTS sample offsets are uint32 but some files store it as int32
3866 * with negative values used to correct DTS delays.
3867 There may be abnormally large values as well. */
3868
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3123 times.
3124 if (sample_duration > c->max_stts_delta) {
3869 // assume high delta is a correction if negative when cast as int32
3870 1 int32_t delta_magnitude = (int32_t)sample_duration;
3871 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",
3872 sample_duration, i, sample_count, st->index);
3873 1 sc->stts_data[i].duration = 1;
3874
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);
3875 } else {
3876 3123 corrected_dts += sample_duration * (uint64_t)sample_count;
3877 }
3878
3879 3124 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3880
3881
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 3102 times.
3124 if (current_dts > corrected_dts) {
3882 22 int64_t drift = av_sat_sub64(current_dts, corrected_dts) / FFMAX(sample_count, 1);
3883
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;
3884 22 current_dts -= correction * (uint64_t)sample_count;
3885 22 sc->stts_data[i].duration -= correction;
3886 }
3887
3888 3124 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3889 3124 total_sample_count+=sc->stts_data[i].count;
3890 }
3891
3892 734 sc->stts_count = i;
3893
3894
2/2
✓ Branch 0 taken 701 times.
✓ Branch 1 taken 33 times.
734 if (duration > 0 &&
3895
1/2
✓ Branch 0 taken 701 times.
✗ Branch 1 not taken.
701 duration <= INT64_MAX - sc->duration_for_fps &&
3896
1/2
✓ Branch 0 taken 701 times.
✗ Branch 1 not taken.
701 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3897 701 sc->duration_for_fps += duration;
3898 701 sc->nb_frames_for_fps += total_sample_count;
3899 }
3900
3901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (pb->eof_reached) {
3902 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3903 ✗ return AVERROR_EOF;
3904 }
3905
3906 734 st->nb_frames= total_sample_count;
3907
2/2
✓ Branch 0 taken 701 times.
✓ Branch 1 taken 33 times.
734 if (duration)
3908 701 st->duration= FFMIN(st->duration, duration);
3909
3910 // All samples have zero duration. They have higher chance be chose by
3911 // mov_find_next_sample, which leads to seek again and again.
3912 //
3913 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3914 // So only mark data stream as discarded for safety.
3915
3/4
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 701 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 33 times.
734 if (!duration && sc->stts_count &&
3916 ✗ st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3917 ✗ av_log(c->fc, AV_LOG_WARNING,
3918 "All samples in data stream index:id [%d:%d] have zero "
3919 "duration, stream set to be discarded by default. Override "
3920 "using AVStream->discard or -discard for ffmpeg command.\n",
3921 st->index, sc->id);
3922 ✗ st->discard = AVDISCARD_ALL;
3923 }
3924 734 sc->track_end = duration;
3925 734 return 0;
3926 }
3927
3928 46 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3929 {
3930 AVStream *st;
3931 MOVStreamContext *sc;
3932 unsigned int i;
3933 int64_t entries;
3934
3935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (c->fc->nb_streams < 1)
3936 ✗ return 0;
3937 46 st = c->fc->streams[c->fc->nb_streams - 1];
3938 46 sc = st->priv_data;
3939
3940 46 avio_r8(pb); /* version */
3941 46 avio_rb24(pb); /* flags */
3942 46 entries = atom.size - 4;
3943
3944 46 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3945 46 c->fc->nb_streams - 1, entries);
3946
3947
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 38 times.
46 if (sc->sdtp_data)
3948 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3949 46 av_freep(&sc->sdtp_data);
3950 46 sc->sdtp_count = 0;
3951
3952
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)
3953 ✗ return AVERROR(ERANGE);
3954
3955 46 sc->sdtp_data = av_malloc(entries);
3956
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!sc->sdtp_data)
3957 ✗ return AVERROR(ENOMEM);
3958
3959
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++)
3960 3823 sc->sdtp_data[i] = avio_r8(pb);
3961 46 sc->sdtp_count = i;
3962
3963 46 return 0;
3964 }
3965
3966 14691 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3967 {
3968
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 13555 times.
14691 if (duration < 0) {
3969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3970 ✗ av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3971 ✗ duration++;
3972 }
3973 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3974 }
3975 14691 }
3976
3977 83 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3978 {
3979 AVStream *st;
3980 MOVStreamContext *sc;
3981 83 unsigned int i, entries, ctts_count = 0;
3982
3983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if (c->trak_index < 0) {
3984 ✗ av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
3985 ✗ return 0;
3986 }
3987
3988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if (c->fc->nb_streams < 1)
3989 ✗ return 0;
3990 83 st = c->fc->streams[c->fc->nb_streams-1];
3991 83 sc = st->priv_data;
3992
3993 83 avio_r8(pb); /* version */
3994 83 avio_rb24(pb); /* flags */
3995 83 entries = avio_rb32(pb);
3996
3997 83 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3998
3999
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 79 times.
83 if (!entries)
4000 4 return 0;
4001
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
4002 ✗ return AVERROR_INVALIDDATA;
4003 79 av_freep(&sc->ctts_data);
4004 79 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
4005
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (!sc->ctts_data)
4006 ✗ return AVERROR(ENOMEM);
4007
4008
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++) {
4009 MOVCtts *ctts_data;
4010 5256 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
4011 5256 const size_t requested_size =
4012 5256 min_size_needed > sc->ctts_allocated_size ?
4013
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5256 times.
5256 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
4014 min_size_needed;
4015 5256 int count = avio_rb32(pb);
4016 5256 int duration = avio_rb32(pb);
4017
4018
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5256 times.
5256 if (count <= 0) {
4019 ✗ av_log(c->fc, AV_LOG_TRACE,
4020 "ignoring CTTS entry with count=%d duration=%d\n",
4021 count, duration);
4022 ✗ continue;
4023 }
4024
4025
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5256 times.
5256 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
4026 ✗ return AVERROR(ENOMEM);
4027
4028 5256 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
4029
4030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5256 times.
5256 if (!ctts_data)
4031 ✗ return AVERROR(ENOMEM);
4032
4033 5256 sc->ctts_data = ctts_data;
4034
4035 5256 ctts_data[ctts_count].count = count;
4036 5256 ctts_data[ctts_count].offset = duration;
4037 5256 ctts_count++;
4038
4039 5256 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
4040 count, duration);
4041
4042
2/2
✓ Branch 0 taken 5110 times.
✓ Branch 1 taken 146 times.
5256 if (i+2<entries)
4043 5110 mov_update_dts_shift(sc, duration, c->fc);
4044 }
4045
4046 79 sc->ctts_count = ctts_count;
4047
4048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (pb->eof_reached) {
4049 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
4050 ✗ return AVERROR_EOF;
4051 }
4052
4053 79 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
4054
4055 79 return 0;
4056 }
4057
4058 52 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4059 {
4060 AVStream *st;
4061 MOVStreamContext *sc;
4062 uint8_t version;
4063 uint32_t grouping_type;
4064 uint32_t default_length;
4065 av_unused uint32_t default_group_description_index;
4066 uint32_t entry_count;
4067
4068
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (c->fc->nb_streams < 1)
4069 ✗ return 0;
4070 52 st = c->fc->streams[c->fc->nb_streams - 1];
4071 52 sc = st->priv_data;
4072
4073 52 version = avio_r8(pb); /* version */
4074 52 avio_rb24(pb); /* flags */
4075 52 grouping_type = avio_rl32(pb);
4076
4077 /*
4078 * This function only supports "sync" boxes, but the code is able to parse
4079 * other boxes (such as "tscl", "tsas" and "stsa")
4080 */
4081
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 5 times.
52 if (grouping_type != MKTAG('s','y','n','c'))
4082 47 return 0;
4083
4084
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
4085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
4086 5 entry_count = avio_rb32(pb);
4087
4088
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (entry_count > atom.size)
4089 ✗ return AVERROR_INVALIDDATA;
4090
4091 5 av_freep(&sc->sgpd_sync);
4092 5 sc->sgpd_sync_count = entry_count;
4093 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
4094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
4095 ✗ return AVERROR(ENOMEM);
4096
4097
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++) {
4098 8 uint32_t description_length = default_length;
4099
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)
4100 ✗ description_length = avio_rb32(pb);
4101
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
4102 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
4103 8 sc->sgpd_sync[i] = nal_unit_type;
4104 8 description_length -= 1;
4105 }
4106 8 avio_skip(pb, description_length);
4107 }
4108
4109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
4110 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
4111 ✗ return AVERROR_EOF;
4112 }
4113
4114 5 return 0;
4115 }
4116
4117 48 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4118 {
4119 AVStream *st;
4120 MOVStreamContext *sc;
4121 unsigned int i, entries;
4122 uint8_t version;
4123 uint32_t grouping_type;
4124 MOVSbgp *table, **tablep;
4125 int *table_count;
4126
4127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (c->fc->nb_streams < 1)
4128 ✗ return 0;
4129 48 st = c->fc->streams[c->fc->nb_streams-1];
4130 48 sc = st->priv_data;
4131
4132 48 version = avio_r8(pb); /* version */
4133 48 avio_rb24(pb); /* flags */
4134 48 grouping_type = avio_rl32(pb);
4135
4136
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 47 times.
48 if (grouping_type == MKTAG('r','a','p',' ')) {
4137 1 tablep = &sc->rap_group;
4138 1 table_count = &sc->rap_group_count;
4139
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 42 times.
47 } else if (grouping_type == MKTAG('s','y','n','c')) {
4140 5 tablep = &sc->sync_group;
4141 5 table_count = &sc->sync_group_count;
4142 } else {
4143 42 return 0;
4144 }
4145
4146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
4147 ✗ avio_rb32(pb); /* grouping_type_parameter */
4148
4149 6 entries = avio_rb32(pb);
4150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
4151 ✗ return 0;
4152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
4153 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
4154 6 av_freep(tablep);
4155 6 table = av_malloc_array(entries, sizeof(*table));
4156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
4157 ✗ return AVERROR(ENOMEM);
4158 6 *tablep = table;
4159
4160
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++) {
4161 32 table[i].count = avio_rb32(pb); /* sample_count */
4162 32 table[i].index = avio_rb32(pb); /* group_description_index */
4163 }
4164
4165 6 *table_count = i;
4166
4167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
4168 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
4169 ✗ return AVERROR_EOF;
4170 }
4171
4172 6 return 0;
4173 }
4174
4175 /**
4176 * Get ith edit list entry (media time, duration).
4177 */
4178 1115 static int get_edit_list_entry(MOVContext *mov,
4179 const MOVStreamContext *msc,
4180 unsigned int edit_list_index,
4181 int64_t *edit_list_media_time,
4182 int64_t *edit_list_duration,
4183 int64_t global_timescale)
4184 {
4185
2/2
✓ Branch 0 taken 543 times.
✓ Branch 1 taken 572 times.
1115 if (edit_list_index == msc->elst_count) {
4186 543 return 0;
4187 }
4188 572 *edit_list_media_time = msc->elst_data[edit_list_index].time;
4189 572 *edit_list_duration = msc->elst_data[edit_list_index].duration;
4190
4191 /* duration is in global timescale units;convert to msc timescale */
4192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 572 times.
572 if (global_timescale == 0) {
4193 ✗ avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
4194 ✗ return 0;
4195 }
4196 572 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
4197 global_timescale);
4198
4199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 572 times.
572 if (*edit_list_duration + (uint64_t)*edit_list_media_time > INT64_MAX)
4200 ✗ *edit_list_duration = 0;
4201
4202 572 return 1;
4203 }
4204
4205 /**
4206 * Find the closest previous frame to the timestamp_pts, in e_old index
4207 * entries. Searching for just any frame / just key frames can be controlled by
4208 * last argument 'flag'.
4209 * Note that if ctts_data is not NULL, we will always search for a key frame
4210 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
4211 * return the first frame of the video.
4212 *
4213 * Here the timestamp_pts is considered to be a presentation timestamp and
4214 * the timestamp of index entries are considered to be decoding timestamps.
4215 *
4216 * Returns 0 if successful in finding a frame, else returns -1.
4217 * Places the found index corresponding output arg.
4218 *
4219 * If ctts_old is not NULL, then refines the searched entry by searching
4220 * backwards from the found timestamp, to find the frame with correct PTS.
4221 *
4222 * Places the found ctts_index and ctts_sample in corresponding output args.
4223 */
4224 572 static int find_prev_closest_index(AVStream *st,
4225 AVIndexEntry *e_old,
4226 int nb_old,
4227 MOVTimeToSample *tts_data,
4228 int64_t tts_count,
4229 int64_t timestamp_pts,
4230 int flag,
4231 int64_t* index,
4232 int64_t* tts_index,
4233 int64_t* tts_sample)
4234 {
4235 572 MOVStreamContext *msc = st->priv_data;
4236 572 FFStream *const sti = ffstream(st);
4237 572 AVIndexEntry *e_keep = sti->index_entries;
4238 572 int nb_keep = sti->nb_index_entries;
4239 572 int64_t i = 0;
4240
4241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 572 times.
572 av_assert0(index);
4242
4243 // If dts_shift > 0, then all the index timestamps will have to be offset by
4244 // at least dts_shift amount to obtain PTS.
4245 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
4246
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 563 times.
572 if (msc->dts_shift > 0) {
4247 9 timestamp_pts -= msc->dts_shift;
4248 }
4249
4250 572 sti->index_entries = e_old;
4251 572 sti->nb_index_entries = nb_old;
4252 572 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
4253
4254 // Keep going backwards in the index entries until the timestamp is the same.
4255
2/2
✓ Branch 0 taken 571 times.
✓ Branch 1 taken 1 times.
572 if (*index >= 0) {
4256
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 543 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
571 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
4257 ✗ i--) {
4258 ✗ if ((flag & AVSEEK_FLAG_ANY) ||
4259 ✗ (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
4260 ✗ *index = i - 1;
4261 }
4262 }
4263 }
4264
4265 // If we have CTTS then refine the search, by searching backwards over PTS
4266 // computed by adding corresponding CTTS durations to index timestamps.
4267
4/4
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 485 times.
✓ Branch 2 taken 86 times.
✓ Branch 3 taken 1 times.
572 if (msc->ctts_count && *index >= 0) {
4268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
86 av_assert0(tts_index);
4269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
86 av_assert0(tts_sample);
4270 // Find out the ctts_index for the found frame.
4271 86 *tts_index = 0;
4272 86 *tts_sample = 0;
4273
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++) {
4274
1/2
✓ Branch 0 taken 215 times.
✗ Branch 1 not taken.
215 if (*tts_index < tts_count) {
4275 215 (*tts_sample)++;
4276
1/2
✓ Branch 0 taken 215 times.
✗ Branch 1 not taken.
215 if (tts_data[*tts_index].count == *tts_sample) {
4277 215 (*tts_index)++;
4278 215 *tts_sample = 0;
4279 }
4280 }
4281 }
4282
4283
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) {
4284 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
4285 // No need to add dts_shift to the timestamp here because timestamp_pts has already been
4286 // compensated by dts_shift above.
4287
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 &&
4288
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 5 times.
84 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
4289 79 break;
4290 }
4291
4292 18 (*index)--;
4293
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (*tts_sample == 0) {
4294 18 (*tts_index)--;
4295
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 7 times.
18 if (*tts_index >= 0)
4296 11 *tts_sample = tts_data[*tts_index].count - 1;
4297 } else {
4298 ✗ (*tts_sample)--;
4299 }
4300 }
4301 }
4302
4303 /* restore AVStream state*/
4304 572 sti->index_entries = e_keep;
4305 572 sti->nb_index_entries = nb_keep;
4306
2/2
✓ Branch 0 taken 564 times.
✓ Branch 1 taken 8 times.
572 return *index >= 0 ? 0 : -1;
4307 }
4308
4309 /**
4310 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
4311 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
4312 *
4313 * This function is similar to ff_add_index_entry in libavformat/utils.c
4314 * except that here we are always unconditionally adding an index entry to
4315 * the end, instead of searching the entries list and skipping the add if
4316 * there is an existing entry with the same timestamp.
4317 * This is needed because the mov_fix_index calls this func with the same
4318 * unincremented timestamp for successive discarded frames.
4319 */
4320 361470 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
4321 int size, int distance, int flags)
4322 {
4323 361470 FFStream *const sti = ffstream(st);
4324 AVIndexEntry *entries, *ie;
4325 361470 int64_t index = -1;
4326 361470 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
4327
4328 // Double the allocation each time, to lower memory fragmentation.
4329 // Another difference from ff_add_index_entry function.
4330 361470 const size_t requested_size =
4331 361470 min_size_needed > sti->index_entries_allocated_size ?
4332
2/2
✓ Branch 0 taken 2411 times.
✓ Branch 1 taken 359059 times.
361470 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
4333 min_size_needed;
4334
4335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 361470 times.
361470 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
4336 ✗ return -1;
4337
4338 361470 entries = av_fast_realloc(sti->index_entries,
4339 &sti->index_entries_allocated_size,
4340 requested_size);
4341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 361470 times.
361470 if (!entries)
4342 ✗ return -1;
4343
4344 361470 sti->index_entries = entries;
4345
4346 361470 index = sti->nb_index_entries++;
4347 361470 ie= &entries[index];
4348
4349 361470 ie->pos = pos;
4350 361470 ie->timestamp = timestamp;
4351 361470 ie->min_distance= distance;
4352 361470 ie->size= size;
4353 361470 ie->flags = flags;
4354 361470 return index;
4355 }
4356
4357 /**
4358 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4359 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4360 */
4361 49 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4362 int64_t* frame_duration_buffer,
4363 int frame_duration_buffer_size) {
4364 49 FFStream *const sti = ffstream(st);
4365 49 int i = 0;
4366
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);
4367
2/2
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 49 times.
243 for (i = 0; i < frame_duration_buffer_size; i++) {
4368 194 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4369 194 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4370 }
4371 49 }
4372
4373 196222 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4374 int count, int offset, unsigned int duration)
4375 {
4376 MOVTimeToSample *tts_buf_new;
4377 196222 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4378 196222 const size_t requested_size =
4379 196222 min_size_needed > *allocated_size ?
4380
2/2
✓ Branch 0 taken 1712 times.
✓ Branch 1 taken 194510 times.
196222 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4381 min_size_needed;
4382
4383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196222 times.
196222 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4384 ✗ return -1;
4385
4386 196222 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4387
4388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196222 times.
196222 if (!tts_buf_new)
4389 ✗ return -1;
4390
4391 196222 *tts_data = tts_buf_new;
4392
4393 196222 tts_buf_new[*tts_count].count = count;
4394 196222 tts_buf_new[*tts_count].offset = offset;
4395 196222 tts_buf_new[*tts_count].duration = duration;
4396
4397 196222 *tts_count = (*tts_count) + 1;
4398 196222 return 0;
4399 }
4400
4401 #define MAX_REORDER_DELAY 16
4402 744 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4403 {
4404 744 MOVStreamContext *msc = st->priv_data;
4405 744 FFStream *const sti = ffstream(st);
4406 744 int ctts_ind = 0;
4407 744 int ctts_sample = 0;
4408 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4409 744 int buf_start = 0;
4410 int j, r, num_swaps;
4411
4412
2/2
✓ Branch 0 taken 12648 times.
✓ Branch 1 taken 744 times.
13392 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4413 12648 pts_buf[j] = INT64_MIN;
4414
4415
3/4
✓ Branch 0 taken 744 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
✓ Branch 3 taken 665 times.
744 if (st->codecpar->video_delay <= 0 && msc->ctts_count &&
4416
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 28 times.
79 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4417 51 st->codecpar->video_delay = 0;
4418
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) {
4419 // Point j to the last elem of the buffer and insert the current pts there.
4420 138515 j = buf_start;
4421 138515 buf_start = (buf_start + 1);
4422
2/2
✓ Branch 0 taken 8121 times.
✓ Branch 1 taken 130394 times.
138515 if (buf_start == MAX_REORDER_DELAY + 1)
4423 8121 buf_start = 0;
4424
4425 138515 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4426
4427 // The timestamps that are already in the sorted buffer, and are greater than the
4428 // current pts, are exactly the timestamps that need to be buffered to output PTS
4429 // in correct sorted order.
4430 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4431 // can be computed as the maximum no. of swaps any particular timestamp needs to
4432 // go through, to keep this buffer in sorted order.
4433 138515 num_swaps = 0;
4434
2/2
✓ Branch 0 taken 142863 times.
✓ Branch 1 taken 4 times.
142867 while (j != buf_start) {
4435 142863 r = j - 1;
4436
2/2
✓ Branch 0 taken 8425 times.
✓ Branch 1 taken 134438 times.
142863 if (r < 0) r = MAX_REORDER_DELAY;
4437
2/2
✓ Branch 0 taken 4352 times.
✓ Branch 1 taken 138511 times.
142863 if (pts_buf[j] < pts_buf[r]) {
4438 4352 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4439 4352 ++num_swaps;
4440 } else {
4441 138511 break;
4442 }
4443 4352 j = r;
4444 }
4445 138515 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4446
4447 138515 ctts_sample++;
4448
1/2
✓ Branch 0 taken 138515 times.
✗ Branch 1 not taken.
138515 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4449 138515 ctts_ind++;
4450 138515 ctts_sample = 0;
4451 }
4452 }
4453 51 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4454 51 st->codecpar->video_delay, st->index);
4455 }
4456 744 }
4457
4458 117288 static void mov_current_sample_inc(MOVStreamContext *sc)
4459 {
4460 117288 sc->current_sample++;
4461 117288 sc->current_index++;
4462
2/2
✓ Branch 0 taken 71230 times.
✓ Branch 1 taken 46058 times.
117288 if (sc->index_ranges &&
4463
2/2
✓ Branch 0 taken 498 times.
✓ Branch 1 taken 70732 times.
71230 sc->current_index >= sc->current_index_range->end &&
4464
1/2
✓ Branch 0 taken 498 times.
✗ Branch 1 not taken.
498 sc->current_index_range->end) {
4465 498 sc->current_index_range++;
4466 498 sc->current_index = sc->current_index_range->start;
4467 }
4468 117288 }
4469
4470 ✗ static void mov_current_sample_dec(MOVStreamContext *sc)
4471 {
4472 ✗ sc->current_sample--;
4473 ✗ sc->current_index--;
4474 ✗ if (sc->index_ranges &&
4475 ✗ sc->current_index < sc->current_index_range->start &&
4476 ✗ sc->current_index_range > sc->index_ranges) {
4477 ✗ sc->current_index_range--;
4478 ✗ sc->current_index = sc->current_index_range->end - 1;
4479 }
4480 ✗ }
4481
4482 339 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4483 {
4484 int64_t range_size;
4485
4486 339 sc->current_sample = current_sample;
4487 339 sc->current_index = current_sample;
4488
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 311 times.
339 if (!sc->index_ranges) {
4489 28 return;
4490 }
4491
4492 311 for (sc->current_index_range = sc->index_ranges;
4493
1/2
✓ Branch 0 taken 311 times.
✗ Branch 1 not taken.
311 sc->current_index_range->end;
4494 ✗ sc->current_index_range++) {
4495 311 range_size = sc->current_index_range->end - sc->current_index_range->start;
4496
1/2
✓ Branch 0 taken 311 times.
✗ Branch 1 not taken.
311 if (range_size > current_sample) {
4497 311 sc->current_index = sc->current_index_range->start + current_sample;
4498 311 break;
4499 }
4500 ✗ current_sample -= range_size;
4501 }
4502 }
4503
4504 /**
4505 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4506 * which are needed to decode them) that fall in the edit list time ranges.
4507 * Also fixes the timestamps of the index entries to match the timeline
4508 * specified the edit lists.
4509 */
4510 744 static void mov_fix_index(MOVContext *mov, AVStream *st)
4511 {
4512 744 MOVStreamContext *msc = st->priv_data;
4513 744 FFStream *const sti = ffstream(st);
4514 744 AVIndexEntry *e_old = sti->index_entries;
4515 744 int nb_old = sti->nb_index_entries;
4516 744 const AVIndexEntry *e_old_end = e_old + nb_old;
4517 744 const AVIndexEntry *current = NULL;
4518 744 MOVTimeToSample *tts_data_old = msc->tts_data;
4519 744 int64_t tts_index_old = 0;
4520 744 int64_t tts_sample_old = 0;
4521 744 int64_t tts_count_old = msc->tts_count;
4522 744 int64_t edit_list_media_time = 0;
4523 744 int64_t edit_list_duration = 0;
4524 744 int64_t frame_duration = 0;
4525 744 int64_t edit_list_dts_counter = 0;
4526 744 int64_t edit_list_dts_entry_end = 0;
4527 744 int64_t edit_list_start_tts_sample = 0;
4528 int64_t curr_cts;
4529 744 int64_t curr_ctts = 0;
4530 744 int64_t empty_edits_sum_duration = 0;
4531 744 int64_t edit_list_index = 0;
4532 int64_t index;
4533 int flags;
4534 744 int64_t start_dts = 0;
4535 744 int64_t edit_list_start_encountered = 0;
4536 744 int64_t search_timestamp = 0;
4537 744 int64_t* frame_duration_buffer = NULL;
4538 744 int num_discarded_begin = 0;
4539 744 int first_non_zero_audio_edit = -1;
4540 744 int packet_skip_samples = 0;
4541 744 MOVIndexRange *current_index_range = NULL;
4542 744 int found_keyframe_after_edit = 0;
4543 744 int found_non_empty_edit = 0;
4544
4545
4/6
✓ Branch 0 taken 543 times.
✓ Branch 1 taken 201 times.
✓ Branch 2 taken 543 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 543 times.
744 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
4546 201 return;
4547 }
4548
4549 // allocate the index ranges array
4550 543 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4551 sizeof(msc->index_ranges[0]));
4552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 543 times.
543 if (!msc->index_ranges) {
4553 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4554 ✗ return;
4555 }
4556 543 msc->current_index_range = msc->index_ranges;
4557
4558 // Clean AVStream from traces of old index
4559 543 sti->index_entries = NULL;
4560 543 sti->index_entries_allocated_size = 0;
4561 543 sti->nb_index_entries = 0;
4562
4563 // Clean time to sample fields of MOVStreamContext
4564 543 msc->tts_data = NULL;
4565 543 msc->tts_count = 0;
4566 543 msc->tts_index = 0;
4567 543 msc->tts_sample = 0;
4568 543 msc->tts_allocated_size = 0;
4569
4570 // Reinitialize min_corrected_pts so that it can be computed again.
4571 543 msc->min_corrected_pts = -1;
4572
4573 // If the dts_shift is positive (in case of negative ctts values in mov),
4574 // then negate the DTS by dts_shift
4575
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 534 times.
543 if (msc->dts_shift > 0) {
4576 9 edit_list_dts_entry_end -= msc->dts_shift;
4577 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4578 }
4579
4580 543 start_dts = edit_list_dts_entry_end;
4581
4582
2/2
✓ Branch 0 taken 572 times.
✓ Branch 1 taken 543 times.
1658 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
4583 1115 &edit_list_duration, mov->time_scale)) {
4584 572 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4585 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4586 572 edit_list_index++;
4587 572 edit_list_dts_counter = edit_list_dts_entry_end;
4588 572 edit_list_dts_entry_end = av_sat_add64(edit_list_dts_entry_end, edit_list_duration);
4589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 572 times.
572 if (edit_list_dts_entry_end == INT64_MAX) {
4590 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot calculate dts entry length with duration %"PRId64"\n",
4591 edit_list_duration);
4592 ✗ break;
4593 }
4594 572 num_discarded_begin = 0;
4595
4/4
✓ Branch 0 taken 547 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 543 times.
572 if (!found_non_empty_edit && edit_list_media_time == -1) {
4596 4 empty_edits_sum_duration += edit_list_duration;
4597 4 continue;
4598 }
4599 568 found_non_empty_edit = 1;
4600
4601 // If we encounter a non-negative edit list reset the skip_samples/initial_padding fields and set them
4602 // according to the edit list below.
4603
2/2
✓ Branch 0 taken 165 times.
✓ Branch 1 taken 403 times.
568 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4604
1/2
✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
165 if (first_non_zero_audio_edit < 0) {
4605 165 first_non_zero_audio_edit = 1;
4606 } else {
4607 ✗ first_non_zero_audio_edit = 0;
4608 }
4609
4610
1/2
✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
165 if (first_non_zero_audio_edit > 0)
4611 165 sti->skip_samples = st->codecpar->initial_padding = 0;
4612 }
4613
4614 // While reordering frame index according to edit list we must handle properly
4615 // the scenario when edit list entry starts from none key frame.
4616 // We find closest previous key frame and preserve it and consequent frames in index.
4617 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4618 568 search_timestamp = edit_list_media_time;
4619
2/2
✓ Branch 0 taken 165 times.
✓ Branch 1 taken 403 times.
568 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4620 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4621 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4622 // edit_list_media_time to cover the decoder delay.
4623 165 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
4624 }
4625
4626
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 564 times.
568 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, 0,
4627 &index, &tts_index_old, &tts_sample_old) < 0) {
4628 4 av_log(mov->fc, AV_LOG_WARNING,
4629 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4630 st->index, edit_list_index, search_timestamp);
4631
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,
4632 &index, &tts_index_old, &tts_sample_old) < 0) {
4633 4 av_log(mov->fc, AV_LOG_WARNING,
4634 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4635 st->index, edit_list_index, search_timestamp);
4636 4 index = 0;
4637 4 tts_index_old = 0;
4638 4 tts_sample_old = 0;
4639 }
4640 }
4641 568 current = e_old + index;
4642 568 edit_list_start_tts_sample = tts_sample_old;
4643
4644 // Iterate over index and arrange it according to edit list
4645 568 edit_list_start_encountered = 0;
4646 568 found_keyframe_after_edit = 0;
4647
2/2
✓ Branch 0 taken 361470 times.
✓ Branch 1 taken 144 times.
361614 for (; current < e_old_end; current++, index++) {
4648 // check if frame outside edit list mark it for discard
4649 722940 frame_duration = (current + 1 < e_old_end) ?
4650
2/2
✓ Branch 0 taken 360935 times.
✓ Branch 1 taken 535 times.
361470 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4651
4652 361470 flags = current->flags;
4653
4654 // frames (pts) before or after edit list
4655 361470 curr_cts = current->timestamp + msc->dts_shift;
4656 361470 curr_ctts = 0;
4657
4658
4/4
✓ Branch 0 taken 196234 times.
✓ Branch 1 taken 165236 times.
✓ Branch 2 taken 196222 times.
✓ Branch 3 taken 12 times.
361470 if (tts_data_old && tts_index_old < tts_count_old) {
4659 196222 curr_ctts = tts_data_old[tts_index_old].offset;
4660 196222 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4661 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4662 196222 curr_cts += curr_ctts;
4663 196222 tts_sample_old++;
4664
1/2
✓ Branch 0 taken 196222 times.
✗ Branch 1 not taken.
196222 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196222 times.
196222 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4666 &msc->tts_allocated_size,
4667 196222 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4668 196222 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4669 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4670 tts_index_old,
4671 ✗ tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4672 ✗ tts_data_old[tts_index_old].offset);
4673 ✗ break;
4674 }
4675 196222 tts_index_old++;
4676 196222 tts_sample_old = 0;
4677 196222 edit_list_start_tts_sample = 0;
4678 }
4679 }
4680
4681
4/4
✓ Branch 0 taken 361247 times.
✓ Branch 1 taken 223 times.
✓ Branch 2 taken 158 times.
✓ Branch 3 taken 361089 times.
361470 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
4682
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 &&
4683
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 &&
4684 first_non_zero_audio_edit > 0) {
4685 25 packet_skip_samples = edit_list_media_time - curr_cts;
4686 25 sti->skip_samples += packet_skip_samples;
4687
4688 // Shift the index entry timestamp by packet_skip_samples to be correct.
4689 25 edit_list_dts_counter -= packet_skip_samples;
4690
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 if (edit_list_start_encountered == 0) {
4691 25 edit_list_start_encountered = 1;
4692 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4693 // discarded packets.
4694
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 10 times.
25 if (frame_duration_buffer) {
4695 15 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4696 frame_duration_buffer, num_discarded_begin);
4697 15 av_freep(&frame_duration_buffer);
4698 }
4699 }
4700
4701 25 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4702 } else {
4703 356 flags |= AVINDEX_DISCARD_FRAME;
4704 356 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4705
4706
2/2
✓ Branch 0 taken 196 times.
✓ Branch 1 taken 160 times.
356 if (edit_list_start_encountered == 0) {
4707 196 num_discarded_begin++;
4708
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 196 times.
196 if (av_reallocp_array(&frame_duration_buffer, num_discarded_begin,
4709 sizeof(*frame_duration_buffer)) < 0) {
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 542 times.
✓ Branch 1 taken 360547 times.
361089 if (msc->min_corrected_pts < 0) {
4724 542 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4725 } else {
4726 360547 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 541 times.
✓ Branch 1 taken 360548 times.
361089 if (edit_list_start_encountered == 0) {
4729 541 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 507 times.
541 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 361470 times.
361470 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
4741 361470 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 360927 times.
✓ Branch 1 taken 543 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 360904 times.
361470 if (!current_index_range || index != current_index_range->end) {
4748 566 current_index_range = current_index_range ? current_index_range + 1
4749
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 543 times.
566 : msc->index_ranges;
4750 566 current_index_range->start = index;
4751 }
4752 361470 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 361274 times.
✓ Branch 1 taken 196 times.
361470 if (edit_list_start_encountered > 0) {
4756 361274 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 763 times.
✓ Branch 1 taken 360707 times.
361470 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
4761
4/4
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 443 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 317 times.
763 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
4762
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 413 times.
446 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 424 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 543 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 216 times.
543 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 543 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 543 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4804 543 st->codecpar->initial_padding = sti->skip_samples;
4805
4806 // Free the old index and the old CTTS structures
4807 543 av_free(e_old);
4808 543 av_free(tts_data_old);
4809 543 av_freep(&frame_duration_buffer);
4810
4811 // Null terminate the index ranges array
4812 543 current_index_range = current_index_range ? current_index_range + 1
4813
1/2
✓ Branch 0 taken 543 times.
✗ Branch 1 not taken.
543 : msc->index_ranges;
4814 543 current_index_range->start = 0;
4815 543 current_index_range->end = 0;
4816 543 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 777 static int build_open_gop_key_points(AVStream *st)
4828 {
4829 int k;
4830 777 int sample_id = 0;
4831 uint32_t cra_index;
4832 777 MOVStreamContext *sc = st->priv_data;
4833
4834
4/4
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 708 times.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 5 times.
777 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count)
4835 772 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 744 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4898 {
4899 744 MOVStreamContext *sc = st->priv_data;
4900
3/4
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 665 times.
✓ Branch 2 taken 79 times.
✗ Branch 3 not taken.
744 int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS);
4901
3/4
✓ Branch 0 taken 744 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 673 times.
✓ Branch 3 taken 71 times.
744 int stts = sc->stts_data && (flags & MOV_MERGE_STTS);
4902 744 int idx = 0;
4903
4904
3/4
✓ Branch 0 taken 665 times.
✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 665 times.
744 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 744 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 744 times.
744 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 665 times.
744 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 665 sc->ctts_count = 0;
4929 744 av_freep(&sc->ctts_data);
4930 744 sc->ctts_allocated_size = 0;
4931
4932 744 idx = 0;
4933
2/2
✓ Branch 0 taken 673 times.
✓ Branch 1 taken 71 times.
744 if (stts) {
4934 673 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4935 673 sc->sample_count * sizeof(*sc->tts_data));
4936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (!tts_data)
4937 ✗ return -1;
4938
4939
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 79 times.
673 if (!sc->tts_data)
4940 594 memset(tts_data, 0, sc->tts_allocated_size);
4941 673 sc->tts_data = tts_data;
4942
4943
2/2
✓ Branch 0 taken 3096 times.
✓ Branch 1 taken 673 times.
3769 for (int i = 0; i < sc->stts_count &&
4944
1/2
✓ Branch 0 taken 3096 times.
✗ Branch 1 not taken.
6192 idx < sc->sample_count; i++)
4945
2/2
✓ Branch 0 taken 249263 times.
✓ Branch 1 taken 3096 times.
252359 for (int j = 0; j < sc->stts_data[i].count &&
4946
1/2
✓ Branch 0 taken 249263 times.
✗ Branch 1 not taken.
249263 idx < sc->sample_count; j++) {
4947 249263 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4948 249263 sc->tts_data[idx++].count = 1;
4949 }
4950
4951 673 sc->tts_count = FFMAX(sc->tts_count, idx);
4952 } else
4953 71 sc->stts_count = 0;
4954 744 av_freep(&sc->stts_data);
4955 744 sc->stts_allocated_size = 0;
4956
4957 744 return 0;
4958 }
4959
4960 777 static void mov_build_index(MOVContext *mov, AVStream *st)
4961 {
4962 777 MOVStreamContext *sc = st->priv_data;
4963 777 FFStream *const sti = ffstream(st);
4964 int64_t current_offset;
4965 777 int64_t current_dts = 0;
4966 777 unsigned int stts_index = 0;
4967 777 unsigned int stsc_index = 0;
4968 777 unsigned int stss_index = 0;
4969 777 unsigned int stps_index = 0;
4970 unsigned int i, j;
4971 777 uint64_t stream_size = 0;
4972
4973 777 int ret = build_open_gop_key_points(st);
4974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 777 times.
777 if (ret < 0)
4975 ✗ return;
4976
4977
2/2
✓ Branch 0 taken 546 times.
✓ Branch 1 taken 231 times.
777 if (sc->elst_count) {
4978 546 int i, edit_start_index = 0, multiple_edits = 0;
4979 546 int64_t empty_duration = 0; // empty duration of the first edit list entry
4980 546 int64_t start_time = 0; // start time of the media
4981
4982
2/2
✓ Branch 0 taken 575 times.
✓ Branch 1 taken 546 times.
1121 for (i = 0; i < sc->elst_count; i++) {
4983 575 const MOVElst *e = &sc->elst_data[i];
4984
4/4
✓ Branch 0 taken 546 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 542 times.
575 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 546 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 546 times.
✗ Branch 3 not taken.
571 } else if (i == edit_start_index && e->time >= 0) {
4990 546 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 539 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
546 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 542 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 116 times.
✓ Branch 3 taken 426 times.
✓ Branch 4 taken 120 times.
✗ Branch 5 not taken.
546 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 539 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 536 times.
546 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 295 times.
✓ Branch 1 taken 482 times.
777 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
5028
5/6
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 243 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 172 times.
✓ Branch 5 taken 71 times.
968 sc->stts_count == 1 && sc->stts_data && sc->stts_data[0].duration == 1)) {
5029 706 unsigned int current_sample = 0;
5030 706 unsigned int stts_sample = 0;
5031 unsigned int sample_size;
5032 706 unsigned int distance = 0;
5033 706 unsigned int rap_group_index = 0;
5034 706 unsigned int rap_group_sample = 0;
5035
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 705 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
706 int rap_group_present = sc->rap_group_count && sc->rap_group;
5036
4/8
✓ Branch 0 taken 170 times.
✓ Branch 1 taken 536 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 170 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 536 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
706 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 706 times.
706 av_assert0(sc->dts_shift >= 0);
5039
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (current_dts < INT64_MIN + sc->dts_shift)
5040 ✗ return;
5041 706 current_dts -= sc->dts_shift;
5042
4/6
✓ Branch 0 taken 673 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 673 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 673 times.
706 if (!sc->sample_count || sti->nb_index_entries || sc->tts_count)
5043 33 return;
5044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 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 673 times.
673 if (av_reallocp_array(&sti->index_entries,
5047 673 sti->nb_index_entries + sc->sample_count,
5048 sizeof(*sti->index_entries)) < 0) {
5049 ✗ sti->nb_index_entries = 0;
5050 ✗ return;
5051 }
5052 673 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
5053
5054 673 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
5055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (ret < 0)
5056 ✗ return;
5057
5058
2/2
✓ Branch 0 taken 174769 times.
✓ Branch 1 taken 673 times.
175442 for (i = 0; i < sc->chunk_count; i++) {
5059
2/2
✓ Branch 0 taken 174096 times.
✓ Branch 1 taken 673 times.
174769 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
5060 174769 current_offset = sc->chunk_offsets[i];
5061
2/2
✓ Branch 1 taken 8723 times.
✓ Branch 2 taken 168602 times.
177325 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 174769 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7422 times.
✓ Branch 3 taken 167347 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7422 times.
174769 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 167347 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7422 times.
174769 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 249263 times.
✓ Branch 1 taken 174769 times.
424032 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
5076 249263 int keyframe = 0;
5077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249263 times.
249263 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 239552 times.
✓ Branch 1 taken 9711 times.
✓ Branch 2 taken 153399 times.
✓ Branch 3 taken 86153 times.
✓ Branch 4 taken 5770 times.
✓ Branch 5 taken 147629 times.
249263 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
5083 91923 keyframe = 1;
5084
2/2
✓ Branch 0 taken 5600 times.
✓ Branch 1 taken 86323 times.
91923 if (stss_index + 1 < sc->keyframe_count)
5085 5600 stss_index++;
5086
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 157340 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
157340 } 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 249075 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
249263 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 239552 times.
249263 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 100762 times.
✓ Branch 1 taken 148501 times.
249263 if (keyframe)
5105 100762 distance = 0;
5106
2/2
✓ Branch 0 taken 9323 times.
✓ Branch 1 taken 239940 times.
249263 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 249263 times.
249263 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 249166 times.
✓ Branch 1 taken 97 times.
249263 if (sc->pseudo_stream_id == -1 ||
5115
2/2
✓ Branch 0 taken 249164 times.
✓ Branch 1 taken 2 times.
249166 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
5116 AVIndexEntry *e;
5117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249261 times.
249261 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 249261 e = &sti->index_entries[sti->nb_index_entries++];
5122 249261 e->pos = current_offset;
5123 249261 e->timestamp = current_dts;
5124 249261 e->size = sample_size;
5125 249261 e->min_distance = distance;
5126 249261 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
5127 249261 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 92941 times.
✓ Branch 2 taken 11687 times.
✓ Branch 3 taken 144633 times.
249261 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 249263 current_offset += sample_size;
5135 249263 stream_size += sample_size;
5136
5137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249263 times.
249263 if (current_dts > INT64_MAX - sc->tts_data[stts_index].duration)
5138 ✗ return;
5139 249263 current_dts += sc->tts_data[stts_index].duration;
5140
5141 249263 distance++;
5142 249263 stts_sample++;
5143 249263 current_sample++;
5144
3/4
✓ Branch 0 taken 248590 times.
✓ Branch 1 taken 673 times.
✓ Branch 2 taken 248590 times.
✗ Branch 3 not taken.
249263 if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) {
5145 248590 stts_sample = 0;
5146 248590 stts_index++;
5147 }
5148 }
5149 }
5150
2/2
✓ Branch 0 taken 630 times.
✓ Branch 1 taken 43 times.
673 if (st->duration > 0)
5151 630 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 744 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 744 times.
✗ Branch 3 not taken.
744 if (!mov->ignore_editlist && mov->advanced_editlist) {
5261 // Fix index according to edit lists.
5262 744 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 543 times.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 130 times.
✓ Branch 4 taken 71 times.
✗ Branch 5 not taken.
744 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 744 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 734 static void mov_update_sample_durations(MOVContext *mov, AVStream *st)
5295 {
5296 734 MOVStreamContext *sc = st->priv_data;
5297 734 FFStream *const sti = ffstream(st);
5298 734 MOVPresentationSample *samples = NULL;
5299 734 MOVTimeToSample *tts_data = NULL;
5300 734 unsigned int tts_index = 0, tts_sample = 0;
5301 734 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 361 times.
734 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 722 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 1579 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5481 {
5482
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1563 times.
1579 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 1579 }
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 777 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5537 {
5538
4/6
✓ Branch 0 taken 744 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 744 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 744 times.
✗ Branch 5 not taken.
777 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5539
3/4
✓ Branch 0 taken 467 times.
✓ Branch 1 taken 277 times.
✓ Branch 2 taken 467 times.
✗ Branch 3 not taken.
744 (!sc->sample_size && !sc->sample_count))) ||
5540
3/4
✓ Branch 0 taken 744 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 744 times.
✗ Branch 3 not taken.
777 (sc->sample_count && (!sc->chunk_count ||
5541
3/4
✓ Branch 0 taken 467 times.
✓ Branch 1 taken 277 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 467 times.
744 (!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 744 times.
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 744 times.
777 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 777 return 0;
5553 }
5554
5555 734 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5556 {
5557 AVStream *st;
5558 MOVStreamContext *sc;
5559 int ret;
5560
5561 734 st = avformat_new_stream(c->fc, NULL);
5562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (!st) return AVERROR(ENOMEM);
5563 734 st->id = -1;
5564 734 sc = av_mallocz(sizeof(MOVStreamContext));
5565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (!sc) return AVERROR(ENOMEM);
5566
5567 734 st->priv_data = sc;
5568 734 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5569 734 sc->ffindex = st->index;
5570 734 c->trak_index = st->index;
5571 734 sc->refcount = 1;
5572
5573
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 734 times.
734 if ((ret = mov_read_default(c, pb, atom)) < 0)
5574 ✗ return ret;
5575
5576 734 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 33 times.
✓ Branch 1 taken 701 times.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 32 times.
734 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 734 ret = sanity_checks(c->fc, sc, st->index);
5586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 if (ret)
5587 ✗ return ret > 1 ? AVERROR_INVALIDDATA : 0;
5588
5589 734 fix_timescale(c, sc);
5590
5591 734 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 33 times.
✓ Branch 1 taken 701 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 9 times.
734 if (!sc->stts_count && c->advanced_editlist) {
5599
5600 24 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5601 "MP4. disabling.\n");
5602 24 c->advanced_editlist = 0;
5603 24 c->advanced_editlist_autodisabled = 1;
5604 }
5605
5606 734 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 734 mov_update_sample_durations(c, st);
5612
5613 #if CONFIG_IAMFDEC
5614
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 722 times.
734 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 733 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 733 times.
734 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 734 sc->pb = c->fc->pb;
5641 734 sc->pb_is_copied = 1;
5642 }
5643
5644
2/2
✓ Branch 0 taken 373 times.
✓ Branch 1 taken 361 times.
734 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 704 times.
734 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 731 times.
734 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 734 av_freep(&sc->chunk_offsets);
5700 734 av_freep(&sc->sample_sizes);
5701 734 av_freep(&sc->keyframes);
5702 734 av_freep(&sc->stps_data);
5703 734 av_freep(&sc->elst_data);
5704 734 av_freep(&sc->rap_group);
5705 734 av_freep(&sc->sync_group);
5706 734 av_freep(&sc->sgpd_sync);
5707
5708 734 return 0;
5709 }
5710
5711 196 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5712 {
5713 int ret;
5714 196 c->itunes_metadata = 1;
5715 196 ret = mov_read_default(c, pb, atom);
5716 196 c->itunes_metadata = 0;
5717 196 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 221 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5933 {
5934
1/2
✓ Branch 0 taken 643 times.
✗ Branch 1 not taken.
643 while (atom.size > 8) {
5935 uint32_t tag;
5936
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 643 times.
643 if (avio_feof(pb))
5937 ✗ return AVERROR_EOF;
5938 643 tag = avio_rl32(pb);
5939 643 atom.size -= 4;
5940
2/2
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 422 times.
643 if (tag == MKTAG('h','d','l','r')) {
5941 221 avio_seek(pb, -8, SEEK_CUR);
5942 221 atom.size += 8;
5943 221 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 734 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 734 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 734 times.
734 if (c->fc->nb_streams < 1)
5971 ✗ return 0;
5972 734 st = c->fc->streams[c->fc->nb_streams-1];
5973 734 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 734 times.
734 if (st->id != -1)
5978 ✗ return AVERROR_INVALIDDATA;
5979
5980 734 version = avio_r8(pb);
5981 734 flags = avio_rb24(pb);
5982 734 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5983
5984
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 721 times.
734 if (version == 1) {
5985 13 avio_rb64(pb);
5986 13 avio_rb64(pb);
5987 } else {
5988 721 avio_rb32(pb); /* creation time */
5989 721 avio_rb32(pb); /* modification time */
5990 }
5991 734 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5992 734 sc->id = st->id;
5993 734 avio_rb32(pb); /* reserved */
5994
5995 /* highlevel (considering edits) duration in movie timebase */
5996
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 721 times.
734 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5997 734 avio_rb32(pb); /* reserved */
5998 734 avio_rb32(pb); /* reserved */
5999
6000 734 avio_rb16(pb); /* layer */
6001 734 avio_rb16(pb); /* alternate group */
6002 734 avio_rb16(pb); /* volume */
6003 734 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 2202 times.
✓ Branch 1 taken 734 times.
2936 for (i = 0; i < 3; i++) {
6010 2202 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
6011 2202 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
6012 2202 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
6013 }
6014
6015 734 width = avio_rb32(pb); // 16.16 fixed point track width
6016 734 height = avio_rb32(pb); // 16.16 fixed point track height
6017 734 sc->width = width >> 16;
6018 734 sc->height = height >> 16;
6019
6020 // apply the moov display matrix (after the tkhd one)
6021
2/2
✓ Branch 0 taken 2202 times.
✓ Branch 1 taken 734 times.
2936 for (i = 0; i < 3; i++) {
6022 2202 const int sh[3] = { 16, 16, 30 };
6023
2/2
✓ Branch 0 taken 6606 times.
✓ Branch 1 taken 2202 times.
8808 for (j = 0; j < 3; j++) {
6024
2/2
✓ Branch 0 taken 19818 times.
✓ Branch 1 taken 6606 times.
26424 for (e = 0; e < 3; e++) {
6025 19818 res_display_matrix[i][j] +=
6026 19818 ((int64_t) display_matrix[i][e] *
6027 19818 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 725 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 725 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 725 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 725 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 725 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 725 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 725 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 725 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 725 times.
734 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 342 times.
✓ Branch 2 taken 392 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 384 times.
734 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 734 return 0;
6061 }
6062
6063 504 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6064 {
6065 504 MOVFragment *frag = &c->fragment;
6066 504 MOVTrackExt *trex = NULL;
6067 int flags, track_id, i;
6068 MOVFragmentStreamInfo * frag_stream_info;
6069
6070 504 avio_r8(pb); /* version */
6071 504 flags = avio_rb24(pb);
6072
6073 504 track_id = avio_rb32(pb);
6074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
504 if (!track_id)
6075 ✗ return AVERROR_INVALIDDATA;
6076
1/2
✓ Branch 0 taken 563 times.
✗ Branch 1 not taken.
563 for (i = 0; i < c->trex_count; i++)
6077
2/2
✓ Branch 0 taken 504 times.
✓ Branch 1 taken 59 times.
563 if (c->trex_data[i].track_id == track_id) {
6078 504 trex = &c->trex_data[i];
6079 504 break;
6080 }
6081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
504 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 504 c->fragment.found_tfhd = 1;
6086 504 frag->track_id = track_id;
6087 504 set_frag_stream(&c->frag_index, track_id);
6088
6089 1008 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
6090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
1008 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
6091
2/2
✓ Branch 0 taken 431 times.
✓ Branch 1 taken 73 times.
504 frag->moof_offset : frag->implicit_offset;
6092
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 440 times.
504 frag->stsd_id = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id;
6093
6094 1008 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
6095
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 435 times.
504 avio_rb32(pb) : trex->duration;
6096 1008 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
6097
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 443 times.
504 avio_rb32(pb) : trex->size;
6098 1008 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
6099
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 369 times.
504 avio_rb32(pb) : trex->flags;
6100 504 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
6101
6102 504 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6103
1/2
✓ Branch 0 taken 504 times.
✗ Branch 1 not taken.
504 if (frag_stream_info) {
6104 504 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
6105 504 frag_stream_info->stsd_id = frag->stsd_id;
6106 }
6107 504 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 32 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 32 times.
32 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 32 times.
32 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 32 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
6145
6146 32 trex = &c->trex_data[c->trex_count++];
6147 32 avio_r8(pb); /* version */
6148 32 avio_rb24(pb); /* flags */
6149 32 trex->track_id = avio_rb32(pb);
6150 32 trex->stsd_id = avio_rb32(pb);
6151 32 trex->duration = avio_rb32(pb);
6152 32 trex->size = avio_rb32(pb);
6153 32 trex->flags = avio_rb32(pb);
6154 32 return 0;
6155 }
6156
6157 431 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6158 {
6159 431 MOVFragment *frag = &c->fragment;
6160 431 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 458 times.
✗ Branch 1 not taken.
458 for (i = 0; i < c->fc->nb_streams; i++) {
6167 458 sc = c->fc->streams[i]->priv_data;
6168
2/2
✓ Branch 0 taken 431 times.
✓ Branch 1 taken 27 times.
458 if (sc->id == frag->track_id) {
6169 431 st = c->fc->streams[i];
6170 431 break;
6171 }
6172 }
6173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 431 times.
431 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 431 sc = st->priv_data;
6178
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 427 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
431 if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1)
6179 ✗ return 0;
6180 431 version = avio_r8(pb);
6181 431 avio_rb24(pb); /* flags */
6182
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 373 times.
431 if (version) {
6183 58 base_media_decode_time = avio_rb64(pb);
6184 } else {
6185 373 base_media_decode_time = avio_rb32(pb);
6186 }
6187
6188 431 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6189
1/2
✓ Branch 0 taken 431 times.
✗ Branch 1 not taken.
431 if (frag_stream_info)
6190 431 frag_stream_info->tfdt_dts = base_media_decode_time;
6191 431 sc->track_end = base_media_decode_time;
6192
6193 431 return 0;
6194 }
6195
6196 504 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6197 {
6198 504 MOVFragment *frag = &c->fragment;
6199 504 AVStream *st = NULL;
6200 504 FFStream *sti = NULL;
6201 MOVStreamContext *sc;
6202 MOVTimeToSample *tts_data;
6203 uint64_t offset;
6204 504 int64_t dts, pts = AV_NOPTS_VALUE;
6205 504 int data_offset = 0;
6206 504 unsigned entries, first_sample_flags = frag->flags;
6207 int flags, distance, i;
6208 504 int64_t prev_dts = AV_NOPTS_VALUE;
6209 504 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 504 times.
504 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 563 times.
✗ Branch 1 not taken.
563 for (i = 0; i < c->fc->nb_streams; i++) {
6221 563 sc = c->fc->streams[i]->priv_data;
6222
2/2
✓ Branch 0 taken 504 times.
✓ Branch 1 taken 59 times.
563 if (sc->id == frag->track_id) {
6223 504 st = c->fc->streams[i];
6224 504 sti = ffstream(st);
6225 504 break;
6226 }
6227 }
6228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
504 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 504 sc = st->priv_data;
6233
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 500 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
504 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 504 index_entry_pos = sti->nb_index_entries;
6243
2/2
✓ Branch 0 taken 1634 times.
✓ Branch 1 taken 504 times.
2138 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 504 times.
504 av_assert0(index_entry_pos <= sti->nb_index_entries);
6252
6253 504 avio_r8(pb); /* version */
6254 504 flags = avio_rb24(pb);
6255 504 entries = avio_rb32(pb);
6256 504 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 504 times.
504 if ((uint64_t)entries+sc->tts_count >= UINT_MAX/sizeof(*sc->tts_data))
6259 ✗ return AVERROR_INVALIDDATA;
6260
1/2
✓ Branch 0 taken 504 times.
✗ Branch 1 not taken.
504 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
6261
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 427 times.
504 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb);
6262
6263 504 int entry_size = !!(flags & MOV_TRUN_SAMPLE_DURATION) * 4
6264 504 + !!(flags & MOV_TRUN_SAMPLE_SIZE) * 4
6265 504 + !!(flags & MOV_TRUN_SAMPLE_FLAGS) * 4
6266 504 + !!(flags & MOV_TRUN_SAMPLE_CTS) * 4;
6267 504 int64_t sample_data_size = avio_size(sc->pb);
6268 504 int64_t max_entries = INT64_MAX;
6269
6270
2/2
✓ Branch 0 taken 503 times.
✓ Branch 1 taken 1 times.
504 if (sample_data_size > 0)
6271 503 max_entries = sample_data_size - sti->nb_index_entries;
6272
2/2
✓ Branch 0 taken 478 times.
✓ Branch 1 taken 26 times.
504 if (entry_size) {
6273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
478 int64_t size = sc->pb == pb ? sample_data_size : avio_size(pb);
6274 478 int64_t pos = avio_tell(pb);
6275 478 int64_t left = atom.size - 8 - !!(flags & MOV_TRUN_DATA_OFFSET) * 4
6276 478 - !!(flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) * 4;
6277
6278
3/4
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 477 times.
✓ Branch 3 taken 1 times.
478 if (pos >= 0 && size >= pos)
6279 477 left = FFMIN(left, size - pos);
6280 478 max_entries = FFMIN(max_entries, left / entry_size);
6281 }
6282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
504 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 504 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6289
1/2
✓ Branch 0 taken 504 times.
✗ Branch 1 not taken.
504 if (frag_stream_info) {
6290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
504 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 501 times.
504 } 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 501 times.
501 } 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 501 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
6304 501 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
6305
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
501 int fallback_tfdt = !c->use_tfdt && !has_sidx && has_tfdt;
6306
4/6
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 428 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
501 int fallback_sidx = c->use_tfdt && !has_tfdt && has_sidx;
6307
6308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
501 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 501 times.
501 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 428 times.
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 428 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
501 if (has_tfdt && c->use_tfdt || fallback_tfdt) {
6316 428 dts = frag_stream_info->tfdt_dts - sc->time_offset;
6317 428 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 504 offset = frag->base_data_offset + data_offset;
6337 504 distance = 0;
6338 504 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 504 times.
504 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 504 times.
504 if (entries == 0)
6346 ✗ return 0;
6347
6348 504 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
6349 504 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 504 times.
504 if (!new_entries)
6353 ✗ return AVERROR(ENOMEM);
6354 504 sti->index_entries= new_entries;
6355
6356 504 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
6357 504 old_allocated_size = sc->tts_allocated_size;
6358 504 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 504 times.
504 if (!tts_data)
6361 ✗ return AVERROR(ENOMEM);
6362 504 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 504 memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0,
6368 504 sc->tts_allocated_size - old_allocated_size);
6369
6370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
504 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 504 sti->nb_index_entries += entries;
6385 504 sc->tts_count = sti->nb_index_entries;
6386 504 sc->stts_count = sti->nb_index_entries;
6387
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 118 times.
504 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 504 times.
✗ Branch 1 not taken.
504 if (frag_stream_info) {
6392 504 frag_stream_info->index_entry = index_entry_pos;
6393
1/2
✓ Branch 0 taken 504 times.
✗ Branch 1 not taken.
504 if (frag_stream_info->index_base < 0)
6394 504 frag_stream_info->index_base = index_entry_pos;
6395 }
6396
6397
2/2
✓ Branch 0 taken 473 times.
✓ Branch 1 taken 31 times.
504 if (index_entry_pos > 0)
6398 473 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6399
6400
3/4
✓ Branch 0 taken 9581 times.
✓ Branch 1 taken 504 times.
✓ Branch 2 taken 9581 times.
✗ Branch 3 not taken.
10085 for (i = 0; i < entries && !pb->eof_reached; i++) {
6401 9581 unsigned sample_size = frag->size;
6402
2/2
✓ Branch 0 taken 9077 times.
✓ Branch 1 taken 504 times.
9581 int sample_flags = i ? frag->flags : first_sample_flags;
6403 9581 unsigned sample_duration = frag->duration;
6404 9581 unsigned ctts_duration = 0;
6405 9581 int keyframe = 0;
6406 9581 int index_entry_flags = 0;
6407
6408
2/2
✓ Branch 0 taken 1684 times.
✓ Branch 1 taken 7897 times.
9581 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
6409
2/2
✓ Branch 0 taken 9523 times.
✓ Branch 1 taken 58 times.
9581 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
6410
2/2
✓ Branch 0 taken 1845 times.
✓ Branch 1 taken 7736 times.
9581 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
6411
2/2
✓ Branch 0 taken 6576 times.
✓ Branch 1 taken 3005 times.
9581 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
6412
6413
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9580 times.
9581 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 9581 mov_update_dts_shift(sc, ctts_duration, c->fc);
6421
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9578 times.
9581 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 9581 keyframe =
6440 9581 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
6441 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
6442
2/2
✓ Branch 0 taken 666 times.
✓ Branch 1 taken 8915 times.
9581 if (keyframe) {
6443 666 distance = 0;
6444 666 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 9557 times.
9581 if (prev_dts >= dts)
6449 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
6450
6451 9581 sti->index_entries[index_entry_pos].pos = offset;
6452 9581 sti->index_entries[index_entry_pos].timestamp = dts;
6453 9581 sti->index_entries[index_entry_pos].size = sample_size;
6454 9581 sti->index_entries[index_entry_pos].min_distance = distance;
6455 9581 sti->index_entries[index_entry_pos].flags = index_entry_flags;
6456
6457 9581 sc->tts_data[index_entry_pos].count = 1;
6458 9581 sc->tts_data[index_entry_pos].offset = ctts_duration;
6459 9581 sc->tts_data[index_entry_pos].duration = sample_duration;
6460 9581 index_entry_pos++;
6461
6462 9581 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 9581 distance++;
6466
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9581 times.
9581 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 9581 times.
9581 if (!sample_size)
6469 ✗ return AVERROR_INVALIDDATA;
6470 9581 dts += sample_duration;
6471 9581 offset += sample_size;
6472 9581 sc->data_size += sample_size;
6473
6474
1/2
✓ Branch 0 taken 9581 times.
✗ Branch 1 not taken.
9581 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
6475
1/2
✓ Branch 0 taken 9581 times.
✗ Branch 1 not taken.
9581 1 <= INT_MAX - sc->nb_frames_for_fps
6476 ) {
6477 9581 sc->duration_for_fps += sample_duration;
6478 9581 sc->nb_frames_for_fps ++;
6479 }
6480 }
6481
1/2
✓ Branch 0 taken 504 times.
✗ Branch 1 not taken.
504 if (frag_stream_info)
6482 504 frag_stream_info->next_trun_dts = dts + sc->time_offset;
6483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
504 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 504 prev_dts = AV_NOPTS_VALUE;
6508
1/2
✓ Branch 0 taken 504 times.
✗ Branch 1 not taken.
504 if (index_entry_pos > 0)
6509 504 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
504 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 504 fix_frag_index_entries(&c->frag_index, next_frag_index,
6520 504 frag->track_id, entries);
6521
6522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
504 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 504 frag->implicit_offset = offset;
6528
6529 504 sc->track_end = dts + sc->time_offset;
6530
2/2
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 386 times.
504 if (st->duration < sc->track_end)
6531 118 st->duration = sc->track_end;
6532
6533 504 return 0;
6534 }
6535
6536 49 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6537 {
6538 49 int64_t stream_size = avio_size(pb);
6539 49 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 49 AVStream *st = NULL;
6544 49 AVStream *ref_st = NULL;
6545 49 MOVStreamContext *sc, *ref_sc = NULL;
6546 AVRational timescale;
6547
6548 49 version = avio_r8(pb);
6549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if (version > 1) {
6550 ✗ avpriv_request_sample(c->fc, "sidx version %u", version);
6551 ✗ return 0;
6552 }
6553
6554 49 avio_rb24(pb); // flags
6555
6556 49 track_id = avio_rb32(pb); // Reference ID
6557
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 for (i = 0; i < c->fc->nb_streams; i++) {
6558 49 sc = c->fc->streams[i]->priv_data;
6559
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 if (sc->id == track_id) {
6560 49 st = c->fc->streams[i];
6561 49 break;
6562 }
6563 }
6564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 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 49 sc = st->priv_data;
6570
6571 49 timescale = av_make_q(1, avio_rb32(pb));
6572
6573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 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 48 times.
✓ Branch 1 taken 1 times.
49 if (version == 0) {
6579 48 pts = avio_rb32(pb);
6580 48 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 49 times.
49 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6586 ✗ return AVERROR_INVALIDDATA;
6587
6588 49 offset += (uint64_t)offadd;
6589
6590 49 avio_rb16(pb); // reserved
6591
6592 49 item_count = avio_rb16(pb);
6593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if (item_count == 0)
6594 ✗ return AVERROR_INVALIDDATA;
6595
6596
2/2
✓ Branch 0 taken 375 times.
✓ Branch 1 taken 49 times.
424 for (i = 0; i < item_count; i++) {
6597 int index;
6598 MOVFragmentStreamInfo * frag_stream_info;
6599 375 uint32_t size = avio_rb32(pb);
6600 375 uint32_t duration = avio_rb32(pb);
6601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 375 times.
375 if (size & 0x80000000) {
6602 ✗ avpriv_request_sample(c->fc, "sidx reference_type 1");
6603 ✗ return AVERROR_PATCHWELCOME;
6604 }
6605 375 avio_rb32(pb); // sap_flags
6606 375 timestamp = av_rescale_q(pts, timescale, st->time_base);
6607
6608 375 index = update_frag_index(c, offset);
6609 375 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6610
1/2
✓ Branch 0 taken 375 times.
✗ Branch 1 not taken.
375 if (frag_stream_info)
6611 375 frag_stream_info->sidx_pts = timestamp;
6612
6613
1/2
✓ Branch 1 taken 375 times.
✗ Branch 2 not taken.
375 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6614
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 375 times.
375 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6615 )
6616 ✗ return AVERROR_INVALIDDATA;
6617 375 offset += size;
6618 375 pts += duration;
6619 }
6620
6621 49 st->duration = sc->track_end = pts;
6622
6623 49 sc->has_sidx = 1;
6624
6625 // See if the remaining bytes are just an mfra which we can ignore.
6626 49 is_complete = offset == stream_size;
6627
5/6
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 41 times.
✗ Branch 5 not taken.
49 if (!is_complete && (pb->seekable & AVIO_SEEKABLE_NORMAL) && stream_size > 0 ) {
6628 int64_t ret;
6629 41 int64_t original_pos = avio_tell(pb);
6630
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 35 times.
41 if (!c->have_read_mfra_size) {
6631
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6632 ✗ return ret;
6633 6 c->mfra_size = avio_rb32(pb);
6634 6 c->have_read_mfra_size = 1;
6635
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6636 ✗ return ret;
6637 }
6638
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (offset == stream_size - c->mfra_size)
6639 ✗ is_complete = 1;
6640 }
6641
6642
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 42 times.
49 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 49 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 546 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 546 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 546 times.
546 if (c->fc->nb_streams < 1 || c->ignore_editlist)
6755 ✗ return 0;
6756 546 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6757
6758 546 version = avio_r8(pb); /* version */
6759 546 avio_rb24(pb); /* flags */
6760 546 edit_count = avio_rb32(pb); /* entries */
6761 546 atom.size -= 8;
6762
6763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 546 times.
546 elst_entry_size = version == 1 ? 20 : 12;
6764
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 545 times.
546 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 546 times.
546 if (!edit_count)
6778 ✗ return 0;
6779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 546 times.
546 if (sc->elst_data)
6780 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6781 546 av_free(sc->elst_data);
6782 546 sc->elst_count = 0;
6783 546 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 546 times.
546 if (!sc->elst_data)
6785 ✗ return AVERROR(ENOMEM);
6786
6787 546 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 575 times.
✓ Branch 1 taken 546 times.
✓ Branch 2 taken 575 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 575 times.
✗ Branch 5 not taken.
1121 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
6789 575 MOVElst *e = &sc->elst_data[i];
6790
6791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 if (version == 1) {
6792 ✗ e->duration = avio_rb64(pb);
6793 ✗ e->time = avio_rb64(pb);
6794 ✗ atom.size -= 16;
6795 } else {
6796 575 e->duration = avio_rb32(pb); /* segment duration */
6797 575 e->time = (int32_t)avio_rb32(pb); /* media time */
6798 575 atom.size -= 8;
6799 }
6800 575 e->rate = avio_rb32(pb) / 65536.0;
6801 575 atom.size -= 4;
6802 575 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6803 575 e->duration, e->time, e->rate);
6804
6805
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 571 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
575 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 575 times.
575 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 546 sc->elst_count = i;
6818
6819 546 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 262 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 144 times.
✓ Branch 1 taken 118 times.
262 if (atom.size < 8)
7861 144 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 107970 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8911 {
8912 107970 int current = frag_index->current;
8913
8914
2/2
✓ Branch 0 taken 106980 times.
✓ Branch 1 taken 990 times.
107970 if (!frag_index->nb_items)
8915 106980 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 990 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 990 times.
✗ Branch 3 not taken.
990 if (current >= 0 && current < frag_index->nb_items) {
8919
2/2
✓ Branch 0 taken 963 times.
✓ Branch 1 taken 27 times.
990 if (frag_index->item[current].moof_offset < pkt->pos &&
8920
2/2
✓ Branch 0 taken 608 times.
✓ Branch 1 taken 355 times.
963 (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 887 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 107970 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 107970 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8943 107970 encrypted_index = current_index;
8944 107970 encryption_index = NULL;
8945
2/2
✓ Branch 0 taken 990 times.
✓ Branch 1 taken 106980 times.
107970 if (frag_stream_info) {
8946 // Note this only supports encryption info in the first sample descriptor.
8947
2/2
✓ Branch 0 taken 942 times.
✓ Branch 1 taken 48 times.
990 if (frag_stream_info->stsd_id == 1) {
8948
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 894 times.
942 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 894 encryption_index = sc->cenc.encryption_index;
8953 }
8954 }
8955 } else {
8956 106980 encryption_index = sc->cenc.encryption_index;
8957 }
8958
8959
2/2
✓ Branch 0 taken 341 times.
✓ Branch 1 taken 107629 times.
107970 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 107629 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 5 static int mov_read_mhac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10044 {
10045 5 AVFormatContext *ctx = c->fc;
10046 AVStream *st;
10047 int profile_level_indication, reference_ch_layout, config_length;
10048 5 int ret = 0;
10049
10050
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ctx->nb_streams < 1)
10051 ✗ return 0;
10052
10053 5 st = ctx->streams[ctx->nb_streams - 1];
10054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
10055 ✗ return 0;
10056
10057
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_r8(pb) != 1) // ConfigurationVersion
10058 ✗ return 0;
10059
10060 5 profile_level_indication = avio_r8(pb);
10061 5 st->codecpar->profile = (profile_level_indication - 1) / 5;
10062 5 st->codecpar->level = ((profile_level_indication - 1) % 5) + 1;
10063
10064 5 reference_ch_layout = avio_r8(pb);
10065 5 config_length = avio_rb16(pb);
10066
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (config_length)
10067 5 ret = ff_get_extradata(ctx, st->codecpar, pb, config_length);
10068
10069
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (!reference_ch_layout ||
10070
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 reference_ch_layout >= FF_ARRAY_ELEMS(ff_mpa_cicp_channel_layout_masks)) {
10071 ✗ av_log(ctx, AV_LOG_WARNING, "Unknown referenceChannelLayout value: %d\n", reference_ch_layout);
10072 ✗ return ret;
10073 }
10074
10075 5 av_channel_layout_from_mask(&st->codecpar->ch_layout,
10076 5 ff_mpa_cicp_channel_layout_masks[reference_ch_layout]);
10077
10078 5 return ret;
10079 }
10080
10081 static const MOVParseTableEntry mov_default_parse_table[] = {
10082 { MKTAG('A','C','L','R'), mov_read_aclr },
10083 { MKTAG('A','P','R','G'), mov_read_avid },
10084 { MKTAG('A','A','L','P'), mov_read_avid },
10085 { MKTAG('A','R','E','S'), mov_read_ares },
10086 { MKTAG('a','v','s','s'), mov_read_avss },
10087 { MKTAG('a','v','1','C'), mov_read_glbl },
10088 { MKTAG('c','h','p','l'), mov_read_chpl },
10089 { MKTAG('c','o','6','4'), mov_read_stco },
10090 { MKTAG('c','o','l','r'), mov_read_colr },
10091 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
10092 { MKTAG('d','i','n','f'), mov_read_default },
10093 { MKTAG('D','p','x','E'), mov_read_dpxe },
10094 { MKTAG('d','r','e','f'), mov_read_dref },
10095 { MKTAG('e','d','t','s'), mov_read_default },
10096 { MKTAG('e','l','s','t'), mov_read_elst },
10097 { MKTAG('e','n','d','a'), mov_read_enda },
10098 { MKTAG('f','i','e','l'), mov_read_fiel },
10099 { MKTAG('a','d','r','m'), mov_read_adrm },
10100 { MKTAG('f','t','y','p'), mov_read_ftyp },
10101 { MKTAG('g','l','b','l'), mov_read_glbl },
10102 { MKTAG('h','d','l','r'), mov_read_hdlr },
10103 { MKTAG('i','l','s','t'), mov_read_ilst },
10104 { MKTAG('j','p','2','h'), mov_read_jp2h },
10105 { MKTAG('m','d','a','t'), mov_read_mdat },
10106 { MKTAG('m','d','h','d'), mov_read_mdhd },
10107 { MKTAG('m','d','i','a'), mov_read_default },
10108 { MKTAG('m','e','t','a'), mov_read_meta },
10109 { MKTAG('m','i','n','f'), mov_read_default },
10110 { MKTAG('m','o','o','f'), mov_read_moof },
10111 { MKTAG('m','o','o','v'), mov_read_moov },
10112 { MKTAG('m','v','e','x'), mov_read_default },
10113 { MKTAG('m','v','h','d'), mov_read_mvhd },
10114 { MKTAG('S','M','I',' '), mov_read_svq3 },
10115 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
10116 { MKTAG('a','v','c','C'), mov_read_glbl },
10117 { MKTAG('p','a','s','p'), mov_read_pasp },
10118 { MKTAG('c','l','a','p'), mov_read_clap },
10119 { MKTAG('c','d','s','c'), mov_read_cdsc_rndr },
10120 { MKTAG('r','n','d','r'), mov_read_cdsc_rndr },
10121 { MKTAG('s','b','a','s'), mov_read_sbas },
10122 { MKTAG('v','d','e','p'), mov_read_vdep },
10123 { MKTAG('s','i','d','x'), mov_read_sidx },
10124 { MKTAG('s','t','b','l'), mov_read_default },
10125 { MKTAG('s','t','c','o'), mov_read_stco },
10126 { MKTAG('s','t','p','s'), mov_read_stps },
10127 { MKTAG('s','t','r','f'), mov_read_strf },
10128 { MKTAG('s','t','s','c'), mov_read_stsc },
10129 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
10130 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
10131 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
10132 { MKTAG('s','t','t','s'), mov_read_stts },
10133 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
10134 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
10135 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
10136 { MKTAG('t','f','d','t'), mov_read_tfdt },
10137 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
10138 { MKTAG('t','r','a','k'), mov_read_trak },
10139 { MKTAG('t','r','a','f'), mov_read_default },
10140 { MKTAG('t','r','e','f'), mov_read_default },
10141 { MKTAG('t','m','c','d'), mov_read_tmcd },
10142 { MKTAG('c','h','a','p'), mov_read_chap },
10143 { MKTAG('t','r','e','x'), mov_read_trex },
10144 { MKTAG('t','r','u','n'), mov_read_trun },
10145 { MKTAG('u','d','t','a'), mov_read_default },
10146 { MKTAG('w','a','v','e'), mov_read_wave },
10147 { MKTAG('e','s','d','s'), mov_read_esds },
10148 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
10149 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
10150 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
10151 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
10152 { MKTAG('w','f','e','x'), mov_read_wfex },
10153 { MKTAG('c','m','o','v'), mov_read_cmov },
10154 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
10155 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
10156 { MKTAG('d','v','c','1'), mov_read_dvc1 },
10157 { MKTAG('s','g','p','d'), mov_read_sgpd },
10158 { MKTAG('s','b','g','p'), mov_read_sbgp },
10159 { MKTAG('h','v','c','C'), mov_read_glbl },
10160 { MKTAG('v','v','c','C'), mov_read_glbl },
10161 { MKTAG('u','u','i','d'), mov_read_uuid },
10162 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
10163 { MKTAG('f','r','e','e'), mov_read_free },
10164 { MKTAG('-','-','-','-'), mov_read_custom },
10165 { MKTAG('s','i','n','f'), mov_read_default },
10166 { MKTAG('f','r','m','a'), mov_read_frma },
10167 { MKTAG('s','e','n','c'), mov_read_senc },
10168 { MKTAG('s','a','i','z'), mov_read_saiz },
10169 { MKTAG('s','a','i','o'), mov_read_saio },
10170 { MKTAG('p','s','s','h'), mov_read_pssh },
10171 { MKTAG('s','c','h','m'), mov_read_schm },
10172 { MKTAG('s','c','h','i'), mov_read_default },
10173 { MKTAG('t','e','n','c'), mov_read_tenc },
10174 { MKTAG('d','f','L','a'), mov_read_dfla },
10175 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
10176 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
10177 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
10178 { MKTAG('h','f','o','v'), mov_read_hfov },
10179 { MKTAG('d','O','p','s'), mov_read_dops },
10180 { MKTAG('d','m','l','p'), mov_read_dmlp },
10181 { MKTAG('S','m','D','m'), mov_read_smdm },
10182 { MKTAG('C','o','L','L'), mov_read_coll },
10183 { MKTAG('v','p','c','C'), mov_read_vpcc },
10184 { MKTAG('m','d','c','v'), mov_read_mdcv },
10185 { MKTAG('c','l','l','i'), mov_read_clli },
10186 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
10187 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
10188 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
10189 { MKTAG('h','v','c','E'), mov_read_hvce },
10190 { MKTAG('k','i','n','d'), mov_read_kind },
10191 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
10192 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
10193 { MKTAG('i','l','o','c'), mov_read_iloc },
10194 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
10195 { MKTAG('p','i','t','m'), mov_read_pitm },
10196 { MKTAG('e','v','c','C'), mov_read_glbl },
10197 { MKTAG('i','d','a','t'), mov_read_idat },
10198 { MKTAG('i','m','i','r'), mov_read_imir },
10199 { MKTAG('i','r','e','f'), mov_read_iref },
10200 { MKTAG('i','s','p','e'), mov_read_ispe },
10201 { MKTAG('i','r','o','t'), mov_read_irot },
10202 { MKTAG('i','p','r','p'), mov_read_iprp },
10203 { MKTAG('i','i','n','f'), mov_read_iinf },
10204 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
10205 { MKTAG('l','h','v','C'), mov_read_lhvc },
10206 { MKTAG('l','v','c','C'), mov_read_glbl },
10207 { MKTAG('a','p','v','C'), mov_read_glbl },
10208 #if CONFIG_IAMFDEC
10209 { MKTAG('i','a','c','b'), mov_read_iacb },
10210 #endif
10211 { MKTAG('s','r','a','t'), mov_read_srat },
10212 { MKTAG('v','m','h','d'), mov_read_vmhd },
10213 { MKTAG('m','h','a','C'), mov_read_mhac },
10214 { 0, NULL }
10215 };
10216
10217 8015 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10218 {
10219 8015 int64_t total_size = 0;
10220 MOVAtom a;
10221 int i;
10222
10223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8015 times.
8015 if (c->atom_depth > 10) {
10224 ✗ av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
10225 ✗ return AVERROR_INVALIDDATA;
10226 }
10227 8015 c->atom_depth ++;
10228
10229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8015 times.
8015 if (atom.size < 0)
10230 ✗ atom.size = INT64_MAX;
10231
2/2
✓ Branch 0 taken 22876 times.
✓ Branch 1 taken 7414 times.
30290 while (total_size <= atom.size - 8) {
10232 22876 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
10233 22876 a.size = avio_rb32(pb);
10234 22876 a.type = avio_rl32(pb);
10235
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 22869 times.
22876 if (avio_feof(pb))
10236 7 break;
10237
3/4
✓ Branch 0 taken 262 times.
✓ Branch 1 taken 22607 times.
✓ Branch 2 taken 262 times.
✗ Branch 3 not taken.
22869 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
10238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22869 times.
22869 a.type == MKTAG('h','o','o','v')) &&
10239 ✗ a.size >= 8 &&
10240 ✗ c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
10241 uint32_t type;
10242 ✗ avio_skip(pb, 4);
10243 ✗ type = avio_rl32(pb);
10244 ✗ if (avio_feof(pb))
10245 ✗ break;
10246 ✗ avio_seek(pb, -8, SEEK_CUR);
10247 ✗ if (type == MKTAG('m','v','h','d') ||
10248 type == MKTAG('c','m','o','v')) {
10249 ✗ av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
10250 ✗ a.type = MKTAG('m','o','o','v');
10251 }
10252 }
10253
2/2
✓ Branch 0 taken 19536 times.
✓ Branch 1 taken 3333 times.
22869 if (atom.type != MKTAG('r','o','o','t') &&
10254
2/2
✓ Branch 0 taken 17769 times.
✓ Branch 1 taken 1767 times.
19536 atom.type != MKTAG('m','o','o','v')) {
10255
1/2
✓ Branch 0 taken 17769 times.
✗ Branch 1 not taken.
17769 if (a.type == MKTAG('t','r','a','k') ||
10256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17769 times.
17769 a.type == MKTAG('m','d','a','t')) {
10257 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
10258 ✗ avio_skip(pb, -8);
10259 ✗ c->atom_depth --;
10260 594 return 0;
10261 }
10262 }
10263 22869 total_size += 8;
10264
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 22840 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
22869 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
10265 29 a.size = avio_rb64(pb) - 8;
10266 29 total_size += 8;
10267 }
10268 22869 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
10269 22869 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
10270
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 22864 times.
22869 if (a.size == 0) {
10271 5 a.size = atom.size - total_size + 8;
10272 }
10273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22869 times.
22869 if (a.size < 0)
10274 ✗ break;
10275 22869 a.size -= 8;
10276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22869 times.
22869 if (a.size < 0)
10277 ✗ break;
10278 22869 a.size = FFMIN(a.size, atom.size - total_size);
10279
10280
2/2
✓ Branch 0 taken 1102372 times.
✓ Branch 1 taken 1959 times.
1104331 for (i = 0; mov_default_parse_table[i].type; i++)
10281
2/2
✓ Branch 0 taken 20910 times.
✓ Branch 1 taken 1081462 times.
1102372 if (mov_default_parse_table[i].type == a.type) {
10282 20910 parse = mov_default_parse_table[i].parse;
10283 20910 break;
10284 }
10285
10286 // container is user data
10287
4/4
✓ Branch 0 taken 1959 times.
✓ Branch 1 taken 20910 times.
✓ Branch 2 taken 1759 times.
✓ Branch 3 taken 200 times.
22869 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
10288
2/2
✓ Branch 0 taken 433 times.
✓ Branch 1 taken 1326 times.
1759 atom.type == MKTAG('i','l','s','t')))
10289 633 parse = mov_read_udta_string;
10290
10291 // Supports parsing the QuickTime Metadata Keys.
10292 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
10293
4/4
✓ Branch 0 taken 1326 times.
✓ Branch 1 taken 21543 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 1312 times.
22869 if (!parse && c->found_hdlr_mdta &&
10294
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 atom.type == MKTAG('m','e','t','a') &&
10295
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 a.type == MKTAG('k','e','y','s') &&
10296
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 c->meta_keys_count == 0) {
10297 14 parse = mov_read_keys;
10298 }
10299
10300
2/2
✓ Branch 0 taken 1312 times.
✓ Branch 1 taken 21557 times.
22869 if (!parse) { /* skip leaf atoms data */
10301 1312 avio_skip(pb, a.size);
10302 } else {
10303 21557 int64_t start_pos = avio_tell(pb);
10304 int64_t left;
10305 21557 int err = parse(c, pb, a);
10306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21557 times.
21557 if (err < 0) {
10307 ✗ c->atom_depth --;
10308 ✗ return err;
10309 }
10310
5/6
✓ Branch 0 taken 3902 times.
✓ Branch 1 taken 17655 times.
✓ Branch 2 taken 3455 times.
✓ Branch 3 taken 447 times.
✓ Branch 4 taken 3455 times.
✗ Branch 5 not taken.
21557 if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos &&
10311
7/8
✓ Branch 0 taken 3454 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3454 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3440 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 579 times.
✓ Branch 7 taken 2861 times.
6895 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
10312 3440 start_pos + a.size == avio_size(pb))) {
10313
5/6
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 593 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 579 times.
594 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
10314 15 c->next_root_atom = start_pos + a.size;
10315 594 c->atom_depth --;
10316 594 return 0;
10317 }
10318 20963 left = a.size - avio_tell(pb) + start_pos;
10319
2/2
✓ Branch 0 taken 2151 times.
✓ Branch 1 taken 18812 times.
20963 if (left > 0) /* skip garbage at atom end */
10320 2151 avio_skip(pb, left);
10321
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18810 times.
18812 else if (left < 0) {
10322 2 av_log(c->fc, AV_LOG_WARNING,
10323 "overread end of atom '%s' by %"PRId64" bytes\n",
10324 2 av_fourcc2str(a.type), -left);
10325 2 avio_seek(pb, left, SEEK_CUR);
10326 }
10327 }
10328
10329 22275 total_size += a.size;
10330 }
10331
10332
4/4
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 7291 times.
✓ Branch 2 taken 123 times.
✓ Branch 3 taken 7 times.
7421 if (total_size < atom.size && atom.size < 0x7ffff)
10333 123 avio_skip(pb, atom.size - total_size);
10334
10335 7421 c->atom_depth --;
10336 7421 return 0;
10337 }
10338
10339 8077 static int mov_probe(const AVProbeData *p)
10340 {
10341 int64_t offset;
10342 uint32_t tag;
10343 8077 int score = 0;
10344 8077 int moov_offset = -1;
10345
10346 /* check file header */
10347 8077 offset = 0;
10348 9977 for (;;) {
10349 int64_t size;
10350 18054 int minsize = 8;
10351 /* ignore invalid offset */
10352
2/2
✓ Branch 0 taken 8077 times.
✓ Branch 1 taken 9977 times.
18054 if ((offset + 8ULL) > (unsigned int)p->buf_size)
10353 8077 break;
10354 9977 size = AV_RB32(p->buf + offset);
10355
3/4
✓ Branch 0 taken 541 times.
✓ Branch 1 taken 9436 times.
✓ Branch 2 taken 541 times.
✗ Branch 3 not taken.
9977 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
10356 541 size = AV_RB64(p->buf+offset + 8);
10357 541 minsize = 16;
10358
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 9364 times.
9436 } else if (size == 0) {
10359 72 size = p->buf_size - offset;
10360 }
10361
2/2
✓ Branch 0 taken 411 times.
✓ Branch 1 taken 9566 times.
9977 if (size < minsize) {
10362 411 offset += 4;
10363 411 continue;
10364 }
10365 9566 tag = AV_RL32(p->buf + offset + 4);
10366
5/6
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 1009 times.
✓ Branch 2 taken 431 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7967 times.
9566 switch(tag) {
10367 /* check for obvious tags */
10368 158 case MKTAG('m','o','o','v'):
10369 158 moov_offset = offset + 4;
10370 av_fallthrough;
10371 1167 case MKTAG('m','d','a','t'):
10372 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
10373 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
10374 case MKTAG('f','t','y','p'):
10375
2/2
✓ Branch 0 taken 523 times.
✓ Branch 1 taken 644 times.
1167 if (tag == MKTAG('f','t','y','p') &&
10376
1/2
✓ Branch 0 taken 523 times.
✗ Branch 1 not taken.
523 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
10377
1/2
✓ Branch 0 taken 523 times.
✗ Branch 1 not taken.
523 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
10378
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 516 times.
523 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
10379 )) {
10380 7 score = FFMAX(score, 5);
10381 } else {
10382 1160 score = AVPROBE_SCORE_MAX;
10383 }
10384 1167 break;
10385 /* those are more common words, so rate then a bit less */
10386 431 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
10387 case MKTAG('w','i','d','e'):
10388 case MKTAG('f','r','e','e'):
10389 case MKTAG('j','u','n','k'):
10390 case MKTAG('p','i','c','t'):
10391 431 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
10392 431 break;
10393 ✗ case MKTAG(0x82,0x82,0x7f,0x7d):
10394 ✗ score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
10395 ✗ break;
10396 1 case MKTAG('s','k','i','p'):
10397 case MKTAG('u','u','i','d'):
10398 case MKTAG('p','r','f','l'):
10399 /* if we only find those cause probedata is too small at least rate them */
10400 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
10401 1 break;
10402 }
10403
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9566 times.
9566 if (size > INT64_MAX - offset)
10404 ✗ break;
10405 9566 offset += size;
10406 }
10407
4/4
✓ Branch 0 taken 570 times.
✓ Branch 1 taken 7507 times.
✓ Branch 2 taken 158 times.
✓ Branch 3 taken 412 times.
8077 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
10408 /* moov atom in the header - we should make sure that this is not a
10409 * MOV-packed MPEG-PS */
10410 158 offset = moov_offset;
10411
10412
2/2
✓ Branch 0 taken 154630 times.
✓ Branch 1 taken 158 times.
154788 while (offset < (p->buf_size - 16)) { /* Sufficient space */
10413 /* We found an actual hdlr atom */
10414
2/2
✓ Branch 0 taken 174 times.
✓ Branch 1 taken 154456 times.
154630 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
10415
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 149 times.
174 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
10416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
10417 ✗ av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
10418 /* We found a media handler reference atom describing an
10419 * MPEG-PS-in-MOV, return a
10420 * low score to force expanding the probe window until
10421 * mpegps_probe finds what it needs */
10422 ✗ return 5;
10423 } else {
10424 /* Keep looking */
10425 154630 offset += 2;
10426 }
10427 }
10428 }
10429
10430 8077 return score;
10431 }
10432
10433 // must be done after parsing all trak because there's no order requirement
10434 2 static void mov_read_chapters(AVFormatContext *s)
10435 {
10436 2 MOVContext *mov = s->priv_data;
10437 MOVStreamContext *sc;
10438 int64_t cur_pos;
10439 int i, j;
10440 int chapter_track;
10441
10442
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
10443 2 AVStream *st = NULL;
10444 2 FFStream *sti = NULL;
10445 2 chapter_track = mov->chapter_tracks[j];
10446
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
10447 4 sc = mov->fc->streams[i]->priv_data;
10448
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
10449 2 st = s->streams[i];
10450 2 break;
10451 }
10452 }
10453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
10454 ✗ av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
10455 ✗ continue;
10456 }
10457 2 sti = ffstream(st);
10458
10459 2 sc = st->priv_data;
10460 2 cur_pos = avio_tell(sc->pb);
10461
10462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
10463 ✗ st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
10464 ✗ if (!st->attached_pic.data && sti->nb_index_entries) {
10465 // Retrieve the first frame, if possible
10466 ✗ AVIndexEntry *sample = &sti->index_entries[0];
10467 ✗ if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10468 ✗ av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
10469 ✗ goto finish;
10470 }
10471
10472 ✗ if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
10473 ✗ goto finish;
10474 }
10475 } else {
10476 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10477 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
10478 2 st->discard = AVDISCARD_ALL;
10479
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
10480 8 AVIndexEntry *sample = &sti->index_entries[i];
10481
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;
10482 uint8_t *title;
10483 uint16_t ch;
10484 int len, title_len;
10485
10486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
10487 ✗ av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
10488 ✗ end = AV_NOPTS_VALUE;
10489 }
10490
10491
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10492 ✗ av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
10493 ✗ goto finish;
10494 }
10495
10496 // the first two bytes are the length of the title
10497 8 len = avio_rb16(sc->pb);
10498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
10499 ✗ continue;
10500 8 title_len = 2*len + 1;
10501
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
10502 ✗ goto finish;
10503
10504 // The samples could theoretically be in any encoding if there's an encd
10505 // atom following, but in practice are only utf-8 or utf-16, distinguished
10506 // instead by the presence of a BOM
10507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
10508 ✗ title[0] = 0;
10509 } else {
10510 8 ch = avio_rb16(sc->pb);
10511
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
10512 ✗ avio_get_str16be(sc->pb, len, title, title_len);
10513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
10514 ✗ avio_get_str16le(sc->pb, len, title, title_len);
10515 else {
10516 8 AV_WB16(title, ch);
10517
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)
10518 ✗ title[len] = 0;
10519 else
10520 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
10521 }
10522 }
10523
10524 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
10525 8 av_freep(&title);
10526 }
10527 }
10528 2 finish:
10529 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
10530 }
10531 2 }
10532
10533 28 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
10534 int64_t value, int flags)
10535 {
10536 AVTimecode tc;
10537 char buf[AV_TIMECODE_STR_SIZE];
10538 28 AVRational rate = st->avg_frame_rate;
10539 28 int ret = av_timecode_init(&tc, rate, flags, 0, s);
10540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
10541 ✗ return ret;
10542 28 av_dict_set(&st->metadata, "timecode",
10543 28 av_timecode_make_string(&tc, buf, value), 0);
10544 28 return 0;
10545 }
10546
10547 ✗ static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
10548 {
10549 ✗ MOVStreamContext *sc = st->priv_data;
10550 ✗ FFStream *const sti = ffstream(st);
10551 char buf[AV_TIMECODE_STR_SIZE];
10552 ✗ int64_t cur_pos = avio_tell(sc->pb);
10553 int hh, mm, ss, ff, drop;
10554
10555 ✗ if (!sti->nb_index_entries)
10556 ✗ return -1;
10557
10558 ✗ avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10559 ✗ avio_skip(s->pb, 13);
10560 ✗ hh = avio_r8(s->pb);
10561 ✗ mm = avio_r8(s->pb);
10562 ✗ ss = avio_r8(s->pb);
10563 ✗ drop = avio_r8(s->pb);
10564 ✗ ff = avio_r8(s->pb);
10565 ✗ snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
10566 hh, mm, ss, drop ? ';' : ':', ff);
10567 ✗ av_dict_set(&st->metadata, "timecode", buf, 0);
10568
10569 ✗ avio_seek(sc->pb, cur_pos, SEEK_SET);
10570 ✗ return 0;
10571 }
10572
10573 28 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
10574 {
10575 28 MOVStreamContext *sc = st->priv_data;
10576 28 FFStream *const sti = ffstream(st);
10577 28 int flags = 0;
10578 28 int64_t cur_pos = avio_tell(sc->pb);
10579 int64_t value;
10580 28 AVRational tc_rate = st->avg_frame_rate;
10581 28 int tmcd_nb_frames = sc->tmcd_nb_frames;
10582 int rounded_tc_rate;
10583
10584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!sti->nb_index_entries)
10585 ✗ return -1;
10586
10587
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)
10588 ✗ return -1;
10589
10590 28 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10591 28 value = avio_rb32(s->pb);
10592
10593
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 10 times.
28 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
10594
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
10595
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
10596
10597 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
10598 * not the case) and thus assume "frame number format" instead of QT one.
10599 * No sample with tmcd track can be found with a QT timecode at the moment,
10600 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
10601 * format). */
10602
10603 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
10604 * we multiply the frame number with the quotient.
10605 * See tickets #9492, #9710. */
10606 28 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
10607 /* Work around files where tmcd_nb_frames is rounded down from frame rate
10608 * instead of up. See ticket #5978. */
10609
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 18 times.
28 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
10610
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
10611 10 tmcd_nb_frames = rounded_tc_rate;
10612 28 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
10613
10614 28 parse_timecode_in_framenum_format(s, st, value, flags);
10615
10616 28 avio_seek(sc->pb, cur_pos, SEEK_SET);
10617 28 return 0;
10618 }
10619
10620 1377 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
10621 int i;
10622
3/4
✓ Branch 0 taken 1377 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1364 times.
✓ Branch 3 taken 13 times.
1377 if (!index || !*index) return;
10623
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 13 times.
208 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
10624 195 av_encryption_info_free((*index)->encrypted_samples[i]);
10625 }
10626 13 av_freep(&(*index)->encrypted_samples);
10627 13 av_freep(&(*index)->auxiliary_info_sizes);
10628 13 av_freep(&(*index)->auxiliary_offsets);
10629 13 av_freep(index);
10630 }
10631
10632 845 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
10633 {
10634 845 MOVStreamContext *sc = st->priv_data;
10635
10636
3/4
✓ Branch 0 taken 845 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 793 times.
845 if (!sc || --sc->refcount) {
10637 52 st->priv_data = NULL;
10638 52 return;
10639 }
10640
10641 793 av_freep(&sc->tts_data);
10642
2/2
✓ Branch 0 taken 734 times.
✓ Branch 1 taken 793 times.
1527 for (int i = 0; i < sc->drefs_count; i++) {
10643 734 av_freep(&sc->drefs[i].path);
10644 734 av_freep(&sc->drefs[i].dir);
10645 }
10646 793 av_freep(&sc->drefs);
10647
10648 793 sc->drefs_count = 0;
10649
10650
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 777 times.
793 if (!sc->pb_is_copied)
10651 16 ff_format_io_close(s, &sc->pb);
10652
10653 793 sc->pb = NULL;
10654 793 av_freep(&sc->chunk_offsets);
10655 793 av_freep(&sc->stsc_data);
10656 793 av_freep(&sc->sample_sizes);
10657 793 av_freep(&sc->keyframes);
10658 793 av_freep(&sc->ctts_data);
10659 793 av_freep(&sc->stts_data);
10660 793 av_freep(&sc->sdtp_data);
10661 793 av_freep(&sc->stps_data);
10662 793 av_freep(&sc->elst_data);
10663 793 av_freep(&sc->rap_group);
10664 793 av_freep(&sc->sync_group);
10665 793 av_freep(&sc->sgpd_sync);
10666 793 av_freep(&sc->sample_offsets);
10667 793 av_freep(&sc->open_key_samples);
10668 793 av_freep(&sc->display_matrix);
10669 793 av_freep(&sc->index_ranges);
10670
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 793 times.
825 for (int i = 0; i < sc->nb_tref_tags; i++)
10671 32 av_freep(&sc->tref_tags[i].id);
10672 793 av_freep(&sc->tref_tags);
10673
10674
2/2
✓ Branch 0 taken 734 times.
✓ Branch 1 taken 59 times.
793 if (sc->extradata)
10675
2/2
✓ Branch 0 taken 751 times.
✓ Branch 1 taken 734 times.
1485 for (int i = 0; i < sc->stsd_count; i++)
10676 751 av_free(sc->extradata[i]);
10677 793 av_freep(&sc->extradata);
10678 793 av_freep(&sc->extradata_size);
10679
10680 793 mov_free_encryption_index(&sc->cenc.encryption_index);
10681 793 av_encryption_info_free(sc->cenc.default_encrypted_sample);
10682 793 av_aes_ctr_free(sc->cenc.aes_ctr);
10683
10684 793 av_freep(&sc->stereo3d);
10685 793 av_freep(&sc->spherical);
10686 793 av_freep(&sc->mastering);
10687 793 av_freep(&sc->coll);
10688 793 av_freep(&sc->ambient);
10689
10690 #if CONFIG_IAMFDEC
10691
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 781 times.
793 if (sc->iamf)
10692 12 ff_iamf_read_deinit(sc->iamf);
10693 #endif
10694 793 av_freep(&sc->iamf);
10695 }
10696
10697 618 static int mov_read_close(AVFormatContext *s)
10698 {
10699 618 MOVContext *mov = s->priv_data;
10700 int i, j;
10701
10702
2/2
✓ Branch 0 taken 845 times.
✓ Branch 1 taken 618 times.
1463 for (i = 0; i < s->nb_streams; i++) {
10703 845 AVStream *st = s->streams[i];
10704
10705 845 mov_free_stream_context(s, st);
10706 }
10707
10708 618 av_freep(&mov->dv_demux);
10709 618 avformat_free_context(mov->dv_fctx);
10710 618 mov->dv_fctx = NULL;
10711
10712
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 604 times.
618 if (mov->meta_keys) {
10713
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 14 times.
114 for (i = 1; i < mov->meta_keys_count; i++) {
10714 100 av_freep(&mov->meta_keys[i]);
10715 }
10716 14 av_freep(&mov->meta_keys);
10717 }
10718
10719 618 av_freep(&mov->trex_data);
10720 618 av_freep(&mov->bitrates);
10721
10722
2/2
✓ Branch 0 taken 482 times.
✓ Branch 1 taken 618 times.
1100 for (i = 0; i < mov->frag_index.nb_items; i++) {
10723 482 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
10724
2/2
✓ Branch 0 taken 584 times.
✓ Branch 1 taken 482 times.
1066 for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) {
10725 584 mov_free_encryption_index(&frag[j].encryption_index);
10726 }
10727 482 av_freep(&mov->frag_index.item[i].stream_info);
10728 }
10729 618 av_freep(&mov->frag_index.item);
10730
10731 618 av_freep(&mov->aes_decrypt);
10732 618 av_freep(&mov->chapter_tracks);
10733
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 618 times.
675 for (i = 0; i < mov->nb_heif_item; i++) {
10734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!mov->heif_item[i])
10735 ✗ continue;
10736 57 av_freep(&mov->heif_item[i]->name);
10737 57 av_freep(&mov->heif_item[i]->iref_list);
10738 57 av_freep(&mov->heif_item[i]->icc_profile);
10739 57 av_freep(&mov->heif_item[i]);
10740 }
10741 618 av_freep(&mov->heif_item);
10742
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 618 times.
627 for (i = 0; i < mov->nb_heif_grid; i++) {
10743 9 av_freep(&mov->heif_grid[i].tile_id_list);
10744 9 av_freep(&mov->heif_grid[i].tile_idx_list);
10745 9 av_freep(&mov->heif_grid[i].tile_item_list);
10746 }
10747 618 av_freep(&mov->heif_grid);
10748
10749 618 return 0;
10750 }
10751
10752 28 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
10753 {
10754 int i;
10755
10756
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 for (i = 0; i < s->nb_streams; i++) {
10757 28 AVStream *st = s->streams[i];
10758 28 MOVStreamContext *sc = st->priv_data;
10759 28 MovTref *tag = mov_find_tref_tag(sc, MKTAG('t','m','c','d'));
10760
10761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!tag)
10762 ✗ continue;
10763
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 if (mov_find_tref_id(tag, tmcd_id))
10764 28 return 1;
10765 }
10766 ✗ return 0;
10767 }
10768
10769 /* look for a tmcd track not referenced by any video track, and export it globally */
10770 618 static void export_orphan_timecode(AVFormatContext *s)
10771 {
10772 int i;
10773
10774
2/2
✓ Branch 0 taken 845 times.
✓ Branch 1 taken 618 times.
1463 for (i = 0; i < s->nb_streams; i++) {
10775 845 AVStream *st = s->streams[i];
10776
10777
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 817 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
873 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
10778 28 !tmcd_is_referenced(s, st->id)) {
10779 ✗ AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
10780 ✗ if (tcr) {
10781 ✗ av_dict_set(&s->metadata, "timecode", tcr->value, 0);
10782 ✗ break;
10783 }
10784 }
10785 }
10786 618 }
10787
10788 3 static int read_tfra(MOVContext *mov, AVIOContext *f)
10789 {
10790 int version, fieldlength, i, j;
10791 3 int64_t pos = avio_tell(f);
10792 3 uint32_t size = avio_rb32(f);
10793 unsigned track_id, item_count;
10794
10795
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
10796 1 return 1;
10797 }
10798 2 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
10799
10800 2 version = avio_r8(f);
10801 2 avio_rb24(f);
10802 2 track_id = avio_rb32(f);
10803 2 fieldlength = avio_rb32(f);
10804 2 item_count = avio_rb32(f);
10805
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (i = 0; i < item_count; i++) {
10806 int64_t time, offset;
10807 int index;
10808 MOVFragmentStreamInfo * frag_stream_info;
10809
10810
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (avio_feof(f)) {
10811 ✗ return AVERROR_INVALIDDATA;
10812 }
10813
10814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1) {
10815 ✗ time = avio_rb64(f);
10816 ✗ offset = avio_rb64(f);
10817 } else {
10818 6 time = avio_rb32(f);
10819 6 offset = avio_rb32(f);
10820 }
10821
10822 // The first sample of each stream in a fragment is always a random
10823 // access sample. So it's entry in the tfra can be used as the
10824 // initial PTS of the fragment.
10825 6 index = update_frag_index(mov, offset);
10826 6 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
10827
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (frag_stream_info &&
10828
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
10829 6 frag_stream_info->first_tfra_pts = time;
10830
10831
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
10832 6 avio_r8(f);
10833
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
10834 6 avio_r8(f);
10835
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
10836 6 avio_r8(f);
10837 }
10838
10839 2 avio_seek(f, pos + size, SEEK_SET);
10840 2 return 0;
10841 }
10842
10843 1 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
10844 {
10845 1 int64_t stream_size = avio_size(f);
10846 1 int64_t original_pos = avio_tell(f);
10847 int64_t seek_ret;
10848 1 int ret = -1;
10849
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
10850 ✗ ret = seek_ret;
10851 ✗ goto fail;
10852 }
10853 1 c->mfra_size = avio_rb32(f);
10854 1 c->have_read_mfra_size = 1;
10855
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) {
10856 ✗ av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
10857 ✗ goto fail;
10858 }
10859
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) {
10860 ✗ ret = seek_ret;
10861 ✗ goto fail;
10862 }
10863
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != c->mfra_size) {
10864 ✗ av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
10865 ✗ goto fail;
10866 }
10867
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
10868 ✗ av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
10869 ✗ goto fail;
10870 }
10871 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
10872 do {
10873 3 ret = read_tfra(c, f);
10874
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
10875 ✗ goto fail;
10876
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 } while (!ret);
10877 1 ret = 0;
10878 1 c->frag_index.complete = 1;
10879 1 fail:
10880 1 seek_ret = avio_seek(f, original_pos, SEEK_SET);
10881
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (seek_ret < 0) {
10882 ✗ av_log(c->fc, AV_LOG_ERROR,
10883 "failed to seek back after looking for mfra\n");
10884 ✗ ret = seek_ret;
10885 }
10886 1 return ret;
10887 }
10888
10889 ✗ static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10890 const HEIFItem *item)
10891 {
10892 ✗ AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
10893 AV_PKT_DATA_ICC_PROFILE,
10894 ✗ item->icc_profile_size, 0);
10895 ✗ if (!sd)
10896 ✗ return AVERROR(ENOMEM);
10897
10898 ✗ memcpy(sd->data, item->icc_profile, item->icc_profile_size);
10899
10900 ✗ return 0;
10901 }
10902
10903 6 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10904 const HEIFItem *item)
10905 {
10906 int32_t *matrix;
10907 6 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data,
10908 nb_coded_side_data,
10909 AV_PKT_DATA_DISPLAYMATRIX,
10910 9 * sizeof(*matrix), 0);
10911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sd)
10912 ✗ return AVERROR(ENOMEM);
10913
10914 6 matrix = (int32_t*)sd->data;
10915 /* rotation is in the counter-clockwise direction whereas
10916 * av_display_rotation_set() expects its argument to be
10917 * oriented clockwise, so we need to negate it. */
10918 6 av_display_rotation_set(matrix, -item->rotation);
10919 6 av_display_matrix_flip(matrix, item->hflip, item->vflip);
10920
10921 6 return 0;
10922 }
10923
10924 5 static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid,
10925 AVStreamGroupTileGrid *tile_grid)
10926 {
10927 5 MOVContext *c = s->priv_data;
10928 5 const HEIFItem *item = grid->item;
10929 5 int64_t coded_width = 0, coded_height = 0;
10930 5 int64_t offset = 0, pos = avio_tell(s->pb);
10931 5 int64_t x = 0, y = 0;
10932 5 int i = 0;
10933 int tile_rows, tile_cols;
10934 int flags, size;
10935
10936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10937 ✗ av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
10938 ✗ return AVERROR_PATCHWELCOME;
10939 }
10940
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (item->is_idat_relative) {
10941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!c->idat_offset) {
10942 ✗ av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
10943 ✗ return AVERROR_INVALIDDATA;
10944 }
10945 5 offset = c->idat_offset;
10946 }
10947
10948
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (offset > INT64_MAX - item->extent_offset)
10949 ✗ return AVERROR_INVALIDDATA;
10950
10951 5 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10952
10953 5 avio_r8(s->pb); /* version */
10954 5 flags = avio_r8(s->pb);
10955
10956 5 tile_rows = avio_r8(s->pb) + 1;
10957 5 tile_cols = avio_r8(s->pb) + 1;
10958 /* actual width and height of output image */
10959
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);
10960
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);
10961
10962 5 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
10963 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
10964
10965 5 avio_seek(s->pb, pos, SEEK_SET);
10966
10967 5 size = tile_rows * tile_cols;
10968 5 tile_grid->nb_tiles = grid->nb_tiles;
10969
10970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (tile_grid->nb_tiles != size)
10971 ✗ return AVERROR_INVALIDDATA;
10972
10973
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < tile_cols; i++)
10974 10 coded_width += grid->tile_item_list[i]->width;
10975
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < size; i += tile_cols)
10976 10 coded_height += grid->tile_item_list[i]->height;
10977
10978
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)
10979 ✗ return AVERROR_INVALIDDATA;
10980
10981 5 tile_grid->coded_width = coded_width;
10982 5 tile_grid->coded_height = coded_height;
10983
10984 5 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!tile_grid->offsets)
10986 ✗ return AVERROR(ENOMEM);
10987
10988
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 while (y < tile_grid->coded_height) {
10989 10 int left_col = i;
10990
10991
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 while (x < tile_grid->coded_width) {
10992
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (i == tile_grid->nb_tiles)
10993 ✗ return AVERROR_INVALIDDATA;
10994
10995 20 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10996 20 tile_grid->offsets[i].horizontal = x;
10997 20 tile_grid->offsets[i].vertical = y;
10998
10999 20 x += grid->tile_item_list[i++]->width;
11000 }
11001
11002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (x > tile_grid->coded_width) {
11003 ✗ av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
11004 ✗ return AVERROR_INVALIDDATA;
11005 }
11006
11007 10 x = 0;
11008 10 y += grid->tile_item_list[left_col]->height;
11009 }
11010
11011
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) {
11012 ✗ av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
11013 ✗ return AVERROR_INVALIDDATA;
11014 }
11015
11016 5 return 0;
11017 }
11018
11019 4 static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid,
11020 AVStreamGroupTileGrid *tile_grid)
11021 {
11022 4 MOVContext *c = s->priv_data;
11023 4 const HEIFItem *item = grid->item;
11024 uint16_t canvas_fill_value[4];
11025 4 int64_t offset = 0, pos = avio_tell(s->pb);
11026 4 int ret = 0, flags;
11027
11028
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11029 ✗ av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
11030 ✗ return AVERROR_PATCHWELCOME;
11031 }
11032
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
11033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
11034 ✗ av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
11035 ✗ return AVERROR_INVALIDDATA;
11036 }
11037 4 offset = c->idat_offset;
11038 }
11039
11040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (offset > INT64_MAX - item->extent_offset)
11041 ✗ return AVERROR_INVALIDDATA;
11042
11043 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
11044
11045 4 avio_r8(s->pb); /* version */
11046 4 flags = avio_r8(s->pb);
11047
11048
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
11049 16 canvas_fill_value[i] = avio_rb16(s->pb);
11050 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
11051 4 canvas_fill_value[0], canvas_fill_value[1],
11052 4 canvas_fill_value[2], canvas_fill_value[3]);
11053
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
11054 16 tile_grid->background[i] = canvas_fill_value[i];
11055
11056 /* actual width and height of output image */
11057 4 tile_grid->width =
11058
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);
11059 4 tile_grid->height =
11060
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);
11061
11062 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
11063 tile_grid->width, tile_grid->height);
11064
11065 4 tile_grid->nb_tiles = grid->nb_tiles;
11066 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
11067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
11068 ✗ ret = AVERROR(ENOMEM);
11069 ✗ goto fail;
11070 }
11071
11072
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
11073 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
11074
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);
11075
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);
11076 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
11077 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
11078 8 i, tile_grid->offsets[i].idx,
11079 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
11080 }
11081
11082 4 fail:
11083 4 avio_seek(s->pb, pos, SEEK_SET);
11084
11085 4 return ret;
11086 }
11087
11088 2 static int mov_parse_exif_item(AVFormatContext *s,
11089 AVPacketSideData **coded_side_data, int *nb_coded_side_data,
11090 const HEIFItem *ref)
11091 {
11092 2 MOVContext *c = s->priv_data;
11093 AVPacketSideData *sd;
11094 2 AVExifMetadata ifd = { 0 };
11095 AVBufferRef *buf;
11096 2 int64_t offset = 0, pos = avio_tell(s->pb);
11097 2 unsigned orientation_id = av_exif_get_tag_id("Orientation");
11098 int err;
11099
11100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11101 ✗ av_log(c->fc, AV_LOG_WARNING, "Exif metadata with non seekable input\n");
11102 ✗ return AVERROR_PATCHWELCOME;
11103 }
11104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ref->is_idat_relative) {
11105 ✗ if (!c->idat_offset) {
11106 ✗ av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the Exif metadata\n");
11107 ✗ return AVERROR_INVALIDDATA;
11108 }
11109 ✗ offset = c->idat_offset;
11110 }
11111
11112 2 buf = av_buffer_alloc(ref->extent_length);
11113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!buf)
11114 ✗ return AVERROR(ENOMEM);
11115
11116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset > INT64_MAX - ref->extent_offset) {
11117 ✗ err = AVERROR(ENOMEM);
11118 ✗ goto fail;
11119 }
11120
11121 2 avio_seek(s->pb, ref->extent_offset + offset, SEEK_SET);
11122 2 err = avio_read(s->pb, buf->data, ref->extent_length);
11123
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != ref->extent_length) {
11124 ✗ if (err > 0)
11125 ✗ err = AVERROR_INVALIDDATA;
11126 ✗ goto fail;
11127 }
11128
11129 // HEIF spec states that Exif metadata is informative. The irot item property is
11130 // the normative source of rotation information. So we remove any Orientation tag
11131 // present in the Exif buffer.
11132 2 err = av_exif_parse_buffer(s, buf->data, ref->extent_length, &ifd, AV_EXIF_T_OFF);
11133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0) {
11134 ✗ av_log(s, AV_LOG_ERROR, "Unable to parse Exif metadata\n");
11135 ✗ goto fail;
11136 }
11137
11138 2 err = av_exif_remove_entry(s, &ifd, orientation_id, 0);
11139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11140 ✗ goto fail;
11141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (!err)
11142 ✗ goto finish;
11143
11144 2 av_buffer_unref(&buf);
11145 2 err = av_exif_write(s, &ifd, &buf, AV_EXIF_T_OFF);
11146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11147 ✗ goto fail;
11148
11149 2 finish:
11150 2 offset = AV_RB32(buf->data) + 4;
11151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset >= buf->size) {
11152 ✗ err = AVERROR_INVALIDDATA;
11153 ✗ goto fail;
11154 }
11155 2 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
11156 2 AV_PKT_DATA_EXIF, buf->size - offset, 0);
11157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!sd) {
11158 ✗ err = AVERROR(ENOMEM);
11159 ✗ goto fail;
11160 }
11161 2 memcpy(sd->data, buf->data + offset, buf->size - offset);
11162
11163 2 err = 0;
11164 2 fail:
11165 2 av_buffer_unref(&buf);
11166 2 av_exif_free(&ifd);
11167 2 avio_seek(s->pb, pos, SEEK_SET);
11168
11169 2 return err;
11170 }
11171
11172 9 static int mov_parse_tiles(AVFormatContext *s)
11173 {
11174 9 MOVContext *mov = s->priv_data;
11175
11176
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for (int i = 0; i < mov->nb_heif_grid; i++) {
11177 9 AVStreamGroup *stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
11178 AVStreamGroupTileGrid *tile_grid;
11179 9 const HEIFGrid *grid = &mov->heif_grid[i];
11180 9 int err, loop = 1;
11181
11182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!stg)
11183 ✗ return AVERROR(ENOMEM);
11184
11185 9 stg->id = grid->item->item_id;
11186 9 tile_grid = stg->params.tile_grid;
11187
11188
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9 times.
37 for (int j = 0; j < grid->nb_tiles; j++) {
11189 28 int tile_id = grid->tile_id_list[j];
11190 int k;
11191
11192
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 for (k = 0; k < mov->nb_heif_item; k++) {
11193 60 HEIFItem *item = mov->heif_item[k];
11194 AVStream *st;
11195
11196
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)
11197 32 continue;
11198 28 st = item->st;
11199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!st) {
11200 ✗ av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
11201 "reference a stream\n",
11202 ✗ tile_id, grid->item->item_id);
11203 ✗ ff_remove_stream_group(s, stg);
11204 ✗ loop = 0;
11205 ✗ break;
11206 }
11207
11208 28 grid->tile_item_list[j] = item;
11209 28 grid->tile_idx_list[j] = stg->nb_streams;
11210
11211 28 err = avformat_stream_group_add_stream(stg, st);
11212
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 26 times.
28 if (err < 0) {
11213 int l;
11214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
11215 ✗ return err;
11216
11217
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_streams; l++)
11218
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->streams[l]->index == st->index)
11219 2 break;
11220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_streams);
11221 2 grid->tile_idx_list[j] = l;
11222 }
11223
11224
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 6 times.
28 if (item->item_id != mov->primary_item_id)
11225 22 st->disposition |= AV_DISPOSITION_DEPENDENT;
11226 28 break;
11227 }
11228
11229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (k == mov->nb_heif_item) {
11230 ✗ av_assert0(loop);
11231 ✗ av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
11232 "exist\n",
11233 ✗ tile_id, grid->item->item_id);
11234 ✗ ff_remove_stream_group(s, stg);
11235 ✗ loop = 0;
11236 }
11237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!loop)
11238 ✗ break;
11239 }
11240
11241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!loop)
11242 ✗ continue;
11243
11244
2/3
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
9 switch (grid->item->type) {
11245 5 case MKTAG('g','r','i','d'):
11246 5 err = read_image_grid(s, grid, tile_grid);
11247 5 break;
11248 4 case MKTAG('i','o','v','l'):
11249 4 err = read_image_iovl(s, grid, tile_grid);
11250 4 break;
11251 ✗ default:
11252 ✗ av_assert0(0);
11253 }
11254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err < 0)
11255 ✗ return err;
11256
11257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 for (int j = 0; j < grid->item->nb_iref_list; j++) {
11258 ✗ HEIFItem *ref = get_heif_item(mov, grid->item->iref_list[j].item_id);
11259
11260 ✗ av_assert0(ref);
11261 ✗ switch(ref->type) {
11262 ✗ case MKTAG('E','x','i','f'):
11263 ✗ err = mov_parse_exif_item(s, &tile_grid->coded_side_data,
11264 &tile_grid->nb_coded_side_data, ref);
11265 ✗ if (err < 0 && (s->error_recognition & AV_EF_EXPLODE))
11266 ✗ return err;
11267 ✗ break;
11268 ✗ default:
11269 ✗ break;
11270 }
11271 }
11272
11273 /* rotation */
11274
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) {
11275 ✗ err = set_display_matrix_from_item(&tile_grid->coded_side_data,
11276 ✗ &tile_grid->nb_coded_side_data, grid->item);
11277 ✗ if (err < 0)
11278 ✗ return err;
11279 }
11280
11281 /* ICC profile */
11282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (grid->item->icc_profile_size) {
11283 ✗ err = set_icc_profile_from_item(&tile_grid->coded_side_data,
11284 ✗ &tile_grid->nb_coded_side_data, grid->item);
11285 ✗ if (err < 0)
11286 ✗ return err;
11287 }
11288
11289
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (grid->item->name)
11290 9 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
11291
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 if (grid->item->item_id == mov->primary_item_id)
11292 5 stg->disposition |= AV_DISPOSITION_DEFAULT;
11293 }
11294
11295 9 return 0;
11296 }
11297
11298 18 static int mov_parse_heif_items(AVFormatContext *s)
11299 {
11300 18 MOVContext *mov = s->priv_data;
11301 int err;
11302
11303
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (int i = 0; i < mov->nb_heif_item; i++) {
11304 57 HEIFItem *item = mov->heif_item[i];
11305 MOVStreamContext *sc;
11306 AVStream *st;
11307 57 int64_t offset = 0;
11308
11309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item)
11310 ✗ continue;
11311
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 43 times.
57 if (!item->st) {
11312 14 continue;
11313 }
11314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (item->is_idat_relative) {
11315 ✗ if (!mov->idat_offset) {
11316 ✗ av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
11317 ✗ return AVERROR_INVALIDDATA;
11318 }
11319 ✗ offset = mov->idat_offset;
11320 }
11321
11322 43 st = item->st;
11323 43 sc = st->priv_data;
11324 43 st->codecpar->width = item->width;
11325 43 st->codecpar->height = item->height;
11326
11327 43 sc->sample_size = sc->stsz_sample_size = item->extent_length;
11328 43 sc->sample_count = 1;
11329
11330 43 err = sanity_checks(s, sc, st->index);
11331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (err)
11332 ✗ return AVERROR_INVALIDDATA;
11333
11334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (offset > INT64_MAX - item->extent_offset)
11335 ✗ return AVERROR_INVALIDDATA;
11336
11337 43 sc->chunk_offsets[0] = item->extent_offset + offset;
11338
11339
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 30 times.
43 if (item->item_id == mov->primary_item_id)
11340 13 st->disposition |= AV_DISPOSITION_DEFAULT;
11341
11342
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 43 times.
54 for (int j = 0; j < item->nb_iref_list; j++) {
11343 11 HEIFItem *ref = get_heif_item(mov, item->iref_list[j].item_id);
11344
11345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 av_assert0(ref);
11346
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 switch(ref->type) {
11347 2 case MKTAG('E','x','i','f'):
11348 2 err = mov_parse_exif_item(s, &st->codecpar->coded_side_data,
11349 2 &st->codecpar->nb_coded_side_data, ref);
11350
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))
11351 ✗ return err;
11352 2 break;
11353 9 default:
11354 9 break;
11355 }
11356 }
11357
11358
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) {
11359 6 err = set_display_matrix_from_item(&st->codecpar->coded_side_data,
11360 6 &st->codecpar->nb_coded_side_data, item);
11361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
11362 ✗ return err;
11363 }
11364
11365 43 mov_build_index(mov, st);
11366 }
11367
11368
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (mov->nb_heif_grid) {
11369 9 err = mov_parse_tiles(s);
11370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err < 0)
11371 ✗ return err;
11372 }
11373
11374 18 return 0;
11375 }
11376
11377 618 static int mov_parse_tmcd_streams(AVFormatContext *s)
11378 {
11379 int err;
11380
11381
2/2
✓ Branch 0 taken 845 times.
✓ Branch 1 taken 618 times.
1463 for (int i = 0; i < s->nb_streams; i++) {
11382 AVStreamGroup *stg;
11383 const AVDictionaryEntry *tcr;
11384 845 AVStream *st = s->streams[i];
11385
11386
2/2
✓ Branch 0 taken 817 times.
✓ Branch 1 taken 28 times.
845 if (st->codecpar->codec_tag != MKTAG('t','m','c','d'))
11387 817 continue;
11388
11389 28 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TREF, NULL);
11390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!stg)
11391 ✗ return AVERROR(ENOMEM);
11392
11393 28 stg->id = st->id;
11394 28 tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
11395
11396
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 28 times.
134 for (int j = 0; j < s->nb_streams; j++) {
11397 106 AVStream *st2 = s->streams[j];
11398 106 MOVStreamContext *sc2 = st2->priv_data;
11399 106 MovTref *tag = mov_find_tref_tag(sc2, MKTAG('t','m','c','d'));
11400
11401
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 29 times.
106 if (!tag)
11402 77 continue;
11403
11404
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 29 times.
88 for (int k = 0; k < tag->nb_id; k++) {
11405
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 29 times.
59 if (tag->id[k] != st->id)
11406 30 continue;
11407
11408 29 err = avformat_stream_group_add_stream(stg, st2);
11409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (err < 0)
11410 ✗ return err;
11411
11412
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (tcr)
11413 29 av_dict_set(&st2->metadata, "timecode", tcr->value, AV_DICT_DONT_OVERWRITE);
11414 }
11415 }
11416
11417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!stg->nb_streams) {
11418 ✗ ff_remove_stream_group(s, stg);
11419 ✗ continue;
11420 }
11421
11422 28 err = avformat_stream_group_add_stream(stg, st);
11423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (err < 0)
11424 ✗ return err;
11425
11426 28 stg->params.tref->metadata_index = stg->nb_streams - 1;
11427 }
11428 618 export_orphan_timecode(s);
11429
11430 618 return 0;
11431 }
11432
11433 11 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
11434 uint32_t *tref_id, int nb_tref_id, int first_index)
11435 {
11436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!nb_tref_id)
11437 ✗ return NULL;
11438
11439
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 for (int i = first_index; i < s->nb_streams; i++)
11440
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 for (int j = 0; j < nb_tref_id; j++)
11441
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (s->streams[i]->index != st->index &&
11442
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 s->streams[i]->id == tref_id[j])
11443 11 return s->streams[i];
11444
11445 ✗ return NULL;
11446 }
11447
11448 618 static int mov_parse_cdsc_and_rndr_streams(AVFormatContext *s)
11449 {
11450 static const uint32_t tref_tags[] = {
11451 MKTAG('c','d','s','c'),
11452 MKTAG('r','n','d','r'),
11453 };
11454
11455 int err;
11456
11457 // Don't try to add a group if there's only one track
11458
2/2
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 119 times.
618 if (s->nb_streams <= 1)
11459 499 return 0;
11460
11461
2/2
✓ Branch 0 taken 346 times.
✓ Branch 1 taken 119 times.
465 for (int i = 0; i < s->nb_streams; i++) {
11462 346 AVStream *st = s->streams[i];
11463 346 MOVStreamContext *sc = st->priv_data;
11464
11465
2/2
✓ Branch 0 taken 692 times.
✓ Branch 1 taken 346 times.
1038 for (int c = 0; c < FF_ARRAY_ELEMS(tref_tags); c++) {
11466 AVStreamGroup *stg;
11467 AVStream *st_ref;
11468 692 MovTref *tag = mov_find_tref_tag(sc, tref_tags[c]);
11469
11470
2/2
✓ Branch 0 taken 681 times.
✓ Branch 1 taken 11 times.
692 if (!tag)
11471 681 continue;
11472
11473 11 st_ref = mov_find_reference_track(s, st, tag->id, tag->nb_id, 0);
11474
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!st_ref) {
11475 ✗ av_log(s, AV_LOG_WARNING, "Failed to find referenced stream\n");
11476 ✗ continue;
11477 }
11478
11479 11 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TREF, NULL);
11480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!stg)
11481 ✗ return AVERROR(ENOMEM);
11482
11483 11 stg->id = st_ref->id;
11484
11485 11 err = avformat_stream_group_add_stream(stg, st_ref);
11486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11487 ✗ return err;
11488
11489 11 err = avformat_stream_group_add_stream(stg, st);
11490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11491 ✗ return err;
11492
11493 11 stg->params.tref->metadata_index = stg->nb_streams - 1;
11494 }
11495 }
11496
11497 119 return 0;
11498 }
11499
11500 618 static int mov_parse_lcevc_streams(AVFormatContext *s)
11501 {
11502 int err;
11503
11504 // Don't try to add a group if there's only one track
11505
2/2
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 119 times.
618 if (s->nb_streams <= 1)
11506 499 return 0;
11507
11508
2/2
✓ Branch 0 taken 346 times.
✓ Branch 1 taken 119 times.
465 for (int i = 0; i < s->nb_streams; i++) {
11509 AVStreamGroup *stg;
11510 346 AVStream *st = s->streams[i];
11511 AVStream *st_base;
11512 346 MOVStreamContext *sc = st->priv_data;
11513 346 MovTref *tag = mov_find_tref_tag(sc, MKTAG('s','b','a','s'));
11514 346 int j = 0;
11515
11516 /* Find an enhancement stream. */
11517
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)
11518 346 continue;
11519
11520 ✗ stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
11521 ✗ if (!stg)
11522 ✗ return AVERROR(ENOMEM);
11523
11524 ✗ stg->id = st->id;
11525 ✗ stg->params.layered_video->width = st->codecpar->width;
11526 ✗ stg->params.layered_video->height = st->codecpar->height;
11527
11528 ✗ while (st_base = mov_find_reference_track(s, st, tag->id, tag->nb_id, j)) {
11529 ✗ err = avformat_stream_group_add_stream(stg, st_base);
11530 ✗ if (err < 0)
11531 ✗ return err;
11532
11533 ✗ j = st_base->index + 1;
11534 }
11535 ✗ if (!j) {
11536 ✗ int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
11537 ✗ av_log(s, loglevel, "Failed to find base stream for LCEVC stream\n");
11538 ✗ ff_remove_stream_group(s, stg);
11539 ✗ if (s->error_recognition & AV_EF_EXPLODE)
11540 ✗ return AVERROR_INVALIDDATA;
11541 ✗ continue;
11542 }
11543
11544 ✗ err = avformat_stream_group_add_stream(stg, st);
11545 ✗ if (err < 0)
11546 ✗ return err;
11547
11548 ✗ stg->params.layered_video->el_index = stg->nb_streams - 1;
11549 }
11550
11551 119 return 0;
11552 }
11553
11554 618 static int mov_parse_dovi_streams(AVFormatContext *s)
11555 {
11556 int err;
11557
11558
2/2
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 119 times.
618 if (s->nb_streams <= 1)
11559 499 return 0;
11560
11561 /* Identify legacy dual-track Dolby Vision profile 7 carriage per Annex
11562 * C of "Dolby Vision Streams Within the ISO Base Media File Format",
11563 * v2.7.1. The 'vdep' track reference type is shared with depth video
11564 * and multi-view dependencies. The spec-mandated DV-specific sample
11565 * entry combined with the dvcC configuration record disambiguates
11566 * those uses. */
11567
2/2
✓ Branch 0 taken 346 times.
✓ Branch 1 taken 119 times.
465 for (int i = 0; i < s->nb_streams; i++) {
11568 AVStreamGroup *stg;
11569 346 AVStream *st = s->streams[i];
11570 AVStream *st_base;
11571 346 MOVStreamContext *sc = st->priv_data;
11572 346 MovTref *tag = mov_find_tref_tag(sc, MKTAG('v','d','e','p'));
11573 const AVPacketSideData *sd;
11574 const AVDOVIDecoderConfigurationRecord *dovi;
11575
11576
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)
11577 346 continue;
11578
11579 ✗ if (st->codecpar->codec_tag != MKTAG('d','v','h','e') &&
11580 ✗ st->codecpar->codec_tag != MKTAG('d','v','h','1'))
11581 ✗ continue;
11582
11583 ✗ sd = av_packet_side_data_get(st->codecpar->coded_side_data,
11584 ✗ st->codecpar->nb_coded_side_data,
11585 AV_PKT_DATA_DOVI_CONF);
11586 ✗ if (!sd)
11587 ✗ continue;
11588 ✗ dovi = (const AVDOVIDecoderConfigurationRecord *)sd->data;
11589
11590 /* EL track of a dual-track stream: rpu_present_flag = 1,
11591 * el_present_flag = 1, bl_present_flag = 0, dv_profile = 7. */
11592 ✗ if (dovi->dv_profile != 7 || !dovi->rpu_present_flag ||
11593 ✗ !dovi->el_present_flag || dovi->bl_present_flag)
11594 ✗ continue;
11595
11596 ✗ st_base = mov_find_reference_track(s, st, tag->id, tag->nb_id, 0);
11597 ✗ if (!st_base) {
11598 ✗ int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
11599 ✗ av_log(s, loglevel, "Failed to find base layer for Dolby Vision EL stream\n");
11600 ✗ if (s->error_recognition & AV_EF_EXPLODE)
11601 ✗ return AVERROR_INVALIDDATA;
11602 ✗ continue;
11603 }
11604
11605 ✗ stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_DOLBY_VISION, NULL);
11606 ✗ if (!stg)
11607 ✗ return AVERROR(ENOMEM);
11608
11609 ✗ stg->id = st->id;
11610
11611 ✗ err = avformat_stream_group_add_stream(stg, st_base);
11612 ✗ if (err < 0)
11613 ✗ return err;
11614
11615 ✗ err = avformat_stream_group_add_stream(stg, st);
11616 ✗ if (err < 0)
11617 ✗ return err;
11618
11619 ✗ stg->params.layered_video->el_index = stg->nb_streams - 1;
11620 ✗ stg->params.layered_video->width = st_base->codecpar->width;
11621 ✗ stg->params.layered_video->height = st_base->codecpar->height;
11622 }
11623
11624 119 return 0;
11625 }
11626
11627 618 static void fix_stream_ids(AVFormatContext *s)
11628 {
11629 618 int highest_id = 0, lowest_iamf_id = INT_MAX;
11630
11631
2/2
✓ Branch 0 taken 845 times.
✓ Branch 1 taken 618 times.
1463 for (int i = 0; i < s->nb_streams; i++) {
11632 845 const AVStream *st = s->streams[i];
11633 845 const MOVStreamContext *sc = st->priv_data;
11634
2/2
✓ Branch 0 taken 781 times.
✓ Branch 1 taken 64 times.
845 if (!sc->iamf)
11635 781 highest_id = FFMAX(highest_id, st->id);
11636 }
11637
11638
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 618 times.
690 for (int i = 0; i < s->nb_stream_groups; i++) {
11639 72 AVStreamGroup *stg = s->stream_groups[i];
11640
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 12 times.
72 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
11641 60 continue;
11642
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_streams; j++) {
11643 64 AVStream *st = stg->streams[j];
11644 64 lowest_iamf_id = FFMIN(lowest_iamf_id, st->id);
11645 }
11646 }
11647
11648
2/2
✓ Branch 0 taken 610 times.
✓ Branch 1 taken 8 times.
618 if (highest_id < lowest_iamf_id)
11649 610 return;
11650
11651 8 highest_id += !lowest_iamf_id;
11652
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++) {
11653 4 AVStreamGroup *stg = s->stream_groups[i];
11654
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
11655 2 continue;
11656
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_streams; j++) {
11657 14 AVStream *st = stg->streams[j];
11658 14 MOVStreamContext *sc = st->priv_data;
11659 14 st->id += highest_id;
11660 14 sc->iamf_stream_offset = highest_id;
11661 }
11662 }
11663 }
11664
11665 618 static int mov_read_header(AVFormatContext *s)
11666 {
11667 618 MOVContext *mov = s->priv_data;
11668 618 AVIOContext *pb = s->pb;
11669 int j, err;
11670 618 MOVAtom atom = { AV_RL32("root") };
11671 int i;
11672
11673 618 mov->fc = s;
11674 618 mov->trak_index = -1;
11675 618 mov->primary_item_id = -1;
11676 618 mov->cur_item_id = -1;
11677 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
11678
2/2
✓ Branch 0 taken 617 times.
✓ Branch 1 taken 1 times.
618 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
11679 617 atom.size = avio_size(pb);
11680 else
11681 1 atom.size = INT64_MAX;
11682
11683 /* check MOV header */
11684 do {
11685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 618 times.
618 if (mov->moov_retry)
11686 ✗ avio_seek(pb, 0, SEEK_SET);
11687
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 618 times.
618 if ((err = mov_read_default(mov, pb, atom)) < 0) {
11688 ✗ av_log(s, AV_LOG_ERROR, "error reading header\n");
11689 ✗ return err;
11690 }
11691 1235 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
11692
6/10
✓ Branch 0 taken 617 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 599 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.
618 !mov->found_moov && (!mov->found_iloc || !mov->found_iinf) && !mov->moov_retry++);
11693
3/6
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 600 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
618 if (!mov->found_moov && !mov->found_iloc && !mov->found_iinf) {
11694 ✗ av_log(s, AV_LOG_ERROR, "moov atom not found\n");
11695 ✗ return AVERROR_INVALIDDATA;
11696 }
11697 618 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
11698
11699
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 600 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
618 if (mov->found_iloc && mov->found_iinf) {
11700 18 err = mov_parse_heif_items(s);
11701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (err < 0)
11702 ✗ return err;
11703 }
11704 // prevent iloc and iinf boxes from being parsed while reading packets.
11705 // this is needed because an iinf box may have been parsed but ignored
11706 // for having old infe boxes which create no streams.
11707 618 mov->found_iloc = mov->found_iinf = 1;
11708
11709
2/2
✓ Branch 0 taken 617 times.
✓ Branch 1 taken 1 times.
618 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
11710
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 615 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
617 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
11711 2 mov_read_chapters(s);
11712
2/2
✓ Branch 0 taken 844 times.
✓ Branch 1 taken 617 times.
1461 for (i = 0; i < s->nb_streams; i++)
11713
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 816 times.
844 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
11714 28 mov_read_timecode_track(s, s->streams[i]);
11715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 816 times.
816 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
11716 ✗ mov_read_rtmd_track(s, s->streams[i]);
11717 }
11718 }
11719
11720 /* Create metadata stream groups. */
11721 618 err = mov_parse_cdsc_and_rndr_streams(s);
11722
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 618 times.
618 if (err < 0)
11723 ✗ return err;
11724
11725 /* copy timecode metadata from tmcd tracks to the related video streams */
11726 618 err = mov_parse_tmcd_streams(s);
11727
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 618 times.
618 if (err < 0)
11728 ✗ return err;
11729
11730 /* Create LCEVC stream groups. */
11731 618 err = mov_parse_lcevc_streams(s);
11732
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 618 times.
618 if (err < 0)
11733 ✗ return err;
11734
11735 /* Create Dolby Vision Profile 7 stream groups. */
11736 618 err = mov_parse_dovi_streams(s);
11737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 618 times.
618 if (err < 0)
11738 ✗ return err;
11739
11740
2/2
✓ Branch 0 taken 845 times.
✓ Branch 1 taken 618 times.
1463 for (i = 0; i < s->nb_streams; i++) {
11741 845 AVStream *st = s->streams[i];
11742 845 FFStream *const sti = ffstream(st);
11743 845 MOVStreamContext *sc = st->priv_data;
11744 845 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
11745 845 fix_timescale(mov, sc);
11746
11747 /* Set the primary extradata based on the first Sample if it doesn't reference the first stsd entry. */
11748
6/6
✓ Branch 0 taken 796 times.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 753 times.
✓ Branch 3 taken 43 times.
✓ Branch 4 taken 689 times.
✓ Branch 5 taken 64 times.
845 if (sc->stsc_count && sc->extradata_size && !sc->iamf &&
11749
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 686 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
689 sc->stsc_data[0].id > 1 && sc->stsc_data[0].id <= sc->stsd_count) {
11750 3 sc->last_stsd_index = sc->stsc_data[0].id - 1;
11751 3 av_freep(&st->codecpar->extradata);
11752 3 st->codecpar->extradata_size = sc->extradata_size[sc->last_stsd_index];
11753
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (sc->extradata_size[sc->last_stsd_index]) {
11754 3 st->codecpar->extradata = av_mallocz(sc->extradata_size[sc->last_stsd_index] + AV_INPUT_BUFFER_PADDING_SIZE);
11755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata)
11756 ✗ return AVERROR(ENOMEM);
11757 3 memcpy(st->codecpar->extradata, sc->extradata[sc->last_stsd_index], sc->extradata_size[sc->last_stsd_index]);
11758 }
11759 }
11760
11761
2/2
✓ Branch 0 taken 347 times.
✓ Branch 1 taken 498 times.
845 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
11762
2/2
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 195 times.
347 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
11763 152 sti->skip_samples = st->codecpar->initial_padding;
11764 }
11765
5/6
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 413 times.
✓ Branch 2 taken 373 times.
✓ Branch 3 taken 59 times.
✓ Branch 4 taken 373 times.
✗ Branch 5 not taken.
845 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
11766 373 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
11767 373 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
11768
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 833 times.
845 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
11769
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) {
11770 8 st->codecpar->width = sc->width;
11771 8 st->codecpar->height = sc->height;
11772 }
11773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
11774 ✗ st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
11775
11776 ✗ for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
11777 ✗ dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
11778
11779 ✗ err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
11780 ✗ if (err < 0)
11781 ✗ return err;
11782
11783 ✗ av_freep(&st->codecpar->extradata);
11784 ✗ st->codecpar->extradata_size = 0;
11785
11786 ✗ err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
11787 st->codecpar);
11788 ✗ if (err < 0)
11789 ✗ return err;
11790 }
11791 }
11792
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 844 times.
845 if (mov->handbrake_version &&
11793
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
11794 ✗ st->codecpar->codec_id == AV_CODEC_ID_MP3) {
11795 ✗ av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
11796 ✗ sti->need_parsing = AVSTREAM_PARSE_FULL;
11797 }
11798 }
11799
11800
3/4
✓ Branch 0 taken 595 times.
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 595 times.
618 if (mov->trex_data || mov->use_mfra_for > 0) {
11801
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 23 times.
55 for (i = 0; i < s->nb_streams; i++) {
11802 32 AVStream *st = s->streams[i];
11803 32 MOVStreamContext *sc = st->priv_data;
11804
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 4 times.
32 if (sc->duration_for_fps > 0) {
11805 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
11806 28 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
11807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (st->codecpar->bit_rate == INT64_MIN) {
11808 ✗ av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
11809 sc->data_size, sc->time_scale);
11810 ✗ st->codecpar->bit_rate = 0;
11811 ✗ if (s->error_recognition & AV_EF_EXPLODE)
11812 ✗ return AVERROR_INVALIDDATA;
11813 }
11814 }
11815 }
11816 }
11817
11818
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 618 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
618 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
11819 ✗ if (mov->bitrates[i]) {
11820 ✗ s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
11821 }
11822 }
11823
11824 618 ff_rfps_calculate(s);
11825
11826
2/2
✓ Branch 0 taken 845 times.
✓ Branch 1 taken 618 times.
1463 for (i = 0; i < s->nb_streams; i++) {
11827 845 AVStream *st = s->streams[i];
11828 845 MOVStreamContext *sc = st->priv_data;
11829
11830
3/3
✓ Branch 0 taken 347 times.
✓ Branch 1 taken 432 times.
✓ Branch 2 taken 66 times.
845 switch (st->codecpar->codec_type) {
11831 347 case AVMEDIA_TYPE_AUDIO:
11832 347 err = ff_replaygain_export(st, s->metadata);
11833
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 347 times.
347 if (err < 0)
11834 ✗ return err;
11835 347 break;
11836 432 case AVMEDIA_TYPE_VIDEO:
11837
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 424 times.
432 if (sc->display_matrix) {
11838
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,
11839 AV_PKT_DATA_DISPLAYMATRIX,
11840 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
11841 ✗ return AVERROR(ENOMEM);
11842
11843 8 sc->display_matrix = NULL;
11844 }
11845
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 426 times.
432 if (sc->stereo3d) {
11846
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,
11847 AV_PKT_DATA_STEREO3D,
11848 6 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
11849 ✗ return AVERROR(ENOMEM);
11850
11851 6 sc->stereo3d = NULL;
11852 }
11853
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 428 times.
432 if (sc->spherical) {
11854
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,
11855 AV_PKT_DATA_SPHERICAL,
11856 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
11857 ✗ return AVERROR(ENOMEM);
11858
11859 4 sc->spherical = NULL;
11860 }
11861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 432 times.
432 if (sc->mastering) {
11862 ✗ if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11863 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
11864 ✗ (uint8_t *)sc->mastering, sc->mastering_size, 0))
11865 ✗ return AVERROR(ENOMEM);
11866
11867 ✗ sc->mastering = NULL;
11868 }
11869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 432 times.
432 if (sc->coll) {
11870 ✗ if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11871 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
11872 ✗ (uint8_t *)sc->coll, sc->coll_size, 0))
11873 ✗ return AVERROR(ENOMEM);
11874
11875 ✗ sc->coll = NULL;
11876 }
11877
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 428 times.
432 if (sc->ambient) {
11878
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,
11879 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
11880 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
11881 ✗ return AVERROR(ENOMEM);
11882
11883 4 sc->ambient = NULL;
11884 }
11885 432 break;
11886 }
11887 }
11888
11889 618 fix_stream_ids(s);
11890
11891 618 ff_configure_buffers_for_index(s, AV_TIME_BASE);
11892
11893
2/2
✓ Branch 0 taken 482 times.
✓ Branch 1 taken 618 times.
1100 for (i = 0; i < mov->frag_index.nb_items; i++)
11894
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 10 times.
482 if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset)
11895 472 mov->frag_index.item[i].headers_read = 1;
11896
11897 618 return 0;
11898 }
11899
11900 117910 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
11901 {
11902 117910 AVIndexEntry *sample = NULL;
11903 117910 int64_t best_dts = INT64_MAX;
11904 int i;
11905 117910 MOVContext *mov = s->priv_data;
11906
3/4
✓ Branch 0 taken 117910 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 117865 times.
117910 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
11907
2/2
✓ Branch 0 taken 151944 times.
✓ Branch 1 taken 117910 times.
269854 for (i = 0; i < s->nb_streams; i++) {
11908 151944 AVStream *avst = s->streams[i];
11909 151944 FFStream *const avsti = ffstream(avst);
11910 151944 MOVStreamContext *msc = avst->priv_data;
11911
4/4
✓ Branch 0 taken 142427 times.
✓ Branch 1 taken 9517 times.
✓ Branch 2 taken 138912 times.
✓ Branch 3 taken 3515 times.
151944 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
11912 138912 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
11913 138912 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
11914
2/2
✓ Branch 0 taken 123636 times.
✓ Branch 1 taken 15276 times.
138912 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
11915 138912 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
11916
3/6
✓ Branch 0 taken 21588 times.
✓ Branch 1 taken 117324 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 21588 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
138912 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
11917
1/2
✓ Branch 0 taken 21588 times.
✗ Branch 1 not taken.
21588 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
11918
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 21588 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 21588 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 21588 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19394 times.
✓ Branch 9 taken 2194 times.
21588 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
11919
4/4
✓ Branch 0 taken 11286 times.
✓ Branch 1 taken 8108 times.
✓ Branch 2 taken 2194 times.
✓ Branch 3 taken 11286 times.
21588 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
11920
3/4
✓ Branch 0 taken 761 times.
✓ Branch 1 taken 1433 times.
✓ Branch 2 taken 761 times.
✗ Branch 3 not taken.
2194 (dtsdiff > AV_TIME_BASE && dts < best_dts && mov->interleaved_read)))))) {
11921 126193 sample = current_sample;
11922 126193 best_dts = dts;
11923 126193 *st = avst;
11924 }
11925 }
11926 }
11927 117910 return sample;
11928 }
11929
11930 11 static int should_retry(AVIOContext *pb, int error_code) {
11931
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
11 if (error_code == AVERROR_EOF || avio_feof(pb))
11932 11 return 0;
11933
11934 ✗ return 1;
11935 }
11936
11937 49 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
11938 {
11939 int ret;
11940 49 MOVContext *mov = s->priv_data;
11941
11942
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)
11943 1 target = mov->frag_index.item[index].moof_offset;
11944
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) {
11945 ✗ av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
11946 ✗ return AVERROR_INVALIDDATA;
11947 }
11948
11949 49 mov->next_root_atom = 0;
11950
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)
11951 48 index = search_frag_moof_offset(&mov->frag_index, target);
11952
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 &&
11953
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 mov->frag_index.item[index].moof_offset == target) {
11954
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 4 times.
42 if (index + 1 < mov->frag_index.nb_items)
11955 38 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11956
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 6 times.
42 if (mov->frag_index.item[index].headers_read)
11957 36 return 0;
11958 6 mov->frag_index.item[index].headers_read = 1;
11959 }
11960
11961 13 mov->found_mdat = 0;
11962
11963 13 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
11964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (ret < 0)
11965 ✗ return ret;
11966
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 6 times.
13 if (avio_feof(s->pb))
11967 7 return AVERROR_EOF;
11968 6 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
11969
11970 6 return 1;
11971 }
11972
11973 17 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
11974 {
11975 17 MOVStreamContext *sc = st->priv_data;
11976 uint8_t *side, *extradata;
11977 int extradata_size;
11978
11979 /* Save the current index. */
11980 17 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
11981
11982 /* Notify the decoder that extradata changed. */
11983 17 extradata_size = sc->extradata_size[sc->last_stsd_index];
11984 17 extradata = sc->extradata[sc->last_stsd_index];
11985
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) {
11986 14 side = av_packet_new_side_data(pkt,
11987 AV_PKT_DATA_NEW_EXTRADATA,
11988 extradata_size);
11989
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!side)
11990 ✗ return AVERROR(ENOMEM);
11991 14 memcpy(side, extradata, extradata_size);
11992 }
11993
11994 17 return 0;
11995 }
11996
11997 ✗ static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
11998 {
11999 /* We can't make assumptions about the structure of the payload,
12000 because it may include multiple cdat and cdt2 samples. */
12001 ✗ const uint32_t cdat = AV_RB32("cdat");
12002 ✗ const uint32_t cdt2 = AV_RB32("cdt2");
12003 ✗ int ret, out_size = 0;
12004
12005 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
12006 ✗ if (src_size < 10)
12007 ✗ return AVERROR_INVALIDDATA;
12008
12009 /* avoid an int overflow: */
12010 ✗ if ((src_size - 8) / 2 >= INT_MAX / 3)
12011 ✗ return AVERROR_INVALIDDATA;
12012
12013 ✗ ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
12014 ✗ if (ret < 0)
12015 ✗ return ret;
12016
12017 /* parse and re-format the c608 payload in one pass. */
12018 ✗ while (src_size >= 10) {
12019 ✗ const uint32_t atom_size = avio_rb32(pb);
12020 ✗ const uint32_t atom_type = avio_rb32(pb);
12021 ✗ const uint32_t data_size = atom_size - 8;
12022 ✗ const uint8_t cc_field =
12023 atom_type == cdat ? 1 :
12024 atom_type == cdt2 ? 2 :
12025 0;
12026
12027 /* account for bytes consumed for atom size and type. */
12028 ✗ src_size -= 8;
12029
12030 /* make sure the data size stays within the buffer boundaries. */
12031 ✗ if (data_size < 2 || data_size > src_size) {
12032 ✗ ret = AVERROR_INVALIDDATA;
12033 ✗ break;
12034 }
12035
12036 /* make sure the data size is consistent with N byte pairs. */
12037 ✗ if (data_size % 2 != 0) {
12038 ✗ ret = AVERROR_INVALIDDATA;
12039 ✗ break;
12040 }
12041
12042 ✗ if (!cc_field) {
12043 /* neither cdat or cdt2 ... skip it */
12044 ✗ avio_skip(pb, data_size);
12045 ✗ src_size -= data_size;
12046 ✗ continue;
12047 }
12048
12049 ✗ for (uint32_t i = 0; i < data_size; i += 2) {
12050 ✗ pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
12051 ✗ pkt->data[out_size + 1] = avio_r8(pb);
12052 ✗ pkt->data[out_size + 2] = avio_r8(pb);
12053 ✗ out_size += 3;
12054 ✗ src_size -= 2;
12055 }
12056 }
12057
12058 ✗ if (src_size > 0)
12059 /* skip any remaining unread portion of the input payload */
12060 ✗ avio_skip(pb, src_size);
12061
12062 ✗ av_shrink_packet(pkt, out_size);
12063 ✗ return ret;
12064 }
12065
12066 117277 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
12067 int64_t current_index, AVPacket *pkt)
12068 {
12069 117277 MOVContext *mov = s->priv_data;
12070 117277 MOVStreamContext *sc = st->priv_data;
12071
12072 117277 pkt->stream_index = sc->ffindex;
12073 117277 pkt->dts = sample->timestamp;
12074
2/2
✓ Branch 0 taken 299 times.
✓ Branch 1 taken 116978 times.
117277 if (sample->flags & AVINDEX_DISCARD_FRAME) {
12075 299 pkt->flags |= AV_PKT_FLAG_DISCARD;
12076 }
12077
4/4
✓ Branch 0 taken 97422 times.
✓ Branch 1 taken 19855 times.
✓ Branch 2 taken 97410 times.
✓ Branch 3 taken 12 times.
117277 if (sc->stts_count && sc->tts_index < sc->tts_count)
12078 97410 pkt->duration = sc->tts_data[sc->tts_index].duration;
12079
3/4
✓ Branch 0 taken 4616 times.
✓ Branch 1 taken 112661 times.
✓ Branch 2 taken 4616 times.
✗ Branch 3 not taken.
117277 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
12080 4616 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
12081 } else {
12082
2/2
✓ Branch 0 taken 15801 times.
✓ Branch 1 taken 96860 times.
112661 if (pkt->duration == 0) {
12083 15801 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
12084
2/2
✓ Branch 0 taken 15706 times.
✓ Branch 1 taken 95 times.
15801 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
12085
2/2
✓ Branch 0 taken 15755 times.
✓ Branch 1 taken 46 times.
15801 if (next_dts >= pkt->dts)
12086 15755 pkt->duration = next_dts - pkt->dts;
12087 }
12088 112661 pkt->pts = pkt->dts;
12089 }
12090
12091
4/4
✓ Branch 0 taken 98582 times.
✓ Branch 1 taken 18695 times.
✓ Branch 2 taken 98495 times.
✓ Branch 3 taken 87 times.
117277 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && !mov->fragment.found_tfhd &&
12092
2/2
✓ Branch 1 taken 233 times.
✓ Branch 2 taken 98262 times.
98495 sc->current_sample >= ffstream(st)->nb_index_entries) {
12093 233 int64_t pts = av_rescale_q(pkt->pts, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12094 233 int64_t total = av_rescale_q(st->duration, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12095 233 int64_t duration = pkt->duration;
12096
12097
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 231 times.
233 if (st->duration < pkt->pts) {
12098 2 duration = 0;
12099 } else
12100 231 duration = FFMIN(duration, (uint64_t)st->duration - pkt->pts);
12101
12102 233 duration = av_rescale_q(duration, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12103
12104
2/2
✓ Branch 1 taken 194 times.
✓ Branch 2 taken 39 times.
233 if (!ffstream(st)->first_discard_sample)
12105 194 ffstream(st)->first_discard_sample = av_sat_add64(pts, duration);
12106
2/2
✓ Branch 1 taken 194 times.
✓ Branch 2 taken 39 times.
233 if (!ffstream(st)->last_discard_sample)
12107 194 ffstream(st)->last_discard_sample = total;
12108 }
12109
12110
4/4
✓ Branch 0 taken 97422 times.
✓ Branch 1 taken 19855 times.
✓ Branch 2 taken 97410 times.
✓ Branch 3 taken 12 times.
117277 if (sc->tts_data && sc->tts_index < sc->tts_count) {
12111 /* update tts context */
12112 97410 sc->tts_sample++;
12113
1/2
✓ Branch 0 taken 97410 times.
✗ Branch 1 not taken.
97410 if (sc->tts_index < sc->tts_count &&
12114
1/2
✓ Branch 0 taken 97410 times.
✗ Branch 1 not taken.
97410 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
12115 97410 sc->tts_index++;
12116 97410 sc->tts_sample = 0;
12117 }
12118 }
12119
12120
4/4
✓ Branch 0 taken 1044 times.
✓ Branch 1 taken 116233 times.
✓ Branch 2 taken 912 times.
✓ Branch 3 taken 132 times.
117277 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
12121 912 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
12122 912 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
12123
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 598 times.
912 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
12124 }
12125 117277 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
12126 117277 pkt->pos = sample->pos;
12127
12128 /* Multiple stsd handling. */
12129
2/2
✓ Branch 0 taken 113888 times.
✓ Branch 1 taken 3389 times.
117277 if (sc->stsc_data) {
12130
1/2
✓ Branch 0 taken 113888 times.
✗ Branch 1 not taken.
113888 if (sc->stsc_data[sc->stsc_index].id > 0 &&
12131
2/2
✓ Branch 0 taken 113845 times.
✓ Branch 1 taken 43 times.
113888 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
12132
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 113828 times.
113845 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
12133 17 int ret = mov_change_extradata(st, pkt);
12134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (ret < 0)
12135 ✗ return ret;
12136 }
12137
12138 /* Update the stsc index for the next sample */
12139 113888 sc->stsc_sample++;
12140
2/2
✓ Branch 1 taken 56824 times.
✓ Branch 2 taken 57064 times.
113888 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
12141
2/2
✓ Branch 1 taken 1212 times.
✓ Branch 2 taken 55612 times.
56824 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
12142 1212 sc->stsc_index++;
12143 1212 sc->stsc_sample = 0;
12144 }
12145 }
12146
12147 117277 return 0;
12148 }
12149
12150 108644 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
12151 {
12152 108644 MOVContext *mov = s->priv_data;
12153 MOVStreamContext *sc;
12154 AVIndexEntry *sample;
12155 108644 AVStream *st = NULL;
12156 108644 FFStream *avsti = NULL;
12157 int64_t current_index;
12158 int ret;
12159 int i;
12160 108644 mov->fc = s;
12161 9266 retry:
12162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117910 times.
117910 if (s->pb->pos == 0) {
12163
12164 // Discard current fragment index
12165 ✗ if (mov->frag_index.allocated_size > 0) {
12166 ✗ for(int i = 0; i < mov->frag_index.nb_items; i++) {
12167 ✗ av_freep(&mov->frag_index.item[i].stream_info);
12168 }
12169 ✗ av_freep(&mov->frag_index.item);
12170 ✗ mov->frag_index.nb_items = 0;
12171 ✗ mov->frag_index.allocated_size = 0;
12172 ✗ mov->frag_index.current = -1;
12173 ✗ mov->frag_index.complete = 0;
12174 }
12175
12176 ✗ for (i = 0; i < s->nb_streams; i++) {
12177 ✗ AVStream *avst = s->streams[i];
12178 ✗ MOVStreamContext *msc = avst->priv_data;
12179
12180 // Clear current sample
12181 ✗ mov_current_sample_set(msc, 0);
12182 ✗ msc->tts_index = 0;
12183
12184 // Discard current index entries
12185 ✗ avsti = ffstream(avst);
12186 ✗ if (avsti->index_entries_allocated_size > 0) {
12187 ✗ av_freep(&avsti->index_entries);
12188 ✗ avsti->index_entries_allocated_size = 0;
12189 ✗ avsti->nb_index_entries = 0;
12190 }
12191 }
12192
12193 ✗ if ((ret = mov_switch_root(s, -1, -1)) < 0)
12194 ✗ return ret;
12195 }
12196 117910 sample = mov_find_next_sample(s, &st);
12197
6/6
✓ Branch 0 taken 117324 times.
✓ Branch 1 taken 586 times.
✓ Branch 2 taken 648 times.
✓ Branch 3 taken 116676 times.
✓ Branch 4 taken 36 times.
✓ Branch 5 taken 612 times.
117910 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
12198
2/2
✓ Branch 0 taken 574 times.
✓ Branch 1 taken 48 times.
622 if (!mov->next_root_atom)
12199 574 return AVERROR_EOF;
12200
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)
12201 7 return ret;
12202 41 goto retry;
12203 }
12204 117288 sc = st->priv_data;
12205 /* must be done just before reading, to avoid infinite loop on sample */
12206 117288 current_index = sc->current_index;
12207 117288 mov_current_sample_inc(sc);
12208
12209
2/2
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 116676 times.
117288 if (mov->next_root_atom) {
12210 612 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
12211 612 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
12212 }
12213
12214
4/4
✓ Branch 0 taken 9235 times.
✓ Branch 1 taken 108053 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 9225 times.
117288 if (st->discard != AVDISCARD_ALL || sc->iamf) {
12215 108063 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
12216
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 108056 times.
108063 if (ret64 != sample->pos) {
12217 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
12218 sc->ffindex, sample->pos);
12219
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
12220 ✗ mov_current_sample_dec(sc);
12221
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
12222 7 return (int)ret64;
12223 }
12224 ✗ return AVERROR_INVALIDDATA;
12225 }
12226
12227
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 108056 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
108056 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
12228 ✗ av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
12229 ✗ goto retry;
12230 }
12231
12232
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 108056 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
108056 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
12233 ✗ ret = get_eia608_packet(sc->pb, pkt, sample->size);
12234 #if CONFIG_IAMFDEC
12235
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 107974 times.
108056 else if (sc->iamf) {
12236 int64_t pts, dts, pos, duration;
12237 82 int flags, size = sample->size;
12238 82 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
12239 82 pts = pkt->pts; dts = pkt->dts;
12240 82 pos = pkt->pos; flags = pkt->flags;
12241 82 duration = pkt->duration;
12242
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) {
12243 454 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
12244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 454 times.
454 if (ret < 0) {
12245 ✗ if (should_retry(sc->pb, ret))
12246 ✗ mov_current_sample_dec(sc);
12247 ✗ return ret;
12248 }
12249 454 size -= ret;
12250
12251
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 334 times.
454 if (pkt->flags & AV_PKT_FLAG_DISCARD) {
12252 120 av_packet_unref(pkt);
12253 120 ret = 0;
12254 120 continue;
12255 }
12256 334 pkt->pts = pts; pkt->dts = dts;
12257 334 pkt->pos = pos; pkt->flags |= flags;
12258 334 pkt->duration = duration;
12259 334 ret = ff_buffer_packet(s, pkt);
12260 }
12261
1/2
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
82 if (!ret)
12262 82 return FFERROR_REDO;
12263 }
12264 #endif
12265
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 107971 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
107977 else if (st->codecpar->codec_id == AV_CODEC_ID_APV && sample->size > 4) {
12266 3 uint32_t au_size = avio_rb32(sc->pb);
12267 3 int explode = !!(mov->fc->error_recognition & AV_EF_EXPLODE);
12268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (au_size > sample->size - 4) {
12269 ✗ av_log(s, explode ? AV_LOG_ERROR : AV_LOG_WARNING,
12270 "APV au_size %u exceeds sample body %d\n",
12271 ✗ au_size, sample->size - 4);
12272 ✗ if (explode)
12273 ✗ return AVERROR_INVALIDDATA;
12274 ✗ au_size = sample->size - 4;
12275 }
12276 3 ret = av_get_packet(sc->pb, pkt, au_size);
12277 } else
12278 107971 ret = av_get_packet(sc->pb, pkt, sample->size);
12279
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 107970 times.
107974 if (ret < 0) {
12280
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (should_retry(sc->pb, ret)) {
12281 ✗ mov_current_sample_dec(sc);
12282 }
12283 4 return ret;
12284 }
12285 #if CONFIG_DV_DEMUXER
12286
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 107970 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
107970 if (mov->dv_demux && sc->dv_audio_container) {
12287 ✗ ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
12288 ✗ av_packet_unref(pkt);
12289 ✗ if (ret < 0)
12290 ✗ return ret;
12291 ✗ ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
12292 ✗ if (ret < 0)
12293 ✗ return ret;
12294 }
12295 #endif
12296
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 107952 times.
107970 if (sc->has_palette) {
12297 uint8_t *pal;
12298
12299 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
12300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
12301 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
12302 } else {
12303 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
12304 18 sc->has_palette = 0;
12305 }
12306 }
12307
4/6
✓ Branch 0 taken 329 times.
✓ Branch 1 taken 107641 times.
✓ Branch 3 taken 329 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 329 times.
✗ Branch 6 not taken.
107970 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
12308
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 329 times.
329 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
12309 ✗ ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
12310 }
12311 }
12312
12313 117195 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
12314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117195 times.
117195 if (ret < 0)
12315 ✗ return ret;
12316
12317
2/2
✓ Branch 0 taken 9225 times.
✓ Branch 1 taken 107970 times.
117195 if (st->discard == AVDISCARD_ALL)
12318 9225 goto retry;
12319
12320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107970 times.
107970 if (mov->aax_mode)
12321 ✗ aax_filter(pkt->data, pkt->size, mov);
12322
12323 107970 ret = cenc_filter(mov, st, sc, pkt, current_index);
12324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107970 times.
107970 if (ret < 0) {
12325 ✗ return ret;
12326 }
12327
12328 107970 return 0;
12329 }
12330
12331 365 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
12332 {
12333 365 MOVContext *mov = s->priv_data;
12334 int index;
12335
12336
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 28 times.
365 if (!mov->frag_index.complete)
12337 337 return 0;
12338
12339 28 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
12340
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 24 times.
28 if (index < 0)
12341 4 index = 0;
12342
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (!mov->frag_index.item[index].headers_read)
12343 1 return mov_switch_root(s, -1, index);
12344
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (index + 1 < mov->frag_index.nb_items)
12345 27 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
12346
12347 27 return 0;
12348 }
12349
12350 ✗ static int is_open_key_sample(const MOVStreamContext *sc, int sample)
12351 {
12352 // TODO: a bisect search would scale much better
12353 ✗ for (int i = 0; i < sc->open_key_samples_count; i++) {
12354 ✗ const int oks = sc->open_key_samples[i];
12355 ✗ if (oks == sample)
12356 ✗ return 1;
12357 ✗ if (oks > sample) /* list is monotically increasing so we can stop early */
12358 ✗ break;
12359 }
12360 ✗ return 0;
12361 }
12362
12363 /*
12364 * Some key sample may be key frames but not IDR frames, so a random access to
12365 * them may not be allowed.
12366 */
12367 231 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
12368 {
12369 231 MOVStreamContext *sc = st->priv_data;
12370 231 FFStream *const sti = ffstream(st);
12371 int64_t key_sample_dts, key_sample_pts;
12372
12373
1/2
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
231 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
12374 231 return 1;
12375
12376 ✗ if (sample >= sc->sample_offsets_count)
12377 ✗ return 1;
12378
12379 ✗ av_assert0(sample >= 0);
12380 ✗ key_sample_dts = sti->index_entries[sample].timestamp;
12381 ✗ key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
12382
12383 /*
12384 * If the sample needs to be presented before an open key sample, they may
12385 * not be decodable properly, even though they come after in decoding
12386 * order.
12387 */
12388 ✗ if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
12389 ✗ return 0;
12390
12391 ✗ return 1;
12392 }
12393
12394 365 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
12395 {
12396 365 MOVStreamContext *sc = st->priv_data;
12397 365 FFStream *const sti = ffstream(st);
12398 int sample, time_sample, ret, requested_sample;
12399 int64_t next_ts;
12400 unsigned int i;
12401
12402 // Here we consider timestamp to be PTS, hence try to offset it so that we
12403 // can search over the DTS timeline.
12404 365 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
12405
12406 365 ret = mov_seek_fragment(s, st, timestamp);
12407
1/2
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
365 if (ret < 0)
12408 ✗ return ret;
12409
12410 for (;;) {
12411 365 sample = av_index_search_timestamp(st, timestamp, flags);
12412 365 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
12413
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)
12414 43 sample = 0;
12415
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 339 times.
365 if (sample < 0) /* not sure what to do */
12416 26 return AVERROR_INVALIDDATA;
12417
12418
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))
12419 break;
12420
12421 ✗ next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
12422 ✗ requested_sample = av_index_search_timestamp(st, next_ts, flags);
12423 ✗ if (requested_sample < 0)
12424 ✗ return AVERROR_INVALIDDATA;
12425
12426 // If we've reached a different sample trying to find a good pts to
12427 // seek to, give up searching because we'll end up seeking back to
12428 // sample 0 on every seek.
12429 ✗ if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
12430 ✗ break;
12431
12432 ✗ timestamp = next_ts;
12433 }
12434
12435 339 mov_current_sample_set(sc, sample);
12436 339 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
12437 /* adjust time to sample index */
12438
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 125 times.
339 if (sc->tts_data) {
12439 214 time_sample = 0;
12440
1/2
✓ Branch 0 taken 60310 times.
✗ Branch 1 not taken.
60310 for (i = 0; i < sc->tts_count; i++) {
12441 60310 int next = time_sample + sc->tts_data[i].count;
12442
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 60096 times.
60310 if (next > sc->current_sample) {
12443 214 sc->tts_index = i;
12444 214 sc->tts_sample = sc->current_sample - time_sample;
12445 214 break;
12446 }
12447 60096 time_sample = next;
12448 }
12449 }
12450
12451 /* adjust stsd index */
12452
2/2
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 28 times.
339 if (sc->chunk_count) {
12453 311 time_sample = 0;
12454
1/2
✓ Branch 0 taken 383 times.
✗ Branch 1 not taken.
383 for (i = 0; i < sc->stsc_count; i++) {
12455 383 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
12456
2/2
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 72 times.
383 if (next > sc->current_sample) {
12457 311 sc->stsc_index = i;
12458 311 sc->stsc_sample = sc->current_sample - time_sample;
12459 311 break;
12460 }
12461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
12462 72 time_sample = next;
12463 }
12464 }
12465
12466 339 return sample;
12467 }
12468
12469 339 static int64_t mov_get_skip_samples(AVStream *st, int sample)
12470 {
12471 339 FFStream *const sti = ffstream(st);
12472 339 int64_t first_ts = sti->index_entries[0].timestamp;
12473 339 int64_t ts = sti->index_entries[sample].timestamp;
12474 int64_t off;
12475
12476
2/2
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 152 times.
339 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
12477 187 return 0;
12478
12479 /* compute skip samples according to stream initial_padding, seek ts and first ts */
12480 152 off = av_rescale_q(ts - first_ts, st->time_base,
12481 152 (AVRational){1, st->codecpar->sample_rate});
12482 152 return FFMAX(st->codecpar->initial_padding - off, 0);
12483 }
12484
12485 343 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
12486 {
12487 343 MOVContext *mc = s->priv_data;
12488 AVStream *st;
12489 FFStream *sti;
12490 int sample;
12491 int i;
12492
12493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 343 times.
343 if (stream_index >= s->nb_streams)
12494 ✗ return AVERROR_INVALIDDATA;
12495
12496 343 st = s->streams[stream_index];
12497 343 sti = ffstream(st);
12498 343 sample = mov_seek_stream(s, st, sample_time, flags);
12499
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 317 times.
343 if (sample < 0)
12500 26 return sample;
12501
12502
1/2
✓ Branch 0 taken 317 times.
✗ Branch 1 not taken.
317 if (mc->seek_individually) {
12503 /* adjust seek timestamp to found sample timestamp */
12504 317 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
12505 317 sti->skip_samples = mov_get_skip_samples(st, sample);
12506
12507
2/2
✓ Branch 0 taken 339 times.
✓ Branch 1 taken 317 times.
656 for (i = 0; i < s->nb_streams; i++) {
12508 339 AVStream *const st = s->streams[i];
12509 339 FFStream *const sti = ffstream(st);
12510 int64_t timestamp;
12511
12512
2/2
✓ Branch 0 taken 317 times.
✓ Branch 1 taken 22 times.
339 if (stream_index == i)
12513 317 continue;
12514
12515 22 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
12516 22 sample = mov_seek_stream(s, st, timestamp, flags);
12517
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (sample >= 0)
12518 22 sti->skip_samples = mov_get_skip_samples(st, sample);
12519 }
12520 } else {
12521 ✗ for (i = 0; i < s->nb_streams; i++) {
12522 MOVStreamContext *sc;
12523 ✗ st = s->streams[i];
12524 ✗ sc = st->priv_data;
12525 ✗ mov_current_sample_set(sc, 0);
12526 }
12527 ✗ while (1) {
12528 MOVStreamContext *sc;
12529 ✗ AVIndexEntry *entry = mov_find_next_sample(s, &st);
12530 ✗ if (!entry)
12531 ✗ return AVERROR_INVALIDDATA;
12532 ✗ sc = st->priv_data;
12533 ✗ if (sc->ffindex == stream_index && sc->current_sample == sample)
12534 ✗ break;
12535 ✗ mov_current_sample_inc(sc);
12536 }
12537 }
12538 317 return 0;
12539 }
12540
12541 #define OFFSET(x) offsetof(MOVContext, x)
12542 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
12543 static const AVOption mov_options[] = {
12544 {"use_absolute_path",
12545 "allow using absolute path when opening alias, this is a possible security issue",
12546 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
12547 0, 1, FLAGS},
12548 {"seek_streams_individually",
12549 "Seek each stream individually to the closest point",
12550 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
12551 0, 1, FLAGS},
12552 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
12553 0, 1, FLAGS},
12554 {"advanced_editlist",
12555 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
12556 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
12557 0, 1, FLAGS},
12558 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
12559 0, 1, FLAGS},
12560 {"use_mfra_for",
12561 "use mfra for fragment timestamps",
12562 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
12563 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
12564 .unit = "use_mfra_for"},
12565 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
12566 FLAGS, .unit = "use_mfra_for" },
12567 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
12568 FLAGS, .unit = "use_mfra_for" },
12569 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
12570 FLAGS, .unit = "use_mfra_for" },
12571 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
12572 0, 1, FLAGS},
12573 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
12574 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
12575 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
12576 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
12577 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
12578 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12579 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
12580 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12581 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
12582 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12583 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
12584 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
12585 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
12586 .flags = AV_OPT_FLAG_DECODING_PARAM },
12587 { "decryption_key", "The default media decryption key (hex)", OFFSET(decryption_default_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12588 { "decryption_keys", "The media decryption keys by KID (hex)", OFFSET(decryption_keys), AV_OPT_TYPE_DICT, .flags = AV_OPT_FLAG_DECODING_PARAM },
12589 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
12590 {.i64 = 0}, 0, 1, FLAGS },
12591 { "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 },
12592 { "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 },
12593
12594 { NULL },
12595 };
12596
12597 static const AVClass mov_class = {
12598 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
12599 .item_name = av_default_item_name,
12600 .option = mov_options,
12601 .version = LIBAVUTIL_VERSION_INT,
12602 };
12603
12604 const FFInputFormat ff_mov_demuxer = {
12605 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
12606 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
12607 .p.priv_class = &mov_class,
12608 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4v,m4b,ism,ismv,isma,f4v,avif,heic,heif",
12609 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
12610 .priv_data_size = sizeof(MOVContext),
12611 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
12612 .read_probe = mov_probe,
12613 .read_header = mov_read_header,
12614 .read_packet = mov_read_packet,
12615 .read_close = mov_read_close,
12616 .read_seek = mov_read_seek,
12617 };
12618