FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2026-10-15 08:01:34
Exec Total Coverage
Lines: 5035 7873 64.0%
Functions: 204 243 84.0%
Branches: 2887 5323 54.2%

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/gain_map.h"
50 #include "libavutil/pixdesc.h"
51 #include "libavutil/sha.h"
52 #include "libavutil/spherical.h"
53 #include "libavutil/stereo3d.h"
54 #include "libavutil/timecode.h"
55 #include "libavutil/uuid.h"
56 #include "libavcodec/ac3tab.h"
57 #include "libavcodec/exif.h"
58 #include "libavcodec/flac.h"
59 #include "libavcodec/hevc/hevc.h"
60 #include "libavcodec/mpegaudiodata.h"
61 #include "libavcodec/mpegaudiodecheader.h"
62 #include "libavcodec/mlp_parse.h"
63 #include "avformat.h"
64 #include "internal.h"
65 #include "avio_internal.h"
66 #include "demux.h"
67 #include "dvdclut.h"
68 #include "iamf_parse.h"
69 #include "iamf_reader.h"
70 #include "dovi_isom.h"
71 #include "riff.h"
72 #include "isom.h"
73 #include "libavcodec/get_bits.h"
74 #include "id3v1.h"
75 #include "mov_chan.h"
76 #include "replaygain.h"
77
78 #if CONFIG_ZLIB
79 #include <zlib.h>
80 #endif
81
82 #include "qtpalette.h"
83
84 /* those functions parse an atom */
85 /* links atom IDs to parse functions */
86 typedef struct MOVParseTableEntry {
87 uint32_t type;
88 int (*parse)(MOVContext *ctx, AVIOContext *pb, MOVAtom atom);
89 } MOVParseTableEntry;
90
91 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom);
92 static int mov_read_mfra(MOVContext *c, AVIOContext *f);
93 static void mov_free_stream_context(AVFormatContext *s, AVStream *st);
94
95 32 static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
96 unsigned len, const char *key)
97 {
98 char buf[16];
99
100 32 short current, total = 0;
101 32 avio_rb16(pb); // unknown
102 32 current = avio_rb16(pb);
103
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (len >= 6)
104 32 total = avio_rb16(pb);
105
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 25 times.
32 if (!total)
106 7 snprintf(buf, sizeof(buf), "%d", current);
107 else
108 25 snprintf(buf, sizeof(buf), "%d/%d", current, total);
109 32 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
110 32 av_dict_set(&c->fc->metadata, key, buf, 0);
111
112 32 return 0;
113 }
114
115 ✗ static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
116 unsigned len, const char *key)
117 {
118 /* bypass padding bytes */
119 ✗ avio_r8(pb);
120 ✗ avio_r8(pb);
121 ✗ avio_r8(pb);
122
123 ✗ c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
124 ✗ av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
125
126 ✗ return 0;
127 }
128
129 30 static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
130 unsigned len, const char *key)
131 {
132 30 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
133 30 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
134
135 30 return 0;
136 }
137
138 12 static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
139 unsigned len, const char *key)
140 {
141 short genre;
142
143 12 avio_r8(pb); // unknown
144
145 12 genre = avio_r8(pb);
146
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)
147 ✗ return 0;
148 12 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
149 12 av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
150
151 12 return 0;
152 }
153
154 static const uint32_t mac_to_unicode[128] = {
155 0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
156 0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
157 0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,
158 0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,
159 0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,
160 0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,
161 0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,
162 0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,
163 0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,
164 0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,
165 0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,
166 0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,
167 0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,
168 0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,
169 0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,
170 0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7,
171 };
172
173 407 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
174 char *dst, int dstlen)
175 {
176 407 char *p = dst;
177 407 char *end = dst+dstlen-1;
178 int i;
179
180
2/2
✓ Branch 0 taken 3423 times.
✓ Branch 1 taken 407 times.
3830 for (i = 0; i < len; i++) {
181 3423 uint8_t t, c = avio_r8(pb);
182
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3423 times.
3423 if (p >= end)
184 ✗ continue;
185
186
2/2
✓ Branch 0 taken 3415 times.
✓ Branch 1 taken 8 times.
3423 if (c < 0x80)
187 3415 *p++ = c;
188
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 else if (p < end)
189
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;);
190 }
191 407 *p = 0;
192 407 return p - dst;
193 }
194
195 /**
196 * Get the requested item.
197 */
198 272 static HEIFItem *get_heif_item(MOVContext *c, unsigned id)
199 {
200 272 HEIFItem *item = NULL;
201
202
2/2
✓ Branch 0 taken 816 times.
✓ Branch 1 taken 15 times.
831 for (int i = 0; i < c->nb_heif_item; i++) {
203
3/4
✓ Branch 0 taken 816 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 559 times.
✓ Branch 3 taken 257 times.
816 if (!c->heif_item[i] || c->heif_item[i]->item_id != id)
204 559 continue;
205
206 257 item = c->heif_item[i];
207 257 break;
208 }
209
210 272 return item;
211 }
212
213 /**
214 * Get the current stream in the parsing process. This can either be the
215 * latest stream added to the context, or the stream referenced by an item.
216 */
217 315 static AVStream *get_curr_st(MOVContext *c)
218 {
219 315 AVStream *st = NULL;
220 HEIFItem *item;
221
222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 315 times.
315 if (c->fc->nb_streams < 1)
223 ✗ return NULL;
224
225
2/2
✓ Branch 0 taken 242 times.
✓ Branch 1 taken 73 times.
315 if (c->cur_item_id == -1)
226 242 return c->fc->streams[c->fc->nb_streams-1];
227
228 73 item = get_heif_item(c, c->cur_item_id);
229
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 if (item)
230 73 st = item->st;
231
232 73 return st;
233 }
234
235 16 static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
236 {
237 AVStream *st;
238 MOVStreamContext *sc;
239 enum AVCodecID id;
240 int ret;
241
242
2/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
16 switch (type) {
243 9 case 0xd: id = AV_CODEC_ID_MJPEG; break;
244 7 case 0xe: id = AV_CODEC_ID_PNG; break;
245 ✗ case 0x1b: id = AV_CODEC_ID_BMP; break;
246 ✗ default:
247 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown cover type: 0x%x.\n", type);
248 ✗ avio_skip(pb, len);
249 ✗ return 0;
250 }
251
252 16 sc = av_mallocz(sizeof(*sc));
253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!sc)
254 ✗ return AVERROR(ENOMEM);
255 16 ret = ff_add_attached_pic(c->fc, NULL, pb, NULL, len);
256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0) {
257 ✗ av_free(sc);
258 ✗ return ret;
259 }
260 16 st = c->fc->streams[c->fc->nb_streams - 1];
261 16 st->priv_data = sc;
262 16 sc->id = st->id;
263 16 sc->refcount = 1;
264
265
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) {
266
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 9 times.
16 if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
267 7 id = AV_CODEC_ID_PNG;
268 } else {
269 9 id = AV_CODEC_ID_MJPEG;
270 }
271 }
272 16 st->codecpar->codec_id = id;
273
274 16 return 0;
275 }
276
277 // 3GPP TS 26.244
278 ✗ static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
279 {
280 ✗ char language[4] = { 0 };
281 char buf[200], place[100];
282 ✗ uint16_t langcode = 0;
283 double longitude, latitude, altitude;
284 ✗ const char *key = "location";
285
286 ✗ if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) {
287 ✗ av_log(c->fc, AV_LOG_ERROR, "loci too short\n");
288 ✗ return AVERROR_INVALIDDATA;
289 }
290
291 ✗ avio_skip(pb, 4); // version+flags
292 ✗ langcode = avio_rb16(pb);
293 ✗ ff_mov_lang_to_iso639(langcode, language);
294 ✗ len -= 6;
295
296 ✗ len -= avio_get_str(pb, len, place, sizeof(place));
297 ✗ if (len < 1) {
298 ✗ av_log(c->fc, AV_LOG_ERROR, "place name too long\n");
299 ✗ return AVERROR_INVALIDDATA;
300 }
301 ✗ avio_skip(pb, 1); // role
302 ✗ len -= 1;
303
304 ✗ if (len < 12) {
305 ✗ av_log(c->fc, AV_LOG_ERROR,
306 "loci too short (%u bytes left, need at least %d)\n", len, 12);
307 ✗ return AVERROR_INVALIDDATA;
308 }
309 ✗ longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
310 ✗ latitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
311 ✗ altitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
312
313 // Try to output in the same format as the ?xyz field
314 ✗ snprintf(buf, sizeof(buf), "%+08.4f%+09.4f", latitude, longitude);
315 ✗ if (altitude)
316 ✗ av_strlcatf(buf, sizeof(buf), "%+f", altitude);
317 ✗ av_strlcatf(buf, sizeof(buf), "/%s", place);
318
319 ✗ if (*language && strcmp(language, "und")) {
320 char key2[16];
321 ✗ snprintf(key2, sizeof(key2), "%s-%s", key, language);
322 ✗ av_dict_set(&c->fc->metadata, key2, buf, 0);
323 }
324 ✗ c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
325 ✗ return av_dict_set(&c->fc->metadata, key, buf, 0);
326 }
327
328 ✗ static int mov_metadata_hmmt(MOVContext *c, AVIOContext *pb, unsigned len)
329 {
330 int i, n_hmmt;
331
332 ✗ if (len < 2)
333 ✗ return 0;
334 ✗ if (c->ignore_chapters)
335 ✗ return 0;
336
337 ✗ n_hmmt = avio_rb32(pb);
338 ✗ if (n_hmmt > len / 4)
339 ✗ return AVERROR_INVALIDDATA;
340 ✗ for (i = 0; i < n_hmmt && !pb->eof_reached; i++) {
341 ✗ int moment_time = avio_rb32(pb);
342 ✗ avpriv_new_chapter(c->fc, i, av_make_q(1, 1000), moment_time, AV_NOPTS_VALUE, NULL);
343 }
344 ✗ if (avio_feof(pb))
345 ✗ return AVERROR_INVALIDDATA;
346 ✗ return 0;
347 }
348
349 634 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
350 {
351 634 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
352 634 char key2[32], language[4] = {0};
353 634 char *str = NULL;
354 634 const char *key = NULL;
355 634 uint16_t langcode = 0;
356 634 uint32_t data_type = 0, str_size_alloc;
357 uint64_t str_size;
358 634 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
359 634 int raw = 0;
360 634 int num = 0;
361 AVDictionary **metadata;
362
363
3/4
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 581 times.
✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
634 if (c->trak_index >= 0 && c->trak_index < c->fc->nb_streams)
364 53 metadata = &c->fc->streams[c->trak_index]->metadata;
365 else
366 581 metadata = &c->fc->metadata;
367
368
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 76 times.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✓ Branch 73 taken 3 times.
✓ Branch 74 taken 5 times.
634 switch (atom.type) {
369 3 case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break;
370 3 case MKTAG( '@','P','R','Q'): key = "quicktime_version"; raw = 1; break;
371 2 case MKTAG( 'X','M','P','_'):
372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->export_xmp) { key = "xmp"; raw = 1; } break;
373 16 case MKTAG( 'a','A','R','T'): key = "album_artist"; break;
374 ✗ case MKTAG( 'a','k','I','D'): key = "account_type";
375 ✗ parse = mov_metadata_int8_no_padding; break;
376 ✗ case MKTAG( 'a','p','I','D'): key = "account_id"; break;
377 ✗ case MKTAG( 'c','a','t','g'): key = "category"; break;
378 15 case MKTAG( 'c','p','i','l'): key = "compilation";
379 15 parse = mov_metadata_int8_no_padding; break;
380 2 case MKTAG( 'c','p','r','t'): key = "copyright"; break;
381 ✗ case MKTAG( 'd','e','s','c'): key = "description"; break;
382 16 case MKTAG( 'd','i','s','k'): key = "disc";
383 16 parse = mov_metadata_track_or_disc_number; break;
384 ✗ case MKTAG( 'e','g','i','d'): key = "episode_uid";
385 ✗ parse = mov_metadata_int8_no_padding; break;
386 ✗ case MKTAG( 'F','I','R','M'): key = "firmware"; raw = 1; break;
387 12 case MKTAG( 'g','n','r','e'): key = "genre";
388 12 parse = mov_metadata_gnre; break;
389 ✗ case MKTAG( 'h','d','v','d'): key = "hd_video";
390 ✗ parse = mov_metadata_int8_no_padding; break;
391 ✗ case MKTAG( 'H','M','M','T'):
392 ✗ return mov_metadata_hmmt(c, pb, atom.size);
393 ✗ case MKTAG( 'k','e','y','w'): key = "keywords"; break;
394 ✗ case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
395 ✗ case MKTAG( 'l','o','c','i'):
396 ✗ return mov_metadata_loci(c, pb, atom.size);
397 ✗ case MKTAG( 'm','a','n','u'): key = "make"; break;
398 ✗ case MKTAG( 'm','o','d','l'): key = "model"; break;
399 5 case MKTAG( 'n','a','m','e'): key = "name"; break;
400 ✗ case MKTAG( 'p','c','s','t'): key = "podcast";
401 ✗ parse = mov_metadata_int8_no_padding; break;
402 15 case MKTAG( 'p','g','a','p'): key = "gapless_playback";
403 15 parse = mov_metadata_int8_no_padding; break;
404 ✗ case MKTAG( 'p','u','r','d'): key = "purchase_date"; break;
405 ✗ case MKTAG( 'r','t','n','g'): key = "rating";
406 ✗ parse = mov_metadata_int8_no_padding; break;
407 ✗ case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break;
408 ✗ case MKTAG( 's','o','a','l'): key = "sort_album"; break;
409 ✗ case MKTAG( 's','o','a','r'): key = "sort_artist"; break;
410 ✗ case MKTAG( 's','o','c','o'): key = "sort_composer"; break;
411 ✗ case MKTAG( 's','o','n','m'): key = "sort_name"; break;
412 ✗ case MKTAG( 's','o','s','n'): key = "sort_show"; break;
413 ✗ case MKTAG( 's','t','i','k'): key = "media_type";
414 ✗ parse = mov_metadata_int8_no_padding; break;
415 16 case MKTAG( 't','r','k','n'): key = "track";
416 16 parse = mov_metadata_track_or_disc_number; break;
417 ✗ case MKTAG( 't','v','e','n'): key = "episode_id"; break;
418 ✗ case MKTAG( 't','v','e','s'): key = "episode_sort";
419 ✗ parse = mov_metadata_int8_bypass_padding; break;
420 ✗ case MKTAG( 't','v','n','n'): key = "network"; break;
421 ✗ case MKTAG( 't','v','s','h'): key = "show"; break;
422 ✗ case MKTAG( 't','v','s','n'): key = "season_number";
423 ✗ parse = mov_metadata_int8_bypass_padding; break;
424 21 case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
425 ✗ case MKTAG(0xa9,'P','R','D'): key = "producer"; break;
426 20 case MKTAG(0xa9,'a','l','b'): key = "album"; break;
427 3 case MKTAG(0xa9,'a','u','t'): key = "artist"; break;
428 ✗ case MKTAG(0xa9,'c','h','p'): key = "chapter"; break;
429 12 case MKTAG(0xa9,'c','m','t'): key = "comment"; break;
430 ✗ case MKTAG(0xa9,'c','o','m'): key = "composer"; break;
431 4 case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
432 20 case MKTAG(0xa9,'d','a','y'): key = "date"; break;
433 ✗ case MKTAG(0xa9,'d','i','r'): key = "director"; break;
434 ✗ case MKTAG(0xa9,'d','i','s'): key = "disclaimer"; break;
435 ✗ case MKTAG(0xa9,'e','d','1'): key = "edit_date"; break;
436 2 case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
437 ✗ case MKTAG(0xa9,'f','m','t'): key = "original_format"; break;
438 5 case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
439 ✗ case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
440 ✗ case MKTAG(0xa9,'h','s','t'): key = "host_computer"; break;
441 ✗ case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
442 ✗ case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
443 5 case MKTAG(0xa9,'m','a','k'): key = "make"; break;
444 5 case MKTAG(0xa9,'m','o','d'): key = "model"; break;
445 47 case MKTAG(0xa9,'n','a','m'): key = "title"; break;
446 ✗ case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break;
447 ✗ case MKTAG(0xa9,'p','r','d'): key = "producer"; break;
448 ✗ case MKTAG(0xa9,'p','r','f'): key = "performers"; break;
449 ✗ case MKTAG(0xa9,'r','e','q'): key = "playback_requirements"; break;
450 ✗ case MKTAG(0xa9,'s','r','c'): key = "original_source"; break;
451 ✗ case MKTAG(0xa9,'s','t','3'): key = "subtitle"; break;
452 63 case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
453 76 case MKTAG(0xa9,'t','o','o'): key = "encoder"; break;
454 ✗ case MKTAG(0xa9,'t','r','k'): key = "track"; break;
455 ✗ case MKTAG(0xa9,'u','r','l'): key = "URL"; break;
456 ✗ case MKTAG(0xa9,'w','r','n'): key = "warning"; break;
457 3 case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
458 5 case MKTAG(0xa9,'x','y','z'): key = "location"; break;
459 }
460 7 retry:
461
3/4
✓ Branch 0 taken 436 times.
✓ Branch 1 taken 205 times.
✓ Branch 2 taken 436 times.
✗ Branch 3 not taken.
1061 if (c->itunes_metadata && atom.size > 8) {
462 436 int data_size = avio_rb32(pb);
463 436 int tag = avio_rl32(pb);
464
3/6
✓ Branch 0 taken 436 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 436 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 436 times.
✗ Branch 5 not taken.
436 if (tag == MKTAG('d','a','t','a') && data_size <= atom.size && data_size >= 16) {
465 436 data_type = avio_rb32(pb); // type
466 436 avio_rb32(pb); // unknown
467 436 str_size = data_size - 16;
468 436 atom.size -= 16;
469
470
5/6
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 279 times.
✓ Branch 2 taken 104 times.
✓ Branch 3 taken 53 times.
✓ Branch 4 taken 104 times.
✗ Branch 5 not taken.
436 if (!key && c->found_hdlr_mdta && c->meta_keys) {
471 104 uint32_t index = av_bswap32(atom.type); // BE number has been read as LE
472
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) {
473 104 key = c->meta_keys[index];
474 ✗ } else if (atom.type != MKTAG('c', 'o', 'v', 'r')) {
475 ✗ av_log(c->fc, AV_LOG_WARNING,
476 "The index of 'data' is out of range: %"PRId32" < 1 or >= %d.\n",
477 index, c->meta_keys_count);
478 }
479 }
480
4/4
✓ Branch 0 taken 420 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 383 times.
✓ Branch 3 taken 37 times.
436 if (atom.type == MKTAG('c', 'o', 'v', 'r') ||
481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 383 times.
383 (key && !strcmp(key, "com.apple.quicktime.artwork"))) {
482 16 int ret = mov_read_covr(c, pb, data_type, str_size);
483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0) {
484 ✗ av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
485 ✗ return ret;
486 }
487 16 atom.size -= str_size;
488
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (atom.size > 8)
489 2 goto retry;
490 14 return ret;
491 }
492 ✗ } else return 0;
493
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) {
494 109 str_size = avio_rb16(pb); // string length
495
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 104 times.
109 if (str_size > atom.size) {
496 5 raw = 1;
497 5 avio_seek(pb, -2, SEEK_CUR);
498 5 av_log(c->fc, AV_LOG_WARNING, "UDTA parsing failed retrying raw\n");
499 5 goto retry;
500 }
501 104 langcode = avio_rb16(pb);
502 104 ff_mov_lang_to_iso639(langcode, language);
503 104 atom.size -= 4;
504 } else
505 96 str_size = atom.size;
506
507
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 620 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
620 if (c->export_all && !key) {
508 ✗ key = av_fourcc_make_string(tmp_key, atom.type);
509 }
510
511
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 498 times.
620 if (!key)
512 122 return 0;
513
2/4
✓ Branch 0 taken 498 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 498 times.
498 if (atom.size < 0 || str_size >= INT_MAX/2)
514 ✗ return AVERROR_INVALIDDATA;
515
516 // Allocates enough space if data_type is a int32 or float32 number, otherwise
517 // worst-case requirement for output string in case of utf8 coded input
518
3/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 426 times.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
498 num = (data_type >= 21 && data_type <= 23);
519
4/4
✓ Branch 0 taken 426 times.
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 415 times.
✓ Branch 3 taken 11 times.
498 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
520 498 str = av_mallocz(str_size_alloc);
521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 498 times.
498 if (!str)
522 ✗ return AVERROR(ENOMEM);
523
524
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 424 times.
498 if (parse)
525 74 parse(c, pb, str_size, key);
526 else {
527
8/10
✓ Branch 0 taken 413 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 413 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 108 times.
✓ Branch 5 taken 305 times.
✓ Branch 6 taken 91 times.
✓ Branch 7 taken 17 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 91 times.
424 if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
528 17 mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
529
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 405 times.
407 } else if (data_type == 21) { // BE signed integer, variable size
530 2 int val = 0;
531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (str_size == 1)
532 ✗ val = (int8_t)avio_r8(pb);
533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 2)
534 ✗ val = (int16_t)avio_rb16(pb);
535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 3)
536 ✗ val = ((int32_t)(avio_rb24(pb)<<8))>>8;
537
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (str_size == 4)
538 2 val = (int32_t)avio_rb32(pb);
539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
540 ✗ av_log(c->fc, AV_LOG_ERROR,
541 "Failed to store the number (%d) in string.\n", val);
542 ✗ av_free(str);
543 ✗ return AVERROR_INVALIDDATA;
544 }
545
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 405 times.
405 } else if (data_type == 22) { // BE unsigned integer, variable size
546 ✗ unsigned int val = 0;
547 ✗ if (str_size == 1)
548 ✗ val = avio_r8(pb);
549 ✗ else if (str_size == 2)
550 ✗ val = avio_rb16(pb);
551 ✗ else if (str_size == 3)
552 ✗ val = avio_rb24(pb);
553 ✗ else if (str_size == 4)
554 ✗ val = avio_rb32(pb);
555 ✗ if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
556 ✗ av_log(c->fc, AV_LOG_ERROR,
557 "Failed to store the number (%u) in string.\n", val);
558 ✗ av_free(str);
559 ✗ return AVERROR_INVALIDDATA;
560 }
561
3/4
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 365 times.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
445 } else if (data_type == 23 && str_size >= 4) { // BE float32
562 40 float val = av_int2float(avio_rb32(pb));
563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
564 ✗ av_log(c->fc, AV_LOG_ERROR,
565 "Failed to store the float32 number (%f) in string.\n", val);
566 ✗ av_free(str);
567 ✗ return AVERROR_INVALIDDATA;
568 }
569
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 365 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
365 } else if (data_type > 1 && data_type != 4) {
570 // data_type can be 0 if not set at all above. data_type 1 means
571 // UTF8 and 4 means "UTF8 sort". For any other type (UTF16 or e.g.
572 // a picture), don't return it blindly in a string that is supposed
573 // to be UTF8 text.
574 ✗ av_log(c->fc, AV_LOG_WARNING, "Skipping unhandled metadata %s of type %"PRIu32"\n", key, data_type);
575 ✗ av_free(str);
576 ✗ return 0;
577 } else {
578 365 int ret = ffio_read_size(pb, str, str_size);
579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 365 times.
365 if (ret < 0) {
580 ✗ av_free(str);
581 ✗ return ret;
582 }
583 365 str[str_size] = 0;
584 }
585 424 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
586
4/4
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 115 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 305 times.
424 if (c->itunes_metadata && av_dict_get(*metadata, key, NULL, 0))
587 4 av_dict_set(metadata, key, ";", AV_DICT_APPEND);
588
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 115 times.
424 av_dict_set(metadata, key, str, c->itunes_metadata ? AV_DICT_APPEND : 0);
589
4/4
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 320 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 67 times.
424 if (*language && strcmp(language, "und")) {
590 37 snprintf(key2, sizeof(key2), "%s-%s", key, language);
591 37 av_dict_set(metadata, key2, str, 0);
592 }
593
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 283 times.
424 if (!strcmp(key, "encoder")) {
594 int major, minor, micro;
595
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 140 times.
141 if (sscanf(str, "HandBrake %d.%d.%d", &major, &minor, &micro) == 3) {
596 1 c->handbrake_version = 1000000*major + 1000*minor + micro;
597 }
598 }
599
600 424 atom.size -= str_size;
601 424 av_freep(&str);
602
603 // Read remaining data atoms for multi-valued iTunes tags (e.g. multiple
604 // artists stored as multiple data atoms within one tag atom), consistent
605 // with the existing covr path.
606 // Note: multiple sibling tag atoms with the same key (e.g. three separate
607 // ©ART atoms under ilst) are handled by the AV_DICT_APPEND logic above,
608 // since mov_read_udta_string() is called once per tag atom.
609
3/4
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 115 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 309 times.
424 if (c->itunes_metadata && atom.size > 8)
610 ✗ goto retry;
611 }
612
613 498 av_freep(&str);
614 498 return 0;
615 }
616
617 12 static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
618 {
619 int64_t start;
620 int i, nb_chapters, str_len, version;
621 char str[256+1];
622 int ret;
623
624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->ignore_chapters)
625 ✗ return 0;
626
627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if ((atom.size -= 5) < 0)
628 ✗ return 0;
629
630 12 version = avio_r8(pb);
631 12 avio_rb24(pb);
632
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (version)
633 12 avio_rb32(pb); // ???
634 12 nb_chapters = avio_r8(pb);
635
636
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
30 for (i = 0; i < nb_chapters; i++) {
637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size < 9)
638 ✗ return 0;
639
640 18 start = avio_rb64(pb);
641 18 str_len = avio_r8(pb);
642
643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if ((atom.size -= 9+str_len) < 0)
644 ✗ return 0;
645
646 18 ret = ffio_read_size(pb, str, str_len);
647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (ret < 0)
648 ✗ return ret;
649 18 str[str_len] = 0;
650 18 avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
651 }
652 12 return 0;
653 }
654
655 #define MIN_DATA_ENTRY_BOX_SIZE 12
656 838 static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
657 {
658 AVStream *st;
659 MOVStreamContext *sc;
660 int entries, i, j;
661
662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->fc->nb_streams < 1)
663 ✗ return 0;
664 838 st = c->fc->streams[c->fc->nb_streams-1];
665 838 sc = st->priv_data;
666
667 838 avio_rb32(pb); // version + flags
668 838 entries = avio_rb32(pb);
669
1/2
✓ Branch 0 taken 838 times.
✗ Branch 1 not taken.
838 if (!entries ||
670
1/2
✓ Branch 0 taken 838 times.
✗ Branch 1 not taken.
838 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 entries >= UINT_MAX / sizeof(*sc->drefs))
672 ✗ return AVERROR_INVALIDDATA;
673
674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 for (i = 0; i < sc->drefs_count; i++) {
675 ✗ MOVDref *dref = &sc->drefs[i];
676 ✗ av_freep(&dref->path);
677 ✗ av_freep(&dref->dir);
678 }
679 838 av_free(sc->drefs);
680 838 sc->drefs_count = 0;
681 838 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (!sc->drefs)
683 ✗ return AVERROR(ENOMEM);
684 838 sc->drefs_count = entries;
685
686
2/2
✓ Branch 0 taken 838 times.
✓ Branch 1 taken 838 times.
1676 for (i = 0; i < entries; i++) {
687 838 MOVDref *dref = &sc->drefs[i];
688 838 uint32_t size = avio_rb32(pb);
689 838 int64_t next = avio_tell(pb);
690
691
3/6
✓ Branch 0 taken 838 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 838 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 838 times.
838 if (size < 12 || next < 0 || next > INT64_MAX - size)
692 ✗ return AVERROR_INVALIDDATA;
693
694 838 next += size - 4;
695
696 838 dref->type = avio_rl32(pb);
697 838 avio_rb32(pb); // version + flags
698
699
3/4
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 686 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 152 times.
838 if (dref->type == MKTAG('a','l','i','s') && size > 150) {
700 /* macintosh alias record */
701 uint16_t volume_len, len;
702 int16_t type;
703 int ret;
704
705 ✗ avio_skip(pb, 10);
706
707 ✗ volume_len = avio_r8(pb);
708 ✗ volume_len = FFMIN(volume_len, 27);
709 ✗ ret = ffio_read_size(pb, dref->volume, 27);
710 ✗ if (ret < 0)
711 ✗ return ret;
712 ✗ dref->volume[volume_len] = 0;
713 ✗ av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
714
715 ✗ avio_skip(pb, 12);
716
717 ✗ len = avio_r8(pb);
718 ✗ len = FFMIN(len, 63);
719 ✗ ret = ffio_read_size(pb, dref->filename, 63);
720 ✗ if (ret < 0)
721 ✗ return ret;
722 ✗ dref->filename[len] = 0;
723 ✗ av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
724
725 ✗ avio_skip(pb, 16);
726
727 /* read next level up_from_alias/down_to_target */
728 ✗ dref->nlvl_from = avio_rb16(pb);
729 ✗ dref->nlvl_to = avio_rb16(pb);
730 ✗ av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
731 ✗ dref->nlvl_from, dref->nlvl_to);
732
733 ✗ avio_skip(pb, 16);
734
735 ✗ for (type = 0; type != -1 && avio_tell(pb) < next; ) {
736 ✗ if (avio_feof(pb))
737 ✗ return AVERROR_EOF;
738 ✗ type = avio_rb16(pb);
739 ✗ len = avio_rb16(pb);
740 ✗ av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
741 ✗ if (len&1)
742 ✗ len += 1;
743 ✗ if (type == 2) { // absolute path
744 ✗ av_free(dref->path);
745 ✗ dref->path = av_mallocz(len+1);
746 ✗ if (!dref->path)
747 ✗ return AVERROR(ENOMEM);
748
749 ✗ ret = ffio_read_size(pb, dref->path, len);
750 ✗ if (ret < 0) {
751 ✗ av_freep(&dref->path);
752 ✗ return ret;
753 }
754 ✗ if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
755 ✗ len -= volume_len;
756 ✗ memmove(dref->path, dref->path+volume_len, len);
757 ✗ dref->path[len] = 0;
758 }
759 // trim string of any ending zeros
760 ✗ for (j = len - 1; j >= 0; j--) {
761 ✗ if (dref->path[j] == 0)
762 ✗ len--;
763 else
764 ✗ break;
765 }
766 ✗ for (j = 0; j < len; j++)
767 ✗ if (dref->path[j] == ':' || dref->path[j] == 0)
768 ✗ dref->path[j] = '/';
769 ✗ av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
770 ✗ } else if (type == 0) { // directory name
771 ✗ av_free(dref->dir);
772 ✗ dref->dir = av_malloc(len+1);
773 ✗ if (!dref->dir)
774 ✗ return AVERROR(ENOMEM);
775
776 ✗ ret = ffio_read_size(pb, dref->dir, len);
777 ✗ if (ret < 0) {
778 ✗ av_freep(&dref->dir);
779 ✗ return ret;
780 }
781 ✗ dref->dir[len] = 0;
782 ✗ for (j = 0; j < len; j++)
783 ✗ if (dref->dir[j] == ':')
784 ✗ dref->dir[j] = '/';
785 ✗ av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
786 } else
787 ✗ avio_skip(pb, len);
788 }
789 } else {
790 838 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
791 dref->type, size);
792 838 entries--;
793 838 i--;
794 }
795 838 avio_seek(pb, next, SEEK_SET);
796 }
797 838 return 0;
798 }
799
800 1464 static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
801 {
802 AVStream *st;
803 uint32_t type;
804 uint32_t ctype;
805 int64_t title_size;
806 char *title_str;
807 int ret;
808
809 1464 avio_r8(pb); /* version */
810 1464 avio_rb24(pb); /* flags */
811
812 /* component type */
813 1464 ctype = avio_rl32(pb);
814 1464 type = avio_rl32(pb); /* component subtype */
815
816 1464 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
817 1464 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
818
819
2/2
✓ Branch 0 taken 222 times.
✓ Branch 1 taken 1242 times.
1464 if (c->trak_index < 0) { // meta not inside a trak
820
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 208 times.
222 if (type == MKTAG('m','d','t','a')) {
821 14 c->found_hdlr_mdta = 1;
822 }
823 222 return 0;
824 }
825
826 1242 st = c->fc->streams[c->fc->nb_streams-1];
827
828
2/2
✓ Branch 0 taken 375 times.
✓ Branch 1 taken 867 times.
1242 if (type == MKTAG('v','i','d','e'))
829 375 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
830
2/2
✓ Branch 0 taken 397 times.
✓ Branch 1 taken 470 times.
867 else if (type == MKTAG('s','o','u','n'))
831 397 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 else if (type == MKTAG('m','1','a',' '))
833 ✗ st->codecpar->codec_id = AV_CODEC_ID_MP2;
834
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')))
835 ✗ st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
836
837 1242 avio_rb32(pb); /* component manufacture */
838 1242 avio_rb32(pb); /* component flags */
839 1242 avio_rb32(pb); /* component flags mask */
840
841 1242 title_size = atom.size - 24;
842
2/2
✓ Branch 0 taken 1236 times.
✓ Branch 1 taken 6 times.
1242 if (title_size > 0) {
843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1236 times.
1236 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
844 ✗ return AVERROR_INVALIDDATA;
845 1236 title_str = av_malloc(title_size + 1); /* Add null terminator */
846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1236 times.
1236 if (!title_str)
847 ✗ return AVERROR(ENOMEM);
848
849 1236 ret = ffio_read_size(pb, title_str, title_size);
850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1236 times.
1236 if (ret < 0) {
851 ✗ av_freep(&title_str);
852 ✗ return ret;
853 }
854 1236 title_str[title_size] = 0;
855
2/2
✓ Branch 0 taken 1172 times.
✓ Branch 1 taken 64 times.
1236 if (title_str[0]) {
856
4/4
✓ Branch 0 taken 778 times.
✓ Branch 1 taken 394 times.
✓ Branch 2 taken 776 times.
✓ Branch 3 taken 2 times.
1172 int off = (!c->isom && title_str[0] == title_size - 1);
857 // flag added so as to not set stream handler name if already set from mdia->hdlr
858 1172 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
859 }
860 1236 av_freep(&title_str);
861 }
862
863 1242 return 0;
864 }
865
866 301 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
867 {
868 301 return ff_mov_read_esds(c->fc, pb);
869 }
870
871 8 static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
872 {
873 AVStream *st;
874 AVPacketSideData *sd;
875 enum AVAudioServiceType *ast;
876 int ac3info, acmod, lfeon, bsmod;
877 uint64_t mask;
878
879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (c->fc->nb_streams < 1)
880 ✗ return 0;
881 8 st = c->fc->streams[c->fc->nb_streams-1];
882
883 8 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
884 8 &st->codecpar->nb_coded_side_data,
885 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
886 sizeof(*ast), 0);
887
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!sd)
888 ✗ return AVERROR(ENOMEM);
889
890 8 ast = (enum AVAudioServiceType*)sd->data;
891 8 ac3info = avio_rb24(pb);
892 8 bsmod = (ac3info >> 14) & 0x7;
893 8 acmod = (ac3info >> 11) & 0x7;
894 8 lfeon = (ac3info >> 10) & 0x1;
895
896 8 mask = ff_ac3_channel_layout_tab[acmod];
897
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (lfeon)
898 1 mask |= AV_CH_LOW_FREQUENCY;
899 8 av_channel_layout_uninit(&st->codecpar->ch_layout);
900 8 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
901
902 8 *ast = bsmod;
903
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)
904 ✗ *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
905
906 8 return 0;
907 }
908
909 #if CONFIG_IAMFDEC
910 12 static int mov_read_iacb(MOVContext *c, AVIOContext *pb, MOVAtom atom)
911 {
912 AVStream *st;
913 MOVStreamContext *sc;
914 FFIOContext b;
915 AVIOContext *descriptor_pb;
916 AVDictionary *metadata;
917 IAMFContext *iamf;
918 int64_t start_time, duration;
919 unsigned descriptors_size;
920 int nb_frames, disposition;
921 int version, ret;
922
923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (atom.size < 5)
924 ✗ return AVERROR_INVALIDDATA;
925
926
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->fc->nb_streams < 1)
927 ✗ return 0;
928
929 12 version = avio_r8(pb);
930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (version != 1) {
931 ✗ av_log(c->fc, AV_LOG_ERROR, "%s configurationVersion %d",
932 version < 1 ? "invalid" : "unsupported", version);
933 ✗ return AVERROR_INVALIDDATA;
934 }
935
936 12 descriptors_size = ffio_read_leb(pb);
937
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)
938 ✗ return AVERROR_INVALIDDATA;
939
940 12 st = c->fc->streams[c->fc->nb_streams - 1];
941 12 sc = st->priv_data;
942
943
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->extradata) {
944 ✗ av_log(c->fc, AV_LOG_WARNING, "ignoring iacb\n");
945 ✗ return 0;
946 }
947
948 12 sc->iamf = av_mallocz(sizeof(*sc->iamf));
949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!sc->iamf)
950 ✗ return AVERROR(ENOMEM);
951 12 iamf = &sc->iamf->iamf;
952
953 12 ret = ff_alloc_extradata(st->codecpar, descriptors_size);
954
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
955 ✗ return ret;
956
957 12 ret = avio_read(pb, st->codecpar->extradata, descriptors_size);
958
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret != descriptors_size)
959 ✗ return ret < 0 ? ret : AVERROR_INVALIDDATA;
960
961 12 ffio_init_read_context(&b, st->codecpar->extradata, descriptors_size);
962 12 descriptor_pb = &b.pub;
963
964 12 ret = ff_iamfdec_read_descriptors(iamf, descriptor_pb, descriptors_size, c->fc);
965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
966 ✗ return ret;
967
968 12 metadata = st->metadata;
969 12 st->metadata = NULL;
970 12 start_time = st->start_time;
971 12 nb_frames = st->nb_frames;
972 12 duration = st->duration;
973 12 disposition = st->disposition;
974
975
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_audio_elements; i++) {
976 12 IAMFAudioElement *audio_element = iamf->audio_elements[i];
977 const AVIAMFAudioElement *element;
978 AVStreamGroup *stg =
979 12 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, NULL);
980
981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!stg) {
982 ✗ ret = AVERROR(ENOMEM);
983 ✗ goto fail;
984 }
985
986 12 av_iamf_audio_element_free(&stg->params.iamf_audio_element);
987 12 stg->id = audio_element->audio_element_id;
988 /* Transfer ownership */
989 12 element = stg->params.iamf_audio_element = audio_element->element;
990 12 audio_element->element = NULL;
991
992
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < audio_element->nb_substreams; j++) {
993 64 IAMFSubStream *substream = &audio_element->substreams[j];
994 AVStream *stream;
995
996
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) {
997
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
12 if (audio_element->layers[0].substream_count != 1)
998 2 disposition &= ~AV_DISPOSITION_DEFAULT;
999 12 stream = st;
1000 } else
1001 52 stream = avformat_new_stream(c->fc, NULL);
1002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (!stream) {
1003 ✗ ret = AVERROR(ENOMEM);
1004 ✗ goto fail;
1005 }
1006
1007 64 stream->start_time = start_time;
1008 64 stream->nb_frames = nb_frames;
1009 64 stream->duration = duration;
1010 64 stream->disposition = disposition;
1011
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 12 times.
64 if (stream != st) {
1012 52 stream->priv_data = sc;
1013 52 sc->refcount++;
1014 }
1015
1016
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 56 times.
64 if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
1017 8 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1018
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) {
1019 52 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1020
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 6 times.
52 if (audio_element->layers[0].substream_count == 1)
1021 46 stream->disposition &= ~AV_DISPOSITION_DEFAULT;
1022 }
1023
1024 64 ret = avcodec_parameters_copy(stream->codecpar, substream->codecpar);
1025
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
1026 ✗ goto fail;
1027
1028 64 stream->id = substream->audio_substream_id;
1029
1030 64 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
1031
1032 64 ret = avformat_stream_group_add_stream(stg, stream);
1033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
1034 ✗ goto fail;
1035 }
1036
1037 12 ret = av_dict_copy(&stg->metadata, metadata, 0);
1038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1039 ✗ goto fail;
1040 }
1041
1042
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1043 12 IAMFMixPresentation *mix_presentation = iamf->mix_presentations[i];
1044 12 const AVIAMFMixPresentation *mix = mix_presentation->cmix;
1045 AVStreamGroup *stg =
1046 12 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, NULL);
1047
1048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!stg) {
1049 ✗ ret = AVERROR(ENOMEM);
1050 ✗ goto fail;
1051 }
1052
1053 12 av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
1054 12 stg->id = mix_presentation->mix_presentation_id;
1055 /* Transfer ownership */
1056 12 stg->params.iamf_mix_presentation = mix_presentation->mix;
1057 12 mix_presentation->mix = NULL;
1058
1059
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 12 times.
26 for (int j = 0; j < mix->nb_submixes; j++) {
1060 14 const AVIAMFSubmix *submix = mix->submixes[j];
1061
1062
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
28 for (int k = 0; k < submix->nb_elements; k++) {
1063 14 const AVIAMFSubmixElement *submix_element = submix->elements[k];
1064 14 const AVStreamGroup *audio_element = NULL;
1065
1066
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 for (int l = 0; l < c->fc->nb_stream_groups; l++)
1067
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 &&
1068
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 c->fc->stream_groups[l]->id == submix_element->audio_element_id) {
1069 14 audio_element = c->fc->stream_groups[l];
1070 14 break;
1071 }
1072
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 av_assert0(audio_element);
1073
1074
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 14 times.
80 for (int l = 0; l < audio_element->nb_entries; l++) {
1075 66 ret = avformat_stream_group_add_stream(stg, audio_element->entries[l]->stream);
1076
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))
1077 ✗ goto fail;
1078 }
1079 }
1080 }
1081
1082 12 ret = av_dict_copy(&stg->metadata, metadata, 0);
1083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1084 ✗ goto fail;
1085 }
1086
1087 12 ret = 0;
1088 12 fail:
1089 12 av_dict_free(&metadata);
1090
1091 12 return ret;
1092 }
1093 #endif
1094
1095 5 static int mov_read_srat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1096 {
1097 AVStream *st;
1098 int32_t sample_rate;
1099
1100
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)
1101 ✗ return 0;
1102
1103 5 st = c->fc->streams[c->fc->nb_streams-1];
1104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
1105 ✗ av_log(c->fc, AV_LOG_WARNING, "'srat' within non-audio sample entry, skip\n");
1106 ✗ return 0;
1107 }
1108
1109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!c->isom) {
1110 ✗ av_log(c->fc, AV_LOG_WARNING, "'srat' within non-isom, skip\n");
1111 ✗ return 0;
1112 }
1113
1114 5 avio_skip(pb, 4); // version+flags
1115 5 sample_rate = avio_rb32(pb);
1116
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (sample_rate > 0) {
1117 5 av_log(c->fc, AV_LOG_DEBUG,
1118 "overwrite sample rate from %d to %d by 'srat'\n",
1119 5 st->codecpar->sample_rate, sample_rate);
1120 5 st->codecpar->sample_rate = sample_rate;
1121 } else {
1122 ✗ av_log(c->fc, AV_LOG_WARNING,
1123 "ignore invalid sample rate %d in 'srat'\n", sample_rate);
1124 }
1125
1126 5 return 0;
1127 }
1128
1129 4 static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1130 {
1131 AVStream *st;
1132 AVPacketSideData *sd;
1133 enum AVAudioServiceType *ast;
1134 int eac3info, acmod, lfeon, bsmod;
1135 uint64_t mask;
1136 int ret;
1137
1138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
1139 ✗ return 0;
1140 4 st = c->fc->streams[c->fc->nb_streams-1];
1141
1142 /* Preserve the complete EC3SpecificBox payload, including optional
1143 * extensions such as E-AC-3 JOC signaling. */
1144
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (atom.size < 5 || (uint64_t)atom.size > (1 << 30))
1145 ✗ return AVERROR_INVALIDDATA;
1146 4 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
1147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
1148 ✗ return ret;
1149
1150 4 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1151 4 &st->codecpar->nb_coded_side_data,
1152 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
1153 sizeof(*ast), 0);
1154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sd)
1155 ✗ return AVERROR(ENOMEM);
1156
1157 4 ast = (enum AVAudioServiceType*)sd->data;
1158
1159 4 eac3info = AV_RB24(st->codecpar->extradata + 2);
1160 4 bsmod = (eac3info >> 12) & 0x1f;
1161 4 acmod = (eac3info >> 9) & 0x7;
1162 4 lfeon = (eac3info >> 8) & 0x1;
1163
1164 4 mask = ff_ac3_channel_layout_tab[acmod];
1165
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (lfeon)
1166 1 mask |= AV_CH_LOW_FREQUENCY;
1167 4 av_channel_layout_uninit(&st->codecpar->ch_layout);
1168 4 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
1169
1170 4 *ast = bsmod;
1171
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)
1172 ✗ *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
1173
1174 4 return 0;
1175 }
1176
1177 /* Maps the DTS `StreamConstruction` field (ETSI TS 102 114 Table E-2) to the
1178 * coarse FFmpeg DTS profile enum. Extension-substream XLL maps to HD_MA;
1179 * extension-substream XXCH, X96, or XBR maps to HD_HRA; core-substream XCH or
1180 * XXCH maps to ES; core-substream X96 maps to 96/24; a core component alone
1181 * maps to DTS; and extension-substream LBR maps to Express. Value 0 (undefined)
1182 * and values outside 1..21 map to AV_PROFILE_UNKNOWN. */
1183 ✗ static int mov_dts_stream_construction_to_profile(unsigned int sc)
1184 {
1185 static const int profile[22] = {
1186 [ 1] = AV_PROFILE_DTS, /* core Core */
1187 [ 2] = AV_PROFILE_DTS_ES, /* core Core + core XCH */
1188 [ 3] = AV_PROFILE_DTS_ES, /* core Core + core XXCH */
1189 [ 4] = AV_PROFILE_DTS_96_24, /* core Core + core X96 */
1190 [ 5] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XXCH */
1191 [ 6] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XBR */
1192 [ 7] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XCH + ext XBR */
1193 [ 8] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XXCH + ext XBR */
1194 [ 9] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XXCH + ext XBR */
1195 [10] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext X96 */
1196 [11] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XCH + ext X96 */
1197 [12] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XXCH + ext X96 */
1198 [13] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XXCH + ext X96 */
1199 [14] = AV_PROFILE_DTS_HD_MA, /* core Core + ext XLL */
1200 [15] = AV_PROFILE_DTS_HD_MA, /* core Core + core XCH + ext XLL */
1201 [16] = AV_PROFILE_DTS_HD_MA, /* core Core + core X96 + ext XLL */
1202 [17] = AV_PROFILE_DTS_HD_MA, /* ext XLL */
1203 [18] = AV_PROFILE_DTS_EXPRESS, /* ext LBR */
1204 [19] = AV_PROFILE_DTS, /* ext Core */
1205 [20] = AV_PROFILE_DTS_HD_HRA, /* ext Core + ext XXCH */
1206 [21] = AV_PROFILE_DTS_HD_MA, /* ext Core + ext XLL */
1207 };
1208 ✗ if (!sc || sc > 21)
1209 ✗ return AV_PROFILE_UNKNOWN;
1210 ✗ return profile[sc];
1211 }
1212
1213 /* Maps the 16-bit DTS `ChannelLayout` bitmask (ETSI TS 102 114 Table E-5) to an
1214 * ffmpeg channel mask. Pair bits follow Table 7-10 / DCA_SPEAKER_PAIR_*;
1215 * LwRw (0x0400) and LssRss (0x0800) must not collapse onto SIDE like LsRs. */
1216 ✗ static uint64_t mov_dts_channel_layout_to_mask(unsigned int code)
1217 {
1218 static const struct { unsigned int dts; uint64_t av; } map[] = {
1219 { 0x0001, AV_CH_FRONT_CENTER },
1220 { 0x0002, AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT },
1221 { 0x0004, AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT },
1222 { 0x0008, AV_CH_LOW_FREQUENCY },
1223 { 0x0010, AV_CH_BACK_CENTER },
1224 { 0x0020, AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT },
1225 { 0x0040, AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT },
1226 { 0x0080, AV_CH_TOP_FRONT_CENTER },
1227 { 0x0100, AV_CH_TOP_CENTER },
1228 { 0x0200, AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER },
1229 { 0x0400, AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT },
1230 { 0x0800, AV_CH_SIDE_SURROUND_LEFT | AV_CH_SIDE_SURROUND_RIGHT },
1231 { 0x1000, AV_CH_LOW_FREQUENCY_2 },
1232 { 0x2000, AV_CH_TOP_SIDE_LEFT | AV_CH_TOP_SIDE_RIGHT },
1233 { 0x4000, AV_CH_TOP_BACK_CENTER },
1234 { 0x8000, AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT },
1235 };
1236 ✗ uint64_t mask = 0;
1237 int i;
1238 ✗ for (i = 0; i < FF_ARRAY_ELEMS(map); i++)
1239 ✗ if (code & map[i].dts)
1240 ✗ mask |= map[i].av;
1241 ✗ return mask;
1242 }
1243
1244 ✗ static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1245 {
1246 #define DDTS_SIZE 20
1247 uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
1248 ✗ AVStream *st = NULL;
1249 ✗ uint32_t frame_duration_code = 0;
1250 ✗ uint32_t channel_layout_code = 0;
1251 uint64_t channel_layout_mask;
1252 unsigned int stream_construction;
1253 unsigned int representation_type;
1254 GetBitContext gb;
1255 int ret;
1256
1257 ✗ if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
1258 ✗ return ret;
1259
1260 ✗ init_get_bits(&gb, buf, 8 * DDTS_SIZE);
1261
1262 ✗ if (c->fc->nb_streams < 1) {
1263 ✗ return 0;
1264 }
1265 ✗ st = c->fc->streams[c->fc->nb_streams-1];
1266
1267 ✗ st->codecpar->sample_rate = get_bits_long(&gb, 32);
1268 ✗ if (st->codecpar->sample_rate <= 0) {
1269 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
1270 ✗ return AVERROR_INVALIDDATA;
1271 }
1272 ✗ skip_bits_long(&gb, 32); /* max bitrate */
1273 ✗ st->codecpar->bit_rate = get_bits_long(&gb, 32);
1274 ✗ st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
1275 ✗ frame_duration_code = get_bits(&gb, 2);
1276 ✗ stream_construction = get_bits(&gb, 5); /* Table E-2 - profile source */
1277 ✗ skip_bits(&gb, 1); /* CoreLFEPresent */
1278 ✗ skip_bits(&gb, 6); /* CoreLayout */
1279 ✗ skip_bits(&gb, 14); /* CoreSize */
1280 ✗ skip_bits(&gb, 1); /* StereoDownmix */
1281 ✗ representation_type = get_bits(&gb, 3);
1282 ✗ channel_layout_code = get_bits(&gb, 16);
1283
1284 ✗ st->codecpar->frame_size =
1285 ✗ (frame_duration_code == 0) ? 512 :
1286 ✗ (frame_duration_code == 1) ? 1024 :
1287 ✗ (frame_duration_code == 2) ? 2048 :
1288 ✗ (frame_duration_code == 3) ? 4096 : 0;
1289
1290 /* Publish StreamConstruction as codecpar->profile, including for encrypted
1291 * tracks where frame headers cannot be inspected. */
1292 ✗ st->codecpar->profile = mov_dts_stream_construction_to_profile(stream_construction);
1293
1294 ✗ channel_layout_mask = mov_dts_channel_layout_to_mask(channel_layout_code);
1295 ✗ if (channel_layout_mask) {
1296 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
1297 ✗ av_channel_layout_from_mask(&st->codecpar->ch_layout, channel_layout_mask);
1298 ✗ } else if (representation_type == 2 || representation_type == 3) {
1299 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
1300 ✗ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
1301 }
1302
1303 ✗ return 0;
1304 }
1305
1306 50 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1307 {
1308 AVStream *st;
1309
1310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (c->fc->nb_streams < 1)
1311 ✗ return 0;
1312 50 st = c->fc->streams[c->fc->nb_streams-1];
1313
1314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (atom.size < 16)
1315 ✗ return 0;
1316
1317 /* skip version and flags */
1318 50 avio_skip(pb, 4);
1319
1320 50 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
1321
1322 50 return 0;
1323 }
1324
1325 5 static int mov_read_chnl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1326 {
1327 5 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
1328 int version, flags;
1329 int ret;
1330 AVStream *st;
1331
1332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
1333 ✗ return 0;
1334 5 st = c->fc->streams[c->fc->nb_streams-1];
1335
1336 5 version = avio_r8(pb);
1337 5 flags = avio_rb24(pb);
1338
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) {
1339 ✗ av_log(c->fc, AV_LOG_WARNING,
1340 "Unsupported 'chnl' box with version %d, flags: %#x\n",
1341 version, flags);
1342 ✗ return 0;
1343 }
1344
1345 5 ret = ff_mov_read_chnl(c->fc, pb, st, version);
1346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0) {
1347 ✗ avio_seek(pb, end, SEEK_SET);
1348 ✗ return 0;
1349 }
1350
1351
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_tell(pb) != end) {
1352 ✗ av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data inside chnl\n",
1353 ✗ end - avio_tell(pb));
1354 ✗ avio_seek(pb, end, SEEK_SET);
1355 }
1356 5 return ret;
1357 }
1358
1359 2 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1360 {
1361 AVStream *st;
1362 int ret;
1363
1364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
1365 ✗ return 0;
1366 2 st = c->fc->streams[c->fc->nb_streams-1];
1367
1368
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)
1369 ✗ av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
1370
1371 2 return ret;
1372 }
1373
1374 21 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1375 {
1376 AVStream *st;
1377 HEIFItem *item;
1378 AVPacketSideData *sd;
1379 21 int width, height, err = 0;
1380 AVRational aperture_width, aperture_height, horiz_off, vert_off;
1381 AVRational pc_x, pc_y;
1382 int64_t top, bottom, left, right;
1383
1384 21 item = get_heif_item(c, c->cur_item_id);
1385 21 st = get_curr_st(c);
1386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!st)
1387 ✗ return 0;
1388
1389 21 width = st->codecpar->width;
1390 21 height = st->codecpar->height;
1391
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) {
1392 6 width = item->width;
1393 6 height = item->height;
1394 }
1395
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
21 if (!width || !height) {
1396 ✗ err = AVERROR_INVALIDDATA;
1397 ✗ goto fail;
1398 }
1399
1400 21 aperture_width.num = avio_rb32(pb);
1401 21 aperture_width.den = avio_rb32(pb);
1402 21 aperture_height.num = avio_rb32(pb);
1403 21 aperture_height.den = avio_rb32(pb);
1404
1405 21 horiz_off.num = avio_rb32(pb);
1406 21 horiz_off.den = avio_rb32(pb);
1407 21 vert_off.num = avio_rb32(pb);
1408 21 vert_off.den = avio_rb32(pb);
1409
1410
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 ||
1411
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 ||
1412
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) {
1413 ✗ err = AVERROR_INVALIDDATA;
1414 ✗ goto fail;
1415 }
1416
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) ||
1417 18 (av_cmp_q((AVRational) { height, 1 }, aperture_height) < 0)) {
1418 3 err = AVERROR_INVALIDDATA;
1419 3 goto fail;
1420 }
1421 18 av_log(c->fc, AV_LOG_TRACE, "clap: apertureWidth %d/%d, apertureHeight %d/%d "
1422 "horizOff %d/%d vertOff %d/%d\n",
1423 aperture_width.num, aperture_width.den, aperture_height.num, aperture_height.den,
1424 horiz_off.num, horiz_off.den, vert_off.num, vert_off.den);
1425
1426 18 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1427 18 pc_x = av_add_q(pc_x, horiz_off);
1428 18 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1429 18 pc_y = av_add_q(pc_y, vert_off);
1430
1431 18 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1432 18 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1433 18 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1434 18 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1435
1436 18 left = av_q2d(av_sub_q(pc_x, aperture_width));
1437 18 right = av_q2d(av_add_q(pc_x, aperture_width));
1438 18 top = av_q2d(av_sub_q(pc_y, aperture_height));
1439 18 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1440
1441
4/8
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
18 if (top < 0 || bottom < 0 || bottom > (height - 1) ||
1442
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 left < 0 || right < 0 || right > (width - 1)) {
1443 ✗ err = AVERROR_INVALIDDATA;
1444 ✗ goto fail;
1445 }
1446
1447 18 bottom = height - 1 - bottom;
1448 18 right = width - 1 - right;
1449
1450
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
18 if (!(left | right | top | bottom))
1451 6 return 0;
1452
1453
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if ((left + right) >= width ||
1454
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 (top + bottom) >= height) {
1455 ✗ err = AVERROR_INVALIDDATA;
1456 ✗ goto fail;
1457 }
1458
1459 12 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1460 12 &st->codecpar->nb_coded_side_data,
1461 AV_PKT_DATA_FRAME_CROPPING,
1462 sizeof(uint32_t) * 4, 0);
1463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!sd)
1464 ✗ return AVERROR(ENOMEM);
1465
1466 12 AV_WL32A(sd->data, top);
1467 12 AV_WL32A(sd->data + 4, bottom);
1468 12 AV_WL32A(sd->data + 8, left);
1469 12 AV_WL32A(sd->data + 12, right);
1470
1471 15 fail:
1472
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 12 times.
15 if (err < 0) {
1473 3 int explode = !!(c->fc->error_recognition & AV_EF_EXPLODE);
1474
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");
1475
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!explode)
1476 3 err = 0;
1477 }
1478
1479 15 return err;
1480 }
1481
1482 /* This atom overrides any previously set aspect ratio */
1483 108 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1484 {
1485 108 const int num = avio_rb32(pb);
1486 108 const int den = avio_rb32(pb);
1487 AVStream *st;
1488 MOVStreamContext *sc;
1489
1490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (c->fc->nb_streams < 1)
1491 ✗ return 0;
1492 108 st = c->fc->streams[c->fc->nb_streams-1];
1493 108 sc = st->priv_data;
1494
1495 108 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1496
1497
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 2 times.
108 if (den != 0) {
1498 106 sc->h_spacing = num;
1499 106 sc->v_spacing = den;
1500 }
1501 108 return 0;
1502 }
1503
1504 /* this atom contains actual media data */
1505 1085 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1506 {
1507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1085 times.
1085 if (atom.size == 0) /* wrong one (MP4) */
1508 ✗ return 0;
1509 1085 c->found_mdat=1;
1510 1085 return 0; /* now go for moov */
1511 }
1512
1513 #define DRM_BLOB_SIZE 56
1514
1515 ✗ static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1516 {
1517 uint8_t intermediate_key[20];
1518 uint8_t intermediate_iv[20];
1519 uint8_t input[64];
1520 uint8_t output[64];
1521 uint8_t file_checksum[20];
1522 uint8_t calculated_checksum[20];
1523 char checksum_string[2 * sizeof(file_checksum) + 1];
1524 struct AVSHA *sha;
1525 int i;
1526 ✗ int ret = 0;
1527 ✗ uint8_t *activation_bytes = c->activation_bytes;
1528 ✗ uint8_t *fixed_key = c->audible_fixed_key;
1529
1530 ✗ c->aax_mode = 1;
1531
1532 ✗ sha = av_sha_alloc();
1533 ✗ if (!sha)
1534 ✗ return AVERROR(ENOMEM);
1535 ✗ av_free(c->aes_decrypt);
1536 ✗ c->aes_decrypt = av_aes_alloc();
1537 ✗ if (!c->aes_decrypt) {
1538 ✗ ret = AVERROR(ENOMEM);
1539 ✗ goto fail;
1540 }
1541
1542 /* drm blob processing */
1543 ✗ avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1544 ✗ avio_read(pb, input, DRM_BLOB_SIZE);
1545 ✗ avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1546 ✗ ret = ffio_read_size(pb, file_checksum, 20);
1547 ✗ if (ret < 0)
1548 ✗ goto fail;
1549
1550 // required by external tools
1551 ✗ ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1);
1552 ✗ av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string);
1553
1554 /* verify activation data */
1555 ✗ if (!activation_bytes) {
1556 ✗ av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1557 ✗ ret = 0; /* allow ffprobe to continue working on .aax files */
1558 ✗ goto fail;
1559 }
1560 ✗ if (c->activation_bytes_size != 4) {
1561 ✗ av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1562 ✗ ret = AVERROR(EINVAL);
1563 ✗ goto fail;
1564 }
1565
1566 /* verify fixed key */
1567 ✗ if (c->audible_fixed_key_size != 16) {
1568 ✗ av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1569 ✗ ret = AVERROR(EINVAL);
1570 ✗ goto fail;
1571 }
1572
1573 /* AAX (and AAX+) key derivation */
1574 ✗ av_sha_init(sha, 160);
1575 ✗ av_sha_update(sha, fixed_key, 16);
1576 ✗ av_sha_update(sha, activation_bytes, 4);
1577 ✗ av_sha_final(sha, intermediate_key);
1578 ✗ av_sha_init(sha, 160);
1579 ✗ av_sha_update(sha, fixed_key, 16);
1580 ✗ av_sha_update(sha, intermediate_key, 20);
1581 ✗ av_sha_update(sha, activation_bytes, 4);
1582 ✗ av_sha_final(sha, intermediate_iv);
1583 ✗ av_sha_init(sha, 160);
1584 ✗ av_sha_update(sha, intermediate_key, 16);
1585 ✗ av_sha_update(sha, intermediate_iv, 16);
1586 ✗ av_sha_final(sha, calculated_checksum);
1587 ✗ if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1588 ✗ av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1589 ✗ ret = AVERROR_INVALIDDATA;
1590 ✗ goto fail;
1591 }
1592 ✗ av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1593 ✗ av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1594 ✗ for (i = 0; i < 4; i++) {
1595 // file data (in output) is stored in big-endian mode
1596 ✗ if (activation_bytes[i] != output[3 - i]) { // critical error
1597 ✗ av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1598 ✗ ret = AVERROR_INVALIDDATA;
1599 ✗ goto fail;
1600 }
1601 }
1602 ✗ memcpy(c->file_key, output + 8, 16);
1603 ✗ memcpy(input, output + 26, 16);
1604 ✗ av_sha_init(sha, 160);
1605 ✗ av_sha_update(sha, input, 16);
1606 ✗ av_sha_update(sha, c->file_key, 16);
1607 ✗ av_sha_update(sha, fixed_key, 16);
1608 ✗ av_sha_final(sha, c->file_iv);
1609
1610 ✗ fail:
1611 ✗ av_free(sha);
1612
1613 ✗ return ret;
1614 }
1615
1616 ✗ static int mov_aaxc_crypto(MOVContext *c)
1617 {
1618 ✗ if (c->audible_key_size != 16) {
1619 ✗ av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n");
1620 ✗ return AVERROR(EINVAL);
1621 }
1622
1623 ✗ if (c->audible_iv_size != 16) {
1624 ✗ av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n");
1625 ✗ return AVERROR(EINVAL);
1626 }
1627
1628 ✗ c->aes_decrypt = av_aes_alloc();
1629 ✗ if (!c->aes_decrypt) {
1630 ✗ return AVERROR(ENOMEM);
1631 }
1632
1633 ✗ memcpy(c->file_key, c->audible_key, 16);
1634 ✗ memcpy(c->file_iv, c->audible_iv, 16);
1635 ✗ c->aax_mode = 1;
1636
1637 ✗ return 0;
1638 }
1639
1640 // Audible AAX (and AAX+) bytestream decryption
1641 ✗ static int aax_filter(uint8_t *input, int size, MOVContext *c)
1642 {
1643 ✗ int blocks = 0;
1644 unsigned char iv[16];
1645
1646 ✗ memcpy(iv, c->file_iv, 16); // iv is overwritten
1647 ✗ blocks = size >> 4; // trailing bytes are not encrypted!
1648 ✗ av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1649 ✗ av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1650
1651 ✗ return 0;
1652 }
1653
1654 /* read major brand, minor version and compatible brands and store them as metadata */
1655 565 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1656 {
1657 uint32_t minor_ver;
1658 int comp_brand_size;
1659 char* comp_brands_str;
1660 565 uint8_t type[5] = {0};
1661 565 int ret = ffio_read_size(pb, type, 4);
1662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 565 times.
565 if (ret < 0)
1663 ✗ return ret;
1664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 565 times.
565 if (c->fc->nb_streams) {
1665 ✗ if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1666 ✗ return AVERROR_INVALIDDATA;
1667 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate FTYP\n");
1668 ✗ return 0;
1669 }
1670
1671
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 245 times.
565 if (strcmp(type, "qt "))
1672 320 c->isom = 1;
1673 565 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1674 565 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1675 565 minor_ver = avio_rb32(pb); /* minor version */
1676 565 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1677
1678 565 comp_brand_size = atom.size - 8;
1679
2/4
✓ Branch 0 taken 565 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 565 times.
565 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1680 ✗ return AVERROR_INVALIDDATA;
1681 565 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 565 times.
565 if (!comp_brands_str)
1683 ✗ return AVERROR(ENOMEM);
1684
1685 565 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 565 times.
565 if (ret < 0) {
1687 ✗ av_freep(&comp_brands_str);
1688 ✗ return ret;
1689 }
1690 565 comp_brands_str[comp_brand_size] = 0;
1691 565 av_dict_set(&c->fc->metadata, "compatible_brands",
1692 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1693
1694 // Logic for handling Audible's .aaxc files
1695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 565 times.
565 if (!strcmp(type, "aaxc")) {
1696 ✗ mov_aaxc_crypto(c);
1697 }
1698
1699 565 return 0;
1700 }
1701
1702 /* this atom should contain all header atoms */
1703 608 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1704 {
1705 int ret;
1706
1707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 if (c->found_moov) {
1708 ✗ av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1709 ✗ avio_skip(pb, atom.size);
1710 ✗ return 0;
1711 }
1712
1713
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 608 times.
608 if ((ret = mov_read_default(c, pb, atom)) < 0)
1714 ✗ return ret;
1715 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1716 /* so we don't parse the whole file if over a network */
1717 608 c->found_moov=1;
1718 608 return 0; /* now go for mdat */
1719 }
1720
1721 6232 static MOVFragmentStreamInfo * get_frag_stream_info(
1722 MOVFragmentIndex *frag_index,
1723 int index,
1724 int id)
1725 {
1726 int i;
1727 MOVFragmentIndexItem * item;
1728
1729
2/4
✓ Branch 0 taken 6232 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6232 times.
6232 if (index < 0 || index >= frag_index->nb_items)
1730 ✗ return NULL;
1731 6232 item = &frag_index->item[index];
1732
1/2
✓ Branch 0 taken 154916 times.
✗ Branch 1 not taken.
154916 for (i = 0; i < item->nb_stream_info; i++)
1733
2/2
✓ Branch 0 taken 6232 times.
✓ Branch 1 taken 148684 times.
154916 if (item->stream_info[i].id == id)
1734 6232 return &item->stream_info[i];
1735
1736 // This shouldn't happen
1737 ✗ return NULL;
1738 }
1739
1740 706 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1741 {
1742 int i;
1743 MOVFragmentIndexItem * item;
1744
1745
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (frag_index->current < 0 ||
1746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 frag_index->current >= frag_index->nb_items)
1747 ✗ return;
1748
1749 706 item = &frag_index->item[frag_index->current];
1750
1/2
✓ Branch 0 taken 10665 times.
✗ Branch 1 not taken.
10665 for (i = 0; i < item->nb_stream_info; i++)
1751
2/2
✓ Branch 0 taken 706 times.
✓ Branch 1 taken 9959 times.
10665 if (item->stream_info[i].id == id) {
1752 706 item->current = i;
1753 706 return;
1754 }
1755
1756 // id not found. This shouldn't happen.
1757 ✗ item->current = -1;
1758 }
1759
1760 2072 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1761 MOVFragmentIndex *frag_index)
1762 {
1763 MOVFragmentIndexItem *item;
1764
1/2
✓ Branch 0 taken 2072 times.
✗ Branch 1 not taken.
2072 if (frag_index->current < 0 ||
1765
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 2051 times.
2072 frag_index->current >= frag_index->nb_items)
1766 21 return NULL;
1767
1768 2051 item = &frag_index->item[frag_index->current];
1769
2/4
✓ Branch 0 taken 2051 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2051 times.
✗ Branch 3 not taken.
2051 if (item->current >= 0 && item->current < item->nb_stream_info)
1770 2051 return &item->stream_info[item->current];
1771
1772 // This shouldn't happen
1773 ✗ return NULL;
1774 }
1775
1776 1113 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1777 {
1778 int a, b, m;
1779 int64_t moof_offset;
1780
1781 // Optimize for appending new entries
1782
2/2
✓ Branch 0 taken 1089 times.
✓ Branch 1 taken 24 times.
1113 if (!frag_index->nb_items ||
1783
2/2
✓ Branch 0 taken 469 times.
✓ Branch 1 taken 620 times.
1089 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1784 493 return frag_index->nb_items;
1785
1786 620 a = -1;
1787 620 b = frag_index->nb_items;
1788
1789
2/2
✓ Branch 0 taken 2980 times.
✓ Branch 1 taken 620 times.
3600 while (b - a > 1) {
1790 2980 m = (a + b) >> 1;
1791 2980 moof_offset = frag_index->item[m].moof_offset;
1792
2/2
✓ Branch 0 taken 950 times.
✓ Branch 1 taken 2030 times.
2980 if (moof_offset >= offset)
1793 950 b = m;
1794
2/2
✓ Branch 0 taken 2648 times.
✓ Branch 1 taken 332 times.
2980 if (moof_offset <= offset)
1795 2648 a = m;
1796 }
1797 620 return b;
1798 }
1799
1800 7 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1801 {
1802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 av_assert0(frag_stream_info);
1803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1804 ✗ return frag_stream_info->sidx_pts;
1805
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1806 4 return frag_stream_info->first_tfra_pts;
1807 3 return frag_stream_info->tfdt_dts;
1808 }
1809
1810 226 static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1811 MOVFragmentIndex *frag_index, int index)
1812 {
1813 MOVFragmentStreamInfo * frag_stream_info;
1814 226 MOVStreamContext *sc = dst_st->priv_data;
1815 int64_t timestamp;
1816 int i, j;
1817
1818 // If the stream is referenced by any sidx, limit the search
1819 // to fragments that referenced this stream in the sidx
1820
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 7 times.
226 if (sc->has_sidx) {
1821 219 frag_stream_info = get_frag_stream_info(frag_index, index, sc->id);
1822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!frag_stream_info)
1823 ✗ return AV_NOPTS_VALUE;
1824
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1825 219 return frag_stream_info->sidx_pts;
1826 ✗ if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1827 ✗ return frag_stream_info->first_tfra_pts;
1828 ✗ return frag_stream_info->sidx_pts;
1829 }
1830
1831
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++) {
1832
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)
1833 5 continue;
1834 7 AVStream *frag_stream = NULL;
1835 7 frag_stream_info = &frag_index->item[index].stream_info[i];
1836
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
21 for (j = 0; j < s->nb_streams; j++) {
1837 14 MOVStreamContext *sc2 = s->streams[j]->priv_data;
1838
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (sc2->id == frag_stream_info->id)
1839 7 frag_stream = s->streams[j];
1840 }
1841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!frag_stream) {
1842 ✗ av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1843 ✗ continue;
1844 }
1845 7 timestamp = get_stream_info_time(frag_stream_info);
1846
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (timestamp != AV_NOPTS_VALUE)
1847 4 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1848 }
1849 3 return AV_NOPTS_VALUE;
1850 }
1851
1852 28 static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1853 AVStream *st, int64_t timestamp)
1854 {
1855 int a, b, m, m0;
1856 int64_t frag_time;
1857
1858 28 a = -1;
1859 28 b = frag_index->nb_items;
1860
1861
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 28 times.
252 while (b - a > 1) {
1862 224 m0 = m = (a + b) >> 1;
1863
1864
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 &&
1865 226 (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
1866 3 m++;
1867
1868
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)
1869 95 a = m;
1870 else
1871 129 b = m0;
1872 }
1873
1874 28 return a;
1875 }
1876
1877 1063 static int update_frag_index(MOVContext *c, int64_t offset)
1878 {
1879 int index, i;
1880 MOVFragmentIndexItem * item;
1881 MOVFragmentStreamInfo * frag_stream_info;
1882
1883 // If moof_offset already exists in frag_index, return index to it
1884 1063 index = search_frag_moof_offset(&c->frag_index, offset);
1885
2/2
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 484 times.
1063 if (index < c->frag_index.nb_items &&
1886
2/2
✓ Branch 0 taken 577 times.
✓ Branch 1 taken 2 times.
579 c->frag_index.item[index].moof_offset == offset)
1887 577 return index;
1888
1889 // offset is not yet in frag index.
1890 // Insert new item at index (sorted by moof offset)
1891 486 item = av_fast_realloc(c->frag_index.item,
1892 486 &c->frag_index.allocated_size,
1893 486 (c->frag_index.nb_items + 1) *
1894 sizeof(*c->frag_index.item));
1895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486 times.
486 if (!item)
1896 ✗ return -1;
1897 486 c->frag_index.item = item;
1898
1899 486 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1900 sizeof(*item->stream_info));
1901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486 times.
486 if (!frag_stream_info)
1902 ✗ return -1;
1903
1904
2/2
✓ Branch 0 taken 786 times.
✓ Branch 1 taken 486 times.
1272 for (i = 0; i < c->fc->nb_streams; i++) {
1905 // Avoid building frag index if streams lack track id.
1906 786 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1907
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 786 times.
786 if (sc->id < 0) {
1908 ✗ av_free(frag_stream_info);
1909 ✗ return AVERROR_INVALIDDATA;
1910 }
1911
1912 786 frag_stream_info[i].id = sc->id;
1913 786 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1914 786 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1915 786 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1916 786 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1917 786 frag_stream_info[i].index_base = -1;
1918 786 frag_stream_info[i].index_entry = -1;
1919 786 frag_stream_info[i].encryption_index = NULL;
1920 786 frag_stream_info[i].stsd_id = -1;
1921 }
1922
1923
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 484 times.
486 if (index < c->frag_index.nb_items)
1924 2 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1925 2 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1926
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 446 times.
486 if (index <= c->frag_index.current)
1927 40 c->frag_index.current++;
1928
1929 486 item = &c->frag_index.item[index];
1930 486 item->headers_read = 0;
1931 486 item->current = 0;
1932 486 item->nb_stream_info = c->fc->nb_streams;
1933 486 item->moof_offset = offset;
1934 486 item->stream_info = frag_stream_info;
1935 486 c->frag_index.nb_items++;
1936
1937 486 return index;
1938 }
1939
1940 706 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1941 int id, int entries)
1942 {
1943 int i;
1944 MOVFragmentStreamInfo * frag_stream_info;
1945
1946
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (index < 0)
1947 706 return;
1948 ✗ for (i = index; i < frag_index->nb_items; i++) {
1949 ✗ frag_stream_info = get_frag_stream_info(frag_index, i, id);
1950 ✗ if (frag_stream_info && frag_stream_info->index_entry >= 0)
1951 ✗ frag_stream_info->index_entry += entries;
1952 }
1953 }
1954
1955 482 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1956 {
1957 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1958 482 c->fragment.found_tfhd = 0;
1959
1960
4/4
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 479 times.
482 if (!c->has_looked_for_mfra && c->use_mfra_for > 0) {
1961 1 c->has_looked_for_mfra = 1;
1962
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1963 int ret;
1964 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1965 "for a mfra\n");
1966
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((ret = mov_read_mfra(c, pb)) < 0) {
1967 ✗ av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1968 "read the mfra (may be a live ismv)\n");
1969 }
1970 } else {
1971 ✗ av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1972 "seekable, can not look for mfra\n");
1973 }
1974 }
1975 482 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1976 482 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1977 482 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1978 482 return mov_read_default(c, pb, atom);
1979 }
1980
1981 1443 static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version)
1982 {
1983 int64_t time;
1984
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1428 times.
1443 if (version == 1) {
1985 15 time = avio_rb64(pb);
1986 15 avio_rb64(pb);
1987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (time < 0) {
1988 ✗ av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n");
1989 ✗ return;
1990 }
1991 } else {
1992 1428 time = avio_rb32(pb);
1993 1428 avio_rb32(pb); /* modification time */
1994
4/4
✓ Branch 0 taken 649 times.
✓ Branch 1 taken 779 times.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 587 times.
1428 if (time > 0 && time < 2082844800) {
1995 62 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1996 62 time += 2082844800;
1997 }
1998 }
1999
2/2
✓ Branch 0 taken 655 times.
✓ Branch 1 taken 788 times.
1443 if (time) {
2000 655 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
2001
2002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 655 times.
655 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
2003 ✗ av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n");
2004 ✗ return;
2005 }
2006
2007 655 ff_dict_set_timestamp(metadata, "creation_time", time * 1000000);
2008 }
2009 }
2010
2011 838 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2012 {
2013 AVStream *st;
2014 MOVStreamContext *sc;
2015 int version;
2016 838 char language[4] = {0};
2017 unsigned lang;
2018
2019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->fc->nb_streams < 1)
2020 ✗ return 0;
2021 838 st = c->fc->streams[c->fc->nb_streams-1];
2022 838 sc = st->priv_data;
2023
2024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (sc->time_scale) {
2025 ✗ av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
2026 ✗ return AVERROR_INVALIDDATA;
2027 }
2028
2029 838 version = avio_r8(pb);
2030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (version > 1) {
2031 ✗ avpriv_request_sample(c->fc, "Version %d", version);
2032 ✗ return AVERROR_PATCHWELCOME;
2033 }
2034 838 avio_rb24(pb); /* flags */
2035 838 mov_metadata_creation_time(c, pb, &st->metadata, version);
2036
2037 838 sc->time_scale = avio_rb32(pb);
2038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (sc->time_scale <= 0) {
2039 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
2040 ✗ sc->time_scale = 1;
2041 }
2042
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 825 times.
838 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
2043
2044
6/6
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 825 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 825 times.
✓ Branch 5 taken 4 times.
838 if ((version == 1 && st->duration == UINT64_MAX) ||
2045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 825 times.
825 (version != 1 && st->duration == UINT32_MAX)) {
2046 9 st->duration = 0;
2047 }
2048
2049 838 lang = avio_rb16(pb); /* language */
2050
2/2
✓ Branch 1 taken 664 times.
✓ Branch 2 taken 174 times.
838 if (ff_mov_lang_to_iso639(lang, language))
2051 664 av_dict_set(&st->metadata, "language", language, 0);
2052 838 avio_rb16(pb); /* quality */
2053
2054 838 return 0;
2055 }
2056
2057 605 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2058 {
2059 int i;
2060 605 int version = avio_r8(pb); /* version */
2061 605 avio_rb24(pb); /* flags */
2062
2063 605 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
2064 605 c->time_scale = avio_rb32(pb); /* time scale */
2065
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 605 times.
605 if (c->time_scale <= 0) {
2066 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
2067 ✗ c->time_scale = 1;
2068 }
2069 605 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
2070
2071
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 603 times.
605 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
2072 605 avio_rb32(pb); /* preferred scale */
2073
2074 605 avio_rb16(pb); /* preferred volume */
2075
2076 605 avio_skip(pb, 10); /* reserved */
2077
2078 /* movie display matrix, store it in main context and use it later on */
2079
2/2
✓ Branch 0 taken 1815 times.
✓ Branch 1 taken 605 times.
2420 for (i = 0; i < 3; i++) {
2080 1815 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
2081 1815 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
2082 1815 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
2083 }
2084
2085 605 avio_rb32(pb); /* preview time */
2086 605 avio_rb32(pb); /* preview duration */
2087 605 avio_rb32(pb); /* poster time */
2088 605 avio_rb32(pb); /* selection time */
2089 605 avio_rb32(pb); /* selection duration */
2090 605 avio_rb32(pb); /* current time */
2091 605 avio_rb32(pb); /* next track ID */
2092
2093 605 return 0;
2094 }
2095
2096 7 static void set_last_stream_little_endian(AVFormatContext *fc)
2097 {
2098 AVStream *st;
2099
2100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (fc->nb_streams < 1)
2101 ✗ return;
2102 7 st = fc->streams[fc->nb_streams-1];
2103
2104
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) {
2105 5 case AV_CODEC_ID_PCM_S16BE:
2106 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2107 5 break;
2108 1 case AV_CODEC_ID_PCM_S24BE:
2109 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
2110 1 break;
2111 ✗ case AV_CODEC_ID_PCM_S32BE:
2112 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
2113 ✗ break;
2114 1 case AV_CODEC_ID_PCM_F32BE:
2115 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
2116 1 break;
2117 ✗ case AV_CODEC_ID_PCM_F64BE:
2118 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
2119 ✗ break;
2120 ✗ default:
2121 ✗ break;
2122 }
2123 }
2124
2125 5 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2126 {
2127 5 int little_endian = avio_rb16(pb) & 0xFF;
2128 5 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
2129
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (little_endian == 1)
2130 1 set_last_stream_little_endian(c->fc);
2131 5 return 0;
2132 }
2133
2134 6 static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2135 {
2136 int format_flags;
2137 int version, flags;
2138 int pcm_sample_size;
2139 6 AVFormatContext *fc = c->fc;
2140 AVStream *st;
2141 MOVStreamContext *sc;
2142
2143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 6) {
2144 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n");
2145 ✗ return AVERROR_INVALIDDATA;
2146 }
2147
2148 6 version = avio_r8(pb);
2149 6 flags = avio_rb24(pb);
2150
2151
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) {
2152 ✗ av_log(c->fc, AV_LOG_ERROR,
2153 "Unsupported 'pcmC' box with version %d, flags: %x",
2154 version, flags);
2155 ✗ return AVERROR_INVALIDDATA;
2156 }
2157
2158 6 format_flags = avio_r8(pb);
2159 6 pcm_sample_size = avio_r8(pb);
2160
2161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fc->nb_streams < 1)
2162 ✗ return AVERROR_INVALIDDATA;
2163
2164 6 st = fc->streams[fc->nb_streams - 1];
2165 6 sc = st->priv_data;
2166
2167
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (sc->format == MOV_MP4_FPCM_TAG) {
2168
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (pcm_sample_size) {
2169 1 case 32:
2170 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE;
2171 1 break;
2172 ✗ case 64:
2173 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE;
2174 ✗ break;
2175 ✗ default:
2176 ✗ av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2177 pcm_sample_size,
2178 ✗ av_fourcc2str(sc->format));
2179 ✗ return AVERROR_INVALIDDATA;
2180 }
2181
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (sc->format == MOV_MP4_IPCM_TAG) {
2182
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 switch (pcm_sample_size) {
2183 5 case 16:
2184 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2185 5 break;
2186 ✗ case 24:
2187 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
2188 ✗ break;
2189 ✗ case 32:
2190 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
2191 ✗ break;
2192 ✗ default:
2193 ✗ av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2194 pcm_sample_size,
2195 ✗ av_fourcc2str(sc->format));
2196 ✗ return AVERROR_INVALIDDATA;
2197 }
2198 } else {
2199 ✗ av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n",
2200 ✗ av_fourcc2str(sc->format));
2201 ✗ return AVERROR_INVALIDDATA;
2202 }
2203
2204
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
2205 6 set_last_stream_little_endian(c->fc);
2206 6 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2207
2208 6 return 0;
2209 }
2210
2211 72 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2212 {
2213 AVStream *st;
2214 72 HEIFItem *item = NULL;
2215 72 char color_parameter_type[5] = { 0 };
2216 uint16_t color_primaries, color_trc, color_matrix;
2217 int ret;
2218
2219 72 st = get_curr_st(c);
2220
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 68 times.
72 if (!st) {
2221 4 item = get_heif_item(c, c->cur_item_id);
2222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!item)
2223 ✗ return 0;
2224 }
2225
2226 72 ret = ffio_read_size(pb, color_parameter_type, 4);
2227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (ret < 0)
2228 ✗ return ret;
2229
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 24 times.
72 if (strncmp(color_parameter_type, "nclx", 4) &&
2230
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 36 times.
48 strncmp(color_parameter_type, "nclc", 4) &&
2231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 strncmp(color_parameter_type, "prof", 4)) {
2232 ✗ av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
2233 color_parameter_type);
2234 ✗ return 0;
2235 }
2236
2237
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 60 times.
72 if (!strncmp(color_parameter_type, "prof", 4)) {
2238 AVPacketSideData *sd;
2239 uint8_t *icc_profile;
2240
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 if (st) {
2241 8 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
2242 8 &st->codecpar->nb_coded_side_data,
2243 AV_PKT_DATA_ICC_PROFILE,
2244 8 atom.size - 4, 0);
2245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!sd)
2246 ✗ return AVERROR(ENOMEM);
2247 8 icc_profile = sd->data;
2248 } else {
2249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->heif_icc_profile_items >= c->fc->max_streams) {
2250 ✗ av_log(c->fc, AV_LOG_WARNING,
2251 "HEIF ICC profile copies exceed cap %d; ignoring further items\n",
2252 ✗ c->fc->max_streams);
2253 ✗ return 0;
2254 }
2255 4 av_freep(&item->icc_profile);
2256 4 icc_profile = item->icc_profile = av_malloc(atom.size - 4);
2257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!icc_profile) {
2258 ✗ item->icc_profile_size = 0;
2259 ✗ return AVERROR(ENOMEM);
2260 }
2261 4 item->icc_profile_size = atom.size - 4;
2262 4 c->heif_icc_profile_items++;
2263 }
2264 12 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
2265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
2266 ✗ return ret;
2267
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 } else if (st) {
2268 60 color_primaries = avio_rb16(pb);
2269 60 color_trc = avio_rb16(pb);
2270 60 color_matrix = avio_rb16(pb);
2271
2272 60 av_log(c->fc, AV_LOG_TRACE,
2273 "%s: pri %d trc %d matrix %d",
2274 color_parameter_type, color_primaries, color_trc, color_matrix);
2275
2276
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 36 times.
60 if (!strncmp(color_parameter_type, "nclx", 4)) {
2277 24 uint8_t color_range = avio_r8(pb) >> 7;
2278 24 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2279
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 20 times.
24 if (color_range)
2280 4 st->codecpar->color_range = AVCOL_RANGE_JPEG;
2281 else
2282 20 st->codecpar->color_range = AVCOL_RANGE_MPEG;
2283 }
2284
2285
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
60 if (!av_color_primaries_name(color_primaries))
2286 ✗ color_primaries = AVCOL_PRI_UNSPECIFIED;
2287
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
60 if (!av_color_transfer_name(color_trc))
2288 ✗ color_trc = AVCOL_TRC_UNSPECIFIED;
2289
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
60 if (!av_color_space_name(color_matrix))
2290 ✗ color_matrix = AVCOL_SPC_UNSPECIFIED;
2291
2292 60 st->codecpar->color_primaries = color_primaries;
2293 60 st->codecpar->color_trc = color_trc;
2294 60 st->codecpar->color_space = color_matrix;
2295 60 av_log(c->fc, AV_LOG_TRACE, "\n");
2296 }
2297 72 return 0;
2298 }
2299
2300 122 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2301 {
2302 AVStream *st;
2303 unsigned mov_field_order;
2304 122 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2305
2306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 122 times.
122 if (c->fc->nb_streams < 1) // will happen with jp2 files
2307 ✗ return 0;
2308 122 st = c->fc->streams[c->fc->nb_streams-1];
2309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 122 times.
122 if (atom.size < 2)
2310 ✗ return AVERROR_INVALIDDATA;
2311 122 mov_field_order = avio_rb16(pb);
2312
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 25 times.
122 if ((mov_field_order & 0xFF00) == 0x0100)
2313 97 decoded_field_order = AV_FIELD_PROGRESSIVE;
2314
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 else if ((mov_field_order & 0xFF00) == 0x0200) {
2315
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) {
2316 1 case 0x01: decoded_field_order = AV_FIELD_TT;
2317 1 break;
2318 ✗ case 0x06: decoded_field_order = AV_FIELD_BB;
2319 ✗ break;
2320 1 case 0x09: decoded_field_order = AV_FIELD_TB;
2321 1 break;
2322 23 case 0x0E: decoded_field_order = AV_FIELD_BT;
2323 23 break;
2324 }
2325 }
2326
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) {
2327 ✗ av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
2328 }
2329 122 st->codecpar->field_order = decoded_field_order;
2330
2331 122 return 0;
2332 }
2333
2334 69 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
2335 {
2336 69 int err = 0;
2337 69 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
2338
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)
2339 ✗ return AVERROR_INVALIDDATA;
2340
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
69 if ((err = av_reallocp(&par->extradata, size)) < 0) {
2341 ✗ par->extradata_size = 0;
2342 ✗ return err;
2343 }
2344 69 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
2345 69 return 0;
2346 }
2347
2348 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
2349 65 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2350 AVCodecParameters *par, uint8_t *buf)
2351 {
2352 65 int64_t result = atom.size;
2353 int err;
2354
2355 65 AV_WB32(buf , atom.size + 8);
2356 65 AV_WL32(buf + 4, atom.type);
2357 65 err = ffio_read_size(pb, buf + 8, atom.size);
2358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (err < 0) {
2359 ✗ par->extradata_size -= atom.size;
2360 ✗ return err;
2361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 } else if (err < atom.size) {
2362 ✗ av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
2363 ✗ par->extradata_size -= atom.size - err;
2364 ✗ result = err;
2365 }
2366 65 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2367 65 return result;
2368 }
2369
2370 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
2371 58 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2372 enum AVCodecID codec_id)
2373 {
2374 AVStream *st;
2375 uint64_t original_size;
2376 int err;
2377
2378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (c->fc->nb_streams < 1) // will happen with jp2 files
2379 ✗ return 0;
2380 58 st = c->fc->streams[c->fc->nb_streams-1];
2381
2382
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
58 if (st->codecpar->codec_id != codec_id)
2383 19 return 0; /* unexpected codec_id - don't mess with extradata */
2384
2385 39 original_size = st->codecpar->extradata_size;
2386 39 err = mov_realloc_extradata(st->codecpar, atom);
2387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err)
2388 ✗ return err;
2389
2390 39 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
2391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err < 0)
2392 ✗ return err;
2393 39 return 0; // Note: this is the original behavior to ignore truncation.
2394 }
2395
2396 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
2397 16 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2398 {
2399 16 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
2400 }
2401
2402 ✗ static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2403 {
2404 ✗ return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS);
2405 }
2406
2407 ✗ static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2408 {
2409 ✗ return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
2410 }
2411
2412 ✗ static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2413 {
2414 ✗ return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
2415 }
2416
2417 19 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2418 {
2419 19 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
2420
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!ret)
2421 19 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
2422 19 return ret;
2423 }
2424
2425 ✗ static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2426 {
2427 ✗ int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
2428
2429 ✗ if (!ret && c->fc->nb_streams >= 1) {
2430 ✗ AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2431 ✗ if (par->extradata_size >= 40) {
2432 ✗ par->height = AV_RB16(&par->extradata[36]);
2433 ✗ par->width = AV_RB16(&par->extradata[38]);
2434 }
2435 }
2436 ✗ return ret;
2437 }
2438
2439 16 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2440 {
2441
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (c->fc->nb_streams >= 1) {
2442 16 AVStream *const st = c->fc->streams[c->fc->nb_streams - 1];
2443 16 FFStream *const sti = ffstream(st);
2444 16 AVCodecParameters *par = st->codecpar;
2445
2446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
2447 ✗ par->codec_id == AV_CODEC_ID_H264 &&
2448 ✗ atom.size > 11) {
2449 int cid;
2450 ✗ avio_skip(pb, 10);
2451 ✗ cid = avio_rb16(pb);
2452 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
2453 ✗ if (cid == 0xd4d || cid == 0xd4e)
2454 ✗ par->width = 1440;
2455 ✗ return 0;
2456
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
2457
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
2458
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
2459
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 atom.size >= 24) {
2460 int num, den;
2461 13 avio_skip(pb, 12);
2462 13 num = avio_rb32(pb);
2463 13 den = avio_rb32(pb);
2464
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)
2465 ✗ return 0;
2466
2/3
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
13 switch (avio_rb32(pb)) {
2467 12 case 2:
2468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (den >= INT_MAX / 2)
2469 ✗ return 0;
2470 12 den *= 2;
2471 av_fallthrough;
2472 13 case 1:
2473 13 sti->display_aspect_ratio = (AVRational){ num, den };
2474 av_fallthrough;
2475 13 default:
2476 13 return 0;
2477 }
2478 }
2479 }
2480
2481 3 return mov_read_avid(c, pb, atom);
2482 }
2483
2484 26 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2485 {
2486 26 int ret = 0;
2487 26 int length = 0;
2488 uint64_t original_size;
2489
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (c->fc->nb_streams >= 1) {
2490 26 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (par->codec_id == AV_CODEC_ID_H264)
2492 ✗ return 0;
2493
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (atom.size == 16) {
2494 26 original_size = par->extradata_size;
2495 26 ret = mov_realloc_extradata(par, atom);
2496
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!ret) {
2497 26 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
2498
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (length == atom.size) {
2499 26 const uint8_t range_value = par->extradata[original_size + 19];
2500
1/3
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
26 switch (range_value) {
2501 26 case 1:
2502 26 par->color_range = AVCOL_RANGE_MPEG;
2503 26 break;
2504 ✗ case 2:
2505 ✗ par->color_range = AVCOL_RANGE_JPEG;
2506 ✗ break;
2507 ✗ default:
2508 ✗ av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
2509 ✗ break;
2510 }
2511 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
2512 } else {
2513 /* For some reason the whole atom was not added to the extradata */
2514 ✗ av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
2515 }
2516 } else {
2517 ✗ av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
2518 }
2519 } else {
2520 ✗ av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
2521 }
2522 }
2523
2524 26 return ret;
2525 }
2526
2527 4 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2528 {
2529 4 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
2530 }
2531
2532 33 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2533 {
2534 AVStream *st;
2535 int ret;
2536
2537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (c->fc->nb_streams < 1)
2538 ✗ return 0;
2539 33 st = c->fc->streams[c->fc->nb_streams-1];
2540
2541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if ((uint64_t)atom.size > (1<<30))
2542 ✗ return AVERROR_INVALIDDATA;
2543
2544
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 2 times.
33 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2545
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
2547 // pass all frma atom to codec, needed at least for QDMC and QDM2
2548 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2550 ✗ return ret;
2551
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 } else if (atom.size > 8) { /* to read frma, esds atoms */
2552
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) {
2553 uint64_t buffer;
2554 10 ret = ffio_ensure_seekback(pb, 8);
2555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2556 ✗ return ret;
2557 10 buffer = avio_rb64(pb);
2558 10 atom.size -= 8;
2559
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
2560
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 <= atom.size
2561
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 >= 8) {
2562 10 avio_skip(pb, -8);
2563 10 atom.size += 8;
2564 ✗ } else if (!st->codecpar->extradata_size) {
2565 #define ALAC_EXTRADATA_SIZE 36
2566 ✗ st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
2567 ✗ if (!st->codecpar->extradata)
2568 ✗ return AVERROR(ENOMEM);
2569 ✗ st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
2570 ✗ AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
2571 ✗ AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
2572 ✗ AV_WB64(st->codecpar->extradata + 12, buffer);
2573 ✗ avio_read(pb, st->codecpar->extradata + 20, 16);
2574 ✗ avio_skip(pb, atom.size - 24);
2575 ✗ return 0;
2576 }
2577 }
2578
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 if ((ret = mov_read_default(c, pb, atom)) < 0)
2579 ✗ return ret;
2580 } else
2581 ✗ avio_skip(pb, atom.size);
2582 33 return 0;
2583 }
2584
2585 /**
2586 * This function reads atom content and puts data in extradata without tag
2587 * nor size unlike mov_read_extradata.
2588 */
2589 211 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2590 {
2591 AVStream *st;
2592 int ret;
2593
2594 211 st = get_curr_st(c);
2595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 211 times.
211 if (!st)
2596 ✗ return 0;
2597
2598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 211 times.
211 if ((uint64_t)atom.size > (1<<30))
2599 ✗ return AVERROR_INVALIDDATA;
2600
2601
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 210 times.
211 if (atom.type == MKTAG('v','v','c','C')) {
2602 1 avio_skip(pb, 4);
2603 1 atom.size -= 4;
2604 }
2605
2606
2/2
✓ Branch 0 taken 207 times.
✓ Branch 1 taken 4 times.
211 if (atom.size >= 10) {
2607 // Broken files created by legacy versions of libavformat will
2608 // wrap a whole fiel atom inside of a glbl atom.
2609 207 unsigned size = avio_rb32(pb);
2610 207 unsigned type = avio_rl32(pb);
2611
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 207 times.
207 if (avio_feof(pb))
2612 ✗ return AVERROR_INVALIDDATA;
2613 207 avio_seek(pb, -8, SEEK_CUR);
2614
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 197 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
207 if (type == MKTAG('f','i','e','l') && size == atom.size)
2615 10 return mov_read_default(c, pb, atom);
2616 }
2617
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 201 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
201 if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
2618 ✗ av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
2619 ✗ return 0;
2620 }
2621 201 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 201 times.
201 if (ret < 0)
2623 ✗ return ret;
2624
3/4
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 118 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 83 times.
201 if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
2625 /* HEVC-based Dolby Vision derived from hvc1.
2626 Happens to match with an identifier
2627 previously utilized for DV. Thus, if we have
2628 the hvcC extradata box available as specified,
2629 set codec to HEVC */
2630 ✗ st->codecpar->codec_id = AV_CODEC_ID_HEVC;
2631
2632 201 return 0;
2633 }
2634
2635 2 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2636 {
2637 AVStream *st;
2638 uint8_t profile_level;
2639 int ret;
2640
2641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
2642 ✗ return 0;
2643 2 st = c->fc->streams[c->fc->nb_streams-1];
2644
2645
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)
2646 ✗ return AVERROR_INVALIDDATA;
2647
2648 2 profile_level = avio_r8(pb);
2649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((profile_level & 0xf0) != 0xc0)
2650 ✗ return 0;
2651
2652 2 avio_seek(pb, 6, SEEK_CUR);
2653 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
2654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2655 ✗ return ret;
2656
2657 2 return 0;
2658 }
2659
2660 70 static int mov_find_tref_id(const MovTref *tag, uint32_t id)
2661 {
2662
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 42 times.
100 for (int i = 0; i < tag->nb_id; i++) {
2663
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 30 times.
58 if (tag->id[i] == id)
2664 28 return 1;
2665 }
2666 42 return 0;
2667 }
2668
2669 42 static int mov_add_tref_id(MovTref *tag, uint32_t id)
2670 {
2671 42 int ret = mov_find_tref_id(tag, id);
2672
2673
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 if (!ret) {
2674 42 uint32_t *tmp = av_realloc_array(tag->id, tag->nb_id + 1, sizeof(*tag->id));
2675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!tmp)
2676 ✗ return AVERROR(ENOMEM);
2677 42 tag->id = tmp;
2678 42 tag->id[tag->nb_id++] = id;
2679 }
2680
2681 42 return 0;
2682 }
2683
2684 1990 static MovTref *mov_find_tref_tag(const MOVStreamContext *sc, uint32_t name)
2685 {
2686
2/2
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 1922 times.
2107 for (int i = 0; i < sc->nb_tref_tags; i++) {
2687 185 MovTref *entry = &sc->tref_tags[i];
2688
2689
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 117 times.
185 if (entry->name == name)
2690 68 return entry;
2691 }
2692 1922 return NULL;
2693 }
2694
2695 32 static MovTref *mov_add_tref_tag(MOVStreamContext *sc, uint32_t name)
2696 {
2697 32 MovTref *tag = mov_find_tref_tag(sc, name);
2698
2699
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (!tag) {
2700 32 MovTref *tmp = av_realloc_array(sc->tref_tags, sc->nb_tref_tags + 1,
2701 sizeof(*sc->tref_tags));
2702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!tmp)
2703 ✗ return NULL;
2704 32 sc->tref_tags = tmp;
2705 32 tag = &sc->tref_tags[sc->nb_tref_tags++];
2706 32 *tag = (MovTref){ .name = name };
2707 }
2708
2709 32 return tag;
2710 }
2711
2712 11 static int mov_read_cdsc_rndr(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2713 {
2714 AVStream* st;
2715 MOVStreamContext* sc;
2716
2717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
2718 ✗ return 0;
2719
2720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size > 4) {
2721 ✗ av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type cdsc/rndr is supported\n");
2722 ✗ return AVERROR_PATCHWELCOME;
2723 }
2724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 4)
2725 ✗ return AVERROR_INVALIDDATA;
2726
2727 11 st = get_curr_st(c);
2728
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!st)
2729 ✗ return AVERROR_INVALIDDATA;
2730 11 sc = st->priv_data;
2731
2732 11 MovTref *tag = mov_add_tref_tag(sc, atom.type);
2733
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!tag)
2734 ✗ return AVERROR(ENOMEM);
2735
2736 11 int ret = mov_add_tref_id(tag, avio_rb32(pb));
2737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0)
2738 ✗ return ret;
2739
2740 11 return 0;
2741 }
2742
2743 ✗ static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2744 {
2745 AVStream* st;
2746 MOVStreamContext* sc;
2747
2748 ✗ if (c->fc->nb_streams < 1)
2749 ✗ return 0;
2750
2751 /* For SBAS this should be fine - though beware if someone implements a
2752 * tref atom processor that doesn't drop down to default then this may
2753 * be lost. */
2754 ✗ if (atom.size > 4) {
2755 ✗ av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2756 ✗ return AVERROR_PATCHWELCOME;
2757 }
2758 ✗ if (atom.size < 4)
2759 ✗ return AVERROR_INVALIDDATA;
2760
2761 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
2762 ✗ sc = st->priv_data;
2763
2764 ✗ MovTref *tag = mov_add_tref_tag(sc, atom.type);
2765 ✗ if (!tag)
2766 ✗ return AVERROR(ENOMEM);
2767
2768 ✗ int ret = mov_add_tref_id(tag, avio_rb32(pb));
2769 ✗ if (ret < 0)
2770 ✗ return ret;
2771
2772 ✗ return 0;
2773 }
2774
2775 ✗ static int mov_read_vdep(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2776 {
2777 AVStream* st;
2778 MOVStreamContext* sc;
2779
2780 ✗ if (c->fc->nb_streams < 1)
2781 ✗ return 0;
2782
2783 ✗ if (atom.size > 4)
2784 ✗ av_log(c->fc, AV_LOG_WARNING, "More than one vdep reference is not supported.\n");
2785 ✗ if (atom.size < 4)
2786 ✗ return AVERROR_INVALIDDATA;
2787
2788 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
2789 ✗ sc = st->priv_data;
2790
2791 ✗ MovTref *tag = mov_add_tref_tag(sc, atom.type);
2792 ✗ if (!tag)
2793 ✗ return AVERROR(ENOMEM);
2794
2795 ✗ int ret = mov_add_tref_id(tag, avio_rb32(pb));
2796 ✗ if (ret < 0)
2797 ✗ return ret;
2798
2799 ✗ return 0;
2800 }
2801
2802 /**
2803 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2804 * but can have extradata appended at the end after the 40 bytes belonging
2805 * to the struct.
2806 */
2807 ✗ static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2808 {
2809 AVStream *st;
2810 int ret;
2811
2812 ✗ if (c->fc->nb_streams < 1)
2813 ✗ return 0;
2814 ✗ if (atom.size <= 40)
2815 ✗ return 0;
2816 ✗ st = c->fc->streams[c->fc->nb_streams-1];
2817
2818 ✗ if ((uint64_t)atom.size > (1<<30))
2819 ✗ return AVERROR_INVALIDDATA;
2820
2821 ✗ avio_skip(pb, 40);
2822 ✗ ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
2823 ✗ if (ret < 0)
2824 ✗ return ret;
2825
2826 ✗ return 0;
2827 }
2828
2829 838 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2830 {
2831 AVStream *st;
2832 MOVStreamContext *sc;
2833 unsigned int i, entries;
2834
2835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->trak_index < 0) {
2836 ✗ av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
2837 ✗ return 0;
2838 }
2839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->fc->nb_streams < 1)
2840 ✗ return 0;
2841 838 st = c->fc->streams[c->fc->nb_streams-1];
2842 838 sc = st->priv_data;
2843
2844 838 avio_r8(pb); /* version */
2845 838 avio_rb24(pb); /* flags */
2846
2847 // Clamp allocation size for `chunk_offsets` -- don't throw an error for an
2848 // invalid count since the EOF path doesn't throw either.
2849 838 entries = avio_rb32(pb);
2850 838 entries =
2851
2/2
✓ Branch 0 taken 833 times.
✓ Branch 1 taken 5 times.
838 FFMIN(entries,
2852 FFMAX(0, (atom.size - 8) /
2853 (atom.type == MKTAG('s', 't', 'c', 'o') ? 4 : 8)));
2854
2855
2/2
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 704 times.
838 if (!entries)
2856 134 return 0;
2857
2858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 704 times.
704 if (sc->chunk_offsets) {
2859 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2860 ✗ return 0;
2861 }
2862
2863 704 av_free(sc->chunk_offsets);
2864 704 sc->chunk_count = 0;
2865 704 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 704 times.
704 if (!sc->chunk_offsets)
2867 ✗ return AVERROR(ENOMEM);
2868 704 sc->chunk_count = entries;
2869
2870
2/2
✓ Branch 0 taken 700 times.
✓ Branch 1 taken 4 times.
704 if (atom.type == MKTAG('s','t','c','o'))
2871
3/4
✓ Branch 0 taken 43956 times.
✓ Branch 1 taken 700 times.
✓ Branch 2 taken 43956 times.
✗ Branch 3 not taken.
44656 for (i = 0; i < entries && !pb->eof_reached; i++)
2872 43956 sc->chunk_offsets[i] = avio_rb32(pb);
2873
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (atom.type == MKTAG('c','o','6','4'))
2874
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++) {
2875 136336 sc->chunk_offsets[i] = avio_rb64(pb);
2876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136336 times.
136336 if (sc->chunk_offsets[i] < 0) {
2877 ✗ av_log(c->fc, AV_LOG_WARNING, "Impossible chunk_offset\n");
2878 ✗ sc->chunk_offsets[i] = 0;
2879 }
2880 }
2881 else
2882 ✗ return AVERROR_INVALIDDATA;
2883
2884 704 sc->chunk_count = i;
2885
2886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 704 times.
704 if (pb->eof_reached) {
2887 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2888 ✗ return AVERROR_EOF;
2889 }
2890
2891 704 return 0;
2892 }
2893
2894 918 static int mov_codec_id(AVStream *st, uint32_t format)
2895 {
2896 918 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2897
2898
2/2
✓ Branch 0 taken 544 times.
✓ Branch 1 taken 374 times.
918 if (id <= 0 &&
2899
2/2
✓ Branch 0 taken 541 times.
✓ Branch 1 taken 3 times.
544 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 541 times.
541 (format & 0xFFFF) == 'T' + ('S' << 8)))
2901 3 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2902
2903
4/4
✓ Branch 0 taken 464 times.
✓ Branch 1 taken 454 times.
✓ Branch 2 taken 377 times.
✓ Branch 3 taken 87 times.
918 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2904 377 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2905
3/4
✓ Branch 0 taken 521 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 521 times.
✗ Branch 3 not taken.
541 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2906 /* skip old ASF MPEG-4 tag */
2907
2/2
✓ Branch 0 taken 517 times.
✓ Branch 1 taken 4 times.
521 format && format != MKTAG('m','p','4','s')) {
2908 517 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2909
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 439 times.
517 if (id <= 0)
2910 78 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2911
2/2
✓ Branch 0 taken 443 times.
✓ Branch 1 taken 74 times.
517 if (id > 0)
2912 443 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2913
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 62 times.
74 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2914
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
12 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2916 62 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2917
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 6 times.
62 if (id <= 0) {
2918
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 4 times.
108 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2919
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 4 times.
108 AV_CODEC_ID_TTML : id;
2920 }
2921
2922
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 48 times.
62 if (id > 0)
2923 14 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2924 else
2925 48 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2926 }
2927 }
2928
2929 918 st->codecpar->codec_tag = format;
2930
2931 918 return id;
2932 }
2933
2934 390 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2935 AVStream *st, MOVStreamContext *sc)
2936 {
2937 390 uint8_t codec_name[32] = { 0 };
2938 int64_t stsd_start;
2939 unsigned int len;
2940 390 uint32_t id = 0;
2941
2942 /* The first 16 bytes of the video sample description are already
2943 * read in ff_mov_read_stsd_entries() */
2944 390 stsd_start = avio_tell(pb) - 16;
2945
2946
2/2
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 261 times.
390 if (c->isom) {
2947 129 avio_skip(pb, 2); /* pre_defined */
2948 129 avio_skip(pb, 2); /* reserved */
2949 129 avio_skip(pb, 12); /* pre_defined */
2950 } else {
2951 261 avio_rb16(pb); /* version */
2952 261 avio_rb16(pb); /* revision level */
2953 261 id = avio_rl32(pb); /* vendor */
2954 261 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2955 261 avio_rb32(pb); /* temporal quality */
2956 261 avio_rb32(pb); /* spatial quality */
2957 }
2958
2959 390 st->codecpar->width = avio_rb16(pb); /* width */
2960 390 st->codecpar->height = avio_rb16(pb); /* height */
2961
2962 390 avio_rb32(pb); /* horiz resolution */
2963 390 avio_rb32(pb); /* vert resolution */
2964 390 avio_rb32(pb); /* data size, always 0 */
2965 390 avio_rb16(pb); /* frames per samples */
2966
2967 390 len = avio_r8(pb); /* codec name, pascal string */
2968
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 389 times.
390 if (len > 31)
2969 1 len = 31;
2970 390 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2971
2/2
✓ Branch 0 taken 387 times.
✓ Branch 1 taken 3 times.
390 if (len < 31)
2972 387 avio_skip(pb, 31 - len);
2973
2974
2/2
✓ Branch 0 taken 297 times.
✓ Branch 1 taken 93 times.
390 if (codec_name[0])
2975 297 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2976
2977 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 390 times.
390 if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2979 ✗ st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2980 ✗ st->codecpar->width &= ~1;
2981 ✗ st->codecpar->height &= ~1;
2982 }
2983 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2984
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 390 times.
390 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2985 ✗ !strncmp(codec_name, "Sorenson H263", 13))
2986 ✗ st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2987
2988 390 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2989
2990 390 avio_seek(pb, stsd_start, SEEK_SET);
2991
2992
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 372 times.
390 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2993 18 st->codecpar->bits_per_coded_sample &= 0x1F;
2994 18 sc->has_palette = 1;
2995 }
2996 390 }
2997
2998 397 static int mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2999 AVStream *st, MOVStreamContext *sc)
3000 {
3001 int bits_per_sample, flags;
3002 397 uint16_t version = avio_rb16(pb);
3003 397 uint32_t id = 0;
3004 397 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
3005 int channel_count;
3006
3007
2/2
✓ Branch 0 taken 307 times.
✓ Branch 1 taken 90 times.
397 if (c->isom)
3008 307 avio_skip(pb, 6); /* reserved */
3009 else {
3010 90 avio_rb16(pb); /* revision level */
3011 90 id = avio_rl32(pb); /* vendor */
3012 90 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
3013 }
3014
3015 397 channel_count = avio_rb16(pb);
3016
3017 397 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3018 397 st->codecpar->ch_layout.nb_channels = channel_count;
3019 397 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
3020 397 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
3021
3022 397 sc->audio_cid = avio_rb16(pb);
3023 397 avio_rb16(pb); /* packet size = 0 */
3024
3025 397 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
3026
3027 // Read QT version 1 fields. In version 0 these do not exist.
3028 397 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
3029
3/4
✓ Branch 0 taken 307 times.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 307 times.
✗ Branch 3 not taken.
397 if (!c->isom ||
3030
1/2
✓ Branch 0 taken 307 times.
✗ Branch 1 not taken.
307 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
3031
4/4
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 298 times.
307 (sc->stsd_version == 0 && version > 0)) {
3032
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 42 times.
94 if (version == 1) {
3033 52 sc->samples_per_frame = avio_rb32(pb);
3034 52 avio_rb32(pb); /* bytes per packet */
3035 52 sc->bytes_per_frame = avio_rb32(pb);
3036 52 avio_rb32(pb); /* bytes per sample */
3037
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 38 times.
42 } else if (version == 2) {
3038 double sample_rate;
3039
3040 4 avio_rb32(pb); /* sizeof struct only */
3041 4 sample_rate = av_int2double(avio_rb64(pb));
3042
3043
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
4 if (sample_rate < 0 || sample_rate > INT_MAX ||
3044 isnan(sample_rate)) {
3045 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %g\n",
3046 sample_rate);
3047 ✗ return AVERROR_INVALIDDATA;
3048 }
3049 4 st->codecpar->sample_rate = sample_rate;
3050 4 channel_count = avio_rb32(pb);
3051 4 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3052 4 st->codecpar->ch_layout.nb_channels = channel_count;
3053 4 avio_rb32(pb); /* always 0x7F000000 */
3054 4 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
3055
3056 4 flags = avio_rb32(pb); /* lpcm format specific flag */
3057 4 sc->bytes_per_frame = avio_rb32(pb);
3058 4 sc->samples_per_frame = avio_rb32(pb);
3059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
3060 ✗ st->codecpar->codec_id =
3061 ✗ ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
3062 flags);
3063 }
3064
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)) {
3065 /* can't correctly handle variable sized packet as audio unit */
3066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 switch (st->codecpar->codec_id) {
3067 ✗ case AV_CODEC_ID_MP2:
3068 case AV_CODEC_ID_MP3:
3069 ✗ ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
3070 ✗ break;
3071 }
3072 }
3073 }
3074
3075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 397 times.
397 if (sc->format == 0) {
3076 ✗ if (st->codecpar->bits_per_coded_sample == 8)
3077 ✗ st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
3078 ✗ else if (st->codecpar->bits_per_coded_sample == 16)
3079 ✗ st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
3080 }
3081
3082
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 350 times.
397 switch (st->codecpar->codec_id) {
3083 7 case AV_CODEC_ID_PCM_S8:
3084 case AV_CODEC_ID_PCM_U8:
3085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
3086 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
3087 7 break;
3088 24 case AV_CODEC_ID_PCM_S16LE:
3089 case AV_CODEC_ID_PCM_S16BE:
3090
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 if (st->codecpar->bits_per_coded_sample == 8)
3091 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
3092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 else if (st->codecpar->bits_per_coded_sample == 24)
3093 ✗ st->codecpar->codec_id =
3094 ✗ st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
3095 ✗ AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
3096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 else if (st->codecpar->bits_per_coded_sample == 32)
3097 ✗ st->codecpar->codec_id =
3098 ✗ st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
3099 ✗ AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
3100 24 break;
3101 /* set values for old format before stsd version 1 appeared */
3102 2 case AV_CODEC_ID_MACE3:
3103 2 sc->samples_per_frame = 6;
3104 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
3105 2 break;
3106 8 case AV_CODEC_ID_MACE6:
3107 8 sc->samples_per_frame = 6;
3108 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
3109 8 break;
3110 5 case AV_CODEC_ID_ADPCM_IMA_QT:
3111 5 sc->samples_per_frame = 64;
3112 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
3113 5 break;
3114 1 case AV_CODEC_ID_GSM:
3115 1 sc->samples_per_frame = 160;
3116 1 sc->bytes_per_frame = 33;
3117 1 break;
3118 350 default:
3119 350 break;
3120 }
3121
3122 397 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
3123
3/4
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 344 times.
✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
397 if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->ch_layout.nb_channels <= INT_MAX) {
3124 53 st->codecpar->bits_per_coded_sample = bits_per_sample;
3125 53 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
3126 }
3127
3128 397 return 0;
3129 }
3130
3131 15 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
3132 AVStream *st, MOVStreamContext *sc,
3133 int64_t size)
3134 {
3135 // ttxt stsd contains display flags, justification, background
3136 // color, fonts, and default styles, so fake an atom to read it
3137 15 MOVAtom fake_atom = { .size = size };
3138 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
3139 // in extradata unlike stpp MP4 TTML.
3140
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
3141
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
15 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
3142 11 mov_read_glbl(c, pb, fake_atom);
3143 15 st->codecpar->width = sc->width;
3144 15 st->codecpar->height = sc->height;
3145 15 }
3146
3147 52 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
3148 AVStream *st, MOVStreamContext *sc,
3149 int64_t size)
3150 {
3151 int ret;
3152
3153
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 24 times.
52 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
3154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if ((int)size != size)
3155 ✗ return AVERROR(ENOMEM);
3156
3157 28 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
3158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
3159 ✗ return ret;
3160
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (size > 16) {
3161 28 MOVStreamContext *tmcd_ctx = st->priv_data;
3162 int val;
3163 28 val = AV_RB32(st->codecpar->extradata + 4);
3164 28 tmcd_ctx->tmcd_flags = val;
3165 28 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
3166 28 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
3167 28 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
3168
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 18 times.
28 if (size > 30) {
3169 10 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
3170 10 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
3171
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) {
3172 10 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
3173
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 &&
3174
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 st->codecpar->extradata[30] /* Don't add empty string */) {
3175 10 char *reel_name = av_malloc(str_size + 1);
3176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!reel_name)
3177 ✗ return AVERROR(ENOMEM);
3178 10 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
3179 10 reel_name[str_size] = 0; /* Add null terminator */
3180 10 av_dict_set(&st->metadata, "reel_name", reel_name,
3181 AV_DICT_DONT_STRDUP_VAL);
3182 }
3183 }
3184 }
3185 }
3186
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 } else if (st->codecpar->codec_id == AV_CODEC_ID_ITUT_T35) {
3187 2 int t35_identifier_length = avio_r8(pb);
3188
3189
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)
3190 ✗ return AVERROR_INVALIDDATA;
3191
3192 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, t35_identifier_length);
3193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
3194 ✗ return ret;
3195
3196 2 int hrsd_len = size - t35_identifier_length - 1;
3197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (hrsd_len > 0) {
3198 ✗ uint8_t *hrsd_str = av_malloc(hrsd_len + 1);
3199 ✗ if (!hrsd_str)
3200 ✗ return AVERROR(ENOMEM);
3201
3202 ✗ ret = ffio_read_size(pb, hrsd_str, hrsd_len);
3203 ✗ if (ret < 0) {
3204 ✗ av_free(hrsd_str);
3205 ✗ return ret;
3206 }
3207 ✗ if (hrsd_str[0]) {
3208 ✗ hrsd_str[hrsd_len] = 0;
3209 ✗ ret = av_dict_set(&st->metadata, "description", hrsd_str, AV_DICT_DONT_OVERWRITE);
3210 }
3211 ✗ av_free(hrsd_str);
3212 }
3213 } else {
3214 /* other codec type, just skip (rtp, mp4s ...) */
3215 22 avio_skip(pb, size);
3216 }
3217 52 return 0;
3218 }
3219
3220 838 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
3221 AVStream *st, MOVStreamContext *sc)
3222 {
3223 838 FFStream *const sti = ffstream(st);
3224
3225
2/2
✓ Branch 0 taken 397 times.
✓ Branch 1 taken 441 times.
838 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
3226
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 397 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
397 !st->codecpar->sample_rate && sc->time_scale > 1)
3227 ✗ st->codecpar->sample_rate = sc->time_scale;
3228
3229 /* special codec parameters handling */
3230
7/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 103 times.
✓ Branch 5 taken 15 times.
✓ Branch 6 taken 16 times.
✓ Branch 7 taken 14 times.
✓ Branch 8 taken 119 times.
✓ Branch 9 taken 560 times.
838 switch (st->codecpar->codec_id) {
3231 #if CONFIG_DV_DEMUXER
3232 ✗ case AV_CODEC_ID_DVAUDIO:
3233 ✗ if (c->dv_fctx) {
3234 ✗ avpriv_request_sample(c->fc, "multiple DV audio streams");
3235 ✗ return AVERROR(ENOSYS);
3236 }
3237
3238 ✗ c->dv_fctx = avformat_alloc_context();
3239 ✗ if (!c->dv_fctx) {
3240 ✗ av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
3241 ✗ return AVERROR(ENOMEM);
3242 }
3243 ✗ c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
3244 ✗ if (!c->dv_demux) {
3245 ✗ av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
3246 ✗ return AVERROR(ENOMEM);
3247 }
3248 ✗ sc->dv_audio_container = 1;
3249 ✗ st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
3250 ✗ break;
3251 #endif
3252 /* no ifdef since parameters are always those */
3253 ✗ case AV_CODEC_ID_QCELP:
3254 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
3255 ✗ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3256 // force sample rate for qcelp when not stored in mov
3257 ✗ if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
3258 ✗ st->codecpar->sample_rate = 8000;
3259 // FIXME: Why is the following needed for some files?
3260 ✗ sc->samples_per_frame = 160;
3261 ✗ if (!sc->bytes_per_frame)
3262 ✗ sc->bytes_per_frame = 35;
3263 ✗ break;
3264 ✗ case AV_CODEC_ID_AMR_NB:
3265 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
3266 ✗ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3267 /* force sample rate for amr, stsd in 3gp does not store sample rate */
3268 ✗ st->codecpar->sample_rate = 8000;
3269 ✗ break;
3270 11 case AV_CODEC_ID_AMR_WB:
3271 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
3272 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3273 11 st->codecpar->sample_rate = 16000;
3274 11 break;
3275 103 case AV_CODEC_ID_MP2:
3276 case AV_CODEC_ID_MP3:
3277 /* force type after stsd for m1a hdlr */
3278 103 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
3279 103 break;
3280 15 case AV_CODEC_ID_GSM:
3281 case AV_CODEC_ID_ADPCM_MS:
3282 case AV_CODEC_ID_ADPCM_IMA_WAV:
3283 case AV_CODEC_ID_ILBC:
3284 case AV_CODEC_ID_MACE3:
3285 case AV_CODEC_ID_MACE6:
3286 case AV_CODEC_ID_QDM2:
3287 15 st->codecpar->block_align = sc->bytes_per_frame;
3288 15 break;
3289 16 case AV_CODEC_ID_ALAC:
3290
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
3291 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
3292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
3293 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
3294 ✗ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3295 ✗ st->codecpar->ch_layout.nb_channels = channel_count;
3296 }
3297 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
3298 }
3299 16 break;
3300 14 case AV_CODEC_ID_AC3:
3301 case AV_CODEC_ID_EAC3:
3302 case AV_CODEC_ID_MPEG1VIDEO:
3303 case AV_CODEC_ID_VC1:
3304 case AV_CODEC_ID_VP8:
3305 case AV_CODEC_ID_VP9:
3306 14 sti->need_parsing = AVSTREAM_PARSE_FULL;
3307 14 break;
3308 119 case AV_CODEC_ID_PRORES_RAW:
3309 case AV_CODEC_ID_PRORES:
3310 case AV_CODEC_ID_APV:
3311 case AV_CODEC_ID_EVC:
3312 case AV_CODEC_ID_LCEVC:
3313 case AV_CODEC_ID_AV1:
3314 /* field_order detection of H264 requires parsing */
3315 case AV_CODEC_ID_H264:
3316 119 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3317 119 break;
3318 560 default:
3319 560 break;
3320 }
3321 838 return 0;
3322 }
3323
3324 855 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
3325 int codec_tag, int format,
3326 int64_t size)
3327 {
3328
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 838 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 16 times.
855 if (codec_tag &&
3329 1 (codec_tag != format &&
3330 // AVID 1:1 samples with differing data format and codec tag exist
3331
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")) &&
3332 // prores is allowed to have differing data format and codec tag
3333
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") &&
3334 // so is dv (sigh)
3335
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") &&
3336
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
3337 : codec_tag != MKTAG('j','p','e','g')))) {
3338 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3339 * export it as a separate AVStream but this needs a few changes
3340 * in the MOV demuxer, patch welcome. */
3341
3342 1 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3343 1 avio_skip(pb, size);
3344 1 return 1;
3345 }
3346
3347 854 return 0;
3348 }
3349
3350 854 static int mov_finalize_stsd_entry(MOVContext *c, AVStream *st)
3351 {
3352 int ret;
3353
3354 /* special codec parameters handling */
3355
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 763 times.
854 switch (st->codecpar->codec_id) {
3356 91 case AV_CODEC_ID_H264:
3357 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
3358
1/30
✗ Branch 0 not taken.
✓ Branch 1 taken 91 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.
91 if (!st->codecpar->extradata_size && TAG_IS_AVCI(st->codecpar->codec_tag)) {
3359 ✗ ret = ff_generate_avci_extradata(st);
3360 ✗ if (ret < 0)
3361 ✗ return ret;
3362 }
3363 91 break;
3364 763 default:
3365 763 break;
3366 }
3367
3368 854 return 0;
3369 }
3370
3371 838 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3372 {
3373 AVStream *st;
3374 MOVStreamContext *sc;
3375 int pseudo_stream_id;
3376
3377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 av_assert0 (c->fc->nb_streams >= 1);
3378 838 st = c->fc->streams[c->fc->nb_streams-1];
3379 838 sc = st->priv_data;
3380
3381 838 for (pseudo_stream_id = 0;
3382
3/4
✓ Branch 0 taken 855 times.
✓ Branch 1 taken 838 times.
✓ Branch 2 taken 855 times.
✗ Branch 3 not taken.
1693 pseudo_stream_id < entries && !pb->eof_reached;
3383 855 pseudo_stream_id++) {
3384 //Parsing Sample description table
3385 enum AVCodecID id;
3386 855 int ret, dref_id = 1;
3387 855 MOVAtom a = { AV_RL32("stsd") };
3388 855 int64_t start_pos = avio_tell(pb);
3389 855 int64_t size = avio_rb32(pb); /* size */
3390 855 uint32_t format = avio_rl32(pb); /* data format */
3391
3392
1/2
✓ Branch 0 taken 855 times.
✗ Branch 1 not taken.
855 if (size >= 16) {
3393 855 avio_rb32(pb); /* reserved */
3394 855 avio_rb16(pb); /* reserved */
3395 855 dref_id = avio_rb16(pb);
3396 ✗ } else if (size <= 7) {
3397 ✗ av_log(c->fc, AV_LOG_ERROR,
3398 "invalid size %"PRId64" in stsd\n", size);
3399 ✗ return AVERROR_INVALIDDATA;
3400 }
3401
3402
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 854 times.
855 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3403 855 size - (avio_tell(pb) - start_pos))) {
3404 1 sc->stsd_count++;
3405 1 continue;
3406 }
3407
3408
2/2
✓ Branch 0 taken 838 times.
✓ Branch 1 taken 16 times.
854 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
3409 854 sc->dref_id= dref_id;
3410 854 sc->format = format;
3411
3412 854 id = mov_codec_id(st, format);
3413
3414 854 av_log(c->fc, AV_LOG_TRACE,
3415 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3416 854 av_fourcc2str(format), st->codecpar->codec_type);
3417
3418 854 st->codecpar->codec_id = id;
3419
2/2
✓ Branch 0 taken 390 times.
✓ Branch 1 taken 464 times.
854 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3420 390 mov_parse_stsd_video(c, pb, st, sc);
3421
2/2
✓ Branch 0 taken 397 times.
✓ Branch 1 taken 67 times.
464 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3422 397 ret = mov_parse_stsd_audio(c, pb, st, sc);
3423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 397 times.
397 if (ret < 0)
3424 ✗ return ret;
3425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 397 times.
397 if (st->codecpar->sample_rate < 0) {
3426 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3427 ✗ return AVERROR_INVALIDDATA;
3428 }
3429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 397 times.
397 if (st->codecpar->ch_layout.nb_channels < 0) {
3430 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3431 ✗ return AVERROR_INVALIDDATA;
3432 }
3433
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 52 times.
67 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3434 15 mov_parse_stsd_subtitle(c, pb, st, sc,
3435 15 size - (avio_tell(pb) - start_pos));
3436 } else {
3437 52 ret = mov_parse_stsd_data(c, pb, st, sc,
3438 52 size - (avio_tell(pb) - start_pos));
3439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (ret < 0)
3440 ✗ return ret;
3441 }
3442 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3443 854 a.size = size - (avio_tell(pb) - start_pos);
3444
2/2
✓ Branch 0 taken 686 times.
✓ Branch 1 taken 168 times.
854 if (a.size > 8) {
3445
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 686 times.
686 if ((ret = mov_read_default(c, pb, a)) < 0)
3446 ✗ return ret;
3447
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 167 times.
168 } else if (a.size > 0)
3448 1 avio_skip(pb, a.size);
3449
3450 854 ret = mov_finalize_stsd_entry(c, st);
3451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 854 times.
854 if (ret < 0)
3452 ✗ return ret;
3453
3454
3/4
✓ Branch 0 taken 854 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 452 times.
✓ Branch 3 taken 402 times.
854 if (sc->extradata && st->codecpar->extradata) {
3455 452 int extra_size = st->codecpar->extradata_size;
3456
3457 /* Move the current stream extradata to the stream context one. */
3458 452 sc->extradata_size[pseudo_stream_id] = extra_size;
3459 452 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3460 452 st->codecpar->extradata = NULL;
3461 452 st->codecpar->extradata_size = 0;
3462 }
3463 854 sc->stsd_count++;
3464 }
3465
3466
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (pb->eof_reached) {
3467 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3468 ✗ return AVERROR_EOF;
3469 }
3470
3471 838 return 0;
3472 }
3473
3474 838 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3475 {
3476 AVStream *st;
3477 MOVStreamContext *sc;
3478 int ret, entries;
3479
3480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->fc->nb_streams < 1)
3481 ✗ return 0;
3482 838 st = c->fc->streams[c->fc->nb_streams - 1];
3483 838 sc = st->priv_data;
3484
3485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (sc->extradata) {
3486 ✗ av_log(c->fc, AV_LOG_ERROR,
3487 "Duplicate stsd found in this track.\n");
3488 ✗ return AVERROR_INVALIDDATA;
3489 }
3490
3491 838 sc->stsd_version = avio_r8(pb);
3492 838 avio_rb24(pb); /* flags */
3493 838 entries = avio_rb32(pb);
3494
3495 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3496
3/6
✓ Branch 0 taken 838 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 838 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 838 times.
838 if (entries <= 0 || entries > atom.size / 8 || entries > 1024) {
3497 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3498 ✗ return AVERROR_INVALIDDATA;
3499 }
3500
3501 /* Prepare space for hosting multiple extradata. */
3502 838 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3503
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (!sc->extradata)
3504 ✗ return AVERROR(ENOMEM);
3505
3506 838 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (!sc->extradata_size) {
3508 ✗ ret = AVERROR(ENOMEM);
3509 ✗ goto fail;
3510 }
3511
3512 838 ret = ff_mov_read_stsd_entries(c, pb, entries);
3513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (ret < 0)
3514 ✗ goto fail;
3515
3516 /* Restore back the primary extradata. */
3517 838 av_freep(&st->codecpar->extradata);
3518 838 st->codecpar->extradata_size = sc->extradata_size[0];
3519
2/2
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 401 times.
838 if (sc->extradata_size[0]) {
3520 437 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 437 times.
437 if (!st->codecpar->extradata)
3522 ✗ return AVERROR(ENOMEM);
3523 437 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3524 }
3525
3526 838 return mov_finalize_stsd_codec(c, pb, st, sc);
3527 ✗ fail:
3528 ✗ if (sc->extradata) {
3529 int j;
3530 ✗ for (j = 0; j < sc->stsd_count; j++)
3531 ✗ av_freep(&sc->extradata[j]);
3532 }
3533
3534 ✗ sc->stsd_count = 0;
3535 ✗ av_freep(&sc->extradata);
3536 ✗ av_freep(&sc->extradata_size);
3537 ✗ return ret;
3538 }
3539
3540 838 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3541 {
3542 AVStream *st;
3543 MOVStreamContext *sc;
3544 unsigned int i, entries;
3545
3546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->trak_index < 0) {
3547 ✗ av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3548 ✗ return 0;
3549 }
3550
3551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->fc->nb_streams < 1)
3552 ✗ return 0;
3553 838 st = c->fc->streams[c->fc->nb_streams-1];
3554 838 sc = st->priv_data;
3555
3556 838 avio_r8(pb); /* version */
3557 838 avio_rb24(pb); /* flags */
3558
3559 838 entries = avio_rb32(pb);
3560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if ((uint64_t)entries * 12 + 4 > atom.size)
3561 ✗ return AVERROR_INVALIDDATA;
3562
3563 838 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3564
3565
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 705 times.
838 if (!entries)
3566 133 return 0;
3567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 705 times.
705 if (sc->stsc_data) {
3568 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3569 ✗ return 0;
3570 }
3571 705 av_free(sc->stsc_data);
3572 705 sc->stsc_count = 0;
3573 705 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 705 times.
705 if (!sc->stsc_data)
3575 ✗ return AVERROR(ENOMEM);
3576
3577
3/4
✓ Branch 0 taken 3932 times.
✓ Branch 1 taken 705 times.
✓ Branch 2 taken 3932 times.
✗ Branch 3 not taken.
4637 for (i = 0; i < entries && !pb->eof_reached; i++) {
3578 3932 sc->stsc_data[i].first = avio_rb32(pb);
3579 3932 sc->stsc_data[i].count = avio_rb32(pb);
3580 3932 sc->stsc_data[i].id = avio_rb32(pb);
3581 }
3582
3583 705 sc->stsc_count = i;
3584
2/2
✓ Branch 0 taken 3932 times.
✓ Branch 1 taken 705 times.
4637 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3585 3932 int64_t first_min = i + 1;
3586
5/6
✓ Branch 0 taken 3227 times.
✓ Branch 1 taken 705 times.
✓ Branch 2 taken 3227 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3227 times.
✓ Branch 5 taken 705 times.
3932 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
3587
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) ||
3588
1/2
✓ Branch 0 taken 3932 times.
✗ Branch 1 not taken.
3932 sc->stsc_data[i].first < first_min ||
3589
1/2
✓ Branch 0 taken 3932 times.
✗ Branch 1 not taken.
3932 sc->stsc_data[i].count < 1 ||
3590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3932 times.
3932 sc->stsc_data[i].id < 1) {
3591 ✗ 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);
3592 ✗ if (i+1 >= sc->stsc_count) {
3593 ✗ if (sc->stsc_data[i].count == 0 && i > 0) {
3594 ✗ sc->stsc_count --;
3595 ✗ continue;
3596 }
3597 ✗ sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3598 ✗ if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3599 ✗ sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3600 ✗ sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3601 ✗ sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3602 ✗ continue;
3603 }
3604 ✗ av_assert0(sc->stsc_data[i+1].first >= 2);
3605 // We replace this entry by the next valid
3606 ✗ sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3607 ✗ sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3608 ✗ sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3609 }
3610 }
3611
3612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 705 times.
705 if (pb->eof_reached) {
3613 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3614 ✗ return AVERROR_EOF;
3615 }
3616
3617 705 return 0;
3618 }
3619
3620 355566 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3621 {
3622 355566 return index < count - 1;
3623 }
3624
3625 /* Compute the samples value for the stsc entry at the given index. */
3626 57199 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3627 {
3628 int chunk_count;
3629
3630
2/2
✓ Branch 1 taken 57001 times.
✓ Branch 2 taken 198 times.
57199 if (mov_stsc_index_valid(index, sc->stsc_count))
3631 57001 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3632 else {
3633 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3635 198 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3636 }
3637
3638 57199 return sc->stsc_data[index].count * (int64_t)chunk_count;
3639 }
3640
3641 ✗ static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3642 {
3643 AVStream *st;
3644 MOVStreamContext *sc;
3645 unsigned i, entries;
3646
3647 ✗ if (c->trak_index < 0) {
3648 ✗ av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3649 ✗ return 0;
3650 }
3651
3652 ✗ if (c->fc->nb_streams < 1)
3653 ✗ return 0;
3654 ✗ st = c->fc->streams[c->fc->nb_streams-1];
3655 ✗ sc = st->priv_data;
3656
3657 ✗ avio_rb32(pb); // version + flags
3658
3659 ✗ entries = avio_rb32(pb);
3660 ✗ if (sc->stps_data)
3661 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3662 ✗ av_free(sc->stps_data);
3663 ✗ sc->stps_count = 0;
3664 ✗ sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3665 ✗ if (!sc->stps_data)
3666 ✗ return AVERROR(ENOMEM);
3667
3668 ✗ for (i = 0; i < entries && !pb->eof_reached; i++) {
3669 ✗ sc->stps_data[i] = avio_rb32(pb);
3670 }
3671
3672 ✗ sc->stps_count = i;
3673
3674 ✗ if (pb->eof_reached) {
3675 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3676 ✗ return AVERROR_EOF;
3677 }
3678
3679 ✗ return 0;
3680 }
3681
3682 185 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3683 {
3684 AVStream *st;
3685 FFStream *sti;
3686 MOVStreamContext *sc;
3687 unsigned int i, entries;
3688
3689
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 185 times.
185 if (c->trak_index < 0) {
3690 ✗ av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3691 ✗ return 0;
3692 }
3693
3694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 185 times.
185 if (c->fc->nb_streams < 1)
3695 ✗ return 0;
3696 185 st = c->fc->streams[c->fc->nb_streams-1];
3697 185 sti = ffstream(st);
3698 185 sc = st->priv_data;
3699
3700 185 avio_r8(pb); /* version */
3701 185 avio_rb24(pb); /* flags */
3702
3703 185 entries = avio_rb32(pb);
3704
3705 185 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3706
3707
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 171 times.
185 if (!entries) {
3708 14 sc->keyframe_absent = 1;
3709
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)
3710 ✗ sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3711 14 return 0;
3712 }
3713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 171 times.
171 if (sc->keyframes)
3714 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 171 times.
171 if (entries >= UINT_MAX / sizeof(int))
3716 ✗ return AVERROR_INVALIDDATA;
3717 171 av_freep(&sc->keyframes);
3718 171 sc->keyframe_count = 0;
3719 171 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 171 times.
171 if (!sc->keyframes)
3721 ✗ return AVERROR(ENOMEM);
3722
3723
3/4
✓ Branch 0 taken 5772 times.
✓ Branch 1 taken 171 times.
✓ Branch 2 taken 5772 times.
✗ Branch 3 not taken.
5943 for (i = 0; i < entries && !pb->eof_reached; i++) {
3724 5772 sc->keyframes[i] = avio_rb32(pb);
3725 }
3726
3727 171 sc->keyframe_count = i;
3728
3729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 171 times.
171 if (pb->eof_reached) {
3730 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3731 ✗ return AVERROR_EOF;
3732 }
3733
3734 171 return 0;
3735 }
3736
3737 838 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3738 {
3739 AVStream *st;
3740 MOVStreamContext *sc;
3741 unsigned int i, entries, sample_size, field_size, num_bytes;
3742 GetBitContext gb;
3743 unsigned char* buf;
3744 int ret;
3745
3746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->trak_index < 0) {
3747 ✗ av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3748 ✗ return 0;
3749 }
3750
3751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->fc->nb_streams < 1)
3752 ✗ return 0;
3753 838 st = c->fc->streams[c->fc->nb_streams-1];
3754 838 sc = st->priv_data;
3755
3756 838 avio_r8(pb); /* version */
3757 838 avio_rb24(pb); /* flags */
3758
3759
1/2
✓ Branch 0 taken 838 times.
✗ Branch 1 not taken.
838 if (atom.type == MKTAG('s','t','s','z')) {
3760 838 sample_size = avio_rb32(pb);
3761
2/2
✓ Branch 0 taken 792 times.
✓ Branch 1 taken 46 times.
838 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3762 792 sc->sample_size = sample_size;
3763 838 sc->stsz_sample_size = sample_size;
3764 838 field_size = 32;
3765 } else {
3766 ✗ sample_size = 0;
3767 ✗ avio_rb24(pb); /* reserved */
3768 ✗ field_size = avio_r8(pb);
3769 }
3770 838 entries = avio_rb32(pb);
3771
3772 838 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3773
3774 838 sc->sample_count = entries;
3775
2/2
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 604 times.
838 if (sample_size)
3776 234 return 0;
3777
3778
4/8
✓ Branch 0 taken 604 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 604 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 604 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 604 times.
604 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
3779 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3780 ✗ return AVERROR_INVALIDDATA;
3781 }
3782
3783
2/2
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 470 times.
604 if (!entries)
3784 134 return 0;
3785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 if (entries >= (INT_MAX - 4 - 8 * AV_INPUT_BUFFER_PADDING_SIZE) / field_size)
3786 ✗ return AVERROR_INVALIDDATA;
3787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 if (sc->sample_sizes)
3788 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3789 470 av_free(sc->sample_sizes);
3790 470 sc->sample_count = 0;
3791 470 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 if (!sc->sample_sizes)
3793 ✗ return AVERROR(ENOMEM);
3794
3795 470 num_bytes = (entries*field_size+4)>>3;
3796
3797 470 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 if (!buf) {
3799 ✗ av_freep(&sc->sample_sizes);
3800 ✗ return AVERROR(ENOMEM);
3801 }
3802
3803 470 ret = ffio_read_size(pb, buf, num_bytes);
3804
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 if (ret < 0) {
3805 ✗ av_freep(&sc->sample_sizes);
3806 ✗ av_free(buf);
3807 ✗ av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3808 ✗ return 0;
3809 }
3810
3811 470 init_get_bits(&gb, buf, 8*num_bytes);
3812
3813
2/2
✓ Branch 0 taken 240774 times.
✓ Branch 1 taken 470 times.
241244 for (i = 0; i < entries; i++) {
3814 240774 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3815
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240774 times.
240774 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3816 ✗ av_free(buf);
3817 ✗ av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3818 ✗ return AVERROR_INVALIDDATA;
3819 }
3820 240774 sc->data_size += sc->sample_sizes[i];
3821 }
3822
3823 470 sc->sample_count = i;
3824
3825 470 av_free(buf);
3826
3827 470 return 0;
3828 }
3829
3830 838 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3831 {
3832 AVStream *st;
3833 MOVStreamContext *sc;
3834 unsigned int i, entries;
3835 838 int64_t duration = 0;
3836 838 int64_t total_sample_count = 0;
3837 838 int64_t current_dts = 0;
3838 838 int64_t corrected_dts = 0;
3839
3840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->trak_index < 0) {
3841 ✗ av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3842 ✗ return 0;
3843 }
3844
3845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->fc->nb_streams < 1)
3846 ✗ return 0;
3847 838 st = c->fc->streams[c->fc->nb_streams-1];
3848 838 sc = st->priv_data;
3849
3850 838 avio_r8(pb); /* version */
3851 838 avio_rb24(pb); /* flags */
3852 838 entries = avio_rb32(pb);
3853
3854 838 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3855 838 c->fc->nb_streams-1, entries);
3856
3857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (sc->stts_data)
3858 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3859 838 av_freep(&sc->stts_data);
3860 838 sc->stts_count = 0;
3861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3862 ✗ return AVERROR(ENOMEM);
3863
3864
3/4
✓ Branch 0 taken 3127 times.
✓ Branch 1 taken 838 times.
✓ Branch 2 taken 3127 times.
✗ Branch 3 not taken.
3965 for (i = 0; i < entries && !pb->eof_reached; i++) {
3865 unsigned int sample_duration;
3866 unsigned int sample_count;
3867 3127 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3868 3127 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3869 min_entries * sizeof(*sc->stts_data));
3870
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3127 times.
3127 if (!stts_data) {
3871 ✗ av_freep(&sc->stts_data);
3872 ✗ sc->stts_count = 0;
3873 ✗ return AVERROR(ENOMEM);
3874 }
3875 3127 sc->stts_count = min_entries;
3876 3127 sc->stts_data = stts_data;
3877
3878 3127 sample_count = avio_rb32(pb);
3879 3127 sample_duration = avio_rb32(pb);
3880
3881 3127 sc->stts_data[i].count= sample_count;
3882 3127 sc->stts_data[i].duration= sample_duration;
3883
3884 3127 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3885 sample_count, sample_duration);
3886
3887 /* STTS sample offsets are uint32 but some files store it as int32
3888 * with negative values used to correct DTS delays.
3889 There may be abnormally large values as well. */
3890
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3126 times.
3127 if (sample_duration > c->max_stts_delta) {
3891 // assume high delta is a correction if negative when cast as int32
3892 1 int32_t delta_magnitude = (int32_t)sample_duration;
3893 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",
3894 sample_duration, i, sample_count, st->index);
3895 1 sc->stts_data[i].duration = 1;
3896
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);
3897 } else {
3898 3126 corrected_dts += sample_duration * (uint64_t)sample_count;
3899 }
3900
3901 3127 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3902
3903
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 3105 times.
3127 if (current_dts > corrected_dts) {
3904 22 int64_t drift = av_sat_sub64(current_dts, corrected_dts) / FFMAX(sample_count, 1);
3905
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;
3906 22 current_dts -= correction * (uint64_t)sample_count;
3907 22 sc->stts_data[i].duration -= correction;
3908 }
3909
3910 3127 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3911 3127 total_sample_count+=sc->stts_data[i].count;
3912 }
3913
3914 838 sc->stts_count = i;
3915
3916
2/2
✓ Branch 0 taken 704 times.
✓ Branch 1 taken 134 times.
838 if (duration > 0 &&
3917
1/2
✓ Branch 0 taken 704 times.
✗ Branch 1 not taken.
704 duration <= INT64_MAX - sc->duration_for_fps &&
3918
1/2
✓ Branch 0 taken 704 times.
✗ Branch 1 not taken.
704 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3919 704 sc->duration_for_fps += duration;
3920 704 sc->nb_frames_for_fps += total_sample_count;
3921 }
3922
3923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (pb->eof_reached) {
3924 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3925 ✗ return AVERROR_EOF;
3926 }
3927
3928 838 st->nb_frames= total_sample_count;
3929
2/2
✓ Branch 0 taken 704 times.
✓ Branch 1 taken 134 times.
838 if (duration)
3930 704 st->duration= FFMIN(st->duration, duration);
3931
3932 // All samples have zero duration. They have higher chance be chose by
3933 // mov_find_next_sample, which leads to seek again and again.
3934 //
3935 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3936 // So only mark data stream as discarded for safety.
3937
3/4
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 704 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 134 times.
838 if (!duration && sc->stts_count &&
3938 ✗ st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3939 ✗ av_log(c->fc, AV_LOG_WARNING,
3940 "All samples in data stream index:id [%d:%d] have zero "
3941 "duration, stream set to be discarded by default. Override "
3942 "using AVStream->discard or -discard for ffmpeg command.\n",
3943 st->index, sc->id);
3944 ✗ st->discard = AVDISCARD_ALL;
3945 }
3946 838 sc->track_end = duration;
3947 838 return 0;
3948 }
3949
3950 46 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3951 {
3952 AVStream *st;
3953 MOVStreamContext *sc;
3954 unsigned int i;
3955 int64_t entries;
3956
3957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (c->fc->nb_streams < 1)
3958 ✗ return 0;
3959 46 st = c->fc->streams[c->fc->nb_streams - 1];
3960 46 sc = st->priv_data;
3961
3962 46 avio_r8(pb); /* version */
3963 46 avio_rb24(pb); /* flags */
3964 46 entries = atom.size - 4;
3965
3966 46 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3967 46 c->fc->nb_streams - 1, entries);
3968
3969
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 38 times.
46 if (sc->sdtp_data)
3970 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3971 46 av_freep(&sc->sdtp_data);
3972 46 sc->sdtp_count = 0;
3973
3974
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)
3975 ✗ return AVERROR(ERANGE);
3976
3977 46 sc->sdtp_data = av_malloc(entries);
3978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!sc->sdtp_data)
3979 ✗ return AVERROR(ENOMEM);
3980
3981
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++)
3982 3823 sc->sdtp_data[i] = avio_r8(pb);
3983 46 sc->sdtp_count = i;
3984
3985 46 return 0;
3986 }
3987
3988 17509 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3989 {
3990
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 16373 times.
17509 if (duration < 0) {
3991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3992 ✗ av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3993 ✗ duration++;
3994 }
3995 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3996 }
3997 17509 }
3998
3999 84 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4000 {
4001 AVStream *st;
4002 MOVStreamContext *sc;
4003 84 unsigned int i, entries, ctts_count = 0;
4004
4005
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (c->trak_index < 0) {
4006 ✗ av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
4007 ✗ return 0;
4008 }
4009
4010
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (c->fc->nb_streams < 1)
4011 ✗ return 0;
4012 84 st = c->fc->streams[c->fc->nb_streams-1];
4013 84 sc = st->priv_data;
4014
4015 84 avio_r8(pb); /* version */
4016 84 avio_rb24(pb); /* flags */
4017 84 entries = avio_rb32(pb);
4018
4019 84 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
4020
4021
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 80 times.
84 if (!entries)
4022 4 return 0;
4023
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
4024 ✗ return AVERROR_INVALIDDATA;
4025 80 av_freep(&sc->ctts_data);
4026 80 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
4027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!sc->ctts_data)
4028 ✗ return AVERROR(ENOMEM);
4029
4030
3/4
✓ Branch 0 taken 5266 times.
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 5266 times.
✗ Branch 3 not taken.
5346 for (i = 0; i < entries && !pb->eof_reached; i++) {
4031 MOVCtts *ctts_data;
4032 5266 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
4033 5266 const size_t requested_size =
4034 5266 min_size_needed > sc->ctts_allocated_size ?
4035
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5266 times.
5266 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
4036 min_size_needed;
4037 5266 int count = avio_rb32(pb);
4038 5266 int duration = avio_rb32(pb);
4039
4040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5266 times.
5266 if (count <= 0) {
4041 ✗ av_log(c->fc, AV_LOG_TRACE,
4042 "ignoring CTTS entry with count=%d duration=%d\n",
4043 count, duration);
4044 ✗ continue;
4045 }
4046
4047
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5266 times.
5266 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
4048 ✗ return AVERROR(ENOMEM);
4049
4050 5266 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
4051
4052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5266 times.
5266 if (!ctts_data)
4053 ✗ return AVERROR(ENOMEM);
4054
4055 5266 sc->ctts_data = ctts_data;
4056
4057 5266 ctts_data[ctts_count].count = count;
4058 5266 ctts_data[ctts_count].offset = duration;
4059 5266 ctts_count++;
4060
4061 5266 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
4062 count, duration);
4063
4064
2/2
✓ Branch 0 taken 5118 times.
✓ Branch 1 taken 148 times.
5266 if (i+2<entries)
4065 5118 mov_update_dts_shift(sc, duration, c->fc);
4066 }
4067
4068 80 sc->ctts_count = ctts_count;
4069
4070
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (pb->eof_reached) {
4071 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
4072 ✗ return AVERROR_EOF;
4073 }
4074
4075 80 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
4076
4077 80 return 0;
4078 }
4079
4080 54 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4081 {
4082 AVStream *st;
4083 MOVStreamContext *sc;
4084 uint8_t version;
4085 uint32_t grouping_type;
4086 uint32_t default_length;
4087 av_unused uint32_t default_group_description_index;
4088 uint32_t entry_count;
4089
4090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (c->fc->nb_streams < 1)
4091 ✗ return 0;
4092 54 st = c->fc->streams[c->fc->nb_streams - 1];
4093 54 sc = st->priv_data;
4094
4095 54 version = avio_r8(pb); /* version */
4096 54 avio_rb24(pb); /* flags */
4097 54 grouping_type = avio_rl32(pb);
4098
4099 /*
4100 * This function only supports "sync" boxes, but the code is able to parse
4101 * other boxes (such as "tscl", "tsas" and "stsa")
4102 */
4103
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 5 times.
54 if (grouping_type != MKTAG('s','y','n','c'))
4104 49 return 0;
4105
4106
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
4107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
4108 5 entry_count = avio_rb32(pb);
4109
4110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (entry_count > atom.size)
4111 ✗ return AVERROR_INVALIDDATA;
4112
4113 5 av_freep(&sc->sgpd_sync);
4114 5 sc->sgpd_sync_count = entry_count;
4115 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
4116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
4117 ✗ return AVERROR(ENOMEM);
4118
4119
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++) {
4120 8 uint32_t description_length = default_length;
4121
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)
4122 ✗ description_length = avio_rb32(pb);
4123
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
4124 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
4125 8 sc->sgpd_sync[i] = nal_unit_type;
4126 8 description_length -= 1;
4127 }
4128 8 avio_skip(pb, description_length);
4129 }
4130
4131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
4132 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
4133 ✗ return AVERROR_EOF;
4134 }
4135
4136 5 return 0;
4137 }
4138
4139 50 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4140 {
4141 AVStream *st;
4142 MOVStreamContext *sc;
4143 unsigned int i, entries;
4144 uint8_t version;
4145 uint32_t grouping_type;
4146 MOVSbgp *table, **tablep;
4147 int *table_count;
4148
4149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (c->fc->nb_streams < 1)
4150 ✗ return 0;
4151 50 st = c->fc->streams[c->fc->nb_streams-1];
4152 50 sc = st->priv_data;
4153
4154 50 version = avio_r8(pb); /* version */
4155 50 avio_rb24(pb); /* flags */
4156 50 grouping_type = avio_rl32(pb);
4157
4158
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 49 times.
50 if (grouping_type == MKTAG('r','a','p',' ')) {
4159 1 tablep = &sc->rap_group;
4160 1 table_count = &sc->rap_group_count;
4161
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 44 times.
49 } else if (grouping_type == MKTAG('s','y','n','c')) {
4162 5 tablep = &sc->sync_group;
4163 5 table_count = &sc->sync_group_count;
4164 } else {
4165 44 return 0;
4166 }
4167
4168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
4169 ✗ avio_rb32(pb); /* grouping_type_parameter */
4170
4171 6 entries = avio_rb32(pb);
4172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
4173 ✗ return 0;
4174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
4175 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
4176 6 av_freep(tablep);
4177 6 table = av_malloc_array(entries, sizeof(*table));
4178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
4179 ✗ return AVERROR(ENOMEM);
4180 6 *tablep = table;
4181
4182
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++) {
4183 32 table[i].count = avio_rb32(pb); /* sample_count */
4184 32 table[i].index = avio_rb32(pb); /* group_description_index */
4185 }
4186
4187 6 *table_count = i;
4188
4189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
4190 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
4191 ✗ return AVERROR_EOF;
4192 }
4193
4194 6 return 0;
4195 }
4196
4197 /**
4198 * Get ith edit list entry (media time, duration).
4199 */
4200 1121 static int get_edit_list_entry(MOVContext *mov,
4201 const MOVStreamContext *msc,
4202 unsigned int edit_list_index,
4203 int64_t *edit_list_media_time,
4204 int64_t *edit_list_duration,
4205 int64_t global_timescale)
4206 {
4207
2/2
✓ Branch 0 taken 546 times.
✓ Branch 1 taken 575 times.
1121 if (edit_list_index == msc->elst_count) {
4208 546 return 0;
4209 }
4210 575 *edit_list_media_time = msc->elst_data[edit_list_index].time;
4211 575 *edit_list_duration = msc->elst_data[edit_list_index].duration;
4212
4213 /* duration is in global timescale units;convert to msc timescale */
4214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 if (global_timescale == 0) {
4215 ✗ avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
4216 ✗ return 0;
4217 }
4218 575 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
4219 global_timescale);
4220
4221
1/2
✓ Branch 0 taken 575 times.
✗ Branch 1 not taken.
575 if (*edit_list_duration < 0 ||
4222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 *edit_list_media_time > INT64_MAX - *edit_list_duration)
4223 ✗ *edit_list_duration = 0;
4224
4225 575 return 1;
4226 }
4227
4228 /**
4229 * Find the closest previous frame to the timestamp_pts, in e_old index
4230 * entries. Searching for just any frame / just key frames can be controlled by
4231 * last argument 'flag'.
4232 * Note that if ctts_data is not NULL, we will always search for a key frame
4233 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
4234 * return the first frame of the video.
4235 *
4236 * Here the timestamp_pts is considered to be a presentation timestamp and
4237 * the timestamp of index entries are considered to be decoding timestamps.
4238 *
4239 * Returns 0 if successful in finding a frame, else returns -1.
4240 * Places the found index corresponding output arg.
4241 *
4242 * If ctts_old is not NULL, then refines the searched entry by searching
4243 * backwards from the found timestamp, to find the frame with correct PTS.
4244 *
4245 * Places the found ctts_index and ctts_sample in corresponding output args.
4246 */
4247 575 static int find_prev_closest_index(AVStream *st,
4248 AVIndexEntry *e_old,
4249 int nb_old,
4250 MOVTimeToSample *tts_data,
4251 int64_t tts_count,
4252 int64_t timestamp_pts,
4253 int flag,
4254 int64_t* index,
4255 int64_t* tts_index,
4256 int64_t* tts_sample)
4257 {
4258 575 MOVStreamContext *msc = st->priv_data;
4259 575 FFStream *const sti = ffstream(st);
4260 575 AVIndexEntry *e_keep = sti->index_entries;
4261 575 int nb_keep = sti->nb_index_entries;
4262 575 int64_t i = 0;
4263
4264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 av_assert0(index);
4265
4266 // If dts_shift > 0, then all the index timestamps will have to be offset by
4267 // at least dts_shift amount to obtain PTS.
4268 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
4269
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 566 times.
575 if (msc->dts_shift > 0) {
4270 9 timestamp_pts -= msc->dts_shift;
4271 }
4272
4273 575 sti->index_entries = e_old;
4274 575 sti->nb_index_entries = nb_old;
4275 575 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
4276
4277 // Keep going backwards in the index entries until the timestamp is the same.
4278
2/2
✓ Branch 0 taken 574 times.
✓ Branch 1 taken 1 times.
575 if (*index >= 0) {
4279
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 546 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
574 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
4280 ✗ i--) {
4281 ✗ if ((flag & AVSEEK_FLAG_ANY) ||
4282 ✗ (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
4283 ✗ *index = i - 1;
4284 }
4285 }
4286 }
4287
4288 // If we have CTTS then refine the search, by searching backwards over PTS
4289 // computed by adding corresponding CTTS durations to index timestamps.
4290
4/4
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 487 times.
✓ Branch 2 taken 87 times.
✓ Branch 3 taken 1 times.
575 if (msc->ctts_count && *index >= 0) {
4291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
87 av_assert0(tts_index);
4292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
87 av_assert0(tts_sample);
4293 // Find out the ctts_index for the found frame.
4294 87 *tts_index = FFMIN(*index, tts_count);
4295 87 *tts_sample = 0;
4296
4297
4/6
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 98 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 98 times.
✗ Branch 5 not taken.
105 while (*index >= 0 && (*tts_index) >= 0 && (*tts_index) < tts_count) {
4298 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
4299 // No need to add dts_shift to the timestamp here because timestamp_pts has already been
4300 // compensated by dts_shift above.
4301
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 13 times.
98 if ((e_old[*index].timestamp + tts_data[*tts_index].offset) <= timestamp_pts &&
4302
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 5 times.
85 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
4303 80 break;
4304 }
4305
4306 18 (*index)--;
4307
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (*tts_sample == 0) {
4308 18 (*tts_index)--;
4309
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 7 times.
18 if (*tts_index >= 0)
4310 11 *tts_sample = tts_data[*tts_index].count - 1;
4311 } else {
4312 ✗ (*tts_sample)--;
4313 }
4314 }
4315 }
4316
4317 /* restore AVStream state*/
4318 575 sti->index_entries = e_keep;
4319 575 sti->nb_index_entries = nb_keep;
4320
2/2
✓ Branch 0 taken 567 times.
✓ Branch 1 taken 8 times.
575 return *index >= 0 ? 0 : -1;
4321 }
4322
4323 /**
4324 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
4325 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
4326 *
4327 * This function is similar to ff_add_index_entry in libavformat/utils.c
4328 * except that here we are always unconditionally adding an index entry to
4329 * the end, instead of searching the entries list and skipping the add if
4330 * there is an existing entry with the same timestamp.
4331 * This is needed because the mov_fix_index calls this func with the same
4332 * unincremented timestamp for successive discarded frames.
4333 */
4334 362304 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
4335 int size, int distance, int flags)
4336 {
4337 362304 FFStream *const sti = ffstream(st);
4338 AVIndexEntry *entries, *ie;
4339 362304 int64_t index = -1;
4340 362304 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
4341
4342 // Double the allocation each time, to lower memory fragmentation.
4343 // Another difference from ff_add_index_entry function.
4344 362304 const size_t requested_size =
4345 362304 min_size_needed > sti->index_entries_allocated_size ?
4346
2/2
✓ Branch 0 taken 2430 times.
✓ Branch 1 taken 359874 times.
362304 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
4347 min_size_needed;
4348
4349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 362304 times.
362304 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
4350 ✗ return -1;
4351
4352 362304 entries = av_fast_realloc(sti->index_entries,
4353 &sti->index_entries_allocated_size,
4354 requested_size);
4355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 362304 times.
362304 if (!entries)
4356 ✗ return -1;
4357
4358 362304 sti->index_entries = entries;
4359
4360 362304 index = sti->nb_index_entries++;
4361 362304 ie= &entries[index];
4362
4363 362304 ie->pos = pos;
4364 362304 ie->timestamp = timestamp;
4365 362304 ie->min_distance= distance;
4366 362304 ie->size= size;
4367 362304 ie->flags = flags;
4368 362304 return index;
4369 }
4370
4371 /**
4372 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4373 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4374 */
4375 51 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4376 int64_t* frame_duration_buffer,
4377 int frame_duration_buffer_size) {
4378 51 FFStream *const sti = ffstream(st);
4379 51 int i = 0;
4380
2/4
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 51 times.
51 av_assert0(end_index >= 0 && end_index <= sti->nb_index_entries);
4381
2/2
✓ Branch 0 taken 196 times.
✓ Branch 1 taken 51 times.
247 for (i = 0; i < frame_duration_buffer_size; i++) {
4382 196 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4383 196 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4384 }
4385 51 }
4386
4387 197056 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4388 int count, int offset, unsigned int duration)
4389 {
4390 MOVTimeToSample *tts_buf_new;
4391 197056 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4392 197056 const size_t requested_size =
4393 197056 min_size_needed > *allocated_size ?
4394
2/2
✓ Branch 0 taken 1729 times.
✓ Branch 1 taken 195327 times.
197056 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4395 min_size_needed;
4396
4397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197056 times.
197056 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4398 ✗ return -1;
4399
4400 197056 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4401
4402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197056 times.
197056 if (!tts_buf_new)
4403 ✗ return -1;
4404
4405 197056 *tts_data = tts_buf_new;
4406
4407 197056 tts_buf_new[*tts_count].count = count;
4408 197056 tts_buf_new[*tts_count].offset = offset;
4409 197056 tts_buf_new[*tts_count].duration = duration;
4410
4411 197056 *tts_count = (*tts_count) + 1;
4412 197056 return 0;
4413 }
4414
4415 #define MAX_REORDER_DELAY 16
4416 757 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4417 {
4418 757 MOVStreamContext *msc = st->priv_data;
4419 757 FFStream *const sti = ffstream(st);
4420 757 int ctts_ind = 0;
4421 757 int ctts_sample = 0;
4422 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4423 757 int buf_start = 0;
4424 int j, r, num_swaps;
4425
4426
2/2
✓ Branch 0 taken 12869 times.
✓ Branch 1 taken 757 times.
13626 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4427 12869 pts_buf[j] = INT64_MIN;
4428
4429
3/4
✓ Branch 0 taken 757 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
✓ Branch 3 taken 677 times.
757 if (st->codecpar->video_delay <= 0 && msc->ctts_count &&
4430
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 28 times.
80 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4431 52 st->codecpar->video_delay = 0;
4432
3/4
✓ Branch 0 taken 138527 times.
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 138527 times.
✗ Branch 3 not taken.
138579 for (int ind = 0; ind < sti->nb_index_entries && ctts_ind < msc->tts_count; ++ind) {
4433 // Point j to the last elem of the buffer and insert the current pts there.
4434 138527 j = buf_start;
4435 138527 buf_start = (buf_start + 1);
4436
2/2
✓ Branch 0 taken 8121 times.
✓ Branch 1 taken 130406 times.
138527 if (buf_start == MAX_REORDER_DELAY + 1)
4437 8121 buf_start = 0;
4438
4439 138527 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4440
4441 // The timestamps that are already in the sorted buffer, and are greater than the
4442 // current pts, are exactly the timestamps that need to be buffered to output PTS
4443 // in correct sorted order.
4444 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4445 // can be computed as the maximum no. of swaps any particular timestamp needs to
4446 // go through, to keep this buffer in sorted order.
4447 138527 num_swaps = 0;
4448
2/2
✓ Branch 0 taken 142881 times.
✓ Branch 1 taken 4 times.
142885 while (j != buf_start) {
4449 142881 r = j - 1;
4450
2/2
✓ Branch 0 taken 8426 times.
✓ Branch 1 taken 134455 times.
142881 if (r < 0) r = MAX_REORDER_DELAY;
4451
2/2
✓ Branch 0 taken 4358 times.
✓ Branch 1 taken 138523 times.
142881 if (pts_buf[j] < pts_buf[r]) {
4452 4358 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4453 4358 ++num_swaps;
4454 } else {
4455 138523 break;
4456 }
4457 4358 j = r;
4458 }
4459 138527 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4460
4461 138527 ctts_sample++;
4462
1/2
✓ Branch 0 taken 138527 times.
✗ Branch 1 not taken.
138527 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4463 138527 ctts_ind++;
4464 138527 ctts_sample = 0;
4465 }
4466 }
4467 52 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4468 52 st->codecpar->video_delay, st->index);
4469 }
4470 757 }
4471
4472 120932 static void mov_current_sample_inc(MOVStreamContext *sc)
4473 {
4474 120932 sc->current_sample++;
4475 120932 sc->current_index++;
4476
2/2
✓ Branch 0 taken 72062 times.
✓ Branch 1 taken 48870 times.
120932 if (sc->index_ranges &&
4477
2/2
✓ Branch 0 taken 501 times.
✓ Branch 1 taken 71561 times.
72062 sc->current_index >= sc->current_index_range->end &&
4478
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 sc->current_index_range->end) {
4479 501 sc->current_index_range++;
4480 501 sc->current_index = sc->current_index_range->start;
4481 }
4482 120932 }
4483
4484 ✗ static void mov_current_sample_dec(MOVStreamContext *sc)
4485 {
4486 ✗ sc->current_sample--;
4487 ✗ sc->current_index--;
4488 ✗ if (sc->index_ranges &&
4489 ✗ sc->current_index < sc->current_index_range->start &&
4490 ✗ sc->current_index_range > sc->index_ranges) {
4491 ✗ sc->current_index_range--;
4492 ✗ sc->current_index = sc->current_index_range->end - 1;
4493 }
4494 ✗ }
4495
4496 339 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4497 {
4498 int64_t range_size;
4499
4500 339 sc->current_sample = current_sample;
4501 339 sc->current_index = current_sample;
4502
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 311 times.
339 if (!sc->index_ranges) {
4503 28 return;
4504 }
4505
4506 311 for (sc->current_index_range = sc->index_ranges;
4507
1/2
✓ Branch 0 taken 311 times.
✗ Branch 1 not taken.
311 sc->current_index_range->end;
4508 ✗ sc->current_index_range++) {
4509 311 range_size = sc->current_index_range->end - sc->current_index_range->start;
4510
1/2
✓ Branch 0 taken 311 times.
✗ Branch 1 not taken.
311 if (range_size > current_sample) {
4511 311 sc->current_index = sc->current_index_range->start + current_sample;
4512 311 break;
4513 }
4514 ✗ current_sample -= range_size;
4515 }
4516 }
4517
4518 /**
4519 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4520 * which are needed to decode them) that fall in the edit list time ranges.
4521 * Also fixes the timestamps of the index entries to match the timeline
4522 * specified the edit lists.
4523 */
4524 757 static void mov_fix_index(MOVContext *mov, AVStream *st)
4525 {
4526 757 MOVStreamContext *msc = st->priv_data;
4527 757 FFStream *const sti = ffstream(st);
4528 757 AVIndexEntry *e_old = sti->index_entries;
4529 757 int nb_old = sti->nb_index_entries;
4530 757 const AVIndexEntry *e_old_end = e_old + nb_old;
4531 757 const AVIndexEntry *current = NULL;
4532 757 MOVTimeToSample *tts_data_old = msc->tts_data;
4533 757 int64_t tts_index_old = 0;
4534 757 int64_t tts_sample_old = 0;
4535 757 int64_t tts_count_old = msc->tts_count;
4536 757 int64_t edit_list_media_time = 0;
4537 757 int64_t edit_list_duration = 0;
4538 757 int64_t frame_duration = 0;
4539 757 int64_t edit_list_dts_counter = 0;
4540 757 int64_t edit_list_dts_entry_end = 0;
4541 757 int64_t edit_list_start_tts_sample = 0;
4542 int64_t curr_cts;
4543 757 int64_t curr_ctts = 0;
4544 757 int64_t empty_edits_sum_duration = 0;
4545 757 int64_t edit_list_index = 0;
4546 int64_t index;
4547 int flags;
4548 757 int64_t start_dts = 0;
4549 757 int64_t edit_list_start_encountered = 0;
4550 757 int64_t search_timestamp = 0;
4551 757 int64_t* frame_duration_buffer = NULL;
4552 757 int num_discarded_begin = 0;
4553 757 int first_non_zero_audio_edit = -1;
4554 757 int packet_skip_samples = 0;
4555 757 MOVIndexRange *current_index_range = NULL;
4556 757 int found_keyframe_after_edit = 0;
4557 757 int found_non_empty_edit = 0;
4558
4559
4/6
✓ Branch 0 taken 546 times.
✓ Branch 1 taken 211 times.
✓ Branch 2 taken 546 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 546 times.
757 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
4560 211 return;
4561 }
4562
4563 546 int64_t max_entries = nb_old * 16LL + (1 << 16);
4564
4565 // allocate the index ranges array
4566 546 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4567 sizeof(msc->index_ranges[0]));
4568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 546 times.
546 if (!msc->index_ranges) {
4569 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4570 ✗ return;
4571 }
4572 546 msc->current_index_range = msc->index_ranges;
4573
4574 // Clean AVStream from traces of old index
4575 546 sti->index_entries = NULL;
4576 546 sti->index_entries_allocated_size = 0;
4577 546 sti->nb_index_entries = 0;
4578
4579 // Clean time to sample fields of MOVStreamContext
4580 546 msc->tts_data = NULL;
4581 546 msc->tts_count = 0;
4582 546 msc->tts_index = 0;
4583 546 msc->tts_sample = 0;
4584 546 msc->tts_allocated_size = 0;
4585
4586 // Reinitialize min_corrected_pts so that it can be computed again.
4587 546 msc->min_corrected_pts = -1;
4588
4589 // If the dts_shift is positive (in case of negative ctts values in mov),
4590 // then negate the DTS by dts_shift
4591
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 537 times.
546 if (msc->dts_shift > 0) {
4592 9 edit_list_dts_entry_end -= msc->dts_shift;
4593 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4594 }
4595
4596 546 start_dts = edit_list_dts_entry_end;
4597
4598
2/2
✓ Branch 0 taken 575 times.
✓ Branch 1 taken 546 times.
1667 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
4599 1121 &edit_list_duration, mov->time_scale)) {
4600 575 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4601 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4602 575 edit_list_index++;
4603 575 edit_list_dts_counter = edit_list_dts_entry_end;
4604 575 edit_list_dts_entry_end = av_sat_add64(edit_list_dts_entry_end, edit_list_duration);
4605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 if (edit_list_dts_entry_end == INT64_MAX) {
4606 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot calculate dts entry length with duration %"PRId64"\n",
4607 edit_list_duration);
4608 ✗ break;
4609 }
4610 575 num_discarded_begin = 0;
4611
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 571 times.
575 if (edit_list_media_time == -1) {
4612
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!found_non_empty_edit)
4613 4 empty_edits_sum_duration += edit_list_duration;
4614 4 continue;
4615 }
4616 571 found_non_empty_edit = 1;
4617
4618 // If we encounter a non-negative edit list reset the skip_samples/initial_padding fields and set them
4619 // according to the edit list below.
4620
2/2
✓ Branch 0 taken 167 times.
✓ Branch 1 taken 404 times.
571 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4621
1/2
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
167 if (first_non_zero_audio_edit < 0) {
4622 167 first_non_zero_audio_edit = 1;
4623 } else {
4624 ✗ first_non_zero_audio_edit = 0;
4625 }
4626
4627
1/2
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
167 if (first_non_zero_audio_edit > 0)
4628 167 sti->skip_samples = st->codecpar->initial_padding = 0;
4629 }
4630
4631 // While reordering frame index according to edit list we must handle properly
4632 // the scenario when edit list entry starts from none key frame.
4633 // We find closest previous key frame and preserve it and consequent frames in index.
4634 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4635 571 search_timestamp = edit_list_media_time;
4636
2/2
✓ Branch 0 taken 167 times.
✓ Branch 1 taken 404 times.
571 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4637 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4638 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4639 // edit_list_media_time to cover the decoder delay.
4640
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 166 times.
167 search_timestamp = FFMAX(av_sat_sub64(search_timestamp, msc->time_scale), e_old[0].timestamp);
4641 }
4642
4643
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 567 times.
571 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, 0,
4644 &index, &tts_index_old, &tts_sample_old) < 0) {
4645 4 av_log(mov->fc, AV_LOG_WARNING,
4646 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4647 st->index, edit_list_index, search_timestamp);
4648
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,
4649 &index, &tts_index_old, &tts_sample_old) < 0) {
4650 4 av_log(mov->fc, AV_LOG_WARNING,
4651 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4652 st->index, edit_list_index, search_timestamp);
4653 4 index = 0;
4654 4 tts_index_old = 0;
4655 4 tts_sample_old = 0;
4656 }
4657 }
4658 571 current = e_old + index;
4659 571 edit_list_start_tts_sample = tts_sample_old;
4660
4661 // Iterate over index and arrange it according to edit list
4662 571 edit_list_start_encountered = 0;
4663 571 found_keyframe_after_edit = 0;
4664
2/2
✓ Branch 0 taken 362304 times.
✓ Branch 1 taken 145 times.
362449 for (; current < e_old_end; current++, index++) {
4665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 362304 times.
362304 if (sti->nb_index_entries >= max_entries) {
4666 ✗ av_log(mov->fc, AV_LOG_ERROR, "Edit list expands the sample index beyond %"PRId64" entries\n",
4667 max_entries);
4668 ✗ goto truncated;
4669 }
4670 // check if frame outside edit list mark it for discard
4671 724608 frame_duration = (current + 1 < e_old_end) ?
4672
2/2
✓ Branch 0 taken 361766 times.
✓ Branch 1 taken 538 times.
362304 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4673
4674 362304 flags = current->flags;
4675
4676 // frames (pts) before or after edit list
4677 362304 curr_cts = current->timestamp + msc->dts_shift;
4678 362304 curr_ctts = 0;
4679
4680
4/4
✓ Branch 0 taken 197068 times.
✓ Branch 1 taken 165236 times.
✓ Branch 2 taken 197056 times.
✓ Branch 3 taken 12 times.
362304 if (tts_data_old && tts_index_old < tts_count_old) {
4681 197056 curr_ctts = tts_data_old[tts_index_old].offset;
4682 197056 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4683 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4684 197056 curr_cts += curr_ctts;
4685 197056 tts_sample_old++;
4686
1/2
✓ Branch 0 taken 197056 times.
✗ Branch 1 not taken.
197056 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197056 times.
197056 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4688 &msc->tts_allocated_size,
4689 197056 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4690 197056 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4691 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4692 tts_index_old,
4693 ✗ tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4694 ✗ tts_data_old[tts_index_old].offset);
4695 ✗ break;
4696 }
4697 197056 tts_index_old++;
4698 197056 tts_sample_old = 0;
4699 197056 edit_list_start_tts_sample = 0;
4700 }
4701 }
4702
4703
4/4
✓ Branch 0 taken 362079 times.
✓ Branch 1 taken 225 times.
✓ Branch 2 taken 158 times.
✓ Branch 3 taken 361921 times.
362304 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
4704
4/4
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 259 times.
✓ Branch 2 taken 80 times.
✓ Branch 3 taken 44 times.
383 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
4705
4/6
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 55 times.
✓ Branch 4 taken 25 times.
✗ Branch 5 not taken.
80 curr_cts < edit_list_media_time && curr_cts + frame_duration > edit_list_media_time &&
4706 first_non_zero_audio_edit > 0) {
4707 25 packet_skip_samples = edit_list_media_time - curr_cts;
4708 25 sti->skip_samples += packet_skip_samples;
4709
4710 // Shift the index entry timestamp by packet_skip_samples to be correct.
4711 25 edit_list_dts_counter -= packet_skip_samples;
4712
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 if (edit_list_start_encountered == 0) {
4713 25 edit_list_start_encountered = 1;
4714 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4715 // discarded packets.
4716
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 10 times.
25 if (frame_duration_buffer) {
4717 15 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4718 frame_duration_buffer, num_discarded_begin);
4719 15 av_freep(&frame_duration_buffer);
4720 }
4721 }
4722
4723 25 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4724 } else {
4725 358 flags |= AVINDEX_DISCARD_FRAME;
4726 358 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4727
4728
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 160 times.
358 if (edit_list_start_encountered == 0) {
4729 198 num_discarded_begin++;
4730
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 198 times.
198 if (av_reallocp_array(&frame_duration_buffer, num_discarded_begin,
4731 sizeof(*frame_duration_buffer)) < 0) {
4732 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4733 ✗ break;
4734 }
4735 198 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4736
4737 // Increment skip_samples for the first non-zero audio edit list
4738
3/4
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 99 times.
✗ Branch 3 not taken.
198 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4739
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 44 times.
99 first_non_zero_audio_edit > 0 && st->codecpar->codec_id != AV_CODEC_ID_VORBIS) {
4740 55 sti->skip_samples += frame_duration;
4741 }
4742 }
4743 }
4744 } else {
4745
2/2
✓ Branch 0 taken 545 times.
✓ Branch 1 taken 361376 times.
361921 if (msc->min_corrected_pts < 0) {
4746 545 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4747 } else {
4748 361376 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4749 }
4750
2/2
✓ Branch 0 taken 544 times.
✓ Branch 1 taken 361377 times.
361921 if (edit_list_start_encountered == 0) {
4751 544 edit_list_start_encountered = 1;
4752 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4753 // discarded packets.
4754
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 508 times.
544 if (frame_duration_buffer) {
4755 36 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4756 frame_duration_buffer, num_discarded_begin);
4757 36 av_freep(&frame_duration_buffer);
4758 }
4759 }
4760 }
4761
4762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 362304 times.
362304 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
4763 362304 current->min_distance, flags) == -1) {
4764 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4765 ✗ break;
4766 }
4767
4768 // Update the index ranges array
4769
4/4
✓ Branch 0 taken 361758 times.
✓ Branch 1 taken 546 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 361735 times.
362304 if (!current_index_range || index != current_index_range->end) {
4770 569 current_index_range = current_index_range ? current_index_range + 1
4771
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 546 times.
569 : msc->index_ranges;
4772 569 current_index_range->start = index;
4773 }
4774 362304 current_index_range->end = index + 1;
4775
4776 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4777
2/2
✓ Branch 0 taken 362106 times.
✓ Branch 1 taken 198 times.
362304 if (edit_list_start_encountered > 0) {
4778 362106 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4779 }
4780
4781 // Break when found first key frame after edit entry completion
4782
2/2
✓ Branch 0 taken 767 times.
✓ Branch 1 taken 361537 times.
362304 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
4783
4/4
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 445 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 319 times.
767 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
4784
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 415 times.
448 if (msc->ctts_count) {
4785 // If we have CTTS and this is the first keyframe after edit elist,
4786 // wait for one more, because there might be trailing B-frames after this I-frame
4787 // that do belong to the edit.
4788
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) {
4789 22 found_keyframe_after_edit = 1;
4790 22 continue;
4791 }
4792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (tts_sample_old != 0) {
4793 ✗ if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4794 &msc->tts_allocated_size,
4795 ✗ tts_sample_old - edit_list_start_tts_sample,
4796 ✗ tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4797 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4798 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4799 ✗ tts_data_old[tts_index_old].offset);
4800 ✗ break;
4801 }
4802 }
4803 }
4804 426 break;
4805 }
4806 }
4807 }
4808 546 truncated:
4809 // If there are empty edits, then msc->min_corrected_pts might be positive
4810 // intentionally. So we subtract the sum duration of empty edits here.
4811 546 msc->min_corrected_pts -= empty_edits_sum_duration;
4812
4813 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4814 // dts by that amount to make the first pts zero.
4815
2/2
✓ Branch 0 taken 328 times.
✓ Branch 1 taken 218 times.
546 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4816
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 266 times.
328 if (msc->min_corrected_pts > 0) {
4817 62 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4818
2/2
✓ Branch 0 taken 3322 times.
✓ Branch 1 taken 62 times.
3384 for (int i = 0; i < sti->nb_index_entries; ++i)
4819 3322 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4820 }
4821 }
4822 // Start time should be equal to zero or the duration of any empty edits.
4823 546 st->start_time = empty_edits_sum_duration;
4824
4825 // Update av stream length, if it ends up shorter than the track's media duration
4826 546 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4827 546 st->codecpar->initial_padding = sti->skip_samples;
4828
4829 // Free the old index and the old CTTS structures
4830 546 av_free(e_old);
4831 546 av_free(tts_data_old);
4832 546 av_freep(&frame_duration_buffer);
4833
4834 // Null terminate the index ranges array
4835 546 current_index_range = current_index_range ? current_index_range + 1
4836
1/2
✓ Branch 0 taken 546 times.
✗ Branch 1 not taken.
546 : msc->index_ranges;
4837 546 current_index_range->start = 0;
4838 546 current_index_range->end = 0;
4839 546 msc->current_index = msc->index_ranges[0].start;
4840 }
4841
4842 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4843 {
4844
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4845
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == nal_unit_type)
4846 5 return i + 1;
4847 ✗ return 0;
4848 }
4849
4850 891 static int build_open_gop_key_points(AVStream *st)
4851 {
4852 int k;
4853 891 int sample_id = 0;
4854 uint32_t cra_index;
4855 891 MOVStreamContext *sc = st->priv_data;
4856
4857
4/4
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 812 times.
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 5 times.
891 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count)
4858 886 return 0;
4859
4860 /* Build an unrolled index of the samples */
4861 5 sc->sample_offsets_count = 0;
4862
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4864 ✗ return AVERROR(ENOMEM);
4865 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4866 }
4867 5 av_freep(&sc->sample_offsets);
4868 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4870 ✗ return AVERROR(ENOMEM);
4871 5 k = 0;
4872
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4873
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4874 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4875
4876 /* The following HEVC NAL type reveal the use of open GOP sync points
4877 * (TODO: BLA types may also be concerned) */
4878 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4880 ✗ return 0;
4881
4882 /* Build a list of open-GOP key samples */
4883 5 sc->open_key_samples_count = 0;
4884
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4885
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4886
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)
4887 ✗ return AVERROR(ENOMEM);
4888 11 sc->open_key_samples_count += sc->sync_group[i].count;
4889 }
4890 5 av_freep(&sc->open_key_samples);
4891 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4892
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4893 ✗ return AVERROR(ENOMEM);
4894 5 k = 0;
4895
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4896 28 const MOVSbgp *sg = &sc->sync_group[i];
4897
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4898
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4899 11 sc->open_key_samples[k++] = sample_id;
4900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4901 ✗ return AVERROR_PATCHWELCOME;
4902 28 sample_id += sg->count;
4903 }
4904
4905 /* Identify the minimal time step between samples */
4906 5 sc->min_sample_duration = UINT_MAX;
4907
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4908 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4909
4910 5 return 0;
4911 }
4912
4913 #define MOV_MERGE_CTTS 1
4914 #define MOV_MERGE_STTS 2
4915 /*
4916 * Merge stts and ctts arrays into a new combined array.
4917 * stts_count and ctts_count may be left untouched as they will be
4918 * used to check for the presence of either of them.
4919 */
4920 757 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4921 {
4922 757 MOVStreamContext *sc = st->priv_data;
4923
3/4
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 677 times.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
757 int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS);
4924
3/4
✓ Branch 0 taken 757 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 686 times.
✓ Branch 3 taken 71 times.
757 int stts = sc->stts_data && (flags & MOV_MERGE_STTS);
4925 757 int idx = 0;
4926
4927
3/4
✓ Branch 0 taken 677 times.
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 677 times.
757 if (!sc->ctts_data && !sc->stts_data)
4928 ✗ return 0;
4929 // Expand time to sample entries such that we have a 1-1 mapping with samples
4930
2/4
✓ Branch 0 taken 757 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 757 times.
757 if (!sc->sample_count || sc->sample_count >= UINT_MAX / sizeof(*sc->tts_data))
4931 ✗ return -1;
4932
4933
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 677 times.
757 if (ctts) {
4934 160 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4935 80 sc->sample_count * sizeof(*sc->tts_data));
4936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!sc->tts_data)
4937 ✗ return -1;
4938
4939 80 memset(sc->tts_data, 0, sc->tts_allocated_size);
4940
4941
2/2
✓ Branch 0 taken 5266 times.
✓ Branch 1 taken 80 times.
5346 for (int i = 0; i < sc->ctts_count &&
4942
1/2
✓ Branch 0 taken 5266 times.
✗ Branch 1 not taken.
10532 idx < sc->sample_count; i++)
4943
2/2
✓ Branch 0 taken 139484 times.
✓ Branch 1 taken 5266 times.
144750 for (int j = 0; j < sc->ctts_data[i].count &&
4944
1/2
✓ Branch 0 taken 139484 times.
✗ Branch 1 not taken.
139484 idx < sc->sample_count; j++) {
4945 139484 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4946 139484 sc->tts_data[idx++].count = 1;
4947 }
4948
4949 80 sc->tts_count = idx;
4950 } else
4951 677 sc->ctts_count = 0;
4952 757 av_freep(&sc->ctts_data);
4953 757 sc->ctts_allocated_size = 0;
4954
4955 757 idx = 0;
4956
2/2
✓ Branch 0 taken 686 times.
✓ Branch 1 taken 71 times.
757 if (stts) {
4957 686 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4958 686 sc->sample_count * sizeof(*sc->tts_data));
4959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 686 times.
686 if (!tts_data)
4960 ✗ return -1;
4961
4962
2/2
✓ Branch 0 taken 606 times.
✓ Branch 1 taken 80 times.
686 if (!sc->tts_data)
4963 606 memset(tts_data, 0, sc->tts_allocated_size);
4964 686 sc->tts_data = tts_data;
4965
4966
2/2
✓ Branch 0 taken 3109 times.
✓ Branch 1 taken 686 times.
3795 for (int i = 0; i < sc->stts_count &&
4967
1/2
✓ Branch 0 taken 3109 times.
✗ Branch 1 not taken.
6218 idx < sc->sample_count; i++)
4968
2/2
✓ Branch 0 taken 250107 times.
✓ Branch 1 taken 3109 times.
253216 for (int j = 0; j < sc->stts_data[i].count &&
4969
1/2
✓ Branch 0 taken 250107 times.
✗ Branch 1 not taken.
250107 idx < sc->sample_count; j++) {
4970 250107 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4971 250107 sc->tts_data[idx++].count = 1;
4972 }
4973
4974 686 sc->tts_count = FFMAX(sc->tts_count, idx);
4975 } else
4976 71 sc->stts_count = 0;
4977 757 av_freep(&sc->stts_data);
4978 757 sc->stts_allocated_size = 0;
4979
4980 757 return 0;
4981 }
4982
4983 891 static void mov_build_index(MOVContext *mov, AVStream *st)
4984 {
4985 891 MOVStreamContext *sc = st->priv_data;
4986 891 FFStream *const sti = ffstream(st);
4987 int64_t current_offset;
4988 891 int64_t current_dts = 0;
4989 891 unsigned int stts_index = 0;
4990 891 unsigned int stsc_index = 0;
4991 891 unsigned int stss_index = 0;
4992 891 unsigned int stps_index = 0;
4993 unsigned int i, j;
4994 891 uint64_t stream_size = 0;
4995
4996 891 int ret = build_open_gop_key_points(st);
4997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 891 times.
891 if (ret < 0)
4998 ✗ return;
4999
5000
2/2
✓ Branch 0 taken 649 times.
✓ Branch 1 taken 242 times.
891 if (sc->elst_count) {
5001 649 int i, edit_start_index = 0, multiple_edits = 0;
5002 649 int64_t empty_duration = 0; // empty duration of the first edit list entry
5003 649 int64_t start_time = 0; // start time of the media
5004
5005
2/2
✓ Branch 0 taken 678 times.
✓ Branch 1 taken 649 times.
1327 for (i = 0; i < sc->elst_count; i++) {
5006 678 const MOVElst *e = &sc->elst_data[i];
5007
4/4
✓ Branch 0 taken 649 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 645 times.
678 if (i == 0 && e->time == -1) {
5008 /* if empty, the first entry is the start time of the stream
5009 * relative to the presentation itself */
5010 4 empty_duration = e->duration;
5011 4 edit_start_index = 1;
5012
3/4
✓ Branch 0 taken 649 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 649 times.
✗ Branch 3 not taken.
674 } else if (i == edit_start_index && e->time >= 0) {
5013 649 start_time = e->time;
5014 } else {
5015 25 multiple_edits = 1;
5016 }
5017 }
5018
5019
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 642 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
649 if (multiple_edits && !mov->advanced_editlist) {
5020 ✗ if (mov->advanced_editlist_autodisabled)
5021 ✗ av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
5022 "not supported in fragmented MP4 files\n");
5023 else
5024 ✗ av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
5025 "Use -advanced_editlist to correctly decode otherwise "
5026 "a/v desync might occur\n");
5027 }
5028
5029 /* adjust first dts according to edit list */
5030
5/6
✓ Branch 0 taken 645 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 119 times.
✓ Branch 3 taken 526 times.
✓ Branch 4 taken 123 times.
✗ Branch 5 not taken.
649 if ((empty_duration || start_time) && mov->time_scale > 0) {
5031
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 119 times.
123 if (empty_duration)
5032 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
5033
5034
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 123 times.
123 if (av_sat_sub64(start_time, empty_duration) != start_time - (uint64_t)empty_duration)
5035 ✗ av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
5036
5037 123 sc->time_offset = start_time - (uint64_t)empty_duration;
5038 123 sc->min_corrected_pts = start_time;
5039
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 122 times.
123 if (!mov->advanced_editlist)
5040 1 current_dts = -av_clip64(sc->time_offset, -INT64_MAX, INT64_MAX);
5041 }
5042
5043
4/4
✓ Branch 0 taken 642 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 103 times.
✓ Branch 3 taken 539 times.
649 if (!multiple_edits && !mov->advanced_editlist &&
5044
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 102 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
103 st->codecpar->codec_id == AV_CODEC_ID_AAC && start_time > 0)
5045 ✗ st->codecpar->initial_padding = av_rescale_q(start_time, st->time_base,
5046 ✗ (AVRational){1, st->codecpar->sample_rate});
5047 }
5048
5049 /* only use old uncompressed audio chunk demuxing when stts specifies it */
5050
2/2
✓ Branch 0 taken 397 times.
✓ Branch 1 taken 494 times.
891 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
5051
5/6
✓ Branch 0 taken 245 times.
✓ Branch 1 taken 152 times.
✓ Branch 2 taken 245 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 174 times.
✓ Branch 5 taken 71 times.
1083 sc->stts_count == 1 && sc->stts_data && sc->stts_data[0].duration == 1)) {
5052 820 unsigned int current_sample = 0;
5053 820 unsigned int stts_sample = 0;
5054 unsigned int sample_size;
5055 820 unsigned int distance = 0;
5056 820 unsigned int rap_group_index = 0;
5057 820 unsigned int rap_group_sample = 0;
5058
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 819 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
820 int rap_group_present = sc->rap_group_count && sc->rap_group;
5059
4/8
✓ Branch 0 taken 171 times.
✓ Branch 1 taken 649 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 171 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 649 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
820 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
5060
5061
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 820 times.
820 av_assert0(sc->dts_shift >= 0);
5062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 820 times.
820 if (current_dts < INT64_MIN + sc->dts_shift)
5063 ✗ return;
5064 820 current_dts -= sc->dts_shift;
5065
4/6
✓ Branch 0 taken 686 times.
✓ Branch 1 taken 134 times.
✓ Branch 2 taken 686 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 686 times.
820 if (!sc->sample_count || sti->nb_index_entries || sc->tts_count)
5066 134 return;
5067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 686 times.
686 if (sc->sample_count >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
5068 ✗ return;
5069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 686 times.
686 if (av_reallocp_array(&sti->index_entries,
5070 686 sti->nb_index_entries + sc->sample_count,
5071 sizeof(*sti->index_entries)) < 0) {
5072 ✗ sti->nb_index_entries = 0;
5073 ✗ return;
5074 }
5075 686 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
5076
5077 686 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
5078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 686 times.
686 if (ret < 0)
5079 ✗ return;
5080
5081
2/2
✓ Branch 0 taken 174782 times.
✓ Branch 1 taken 686 times.
175468 for (i = 0; i < sc->chunk_count; i++) {
5082
2/2
✓ Branch 0 taken 174096 times.
✓ Branch 1 taken 686 times.
174782 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
5083 174782 current_offset = sc->chunk_offsets[i];
5084
2/2
✓ Branch 1 taken 8723 times.
✓ Branch 2 taken 168615 times.
177338 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
5085
2/2
✓ Branch 0 taken 2556 times.
✓ Branch 1 taken 6167 times.
8723 i + 1 == sc->stsc_data[stsc_index + 1].first)
5086 2556 stsc_index++;
5087
5088
4/6
✓ Branch 0 taken 174782 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7432 times.
✓ Branch 3 taken 167350 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7432 times.
174782 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
5089 ✗ sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
5090 ✗ av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
5091 ✗ sc->stsz_sample_size = sc->sample_size;
5092 }
5093
3/4
✓ Branch 0 taken 7432 times.
✓ Branch 1 taken 167350 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7432 times.
174782 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
5094 ✗ av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
5095 ✗ sc->stsz_sample_size = sc->sample_size;
5096 }
5097
5098
2/2
✓ Branch 0 taken 250107 times.
✓ Branch 1 taken 174782 times.
424889 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
5099 250107 int keyframe = 0;
5100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 250107 times.
250107 if (current_sample >= sc->sample_count) {
5101 ✗ av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
5102 ✗ return;
5103 }
5104
5105
6/6
✓ Branch 0 taken 240396 times.
✓ Branch 1 taken 9711 times.
✓ Branch 2 taken 153411 times.
✓ Branch 3 taken 86985 times.
✓ Branch 4 taken 5772 times.
✓ Branch 5 taken 147639 times.
250107 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
5106 92757 keyframe = 1;
5107
2/2
✓ Branch 0 taken 5601 times.
✓ Branch 1 taken 87156 times.
92757 if (stss_index + 1 < sc->keyframe_count)
5108 5601 stss_index++;
5109
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 157350 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
157350 } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
5110 ✗ keyframe = 1;
5111 ✗ if (stps_index + 1 < sc->stps_count)
5112 ✗ stps_index++;
5113 }
5114
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 249919 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
250107 if (rap_group_present && rap_group_index < sc->rap_group_count) {
5115
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
5116 2 keyframe = 1;
5117
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
5118 4 rap_group_sample = 0;
5119 4 rap_group_index++;
5120 }
5121 }
5122
2/2
✓ Branch 0 taken 9711 times.
✓ Branch 1 taken 240396 times.
250107 if (sc->keyframe_absent
5123
1/2
✓ Branch 0 taken 9711 times.
✗ Branch 1 not taken.
9711 && !sc->stps_count
5124
1/2
✓ Branch 0 taken 9711 times.
✗ Branch 1 not taken.
9711 && !rap_group_present
5125
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)))
5126 8839 keyframe = 1;
5127
2/2
✓ Branch 0 taken 101596 times.
✓ Branch 1 taken 148511 times.
250107 if (keyframe)
5128 101596 distance = 0;
5129
2/2
✓ Branch 0 taken 9333 times.
✓ Branch 1 taken 240774 times.
250107 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
5130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 250107 times.
250107 if (current_offset > INT64_MAX - sample_size) {
5131 ✗ av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
5132 current_offset,
5133 sample_size);
5134 ✗ return;
5135 }
5136
5137
2/2
✓ Branch 0 taken 250010 times.
✓ Branch 1 taken 97 times.
250107 if (sc->pseudo_stream_id == -1 ||
5138
2/2
✓ Branch 0 taken 250008 times.
✓ Branch 1 taken 2 times.
250010 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
5139 AVIndexEntry *e;
5140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 250105 times.
250105 if (sample_size > 0x3FFFFFFF) {
5141 ✗ av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
5142 ✗ return;
5143 }
5144 250105 e = &sti->index_entries[sti->nb_index_entries++];
5145 250105 e->pos = current_offset;
5146 250105 e->timestamp = current_dts;
5147 250105 e->size = sample_size;
5148 250105 e->min_distance = distance;
5149 250105 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
5150 250105 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
5151 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
5152 current_offset, current_dts, sample_size, distance, keyframe);
5153
4/4
✓ Branch 0 taken 156342 times.
✓ Branch 1 taken 93763 times.
✓ Branch 2 taken 11709 times.
✓ Branch 3 taken 144633 times.
250105 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries < 100)
5154 11709 ff_rfps_add_frame(mov->fc, st, current_dts);
5155 }
5156
5157 250107 current_offset += sample_size;
5158 250107 stream_size += sample_size;
5159
5160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 250107 times.
250107 if (current_dts > INT64_MAX - sc->tts_data[stts_index].duration)
5161 ✗ return;
5162 250107 current_dts += sc->tts_data[stts_index].duration;
5163
5164 250107 distance++;
5165 250107 stts_sample++;
5166 250107 current_sample++;
5167
3/4
✓ Branch 0 taken 249421 times.
✓ Branch 1 taken 686 times.
✓ Branch 2 taken 249421 times.
✗ Branch 3 not taken.
250107 if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) {
5168 249421 stts_sample = 0;
5169 249421 stts_index++;
5170 }
5171 }
5172 }
5173
2/2
✓ Branch 0 taken 633 times.
✓ Branch 1 taken 53 times.
686 if (st->duration > 0)
5174 633 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
5175 } else {
5176 71 unsigned chunk_samples, total = 0;
5177
5178
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)
5179 ✗ return;
5180
5181 // compute total chunk count
5182
2/2
✓ Branch 0 taken 742 times.
✓ Branch 1 taken 71 times.
813 for (i = 0; i < sc->stsc_count; i++) {
5183 unsigned count, chunk_count;
5184
5185 742 chunk_samples = sc->stsc_data[i].count;
5186
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 71 times.
742 if (i != sc->stsc_count - 1 &&
5187
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) {
5188 ✗ av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
5189 ✗ return;
5190 }
5191
5192
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 667 times.
742 if (sc->samples_per_frame >= 160) { // gsm
5193 75 count = chunk_samples / sc->samples_per_frame;
5194
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 136 times.
667 } else if (sc->samples_per_frame > 1) {
5195 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
5196 531 count = (chunk_samples+samples-1) / samples;
5197 } else {
5198 136 count = (chunk_samples+1023) / 1024;
5199 }
5200
5201
2/2
✓ Branch 1 taken 671 times.
✓ Branch 2 taken 71 times.
742 if (mov_stsc_index_valid(i, sc->stsc_count))
5202 671 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
5203 else
5204 71 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
5205 742 total += chunk_count * count;
5206 }
5207
5208 71 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
5209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
5210 ✗ return;
5211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (av_reallocp_array(&sti->index_entries,
5212 71 sti->nb_index_entries + total,
5213 sizeof(*sti->index_entries)) < 0) {
5214 ✗ sti->nb_index_entries = 0;
5215 ✗ return;
5216 }
5217 71 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
5218
5219 // populate index
5220
2/2
✓ Branch 0 taken 5563 times.
✓ Branch 1 taken 71 times.
5634 for (i = 0; i < sc->chunk_count; i++) {
5221 5563 current_offset = sc->chunk_offsets[i];
5222
2/2
✓ Branch 1 taken 5399 times.
✓ Branch 2 taken 164 times.
5563 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
5223
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 4728 times.
5399 i + 1 == sc->stsc_data[stsc_index + 1].first)
5224 671 stsc_index++;
5225 5563 chunk_samples = sc->stsc_data[stsc_index].count;
5226
5227
2/2
✓ Branch 0 taken 165283 times.
✓ Branch 1 taken 5563 times.
170846 while (chunk_samples > 0) {
5228 AVIndexEntry *e;
5229 unsigned size, samples;
5230
5231
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) {
5232 ✗ avpriv_request_sample(mov->fc,
5233 "Zero bytes per frame, but %d samples per frame",
5234 sc->samples_per_frame);
5235 ✗ return;
5236 }
5237
5238
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 150925 times.
165283 if (sc->samples_per_frame >= 160) { // gsm
5239 14358 samples = sc->samples_per_frame;
5240 14358 size = sc->bytes_per_frame;
5241 } else {
5242
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 141362 times.
150925 if (sc->samples_per_frame > 1) {
5243 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
5244 sc->samples_per_frame, chunk_samples);
5245 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
5246 } else {
5247 141362 samples = FFMIN(1024, chunk_samples);
5248 141362 size = samples * sc->sample_size;
5249 }
5250 }
5251
5252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165283 times.
165283 if (sti->nb_index_entries >= total) {
5253 ✗ av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
5254 ✗ return;
5255 }
5256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165283 times.
165283 if (size > 0x3FFFFFFF) {
5257 ✗ av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
5258 ✗ return;
5259 }
5260 165283 e = &sti->index_entries[sti->nb_index_entries++];
5261 165283 e->pos = current_offset;
5262 165283 e->timestamp = current_dts;
5263 165283 e->size = size;
5264 165283 e->min_distance = 0;
5265 165283 e->flags = AVINDEX_KEYFRAME;
5266 165283 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
5267 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
5268 size, samples);
5269
5270 165283 current_offset += size;
5271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165283 times.
165283 if (current_dts > INT64_MAX - samples)
5272 ✗ return;
5273 165283 current_dts += samples;
5274 165283 chunk_samples -= samples;
5275 }
5276 }
5277
5278 71 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
5279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (ret < 0)
5280 ✗ return;
5281 }
5282
5283
2/4
✓ Branch 0 taken 757 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 757 times.
✗ Branch 3 not taken.
757 if (!mov->ignore_editlist && mov->advanced_editlist) {
5284 // Fix index according to edit lists.
5285 757 mov_fix_index(mov, st);
5286 }
5287
5288 // Update start time of the stream.
5289
5/6
✓ Branch 0 taken 211 times.
✓ Branch 1 taken 546 times.
✓ Branch 2 taken 81 times.
✓ Branch 3 taken 130 times.
✓ Branch 4 taken 81 times.
✗ Branch 5 not taken.
757 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) {
5290 81 st->start_time = av_sat_add64(sti->index_entries[0].timestamp, sc->dts_shift);
5291
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 if (sc->tts_data) {
5292 81 st->start_time = av_sat_add64(st->start_time, sc->tts_data[0].offset);
5293 }
5294 }
5295
5296 757 mov_estimate_video_delay(mov, st);
5297 }
5298
5299 typedef struct MOVPresentationSample {
5300 int index;
5301 int64_t pts;
5302 } MOVPresentationSample;
5303
5304 12202 static int mov_compare_presentation_samples(const void *a, const void *b)
5305 {
5306 12202 const MOVPresentationSample *sa = a;
5307 12202 const MOVPresentationSample *sb = b;
5308
5309
2/2
✓ Branch 0 taken 12198 times.
✓ Branch 1 taken 4 times.
12202 if (sa->pts != sb->pts)
5310 12198 return (sa->pts > sb->pts) - (sa->pts < sb->pts);
5311 4 return (sa->index > sb->index) - (sa->index < sb->index);
5312 }
5313
5314 /*
5315 * Set sample durations from adjacent presentation timestamps.
5316 */
5317 838 static void mov_update_sample_durations(MOVContext *mov, AVStream *st)
5318 {
5319 838 MOVStreamContext *sc = st->priv_data;
5320 838 FFStream *const sti = ffstream(st);
5321 838 MOVPresentationSample *samples = NULL;
5322 838 MOVTimeToSample *tts_data = NULL;
5323 838 unsigned int tts_index = 0, tts_sample = 0;
5324 838 int count = sti->nb_index_entries;
5325
5326 /* A single STTS entry describes a fixed sample delta. */
5327
2/2
✓ Branch 0 taken 375 times.
✓ Branch 1 taken 463 times.
838 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
5328
4/4
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 299 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 64 times.
375 !sc->ctts_count || sc->stts_count < 2 ||
5329
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 ||
5330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 count >= UINT_MAX / sizeof(*tts_data))
5331 826 return;
5332
5333 12 samples = av_malloc_array(count, sizeof(*samples));
5334 12 tts_data = av_malloc_array(count, sizeof(*tts_data));
5335
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)
5336 ✗ goto fail;
5337
5338
2/2
✓ Branch 0 taken 2654 times.
✓ Branch 1 taken 12 times.
2666 for (int i = 0; i < count; i++) {
5339 int64_t dts, offset;
5340
5341
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)
5342 ✗ goto fail;
5343
5344 2654 tts_data[i] = sc->tts_data[tts_index];
5345 2654 tts_data[i].count = 1;
5346
5347 2654 dts = sti->index_entries[i].timestamp;
5348 2654 offset = (int64_t)sc->dts_shift + tts_data[i].offset;
5349
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 ||
5350
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) ||
5351 ✗ (offset < 0 && dts < INT64_MIN - offset))
5352 ✗ goto fail;
5353
5354 2654 samples[i].index = i;
5355 2654 samples[i].pts = dts + offset;
5356
5357
1/2
✓ Branch 0 taken 2654 times.
✗ Branch 1 not taken.
2654 if (++tts_sample == sc->tts_data[tts_index].count) {
5358 2654 tts_index++;
5359 2654 tts_sample = 0;
5360 }
5361 }
5362
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)
5363 ✗ goto fail;
5364
5365 12 qsort(samples, count, sizeof(*samples), mov_compare_presentation_samples);
5366
5367
2/2
✓ Branch 0 taken 2624 times.
✓ Branch 1 taken 10 times.
2634 for (int i = 0; i + 1 < count; i++) {
5368 uint64_t duration;
5369
5370
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2622 times.
2624 if (samples[i].pts >= samples[i + 1].pts)
5371 2 goto fail;
5372
5373 /*
5374 * In VFR streams with reordered frames, STTS deltas follow decode
5375 * order while AVPacket.duration follows presentation order. CTTS
5376 * may produce presentation intervals that cannot be obtained by
5377 * merely permuting the STTS deltas, so derive each known duration
5378 * from adjacent PTS.
5379 */
5380 2622 duration = (uint64_t)samples[i + 1].pts - samples[i].pts;
5381
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)
5382 ✗ goto fail;
5383
5384 2622 tts_data[samples[i].index].duration = (unsigned int)duration;
5385 }
5386
5387 10 av_log(mov->fc, AV_LOG_DEBUG,
5388 "Updated sample durations in presentation order for stream %d\n",
5389 st->index);
5390
5391 10 av_freep(&sc->tts_data);
5392 10 sc->tts_data = tts_data;
5393 10 sc->tts_count = count;
5394 10 sc->tts_allocated_size = count * sizeof(*tts_data);
5395 10 tts_data = NULL;
5396
5397 12 fail:
5398 12 av_free(samples);
5399 12 av_free(tts_data);
5400 }
5401
5402 ✗ static int test_same_origin(const char *src, const char *ref) {
5403 char src_proto[64];
5404 char ref_proto[64];
5405 char src_auth[256];
5406 char ref_auth[256];
5407 char src_host[256];
5408 char ref_host[256];
5409 ✗ int src_port=-1;
5410 ✗ int ref_port=-1;
5411
5412 ✗ av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
5413 ✗ av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
5414
5415 ✗ if (strlen(src) == 0) {
5416 ✗ return -1;
5417 ✗ } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
5418 ✗ strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
5419 ✗ strlen(src_host) + 1 >= sizeof(src_host) ||
5420 ✗ strlen(ref_host) + 1 >= sizeof(ref_host)) {
5421 ✗ return 0;
5422 ✗ } else if (strcmp(src_proto, ref_proto) ||
5423 ✗ strcmp(src_auth, ref_auth) ||
5424 ✗ strcmp(src_host, ref_host) ||
5425 ✗ src_port != ref_port) {
5426 ✗ return 0;
5427 } else
5428 ✗ return 1;
5429 }
5430
5431 ✗ static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
5432 {
5433 /* try relative path, we do not try the absolute because it can leak information about our
5434 system to an attacker */
5435 ✗ if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
5436 char filename[1025];
5437 const char *src_path;
5438 int i, l;
5439
5440 /* find a source dir */
5441 ✗ src_path = strrchr(src, '/');
5442 ✗ if (src_path)
5443 ✗ src_path++;
5444 else
5445 ✗ src_path = src;
5446
5447 /* find a next level down to target */
5448 ✗ for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
5449 ✗ if (ref->path[l] == '/') {
5450 ✗ if (i == ref->nlvl_to - 1)
5451 ✗ break;
5452 else
5453 ✗ i++;
5454 }
5455
5456 /* compose filename if next level down to target was found */
5457 ✗ if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
5458 ✗ memcpy(filename, src, src_path - src);
5459 ✗ filename[src_path - src] = 0;
5460
5461 ✗ for (i = 1; i < ref->nlvl_from; i++)
5462 ✗ av_strlcat(filename, "../", sizeof(filename));
5463
5464 ✗ av_strlcat(filename, ref->path + l + 1, sizeof(filename));
5465 ✗ if (!c->use_absolute_path) {
5466 ✗ int same_origin = test_same_origin(src, filename);
5467
5468 ✗ if (!same_origin) {
5469 ✗ av_log(c->fc, AV_LOG_ERROR,
5470 "Reference with mismatching origin, %s not tried for security reasons, "
5471 "set demuxer option use_absolute_path to allow it anyway\n",
5472 ref->path);
5473 ✗ return AVERROR(ENOENT);
5474 }
5475
5476 ✗ if (strstr(ref->path + l + 1, "..") ||
5477 ✗ strstr(ref->path + l + 1, ":") ||
5478 ✗ (ref->nlvl_from > 1 && same_origin < 0) ||
5479 ✗ (filename[0] == '/' && src_path == src))
5480 ✗ return AVERROR(ENOENT);
5481 }
5482
5483 ✗ if (strlen(filename) + 1 == sizeof(filename))
5484 ✗ return AVERROR(ENOENT);
5485 ✗ if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5486 ✗ return 0;
5487 }
5488 ✗ } else if (c->use_absolute_path) {
5489 ✗ av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5490 "this is a possible security issue\n");
5491 ✗ if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5492 ✗ return 0;
5493 } else {
5494 ✗ av_log(c->fc, AV_LOG_ERROR,
5495 "Absolute path %s not tried for security reasons, "
5496 "set demuxer option use_absolute_path to allow absolute paths\n",
5497 ref->path);
5498 }
5499
5500 ✗ return AVERROR(ENOENT);
5501 }
5502
5503 1797 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5504 {
5505
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1781 times.
1797 if (sc->time_scale <= 0) {
5506 16 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5507 16 sc->time_scale = c->time_scale;
5508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (sc->time_scale <= 0)
5509 ✗ sc->time_scale = 1;
5510 }
5511 1797 }
5512
5513 #if CONFIG_IAMFDEC
5514 12 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5515 {
5516 12 const MOVStreamContext *sc = st->priv_data;
5517 12 const IAMFContext *iamf = &sc->iamf->iamf;
5518
5519
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5520 12 const AVStreamGroup *stg = NULL;
5521
5522
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5523
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)
5524 12 stg = c->fc->stream_groups[j];
5525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 av_assert0(stg);
5526
5527
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_entries; j++) {
5528 64 const FFStream *sti = cffstream(st);
5529 64 AVStream *out = stg->entries[j]->stream;
5530 64 FFStream *out_sti = ffstream(stg->entries[j]->stream);
5531
5532 64 out->codecpar->bit_rate = 0;
5533
5534
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 52 times.
64 if (out == st)
5535 12 continue;
5536
5537 52 out->time_base = st->time_base;
5538 52 out->start_time = st->start_time;
5539 52 out->duration = st->duration;
5540 52 out->nb_frames = st->nb_frames;
5541 52 out->discard = st->discard;
5542
5543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 av_assert0(!out_sti->index_entries);
5544 52 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5545
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (!out_sti->index_entries)
5546 ✗ return AVERROR(ENOMEM);
5547
5548 52 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5549 52 out_sti->nb_index_entries = sti->nb_index_entries;
5550 52 out_sti->skip_samples = sti->skip_samples;
5551 52 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5552 }
5553 }
5554
5555 12 return 0;
5556 }
5557 #endif
5558
5559 891 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5560 {
5561
4/6
✓ Branch 0 taken 757 times.
✓ Branch 1 taken 134 times.
✓ Branch 2 taken 757 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 757 times.
✗ Branch 5 not taken.
891 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5562
3/4
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 287 times.
✓ Branch 2 taken 470 times.
✗ Branch 3 not taken.
757 (!sc->sample_size && !sc->sample_count))) ||
5563
3/4
✓ Branch 0 taken 757 times.
✓ Branch 1 taken 134 times.
✓ Branch 2 taken 757 times.
✗ Branch 3 not taken.
891 (sc->sample_count && (!sc->chunk_count ||
5564
3/4
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 287 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 470 times.
757 (!sc->sample_size && !sc->sample_sizes)))) {
5565 ✗ av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5566 index);
5567 ✗ return 1;
5568 }
5569
5570
3/4
✓ Branch 0 taken 757 times.
✓ Branch 1 taken 134 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 757 times.
891 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
5571 ✗ av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5572 index);
5573 ✗ return 2;
5574 }
5575 891 return 0;
5576 }
5577
5578 838 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5579 {
5580 AVStream *st;
5581 MOVStreamContext *sc;
5582 int ret;
5583
5584 838 st = avformat_new_stream(c->fc, NULL);
5585
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (!st) return AVERROR(ENOMEM);
5586 838 st->id = -1;
5587 838 sc = av_mallocz(sizeof(MOVStreamContext));
5588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (!sc) return AVERROR(ENOMEM);
5589
5590 838 st->priv_data = sc;
5591 838 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5592 838 sc->ffindex = st->index;
5593 838 c->trak_index = st->index;
5594 838 sc->refcount = 1;
5595
5596
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 838 times.
838 if ((ret = mov_read_default(c, pb, atom)) < 0)
5597 ✗ return ret;
5598
5599 838 c->trak_index = -1;
5600
5601 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5602 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5603
5/6
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 704 times.
✓ Branch 2 taken 134 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 133 times.
838 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
5604 1 sc->stsc_count = 0;
5605 1 av_freep(&sc->stsc_data);
5606 }
5607
5608 838 ret = sanity_checks(c->fc, sc, st->index);
5609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (ret)
5610 ✗ return ret > 1 ? AVERROR_INVALIDDATA : 0;
5611
5612 838 fix_timescale(c, sc);
5613
5614 838 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5615
5616 /*
5617 * Advanced edit list support does not work with fragemented MP4s, which
5618 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5619 * In these files, trun atoms may be streamed in.
5620 */
5621
4/4
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 704 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 108 times.
838 if (!sc->stts_count && c->advanced_editlist) {
5622
5623 26 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5624 "MP4. disabling.\n");
5625 26 c->advanced_editlist = 0;
5626 26 c->advanced_editlist_autodisabled = 1;
5627 }
5628
5629 838 mov_build_index(c, st);
5630 /*
5631 * Fragment samples are appended later by mov_read_trun() and are not
5632 * covered by this non-fragmented track update.
5633 */
5634 838 mov_update_sample_durations(c, st);
5635
5636 #if CONFIG_IAMFDEC
5637
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 826 times.
838 if (sc->iamf) {
5638 12 ret = mov_update_iamf_streams(c, st);
5639
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
5640 ✗ return ret;
5641 }
5642 #endif
5643
5644
3/4
✓ Branch 0 taken 837 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 837 times.
838 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
5645 ✗ MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5646 ✗ if (c->enable_drefs) {
5647 ✗ if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5648 ✗ av_log(c->fc, AV_LOG_ERROR,
5649 "stream %d, error opening alias: path='%s', dir='%s', "
5650 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5651 ✗ st->index, dref->path, dref->dir, dref->filename,
5652 ✗ dref->volume, dref->nlvl_from, dref->nlvl_to);
5653 } else {
5654 ✗ av_log(c->fc, AV_LOG_WARNING,
5655 "Skipped opening external track: "
5656 "stream %d, alias: path='%s', dir='%s', "
5657 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5658 "Set enable_drefs to allow this.\n",
5659 ✗ st->index, dref->path, dref->dir, dref->filename,
5660 ✗ dref->volume, dref->nlvl_from, dref->nlvl_to);
5661 }
5662 } else {
5663 838 sc->pb = c->fc->pb;
5664 838 sc->pb_is_copied = 1;
5665 }
5666
5667
2/2
✓ Branch 0 taken 375 times.
✓ Branch 1 taken 463 times.
838 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5668
3/4
✓ Branch 0 taken 356 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 356 times.
✗ Branch 3 not taken.
375 int stts_constant = sc->stts_count && sc->tts_count;
5669
3/4
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 280 times.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
375 if (sc->h_spacing && sc->v_spacing)
5670 95 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5671 95 sc->h_spacing, sc->v_spacing, INT_MAX);
5672
4/6
✓ Branch 0 taken 277 times.
✓ Branch 1 taken 98 times.
✓ Branch 2 taken 277 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 277 times.
✗ Branch 5 not taken.
375 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
5673
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 &&
5674
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)) {
5675 ✗ av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5676 ✗ (int64_t)st->codecpar->height * sc->width,
5677 ✗ (int64_t)st->codecpar->width * sc->height, INT_MAX);
5678 }
5679
5680 #if FF_API_R_FRAME_RATE
5681
4/4
✓ Branch 0 taken 156120 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 155764 times.
✓ Branch 3 taken 356 times.
156139 for (unsigned int i = 1; sc->stts_count && i + 1 < sc->tts_count; i++) {
5682
2/2
✓ Branch 0 taken 153269 times.
✓ Branch 1 taken 2495 times.
155764 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5683 153269 continue;
5684 2495 stts_constant = 0;
5685 }
5686
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 38 times.
375 if (stts_constant)
5687 337 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5688 337 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5689 #endif
5690 }
5691
5692 #if CONFIG_H261_DECODER || CONFIG_H263_DECODER || CONFIG_MPEG4_DECODER
5693
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 807 times.
838 switch (st->codecpar->codec_id) {
5694 #if CONFIG_H261_DECODER
5695 31 case AV_CODEC_ID_H261:
5696 #endif
5697 #if CONFIG_H263_DECODER
5698 case AV_CODEC_ID_H263:
5699 #endif
5700 #if CONFIG_MPEG4_DECODER
5701 case AV_CODEC_ID_MPEG4:
5702 #endif
5703 31 st->codecpar->width = 0; /* let decoder init width/height */
5704 31 st->codecpar->height= 0;
5705 31 break;
5706 }
5707 #endif
5708
5709 // If the duration of the mp3 packets is not constant, then they could need a parser
5710
2/2
✓ Branch 0 taken 103 times.
✓ Branch 1 taken 735 times.
838 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5711
1/2
✓ Branch 0 taken 103 times.
✗ Branch 1 not taken.
103 && sc->time_scale == st->codecpar->sample_rate) {
5712 103 int stts_constant = 1;
5713
4/4
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 100 times.
✓ Branch 2 taken 365 times.
✓ Branch 3 taken 3 times.
468 for (int i = 1; sc->stts_count && i < sc->tts_count; i++) {
5714
1/2
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
365 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5715 365 continue;
5716 ✗ stts_constant = 0;
5717 }
5718
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103 times.
103 if (!stts_constant)
5719 ✗ ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5720 }
5721 /* Do not need those anymore. */
5722 838 av_freep(&sc->chunk_offsets);
5723 838 av_freep(&sc->sample_sizes);
5724 838 av_freep(&sc->keyframes);
5725 838 av_freep(&sc->stps_data);
5726 838 av_freep(&sc->elst_data);
5727 838 av_freep(&sc->rap_group);
5728 838 av_freep(&sc->sync_group);
5729 838 av_freep(&sc->sgpd_sync);
5730
5731 838 return 0;
5732 }
5733
5734 201 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5735 {
5736 int ret;
5737 201 c->itunes_metadata = 1;
5738 201 ret = mov_read_default(c, pb, atom);
5739 201 c->itunes_metadata = 0;
5740 201 return ret;
5741 }
5742
5743 14 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5744 {
5745 uint32_t count;
5746 uint32_t i;
5747
5748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (atom.size < 8)
5749 ✗ return 0;
5750
5751 14 avio_skip(pb, 4);
5752 14 count = avio_rb32(pb);
5753 14 atom.size -= 8;
5754
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)) {
5755 ✗ av_log(c->fc, AV_LOG_ERROR,
5756 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5757 ✗ return AVERROR_INVALIDDATA;
5758 }
5759
5760 14 c->meta_keys = av_malloc_array(count + 1, sizeof(*c->meta_keys));
5761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!c->meta_keys)
5762 ✗ return AVERROR(ENOMEM);
5763
5764 14 c->meta_keys[0] = NULL;
5765 14 c->meta_keys_count = 1;
5766
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 14 times.
114 for (i = 1; i <= count; ++i) {
5767 100 uint32_t key_size = avio_rb32(pb);
5768 100 uint32_t type = avio_rl32(pb);
5769 100 c->meta_keys[i] = NULL;
5770 100 c->meta_keys_count = i + 1;
5771
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) {
5772 ✗ av_log(c->fc, AV_LOG_ERROR,
5773 "The key# %"PRIu32" in meta has invalid size:"
5774 "%"PRIu32"\n", i, key_size);
5775 ✗ return AVERROR_INVALIDDATA;
5776 }
5777 100 atom.size -= key_size;
5778 100 key_size -= 8;
5779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (type != MKTAG('m','d','t','a')) {
5780 ✗ avio_skip(pb, key_size);
5781 ✗ continue;
5782 }
5783 100 c->meta_keys[i] = av_malloc(key_size + 1);
5784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (!c->meta_keys[i])
5785 ✗ return AVERROR(ENOMEM);
5786 100 int ret = ffio_read_size(pb, c->meta_keys[i], key_size);
5787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (ret < 0)
5788 ✗ return ret;
5789 100 c->meta_keys[i][key_size] = 0;
5790 }
5791
5792 14 return 0;
5793 }
5794
5795 80 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5796 {
5797 80 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5798 80 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5799 int i;
5800 80 int ret = 0;
5801 AVStream *st;
5802
5803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (c->fc->nb_streams < 1)
5804 ✗ return 0;
5805 80 st = c->fc->streams[c->fc->nb_streams-1];
5806
5807
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 80 times.
320 for (i = 0; i < 3; i++) {
5808 uint8_t **p;
5809 uint32_t len, tag;
5810
5811
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 240 times.
240 if (end - avio_tell(pb) <= 12)
5812 ✗ break;
5813
5814 240 len = avio_rb32(pb);
5815 240 tag = avio_rl32(pb);
5816 240 avio_skip(pb, 4); // flags
5817
5818
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))
5819 break;
5820 240 len -= 12;
5821
5822
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 160 times.
240 if (tag == MKTAG('m', 'e', 'a', 'n'))
5823 80 p = &mean;
5824
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 80 times.
160 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5825 80 p = &key;
5826
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) {
5827 80 avio_skip(pb, 4);
5828 80 len -= 4;
5829 80 p = &val;
5830 } else
5831 break;
5832
5833
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (*p)
5834 ✗ break;
5835
5836 240 *p = av_malloc(len + 1);
5837
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (!*p) {
5838 ✗ ret = AVERROR(ENOMEM);
5839 ✗ break;
5840 }
5841 240 ret = ffio_read_size(pb, *p, len);
5842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (ret < 0) {
5843 ✗ av_freep(p);
5844 ✗ break;
5845 }
5846 240 (*p)[len] = 0;
5847 }
5848
5849
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) {
5850
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 38 times.
80 if (strcmp(key, "iTunSMPB") == 0) {
5851 int64_t priming, remainder, samples;
5852
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 if (ff_itunes_parse_smpb(val, &priming, &remainder, &samples) >= 0) {
5853
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)
5854 42 st->codecpar->initial_padding = priming = av_rescale_q(priming, st->time_base,
5855 42 (AVRational){ 1, st->codecpar->sample_rate });
5856
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 if (remainder > 0) {
5857 42 int64_t duration = av_rescale_q(st->duration, st->time_base,
5858 42 (AVRational){ 1, st->codecpar->sample_rate });
5859 42 remainder = av_rescale_q(remainder, st->time_base,
5860 42 (AVRational){ 1, st->codecpar->sample_rate });
5861 42 samples = av_rescale_q(samples, st->time_base,
5862 42 (AVRational){ 1, st->codecpar->sample_rate });
5863
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) {
5864 42 ffstream(st)->first_discard_sample = duration - remainder;
5865 42 ffstream(st)->last_discard_sample = duration;
5866 }
5867 }
5868 42 av_log(c->fc, AV_LOG_DEBUG, "Parsed iTunSMPB: priming %"PRId64", "
5869 "remainder %"PRId64" samples %"PRId64"\n",
5870 priming, remainder, samples);
5871 }
5872 }
5873
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 if (strcmp(mean, "com.apple.iTunes") == 0 &&
5874
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 78 times.
80 strcmp(key, "DISCSUBTITLE") == 0) {
5875 2 av_dict_set(&c->fc->metadata, "disc_subtitle", val,
5876 AV_DICT_DONT_STRDUP_VAL);
5877 2 val = NULL;
5878 }
5879
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 10 times.
150 if (strcmp(key, "cdec") != 0) {
5880 70 av_dict_set(&c->fc->metadata, key, val,
5881 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5882 70 key = val = NULL;
5883 }
5884 } else {
5885 ✗ av_log(c->fc, AV_LOG_VERBOSE,
5886 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5887 }
5888
5889 80 avio_seek(pb, end, SEEK_SET);
5890 80 av_freep(&key);
5891 80 av_freep(&val);
5892 80 av_freep(&mean);
5893 80 return ret;
5894 }
5895
5896 53 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5897 {
5898 MOVStreamContext *sc;
5899 AVStream *st;
5900
5901 53 st = avformat_new_stream(c->fc, NULL);
5902
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (!st)
5903 ✗ return AVERROR(ENOMEM);
5904 53 sc = av_mallocz(sizeof(MOVStreamContext));
5905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (!sc)
5906 ✗ goto fail;
5907
5908 53 item->st = st;
5909 53 st->id = item->item_id;
5910 53 st->priv_data = sc;
5911 53 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5912 53 st->codecpar->codec_id = mov_codec_id(st, item->type);
5913 53 sc->id = st->id;
5914 53 sc->ffindex = st->index;
5915 53 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5916 53 st->time_base.num = st->time_base.den = 1;
5917 53 st->nb_frames = 1;
5918 53 sc->time_scale = 1;
5919 53 sc->pb = c->fc->pb;
5920 53 sc->pb_is_copied = 1;
5921 53 sc->refcount = 1;
5922
5923
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 10 times.
53 if (item->name)
5924 43 av_dict_set(&st->metadata, "title", item->name, 0);
5925
5926 // Populate the necessary fields used by mov_build_index.
5927 53 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5928
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (!sc->stsc_data)
5929 ✗ goto fail;
5930 53 sc->stsc_count = 1;
5931 53 sc->stsc_data[0].first = 1;
5932 53 sc->stsc_data[0].count = 1;
5933 53 sc->stsc_data[0].id = 1;
5934 53 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (!sc->chunk_offsets)
5936 ✗ goto fail;
5937 53 sc->chunk_count = 1;
5938 53 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (!sc->stts_data)
5940 ✗ goto fail;
5941 53 sc->stts_count = 1;
5942 53 sc->stts_data[0].count = 1;
5943 // Not used for still images. But needed by mov_build_index.
5944 53 sc->stts_data[0].duration = 0;
5945
5946 53 return 0;
5947 ✗ fail:
5948 ✗ mov_free_stream_context(c->fc, st);
5949 ✗ ff_remove_stream(c->fc, st);
5950 ✗ item->st = NULL;
5951
5952 ✗ return AVERROR(ENOMEM);
5953 }
5954
5955 228 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5956 {
5957
1/2
✓ Branch 0 taken 664 times.
✗ Branch 1 not taken.
664 while (atom.size > 8) {
5958 uint32_t tag;
5959
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 664 times.
664 if (avio_feof(pb))
5960 ✗ return AVERROR_EOF;
5961 664 tag = avio_rl32(pb);
5962 664 atom.size -= 4;
5963
2/2
✓ Branch 0 taken 228 times.
✓ Branch 1 taken 436 times.
664 if (tag == MKTAG('h','d','l','r')) {
5964 228 avio_seek(pb, -8, SEEK_CUR);
5965 228 atom.size += 8;
5966 228 return mov_read_default(c, pb, atom);
5967 }
5968 }
5969 ✗ return 0;
5970 }
5971
5972 // return 1 when matrix is identity, 0 otherwise
5973 #define IS_MATRIX_IDENT(matrix) \
5974 ( (matrix)[0][0] == (1 << 16) && \
5975 (matrix)[1][1] == (1 << 16) && \
5976 (matrix)[2][2] == (1 << 30) && \
5977 !(matrix)[0][1] && !(matrix)[0][2] && \
5978 !(matrix)[1][0] && !(matrix)[1][2] && \
5979 !(matrix)[2][0] && !(matrix)[2][1])
5980
5981 838 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5982 {
5983 int i, j, e;
5984 int width;
5985 int height;
5986 int display_matrix[3][3];
5987 838 int res_display_matrix[3][3] = { { 0 } };
5988 AVStream *st;
5989 MOVStreamContext *sc;
5990 int version;
5991 int flags;
5992
5993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (c->fc->nb_streams < 1)
5994 ✗ return 0;
5995 838 st = c->fc->streams[c->fc->nb_streams-1];
5996 838 sc = st->priv_data;
5997
5998 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5999 // avoids corrupting AVStreams mapped to an earlier tkhd.
6000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 838 times.
838 if (st->id != -1)
6001 ✗ return AVERROR_INVALIDDATA;
6002
6003 838 version = avio_r8(pb);
6004 838 flags = avio_rb24(pb);
6005 838 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
6006
6007
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 825 times.
838 if (version == 1) {
6008 13 avio_rb64(pb);
6009 13 avio_rb64(pb);
6010 } else {
6011 825 avio_rb32(pb); /* creation time */
6012 825 avio_rb32(pb); /* modification time */
6013 }
6014 838 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
6015 838 sc->id = st->id;
6016 838 avio_rb32(pb); /* reserved */
6017
6018 /* highlevel (considering edits) duration in movie timebase */
6019
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 825 times.
838 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
6020 838 avio_rb32(pb); /* reserved */
6021 838 avio_rb32(pb); /* reserved */
6022
6023 838 avio_rb16(pb); /* layer */
6024 838 avio_rb16(pb); /* alternate group */
6025 838 avio_rb16(pb); /* volume */
6026 838 avio_rb16(pb); /* reserved */
6027
6028 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
6029 // they're kept in fixed point format through all calculations
6030 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
6031 // side data, but the scale factor is not needed to calculate aspect ratio
6032
2/2
✓ Branch 0 taken 2514 times.
✓ Branch 1 taken 838 times.
3352 for (i = 0; i < 3; i++) {
6033 2514 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
6034 2514 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
6035 2514 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
6036 }
6037
6038 838 width = avio_rb32(pb); // 16.16 fixed point track width
6039 838 height = avio_rb32(pb); // 16.16 fixed point track height
6040 838 sc->width = width >> 16;
6041 838 sc->height = height >> 16;
6042
6043 // apply the moov display matrix (after the tkhd one)
6044
2/2
✓ Branch 0 taken 2514 times.
✓ Branch 1 taken 838 times.
3352 for (i = 0; i < 3; i++) {
6045 2514 const int sh[3] = { 16, 16, 30 };
6046
2/2
✓ Branch 0 taken 7542 times.
✓ Branch 1 taken 2514 times.
10056 for (j = 0; j < 3; j++) {
6047
2/2
✓ Branch 0 taken 22626 times.
✓ Branch 1 taken 7542 times.
30168 for (e = 0; e < 3; e++) {
6048 22626 res_display_matrix[i][j] +=
6049 22626 ((int64_t) display_matrix[i][e] *
6050 22626 c->movie_display_matrix[e][j]) >> sh[e];
6051 }
6052 }
6053 }
6054
6055 // save the matrix when it is not the default identity
6056
10/18
✓ Branch 0 taken 829 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 829 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 829 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 829 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 829 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 829 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 829 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 829 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 829 times.
838 if (!IS_MATRIX_IDENT(res_display_matrix)) {
6057 9 av_freep(&sc->display_matrix);
6058 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
6059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
6060 ✗ return AVERROR(ENOMEM);
6061
6062
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
6063
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
6064 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
6065 }
6066
6067 // transform the display width/height according to the matrix
6068 // to keep the same scale, use [width height 1<<16]
6069
5/6
✓ Branch 0 taken 394 times.
✓ Branch 1 taken 444 times.
✓ Branch 2 taken 394 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 386 times.
838 if (width && height && sc->display_matrix) {
6070 double disp_transform[2];
6071
6072
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
6073 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
6074 16 sc->display_matrix[3 + i]);
6075
6076
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 &&
6077
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) &&
6078
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
6079 3 st->sample_aspect_ratio = av_d2q(
6080 3 disp_transform[0] / disp_transform[1],
6081 INT_MAX);
6082 }
6083 838 return 0;
6084 }
6085
6086 706 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6087 {
6088 706 MOVFragment *frag = &c->fragment;
6089 706 MOVTrackExt *trex = NULL;
6090 int flags, track_id, i;
6091 MOVFragmentStreamInfo * frag_stream_info;
6092
6093 706 avio_r8(pb); /* version */
6094 706 flags = avio_rb24(pb);
6095
6096 706 track_id = avio_rb32(pb);
6097
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (!track_id)
6098 ✗ return AVERROR_INVALIDDATA;
6099
1/2
✓ Branch 0 taken 10665 times.
✗ Branch 1 not taken.
10665 for (i = 0; i < c->trex_count; i++)
6100
2/2
✓ Branch 0 taken 706 times.
✓ Branch 1 taken 9959 times.
10665 if (c->trex_data[i].track_id == track_id) {
6101 706 trex = &c->trex_data[i];
6102 706 break;
6103 }
6104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (!trex) {
6105 ✗ av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
6106 ✗ return 0;
6107 }
6108 706 c->fragment.found_tfhd = 1;
6109 706 frag->track_id = track_id;
6110 706 set_frag_stream(&c->frag_index, track_id);
6111
6112 1412 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
6113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
1412 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
6114
2/2
✓ Branch 0 taken 633 times.
✓ Branch 1 taken 73 times.
706 frag->moof_offset : frag->implicit_offset;
6115
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 642 times.
706 frag->stsd_id = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id;
6116
6117 1412 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
6118
2/2
✓ Branch 0 taken 271 times.
✓ Branch 1 taken 435 times.
706 avio_rb32(pb) : trex->duration;
6119 1412 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
6120
2/2
✓ Branch 0 taken 263 times.
✓ Branch 1 taken 443 times.
706 avio_rb32(pb) : trex->size;
6121 1412 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
6122
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 369 times.
706 avio_rb32(pb) : trex->flags;
6123 706 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
6124
6125 706 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6126
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (frag_stream_info) {
6127 706 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
6128 706 frag_stream_info->stsd_id = frag->stsd_id;
6129 }
6130 706 return 0;
6131 }
6132
6133 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6134 {
6135 unsigned i, num;
6136 void *new_tracks;
6137
6138 2 num = atom.size / 4;
6139
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
6140 ✗ return AVERROR(ENOMEM);
6141
6142 2 av_free(c->chapter_tracks);
6143 2 c->chapter_tracks = new_tracks;
6144 2 c->nb_chapter_tracks = num;
6145
6146
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++)
6147 2 c->chapter_tracks[i] = avio_rb32(pb);
6148
6149 2 c->nb_chapter_tracks = i;
6150
6151 2 return 0;
6152 }
6153
6154 133 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6155 {
6156 MOVTrackExt *trex;
6157 int err;
6158
6159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
133 if ((uint64_t)c->trex_count+1 >= UINT_MAX / sizeof(*c->trex_data))
6160 ✗ return AVERROR_INVALIDDATA;
6161
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 133 times.
133 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
6162 sizeof(*c->trex_data))) < 0) {
6163 ✗ c->trex_count = 0;
6164 ✗ return err;
6165 }
6166
6167 133 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
6168
6169 133 trex = &c->trex_data[c->trex_count++];
6170 133 avio_r8(pb); /* version */
6171 133 avio_rb24(pb); /* flags */
6172 133 trex->track_id = avio_rb32(pb);
6173 133 trex->stsd_id = avio_rb32(pb);
6174 133 trex->duration = avio_rb32(pb);
6175 133 trex->size = avio_rb32(pb);
6176 133 trex->flags = avio_rb32(pb);
6177 133 return 0;
6178 }
6179
6180 633 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6181 {
6182 633 MOVFragment *frag = &c->fragment;
6183 633 AVStream *st = NULL;
6184 MOVStreamContext *sc;
6185 int version, i;
6186 MOVFragmentStreamInfo * frag_stream_info;
6187 int64_t base_media_decode_time;
6188
6189
1/2
✓ Branch 0 taken 10560 times.
✗ Branch 1 not taken.
10560 for (i = 0; i < c->fc->nb_streams; i++) {
6190 10560 sc = c->fc->streams[i]->priv_data;
6191
2/2
✓ Branch 0 taken 633 times.
✓ Branch 1 taken 9927 times.
10560 if (sc->id == frag->track_id) {
6192 633 st = c->fc->streams[i];
6193 633 break;
6194 }
6195 }
6196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 633 times.
633 if (!st) {
6197 ✗ av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
6198 ✗ return 0;
6199 }
6200 633 sc = st->priv_data;
6201
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 629 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
633 if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1)
6202 ✗ return 0;
6203 633 version = avio_r8(pb);
6204 633 avio_rb24(pb); /* flags */
6205
2/2
✓ Branch 0 taken 260 times.
✓ Branch 1 taken 373 times.
633 if (version) {
6206 260 base_media_decode_time = avio_rb64(pb);
6207 } else {
6208 373 base_media_decode_time = avio_rb32(pb);
6209 }
6210
6211 633 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6212
1/2
✓ Branch 0 taken 633 times.
✗ Branch 1 not taken.
633 if (frag_stream_info)
6213 633 frag_stream_info->tfdt_dts = base_media_decode_time;
6214 633 sc->track_end = base_media_decode_time;
6215
6216 633 return 0;
6217 }
6218
6219 706 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6220 {
6221 706 MOVFragment *frag = &c->fragment;
6222 706 AVStream *st = NULL;
6223 706 FFStream *sti = NULL;
6224 MOVStreamContext *sc;
6225 MOVTimeToSample *tts_data;
6226 uint64_t offset;
6227 706 int64_t dts, pts = AV_NOPTS_VALUE;
6228 706 int data_offset = 0;
6229 706 unsigned entries, first_sample_flags = frag->flags;
6230 int flags, distance, i;
6231 706 int64_t prev_dts = AV_NOPTS_VALUE;
6232 706 int next_frag_index = -1, index_entry_pos;
6233 size_t requested_size;
6234 AVIndexEntry *new_entries;
6235 MOVFragmentStreamInfo * frag_stream_info;
6236
6237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (!frag->found_tfhd) {
6238 ✗ av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
6239 ✗ return AVERROR_INVALIDDATA;
6240 }
6241
6242
1/2
✓ Branch 0 taken 10665 times.
✗ Branch 1 not taken.
10665 for (i = 0; i < c->fc->nb_streams; i++) {
6243 10665 sc = c->fc->streams[i]->priv_data;
6244
2/2
✓ Branch 0 taken 706 times.
✓ Branch 1 taken 9959 times.
10665 if (sc->id == frag->track_id) {
6245 706 st = c->fc->streams[i];
6246 706 sti = ffstream(st);
6247 706 break;
6248 }
6249 }
6250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (!st) {
6251 ✗ av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
6252 ✗ return 0;
6253 }
6254 706 sc = st->priv_data;
6255
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 702 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
706 if (sc->pseudo_stream_id+1 != frag->stsd_id && sc->pseudo_stream_id != -1)
6256 ✗ return 0;
6257
6258 // Find the next frag_index index that has a valid index_entry for
6259 // the current track_id.
6260 //
6261 // A valid index_entry means the trun for the fragment was read
6262 // and it's samples are in index_entries at the given position.
6263 // New index entries will be inserted before the index_entry found.
6264 706 index_entry_pos = sti->nb_index_entries;
6265
2/2
✓ Branch 0 taken 1634 times.
✓ Branch 1 taken 706 times.
2340 for (i = c->frag_index.current + 1; i < c->frag_index.nb_items; i++) {
6266 1634 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
6267
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) {
6268 ✗ next_frag_index = i;
6269 ✗ index_entry_pos = frag_stream_info->index_entry;
6270 ✗ break;
6271 }
6272 }
6273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 av_assert0(index_entry_pos <= sti->nb_index_entries);
6274
6275 706 avio_r8(pb); /* version */
6276 706 flags = avio_rb24(pb);
6277 706 entries = avio_rb32(pb);
6278 706 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
6279
6280 /* Explicit zero sizes are bounded by the trun payload. Reject a zero
6281 * default size before allocating or updating the sample index. */
6282
4/6
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 443 times.
✓ Branch 3 taken 263 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 443 times.
706 if (entries && !frag->size && !(flags & MOV_TRUN_SAMPLE_SIZE))
6283 ✗ return AVERROR_INVALIDDATA;
6284
6285
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if ((uint64_t)entries+sc->tts_count >= UINT_MAX/sizeof(*sc->tts_data))
6286 ✗ return AVERROR_INVALIDDATA;
6287
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
6288
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 627 times.
706 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb);
6289
6290 706 int entry_size = !!(flags & MOV_TRUN_SAMPLE_DURATION) * 4
6291 706 + !!(flags & MOV_TRUN_SAMPLE_SIZE) * 4
6292 706 + !!(flags & MOV_TRUN_SAMPLE_FLAGS) * 4
6293 706 + !!(flags & MOV_TRUN_SAMPLE_CTS) * 4;
6294 706 int64_t sample_data_size = avio_size(sc->pb);
6295 706 int64_t max_entries = INT64_MAX;
6296
6297
2/2
✓ Branch 0 taken 505 times.
✓ Branch 1 taken 201 times.
706 if (sample_data_size > 0)
6298 505 max_entries = sample_data_size - sti->nb_index_entries;
6299
2/2
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 226 times.
706 if (entry_size) {
6300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 480 times.
480 int64_t size = sc->pb == pb ? sample_data_size : avio_size(pb);
6301 480 int64_t pos = avio_tell(pb);
6302 480 int64_t left = atom.size - 8 - !!(flags & MOV_TRUN_DATA_OFFSET) * 4
6303 480 - !!(flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) * 4;
6304
6305
3/4
✓ Branch 0 taken 480 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 479 times.
✓ Branch 3 taken 1 times.
480 if (pos >= 0 && size >= pos)
6306 479 left = FFMIN(left, size - pos);
6307 480 max_entries = FFMIN(max_entries, left / entry_size);
6308 }
6309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (entries > max_entries) {
6310 ✗ av_log(c->fc, AV_LOG_ERROR, "trun sample count %u exceeds the %"PRId64" "
6311 "samples the input can hold\n", entries, max_entries);
6312 ✗ return AVERROR_INVALIDDATA;
6313 }
6314
6315 706 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6316
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (frag_stream_info) {
6317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
6318 ✗ dts = frag_stream_info->next_trun_dts - sc->time_offset;
6319
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 703 times.
706 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
6320
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
6321 3 pts = frag_stream_info->first_tfra_pts;
6322 3 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
6323 ", using it for pts\n", pts);
6324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 703 times.
703 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
6325 ✗ c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
6326 ✗ dts = frag_stream_info->first_tfra_pts;
6327 ✗ av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
6328 ", using it for dts\n", pts);
6329 } else {
6330 703 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
6331 703 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
6332
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 703 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
703 int fallback_tfdt = !c->use_tfdt && !has_sidx && has_tfdt;
6333
4/6
✓ Branch 0 taken 703 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 630 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
703 int fallback_sidx = c->use_tfdt && !has_tfdt && has_sidx;
6334
6335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 703 times.
703 if (fallback_sidx) {
6336 ✗ av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
6337 }
6338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 703 times.
703 if (fallback_tfdt) {
6339 ✗ av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
6340 }
6341
6342
4/6
✓ Branch 0 taken 630 times.
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 630 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
703 if (has_tfdt && c->use_tfdt || fallback_tfdt) {
6343 630 dts = frag_stream_info->tfdt_dts - sc->time_offset;
6344 630 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
6345 ", using it for dts\n", dts);
6346
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) {
6347 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
6348 // pts = frag_stream_info->sidx_pts;
6349 ✗ dts = frag_stream_info->sidx_pts;
6350 ✗ av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
6351 ", using it for dts\n", frag_stream_info->sidx_pts);
6352 } else {
6353 73 dts = sc->track_end - sc->time_offset;
6354 73 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
6355 ", using it for dts\n", dts);
6356 }
6357 }
6358 } else {
6359 ✗ dts = sc->track_end - sc->time_offset;
6360 ✗ av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
6361 ", using it for dts\n", dts);
6362 }
6363 706 offset = frag->base_data_offset + data_offset;
6364 706 distance = 0;
6365 706 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
6366
6367 // realloc space for new index entries
6368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
6369 ✗ entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
6370 ✗ av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
6371 }
6372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (entries == 0)
6373 ✗ return 0;
6374
6375 706 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
6376 706 new_entries = av_fast_realloc(sti->index_entries,
6377 &sti->index_entries_allocated_size,
6378 requested_size);
6379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (!new_entries)
6380 ✗ return AVERROR(ENOMEM);
6381 706 sti->index_entries= new_entries;
6382
6383 706 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
6384 706 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
6385 requested_size);
6386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (!tts_data)
6387 ✗ return AVERROR(ENOMEM);
6388 706 sc->tts_data = tts_data;
6389
6390 // In case there were samples without time to sample entries, ensure they get
6391 // zero valued entries. This ensures clips which mix boxes with and
6392 // without time to sample entries don't pickup uninitialized data.
6393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (sc->tts_count < sti->nb_index_entries)
6394 ✗ memset(sc->tts_data + sc->tts_count, 0,
6395 ✗ sizeof(*sc->tts_data) * (sti->nb_index_entries - sc->tts_count));
6396
6397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (index_entry_pos < sti->nb_index_entries) {
6398 // Make hole in index_entries and tts_data for new samples
6399 ✗ memmove(sti->index_entries + index_entry_pos + entries,
6400 ✗ sti->index_entries + index_entry_pos,
6401 sizeof(*sti->index_entries) *
6402 ✗ (sti->nb_index_entries - index_entry_pos));
6403 ✗ memmove(sc->tts_data + index_entry_pos + entries,
6404 ✗ sc->tts_data + index_entry_pos,
6405 ✗ sizeof(*sc->tts_data) * (sti->nb_index_entries - index_entry_pos));
6406 ✗ if (index_entry_pos < sc->current_sample) {
6407 ✗ sc->current_sample += entries;
6408 }
6409 }
6410
6411 706 sti->nb_index_entries += entries;
6412 706 sc->tts_count = sti->nb_index_entries;
6413 706 sc->stts_count = sti->nb_index_entries;
6414
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 320 times.
706 if (flags & MOV_TRUN_SAMPLE_CTS)
6415 386 sc->ctts_count = sti->nb_index_entries;
6416
6417 // Record the index_entry position in frag_index of this fragment
6418
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (frag_stream_info) {
6419 706 frag_stream_info->index_entry = index_entry_pos;
6420
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (frag_stream_info->index_base < 0)
6421 706 frag_stream_info->index_base = index_entry_pos;
6422 }
6423
6424
2/2
✓ Branch 0 taken 574 times.
✓ Branch 1 taken 132 times.
706 if (index_entry_pos > 0)
6425 574 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6426
6427
3/4
✓ Branch 0 taken 12391 times.
✓ Branch 1 taken 706 times.
✓ Branch 2 taken 12391 times.
✗ Branch 3 not taken.
13097 for (i = 0; i < entries && !pb->eof_reached; i++) {
6428 12391 unsigned sample_size = frag->size;
6429
2/2
✓ Branch 0 taken 11685 times.
✓ Branch 1 taken 706 times.
12391 int sample_flags = i ? frag->flags : first_sample_flags;
6430 12391 unsigned sample_duration = frag->duration;
6431 12391 unsigned ctts_duration = 0;
6432 12391 int keyframe = 0;
6433 12391 int index_entry_flags = 0;
6434
6435
2/2
✓ Branch 0 taken 1694 times.
✓ Branch 1 taken 10697 times.
12391 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
6436
2/2
✓ Branch 0 taken 9533 times.
✓ Branch 1 taken 2858 times.
12391 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
6437
2/2
✓ Branch 0 taken 1845 times.
✓ Branch 1 taken 10546 times.
12391 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
6438
2/2
✓ Branch 0 taken 6576 times.
✓ Branch 1 taken 5815 times.
12391 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
6439
6440
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12390 times.
12391 if (sample_duration > c->max_stts_delta) {
6441 1 av_log(c->fc, AV_LOG_WARNING,
6442 "Too large sample duration %u in trun entry %u in st:%d. Clipping to 1.\n",
6443 sample_duration, i, st->index);
6444 1 sample_duration = 1;
6445 }
6446
6447 12391 mov_update_dts_shift(sc, ctts_duration, c->fc);
6448
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 12388 times.
12391 if (pts != AV_NOPTS_VALUE) {
6449 3 dts = pts - sc->dts_shift;
6450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (flags & MOV_TRUN_SAMPLE_CTS) {
6451 ✗ dts -= ctts_duration;
6452 } else {
6453 3 dts -= sc->time_offset;
6454 }
6455 3 av_log(c->fc, AV_LOG_DEBUG,
6456 "pts %"PRId64" calculated dts %"PRId64
6457 " sc->dts_shift %d ctts.duration %d"
6458 " sc->time_offset %"PRId64
6459 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
6460 pts, dts,
6461 sc->dts_shift, ctts_duration,
6462 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
6463 3 pts = AV_NOPTS_VALUE;
6464 }
6465
6466 12391 keyframe =
6467 12391 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
6468 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
6469
2/2
✓ Branch 0 taken 3468 times.
✓ Branch 1 taken 8923 times.
12391 if (keyframe) {
6470 3468 distance = 0;
6471 3468 index_entry_flags |= AVINDEX_KEYFRAME;
6472 }
6473 // Fragments can overlap in time. Discard overlapping frames after
6474 // decoding.
6475
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12367 times.
12391 if (prev_dts >= dts)
6476 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
6477
6478 12391 sti->index_entries[index_entry_pos].pos = offset;
6479 12391 sti->index_entries[index_entry_pos].timestamp = dts;
6480 12391 sti->index_entries[index_entry_pos].size = sample_size;
6481 12391 sti->index_entries[index_entry_pos].min_distance = distance;
6482 12391 sti->index_entries[index_entry_pos].flags = index_entry_flags;
6483
6484 12391 sc->tts_data[index_entry_pos].count = 1;
6485 12391 sc->tts_data[index_entry_pos].offset = ctts_duration;
6486 12391 sc->tts_data[index_entry_pos].duration = sample_duration;
6487 12391 index_entry_pos++;
6488
6489 12391 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
6490 "size %u, distance %d, keyframe %d\n", st->index,
6491 index_entry_pos, offset, dts, sample_size, distance, keyframe);
6492 12391 distance++;
6493
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12391 times.
12391 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
6494 ✗ return AVERROR_INVALIDDATA;
6495 12391 dts += sample_duration;
6496 12391 offset += sample_size;
6497 12391 sc->data_size += sample_size;
6498
6499
1/2
✓ Branch 0 taken 12391 times.
✗ Branch 1 not taken.
12391 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
6500
1/2
✓ Branch 0 taken 12391 times.
✗ Branch 1 not taken.
12391 1 <= INT_MAX - sc->nb_frames_for_fps
6501 ) {
6502 12391 sc->duration_for_fps += sample_duration;
6503 12391 sc->nb_frames_for_fps ++;
6504 }
6505 }
6506
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (frag_stream_info)
6507 706 frag_stream_info->next_trun_dts = dts + sc->time_offset;
6508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (i < entries) {
6509 // EOF found before reading all entries. Fix the hole this would
6510 // leave in index_entries and tts_data
6511 ✗ int gap = entries - i;
6512 ✗ memmove(sti->index_entries + index_entry_pos,
6513 ✗ sti->index_entries + index_entry_pos + gap,
6514 sizeof(*sti->index_entries) *
6515 ✗ (sti->nb_index_entries - (index_entry_pos + gap)));
6516 ✗ memmove(sc->tts_data + index_entry_pos,
6517 ✗ sc->tts_data + index_entry_pos + gap,
6518 sizeof(*sc->tts_data) *
6519 ✗ (sc->tts_count - (index_entry_pos + gap)));
6520
6521 ✗ sti->nb_index_entries -= gap;
6522 ✗ sc->tts_count -= gap;
6523 ✗ if (index_entry_pos < sc->current_sample) {
6524 ✗ sc->current_sample -= gap;
6525 }
6526 ✗ entries = i;
6527 }
6528
6529 // The end of this new fragment may overlap in time with the start
6530 // of the next fragment in index_entries. Mark the samples in the next
6531 // fragment that overlap with AVINDEX_DISCARD_FRAME
6532 706 prev_dts = AV_NOPTS_VALUE;
6533
1/2
✓ Branch 0 taken 706 times.
✗ Branch 1 not taken.
706 if (index_entry_pos > 0)
6534 706 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
6536 ✗ if (prev_dts < sti->index_entries[i].timestamp)
6537 ✗ break;
6538 ✗ sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6539 }
6540
6541 // If a hole was created to insert the new index_entries into,
6542 // the index_entry recorded for all subsequent moof must
6543 // be incremented by the number of entries inserted.
6544 706 fix_frag_index_entries(&c->frag_index, next_frag_index,
6545 706 frag->track_id, entries);
6546
6547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 if (pb->eof_reached) {
6548 ✗ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6549 ✗ return AVERROR_EOF;
6550 }
6551
6552 706 frag->implicit_offset = offset;
6553
6554 706 sc->track_end = dts + sc->time_offset;
6555
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 586 times.
706 if (st->duration < sc->track_end)
6556 120 st->duration = sc->track_end;
6557
6558 706 return 0;
6559 }
6560
6561 249 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6562 {
6563 249 int64_t stream_size = avio_size(pb);
6564 249 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6565 uint8_t version, is_complete;
6566 int64_t offadd;
6567 unsigned i, j, track_id, item_count;
6568 249 AVStream *st = NULL;
6569 249 AVStream *ref_st = NULL;
6570 249 MOVStreamContext *sc, *ref_sc = NULL;
6571 AVRational timescale;
6572
6573 249 version = avio_r8(pb);
6574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if (version > 1) {
6575 ✗ avpriv_request_sample(c->fc, "sidx version %u", version);
6576 ✗ return 0;
6577 }
6578
6579 249 avio_rb24(pb); // flags
6580
6581 249 track_id = avio_rb32(pb); // Reference ID
6582
1/2
✓ Branch 0 taken 10149 times.
✗ Branch 1 not taken.
10149 for (i = 0; i < c->fc->nb_streams; i++) {
6583 10149 sc = c->fc->streams[i]->priv_data;
6584
2/2
✓ Branch 0 taken 249 times.
✓ Branch 1 taken 9900 times.
10149 if (sc->id == track_id) {
6585 249 st = c->fc->streams[i];
6586 249 break;
6587 }
6588 }
6589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if (!st) {
6590 ✗ av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6591 ✗ return 0;
6592 }
6593
6594 249 sc = st->priv_data;
6595
6596 249 timescale = av_make_q(1, avio_rb32(pb));
6597
6598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if (timescale.den <= 0) {
6599 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6600 ✗ return AVERROR_INVALIDDATA;
6601 }
6602
6603
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 201 times.
249 if (version == 0) {
6604 48 pts = avio_rb32(pb);
6605 48 offadd= avio_rb32(pb);
6606 } else {
6607 201 pts = avio_rb64(pb);
6608 201 offadd= avio_rb64(pb);
6609 }
6610
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 249 times.
249 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6611 ✗ return AVERROR_INVALIDDATA;
6612
6613 249 offset += (uint64_t)offadd;
6614
6615 249 avio_rb16(pb); // reserved
6616
6617 249 item_count = avio_rb16(pb);
6618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if (item_count == 0)
6619 ✗ return AVERROR_INVALIDDATA;
6620
6621
2/2
✓ Branch 0 taken 575 times.
✓ Branch 1 taken 249 times.
824 for (i = 0; i < item_count; i++) {
6622 int index;
6623 MOVFragmentStreamInfo * frag_stream_info;
6624 575 uint32_t size = avio_rb32(pb);
6625 575 uint32_t duration = avio_rb32(pb);
6626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 if (size & 0x80000000) {
6627 ✗ avpriv_request_sample(c->fc, "sidx reference_type 1");
6628 ✗ return AVERROR_PATCHWELCOME;
6629 }
6630 575 avio_rb32(pb); // sap_flags
6631 575 timestamp = av_rescale_q(pts, timescale, st->time_base);
6632
6633 575 index = update_frag_index(c, offset);
6634 575 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6635
1/2
✓ Branch 0 taken 575 times.
✗ Branch 1 not taken.
575 if (frag_stream_info)
6636 575 frag_stream_info->sidx_pts = timestamp;
6637
6638
1/2
✓ Branch 1 taken 575 times.
✗ Branch 2 not taken.
575 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6639
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 575 times.
575 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6640 )
6641 ✗ return AVERROR_INVALIDDATA;
6642 575 offset += size;
6643 575 pts += duration;
6644 }
6645
6646 249 st->duration = sc->track_end = pts;
6647
6648 249 sc->has_sidx = 1;
6649
6650 // See if the remaining bytes are just an mfra which we can ignore.
6651 249 is_complete = offset == stream_size;
6652
5/6
✓ Branch 0 taken 242 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 201 times.
✓ Branch 4 taken 41 times.
✗ Branch 5 not taken.
249 if (!is_complete && (pb->seekable & AVIO_SEEKABLE_NORMAL) && stream_size > 0 ) {
6653 int64_t ret;
6654 41 int64_t original_pos = avio_tell(pb);
6655
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 35 times.
41 if (!c->have_read_mfra_size) {
6656
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6657 ✗ return ret;
6658 6 c->mfra_size = avio_rb32(pb);
6659 6 c->have_read_mfra_size = 1;
6660
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6661 ✗ return ret;
6662 }
6663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (offset == stream_size - c->mfra_size)
6664 ✗ is_complete = 1;
6665 }
6666
6667
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 242 times.
249 if (is_complete) {
6668 // Find first entry in fragment index that came from an sidx.
6669 // This will pretty much always be the first entry.
6670
2/2
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 7 times.
378 for (i = 0; i < c->frag_index.nb_items; i++) {
6671 371 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6672
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++) {
6673 MOVFragmentStreamInfo * si;
6674 7 si = &item->stream_info[j];
6675
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (si->sidx_pts != AV_NOPTS_VALUE) {
6676 7 ref_st = c->fc->streams[j];
6677 7 ref_sc = ref_st->priv_data;
6678 7 break;
6679 }
6680 }
6681 }
6682
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++) {
6683 7 st = c->fc->streams[i];
6684 7 sc = st->priv_data;
6685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sc->has_sidx) {
6686 ✗ st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6687 }
6688 }
6689
6690
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (offadd == 0)
6691 7 c->frag_index.complete = 1;
6692 }
6693
6694 249 return 0;
6695 }
6696
6697 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6698 /* like the files created with Adobe Premiere 5.0, for samples see */
6699 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6700 299 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6701 {
6702 int err;
6703
6704
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 if (atom.size < 8)
6705 299 return 0; /* continue */
6706 ✗ if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6707 ✗ avio_skip(pb, atom.size - 4);
6708 ✗ return 0;
6709 }
6710 ✗ atom.type = avio_rl32(pb);
6711 ✗ atom.size -= 8;
6712 ✗ if (atom.type != MKTAG('m','d','a','t')) {
6713 ✗ avio_skip(pb, atom.size);
6714 ✗ return 0;
6715 }
6716 ✗ err = mov_read_mdat(c, pb, atom);
6717 ✗ return err;
6718 }
6719
6720 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6721 {
6722 #if CONFIG_ZLIB
6723 FFIOContext ctx;
6724 uint8_t *cmov_data;
6725 uint8_t *moov_data; /* uncompressed data */
6726 long cmov_len, moov_len;
6727 3 int ret = -1;
6728
6729 3 avio_rb32(pb); /* dcom atom */
6730
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6731 ✗ return AVERROR_INVALIDDATA;
6732
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6733 ✗ av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6734 ✗ return AVERROR_INVALIDDATA;
6735 }
6736 3 avio_rb32(pb); /* cmvd atom */
6737
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6738 ✗ return AVERROR_INVALIDDATA;
6739 3 moov_len = avio_rb32(pb); /* uncompressed size */
6740 3 cmov_len = atom.size - 6 * 4;
6741
6742 3 cmov_data = av_malloc(cmov_len);
6743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6744 ✗ return AVERROR(ENOMEM);
6745 3 moov_data = av_malloc(moov_len);
6746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6747 ✗ av_free(cmov_data);
6748 ✗ return AVERROR(ENOMEM);
6749 }
6750 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6752 ✗ goto free_and_return;
6753
6754 3 ret = AVERROR_INVALIDDATA;
6755
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)
6756 ✗ goto free_and_return;
6757 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6758 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6759 3 atom.type = MKTAG('m','o','o','v');
6760 3 atom.size = moov_len;
6761 3 ret = mov_read_default(c, &ctx.pub, atom);
6762 3 free_and_return:
6763 3 av_free(moov_data);
6764 3 av_free(cmov_data);
6765 3 return ret;
6766 #else
6767 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6768 return AVERROR(ENOSYS);
6769 #endif
6770 }
6771
6772 /* edit list atom */
6773 649 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6774 {
6775 MOVStreamContext *sc;
6776 int i, edit_count, version;
6777 int64_t elst_entry_size;
6778
6779
2/4
✓ Branch 0 taken 649 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 649 times.
649 if (c->fc->nb_streams < 1 || c->ignore_editlist)
6780 ✗ return 0;
6781 649 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6782
6783 649 version = avio_r8(pb); /* version */
6784 649 avio_rb24(pb); /* flags */
6785 649 edit_count = avio_rb32(pb); /* entries */
6786 649 atom.size -= 8;
6787
6788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 649 times.
649 elst_entry_size = version == 1 ? 20 : 12;
6789
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 648 times.
649 if (atom.size != edit_count * elst_entry_size) {
6790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6791 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6792 ✗ edit_count, atom.size + 8);
6793 ✗ return AVERROR_INVALIDDATA;
6794 } else {
6795 1 edit_count = atom.size / elst_entry_size;
6796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6797 ✗ av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6798 }
6799 }
6800 }
6801
6802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 649 times.
649 if (!edit_count)
6803 ✗ return 0;
6804
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 649 times.
649 if (sc->elst_data)
6805 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6806 649 av_free(sc->elst_data);
6807 649 sc->elst_count = 0;
6808 649 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 649 times.
649 if (!sc->elst_data)
6810 ✗ return AVERROR(ENOMEM);
6811
6812 649 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6813
4/6
✓ Branch 0 taken 678 times.
✓ Branch 1 taken 649 times.
✓ Branch 2 taken 678 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 678 times.
✗ Branch 5 not taken.
1327 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
6814 678 MOVElst *e = &sc->elst_data[i];
6815
6816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 678 times.
678 if (version == 1) {
6817 ✗ e->duration = avio_rb64(pb);
6818 ✗ e->time = avio_rb64(pb);
6819 ✗ atom.size -= 16;
6820 } else {
6821 678 e->duration = avio_rb32(pb); /* segment duration */
6822 678 e->time = (int32_t)avio_rb32(pb); /* media time */
6823 678 atom.size -= 8;
6824 }
6825 678 e->rate = avio_rb32(pb) / 65536.0;
6826 678 atom.size -= 4;
6827 678 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6828 678 e->duration, e->time, e->rate);
6829
6830
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 674 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
678 if (e->time < 0 && e->time != -1 &&
6831 ✗ c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6832 ✗ av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6833 ✗ c->fc->nb_streams-1, i, e->time);
6834 ✗ return AVERROR_INVALIDDATA;
6835 }
6836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 678 times.
678 if (e->duration < 0) {
6837 ✗ av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list duration=%"PRId64"\n",
6838 ✗ c->fc->nb_streams-1, i, e->duration);
6839 ✗ return AVERROR_INVALIDDATA;
6840 }
6841 }
6842 649 sc->elst_count = i;
6843
6844 649 return 0;
6845 }
6846
6847 21 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6848 {
6849 MOVStreamContext *sc;
6850 int err;
6851
6852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (c->fc->nb_streams < 1)
6853 ✗ return AVERROR_INVALIDDATA;
6854 21 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6855
6856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (atom.size % sizeof(uint32_t))
6857 ✗ return AVERROR_INVALIDDATA;
6858
6859 21 MovTref *tag = mov_add_tref_tag(sc, atom.type);
6860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!tag)
6861 ✗ return AVERROR(ENOMEM);
6862
6863 21 int nb_timecode_track = atom.size >> 2;
6864
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 21 times.
52 for (int i = 0; i < nb_timecode_track; i++) {
6865
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 if (avio_feof(pb))
6866 ✗ return AVERROR_INVALIDDATA;
6867 31 err = mov_add_tref_id(tag, avio_rb32(pb));
6868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (err < 0)
6869 ✗ return err;
6870 }
6871
6872 21 return 0;
6873 }
6874
6875 ✗ static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6876 {
6877 AVStream *st;
6878 int version, color_range, color_primaries, color_trc, color_space;
6879
6880 ✗ if (c->fc->nb_streams < 1)
6881 ✗ return 0;
6882 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
6883
6884 ✗ if (atom.size < 5) {
6885 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6886 ✗ return AVERROR_INVALIDDATA;
6887 }
6888
6889 ✗ version = avio_r8(pb);
6890 ✗ if (version != 1) {
6891 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6892 ✗ return 0;
6893 }
6894 ✗ avio_skip(pb, 3); /* flags */
6895
6896 ✗ avio_skip(pb, 2); /* profile + level */
6897 ✗ color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6898 ✗ color_primaries = avio_r8(pb);
6899 ✗ color_trc = avio_r8(pb);
6900 ✗ color_space = avio_r8(pb);
6901 ✗ if (avio_rb16(pb)) /* codecIntializationDataSize */
6902 ✗ return AVERROR_INVALIDDATA;
6903
6904 ✗ if (!av_color_primaries_name(color_primaries))
6905 ✗ color_primaries = AVCOL_PRI_UNSPECIFIED;
6906 ✗ if (!av_color_transfer_name(color_trc))
6907 ✗ color_trc = AVCOL_TRC_UNSPECIFIED;
6908 ✗ if (!av_color_space_name(color_space))
6909 ✗ color_space = AVCOL_SPC_UNSPECIFIED;
6910
6911 ✗ st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6912 ✗ st->codecpar->color_primaries = color_primaries;
6913 ✗ st->codecpar->color_trc = color_trc;
6914 ✗ st->codecpar->color_space = color_space;
6915
6916 ✗ return 0;
6917 }
6918
6919 ✗ static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6920 {
6921 MOVStreamContext *sc;
6922 int i, version;
6923
6924 ✗ if (c->fc->nb_streams < 1)
6925 ✗ return AVERROR_INVALIDDATA;
6926
6927 ✗ sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6928
6929 ✗ if (atom.size < 5) {
6930 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6931 ✗ return AVERROR_INVALIDDATA;
6932 }
6933
6934 ✗ version = avio_r8(pb);
6935 ✗ if (version) {
6936 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6937 ✗ return 0;
6938 }
6939 ✗ if (sc->mastering) {
6940 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6941 ✗ return 0;
6942 }
6943
6944 ✗ avio_skip(pb, 3); /* flags */
6945
6946 ✗ sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6947 ✗ if (!sc->mastering)
6948 ✗ return AVERROR(ENOMEM);
6949
6950 ✗ for (i = 0; i < 3; i++) {
6951 ✗ sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6952 ✗ sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6953 }
6954 ✗ sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6955 ✗ sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6956
6957 ✗ sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6958 ✗ sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6959
6960 ✗ sc->mastering->has_primaries = 1;
6961 ✗ sc->mastering->has_luminance = 1;
6962
6963 ✗ return 0;
6964 }
6965
6966 ✗ static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6967 {
6968 MOVStreamContext *sc;
6969 ✗ const int mapping[3] = {1, 2, 0};
6970 ✗ const int chroma_den = 50000;
6971 ✗ const int luma_den = 10000;
6972 int i;
6973
6974 ✗ if (c->fc->nb_streams < 1)
6975 ✗ return AVERROR_INVALIDDATA;
6976
6977 ✗ sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6978
6979 ✗ if (atom.size < 24) {
6980 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6981 ✗ return AVERROR_INVALIDDATA;
6982 }
6983
6984 ✗ if (sc->mastering) {
6985 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6986 ✗ return 0;
6987 }
6988
6989 ✗ sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6990 ✗ if (!sc->mastering)
6991 ✗ return AVERROR(ENOMEM);
6992
6993 ✗ for (i = 0; i < 3; i++) {
6994 ✗ const int j = mapping[i];
6995 ✗ sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6996 ✗ sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6997 }
6998 ✗ sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6999 ✗ sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
7000
7001 ✗ sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
7002 ✗ sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
7003
7004 ✗ sc->mastering->has_luminance = 1;
7005 ✗ sc->mastering->has_primaries = 1;
7006
7007 ✗ return 0;
7008 }
7009
7010 ✗ static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7011 {
7012 MOVStreamContext *sc;
7013 int version;
7014
7015 ✗ if (c->fc->nb_streams < 1)
7016 ✗ return AVERROR_INVALIDDATA;
7017
7018 ✗ sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7019
7020 ✗ if (atom.size < 5) {
7021 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
7022 ✗ return AVERROR_INVALIDDATA;
7023 }
7024
7025 ✗ version = avio_r8(pb);
7026 ✗ if (version) {
7027 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
7028 ✗ return 0;
7029 }
7030 ✗ avio_skip(pb, 3); /* flags */
7031
7032 ✗ if (sc->coll){
7033 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
7034 ✗ return 0;
7035 }
7036
7037 ✗ sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
7038 ✗ if (!sc->coll)
7039 ✗ return AVERROR(ENOMEM);
7040
7041 ✗ sc->coll->MaxCLL = avio_rb16(pb);
7042 ✗ sc->coll->MaxFALL = avio_rb16(pb);
7043
7044 ✗ return 0;
7045 }
7046
7047 ✗ static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7048 {
7049 MOVStreamContext *sc;
7050
7051 ✗ if (c->fc->nb_streams < 1)
7052 ✗ return AVERROR_INVALIDDATA;
7053
7054 ✗ sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7055
7056 ✗ if (atom.size < 4) {
7057 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
7058 ✗ return AVERROR_INVALIDDATA;
7059 }
7060
7061 ✗ if (sc->coll){
7062 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
7063 ✗ return 0;
7064 }
7065
7066 ✗ sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
7067 ✗ if (!sc->coll)
7068 ✗ return AVERROR(ENOMEM);
7069
7070 ✗ sc->coll->MaxCLL = avio_rb16(pb);
7071 ✗ sc->coll->MaxFALL = avio_rb16(pb);
7072
7073 ✗ return 0;
7074 }
7075
7076 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7077 {
7078 MOVStreamContext *sc;
7079 4 const int illuminance_den = 10000;
7080 4 const int ambient_den = 50000;
7081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
7082 ✗ return AVERROR_INVALIDDATA;
7083 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
7085 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
7086 ✗ return AVERROR_INVALIDDATA;
7087 }
7088
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
7089 ✗ av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
7090 ✗ return 0;
7091 }
7092 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
7093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
7094 ✗ return AVERROR(ENOMEM);
7095 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
7096 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
7097 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
7098 4 return 0;
7099 }
7100
7101 3 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7102 {
7103 AVStream *st;
7104 MOVStreamContext *sc;
7105 enum AVStereo3DType type;
7106 int mode;
7107
7108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7109 ✗ return 0;
7110
7111 3 st = c->fc->streams[c->fc->nb_streams - 1];
7112 3 sc = st->priv_data;
7113
7114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 5) {
7115 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
7116 ✗ return AVERROR_INVALIDDATA;
7117 }
7118
7119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->stereo3d)
7120 ✗ return AVERROR_INVALIDDATA;
7121
7122 3 avio_skip(pb, 4); /* version + flags */
7123
7124 3 mode = avio_r8(pb);
7125
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
3 switch (mode) {
7126 1 case 0:
7127 1 type = AV_STEREO3D_2D;
7128 1 break;
7129 ✗ case 1:
7130 ✗ type = AV_STEREO3D_TOPBOTTOM;
7131 ✗ break;
7132 2 case 2:
7133 2 type = AV_STEREO3D_SIDEBYSIDE;
7134 2 break;
7135 ✗ default:
7136 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
7137 ✗ return 0;
7138 }
7139
7140 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7142 ✗ return AVERROR(ENOMEM);
7143
7144 3 sc->stereo3d->type = type;
7145 3 return 0;
7146 }
7147
7148 ✗ static int mov_read_pack(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7149 {
7150 AVStream *st;
7151 MOVStreamContext *sc;
7152 ✗ int size = 0;
7153 int64_t remaining;
7154 ✗ uint32_t tag = 0;
7155 ✗ enum AVStereo3DType type = AV_STEREO3D_2D;
7156
7157 ✗ if (c->fc->nb_streams < 1)
7158 ✗ return 0;
7159
7160 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
7161 ✗ sc = st->priv_data;
7162
7163 ✗ remaining = atom.size;
7164 ✗ while (remaining > 0) {
7165 ✗ size = avio_rb32(pb);
7166 ✗ if (size < 8 || size > remaining ) {
7167 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid child size in pack box\n");
7168 ✗ return AVERROR_INVALIDDATA;
7169 }
7170
7171 ✗ tag = avio_rl32(pb);
7172 ✗ switch (tag) {
7173 ✗ case MKTAG('p','k','i','n'): {
7174 ✗ if (size != 16) {
7175 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of pkin box: %d\n", size);
7176 ✗ return AVERROR_INVALIDDATA;
7177 }
7178 ✗ avio_skip(pb, 1); // version
7179 ✗ avio_skip(pb, 3); // flags
7180
7181 ✗ tag = avio_rl32(pb);
7182 ✗ switch (tag) {
7183 ✗ case MKTAG('s','i','d','e'):
7184 ✗ type = AV_STEREO3D_SIDEBYSIDE;
7185 ✗ break;
7186 ✗ case MKTAG('o','v','e','r'):
7187 ✗ type = AV_STEREO3D_TOPBOTTOM;
7188 ✗ break;
7189 ✗ case 0:
7190 // This means value will be set in another layer
7191 ✗ break;
7192 ✗ default:
7193 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pkin: %s\n",
7194 ✗ av_fourcc2str(tag));
7195 ✗ avio_skip(pb, size - 8);
7196 ✗ break;
7197 }
7198
7199 ✗ break;
7200 }
7201 ✗ default:
7202 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pack: %s\n",
7203 ✗ av_fourcc2str(tag));
7204 ✗ avio_skip(pb, size - 8);
7205 ✗ break;
7206 }
7207 ✗ remaining -= size;
7208 }
7209
7210 ✗ if (remaining != 0) {
7211 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken pack box\n");
7212 ✗ return AVERROR_INVALIDDATA;
7213 }
7214
7215 ✗ if (type == AV_STEREO3D_2D)
7216 ✗ return 0;
7217
7218 ✗ if (!sc->stereo3d) {
7219 ✗ sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7220 ✗ if (!sc->stereo3d)
7221 ✗ return AVERROR(ENOMEM);
7222 }
7223
7224 ✗ sc->stereo3d->type = type;
7225
7226 ✗ return 0;
7227 }
7228
7229 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7230 {
7231 AVStream *st;
7232 MOVStreamContext *sc;
7233 int size, version, layout;
7234 int32_t yaw, pitch, roll;
7235 1 uint32_t l = 0, t = 0, r = 0, b = 0;
7236 1 uint32_t tag, padding = 0;
7237 enum AVSphericalProjection projection;
7238
7239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
7240 ✗ return 0;
7241
7242 1 st = c->fc->streams[c->fc->nb_streams - 1];
7243 1 sc = st->priv_data;
7244
7245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
7246 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
7247 ✗ return AVERROR_INVALIDDATA;
7248 }
7249
7250 1 size = avio_rb32(pb);
7251
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)
7252 ✗ return AVERROR_INVALIDDATA;
7253
7254 1 tag = avio_rl32(pb);
7255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
7256 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
7257 ✗ return 0;
7258 }
7259 1 version = avio_r8(pb);
7260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7261 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7262 version);
7263 ✗ return 0;
7264 }
7265 1 avio_skip(pb, 3); /* flags */
7266 1 avio_skip(pb, size - 12); /* metadata_source */
7267
7268 1 size = avio_rb32(pb);
7269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7270 ✗ return AVERROR_INVALIDDATA;
7271
7272 1 tag = avio_rl32(pb);
7273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
7274 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
7275 ✗ return 0;
7276 }
7277
7278 1 size = avio_rb32(pb);
7279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7280 ✗ return AVERROR_INVALIDDATA;
7281
7282 1 tag = avio_rl32(pb);
7283
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
7284 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
7285 ✗ return 0;
7286 }
7287 1 version = avio_r8(pb);
7288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7289 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7290 version);
7291 ✗ return 0;
7292 }
7293 1 avio_skip(pb, 3); /* flags */
7294
7295 /* 16.16 fixed point */
7296 1 yaw = avio_rb32(pb);
7297 1 pitch = avio_rb32(pb);
7298 1 roll = avio_rb32(pb);
7299
7300 1 size = avio_rb32(pb);
7301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7302 ✗ return AVERROR_INVALIDDATA;
7303
7304 1 tag = avio_rl32(pb);
7305 1 version = avio_r8(pb);
7306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7307 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7308 version);
7309 ✗ return 0;
7310 }
7311 1 avio_skip(pb, 3); /* flags */
7312
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
7313 ✗ case MKTAG('c','b','m','p'):
7314 ✗ layout = avio_rb32(pb);
7315 ✗ if (layout) {
7316 ✗ av_log(c->fc, AV_LOG_WARNING,
7317 "Unsupported cubemap layout %d\n", layout);
7318 ✗ return 0;
7319 }
7320 ✗ projection = AV_SPHERICAL_CUBEMAP;
7321 ✗ padding = avio_rb32(pb);
7322 ✗ break;
7323 1 case MKTAG('e','q','u','i'):
7324 1 t = avio_rb32(pb);
7325 1 b = avio_rb32(pb);
7326 1 l = avio_rb32(pb);
7327 1 r = avio_rb32(pb);
7328
7329
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) {
7330 ✗ av_log(c->fc, AV_LOG_ERROR,
7331 "Invalid bounding rectangle coordinates "
7332 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
7333 ✗ return AVERROR_INVALIDDATA;
7334 }
7335
7336
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)
7337 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
7338 else
7339 ✗ projection = AV_SPHERICAL_EQUIRECTANGULAR;
7340 1 break;
7341 ✗ default:
7342 ✗ av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
7343 ✗ return 0;
7344 }
7345
7346 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
7348 ✗ return AVERROR(ENOMEM);
7349
7350 1 sc->spherical->projection = projection;
7351
7352 1 sc->spherical->yaw = yaw;
7353 1 sc->spherical->pitch = pitch;
7354 1 sc->spherical->roll = roll;
7355
7356 1 sc->spherical->padding = padding;
7357
7358 1 sc->spherical->bound_left = l;
7359 1 sc->spherical->bound_top = t;
7360 1 sc->spherical->bound_right = r;
7361 1 sc->spherical->bound_bottom = b;
7362
7363 1 return 0;
7364 }
7365
7366 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7367 {
7368 AVStream *st;
7369 MOVStreamContext *sc;
7370 int size;
7371 uint32_t tag;
7372 enum AVSphericalProjection projection;
7373
7374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7375 ✗ return 0;
7376
7377 3 st = c->fc->streams[c->fc->nb_streams - 1];
7378 3 sc = st->priv_data;
7379
7380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 16) {
7381 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
7382 ✗ return AVERROR_INVALIDDATA;
7383 }
7384
7385 3 size = avio_rb32(pb);
7386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size < 16) {
7387 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
7388 ✗ return AVERROR_INVALIDDATA;
7389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (size > 16) {
7390 ✗ av_log(c->fc, AV_LOG_WARNING, "Box has more bytes (%d) than prji box required (16) \n", size);
7391 }
7392
7393 3 tag = avio_rl32(pb);
7394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
7395 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: %s\n",
7396 ✗ av_fourcc2str(tag));
7397 ✗ return AVERROR_INVALIDDATA;
7398 }
7399
7400 // version and flags, only support (0, 0)
7401 3 unsigned n = avio_rl32(pb);
7402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (n != 0) {
7403 ✗ av_log(c->fc, AV_LOG_ERROR, "prji version %u, flag %u are not supported\n",
7404 n & 0xFF, n >> 8);
7405 ✗ return AVERROR_PATCHWELCOME;
7406 }
7407
7408 3 tag = avio_rl32(pb);
7409
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) {
7410 3 case MKTAG('r','e','c','t'):
7411 3 projection = AV_SPHERICAL_RECTILINEAR;
7412 3 break;
7413 ✗ case MKTAG('e','q','u','i'):
7414 ✗ projection = AV_SPHERICAL_EQUIRECTANGULAR;
7415 ✗ break;
7416 ✗ case MKTAG('h','e','q','u'):
7417 ✗ projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
7418 ✗ break;
7419 ✗ case MKTAG('f','i','s','h'):
7420 ✗ projection = AV_SPHERICAL_FISHEYE;
7421 ✗ break;
7422 ✗ case MKTAG('p','r','i','m'):
7423 ✗ projection = AV_SPHERICAL_PARAMETRIC_IMMERSIVE;
7424 ✗ break;
7425 ✗ default:
7426 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: %s\n", av_fourcc2str(tag));
7427 ✗ return AVERROR_INVALIDDATA;
7428 }
7429
7430 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
7432 ✗ return AVERROR(ENOMEM);
7433
7434 3 sc->spherical->projection = projection;
7435
7436 3 return 0;
7437 }
7438
7439 5 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7440 {
7441 AVStream *st;
7442 MOVStreamContext *sc;
7443 5 int size, flags = 0;
7444 int64_t remaining;
7445 5 uint32_t tag, baseline = 0;
7446 5 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
7447 5 enum AVStereo3DType type = AV_STEREO3D_2D;
7448 5 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
7449 5 AVRational horizontal_disparity_adjustment = { 0, 1 };
7450
7451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
7452 ✗ return 0;
7453
7454 5 st = c->fc->streams[c->fc->nb_streams - 1];
7455 5 sc = st->priv_data;
7456
7457 5 remaining = atom.size;
7458
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 while (remaining > 0) {
7459 11 size = avio_rb32(pb);
7460
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 ) {
7461 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
7462 ✗ return AVERROR_INVALIDDATA;
7463 }
7464
7465 11 tag = avio_rl32(pb);
7466
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) {
7467 5 case MKTAG('s','t','r','i'): {
7468 int has_right, has_left;
7469 uint8_t tmp;
7470
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (size != 13) {
7471 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
7472 ✗ return AVERROR_INVALIDDATA;
7473 }
7474 5 avio_skip(pb, 1); // version
7475 5 avio_skip(pb, 3); // flags
7476
7477 5 tmp = avio_r8(pb);
7478
7479 // eye_views_reversed
7480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (tmp & 8) {
7481 ✗ flags |= AV_STEREO3D_FLAG_INVERT;
7482 }
7483 // has_additional_views
7484 5 if (tmp & 4) {
7485 // skip...
7486 }
7487
7488 5 has_right = tmp & 2; // has_right_eye_view
7489 5 has_left = tmp & 1; // has_left_eye_view
7490
7491
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)
7492 5 view = AV_STEREO3D_VIEW_PACKED;
7493 ✗ else if (has_left)
7494 ✗ view = AV_STEREO3D_VIEW_LEFT;
7495 ✗ else if (has_right)
7496 ✗ view = AV_STEREO3D_VIEW_RIGHT;
7497
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)
7498 5 type = AV_STEREO3D_UNSPEC;
7499
7500 5 break;
7501 }
7502 ✗ case MKTAG('h','e','r','o'): {
7503 int tmp;
7504 ✗ if (size != 13) {
7505 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
7506 ✗ return AVERROR_INVALIDDATA;
7507 }
7508 ✗ avio_skip(pb, 1); // version
7509 ✗ avio_skip(pb, 3); // flags
7510
7511 ✗ tmp = avio_r8(pb);
7512 ✗ if (tmp == 0)
7513 ✗ primary_eye = AV_PRIMARY_EYE_NONE;
7514 ✗ else if (tmp == 1)
7515 ✗ primary_eye = AV_PRIMARY_EYE_LEFT;
7516 ✗ else if (tmp == 2)
7517 ✗ primary_eye = AV_PRIMARY_EYE_RIGHT;
7518 else
7519 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
7520
7521 ✗ break;
7522 }
7523 3 case MKTAG('c','a','m','s'): {
7524 uint32_t subtag;
7525 int subsize;
7526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7527 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
7528 ✗ return AVERROR_INVALIDDATA;
7529 }
7530
7531 3 subsize = avio_rb32(pb);
7532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7533 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
7534 ✗ return AVERROR_INVALIDDATA;
7535 }
7536
7537 3 subtag = avio_rl32(pb);
7538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
7539 ✗ av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got %s\n",
7540 ✗ av_fourcc2str(subtag));
7541 ✗ return AVERROR_INVALIDDATA;
7542 }
7543
7544 3 avio_skip(pb, 1); // version
7545 3 avio_skip(pb, 3); // flags
7546
7547 3 baseline = avio_rb32(pb);
7548
7549 3 break;
7550 }
7551 3 case MKTAG('c','m','f','y'): {
7552 uint32_t subtag;
7553 int subsize;
7554 int32_t adjustment;
7555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7556 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
7557 ✗ return AVERROR_INVALIDDATA;
7558 }
7559
7560 3 subsize = avio_rb32(pb);
7561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7562 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
7563 ✗ return AVERROR_INVALIDDATA;
7564 }
7565
7566 3 subtag = avio_rl32(pb);
7567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
7568 ✗ av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got %s\n",
7569 ✗ av_fourcc2str(subtag));
7570 ✗ return AVERROR_INVALIDDATA;
7571 }
7572
7573 3 avio_skip(pb, 1); // version
7574 3 avio_skip(pb, 3); // flags
7575
7576 3 adjustment = (int32_t) avio_rb32(pb);
7577
7578 3 horizontal_disparity_adjustment.num = (int) adjustment;
7579 3 horizontal_disparity_adjustment.den = 10000;
7580
7581 3 break;
7582 }
7583 ✗ default:
7584 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: %s\n",
7585 ✗ av_fourcc2str(tag));
7586 ✗ avio_skip(pb, size - 8);
7587 ✗ break;
7588 }
7589 11 remaining -= size;
7590 }
7591
7592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (remaining != 0) {
7593 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
7594 ✗ return AVERROR_INVALIDDATA;
7595 }
7596
7597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (type == AV_STEREO3D_2D)
7598 ✗ return 0;
7599
7600
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (!sc->stereo3d) {
7601 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7603 ✗ return AVERROR(ENOMEM);
7604 }
7605
7606 5 sc->stereo3d->flags = flags;
7607 /* eyes/stri only records packed vs single-eye, not SBS/TB. Keep a more
7608 * specific type already set by st3d. */
7609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (type != AV_STEREO3D_UNSPEC)
7610 ✗ sc->stereo3d->type = type;
7611
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 else if (sc->stereo3d->type == AV_STEREO3D_2D)
7612 3 sc->stereo3d->type = type;
7613 5 sc->stereo3d->view = view;
7614 5 sc->stereo3d->primary_eye = primary_eye;
7615 5 sc->stereo3d->baseline = baseline;
7616 5 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
7617
7618 5 return 0;
7619 }
7620
7621 5 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7622 {
7623 int size;
7624 int64_t remaining;
7625 uint32_t tag;
7626
7627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
7628 ✗ return 0;
7629
7630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (atom.size < 8) {
7631 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
7632 ✗ return AVERROR_INVALIDDATA;
7633 }
7634
7635 5 remaining = atom.size;
7636
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5 times.
13 while (remaining > 0) {
7637 8 size = avio_rb32(pb);
7638
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 ) {
7639 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
7640 ✗ return AVERROR_INVALIDDATA;
7641 }
7642
7643 8 tag = avio_rl32(pb);
7644
2/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 switch (tag) {
7645 3 case MKTAG('p','r','o','j'): {
7646 3 MOVAtom proj = { tag, size - 8 };
7647 3 int ret = mov_read_vexu_proj(c, pb, proj);
7648
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7649 ✗ return ret;
7650 3 break;
7651 }
7652 5 case MKTAG('e','y','e','s'): {
7653 5 MOVAtom eyes = { tag, size - 8 };
7654 5 int ret = mov_read_eyes(c, pb, eyes);
7655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
7656 ✗ return ret;
7657 5 break;
7658 }
7659 ✗ case MKTAG('p','a','c','k'): {
7660 ✗ MOVAtom pack = { tag, size - 8 };
7661 ✗ int ret = mov_read_pack(c, pb, pack);
7662 ✗ if (ret < 0)
7663 ✗ return ret;
7664 ✗ break;
7665 }
7666 ✗ default:
7667 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: %s\n",
7668 ✗ av_fourcc2str(tag));
7669 ✗ avio_skip(pb, size - 8);
7670 ✗ break;
7671 }
7672 8 remaining -= size;
7673 }
7674
7675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (remaining != 0) {
7676 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7677 ✗ return AVERROR_INVALIDDATA;
7678 }
7679
7680 5 return 0;
7681 }
7682
7683 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7684 {
7685 AVStream *st;
7686 MOVStreamContext *sc;
7687
7688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7689 ✗ return 0;
7690
7691 3 st = c->fc->streams[c->fc->nb_streams - 1];
7692 3 sc = st->priv_data;
7693
7694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7695 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7696 ✗ return AVERROR_INVALIDDATA;
7697 }
7698
7699
7700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7701 ✗ sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7702 ✗ if (!sc->stereo3d)
7703 ✗ return AVERROR(ENOMEM);
7704 }
7705
7706 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7707 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7708
7709 3 return 0;
7710 }
7711
7712 ✗ static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7713 {
7714 ✗ int ret = 0;
7715 ✗ uint8_t *buffer = av_malloc(len + 1);
7716 const char *val;
7717
7718 ✗ if (!buffer)
7719 ✗ return AVERROR(ENOMEM);
7720 ✗ buffer[len] = '\0';
7721
7722 ✗ ret = ffio_read_size(pb, buffer, len);
7723 ✗ if (ret < 0)
7724 ✗ goto out;
7725
7726 /* Check for mandatory keys and values, try to support XML as best-effort */
7727 ✗ if (!sc->spherical &&
7728 ✗ av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7729 ✗ (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7730 ✗ av_stristr(val, "true") &&
7731 ✗ (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7732 ✗ av_stristr(val, "true") &&
7733 ✗ (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7734 ✗ av_stristr(val, "equirectangular")) {
7735 ✗ sc->spherical = av_spherical_alloc(&sc->spherical_size);
7736 ✗ if (!sc->spherical)
7737 ✗ goto out;
7738
7739 ✗ sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7740
7741 ✗ if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7742 enum AVStereo3DType mode;
7743
7744 ✗ if (av_stristr(buffer, "left-right"))
7745 ✗ mode = AV_STEREO3D_SIDEBYSIDE;
7746 ✗ else if (av_stristr(buffer, "top-bottom"))
7747 ✗ mode = AV_STEREO3D_TOPBOTTOM;
7748 else
7749 ✗ mode = AV_STEREO3D_2D;
7750
7751 ✗ sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7752 ✗ if (!sc->stereo3d)
7753 ✗ goto out;
7754
7755 ✗ sc->stereo3d->type = mode;
7756 }
7757
7758 /* orientation */
7759 ✗ val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7760 ✗ if (val)
7761 ✗ sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7762 ✗ val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7763 ✗ if (val)
7764 ✗ sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7765 ✗ val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7766 ✗ if (val)
7767 ✗ sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7768 }
7769
7770 ✗ out:
7771 ✗ av_free(buffer);
7772 ✗ return ret;
7773 }
7774
7775 69 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7776 {
7777 AVStream *st;
7778 MOVStreamContext *sc;
7779 int64_t ret;
7780 AVUUID uuid;
7781 static const AVUUID uuid_isml_manifest = {
7782 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7783 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7784 };
7785 static const AVUUID uuid_xmp = {
7786 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7787 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7788 };
7789 static const AVUUID uuid_spherical = {
7790 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7791 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7792 };
7793
7794
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))
7795 ✗ return AVERROR_INVALIDDATA;
7796
7797
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 66 times.
69 if (c->fc->nb_streams < 1)
7798 3 return 0;
7799 66 st = c->fc->streams[c->fc->nb_streams - 1];
7800 66 sc = st->priv_data;
7801
7802 66 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
7804 ✗ return ret;
7805
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7806 uint8_t *buffer, *ptr;
7807 char *endptr;
7808 ✗ size_t len = atom.size - AV_UUID_LEN;
7809
7810 ✗ if (len < 4) {
7811 ✗ return AVERROR_INVALIDDATA;
7812 }
7813 ✗ ret = avio_skip(pb, 4); // zeroes
7814 ✗ len -= 4;
7815
7816 ✗ buffer = av_mallocz(len + 1);
7817 ✗ if (!buffer) {
7818 ✗ return AVERROR(ENOMEM);
7819 }
7820 ✗ ret = ffio_read_size(pb, buffer, len);
7821 ✗ if (ret < 0) {
7822 ✗ av_free(buffer);
7823 ✗ return ret;
7824 }
7825
7826 ✗ ptr = buffer;
7827 ✗ while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7828 ✗ ptr += sizeof("systemBitrate=\"") - 1;
7829 ✗ c->bitrates_count++;
7830 ✗ c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7831 ✗ if (!c->bitrates) {
7832 ✗ c->bitrates_count = 0;
7833 ✗ av_free(buffer);
7834 ✗ return AVERROR(ENOMEM);
7835 }
7836 ✗ errno = 0;
7837 ✗ ret = strtol(ptr, &endptr, 10);
7838 ✗ if (ret < 0 || errno || *endptr != '"') {
7839 ✗ c->bitrates[c->bitrates_count - 1] = 0;
7840 } else {
7841 ✗ c->bitrates[c->bitrates_count - 1] = ret;
7842 }
7843 }
7844
7845 ✗ av_free(buffer);
7846
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7847 uint8_t *buffer;
7848 ✗ size_t len = atom.size - AV_UUID_LEN;
7849 ✗ if (c->export_xmp) {
7850 ✗ buffer = av_mallocz(len + 1);
7851 ✗ if (!buffer) {
7852 ✗ return AVERROR(ENOMEM);
7853 }
7854 ✗ ret = ffio_read_size(pb, buffer, len);
7855 ✗ if (ret < 0) {
7856 ✗ av_free(buffer);
7857 ✗ return ret;
7858 }
7859 ✗ buffer[len] = '\0';
7860 ✗ av_dict_set(&c->fc->metadata, "xmp",
7861 buffer, AV_DICT_DONT_STRDUP_VAL);
7862 } else {
7863 // skip all uuid atom, which makes it fast for long uuid-xmp file
7864 ✗ ret = avio_skip(pb, len);
7865 ✗ if (ret < 0)
7866 ✗ return ret;
7867 }
7868
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7869 ✗ size_t len = atom.size - AV_UUID_LEN;
7870 ✗ ret = mov_parse_uuid_spherical(sc, pb, len);
7871 ✗ if (ret < 0)
7872 ✗ return ret;
7873 ✗ if (!sc->spherical)
7874 ✗ av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7875 }
7876
7877 66 return 0;
7878 }
7879
7880 265 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7881 {
7882 int ret;
7883 uint8_t content[16];
7884
7885
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 118 times.
265 if (atom.size < 8)
7886 147 return 0;
7887
7888 118 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7889
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (ret < 0)
7890 ✗ return ret;
7891
7892
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 73 times.
118 if ( !c->found_moov
7893
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 23 times.
45 && !c->found_mdat
7894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 && !memcmp(content, "Anevia\x1A\x1A", 8)
7895 ✗ && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7896 ✗ c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7897 }
7898
7899 118 return 0;
7900 }
7901
7902 42 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7903 {
7904 42 uint32_t format = avio_rl32(pb);
7905 MOVStreamContext *sc;
7906 enum AVCodecID id;
7907 AVStream *st;
7908
7909
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (c->fc->nb_streams < 1)
7910 ✗ return 0;
7911 42 st = c->fc->streams[c->fc->nb_streams - 1];
7912 42 sc = st->priv_data;
7913
7914
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 31 times.
42 switch (sc->format)
7915 {
7916 11 case MKTAG('e','n','c','v'): // encrypted video
7917 case MKTAG('e','n','c','a'): // encrypted audio
7918 11 id = mov_codec_id(st, format);
7919
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7920 ✗ st->codecpar->codec_id != id) {
7921 ✗ av_log(c->fc, AV_LOG_WARNING,
7922 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7923 ✗ (char*)&format, st->codecpar->codec_id);
7924 ✗ break;
7925 }
7926
7927 11 st->codecpar->codec_id = id;
7928 11 sc->format = format;
7929 11 break;
7930
7931 31 default:
7932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (format != sc->format) {
7933 ✗ av_log(c->fc, AV_LOG_WARNING,
7934 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7935 ✗ (char*)&format, (char*)&sc->format);
7936 }
7937 31 break;
7938 }
7939
7940 42 return 0;
7941 }
7942
7943 /**
7944 * Gets the current encryption info and associated current stream context. If
7945 * we are parsing a track fragment, this will return the specific encryption
7946 * info for this fragment; otherwise this will return the global encryption
7947 * info for the current stream.
7948 */
7949 27 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7950 {
7951 MOVFragmentStreamInfo *frag_stream_info;
7952 AVStream *st;
7953 int i;
7954
7955 27 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7956
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 21 times.
27 if (frag_stream_info) {
7957
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 for (i = 0; i < c->fc->nb_streams; i++) {
7958 6 *sc = c->fc->streams[i]->priv_data;
7959
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if ((*sc)->id == frag_stream_info->id) {
7960 6 st = c->fc->streams[i];
7961 6 break;
7962 }
7963 }
7964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (i == c->fc->nb_streams)
7965 ✗ return 0;
7966 6 *sc = st->priv_data;
7967
7968
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (!frag_stream_info->encryption_index) {
7969 // If this stream isn't encrypted, don't create the index.
7970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(*sc)->cenc.default_encrypted_sample)
7971 ✗ return 0;
7972 2 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7973
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!frag_stream_info->encryption_index)
7974 ✗ return AVERROR(ENOMEM);
7975 }
7976 6 *encryption_index = frag_stream_info->encryption_index;
7977 6 return 1;
7978 } else {
7979 // No current track fragment, using stream level encryption info.
7980
7981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (c->fc->nb_streams < 1)
7982 ✗ return 0;
7983 21 st = c->fc->streams[c->fc->nb_streams - 1];
7984 21 *sc = st->priv_data;
7985
7986
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!(*sc)->cenc.encryption_index) {
7987 // If this stream isn't encrypted, don't create the index.
7988 ✗ if (!(*sc)->cenc.default_encrypted_sample)
7989 ✗ return 0;
7990 ✗ (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7991 ✗ if (!(*sc)->cenc.encryption_index)
7992 ✗ return AVERROR(ENOMEM);
7993 }
7994
7995 21 *encryption_index = (*sc)->cenc.encryption_index;
7996 21 return 1;
7997 }
7998 }
7999
8000 195 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
8001 {
8002 int i, ret;
8003 unsigned int subsample_count;
8004 AVSubsampleEncryptionInfo *subsamples;
8005
8006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!sc->cenc.default_encrypted_sample) {
8007 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
8008 ✗ return AVERROR_INVALIDDATA;
8009 }
8010
8011
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) {
8012 195 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
8013
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*sample)
8014 ✗ return AVERROR(ENOMEM);
8015 } else
8016 ✗ *sample = NULL;
8017
8018
1/2
✓ Branch 0 taken 195 times.
✗ Branch 1 not taken.
195 if (sc->cenc.per_sample_iv_size != 0) {
8019
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) {
8020 ✗ av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
8021 ✗ av_encryption_info_free(*sample);
8022 ✗ *sample = NULL;
8023 ✗ return ret;
8024 }
8025 }
8026
8027
1/2
✓ Branch 0 taken 195 times.
✗ Branch 1 not taken.
195 if (use_subsamples) {
8028 195 subsample_count = avio_rb16(pb);
8029 195 av_free((*sample)->subsamples);
8030 195 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
8031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!(*sample)->subsamples) {
8032 ✗ av_encryption_info_free(*sample);
8033 ✗ *sample = NULL;
8034 ✗ return AVERROR(ENOMEM);
8035 }
8036
8037
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++) {
8038 272 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
8039 272 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
8040 }
8041
8042
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (pb->eof_reached) {
8043 ✗ av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
8044 ✗ av_encryption_info_free(*sample);
8045 ✗ *sample = NULL;
8046 ✗ return AVERROR_INVALIDDATA;
8047 }
8048 195 (*sample)->subsample_count = subsample_count;
8049 }
8050
8051 195 return 0;
8052 }
8053
8054 9 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8055 {
8056 AVEncryptionInfo **encrypted_samples;
8057 MOVEncryptionIndex *encryption_index;
8058 MOVStreamContext *sc;
8059 int use_subsamples, ret;
8060 9 unsigned int sample_count, i, alloc_size = 0;
8061
8062 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8064 ✗ return ret;
8065
8066
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (encryption_index->nb_encrypted_samples) {
8067 // This can happen if we have both saio/saiz and senc atoms.
8068 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
8069 2 return 0;
8070 }
8071
8072 7 avio_r8(pb); /* version */
8073 7 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
8074
8075 7 sample_count = avio_rb32(pb);
8076
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
8077 ✗ return AVERROR(ENOMEM);
8078
8079
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 7 times.
154 for (i = 0; i < sample_count; i++) {
8080 147 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
8081 147 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
8082 min_samples * sizeof(*encrypted_samples));
8083
1/2
✓ Branch 0 taken 147 times.
✗ Branch 1 not taken.
147 if (encrypted_samples) {
8084 147 encryption_index->encrypted_samples = encrypted_samples;
8085
8086 147 ret = mov_read_sample_encryption_info(
8087 147 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
8088 } else {
8089 ✗ ret = AVERROR(ENOMEM);
8090 }
8091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
147 if (pb->eof_reached) {
8092 ✗ av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
8093 ✗ if (ret >= 0)
8094 ✗ av_encryption_info_free(encryption_index->encrypted_samples[i]);
8095 ✗ ret = AVERROR_INVALIDDATA;
8096 }
8097
8098
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
147 if (ret < 0) {
8099 ✗ for (; i > 0; i--)
8100 ✗ av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
8101 ✗ av_freep(&encryption_index->encrypted_samples);
8102 ✗ return ret;
8103 }
8104 }
8105 7 encryption_index->nb_encrypted_samples = sample_count;
8106
8107 7 return 0;
8108 }
8109
8110 2 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
8111 {
8112 AVEncryptionInfo **sample, **encrypted_samples;
8113 int64_t prev_pos;
8114 size_t sample_count, sample_info_size, i;
8115 2 int ret = 0;
8116 2 unsigned int alloc_size = 0;
8117
8118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->nb_encrypted_samples)
8119 ✗ return 0;
8120 2 sample_count = encryption_index->auxiliary_info_sample_count;
8121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count != 1) {
8122 ✗ av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
8123 ✗ return AVERROR_PATCHWELCOME;
8124 }
8125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
8126 ✗ return AVERROR(ENOMEM);
8127
8128 2 prev_pos = avio_tell(pb);
8129
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
8130
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]) {
8131 ✗ av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
8132 ✗ goto finish;
8133 }
8134
8135
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++) {
8136 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
8137 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
8138 min_samples * sizeof(*encrypted_samples));
8139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (!encrypted_samples) {
8140 ✗ ret = AVERROR(ENOMEM);
8141 ✗ goto finish;
8142 }
8143 48 encryption_index->encrypted_samples = encrypted_samples;
8144
8145 48 sample = &encryption_index->encrypted_samples[i];
8146 96 sample_info_size = encryption_index->auxiliary_info_default_size
8147 48 ? encryption_index->auxiliary_info_default_size
8148
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 : encryption_index->auxiliary_info_sizes[i];
8149
8150 48 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
8151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0)
8152 ✗ goto finish;
8153 }
8154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
8155 ✗ av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
8156 ✗ ret = AVERROR_INVALIDDATA;
8157 } else {
8158 2 encryption_index->nb_encrypted_samples = sample_count;
8159 }
8160
8161 2 finish:
8162 2 avio_seek(pb, prev_pos, SEEK_SET);
8163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
8164 ✗ for (; i > 0; i--) {
8165 ✗ av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
8166 }
8167 ✗ av_freep(&encryption_index->encrypted_samples);
8168 }
8169 2 return ret;
8170 }
8171
8172 9 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8173 {
8174 MOVEncryptionIndex *encryption_index;
8175 MOVStreamContext *sc;
8176 int ret;
8177 unsigned int sample_count, aux_info_type, aux_info_param;
8178
8179 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8181 ✗ return ret;
8182
8183
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (encryption_index->nb_encrypted_samples) {
8184 // This can happen if we have both saio/saiz and senc atoms.
8185 7 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
8186 7 return 0;
8187 }
8188
8189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_sample_count) {
8190 ✗ av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
8191 ✗ return AVERROR_INVALIDDATA;
8192 }
8193
8194 2 avio_r8(pb); /* version */
8195
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
8196 ✗ aux_info_type = avio_rb32(pb);
8197 ✗ aux_info_param = avio_rb32(pb);
8198 ✗ if (sc->cenc.default_encrypted_sample) {
8199 ✗ if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
8200 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
8201 ✗ return 0;
8202 }
8203 ✗ if (aux_info_param != 0) {
8204 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
8205 ✗ return 0;
8206 }
8207 } else {
8208 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8209 ✗ if ((aux_info_type == MKBETAG('c','e','n','c') ||
8210 ✗ aux_info_type == MKBETAG('c','e','n','s') ||
8211 ✗ aux_info_type == MKBETAG('c','b','c','1') ||
8212 ✗ aux_info_type == MKBETAG('c','b','c','s')) &&
8213 aux_info_param == 0) {
8214 ✗ av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
8215 ✗ return AVERROR_INVALIDDATA;
8216 } else {
8217 ✗ return 0;
8218 }
8219 }
8220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
8221 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8222 ✗ return 0;
8223 }
8224
8225 2 encryption_index->auxiliary_info_default_size = avio_r8(pb);
8226 2 sample_count = avio_rb32(pb);
8227
8228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_default_size == 0) {
8229 ✗ if (sample_count == 0)
8230 ✗ return AVERROR_INVALIDDATA;
8231
8232 ✗ encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
8233 ✗ if (!encryption_index->auxiliary_info_sizes)
8234 ✗ return AVERROR(ENOMEM);
8235
8236 ✗ ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
8237 ✗ if (ret != sample_count) {
8238 ✗ av_freep(&encryption_index->auxiliary_info_sizes);
8239
8240 ✗ if (ret >= 0)
8241 ✗ ret = AVERROR_INVALIDDATA;
8242 ✗ av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
8243 ✗ av_err2str(ret));
8244 ✗ return ret;
8245 }
8246 }
8247 2 encryption_index->auxiliary_info_sample_count = sample_count;
8248
8249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
8250 ✗ return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
8251 }
8252
8253 2 return 0;
8254 }
8255
8256 9 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8257 {
8258 uint64_t *auxiliary_offsets;
8259 MOVEncryptionIndex *encryption_index;
8260 MOVStreamContext *sc;
8261 int i, ret;
8262 unsigned int version, entry_count, aux_info_type, aux_info_param;
8263 9 unsigned int alloc_size = 0;
8264
8265 9 ret = get_current_encryption_info(c, &encryption_index, &sc);
8266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret != 1)
8267 ✗ return ret;
8268
8269
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (encryption_index->nb_encrypted_samples) {
8270 // This can happen if we have both saio/saiz and senc atoms.
8271 7 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
8272 7 return 0;
8273 }
8274
8275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
8276 ✗ av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
8277 ✗ return AVERROR_INVALIDDATA;
8278 }
8279
8280 2 version = avio_r8(pb); /* version */
8281
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
8282 ✗ aux_info_type = avio_rb32(pb);
8283 ✗ aux_info_param = avio_rb32(pb);
8284 ✗ if (sc->cenc.default_encrypted_sample) {
8285 ✗ if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
8286 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
8287 ✗ return 0;
8288 }
8289 ✗ if (aux_info_param != 0) {
8290 ✗ av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
8291 ✗ return 0;
8292 }
8293 } else {
8294 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8295 ✗ if ((aux_info_type == MKBETAG('c','e','n','c') ||
8296 ✗ aux_info_type == MKBETAG('c','e','n','s') ||
8297 ✗ aux_info_type == MKBETAG('c','b','c','1') ||
8298 ✗ aux_info_type == MKBETAG('c','b','c','s')) &&
8299 aux_info_param == 0) {
8300 ✗ av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
8301 ✗ return AVERROR_INVALIDDATA;
8302 } else {
8303 ✗ return 0;
8304 }
8305 }
8306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
8307 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8308 ✗ return 0;
8309 }
8310
8311 2 entry_count = avio_rb32(pb);
8312
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
8313 ✗ return AVERROR(ENOMEM);
8314
8315
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++) {
8316
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);
8317 2 auxiliary_offsets = av_fast_realloc(
8318 2 encryption_index->auxiliary_offsets, &alloc_size,
8319 min_offsets * sizeof(*auxiliary_offsets));
8320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!auxiliary_offsets) {
8321 ✗ av_freep(&encryption_index->auxiliary_offsets);
8322 ✗ return AVERROR(ENOMEM);
8323 }
8324 2 encryption_index->auxiliary_offsets = auxiliary_offsets;
8325
8326
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version == 0) {
8327 2 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
8328 } else {
8329 ✗ encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
8330 }
8331
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (c->frag_index.current >= 0) {
8332 2 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
8333 }
8334 }
8335
8336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
8337 ✗ av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
8338 ✗ av_freep(&encryption_index->auxiliary_offsets);
8339 ✗ return AVERROR_INVALIDDATA;
8340 }
8341
8342 2 encryption_index->auxiliary_offsets_count = entry_count;
8343
8344
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (encryption_index->auxiliary_info_sample_count) {
8345 2 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
8346 }
8347
8348 ✗ return 0;
8349 }
8350
8351 4 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8352 {
8353 AVEncryptionInitInfo *info, *old_init_info;
8354 uint8_t **key_ids;
8355 AVStream *st;
8356 const AVPacketSideData *old_side_data;
8357 uint8_t *side_data, *extra_data;
8358 size_t side_data_size;
8359 4 int ret = 0;
8360 4 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
8361
8362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8363 ✗ return 0;
8364 4 st = c->fc->streams[c->fc->nb_streams-1];
8365
8366 4 version = avio_r8(pb); /* version */
8367 4 avio_rb24(pb); /* flags */
8368
8369 4 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
8370 /* key_id_size */ 16, /* data_size */ 0);
8371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info)
8372 ✗ return AVERROR(ENOMEM);
8373
8374
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
8375 ✗ av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
8376 ✗ goto finish;
8377 }
8378
8379
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (version > 0) {
8380 4 kid_count = avio_rb32(pb);
8381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
8382 ✗ ret = AVERROR(ENOMEM);
8383 ✗ goto finish;
8384 }
8385
8386
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++) {
8387 4 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
8388 4 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
8389 min_kid_count * sizeof(*key_ids));
8390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!key_ids) {
8391 ✗ ret = AVERROR(ENOMEM);
8392 ✗ goto finish;
8393 }
8394 4 info->key_ids = key_ids;
8395
8396 4 info->key_ids[i] = av_mallocz(16);
8397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info->key_ids[i]) {
8398 ✗ ret = AVERROR(ENOMEM);
8399 ✗ goto finish;
8400 }
8401 4 info->num_key_ids = i + 1;
8402
8403
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
8404 ✗ av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
8405 ✗ goto finish;
8406 }
8407 }
8408
8409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pb->eof_reached) {
8410 ✗ av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
8411 ✗ ret = AVERROR_INVALIDDATA;
8412 ✗ goto finish;
8413 }
8414 }
8415
8416 4 extra_data_size = avio_rb32(pb);
8417 4 extra_data = av_malloc(extra_data_size);
8418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!extra_data) {
8419 ✗ ret = AVERROR(ENOMEM);
8420 ✗ goto finish;
8421 }
8422 4 ret = avio_read(pb, extra_data, extra_data_size);
8423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != extra_data_size) {
8424 ✗ av_free(extra_data);
8425
8426 ✗ if (ret >= 0)
8427 ✗ ret = AVERROR_INVALIDDATA;
8428 ✗ goto finish;
8429 }
8430
8431 4 av_freep(&info->data); // malloc(0) may still allocate something.
8432 4 info->data = extra_data;
8433 4 info->data_size = extra_data_size;
8434
8435 // If there is existing initialization data, append to the list.
8436 4 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
8437 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
8438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (old_side_data) {
8439 ✗ old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
8440 ✗ if (old_init_info) {
8441 // Append to the end of the list.
8442 ✗ for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
8443 ✗ if (!cur->next) {
8444 ✗ cur->next = info;
8445 ✗ break;
8446 }
8447 }
8448 ✗ info = old_init_info;
8449 } else {
8450 // Assume existing side-data will be valid, so the only error we could get is OOM.
8451 ✗ ret = AVERROR(ENOMEM);
8452 ✗ goto finish;
8453 }
8454 }
8455
8456 4 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
8457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!side_data) {
8458 ✗ ret = AVERROR(ENOMEM);
8459 ✗ goto finish;
8460 }
8461
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
8462 4 &st->codecpar->nb_coded_side_data,
8463 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
8464 side_data, side_data_size, 0))
8465 ✗ av_free(side_data);
8466
8467 4 finish:
8468 4 av_encryption_init_info_free(info);
8469 4 return ret;
8470 }
8471
8472 11 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8473 {
8474 AVStream *st;
8475 MOVStreamContext *sc;
8476
8477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
8478 ✗ return 0;
8479 11 st = c->fc->streams[c->fc->nb_streams-1];
8480 11 sc = st->priv_data;
8481
8482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (sc->pseudo_stream_id != 0) {
8483 ✗ av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
8484 ✗ return AVERROR_PATCHWELCOME;
8485 }
8486
8487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
8488 ✗ return AVERROR_INVALIDDATA;
8489
8490 11 avio_rb32(pb); /* version and flags */
8491
8492
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (!sc->cenc.default_encrypted_sample) {
8493 11 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.default_encrypted_sample) {
8495 ✗ return AVERROR(ENOMEM);
8496 }
8497 }
8498
8499 11 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
8500 11 return 0;
8501 }
8502
8503 11 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8504 {
8505 AVStream *st;
8506 MOVStreamContext *sc;
8507 unsigned int version, pattern, is_protected, iv_size;
8508
8509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
8510 ✗ return 0;
8511 11 st = c->fc->streams[c->fc->nb_streams-1];
8512 11 sc = st->priv_data;
8513
8514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (sc->pseudo_stream_id != 0) {
8515 ✗ av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
8516 ✗ return AVERROR_PATCHWELCOME;
8517 }
8518
8519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.default_encrypted_sample) {
8520 ✗ sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8521 ✗ if (!sc->cenc.default_encrypted_sample) {
8522 ✗ return AVERROR(ENOMEM);
8523 }
8524 }
8525
8526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 20)
8527 ✗ return AVERROR_INVALIDDATA;
8528
8529 11 version = avio_r8(pb); /* version */
8530 11 avio_rb24(pb); /* flags */
8531
8532 11 avio_r8(pb); /* reserved */
8533 11 pattern = avio_r8(pb);
8534
8535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (version > 0) {
8536 ✗ sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
8537 ✗ sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
8538 }
8539
8540 11 is_protected = avio_r8(pb);
8541
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) {
8542 // The whole stream should be by-default encrypted.
8543 11 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
8544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.encryption_index)
8545 ✗ return AVERROR(ENOMEM);
8546 }
8547 11 iv_size = avio_r8(pb);
8548
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) {
8549 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
8550 ✗ return AVERROR_INVALIDDATA;
8551 }
8552 11 sc->cenc.per_sample_iv_size = iv_size;
8553
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) {
8554 ✗ av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
8555 ✗ return AVERROR_INVALIDDATA;
8556 }
8557
8558
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) {
8559 2 iv_size = avio_r8(pb);
8560
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) {
8561 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
8562 ✗ return AVERROR_INVALIDDATA;
8563 }
8564
8565
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) {
8566 ✗ av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
8567 ✗ return AVERROR_INVALIDDATA;
8568 }
8569 }
8570
8571 11 return 0;
8572 }
8573
8574 ✗ static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8575 {
8576 AVStream *st;
8577 int last, type, size, ret;
8578 uint8_t buf[4];
8579
8580 ✗ if (c->fc->nb_streams < 1)
8581 ✗ return 0;
8582 ✗ st = c->fc->streams[c->fc->nb_streams-1];
8583
8584 ✗ if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
8585 ✗ return AVERROR_INVALIDDATA;
8586
8587 /* Check FlacSpecificBox version. */
8588 ✗ if (avio_r8(pb) != 0)
8589 ✗ return AVERROR_INVALIDDATA;
8590
8591 ✗ avio_rb24(pb); /* Flags */
8592
8593 ✗ if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
8594 ✗ av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
8595 ✗ return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
8596 }
8597 ✗ flac_parse_block_header(buf, &last, &type, &size);
8598
8599 ✗ if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
8600 ✗ av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
8601 ✗ return AVERROR_INVALIDDATA;
8602 }
8603
8604 ✗ ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
8605 ✗ if (ret < 0)
8606 ✗ return ret;
8607
8608 ✗ if (!last)
8609 ✗ av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
8610
8611 ✗ return 0;
8612 }
8613
8614 11 static int get_key_from_kid(uint8_t* out, int len, MOVContext *c, AVEncryptionInfo *sample) {
8615 AVDictionaryEntry *key_entry_hex;
8616 char kid_hex[16*2+1];
8617
8618
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) {
8619 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid default decryption key length: got %d, expected %d\n", c->decryption_default_key_len, len);
8620 ✗ return -1;
8621 }
8622
8623
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
11 if (!c->decryption_keys) {
8624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 av_assert0(c->decryption_default_key);
8625 8 memcpy(out, c->decryption_default_key, len);
8626 8 return 0;
8627 }
8628
8629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sample->key_id_size != 16) {
8630 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid key ID size: got %u, expected 16\n", sample->key_id_size);
8631 ✗ return -1;
8632 }
8633
8634 3 ff_data_to_hex(kid_hex, sample->key_id, 16, 1);
8635 3 key_entry_hex = av_dict_get(c->decryption_keys, kid_hex, NULL, AV_DICT_DONT_STRDUP_KEY|AV_DICT_DONT_STRDUP_VAL);
8636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!key_entry_hex) {
8637 ✗ if (!c->decryption_default_key) {
8638 ✗ av_log(c->fc, AV_LOG_ERROR, "unable to find KID %s\n", kid_hex);
8639 ✗ return -1;
8640 }
8641 ✗ memcpy(out, c->decryption_default_key, len);
8642 ✗ return 0;
8643 }
8644
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (strlen(key_entry_hex->value) != len*2) {
8645 ✗ return -1;
8646 }
8647 3 ff_hex_to_data(out, key_entry_hex->value);
8648 3 return 0;
8649 }
8650
8651 341 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8652 {
8653 int i, ret;
8654 int bytes_of_protected_data;
8655 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8656
8657
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 330 times.
341 if (!sc->cenc.aes_ctr) {
8658 11 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0) {
8660 ✗ return ret;
8661 }
8662
8663 /* initialize the cipher */
8664 11 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!sc->cenc.aes_ctr) {
8666 ✗ return AVERROR(ENOMEM);
8667 }
8668
8669 11 ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8670
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0) {
8671 ✗ return ret;
8672 }
8673 }
8674
8675 341 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8676
8677
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 245 times.
341 if (!sample->subsample_count) {
8678 /* decrypt the whole packet */
8679 96 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8680 96 return 0;
8681 }
8682
8683
2/2
✓ Branch 0 taken 321 times.
✓ Branch 1 taken 245 times.
566 for (i = 0; i < sample->subsample_count; i++) {
8684
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) {
8685 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8686 ✗ return AVERROR_INVALIDDATA;
8687 }
8688
8689 /* skip the clear bytes */
8690 321 input += sample->subsamples[i].bytes_of_clear_data;
8691 321 size -= sample->subsamples[i].bytes_of_clear_data;
8692
8693 /* decrypt the encrypted bytes */
8694
8695 321 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
8696 321 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
8697
8698 321 input += bytes_of_protected_data;
8699 321 size -= bytes_of_protected_data;
8700 }
8701
8702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
245 if (size > 0) {
8703 ✗ av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8704 ✗ return AVERROR_INVALIDDATA;
8705 }
8706
8707 245 return 0;
8708 }
8709
8710 ✗ static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8711 {
8712 int i, ret;
8713 int num_of_encrypted_blocks;
8714 uint8_t iv[16];
8715 uint8_t decryption_key[16];
8716
8717 ✗ if (!sc->cenc.aes_ctx) {
8718 ✗ ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8719 ✗ if (ret < 0) {
8720 ✗ return ret;
8721 }
8722
8723 /* initialize the cipher */
8724 ✗ sc->cenc.aes_ctx = av_aes_alloc();
8725 ✗ if (!sc->cenc.aes_ctx) {
8726 ✗ return AVERROR(ENOMEM);
8727 }
8728
8729 ✗ ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8730 ✗ if (ret < 0) {
8731 ✗ return ret;
8732 }
8733 }
8734
8735 ✗ memcpy(iv, sample->iv, 16);
8736
8737 /* whole-block full sample encryption */
8738 ✗ if (!sample->subsample_count) {
8739 /* decrypt the whole packet */
8740 ✗ av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8741 ✗ return 0;
8742 }
8743
8744 ✗ for (i = 0; i < sample->subsample_count; i++) {
8745 ✗ if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8746 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8747 ✗ return AVERROR_INVALIDDATA;
8748 }
8749
8750 ✗ if (sample->subsamples[i].bytes_of_protected_data % 16) {
8751 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8752 ✗ return AVERROR_INVALIDDATA;
8753 }
8754
8755 /* skip the clear bytes */
8756 ✗ input += sample->subsamples[i].bytes_of_clear_data;
8757 ✗ size -= sample->subsamples[i].bytes_of_clear_data;
8758
8759 /* decrypt the encrypted bytes */
8760 ✗ num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8761 ✗ if (num_of_encrypted_blocks > 0) {
8762 ✗ av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8763 }
8764 ✗ input += sample->subsamples[i].bytes_of_protected_data;
8765 ✗ size -= sample->subsamples[i].bytes_of_protected_data;
8766 }
8767
8768 ✗ if (size > 0) {
8769 ✗ av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8770 ✗ return AVERROR_INVALIDDATA;
8771 }
8772
8773 ✗ return 0;
8774 }
8775
8776 ✗ static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8777 {
8778 int i, ret, rem_bytes;
8779 uint8_t *data;
8780 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8781
8782 ✗ if (!sc->cenc.aes_ctr) {
8783 ✗ ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8784 ✗ if (ret < 0) {
8785 ✗ return ret;
8786 }
8787
8788 /* initialize the cipher */
8789 ✗ sc->cenc.aes_ctr = av_aes_ctr_alloc();
8790 ✗ if (!sc->cenc.aes_ctr) {
8791 ✗ return AVERROR(ENOMEM);
8792 }
8793
8794 ✗ ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8795 ✗ if (ret < 0) {
8796 ✗ return ret;
8797 }
8798 }
8799
8800 ✗ av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8801
8802 /* whole-block full sample encryption */
8803 ✗ if (!sample->subsample_count) {
8804 /* decrypt the whole packet */
8805 ✗ av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8806 ✗ return 0;
8807 ✗ } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8808 ✗ av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8809 ✗ return AVERROR_INVALIDDATA;
8810 }
8811
8812 ✗ for (i = 0; i < sample->subsample_count; i++) {
8813 ✗ if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8814 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8815 ✗ return AVERROR_INVALIDDATA;
8816 }
8817
8818 /* skip the clear bytes */
8819 ✗ input += sample->subsamples[i].bytes_of_clear_data;
8820 ✗ size -= sample->subsamples[i].bytes_of_clear_data;
8821
8822 /* decrypt the encrypted bytes */
8823 ✗ data = input;
8824 ✗ rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8825 ✗ while (rem_bytes > 0) {
8826 ✗ if (rem_bytes < 16*sample->crypt_byte_block) {
8827 ✗ break;
8828 }
8829 ✗ av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8830 ✗ data += 16*sample->crypt_byte_block;
8831 ✗ rem_bytes -= 16*sample->crypt_byte_block;
8832 ✗ data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8833 ✗ rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8834 }
8835 ✗ input += sample->subsamples[i].bytes_of_protected_data;
8836 ✗ size -= sample->subsamples[i].bytes_of_protected_data;
8837 }
8838
8839 ✗ if (size > 0) {
8840 ✗ av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8841 ✗ return AVERROR_INVALIDDATA;
8842 }
8843
8844 ✗ return 0;
8845 }
8846
8847 ✗ static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8848 {
8849 int i, ret, rem_bytes;
8850 uint8_t iv[16];
8851 uint8_t *data;
8852 uint8_t decryption_key[16];
8853
8854 ✗ if (!sc->cenc.aes_ctx) {
8855 ✗ ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8856 ✗ if (ret < 0) {
8857 ✗ return ret;
8858 }
8859
8860 /* initialize the cipher */
8861 ✗ sc->cenc.aes_ctx = av_aes_alloc();
8862 ✗ if (!sc->cenc.aes_ctx) {
8863 ✗ return AVERROR(ENOMEM);
8864 }
8865
8866 ✗ ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8867 ✗ if (ret < 0) {
8868 ✗ return ret;
8869 }
8870 }
8871
8872 /* whole-block full sample encryption */
8873 ✗ if (!sample->subsample_count) {
8874 /* decrypt the whole packet */
8875 ✗ memcpy(iv, sample->iv, 16);
8876 ✗ av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8877 ✗ return 0;
8878 ✗ } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8879 ✗ av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8880 ✗ return AVERROR_INVALIDDATA;
8881 }
8882
8883 ✗ for (i = 0; i < sample->subsample_count; i++) {
8884 ✗ if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8885 ✗ av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8886 ✗ return AVERROR_INVALIDDATA;
8887 }
8888
8889 /* skip the clear bytes */
8890 ✗ input += sample->subsamples[i].bytes_of_clear_data;
8891 ✗ size -= sample->subsamples[i].bytes_of_clear_data;
8892
8893 /* decrypt the encrypted bytes */
8894 ✗ memcpy(iv, sample->iv, 16);
8895 ✗ data = input;
8896 ✗ rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8897 ✗ while (rem_bytes > 0) {
8898 ✗ if (rem_bytes < 16*sample->crypt_byte_block) {
8899 ✗ break;
8900 }
8901 ✗ av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8902 ✗ data += 16*sample->crypt_byte_block;
8903 ✗ rem_bytes -= 16*sample->crypt_byte_block;
8904 ✗ data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8905 ✗ rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8906 }
8907 ✗ input += sample->subsamples[i].bytes_of_protected_data;
8908 ✗ size -= sample->subsamples[i].bytes_of_protected_data;
8909 }
8910
8911 ✗ if (size > 0) {
8912 ✗ av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8913 ✗ return AVERROR_INVALIDDATA;
8914 }
8915
8916 ✗ return 0;
8917 }
8918
8919 341 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8920 {
8921
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) {
8922 341 return cenc_scheme_decrypt(c, sc, sample, input, size);
8923 ✗ } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8924 ✗ return cbc1_scheme_decrypt(c, sc, sample, input, size);
8925 ✗ } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8926 ✗ return cens_scheme_decrypt(c, sc, sample, input, size);
8927 ✗ } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8928 ✗ return cbcs_scheme_decrypt(c, sc, sample, input, size);
8929 } else {
8930 ✗ av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8931 ✗ return AVERROR_INVALIDDATA;
8932 }
8933 }
8934
8935 111615 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8936 {
8937 111615 int current = frag_index->current;
8938
8939
2/2
✓ Branch 0 taken 107817 times.
✓ Branch 1 taken 3798 times.
111615 if (!frag_index->nb_items)
8940 107817 return NULL;
8941
8942 // Check frag_index->current is the right one for pkt. It can out of sync.
8943
2/4
✓ Branch 0 taken 3798 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3798 times.
✗ Branch 3 not taken.
3798 if (current >= 0 && current < frag_index->nb_items) {
8944
2/2
✓ Branch 0 taken 3770 times.
✓ Branch 1 taken 28 times.
3798 if (frag_index->item[current].moof_offset < pkt->pos &&
8945
2/2
✓ Branch 0 taken 611 times.
✓ Branch 1 taken 3159 times.
3770 (current + 1 == frag_index->nb_items ||
8946
2/2
✓ Branch 0 taken 534 times.
✓ Branch 1 taken 77 times.
611 frag_index->item[current + 1].moof_offset > pkt->pos))
8947 3693 return get_frag_stream_info(frag_index, current, id);
8948 }
8949
8950
8951
2/2
✓ Branch 0 taken 4561 times.
✓ Branch 1 taken 10 times.
4571 for (int i = 0; i < frag_index->nb_items; i++) {
8952
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 4466 times.
4561 if (frag_index->item[i].moof_offset > pkt->pos)
8953 95 break;
8954 4466 current = i;
8955 }
8956 105 frag_index->current = current;
8957 105 return get_frag_stream_info(frag_index, current, id);
8958 }
8959
8960 111615 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8961 {
8962 MOVFragmentStreamInfo *frag_stream_info;
8963 MOVEncryptionIndex *encryption_index;
8964 AVEncryptionInfo *encrypted_sample;
8965 int encrypted_index, ret;
8966
8967 111615 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8968 111615 encrypted_index = current_index;
8969 111615 encryption_index = NULL;
8970
2/2
✓ Branch 0 taken 3798 times.
✓ Branch 1 taken 107817 times.
111615 if (frag_stream_info) {
8971 // Note this only supports encryption info in the first sample descriptor.
8972
2/2
✓ Branch 0 taken 3750 times.
✓ Branch 1 taken 48 times.
3798 if (frag_stream_info->stsd_id == 1) {
8973
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3702 times.
3750 if (frag_stream_info->encryption_index) {
8974 48 encrypted_index = current_index - frag_stream_info->index_base;
8975 48 encryption_index = frag_stream_info->encryption_index;
8976 } else {
8977 3702 encryption_index = sc->cenc.encryption_index;
8978 }
8979 }
8980 } else {
8981 107817 encryption_index = sc->cenc.encryption_index;
8982 }
8983
8984
2/2
✓ Branch 0 taken 341 times.
✓ Branch 1 taken 111274 times.
111615 if (encryption_index) {
8985
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 293 times.
341 if (encryption_index->auxiliary_info_sample_count &&
8986
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8987 ✗ av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8988 ✗ return AVERROR_INVALIDDATA;
8989 }
8990
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 293 times.
341 if (encryption_index->auxiliary_offsets_count &&
8991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8992 ✗ av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8993 ✗ return AVERROR_INVALIDDATA;
8994 }
8995
8996 341 encrypted_sample = NULL;
8997
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 245 times.
341 if (!encryption_index->nb_encrypted_samples) {
8998 // Full-sample encryption with default settings.
8999 96 encrypted_sample = sc->cenc.default_encrypted_sample;
9000
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) {
9001 // Per-sample setting override.
9002 245 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
9003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
245 if (!encrypted_sample) {
9004 ✗ encrypted_sample = sc->cenc.default_encrypted_sample;
9005 }
9006 }
9007
9008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
341 if (!encrypted_sample) {
9009 ✗ av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
9010 ✗ return AVERROR_INVALIDDATA;
9011 }
9012
9013
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) {
9014 341 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
9015 } else {
9016 size_t size;
9017 ✗ uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
9018 ✗ if (!side_data)
9019 ✗ return AVERROR(ENOMEM);
9020 ✗ ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
9021 ✗ if (ret < 0)
9022 ✗ av_free(side_data);
9023 ✗ return ret;
9024 }
9025 }
9026
9027 111274 return 0;
9028 }
9029
9030 ✗ static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9031 {
9032 ✗ const int OPUS_SEEK_PREROLL_MS = 80;
9033 int ret;
9034 AVStream *st;
9035 size_t size;
9036 uint16_t pre_skip;
9037
9038 ✗ if (c->fc->nb_streams < 1)
9039 ✗ return 0;
9040 ✗ st = c->fc->streams[c->fc->nb_streams-1];
9041
9042 ✗ if ((uint64_t)atom.size > (1<<30) || atom.size < 11 || st->codecpar->extradata)
9043 ✗ return AVERROR_INVALIDDATA;
9044
9045 /* Check OpusSpecificBox version. */
9046 ✗ if (avio_r8(pb) != 0) {
9047 ✗ av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
9048 ✗ return AVERROR_INVALIDDATA;
9049 }
9050
9051 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
9052 ✗ size = atom.size + 8;
9053
9054 ✗ if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
9055 ✗ return ret;
9056
9057 ✗ AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
9058 ✗ AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
9059 ✗ AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
9060 ✗ if ((ret = ffio_read_size(pb, st->codecpar->extradata + 9, size - 9)) < 0) {
9061 ✗ av_freep(&st->codecpar->extradata);
9062 ✗ st->codecpar->extradata_size = 0;
9063 ✗ return ret;
9064 }
9065
9066 /* OpusSpecificBox is stored in big-endian, but OpusHead is
9067 little-endian; aside from the preceding magic and version they're
9068 otherwise currently identical. Data after output gain at offset 16
9069 doesn't need to be bytewapped. */
9070 ✗ pre_skip = AV_RB16A(st->codecpar->extradata + 10);
9071 ✗ AV_WL16A(st->codecpar->extradata + 10, pre_skip);
9072 ✗ AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
9073 ✗ AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
9074
9075 ✗ st->codecpar->initial_padding = pre_skip;
9076 ✗ st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
9077 ✗ (AVRational){1, 1000},
9078 ✗ (AVRational){1, 48000});
9079
9080 ✗ return 0;
9081 }
9082
9083 ✗ static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9084 {
9085 AVStream *st;
9086 unsigned format_info;
9087 int channel_assignment, channel_assignment1, channel_assignment2;
9088 int ratebits;
9089 uint64_t chmask;
9090
9091 ✗ if (c->fc->nb_streams < 1)
9092 ✗ return 0;
9093 ✗ st = c->fc->streams[c->fc->nb_streams-1];
9094
9095 ✗ if (atom.size < 10)
9096 ✗ return AVERROR_INVALIDDATA;
9097
9098 ✗ format_info = avio_rb32(pb);
9099
9100 ✗ ratebits = (format_info >> 28) & 0xF;
9101 ✗ channel_assignment1 = (format_info >> 15) & 0x1F;
9102 ✗ channel_assignment2 = format_info & 0x1FFF;
9103 ✗ if (channel_assignment2)
9104 ✗ channel_assignment = channel_assignment2;
9105 else
9106 ✗ channel_assignment = channel_assignment1;
9107
9108 ✗ st->codecpar->frame_size = 40 << (ratebits & 0x7);
9109 ✗ st->codecpar->sample_rate = mlp_samplerate(ratebits);
9110
9111 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
9112 ✗ chmask = truehd_layout(channel_assignment);
9113 ✗ av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
9114
9115 ✗ return 0;
9116 }
9117
9118 11 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9119 {
9120 AVStream *st;
9121 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
9122 int ret;
9123 11 int64_t read_size = atom.size;
9124
9125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
9126 ✗ return 0;
9127 11 st = c->fc->streams[c->fc->nb_streams-1];
9128
9129 // At most 24 bytes
9130 11 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
9131
9132
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
9133 ✗ return ret;
9134
9135 11 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
9136 }
9137
9138 7 static int mov_read_hvce(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9139 {
9140 AVStream *st;
9141 AVPacketSideData *sd;
9142 int ret;
9143
9144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (c->fc->nb_streams < 1)
9145 ✗ return 0;
9146 7 st = c->fc->streams[c->fc->nb_streams - 1];
9147
9148
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)
9149 ✗ return AVERROR_INVALIDDATA;
9150
9151 7 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
9152 7 &st->codecpar->nb_coded_side_data,
9153 AV_PKT_DATA_HEVC_CONF,
9154 7 atom.size, 0);
9155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sd)
9156 ✗ return AVERROR(ENOMEM);
9157
9158 7 ret = ffio_read_size(pb, sd->data, atom.size);
9159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
9160 ✗ return ret;
9161
9162 7 return 0;
9163 }
9164
9165 4 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9166 {
9167 AVStream *st;
9168 uint8_t *buf;
9169 int ret, old_size, num_arrays;
9170
9171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
9172 ✗ return 0;
9173 4 st = c->fc->streams[c->fc->nb_streams-1];
9174
9175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!st->codecpar->extradata_size)
9176 // TODO: handle lhvC when present before hvcC
9177 ✗ return 0;
9178
9179
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 ||
9180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 atom.size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
9181 ✗ return AVERROR_INVALIDDATA;
9182 }
9183
9184 4 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
9185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!buf)
9186 ✗ return AVERROR(ENOMEM);
9187 4 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
9188
9189 4 ret = ffio_read_size(pb, buf, atom.size);
9190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
9191 ✗ av_free(buf);
9192 ✗ av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
9193 ✗ return 0;
9194 }
9195
9196 4 num_arrays = buf[5];
9197 4 old_size = st->codecpar->extradata_size;
9198 4 atom.size -= 8 /* account for mov_realloc_extradata offsetting */
9199 + 6 /* lhvC bytes before the arrays*/;
9200
9201 4 ret = mov_realloc_extradata(st->codecpar, atom);
9202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
9203 ✗ av_free(buf);
9204 ✗ return ret;
9205 }
9206
9207 4 st->codecpar->extradata[22] += num_arrays;
9208 4 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
9209
9210 4 st->disposition |= AV_DISPOSITION_MULTILAYER;
9211
9212 4 av_free(buf);
9213 4 return 0;
9214 }
9215
9216 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9217 {
9218 4 AVFormatContext *ctx = c->fc;
9219 4 AVStream *st = NULL;
9220 AVBPrint scheme_buf, value_buf;
9221 4 int64_t scheme_str_len = 0, value_str_len = 0;
9222 4 int version, flags, ret = AVERROR_BUG;
9223 4 int64_t size = atom.size;
9224
9225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
9226 // 4 bytes for version + flags, 2x 1 byte for null
9227 ✗ return AVERROR_INVALIDDATA;
9228
9229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
9230 ✗ return 0;
9231 4 st = c->fc->streams[c->fc->nb_streams-1];
9232
9233 4 version = avio_r8(pb);
9234 4 flags = avio_rb24(pb);
9235 4 size -= 4;
9236
9237
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) {
9238 ✗ av_log(ctx, AV_LOG_ERROR,
9239 "Unsupported 'kind' box with version %d, flags: %x",
9240 version, flags);
9241 ✗ return AVERROR_INVALIDDATA;
9242 }
9243
9244 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
9245 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
9246
9247
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,
9248 size)) < 0) {
9249 ✗ ret = scheme_str_len;
9250 ✗ goto cleanup;
9251 }
9252
9253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
9254 // we need to have another string, even if nullptr.
9255 // we check with + 1 since we expect that if size was not hit,
9256 // an additional null was read.
9257 ✗ ret = AVERROR_INVALIDDATA;
9258 ✗ goto cleanup;
9259 }
9260
9261 4 size -= scheme_str_len + 1;
9262
9263
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,
9264 size)) < 0) {
9265 ✗ ret = value_str_len;
9266 ✗ goto cleanup;
9267 }
9268
9269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
9270 // in case of no trailing null, box is not valid.
9271 ✗ ret = AVERROR_INVALIDDATA;
9272 ✗ goto cleanup;
9273 }
9274
9275 4 av_log(ctx, AV_LOG_TRACE,
9276 "%s stream %d KindBox(scheme: %s, value: %s)\n",
9277 4 av_get_media_type_string(st->codecpar->codec_type),
9278 st->index,
9279 scheme_buf.str, value_buf.str);
9280
9281
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++) {
9282 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
9283
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
9284 ✗ continue;
9285
9286
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
9287 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
9288
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
9289 16 continue;
9290
9291 4 st->disposition |= value_map.disposition;
9292 }
9293 }
9294
9295 4 ret = 0;
9296
9297 4 cleanup:
9298
9299 4 av_bprint_finalize(&scheme_buf, NULL);
9300 4 av_bprint_finalize(&value_buf, NULL);
9301
9302 4 return ret;
9303 }
9304
9305 ✗ static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9306 {
9307 AVStream *st;
9308 ✗ AVChannelLayout ch_layout = { 0 };
9309 int ret, i, version, type;
9310 int ambisonic_order, channel_order, normalization, channel_count;
9311 int ambi_channels, non_diegetic_channels;
9312
9313 ✗ if (c->fc->nb_streams < 1)
9314 ✗ return 0;
9315
9316 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
9317
9318 ✗ if (atom.size < 16) {
9319 ✗ av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
9320 ✗ return AVERROR_INVALIDDATA;
9321 }
9322
9323 ✗ version = avio_r8(pb);
9324 ✗ if (version) {
9325 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
9326 ✗ return 0;
9327 }
9328
9329 ✗ type = avio_r8(pb);
9330 ✗ if (type & 0x7f) {
9331 ✗ av_log(c->fc, AV_LOG_WARNING,
9332 "Unsupported ambisonic type %d\n", type & 0x7f);
9333 ✗ return 0;
9334 }
9335 ✗ non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
9336
9337 ✗ ambisonic_order = avio_rb32(pb);
9338
9339 ✗ channel_order = avio_r8(pb);
9340 ✗ if (channel_order) {
9341 ✗ av_log(c->fc, AV_LOG_WARNING,
9342 "Unsupported channel_order %d\n", channel_order);
9343 ✗ return 0;
9344 }
9345
9346 ✗ normalization = avio_r8(pb);
9347 ✗ if (normalization) {
9348 ✗ av_log(c->fc, AV_LOG_WARNING,
9349 "Unsupported normalization %d\n", normalization);
9350 ✗ return 0;
9351 }
9352
9353 ✗ channel_count = avio_rb32(pb);
9354 ✗ if (ambisonic_order < 0 || ambisonic_order > 31 ||
9355 ✗ channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
9356 non_diegetic_channels)) {
9357 ✗ av_log(c->fc, AV_LOG_ERROR,
9358 "Invalid number of channels (%d / %d)\n",
9359 channel_count, ambisonic_order);
9360 ✗ return 0;
9361 }
9362 ✗ ambi_channels = channel_count - non_diegetic_channels;
9363
9364 ✗ ret = av_channel_layout_custom_init(&ch_layout, channel_count);
9365 ✗ if (ret < 0)
9366 ✗ return 0;
9367
9368 ✗ for (i = 0; i < channel_count; i++) {
9369 ✗ unsigned channel = avio_rb32(pb);
9370
9371 ✗ if (channel >= channel_count) {
9372 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
9373 channel, ambisonic_order);
9374 ✗ av_channel_layout_uninit(&ch_layout);
9375 ✗ return 0;
9376 }
9377 ✗ if (channel >= ambi_channels)
9378 ✗ ch_layout.u.map[i].id = channel - ambi_channels;
9379 else
9380 ✗ ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
9381 }
9382
9383 ✗ ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
9384 ✗ if (ret < 0) {
9385 ✗ av_channel_layout_uninit(&ch_layout);
9386 ✗ return 0;
9387 }
9388
9389 ✗ av_channel_layout_uninit(&st->codecpar->ch_layout);
9390 ✗ st->codecpar->ch_layout = ch_layout;
9391
9392 ✗ return 0;
9393 }
9394
9395 ✗ static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9396 {
9397 AVStream *st;
9398 int version;
9399
9400 ✗ if (c->fc->nb_streams < 1)
9401 ✗ return 0;
9402
9403 ✗ st = c->fc->streams[c->fc->nb_streams - 1];
9404
9405 ✗ if (atom.size < 5) {
9406 ✗ av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
9407 ✗ return AVERROR_INVALIDDATA;
9408 }
9409
9410 ✗ version = avio_r8(pb);
9411 ✗ if (version) {
9412 ✗ av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
9413 ✗ return 0;
9414 }
9415
9416 ✗ st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
9417
9418 ✗ return 0;
9419 }
9420
9421 231 static int rb_size(AVIOContext *pb, int64_t *value, int size)
9422 {
9423
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 200 times.
231 if (size == 0)
9424 31 *value = 0;
9425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 else if (size == 1)
9426 ✗ *value = avio_r8(pb);
9427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 else if (size == 2)
9428 ✗ *value = avio_rb16(pb);
9429
1/2
✓ Branch 0 taken 200 times.
✗ Branch 1 not taken.
200 else if (size == 4)
9430 200 *value = avio_rb32(pb);
9431 ✗ else if (size == 8) {
9432 ✗ *value = avio_rb64(pb);
9433 ✗ if (*value < 0)
9434 ✗ return -1;
9435 } else
9436 ✗ return -1;
9437 231 return size;
9438 }
9439
9440 2 static int mov_read_auxc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9441 {
9442 AVBPrint aux_type;
9443 HEIFItem *item;
9444
9445 2 avio_r8(pb); /* version */
9446 2 avio_rb24(pb); /* flags */
9447
9448 2 av_bprint_init(&aux_type, 0, AV_BPRINT_SIZE_AUTOMATIC);
9449 2 ff_read_string_to_bprint_overwrite(pb, &aux_type, atom.size - 4);
9450
9451 2 av_log(c->fc, AV_LOG_TRACE, "auxC: item_id %d, aux_type %s\n",
9452 c->cur_item_id, aux_type.str);
9453
9454 2 item = get_heif_item(c, c->cur_item_id);
9455
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
2 if (item && (av_stristr(aux_type.str, "hdrgainmap")))
9456 2 item->is_gainmap = 1;
9457
9458 2 return 0;
9459 }
9460
9461 20 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9462 {
9463 20 avio_rb32(pb); // version & flags.
9464 20 c->primary_item_id = avio_rb16(pb);
9465 20 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
9466 20 return atom.size;
9467 }
9468
9469 11 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9470 {
9471 11 c->idat_offset = avio_tell(pb);
9472 11 return 0;
9473 }
9474
9475 20 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9476 {
9477 HEIFItem **heif_item;
9478 int version, offset_size, length_size, base_offset_size, index_size;
9479 int item_count, extent_count;
9480 int64_t base_offset, extent_offset, extent_length;
9481 uint8_t value;
9482
9483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (c->found_iloc) {
9484 ✗ av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
9485 ✗ return 0;
9486 }
9487
9488 20 version = avio_r8(pb);
9489 20 avio_rb24(pb); // flags.
9490
9491 20 value = avio_r8(pb);
9492 20 offset_size = (value >> 4) & 0xF;
9493 20 length_size = value & 0xF;
9494 20 value = avio_r8(pb);
9495 20 base_offset_size = (value >> 4) & 0xF;
9496
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 7 times.
20 index_size = !version ? 0 : (value & 0xF);
9497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (index_size) {
9498 ✗ avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
9499 ✗ return AVERROR_PATCHWELCOME;
9500 }
9501
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9502
9503
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (item_count > atom.size)
9504 ✗ return AVERROR_INVALIDDATA;
9505
9506 20 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
9507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (!heif_item)
9508 ✗ return AVERROR(ENOMEM);
9509 20 c->heif_item = heif_item;
9510
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2 times.
20 if (item_count > c->nb_heif_item)
9511 18 memset(&c->heif_item[c->nb_heif_item], 0,
9512 18 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
9513 20 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
9514
9515 20 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
9516
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 20 times.
97 for (int i = 0; i < item_count; i++) {
9517 77 HEIFItem *item = NULL;
9518
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9519
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 12 times.
77 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
9520 int j;
9521
9522
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
77 if (avio_feof(pb))
9523 ✗ return AVERROR_INVALIDDATA;
9524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (offset_type > 1) {
9525 ✗ avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
9526 ✗ return AVERROR_PATCHWELCOME;
9527 }
9528
9529 77 avio_rb16(pb); // data_reference_index.
9530
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
77 if (rb_size(pb, &base_offset, base_offset_size) < 0)
9531 ✗ return AVERROR_INVALIDDATA;
9532 77 extent_count = avio_rb16(pb);
9533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (extent_count > 1) {
9534 // For still AVIF images, we only support one extent item.
9535 ✗ avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
9536 ✗ return AVERROR_PATCHWELCOME;
9537 }
9538
9539
2/4
✓ Branch 1 taken 77 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 77 times.
✗ Branch 4 not taken.
154 if (rb_size(pb, &extent_offset, offset_size) < 0 ||
9540 77 rb_size(pb, &extent_length, length_size) < 0 ||
9541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 base_offset > INT64_MAX - extent_offset)
9542 ✗ return AVERROR_INVALIDDATA;
9543
9544
1/2
✓ Branch 0 taken 250 times.
✗ Branch 1 not taken.
250 for (j = 0; j < c->nb_heif_item; j++) {
9545 250 item = c->heif_item[j];
9546
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 193 times.
250 if (!item)
9547 57 item = c->heif_item[j] = av_mallocz(sizeof(*item));
9548
2/2
✓ Branch 0 taken 173 times.
✓ Branch 1 taken 20 times.
193 else if (item->item_id != item_id)
9549 173 continue;
9550 77 break;
9551 }
9552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (!item)
9553 ✗ return AVERROR(ENOMEM);
9554
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (j == c->nb_heif_item)
9555 ✗ return AVERROR_INVALIDDATA;
9556
9557 77 item->item_id = item_id;
9558
9559
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 64 times.
77 if (offset_type == 1)
9560 13 item->is_idat_relative = 1;
9561 77 item->extent_length = extent_length;
9562 77 item->extent_offset = base_offset + extent_offset;
9563 77 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, item->item_id %d, offset_type %d, "
9564 "extent_offset %"PRId64", extent_length %"PRId64"\n",
9565 i, item->item_id, offset_type, item->extent_offset, item->extent_length);
9566 }
9567
9568 20 c->found_iloc = 1;
9569 20 return atom.size;
9570 }
9571
9572 77 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9573 {
9574 77 HEIFItem *item = NULL;
9575 AVBPrint item_name;
9576 77 int64_t size = atom.size;
9577 uint32_t item_type;
9578 int item_id;
9579 int i, version, flags, ret;
9580
9581 77 version = avio_r8(pb);
9582 77 flags = avio_rb24(pb);
9583 77 size -= 4;
9584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (size < 0)
9585 ✗ return AVERROR_INVALIDDATA;
9586
9587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (version < 2) {
9588 ✗ avpriv_report_missing_feature(c->fc, "infe version < 2");
9589 ✗ avio_skip(pb, size);
9590 ✗ return 1;
9591 }
9592
9593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
9594 77 avio_rb16(pb); // item_protection_index
9595 77 item_type = avio_rl32(pb);
9596 77 size -= 8;
9597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (size < 1)
9598 ✗ return AVERROR_INVALIDDATA;
9599
9600 77 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
9601 77 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
9602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (ret < 0) {
9603 ✗ av_bprint_finalize(&item_name, NULL);
9604 ✗ return ret;
9605 }
9606
9607 77 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
9608 77 item_id, av_fourcc2str(item_type), item_name.str);
9609
9610 77 size -= ret + 1;
9611
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 71 times.
77 if (size > 0)
9612 6 avio_skip(pb, size);
9613
9614
1/2
✓ Branch 0 taken 250 times.
✗ Branch 1 not taken.
250 for (i = 0; i < c->nb_heif_item; i++) {
9615 250 item = c->heif_item[i];
9616
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 230 times.
250 if (!item)
9617 20 item = c->heif_item[i] = av_mallocz(sizeof(*item));
9618
2/2
✓ Branch 0 taken 173 times.
✓ Branch 1 taken 57 times.
230 else if (item->item_id != item_id)
9619 173 continue;
9620 77 break;
9621 }
9622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (!item) {
9623 ✗ av_bprint_finalize(&item_name, NULL);
9624 ✗ return AVERROR(ENOMEM);
9625 }
9626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (i == c->nb_heif_item) {
9627 ✗ av_bprint_finalize(&item_name, NULL);
9628 ✗ return AVERROR_INVALIDDATA;
9629 }
9630
9631 77 av_freep(&item->name);
9632
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 21 times.
77 av_bprint_finalize(&item_name, ret ? &item->name : NULL);
9633 77 item->item_id = item_id;
9634 77 item->type = item_type;
9635 77 item->flags = flags;
9636
9637
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 24 times.
77 switch (item_type) {
9638 53 case MKTAG('a','v','0','1'):
9639 case MKTAG('j','p','e','g'):
9640 case MKTAG('h','v','c','1'):
9641 53 ret = heif_add_stream(c, item);
9642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (ret < 0)
9643 ✗ return ret;
9644 53 break;
9645 }
9646
9647 77 return 0;
9648 }
9649
9650 20 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9651 {
9652 HEIFItem **heif_item;
9653 int entry_count;
9654 20 int version, got_stream = 0, ret, i;
9655
9656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (c->found_iinf) {
9657 ✗ av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
9658 ✗ return 0;
9659 }
9660
9661 20 version = avio_r8(pb);
9662 20 avio_rb24(pb); // flags.
9663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
9664
9665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (entry_count > atom.size)
9666 ✗ return AVERROR_INVALIDDATA;
9667
9668 /* account for the version/flags/entry_count fields already consumed,
9669 * so the per-entry loop below can bound each infe box by what is
9670 * actually left in this iinf box, the same way mov_read_iprp() bounds
9671 * ipco/ipma entries by the remaining iprp size. */
9672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 atom.size -= version ? 8 : 6;
9673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (atom.size < 0)
9674 ✗ return AVERROR_INVALIDDATA;
9675
9676 20 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
9677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (!heif_item)
9678 ✗ return AVERROR(ENOMEM);
9679 20 c->heif_item = heif_item;
9680
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
20 if (entry_count > c->nb_heif_item)
9681 2 memset(&c->heif_item[c->nb_heif_item], 0,
9682 2 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
9683 20 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
9684
9685
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 20 times.
97 for (i = 0; i < entry_count; i++) {
9686 MOVAtom infe;
9687
9688 77 infe.size = avio_rb32(pb);
9689 77 infe.type = avio_rl32(pb);
9690
3/6
✓ Branch 1 taken 77 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 77 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 77 times.
✗ Branch 6 not taken.
77 if (avio_feof(pb) || infe.size < 8 || infe.size > atom.size ||
9691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 infe.type != MKTAG('i','n','f','e')) {
9692 ✗ ret = AVERROR_INVALIDDATA;
9693 ✗ goto fail;
9694 }
9695
9696 77 atom.size -= infe.size;
9697 77 infe.size -= 8;
9698
9699 77 ret = mov_read_infe(c, pb, infe);
9700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (ret < 0)
9701 ✗ goto fail;
9702
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 if (!ret)
9703 77 got_stream = 1;
9704 }
9705
9706 20 c->found_iinf = got_stream;
9707 20 return 0;
9708 ✗ fail:
9709 ✗ for (; i >= 0; i--) {
9710 ✗ HEIFItem *item = c->heif_item[i];
9711
9712 ✗ if (!item)
9713 ✗ continue;
9714
9715 ✗ av_freep(&item->name);
9716 }
9717 ✗ return ret;
9718 }
9719
9720 2 static int mov_read_iref_dimg_tmap(MOVContext *c, AVIOContext *pb,
9721 HEIFItem *item, int version, int entries)
9722 {
9723 2 HEIFGroup *tmap = av_realloc_array(c->heif_group, c->nb_heif_group + 1U,
9724 sizeof(*c->heif_group));
9725 int ret;
9726
9727
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!tmap)
9728 ✗ return AVERROR(ENOMEM);
9729 2 c->heif_group = tmap;
9730
9731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (entries != 2) {
9732 ✗ avpriv_report_missing_feature(c->fc, "Derived image item of type %s with an "
9733 "item reference count other than 2",
9734 ✗ av_fourcc2str(item->type));
9735 ✗ return 0;
9736 }
9737
9738 2 tmap = &tmap[c->nb_heif_group];
9739
9740 2 tmap->item_idx_list = NULL; // Not needed
9741 2 tmap->item_id_list = av_malloc_array(entries, sizeof(*tmap->item_id_list));
9742 2 tmap->item_list = av_calloc(entries, sizeof(*tmap->item_list));
9743
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (!tmap->item_id_list || !tmap->item_list) {
9744 ✗ ret = AVERROR(ENOMEM);
9745 ✗ goto fail;
9746 }
9747
9748 /* 'to' item ids */
9749
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < entries; i++) {
9750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 tmap->item_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
9751
9752
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (avio_feof(pb)) {
9753 ✗ ret = AVERROR_INVALIDDATA;
9754 ✗ goto fail;
9755 }
9756 }
9757
9758 2 tmap->nb_items = entries;
9759 2 tmap->item = item;
9760 2 ++c->nb_heif_group;
9761
9762 2 return 0;
9763 ✗ fail:
9764 ✗ av_freep(&tmap->item_id_list);
9765 ✗ av_freep(&tmap->item_list);
9766
9767 ✗ return ret;
9768 }
9769
9770 11 static int mov_read_iref_dimg_grid(MOVContext *c, AVIOContext *pb,
9771 HEIFItem *item, int version, int entries)
9772 {
9773 11 HEIFGroup *grid = av_realloc_array(c->heif_group, c->nb_heif_group + 1U,
9774 sizeof(*c->heif_group));
9775 int ret;
9776
9777
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!grid)
9778 ✗ return AVERROR(ENOMEM);
9779 11 c->heif_group = grid;
9780 11 grid = &grid[c->nb_heif_group];
9781
9782 11 grid->item_id_list = av_malloc_array(entries, sizeof(*grid->item_id_list));
9783 11 grid->item_idx_list = av_calloc(entries, sizeof(*grid->item_idx_list));
9784 11 grid->item_list = av_calloc(entries, sizeof(*grid->item_list));
9785
3/6
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 11 times.
11 if (!grid->item_id_list || !grid->item_list || !grid->item_idx_list) {
9786 ✗ ret = AVERROR(ENOMEM);
9787 ✗ goto fail;
9788 }
9789 /* 'to' item ids */
9790
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 11 times.
47 for (int i = 0; i < entries; i++) {
9791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 grid->item_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
9792
9793
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
36 if (avio_feof(pb)) {
9794 ✗ ret = AVERROR_INVALIDDATA;
9795 ✗ goto fail;
9796 }
9797 }
9798
9799 11 grid->nb_items = entries;
9800 11 grid->item = item;
9801 11 ++c->nb_heif_group;
9802
9803 11 return 0;
9804 ✗ fail:
9805 ✗ av_freep(&grid->item_id_list);
9806 ✗ av_freep(&grid->item_idx_list);
9807 ✗ av_freep(&grid->item_list);
9808
9809 ✗ return ret;
9810 }
9811
9812 13 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
9813 {
9814 13 HEIFItem *item = NULL;
9815 int entries;
9816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9817 int ret;
9818
9819
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 13 times.
15 for (int i = 0; i < c->nb_heif_group; i++) {
9820
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->heif_group[i].item->item_id == from_item_id) {
9821 ✗ av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
9822 "referencing the same Derived Image item\n");
9823 ✗ return AVERROR_INVALIDDATA;
9824 }
9825 }
9826
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 for (int i = 0; i < c->nb_heif_item; i++) {
9827
3/4
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 13 times.
59 if (!c->heif_item[i] || c->heif_item[i]->item_id != from_item_id)
9828 46 continue;
9829 13 item = c->heif_item[i];
9830
9831
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 switch (item->type) {
9832 13 case MKTAG('g','r','i','d'):
9833 case MKTAG('i','o','v','l'):
9834 case MKTAG('t','m','a','p'):
9835 13 break;
9836 ✗ default:
9837 ✗ avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
9838 ✗ av_fourcc2str(item->type));
9839 ✗ return 0;
9840 }
9841 13 break;
9842 }
9843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!item) {
9844 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing derived image information\n");
9845 ✗ return AVERROR_INVALIDDATA;
9846 }
9847
9848 13 entries = avio_rb16(pb);
9849
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!entries) {
9850 ✗ av_log(c->fc, AV_LOG_ERROR,
9851 "Derived image item references no input images\n");
9852 ✗ return AVERROR_INVALIDDATA;
9853 }
9854
9855 13 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
9856 from_item_id, entries);
9857
9858
2/3
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
13 switch (item->type) {
9859 11 case MKTAG('g','r','i','d'):
9860 case MKTAG('i','o','v','l'):
9861 11 ret = mov_read_iref_dimg_grid(c, pb, item, version, entries);
9862 11 break;
9863 2 case MKTAG('t','m','a','p'):
9864 2 ret = mov_read_iref_dimg_tmap(c, pb, item, version, entries);
9865 2 break;
9866 ✗ default:
9867 ✗ av_unreachable("item->type should have been checked above");
9868 }
9869
9870 13 return ret;
9871 }
9872
9873 10 static int mov_read_iref_cdsc(MOVContext *c, AVIOContext *pb, uint32_t type,
9874 int version, uint32_t size)
9875 {
9876 10 HEIFItem *from_item = NULL;
9877 int entries;
9878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 int item_id_size = version ? 4 : 2;
9879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9880 10 const HEIFItemRef ref = { type, from_item_id };
9881
9882 10 from_item = get_heif_item(c, from_item_id);
9883
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!from_item) {
9884 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing stream referenced by %s iref\n",
9885 ✗ av_fourcc2str(type));
9886 ✗ return AVERROR_INVALIDDATA;
9887 }
9888
9889 10 entries = avio_rb16(pb);
9890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if ((int64_t)entries * item_id_size > (int64_t)size - item_id_size - 2) {
9891 ✗ av_log(c->fc, AV_LOG_ERROR, "iref %s entry count %d exceeds the sub-box size\n",
9892 ✗ av_fourcc2str(type), entries);
9893 ✗ return AVERROR_INVALIDDATA;
9894 }
9895 /* 'to' item ids */
9896
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < entries; i++) {
9897
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 HEIFItem *item = get_heif_item(c, version ? avio_rb32(pb) : avio_rb16(pb));
9898
9899
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (avio_feof(pb))
9900 ✗ return AVERROR_INVALIDDATA;
9901
9902
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!item) {
9903 ✗ av_log(c->fc, AV_LOG_WARNING, "Missing stream referenced by %s item\n",
9904 ✗ av_fourcc2str(type));
9905 ✗ continue;
9906 }
9907
9908
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (!av_dynarray2_add((void **)&item->iref_from_list, &item->nb_iref_from_list,
9909 sizeof(*item->iref_from_list), (const uint8_t *)&ref))
9910 ✗ return AVERROR(ENOMEM);
9911 }
9912
9913 10 av_log(c->fc, AV_LOG_TRACE, "%s: from_item_id %d, entries %d\n",
9914 10 av_fourcc2str(type), from_item_id, entries);
9915
9916 10 return 0;
9917 }
9918
9919 9 static int mov_read_iref_auxl(MOVContext *c, AVIOContext *pb, uint32_t type,
9920 int version, uint32_t size)
9921 {
9922 9 HEIFItem *from_item = NULL;
9923 int entries;
9924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 unsigned from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9925
9926 9 from_item = get_heif_item(c, from_item_id);
9927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!from_item) {
9928 ✗ av_log(c->fc, AV_LOG_ERROR, "Missing item referenced by %s iref\n",
9929 ✗ av_fourcc2str(type));
9930 ✗ return AVERROR_INVALIDDATA;
9931 }
9932
9933 9 entries = avio_rb16(pb);
9934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (entries != 1) {
9935 ✗ avpriv_report_missing_feature(c->fc, "%s iref with an item reference "
9936 "count other than 1",
9937 ✗ av_fourcc2str(type));
9938 ✗ return 0;
9939 }
9940
9941 /* 'to' item ids */
9942
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for (int i = 0; i < entries; i++) {
9943
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 unsigned to_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9944 9 const HEIFItemRef ref = { type, to_item_id };
9945 9 HEIFItem *item = get_heif_item(c, to_item_id);
9946
9947
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 if (avio_feof(pb))
9948 ✗ return AVERROR_INVALIDDATA;
9949
9950
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!item) {
9951 ✗ av_log(c->fc, AV_LOG_WARNING, "Missing item referenced by %s iref\n",
9952 ✗ av_fourcc2str(type));
9953 ✗ continue;
9954 }
9955
9956
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 if (!av_dynarray2_add((void **)&from_item->iref_to_list, &from_item->nb_iref_to_list,
9957 sizeof(*from_item->iref_to_list), (const uint8_t *)&ref))
9958 ✗ return AVERROR(ENOMEM);
9959 }
9960
9961 9 av_log(c->fc, AV_LOG_TRACE, "%s: from_item_id %d, entries %d\n",
9962 9 av_fourcc2str(type), from_item_id, entries);
9963
9964 9 return 0;
9965 }
9966
9967 16 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9968 {
9969 16 int version = avio_r8(pb);
9970 int ret;
9971
9972 16 avio_rb24(pb); // flags
9973 16 atom.size -= 4;
9974
9975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (version > 1) {
9976 ✗ av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
9977 ✗ return 0;
9978 }
9979
9980
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 16 times.
48 while (atom.size) {
9981 32 int64_t next = avio_tell(pb);
9982 32 uint32_t type, size = avio_rb32(pb);
9983
9984
3/6
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 32 times.
32 if (size < 14 || size > atom.size || next > INT64_MAX - size)
9985 ✗ return AVERROR_INVALIDDATA;
9986
9987 32 next += size;
9988 32 type = avio_rl32(pb);
9989
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
32 switch (type) {
9990 13 case MKTAG('d','i','m','g'):
9991 13 ret = mov_read_iref_dimg(c, pb, version);
9992
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (ret < 0)
9993 ✗ return ret;
9994 32 break;
9995 10 case MKTAG('c','d','s','c'):
9996 10 ret = mov_read_iref_cdsc(c, pb, type, version, size - 8);
9997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
9998 ✗ return ret;
9999 10 break;
10000 9 case MKTAG('a','u','x','l'):
10001 case MKTAG('t','h','m','b'):
10002 9 ret = mov_read_iref_auxl(c, pb, type, version, size - 8);
10003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret < 0)
10004 ✗ return ret;
10005 9 break;
10006 ✗ default:
10007 ✗ av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
10008 ✗ av_fourcc2str(type), size);
10009 }
10010
10011 32 atom.size -= size;
10012 32 avio_seek(pb, next, SEEK_SET);
10013 }
10014 16 return 0;
10015 }
10016
10017 66 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10018 {
10019 HEIFItem *item;
10020 uint32_t width, height;
10021
10022 66 avio_r8(pb); /* version */
10023 66 avio_rb24(pb); /* flags */
10024 66 width = avio_rb32(pb);
10025 66 height = avio_rb32(pb);
10026
10027 66 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %"PRIu32", height %"PRIu32"\n",
10028 c->cur_item_id, width, height);
10029
10030
4/8
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 66 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 66 times.
66 if (!width || !height || width > INT_MAX || height > INT_MAX) {
10031 ✗ av_log(c->fc, AV_LOG_ERROR, "Invalid ispe dimensions %"PRIu32"x%"PRIu32"\n",
10032 width, height);
10033 ✗ return AVERROR_INVALIDDATA;
10034 }
10035
10036 66 item = get_heif_item(c, c->cur_item_id);
10037
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if (item) {
10038 66 item->width = width;
10039 66 item->height = height;
10040 }
10041
10042 66 return 0;
10043 }
10044
10045 10 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10046 {
10047 HEIFItem *item;
10048 int angle;
10049
10050 10 angle = avio_r8(pb) & 0x3;
10051
10052 10 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
10053 c->cur_item_id, angle);
10054
10055 10 item = get_heif_item(c, c->cur_item_id);
10056
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (item) {
10057 // angle * 90 specifies the angle (in anti-clockwise direction)
10058 // in units of degrees.
10059 10 item->rotation = angle * 90;
10060 }
10061
10062 10 return 0;
10063 }
10064
10065 6 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10066 {
10067 HEIFItem *item;
10068 int axis;
10069
10070 6 axis = avio_r8(pb) & 0x1;
10071
10072 6 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
10073 c->cur_item_id, axis);
10074
10075 6 item = get_heif_item(c, c->cur_item_id);
10076
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
10077 6 item->hflip = axis;
10078 6 item->vflip = !axis;
10079 }
10080
10081 6 return 0;
10082 }
10083
10084 20 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10085 {
10086 typedef struct MOVAtoms {
10087 FFIOContext b;
10088 uint32_t type;
10089 int64_t size;
10090 uint8_t *data;
10091 } MOVAtoms;
10092 20 MOVAtoms *atoms = NULL;
10093 MOVAtom a;
10094 unsigned count;
10095 20 int nb_atoms = 0;
10096 int version, flags;
10097 int ret;
10098
10099 20 a.size = avio_rb32(pb);
10100 20 a.type = avio_rl32(pb);
10101
10102
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 (a.size < 8 || a.size > atom.size || a.type != MKTAG('i','p','c','o'))
10103 ✗ return AVERROR_INVALIDDATA;
10104
10105 20 atom.size -= a.size;
10106 20 a.size -= 8;
10107
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 20 times.
120 while (a.size >= 8) {
10108 100 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
10109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (!ref) {
10110 ✗ ret = AVERROR(ENOMEM);
10111 ✗ goto fail;
10112 }
10113 100 ref->data = NULL;
10114 100 ref->size = avio_rb32(pb);
10115 100 ref->type = avio_rl32(pb);
10116
2/4
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
100 if (ref->size > a.size || ref->size < 8)
10117 break;
10118 100 ref->data = av_malloc(ref->size);
10119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (!ref->data) {
10120 ✗ ret = AVERROR_INVALIDDATA;
10121 ✗ goto fail;
10122 }
10123 100 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
10124 100 AV_WB32(ref->data, ref->size);
10125 100 AV_WL32(ref->data + 4, ref->type);
10126
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 100 times.
100 if (avio_read(pb, ref->data + 8, ref->size - 8) != ref->size - 8) {
10127 ✗ ret = AVERROR_INVALIDDATA;
10128 ✗ goto fail;
10129 }
10130 100 ffio_init_read_context(&ref->b, ref->data, ref->size);
10131 100 a.size -= ref->size;
10132 }
10133
10134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (a.size) {
10135 ✗ ret = AVERROR_INVALIDDATA;
10136 ✗ goto fail;
10137 }
10138
10139 20 a.size = avio_rb32(pb);
10140 20 a.type = avio_rl32(pb);
10141
10142
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 (a.size < 16 || a.size > atom.size || a.type != MKTAG('i','p','m','a')) {
10143 ✗ ret = AVERROR_INVALIDDATA;
10144 ✗ goto fail;
10145 }
10146
10147 20 version = avio_r8(pb);
10148 20 flags = avio_rb24(pb);
10149 20 count = avio_rb32(pb);
10150 20 a.size -= 16;
10151
10152
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 20 times.
86 for (int i = 0; i < count; i++) {
10153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
10154 66 int assoc_count = avio_r8(pb);
10155
10156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 a.size -= (version ? 5 : 3) + assoc_count * (1 + (flags & 1));
10157
2/4
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 66 times.
66 if (avio_feof(pb) || a.size < 0) {
10158 ✗ ret = AVERROR_INVALIDDATA;
10159 ✗ goto fail;
10160 }
10161
10162
2/2
✓ Branch 0 taken 173 times.
✓ Branch 1 taken 66 times.
239 for (int j = 0; j < assoc_count; j++) {
10163 MOVAtoms *ref;
10164 173 int index = avio_r8(pb) & 0x7f;
10165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 173 times.
173 if (flags & 1) {
10166 ✗ index <<= 8;
10167 ✗ index |= avio_r8(pb);
10168 }
10169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 173 times.
173 if (!index)
10170 ✗ continue;
10171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 173 times.
173 if (index > nb_atoms) {
10172 ✗ ret = AVERROR_INVALIDDATA;
10173 ✗ goto fail;
10174 }
10175 173 ref = &atoms[--index];
10176
10177 173 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
10178 173 index + 1, item_id, av_fourcc2str(ref->type));
10179
10180 173 c->cur_item_id = item_id;
10181
10182 173 ret = mov_read_default(c, &ref->b.pub,
10183 173 (MOVAtom) { .size = ref->size,
10184 .type = MKTAG('i','p','c','o') });
10185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 173 times.
173 if (ret < 0)
10186 ✗ goto fail;
10187 173 ffio_init_read_context(&ref->b, ref->data, ref->size);
10188 }
10189 }
10190
10191 20 ret = 0;
10192 20 fail:
10193 20 c->cur_item_id = -1;
10194
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 20 times.
120 for (int i = 0; i < nb_atoms; i++)
10195 100 av_free(atoms[i].data);
10196 20 av_free(atoms);
10197
10198 20 return ret;
10199 }
10200
10201 375 static int mov_read_vmhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10202 {
10203 375 avio_rb32(pb); // version & flags
10204 375 uint16_t graphics_mode = avio_rb16(pb);
10205 // ignored: opcolor[3]
10206
10207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 375 times.
375 if (c->fc->nb_streams < 1)
10208 ✗ return 0;
10209 375 AVStream *st = c->fc->streams[c->fc->nb_streams - 1];
10210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 375 times.
375 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
10211 ✗ return 0;
10212
10213
2/4
✓ Branch 0 taken 374 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
375 switch (graphics_mode) {
10214 374 case MOV_GRAPHICS_MODE_COPY:
10215 case MOV_GRAPHICS_MODE_DITHER_COPY:
10216 374 st->codecpar->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
10217 374 break;
10218 ✗ case MOV_GRAPHICS_MODE_STRAIGHT_ALPHA:
10219 ✗ st->codecpar->alpha_mode = AVALPHA_MODE_STRAIGHT;
10220 ✗ break;
10221 ✗ case MOV_GRAPHICS_MODE_PREMUL_BLACK_ALPHA:
10222 ✗ st->codecpar->alpha_mode = AVALPHA_MODE_PREMULTIPLIED;
10223 ✗ break;
10224 1 default:
10225 1 st->codecpar->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
10226 1 av_log(c->fc, AV_LOG_WARNING, "Unhandled graphics mode: 0x%x\n",
10227 graphics_mode);
10228 1 break;
10229 }
10230
10231 375 return 0;
10232 }
10233
10234 5 static int mov_read_mhac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10235 {
10236 5 AVFormatContext *ctx = c->fc;
10237 AVStream *st;
10238 int profile_level_indication, reference_ch_layout, config_length;
10239 5 int ret = 0;
10240
10241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ctx->nb_streams < 1)
10242 ✗ return 0;
10243
10244 5 st = ctx->streams[ctx->nb_streams - 1];
10245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
10246 ✗ return 0;
10247
10248
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_r8(pb) != 1) // ConfigurationVersion
10249 ✗ return 0;
10250
10251 5 profile_level_indication = avio_r8(pb);
10252 5 st->codecpar->profile = (profile_level_indication - 1) / 5;
10253 5 st->codecpar->level = ((profile_level_indication - 1) % 5) + 1;
10254
10255 5 reference_ch_layout = avio_r8(pb);
10256 5 config_length = avio_rb16(pb);
10257
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (config_length)
10258 5 ret = ff_get_extradata(ctx, st->codecpar, pb, config_length);
10259
10260
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (!reference_ch_layout ||
10261
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 reference_ch_layout >= FF_ARRAY_ELEMS(ff_mpa_cicp_channel_layout_masks)) {
10262 ✗ av_log(ctx, AV_LOG_WARNING, "Unknown referenceChannelLayout value: %d\n", reference_ch_layout);
10263 ✗ return ret;
10264 }
10265
10266 5 av_channel_layout_from_mask(&st->codecpar->ch_layout,
10267 5 ff_mpa_cicp_channel_layout_masks[reference_ch_layout]);
10268
10269 5 return ret;
10270 }
10271
10272 static const MOVParseTableEntry mov_default_parse_table[] = {
10273 { MKTAG('A','C','L','R'), mov_read_aclr },
10274 { MKTAG('A','P','R','G'), mov_read_avid },
10275 { MKTAG('A','A','L','P'), mov_read_avid },
10276 { MKTAG('A','R','E','S'), mov_read_ares },
10277 { MKTAG('a','v','s','s'), mov_read_avss },
10278 { MKTAG('a','v','1','C'), mov_read_glbl },
10279 { MKTAG('c','h','p','l'), mov_read_chpl },
10280 { MKTAG('c','o','6','4'), mov_read_stco },
10281 { MKTAG('c','o','l','r'), mov_read_colr },
10282 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
10283 { MKTAG('d','i','n','f'), mov_read_default },
10284 { MKTAG('D','p','x','E'), mov_read_dpxe },
10285 { MKTAG('d','r','e','f'), mov_read_dref },
10286 { MKTAG('e','d','t','s'), mov_read_default },
10287 { MKTAG('e','l','s','t'), mov_read_elst },
10288 { MKTAG('e','n','d','a'), mov_read_enda },
10289 { MKTAG('f','i','e','l'), mov_read_fiel },
10290 { MKTAG('a','d','r','m'), mov_read_adrm },
10291 { MKTAG('f','t','y','p'), mov_read_ftyp },
10292 { MKTAG('g','l','b','l'), mov_read_glbl },
10293 { MKTAG('h','d','l','r'), mov_read_hdlr },
10294 { MKTAG('i','l','s','t'), mov_read_ilst },
10295 { MKTAG('j','p','2','h'), mov_read_jp2h },
10296 { MKTAG('m','d','a','t'), mov_read_mdat },
10297 { MKTAG('m','d','h','d'), mov_read_mdhd },
10298 { MKTAG('m','d','i','a'), mov_read_default },
10299 { MKTAG('m','e','t','a'), mov_read_meta },
10300 { MKTAG('m','i','n','f'), mov_read_default },
10301 { MKTAG('m','o','o','f'), mov_read_moof },
10302 { MKTAG('m','o','o','v'), mov_read_moov },
10303 { MKTAG('m','v','e','x'), mov_read_default },
10304 { MKTAG('m','v','h','d'), mov_read_mvhd },
10305 { MKTAG('S','M','I',' '), mov_read_svq3 },
10306 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
10307 { MKTAG('a','v','c','C'), mov_read_glbl },
10308 { MKTAG('p','a','s','p'), mov_read_pasp },
10309 { MKTAG('c','l','a','p'), mov_read_clap },
10310 { MKTAG('c','d','s','c'), mov_read_cdsc_rndr },
10311 { MKTAG('r','n','d','r'), mov_read_cdsc_rndr },
10312 { MKTAG('s','b','a','s'), mov_read_sbas },
10313 { MKTAG('v','d','e','p'), mov_read_vdep },
10314 { MKTAG('s','i','d','x'), mov_read_sidx },
10315 { MKTAG('s','t','b','l'), mov_read_default },
10316 { MKTAG('s','t','c','o'), mov_read_stco },
10317 { MKTAG('s','t','p','s'), mov_read_stps },
10318 { MKTAG('s','t','r','f'), mov_read_strf },
10319 { MKTAG('s','t','s','c'), mov_read_stsc },
10320 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
10321 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
10322 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
10323 { MKTAG('s','t','t','s'), mov_read_stts },
10324 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
10325 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
10326 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
10327 { MKTAG('t','f','d','t'), mov_read_tfdt },
10328 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
10329 { MKTAG('t','r','a','k'), mov_read_trak },
10330 { MKTAG('t','r','a','f'), mov_read_default },
10331 { MKTAG('t','r','e','f'), mov_read_default },
10332 { MKTAG('t','m','c','d'), mov_read_tmcd },
10333 { MKTAG('c','h','a','p'), mov_read_chap },
10334 { MKTAG('t','r','e','x'), mov_read_trex },
10335 { MKTAG('t','r','u','n'), mov_read_trun },
10336 { MKTAG('u','d','t','a'), mov_read_default },
10337 { MKTAG('w','a','v','e'), mov_read_wave },
10338 { MKTAG('e','s','d','s'), mov_read_esds },
10339 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
10340 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
10341 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
10342 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
10343 { MKTAG('w','f','e','x'), mov_read_wfex },
10344 { MKTAG('c','m','o','v'), mov_read_cmov },
10345 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
10346 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
10347 { MKTAG('d','v','c','1'), mov_read_dvc1 },
10348 { MKTAG('s','g','p','d'), mov_read_sgpd },
10349 { MKTAG('s','b','g','p'), mov_read_sbgp },
10350 { MKTAG('h','v','c','C'), mov_read_glbl },
10351 { MKTAG('v','v','c','C'), mov_read_glbl },
10352 { MKTAG('u','u','i','d'), mov_read_uuid },
10353 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
10354 { MKTAG('f','r','e','e'), mov_read_free },
10355 { MKTAG('-','-','-','-'), mov_read_custom },
10356 { MKTAG('s','i','n','f'), mov_read_default },
10357 { MKTAG('f','r','m','a'), mov_read_frma },
10358 { MKTAG('s','e','n','c'), mov_read_senc },
10359 { MKTAG('s','a','i','z'), mov_read_saiz },
10360 { MKTAG('s','a','i','o'), mov_read_saio },
10361 { MKTAG('p','s','s','h'), mov_read_pssh },
10362 { MKTAG('s','c','h','m'), mov_read_schm },
10363 { MKTAG('s','c','h','i'), mov_read_default },
10364 { MKTAG('t','e','n','c'), mov_read_tenc },
10365 { MKTAG('d','f','L','a'), mov_read_dfla },
10366 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
10367 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
10368 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
10369 { MKTAG('h','f','o','v'), mov_read_hfov },
10370 { MKTAG('d','O','p','s'), mov_read_dops },
10371 { MKTAG('d','m','l','p'), mov_read_dmlp },
10372 { MKTAG('S','m','D','m'), mov_read_smdm },
10373 { MKTAG('C','o','L','L'), mov_read_coll },
10374 { MKTAG('v','p','c','C'), mov_read_vpcc },
10375 { MKTAG('m','d','c','v'), mov_read_mdcv },
10376 { MKTAG('c','l','l','i'), mov_read_clli },
10377 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
10378 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
10379 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
10380 { MKTAG('h','v','c','E'), mov_read_hvce },
10381 { MKTAG('k','i','n','d'), mov_read_kind },
10382 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
10383 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
10384 { MKTAG('i','l','o','c'), mov_read_iloc },
10385 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
10386 { MKTAG('p','i','t','m'), mov_read_pitm },
10387 { MKTAG('e','v','c','C'), mov_read_glbl },
10388 { MKTAG('a','u','x','C'), mov_read_auxc },
10389 { MKTAG('i','d','a','t'), mov_read_idat },
10390 { MKTAG('i','m','i','r'), mov_read_imir },
10391 { MKTAG('i','r','e','f'), mov_read_iref },
10392 { MKTAG('i','s','p','e'), mov_read_ispe },
10393 { MKTAG('i','r','o','t'), mov_read_irot },
10394 { MKTAG('i','p','r','p'), mov_read_iprp },
10395 { MKTAG('i','i','n','f'), mov_read_iinf },
10396 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
10397 { MKTAG('l','h','v','C'), mov_read_lhvc },
10398 { MKTAG('l','v','c','C'), mov_read_glbl },
10399 { MKTAG('a','p','v','C'), mov_read_glbl },
10400 #if CONFIG_IAMFDEC
10401 { MKTAG('i','a','c','b'), mov_read_iacb },
10402 #endif
10403 { MKTAG('s','r','a','t'), mov_read_srat },
10404 { MKTAG('v','m','h','d'), mov_read_vmhd },
10405 { MKTAG('m','h','a','C'), mov_read_mhac },
10406 { 0, NULL }
10407 };
10408
10409 9029 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10410 {
10411 9029 int64_t total_size = 0;
10412 MOVAtom a;
10413 int i;
10414
10415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9029 times.
9029 if (c->atom_depth > 10) {
10416 ✗ av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
10417 ✗ return AVERROR_INVALIDDATA;
10418 }
10419 9029 c->atom_depth ++;
10420
10421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9029 times.
9029 if (atom.size < 0)
10422 ✗ atom.size = INT64_MAX;
10423
2/2
✓ Branch 0 taken 26099 times.
✓ Branch 1 taken 8422 times.
34521 while (total_size <= atom.size - 8) {
10424 26099 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
10425 26099 a.size = avio_rb32(pb);
10426 26099 a.type = avio_rl32(pb);
10427
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 26091 times.
26099 if (avio_feof(pb))
10428 8 break;
10429
3/4
✓ Branch 0 taken 265 times.
✓ Branch 1 taken 25826 times.
✓ Branch 2 taken 265 times.
✗ Branch 3 not taken.
26091 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
10430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26091 times.
26091 a.type == MKTAG('h','o','o','v')) &&
10431 ✗ a.size >= 8 &&
10432 ✗ c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
10433 uint32_t type;
10434 ✗ avio_skip(pb, 4);
10435 ✗ type = avio_rl32(pb);
10436 ✗ if (avio_feof(pb))
10437 ✗ break;
10438 ✗ avio_seek(pb, -8, SEEK_CUR);
10439 ✗ if (type == MKTAG('m','v','h','d') ||
10440 type == MKTAG('c','m','o','v')) {
10441 ✗ av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
10442 ✗ a.type = MKTAG('m','o','o','v');
10443 }
10444 }
10445
2/2
✓ Branch 0 taken 22523 times.
✓ Branch 1 taken 3568 times.
26091 if (atom.type != MKTAG('r','o','o','t') &&
10446
2/2
✓ Branch 0 taken 20640 times.
✓ Branch 1 taken 1883 times.
22523 atom.type != MKTAG('m','o','o','v')) {
10447
1/2
✓ Branch 0 taken 20640 times.
✗ Branch 1 not taken.
20640 if (a.type == MKTAG('t','r','a','k') ||
10448
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20640 times.
20640 a.type == MKTAG('m','d','a','t')) {
10449 ✗ av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
10450 ✗ avio_skip(pb, -8);
10451 ✗ c->atom_depth --;
10452 599 return 0;
10453 }
10454 }
10455 26091 total_size += 8;
10456
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 26062 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
26091 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
10457 29 a.size = avio_rb64(pb) - 8;
10458 29 total_size += 8;
10459 }
10460 26091 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
10461 26091 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
10462
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 26086 times.
26091 if (a.size == 0) {
10463 5 a.size = atom.size - total_size + 8;
10464 }
10465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26091 times.
26091 if (a.size < 0)
10466 ✗ break;
10467 26091 a.size -= 8;
10468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26091 times.
26091 if (a.size < 0)
10469 ✗ break;
10470 26091 a.size = FFMIN(a.size, atom.size - total_size);
10471
10472
2/2
✓ Branch 0 taken 1266442 times.
✓ Branch 1 taken 2183 times.
1268625 for (i = 0; mov_default_parse_table[i].type; i++)
10473
2/2
✓ Branch 0 taken 23908 times.
✓ Branch 1 taken 1242534 times.
1266442 if (mov_default_parse_table[i].type == a.type) {
10474 23908 parse = mov_default_parse_table[i].parse;
10475 23908 break;
10476 }
10477
10478 // container is user data
10479
4/4
✓ Branch 0 taken 2183 times.
✓ Branch 1 taken 23908 times.
✓ Branch 2 taken 1983 times.
✓ Branch 3 taken 200 times.
26091 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
10480
2/2
✓ Branch 0 taken 434 times.
✓ Branch 1 taken 1549 times.
1983 atom.type == MKTAG('i','l','s','t')))
10481 634 parse = mov_read_udta_string;
10482
10483 // Supports parsing the QuickTime Metadata Keys.
10484 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
10485
4/4
✓ Branch 0 taken 1549 times.
✓ Branch 1 taken 24542 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 1535 times.
26091 if (!parse && c->found_hdlr_mdta &&
10486
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 atom.type == MKTAG('m','e','t','a') &&
10487
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 a.type == MKTAG('k','e','y','s') &&
10488
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 c->meta_keys_count == 0) {
10489 14 parse = mov_read_keys;
10490 }
10491
10492
2/2
✓ Branch 0 taken 1535 times.
✓ Branch 1 taken 24556 times.
26091 if (!parse) { /* skip leaf atoms data */
10493 1535 avio_skip(pb, a.size);
10494 } else {
10495 24556 int64_t start_pos = avio_tell(pb);
10496 int64_t left;
10497 24556 int err = parse(c, pb, a);
10498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24556 times.
24556 if (err < 0) {
10499 ✗ c->atom_depth --;
10500 ✗ return err;
10501 }
10502
5/6
✓ Branch 0 taken 4923 times.
✓ Branch 1 taken 19633 times.
✓ Branch 2 taken 3467 times.
✓ Branch 3 taken 1456 times.
✓ Branch 4 taken 3467 times.
✗ Branch 5 not taken.
24556 if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos &&
10503
7/8
✓ Branch 0 taken 3464 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3464 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3450 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 582 times.
✓ Branch 7 taken 2868 times.
6917 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
10504 3450 start_pos + a.size == avio_size(pb))) {
10505
5/6
✓ Branch 0 taken 596 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 596 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 582 times.
599 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
10506 17 c->next_root_atom = start_pos + a.size;
10507 599 c->atom_depth --;
10508 599 return 0;
10509 }
10510 23957 left = a.size - avio_tell(pb) + start_pos;
10511
2/2
✓ Branch 0 taken 2275 times.
✓ Branch 1 taken 21682 times.
23957 if (left > 0) /* skip garbage at atom end */
10512 2275 avio_skip(pb, left);
10513
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 21680 times.
21682 else if (left < 0) {
10514 2 av_log(c->fc, AV_LOG_WARNING,
10515 "overread end of atom '%s' by %"PRId64" bytes\n",
10516 2 av_fourcc2str(a.type), -left);
10517 2 avio_seek(pb, left, SEEK_CUR);
10518 }
10519 }
10520
10521 25492 total_size += a.size;
10522 }
10523
10524
4/4
✓ Branch 0 taken 131 times.
✓ Branch 1 taken 8299 times.
✓ Branch 2 taken 123 times.
✓ Branch 3 taken 8 times.
8430 if (total_size < atom.size && atom.size < 0x7ffff)
10525 123 avio_skip(pb, atom.size - total_size);
10526
10527 8430 c->atom_depth --;
10528 8430 return 0;
10529 }
10530
10531 8162 static int mov_probe(const AVProbeData *p)
10532 {
10533 int64_t offset;
10534 uint32_t tag;
10535 8162 int score = 0;
10536 8162 int moov_offset = -1;
10537
10538 /* check file header */
10539 8162 offset = 0;
10540 10080 for (;;) {
10541 int64_t size;
10542 18242 int minsize = 8;
10543 /* ignore invalid offset */
10544
2/2
✓ Branch 0 taken 8162 times.
✓ Branch 1 taken 10080 times.
18242 if ((offset + 8ULL) > (unsigned int)p->buf_size)
10545 8162 break;
10546 10080 size = AV_RB32(p->buf + offset);
10547
3/4
✓ Branch 0 taken 547 times.
✓ Branch 1 taken 9533 times.
✓ Branch 2 taken 547 times.
✗ Branch 3 not taken.
10080 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
10548 547 size = AV_RB64(p->buf+offset + 8);
10549 547 minsize = 16;
10550
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 9461 times.
9533 } else if (size == 0) {
10551 72 size = p->buf_size - offset;
10552 }
10553
2/2
✓ Branch 0 taken 416 times.
✓ Branch 1 taken 9664 times.
10080 if (size < minsize) {
10554 416 offset += 4;
10555 416 continue;
10556 }
10557 9664 tag = AV_RL32(p->buf + offset + 4);
10558
5/6
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 1021 times.
✓ Branch 2 taken 434 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 8048 times.
9664 switch(tag) {
10559 /* check for obvious tags */
10560 160 case MKTAG('m','o','o','v'):
10561 160 moov_offset = offset + 4;
10562 av_fallthrough;
10563 1181 case MKTAG('m','d','a','t'):
10564 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
10565 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
10566 case MKTAG('f','t','y','p'):
10567
2/2
✓ Branch 0 taken 529 times.
✓ Branch 1 taken 652 times.
1181 if (tag == MKTAG('f','t','y','p') &&
10568
1/2
✓ Branch 0 taken 529 times.
✗ Branch 1 not taken.
529 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
10569
1/2
✓ Branch 0 taken 529 times.
✗ Branch 1 not taken.
529 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
10570
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 522 times.
529 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
10571 )) {
10572 7 score = FFMAX(score, 5);
10573 } else {
10574 1174 score = AVPROBE_SCORE_MAX;
10575 }
10576 1181 break;
10577 /* those are more common words, so rate then a bit less */
10578 434 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
10579 case MKTAG('w','i','d','e'):
10580 case MKTAG('f','r','e','e'):
10581 case MKTAG('j','u','n','k'):
10582 case MKTAG('p','i','c','t'):
10583 434 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
10584 434 break;
10585 ✗ case MKTAG(0x82,0x82,0x7f,0x7d):
10586 ✗ score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
10587 ✗ break;
10588 1 case MKTAG('s','k','i','p'):
10589 case MKTAG('u','u','i','d'):
10590 case MKTAG('p','r','f','l'):
10591 /* if we only find those cause probedata is too small at least rate them */
10592 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
10593 1 break;
10594 }
10595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9664 times.
9664 if (size > INT64_MAX - offset)
10596 ✗ break;
10597 9664 offset += size;
10598 }
10599
4/4
✓ Branch 0 taken 576 times.
✓ Branch 1 taken 7586 times.
✓ Branch 2 taken 160 times.
✓ Branch 3 taken 416 times.
8162 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
10600 /* moov atom in the header - we should make sure that this is not a
10601 * MOV-packed MPEG-PS */
10602 160 offset = moov_offset;
10603
10604
2/2
✓ Branch 0 taken 156244 times.
✓ Branch 1 taken 160 times.
156404 while (offset < (p->buf_size - 16)) { /* Sufficient space */
10605 /* We found an actual hdlr atom */
10606
2/2
✓ Branch 0 taken 178 times.
✓ Branch 1 taken 156066 times.
156244 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
10607
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 153 times.
178 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
10608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
10609 ✗ av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
10610 /* We found a media handler reference atom describing an
10611 * MPEG-PS-in-MOV, return a
10612 * low score to force expanding the probe window until
10613 * mpegps_probe finds what it needs */
10614 ✗ return 5;
10615 } else {
10616 /* Keep looking */
10617 156244 offset += 2;
10618 }
10619 }
10620 }
10621
10622 8162 return score;
10623 }
10624
10625 // must be done after parsing all trak because there's no order requirement
10626 2 static void mov_read_chapters(AVFormatContext *s)
10627 {
10628 2 MOVContext *mov = s->priv_data;
10629 MOVStreamContext *sc;
10630 int64_t cur_pos;
10631 int i, j;
10632 int chapter_track;
10633
10634
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
10635 2 AVStream *st = NULL;
10636 2 FFStream *sti = NULL;
10637 2 chapter_track = mov->chapter_tracks[j];
10638
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
10639 4 sc = mov->fc->streams[i]->priv_data;
10640
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
10641 2 st = s->streams[i];
10642 2 break;
10643 }
10644 }
10645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
10646 ✗ av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
10647 ✗ continue;
10648 }
10649 2 sti = ffstream(st);
10650
10651 2 sc = st->priv_data;
10652 2 cur_pos = avio_tell(sc->pb);
10653
10654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
10655 ✗ st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
10656 ✗ if (!st->attached_pic.data && sti->nb_index_entries) {
10657 // Retrieve the first frame, if possible
10658 ✗ AVIndexEntry *sample = &sti->index_entries[0];
10659 ✗ if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10660 ✗ av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
10661 ✗ goto finish;
10662 }
10663
10664 ✗ if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
10665 ✗ goto finish;
10666 }
10667 } else {
10668 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10669 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
10670 2 st->discard = AVDISCARD_ALL;
10671
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
10672 8 AVIndexEntry *sample = &sti->index_entries[i];
10673
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;
10674 uint8_t *title;
10675 uint16_t ch;
10676 int len, title_len;
10677
10678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
10679 ✗ av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
10680 ✗ end = AV_NOPTS_VALUE;
10681 }
10682
10683
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10684 ✗ av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
10685 ✗ goto finish;
10686 }
10687
10688 // the first two bytes are the length of the title
10689 8 len = avio_rb16(sc->pb);
10690
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
10691 ✗ continue;
10692 8 title_len = 2*len + 1;
10693
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
10694 ✗ goto finish;
10695
10696 // The samples could theoretically be in any encoding if there's an encd
10697 // atom following, but in practice are only utf-8 or utf-16, distinguished
10698 // instead by the presence of a BOM
10699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
10700 ✗ title[0] = 0;
10701 } else {
10702 8 ch = avio_rb16(sc->pb);
10703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
10704 ✗ avio_get_str16be(sc->pb, len, title, title_len);
10705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
10706 ✗ avio_get_str16le(sc->pb, len, title, title_len);
10707 else {
10708 8 AV_WB16(title, ch);
10709
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)
10710 ✗ title[len] = 0;
10711 else
10712 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
10713 }
10714 }
10715
10716 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
10717 8 av_freep(&title);
10718 }
10719 }
10720 2 finish:
10721 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
10722 }
10723 2 }
10724
10725 28 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
10726 int64_t value, int flags)
10727 {
10728 AVTimecode tc;
10729 char buf[AV_TIMECODE_STR_SIZE];
10730 28 AVRational rate = st->avg_frame_rate;
10731 28 int ret = av_timecode_init(&tc, rate, flags, 0, s);
10732
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
10733 ✗ return ret;
10734 28 av_dict_set(&st->metadata, "timecode",
10735 28 av_timecode_make_string(&tc, buf, value), 0);
10736 28 return 0;
10737 }
10738
10739 ✗ static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
10740 {
10741 ✗ MOVStreamContext *sc = st->priv_data;
10742 ✗ FFStream *const sti = ffstream(st);
10743 char buf[AV_TIMECODE_STR_SIZE];
10744 ✗ int64_t cur_pos = avio_tell(sc->pb);
10745 int hh, mm, ss, ff, drop;
10746
10747 ✗ if (!sti->nb_index_entries)
10748 ✗ return -1;
10749
10750 ✗ avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10751 ✗ avio_skip(s->pb, 13);
10752 ✗ hh = avio_r8(s->pb);
10753 ✗ mm = avio_r8(s->pb);
10754 ✗ ss = avio_r8(s->pb);
10755 ✗ drop = avio_r8(s->pb);
10756 ✗ ff = avio_r8(s->pb);
10757 ✗ snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
10758 hh, mm, ss, drop ? ';' : ':', ff);
10759 ✗ av_dict_set(&st->metadata, "timecode", buf, 0);
10760
10761 ✗ avio_seek(sc->pb, cur_pos, SEEK_SET);
10762 ✗ return 0;
10763 }
10764
10765 28 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
10766 {
10767 28 MOVStreamContext *sc = st->priv_data;
10768 28 FFStream *const sti = ffstream(st);
10769 28 int flags = 0;
10770 28 int64_t cur_pos = avio_tell(sc->pb);
10771 int64_t value;
10772 28 AVRational tc_rate = st->avg_frame_rate;
10773 28 int tmcd_nb_frames = sc->tmcd_nb_frames;
10774 int rounded_tc_rate;
10775
10776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!sti->nb_index_entries)
10777 ✗ return -1;
10778
10779
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)
10780 ✗ return -1;
10781
10782 28 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10783 28 value = avio_rb32(s->pb);
10784
10785
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 10 times.
28 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
10786
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
10787
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
10788
10789 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
10790 * not the case) and thus assume "frame number format" instead of QT one.
10791 * No sample with tmcd track can be found with a QT timecode at the moment,
10792 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
10793 * format). */
10794
10795 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
10796 * we multiply the frame number with the quotient.
10797 * See tickets #9492, #9710. */
10798 28 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
10799 /* Work around files where tmcd_nb_frames is rounded down from frame rate
10800 * instead of up. See ticket #5978. */
10801
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 18 times.
28 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
10802
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
10803 10 tmcd_nb_frames = rounded_tc_rate;
10804 28 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
10805
10806 28 parse_timecode_in_framenum_format(s, st, value, flags);
10807
10808 28 avio_seek(sc->pb, cur_pos, SEEK_SET);
10809 28 return 0;
10810 }
10811
10812 1693 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
10813 int i;
10814
3/4
✓ Branch 0 taken 1693 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1680 times.
✓ Branch 3 taken 13 times.
1693 if (!index || !*index) return;
10815
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 13 times.
208 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
10816 195 av_encryption_info_free((*index)->encrypted_samples[i]);
10817 }
10818 13 av_freep(&(*index)->encrypted_samples);
10819 13 av_freep(&(*index)->auxiliary_info_sizes);
10820 13 av_freep(&(*index)->auxiliary_offsets);
10821 13 av_freep(index);
10822 }
10823
10824 959 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
10825 {
10826 959 MOVStreamContext *sc = st->priv_data;
10827
10828
3/4
✓ Branch 0 taken 959 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 907 times.
959 if (!sc || --sc->refcount) {
10829 52 st->priv_data = NULL;
10830 52 return;
10831 }
10832
10833 907 av_freep(&sc->tts_data);
10834
2/2
✓ Branch 0 taken 838 times.
✓ Branch 1 taken 907 times.
1745 for (int i = 0; i < sc->drefs_count; i++) {
10835 838 av_freep(&sc->drefs[i].path);
10836 838 av_freep(&sc->drefs[i].dir);
10837 }
10838 907 av_freep(&sc->drefs);
10839
10840 907 sc->drefs_count = 0;
10841
10842
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 891 times.
907 if (!sc->pb_is_copied)
10843 16 ff_format_io_close(s, &sc->pb);
10844
10845 907 sc->pb = NULL;
10846 907 av_freep(&sc->chunk_offsets);
10847 907 av_freep(&sc->stsc_data);
10848 907 av_freep(&sc->sample_sizes);
10849 907 av_freep(&sc->keyframes);
10850 907 av_freep(&sc->ctts_data);
10851 907 av_freep(&sc->stts_data);
10852 907 av_freep(&sc->sdtp_data);
10853 907 av_freep(&sc->stps_data);
10854 907 av_freep(&sc->elst_data);
10855 907 av_freep(&sc->rap_group);
10856 907 av_freep(&sc->sync_group);
10857 907 av_freep(&sc->sgpd_sync);
10858 907 av_freep(&sc->sample_offsets);
10859 907 av_freep(&sc->open_key_samples);
10860 907 av_freep(&sc->display_matrix);
10861 907 av_freep(&sc->index_ranges);
10862
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 907 times.
939 for (int i = 0; i < sc->nb_tref_tags; i++)
10863 32 av_freep(&sc->tref_tags[i].id);
10864 907 av_freep(&sc->tref_tags);
10865
10866
2/2
✓ Branch 0 taken 838 times.
✓ Branch 1 taken 69 times.
907 if (sc->extradata)
10867
2/2
✓ Branch 0 taken 855 times.
✓ Branch 1 taken 838 times.
1693 for (int i = 0; i < sc->stsd_count; i++)
10868 855 av_free(sc->extradata[i]);
10869 907 av_freep(&sc->extradata);
10870 907 av_freep(&sc->extradata_size);
10871
10872 907 mov_free_encryption_index(&sc->cenc.encryption_index);
10873 907 av_encryption_info_free(sc->cenc.default_encrypted_sample);
10874 907 av_aes_ctr_free(sc->cenc.aes_ctr);
10875
10876 907 av_freep(&sc->stereo3d);
10877 907 av_freep(&sc->spherical);
10878 907 av_freep(&sc->mastering);
10879 907 av_freep(&sc->coll);
10880 907 av_freep(&sc->ambient);
10881
10882 #if CONFIG_IAMFDEC
10883
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 895 times.
907 if (sc->iamf)
10884 12 ff_iamf_read_deinit(sc->iamf);
10885 #endif
10886 907 av_freep(&sc->iamf);
10887 }
10888
10889 625 static int mov_read_close(AVFormatContext *s)
10890 {
10891 625 MOVContext *mov = s->priv_data;
10892 int i, j;
10893
10894
2/2
✓ Branch 0 taken 959 times.
✓ Branch 1 taken 625 times.
1584 for (i = 0; i < s->nb_streams; i++) {
10895 959 AVStream *st = s->streams[i];
10896
10897 959 mov_free_stream_context(s, st);
10898 }
10899
10900 625 av_freep(&mov->dv_demux);
10901 625 avformat_free_context(mov->dv_fctx);
10902 625 mov->dv_fctx = NULL;
10903
10904
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 611 times.
625 if (mov->meta_keys) {
10905
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 14 times.
114 for (i = 1; i < mov->meta_keys_count; i++) {
10906 100 av_freep(&mov->meta_keys[i]);
10907 }
10908 14 av_freep(&mov->meta_keys);
10909 }
10910
10911 625 av_freep(&mov->trex_data);
10912 625 av_freep(&mov->bitrates);
10913
10914
2/2
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 625 times.
1111 for (i = 0; i < mov->frag_index.nb_items; i++) {
10915 486 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
10916
2/2
✓ Branch 0 taken 786 times.
✓ Branch 1 taken 486 times.
1272 for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) {
10917 786 mov_free_encryption_index(&frag[j].encryption_index);
10918 }
10919 486 av_freep(&mov->frag_index.item[i].stream_info);
10920 }
10921 625 av_freep(&mov->frag_index.item);
10922
10923 625 av_freep(&mov->aes_decrypt);
10924 625 av_freep(&mov->chapter_tracks);
10925
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 625 times.
702 for (i = 0; i < mov->nb_heif_item; i++) {
10926
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (!mov->heif_item[i])
10927 ✗ continue;
10928 77 av_freep(&mov->heif_item[i]->name);
10929 77 av_freep(&mov->heif_item[i]->iref_from_list);
10930 77 av_freep(&mov->heif_item[i]->iref_to_list);
10931 77 av_freep(&mov->heif_item[i]->icc_profile);
10932 77 av_exif_free(&mov->heif_item[i]->ifd);
10933 77 av_freep(&mov->heif_item[i]);
10934 }
10935 625 av_freep(&mov->heif_item);
10936
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 625 times.
638 for (i = 0; i < mov->nb_heif_group; i++) {
10937 13 av_freep(&mov->heif_group[i].item_id_list);
10938 13 av_freep(&mov->heif_group[i].item_idx_list);
10939 13 av_freep(&mov->heif_group[i].item_list);
10940 }
10941 625 av_freep(&mov->heif_group);
10942
10943 625 return 0;
10944 }
10945
10946 28 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
10947 {
10948 int i;
10949
10950
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 for (i = 0; i < s->nb_streams; i++) {
10951 28 AVStream *st = s->streams[i];
10952 28 MOVStreamContext *sc = st->priv_data;
10953 28 MovTref *tag = mov_find_tref_tag(sc, MKTAG('t','m','c','d'));
10954
10955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!tag)
10956 ✗ continue;
10957
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 if (mov_find_tref_id(tag, tmcd_id))
10958 28 return 1;
10959 }
10960 ✗ return 0;
10961 }
10962
10963 /* look for a tmcd track not referenced by any video track, and export it globally */
10964 625 static void export_orphan_timecode(AVFormatContext *s)
10965 {
10966 int i;
10967
10968
2/2
✓ Branch 0 taken 959 times.
✓ Branch 1 taken 625 times.
1584 for (i = 0; i < s->nb_streams; i++) {
10969 959 AVStream *st = s->streams[i];
10970
10971
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 931 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
987 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
10972 28 !tmcd_is_referenced(s, st->id)) {
10973 ✗ AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
10974 ✗ if (tcr) {
10975 ✗ av_dict_set(&s->metadata, "timecode", tcr->value, 0);
10976 ✗ break;
10977 }
10978 }
10979 }
10980 625 }
10981
10982 3 static int read_tfra(MOVContext *mov, AVIOContext *f)
10983 {
10984 int version, fieldlength, i, j;
10985 3 int64_t pos = avio_tell(f);
10986 3 uint32_t size = avio_rb32(f);
10987 unsigned track_id, item_count;
10988
10989
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
10990 1 return 1;
10991 }
10992 2 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
10993
10994 2 version = avio_r8(f);
10995 2 avio_rb24(f);
10996 2 track_id = avio_rb32(f);
10997 2 fieldlength = avio_rb32(f);
10998 2 item_count = avio_rb32(f);
10999
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (i = 0; i < item_count; i++) {
11000 int64_t time, offset;
11001 int index;
11002 MOVFragmentStreamInfo * frag_stream_info;
11003
11004
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (avio_feof(f)) {
11005 ✗ return AVERROR_INVALIDDATA;
11006 }
11007
11008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1) {
11009 ✗ time = avio_rb64(f);
11010 ✗ offset = avio_rb64(f);
11011 } else {
11012 6 time = avio_rb32(f);
11013 6 offset = avio_rb32(f);
11014 }
11015
11016 // The first sample of each stream in a fragment is always a random
11017 // access sample. So it's entry in the tfra can be used as the
11018 // initial PTS of the fragment.
11019 6 index = update_frag_index(mov, offset);
11020 6 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
11021
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (frag_stream_info &&
11022
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
11023 6 frag_stream_info->first_tfra_pts = time;
11024
11025
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
11026 6 avio_r8(f);
11027
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
11028 6 avio_r8(f);
11029
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
11030 6 avio_r8(f);
11031 }
11032
11033 2 avio_seek(f, pos + size, SEEK_SET);
11034 2 return 0;
11035 }
11036
11037 1 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
11038 {
11039 1 int64_t stream_size = avio_size(f);
11040 1 int64_t original_pos = avio_tell(f);
11041 int64_t seek_ret;
11042 1 int ret = -1;
11043
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
11044 ✗ ret = seek_ret;
11045 ✗ goto fail;
11046 }
11047 1 c->mfra_size = avio_rb32(f);
11048 1 c->have_read_mfra_size = 1;
11049
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) {
11050 ✗ av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
11051 ✗ goto fail;
11052 }
11053
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) {
11054 ✗ ret = seek_ret;
11055 ✗ goto fail;
11056 }
11057
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != c->mfra_size) {
11058 ✗ av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
11059 ✗ goto fail;
11060 }
11061
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
11062 ✗ av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
11063 ✗ goto fail;
11064 }
11065 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
11066 do {
11067 3 ret = read_tfra(c, f);
11068
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
11069 ✗ goto fail;
11070
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 } while (!ret);
11071 1 ret = 0;
11072 1 c->frag_index.complete = 1;
11073 1 fail:
11074 1 seek_ret = avio_seek(f, original_pos, SEEK_SET);
11075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (seek_ret < 0) {
11076 ✗ av_log(c->fc, AV_LOG_ERROR,
11077 "failed to seek back after looking for mfra\n");
11078 ✗ ret = seek_ret;
11079 }
11080 1 return ret;
11081 }
11082
11083 4 static int set_exif_from_item(AVFormatContext *s,
11084 AVPacketSideData **coded_side_data, int *nb_coded_side_data,
11085 const HEIFItem *item)
11086 {
11087 AVPacketSideData *sd =
11088 4 (AVPacketSideData *)av_packet_side_data_get(*coded_side_data,
11089 *nb_coded_side_data,
11090 AV_PKT_DATA_EXIF);
11091 4 const AVExifMetadata *ifd = &item->ifd;
11092 4 AVBufferRef *buf = NULL;
11093 int64_t offset;
11094 int err;
11095
11096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sd)
11097 ✗ return 0;
11098
11099 4 err = av_exif_write(s, ifd, &buf, AV_EXIF_T_OFF);
11100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
11101 ✗ return err;
11102
11103 4 offset = AV_RB32(buf->data) + 4;
11104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (offset >= buf->size) {
11105 ✗ av_buffer_unref(&buf);
11106 ✗ return AVERROR_INVALIDDATA;
11107 }
11108 4 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
11109 4 AV_PKT_DATA_EXIF, buf->size - offset, 0);
11110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sd) {
11111 ✗ av_buffer_unref(&buf);
11112 ✗ return AVERROR(ENOMEM);
11113 }
11114 4 memcpy(sd->data, buf->data + offset, buf->size - offset);
11115
11116 4 av_buffer_unref(&buf);
11117
11118 4 return 0;
11119 }
11120
11121 4 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
11122 const HEIFItem *item)
11123 {
11124 AVPacketSideData *sd =
11125 4 (AVPacketSideData *)av_packet_side_data_get(*coded_side_data,
11126 *nb_coded_side_data,
11127 AV_PKT_DATA_ICC_PROFILE);
11128
11129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sd)
11130 ✗ return 0;
11131
11132 4 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
11133 AV_PKT_DATA_ICC_PROFILE,
11134 4 item->icc_profile_size, 0);
11135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sd)
11136 ✗ return AVERROR(ENOMEM);
11137
11138 4 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
11139
11140 4 return 0;
11141 }
11142
11143 6 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
11144 const HEIFItem *item)
11145 {
11146 int32_t *matrix;
11147 AVPacketSideData *sd =
11148 6 (AVPacketSideData *)av_packet_side_data_get(*coded_side_data,
11149 *nb_coded_side_data,
11150 AV_PKT_DATA_DISPLAYMATRIX);
11151
11152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (sd)
11153 ✗ return 0;
11154
11155 6 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
11156 AV_PKT_DATA_DISPLAYMATRIX,
11157 9 * sizeof(*matrix), 0);
11158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sd)
11159 ✗ return AVERROR(ENOMEM);
11160
11161 6 matrix = (int32_t*)sd->data;
11162 /* rotation is in the counter-clockwise direction whereas
11163 * av_display_rotation_set() expects its argument to be
11164 * oriented clockwise, so we need to negate it. */
11165 6 av_display_rotation_set(matrix, -item->rotation);
11166 6 av_display_matrix_flip(matrix, item->hflip, item->vflip);
11167
11168 6 return 0;
11169 }
11170
11171 7 static int read_image_grid(AVFormatContext *s, const HEIFGroup *grid,
11172 AVStreamGroupTileGrid *tile_grid)
11173 {
11174 7 MOVContext *c = s->priv_data;
11175 7 const HEIFItem *item = grid->item;
11176 7 int64_t coded_width = 0, coded_height = 0;
11177 7 int64_t offset = 0, pos = avio_tell(s->pb);
11178 7 int64_t x = 0, y = 0;
11179 7 int i = 0;
11180 int tile_rows, tile_cols;
11181 int flags, size;
11182
11183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11184 ✗ av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
11185 ✗ return AVERROR_PATCHWELCOME;
11186 }
11187
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (item->is_idat_relative) {
11188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!c->idat_offset) {
11189 ✗ av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
11190 ✗ return AVERROR_INVALIDDATA;
11191 }
11192 7 offset = c->idat_offset;
11193 }
11194
11195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (offset > INT64_MAX - item->extent_offset)
11196 ✗ return AVERROR_INVALIDDATA;
11197
11198 7 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
11199
11200 7 avio_r8(s->pb); /* version */
11201 7 flags = avio_r8(s->pb);
11202
11203 7 tile_rows = avio_r8(s->pb) + 1;
11204 7 tile_cols = avio_r8(s->pb) + 1;
11205 /* actual width and height of output image */
11206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 tile_grid->width = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
11207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 tile_grid->height = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
11208
11209 7 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
11210 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
11211
11212 7 avio_seek(s->pb, pos, SEEK_SET);
11213
11214 7 size = tile_rows * tile_cols;
11215 7 tile_grid->nb_tiles = grid->nb_items;
11216
11217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (tile_grid->nb_tiles != size)
11218 ✗ return AVERROR_INVALIDDATA;
11219
11220
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
21 for (int i = 0; i < tile_cols; i++)
11221 14 coded_width += grid->item_list[i]->width;
11222
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
21 for (int i = 0; i < size; i += tile_cols)
11223 14 coded_height += grid->item_list[i]->height;
11224
11225
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (coded_width > INT_MAX || coded_height > INT_MAX)
11226 ✗ return AVERROR_INVALIDDATA;
11227
11228 7 tile_grid->coded_width = coded_width;
11229 7 tile_grid->coded_height = coded_height;
11230
11231 7 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
11232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!tile_grid->offsets)
11233 ✗ return AVERROR(ENOMEM);
11234
11235
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
21 while (y < tile_grid->coded_height) {
11236 14 int left_col = i;
11237
11238
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 14 times.
42 while (x < tile_grid->coded_width) {
11239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (i == tile_grid->nb_tiles)
11240 ✗ return AVERROR_INVALIDDATA;
11241
11242 28 tile_grid->offsets[i].idx = grid->item_idx_list[i];
11243 28 tile_grid->offsets[i].horizontal = x;
11244 28 tile_grid->offsets[i].vertical = y;
11245
11246 28 x += grid->item_list[i++]->width;
11247 }
11248
11249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (x > tile_grid->coded_width) {
11250 ✗ av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
11251 ✗ return AVERROR_INVALIDDATA;
11252 }
11253
11254 14 x = 0;
11255 14 y += grid->item_list[left_col]->height;
11256 }
11257
11258
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (y > tile_grid->coded_height || i != tile_grid->nb_tiles) {
11259 ✗ av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
11260 ✗ return AVERROR_INVALIDDATA;
11261 }
11262
11263 7 return 0;
11264 }
11265
11266 4 static int read_image_iovl(AVFormatContext *s, const HEIFGroup *grid,
11267 AVStreamGroupTileGrid *tile_grid)
11268 {
11269 4 MOVContext *c = s->priv_data;
11270 4 const HEIFItem *item = grid->item;
11271 uint16_t canvas_fill_value[4];
11272 4 int64_t offset = 0, pos = avio_tell(s->pb);
11273 4 int ret = 0, flags;
11274
11275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11276 ✗ av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
11277 ✗ return AVERROR_PATCHWELCOME;
11278 }
11279
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
11280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
11281 ✗ av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
11282 ✗ return AVERROR_INVALIDDATA;
11283 }
11284 4 offset = c->idat_offset;
11285 }
11286
11287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (offset > INT64_MAX - item->extent_offset)
11288 ✗ return AVERROR_INVALIDDATA;
11289
11290 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
11291
11292 4 avio_r8(s->pb); /* version */
11293 4 flags = avio_r8(s->pb);
11294
11295
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
11296 16 canvas_fill_value[i] = avio_rb16(s->pb);
11297 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
11298 4 canvas_fill_value[0], canvas_fill_value[1],
11299 4 canvas_fill_value[2], canvas_fill_value[3]);
11300
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
11301 16 tile_grid->background[i] = canvas_fill_value[i];
11302
11303 /* actual width and height of output image */
11304 4 tile_grid->width =
11305
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);
11306 4 tile_grid->height =
11307
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);
11308
11309 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
11310 tile_grid->width, tile_grid->height);
11311
11312 4 tile_grid->nb_tiles = grid->nb_items;
11313 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
11314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
11315 ✗ ret = AVERROR(ENOMEM);
11316 ✗ goto fail;
11317 }
11318
11319
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
11320 8 tile_grid->offsets[i].idx = grid->item_idx_list[i];
11321
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);
11322
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);
11323 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
11324 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
11325 8 i, tile_grid->offsets[i].idx,
11326 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
11327 }
11328
11329 4 fail:
11330 4 avio_seek(s->pb, pos, SEEK_SET);
11331
11332 4 return ret;
11333 }
11334
11335 4 static int mov_parse_exif_item(AVFormatContext *s, HEIFItem *item, const HEIFItem *ref)
11336 {
11337 4 MOVContext *c = s->priv_data;
11338 4 AVExifMetadata *ifd = &item->ifd;
11339 uint8_t *buf;
11340 4 int64_t offset = 0, pos = avio_tell(s->pb);
11341 4 unsigned orientation_id = av_exif_get_tag_id("Orientation");
11342 int err;
11343
11344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11345 ✗ av_log(c->fc, AV_LOG_WARNING, "Exif metadata with non seekable input\n");
11346 ✗ return AVERROR_PATCHWELCOME;
11347 }
11348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ref->is_idat_relative) {
11349 ✗ if (!c->idat_offset) {
11350 ✗ av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the Exif metadata\n");
11351 ✗ return AVERROR_INVALIDDATA;
11352 }
11353 ✗ offset = c->idat_offset;
11354 }
11355
11356 4 buf = av_malloc(ref->extent_length);
11357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!buf)
11358 ✗ return AVERROR(ENOMEM);
11359
11360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (offset > INT64_MAX - ref->extent_offset) {
11361 ✗ err = AVERROR(ENOMEM);
11362 ✗ goto fail;
11363 }
11364
11365 4 avio_seek(s->pb, ref->extent_offset + offset, SEEK_SET);
11366 4 err = avio_read(s->pb, buf, ref->extent_length);
11367
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err != ref->extent_length) {
11368 ✗ if (err > 0)
11369 ✗ err = AVERROR_INVALIDDATA;
11370 ✗ goto fail;
11371 }
11372
11373 // HEIF spec states that Exif metadata is informative. The irot item property is
11374 // the normative source of rotation information. So we remove any Orientation tag
11375 // present in the Exif buffer.
11376 4 err = av_exif_parse_buffer(s, buf, ref->extent_length, ifd, AV_EXIF_T_OFF);
11377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0) {
11378 ✗ av_log(s, AV_LOG_ERROR, "Unable to parse Exif metadata\n");
11379 ✗ goto fail;
11380 }
11381
11382 4 err = av_exif_remove_entry(s, ifd, orientation_id, 0);
11383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
11384 ✗ goto fail;
11385
11386 4 err = 0;
11387 4 fail:
11388 4 av_free(buf);
11389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
11390 ✗ av_exif_free(ifd);
11391 4 avio_seek(s->pb, pos, SEEK_SET);
11392
11393 4 return err;
11394 }
11395
11396 66 static int mov_apply_heif_item_references(AVFormatContext *s, HEIFItem *item,
11397 AVPacketSideData **coded_side_data,
11398 int *nb_coded_side_data)
11399 {
11400 int err;
11401
11402 /* exif */
11403
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 62 times.
66 if (item->ifd.count) {
11404 4 err = set_exif_from_item(s, coded_side_data, nb_coded_side_data, item);
11405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
11406 ✗ return err;
11407 }
11408
11409 /* rotation */
11410
4/6
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 60 times.
66 if (item->rotation || item->hflip || item->vflip) {
11411 6 err = set_display_matrix_from_item(coded_side_data, nb_coded_side_data, item);
11412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
11413 ✗ return err;
11414 }
11415
11416 /* ICC profile */
11417
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 62 times.
66 if (item->icc_profile_size) {
11418 4 err = set_icc_profile_from_item(coded_side_data, nb_coded_side_data, item);
11419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
11420 ✗ return err;
11421 }
11422
11423 66 return 0;
11424 }
11425
11426 66 static int mov_parse_heif_item_references(AVFormatContext *s, HEIFItem *item,
11427 AVPacketSideData **coded_side_data,
11428 int *nb_coded_side_data)
11429 {
11430 66 MOVContext *mov = s->priv_data;
11431 int err;
11432
11433
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 66 times.
76 for (int j = 0; j < item->nb_iref_from_list; j++) {
11434 10 HEIFItem *ref = get_heif_item(mov, item->iref_from_list[j].item_id);
11435
11436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 av_assert0(ref);
11437
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
10 switch(ref->type) {
11438 4 case MKTAG('E','x','i','f'):
11439 4 err = mov_parse_exif_item(s, item, ref);
11440
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 if (err < 0 && (s->error_recognition & AV_EF_EXPLODE))
11441 ✗ return err;
11442 4 break;
11443 6 default:
11444 6 break;
11445 }
11446 }
11447
11448 66 err = mov_apply_heif_item_references(s, item, coded_side_data, nb_coded_side_data);
11449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (err < 0)
11450 ✗ return err;
11451
11452 66 return 0;
11453 }
11454
11455 11 static int mov_parse_tiles(AVFormatContext *s)
11456 {
11457 11 MOVContext *mov = s->priv_data;
11458
11459
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 11 times.
24 for (int i = 0; i < mov->nb_heif_group; i++) {
11460 AVStreamGroup *stg;
11461 AVStreamGroupTileGrid *tile_grid;
11462 13 const HEIFGroup *grid = &mov->heif_group[i];
11463 int err;
11464
11465
3/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 7 times.
13 if (!grid->item || (grid->item->type != MKTAG('g','r','i','d') &&
11466
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 grid->item->type != MKTAG('i','o','v','l')))
11467 2 continue;
11468
11469 11 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
11470
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!stg)
11471 ✗ return AVERROR(ENOMEM);
11472
11473 11 stg->id = grid->item->item_id;
11474 11 tile_grid = stg->params.tile_grid;
11475
11476
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 11 times.
47 for (int j = 0; j < grid->nb_items; j++) {
11477 36 int tile_id = grid->item_id_list[j];
11478 36 HEIFItem *item = get_heif_item(mov, tile_id);
11479 AVStream *st;
11480
11481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!item) {
11482 ✗ av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
11483 "exist\n",
11484 ✗ tile_id, grid->item->item_id);
11485 ✗ ff_remove_stream_group(s, stg);
11486 ✗ stg = NULL;
11487 ✗ break;
11488 }
11489
11490 36 st = item->st;
11491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!st) {
11492 ✗ av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
11493 "reference a stream\n",
11494 ✗ tile_id, grid->item->item_id);
11495 ✗ ff_remove_stream_group(s, stg);
11496 ✗ stg = NULL;
11497 ✗ break;
11498 }
11499
11500 36 grid->item_list[j] = item;
11501 36 grid->item_idx_list[j] = stg->nb_entries;
11502
11503 36 err = avformat_stream_group_add_stream(stg, st);
11504
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 34 times.
36 if (err < 0) {
11505 int l;
11506
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
11507 ✗ return err;
11508
11509
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_entries; l++)
11510
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->entries[l]->stream->index == st->index)
11511 2 break;
11512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_entries);
11513 2 grid->item_idx_list[j] = l;
11514 }
11515
11516
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 6 times.
36 if (item->item_id != mov->primary_item_id)
11517 30 st->disposition |= AV_DISPOSITION_DEPENDENT;
11518 }
11519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!stg)
11520 ✗ continue;
11521
11522
2/3
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
11 switch (grid->item->type) {
11523 7 case MKTAG('g','r','i','d'):
11524 7 err = read_image_grid(s, grid, tile_grid);
11525 7 break;
11526 4 case MKTAG('i','o','v','l'):
11527 4 err = read_image_iovl(s, grid, tile_grid);
11528 4 break;
11529 ✗ default:
11530 ✗ av_assert0(0);
11531 }
11532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11533 ✗ return err;
11534
11535 11 err = mov_parse_heif_item_references(s, grid->item, &stg->coded_side_data,
11536 &stg->nb_coded_side_data);
11537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11538 ✗ return err;
11539
11540
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 if (grid->item->name)
11541 9 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
11542
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
11 if (grid->item->item_id == mov->primary_item_id)
11543 7 stg->disposition |= AV_DISPOSITION_DEFAULT;
11544
11545 11 grid->item->stg = stg;
11546 }
11547
11548 11 return 0;
11549 }
11550
11551 2 static int mov_parse_heif_layered_video_tmap(AVFormatContext *s, const HEIFGroup *tmap)
11552 {
11553 2 MOVContext *mov = s->priv_data;
11554 AVStreamGroup *stg;
11555 AVStreamGroupLayeredVideo *layered_video;
11556 2 AVGainMapParams *gain = NULL;
11557 2 uint8_t *payload = NULL;
11558 2 int64_t pos, offset = 0;
11559 size_t gain_size;
11560 int64_t err64;
11561 int err;
11562
11563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11564 ✗ av_log(s, AV_LOG_WARNING, "tmap box with non seekable input\n");
11565 ✗ return 0;
11566 }
11567
11568 2 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_GAIN_MAP, NULL);
11569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!stg)
11570 ✗ return AVERROR(ENOMEM);
11571
11572 2 stg->id = tmap->item->item_id;
11573 2 layered_video = stg->params.layered_video;
11574
11575
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int j = 0; j < tmap->nb_items; j++) {
11576 4 int item_id = tmap->item_id_list[j];
11577 4 HEIFItem *item = get_heif_item(mov, item_id);
11578 AVStreamGroup *child_stg;
11579 AVStream *st;
11580
11581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!item) {
11582 ✗ av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by tmap id %d doesn't "
11583 "exist\n",
11584 ✗ item_id, tmap->item->item_id);
11585 ✗ ff_remove_stream_group(s, stg);
11586 ✗ return 0;
11587 }
11588
11589 4 st = item->st;
11590 4 child_stg = item->stg;
11591
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
4 if (!st && !child_stg) {
11592 ✗ av_log(s, AV_LOG_WARNING, "HEIF item id %d from tmap id %d doesn't "
11593 "reference a stream or tmap\n",
11594 ✗ item_id, tmap->item->item_id);
11595 ✗ ff_remove_stream_group(s, stg);
11596 ✗ return 0;
11597 }
11598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 av_assert0(!st != !child_stg);
11599
11600 4 tmap->item_list[j] = item;
11601
11602
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (st)
11603 2 err = avformat_stream_group_add_stream(stg, st);
11604 else
11605 2 err = avformat_stream_group_add_stream_group(stg, child_stg);
11606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0) {
11607 ✗ if (err == AVERROR(EEXIST))
11608 ✗ err = AVERROR_INVALIDDATA;
11609
11610 ✗ return err;
11611 }
11612
11613
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if ((item->flags & MOV_INFE_FLAG_HIDDEN)) {
11614
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (st)
11615 2 st->disposition |= AV_DISPOSITION_DEPENDENT;
11616 else
11617 ✗ child_stg->disposition |= AV_DISPOSITION_DEPENDENT;
11618 }
11619 }
11620
11621 2 layered_video->width = tmap->item->width;
11622 2 layered_video->height = tmap->item->height;
11623
11624
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (tmap->item->is_idat_relative) {
11625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!mov->idat_offset) {
11626 ✗ av_log(s, AV_LOG_ERROR, "Missing idat box required by the tmap\n");
11627 ✗ return AVERROR_INVALIDDATA;
11628 }
11629 2 offset = mov->idat_offset;
11630 }
11631
11632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset > INT64_MAX - tmap->item->extent_offset)
11633 ✗ return AVERROR_INVALIDDATA;
11634
11635 2 gain = av_gain_map_params_alloc(&gain_size);
11636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!gain)
11637 ✗ return AVERROR(ENOMEM);
11638
11639 2 payload = av_malloc(tmap->item->extent_length);
11640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!payload) {
11641 ✗ return AVERROR(ENOMEM);
11642 goto fail;
11643 }
11644
11645 2 pos = avio_tell(s->pb);
11646 2 err64 = avio_seek(s->pb, tmap->item->extent_offset + offset, SEEK_SET);
11647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err64 != tmap->item->extent_offset + offset) {
11648 ✗ err64 = err64 < 0 ? err64 : AVERROR_INVALIDDATA;
11649 ✗ goto fail;
11650 }
11651 2 avio_r8(s->pb); /* version */
11652
11653 2 err = avio_read(s->pb, payload, tmap->item->extent_length);
11654
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (err == tmap->item->extent_length)
11655 2 err64 = avio_seek(s->pb, pos, SEEK_SET);
11656 else {
11657 ✗ err = err < 0 ? err : AVERROR_INVALIDDATA;
11658 ✗ goto fail;
11659 }
11660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err64 != pos) {
11661 ✗ err = err64 < 0 ? err64 : AVERROR_INVALIDDATA;
11662 ✗ goto fail;
11663 }
11664
11665 2 err = av_gain_map_params_from_iso21496(gain, payload, tmap->item->extent_length);
11666 2 av_freep(&payload);
11667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11668 ✗ goto fail;
11669
11670
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (int j = 0; j < tmap->nb_items; j++) {
11671 4 HEIFItem *item = tmap->item_list[j];
11672 AVPacketSideData *sd;
11673 AVPacketSideData **coded_side_data;
11674 int *nb_coded_side_data;
11675
11676
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (!(item->flags & MOV_INFE_FLAG_HIDDEN))
11677 2 continue;
11678
11679 2 layered_video->el_index = j;
11680
11681
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (item->st) {
11682 2 coded_side_data = &item->st->codecpar->coded_side_data;
11683 2 nb_coded_side_data = &item->st->codecpar->nb_coded_side_data;
11684 } else {
11685 ✗ av_assert0(item->stg);
11686 ✗ coded_side_data = &item->stg->coded_side_data;
11687 ✗ nb_coded_side_data = &item->stg->nb_coded_side_data;
11688 }
11689
11690 2 sd = av_packet_side_data_add(coded_side_data, nb_coded_side_data,
11691 AV_PKT_DATA_GAIN_MAP_PARAMS,
11692 (uint8_t *)gain, gain_size, 0);
11693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!sd) {
11694 ✗ av_free(gain);
11695 ✗ return AVERROR(ENOMEM);
11696 }
11697 2 gain = NULL;
11698
11699
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (int k = 0; k < item->nb_iref_to_list; k++) {
11700 2 HEIFItem *ref = get_heif_item(mov, item->iref_to_list[k].item_id);
11701
11702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(ref);
11703 // Remove auxl reference so we don't create the same group we made with
11704 // this tmap using it. Strictly speaking, the chances for Apple style
11705 // Exif values being present on a base item referenced by a tmap item
11706 // are very low, but better safe than sorry.
11707
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (item->iref_to_list[k].type == MKTAG('a','u','x','l') &&
11708
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 (ref == tmap->item_list[!j])) {
11709
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (k != (item->nb_iref_to_list - 1))
11710 ✗ item->iref_to_list[k] = item->iref_to_list[item->nb_iref_to_list - 1];
11711 2 --item->nb_iref_to_list;
11712 2 break;
11713 }
11714 }
11715 2 break;
11716 }
11717 2 av_free(gain);
11718
11719 2 err = mov_parse_heif_item_references(s, tmap->item, &stg->coded_side_data,
11720 &stg->nb_coded_side_data);
11721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11722 ✗ return err;
11723
11724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tmap->item->name)
11725 ✗ av_dict_set(&stg->metadata, "title", tmap->item->name, 0);
11726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tmap->item->item_id == mov->primary_item_id)
11727 ✗ stg->disposition |= AV_DISPOSITION_DEFAULT;
11728
11729 2 tmap->item->stg = stg;
11730
11731 2 return 0;
11732 ✗ fail:
11733 ✗ av_free(gain);
11734 ✗ av_free(payload);
11735
11736 ✗ return err;
11737 }
11738
11739 // Parse Apple style Gain Map metadata from Exif values
11740 // See https://developer.apple.com/documentation/appkit/applying-apple-hdr-effect-to-your-photos
11741 ✗ static int mov_parse_heif_layered_video_auxl(AVFormatContext *s,
11742 HEIFItem *base, HEIFItem *gain_map)
11743 {
11744 AVStreamGroupLayeredVideo *layered_video;
11745 AVStreamGroup *stg;
11746 AVGainMapParams *gain;
11747 AVPacketSideData **coded_side_data;
11748 int *nb_coded_side_data;
11749 ✗ AVExifEntry *entry, *maker33 = NULL, *maker48 = NULL;
11750 ✗ double maker_33 = 0.0, maker_48 = 0.0, headroom;
11751 size_t gain_size;
11752 int err;
11753
11754 ✗ if ((!gain_map->st && !gain_map->stg) ||
11755 ✗ (!base->st && !base->stg)) {
11756 ✗ av_log(s, AV_LOG_WARNING, "HEIF gain_map id %d or its base doesn't reference "
11757 "a stream or group\n",
11758 gain_map->item_id);
11759 ✗ return 0;
11760 }
11761
11762 ✗ if (!base->ifd.count)
11763 ✗ return 0;
11764
11765 ✗ err = av_exif_get_entry(s, &base->ifd, 0x8769, 0, &entry);
11766 ✗ if (err > 0)
11767 ✗ err = av_exif_get_entry(s, &entry->value.ifd, 0x927c, 0, &entry);
11768 ✗ if (err > 0) {
11769 ✗ av_exif_get_entry(s, &entry->value.ifd, 0x21, 0, &maker33);
11770 ✗ av_exif_get_entry(s, &entry->value.ifd, 0x30, 0, &maker48);
11771 }
11772 ✗ if ((!maker33 && !maker48) ||
11773 ✗ (maker33 && maker33->type != AV_TIFF_SRATIONAL) ||
11774 ✗ (maker48 && maker48->type != AV_TIFF_SRATIONAL))
11775 ✗ return 0;
11776
11777 ✗ if (maker33)
11778 ✗ maker_33 = av_q2d(*maker33->value.rat);
11779 ✗ if (maker48)
11780 ✗ maker_48 = av_q2d(*maker48->value.rat);
11781
11782 ✗ if (maker_33 < 1.0) {
11783 ✗ if (maker_48 <= 0.01) {
11784 ✗ headroom = -20.0 * maker_48 + 1.8;
11785 } else {
11786 ✗ headroom = -0.101 * maker_48 + 1.601;
11787 }
11788 } else {
11789 ✗ if (maker_48 <= 0.01) {
11790 ✗ headroom = -70.0 * maker_48 + 3.0;
11791 } else {
11792 ✗ headroom = -0.303 * maker_48 + 2.303;
11793 }
11794 }
11795 ✗ if (headroom <= 0.0)
11796 ✗ return 0;
11797
11798 ✗ stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_GAIN_MAP, NULL);
11799 ✗ if (!stg)
11800 ✗ return AVERROR(ENOMEM);
11801
11802 ✗ stg->id = gain_map->item_id;
11803 ✗ layered_video = stg->params.layered_video;
11804
11805 ✗ layered_video->width = base->width;
11806 ✗ layered_video->height = base->height;
11807 ✗ layered_video->el_index = 1;
11808
11809 ✗ av_assert0(!base->st != !base->stg);
11810 ✗ if (base->st)
11811 ✗ err = avformat_stream_group_add_stream(stg, base->st);
11812 else
11813 ✗ err = avformat_stream_group_add_stream_group(stg, base->stg);
11814 ✗ if (err < 0) {
11815 ✗ if (err == AVERROR(EEXIST))
11816 ✗ err = AVERROR_INVALIDDATA;
11817 ✗ return err;
11818 }
11819
11820 ✗ av_assert0(!gain_map->st != !gain_map->stg);
11821 ✗ if (gain_map->st) {
11822 ✗ coded_side_data = &gain_map->st->codecpar->coded_side_data;
11823 ✗ nb_coded_side_data = &gain_map->st->codecpar->nb_coded_side_data;
11824 ✗ err = avformat_stream_group_add_stream(stg, gain_map->st);
11825 } else {
11826 ✗ coded_side_data = &gain_map->stg->coded_side_data;
11827 ✗ nb_coded_side_data = &gain_map->stg->nb_coded_side_data;
11828 ✗ err = avformat_stream_group_add_stream_group(stg, gain_map->stg);
11829 }
11830 ✗ if (err < 0) {
11831 ✗ if (err == AVERROR(EEXIST))
11832 ✗ err = AVERROR_INVALIDDATA;
11833 ✗ return err;
11834 }
11835
11836 ✗ gain = av_gain_map_params_alloc(&gain_size);
11837 ✗ if (!gain)
11838 ✗ return AVERROR(ENOMEM);
11839
11840 ✗ gain->use_base_color_space = 1;
11841 ✗ gain->alternate_hdr_headroom = av_d2q(headroom, INT_MAX);
11842 ✗ gain->nb_channels = 1;
11843 ✗ gain->channels[0].base_offset = (AVRational) { 0, 1 };
11844 ✗ gain->channels[0].alternate_offset = (AVRational) { 0, 1 };
11845 ✗ gain->channels[0].gain_map_max = gain->alternate_hdr_headroom;
11846
11847 ✗ AVPacketSideData *sd = av_packet_side_data_add(coded_side_data, nb_coded_side_data,
11848 AV_PKT_DATA_GAIN_MAP_PARAMS,
11849 (uint8_t *)gain, gain_size, 0);
11850 ✗ if (!sd) {
11851 ✗ av_free(gain);
11852 ✗ return AVERROR(ENOMEM);
11853 }
11854
11855 // Apply all references from the base image except Exif to the Gain Map group
11856 ✗ int count = base->ifd.count;
11857 ✗ base->ifd.count = 0;
11858 ✗ err = mov_apply_heif_item_references(s, base, &stg->coded_side_data,
11859 &stg->nb_coded_side_data);
11860 ✗ base->ifd.count = count;
11861 ✗ if (err < 0)
11862 ✗ return err;
11863
11864 ✗ return 0;
11865 }
11866
11867 11 static int mov_parse_heif_layered_video(AVFormatContext *s)
11868 {
11869 11 MOVContext *mov = s->priv_data;
11870 int err;
11871
11872
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 11 times.
24 for (int i = 0; i < mov->nb_heif_group; i++) {
11873 13 const HEIFGroup *tmap = &mov->heif_group[i];
11874
11875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!tmap->item)
11876 ✗ continue;
11877
11878
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
13 switch (tmap->item->type) {
11879 2 case MKTAG('t','m','a','p'):
11880 2 err = mov_parse_heif_layered_video_tmap(s, tmap);
11881
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11882 ✗ return err;
11883 2 break;
11884 11 default:
11885 11 break;
11886 }
11887 }
11888
11889
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 11 times.
66 for (int i = 0; i < mov->nb_heif_item; i++) {
11890 55 HEIFItem *item = mov->heif_item[i];
11891 int err;
11892
11893
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
55 if (!item)
11894 ✗ continue;
11895
11896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
55 for (int j = 0; j < item->nb_iref_to_list; j++) {
11897 ✗ HEIFItem *ref = get_heif_item(mov, item->iref_to_list[j].item_id);
11898
11899 ✗ av_assert0(ref);
11900 ✗ switch(item->iref_to_list[j].type) {
11901 ✗ case MKTAG('a','u','x','l'):
11902 ✗ if (!item->is_gainmap)
11903 ✗ break;
11904
11905 ✗ err = mov_parse_heif_layered_video_auxl(s, ref, item);
11906 ✗ if (err < 0)
11907 ✗ return err;
11908 ✗ break;
11909 }
11910 }
11911 }
11912
11913 11 return 0;
11914 }
11915
11916 20 static int mov_parse_heif_items(AVFormatContext *s)
11917 {
11918 20 MOVContext *mov = s->priv_data;
11919 int err;
11920
11921
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 20 times.
97 for (int i = 0; i < mov->nb_heif_item; i++) {
11922 77 HEIFItem *item = mov->heif_item[i];
11923 MOVStreamContext *sc;
11924 AVStream *st;
11925 77 int64_t offset = 0;
11926
11927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (!item)
11928 ✗ continue;
11929
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 53 times.
77 if (!item->st) {
11930 24 continue;
11931 }
11932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (item->is_idat_relative) {
11933 ✗ if (!mov->idat_offset) {
11934 ✗ av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
11935 ✗ return AVERROR_INVALIDDATA;
11936 }
11937 ✗ offset = mov->idat_offset;
11938 }
11939
11940 53 st = item->st;
11941 53 sc = st->priv_data;
11942 53 st->codecpar->width = item->width;
11943 53 st->codecpar->height = item->height;
11944
11945 53 sc->sample_size = sc->stsz_sample_size = item->extent_length;
11946 53 sc->sample_count = 1;
11947
11948 53 err = sanity_checks(s, sc, st->index);
11949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (err)
11950 ✗ return AVERROR_INVALIDDATA;
11951
11952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (offset > INT64_MAX - item->extent_offset)
11953 ✗ return AVERROR_INVALIDDATA;
11954
11955 53 sc->chunk_offsets[0] = item->extent_offset + offset;
11956
11957 53 err = mov_parse_heif_item_references(s, item, &st->codecpar->coded_side_data,
11958 53 &st->codecpar->nb_coded_side_data);
11959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (err < 0)
11960 ✗ return err;
11961
11962
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 10 times.
53 if (item->name)
11963 43 av_dict_set(&st->metadata, "title", item->name, 0);
11964
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 40 times.
53 if (item->item_id == mov->primary_item_id)
11965 13 st->disposition |= AV_DISPOSITION_DEFAULT;
11966
11967 53 mov_build_index(mov, st);
11968 }
11969
11970
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 9 times.
20 if (mov->nb_heif_group) {
11971 11 err = mov_parse_tiles(s);
11972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11973 ✗ return err;
11974
11975 11 err = mov_parse_heif_layered_video(s);
11976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11977 ✗ return err;
11978 }
11979
11980 20 return 0;
11981 }
11982
11983 625 static int mov_parse_tmcd_streams(AVFormatContext *s)
11984 {
11985 int err;
11986
11987
2/2
✓ Branch 0 taken 959 times.
✓ Branch 1 taken 625 times.
1584 for (int i = 0; i < s->nb_streams; i++) {
11988 AVStreamGroup *stg;
11989 const AVDictionaryEntry *tcr;
11990 959 AVStream *st = s->streams[i];
11991
11992
2/2
✓ Branch 0 taken 931 times.
✓ Branch 1 taken 28 times.
959 if (st->codecpar->codec_tag != MKTAG('t','m','c','d'))
11993 931 continue;
11994
11995 28 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TREF, NULL);
11996
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!stg)
11997 ✗ return AVERROR(ENOMEM);
11998
11999 28 stg->id = st->id;
12000 28 tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
12001
12002
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 28 times.
134 for (int j = 0; j < s->nb_streams; j++) {
12003 106 AVStream *st2 = s->streams[j];
12004 106 MOVStreamContext *sc2 = st2->priv_data;
12005 106 MovTref *tag = mov_find_tref_tag(sc2, MKTAG('t','m','c','d'));
12006
12007
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 29 times.
106 if (!tag)
12008 77 continue;
12009
12010
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 29 times.
88 for (int k = 0; k < tag->nb_id; k++) {
12011
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 29 times.
59 if (tag->id[k] != st->id)
12012 30 continue;
12013
12014 29 err = avformat_stream_group_add_stream(stg, st2);
12015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (err < 0)
12016 ✗ return err;
12017
12018
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (tcr)
12019 29 av_dict_set(&st2->metadata, "timecode", tcr->value, AV_DICT_DONT_OVERWRITE);
12020 }
12021 }
12022
12023
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!stg->nb_entries) {
12024 ✗ ff_remove_stream_group(s, stg);
12025 ✗ continue;
12026 }
12027
12028 28 err = avformat_stream_group_add_stream(stg, st);
12029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (err < 0)
12030 ✗ return err;
12031
12032 28 stg->params.tref->metadata_index = stg->nb_entries - 1;
12033 }
12034 625 export_orphan_timecode(s);
12035
12036 625 return 0;
12037 }
12038
12039 11 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
12040 uint32_t *tref_id, int nb_tref_id, int first_index)
12041 {
12042
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!nb_tref_id)
12043 ✗ return NULL;
12044
12045
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 for (int i = first_index; i < s->nb_streams; i++)
12046
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 for (int j = 0; j < nb_tref_id; j++)
12047
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (s->streams[i]->index != st->index &&
12048
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 s->streams[i]->id == tref_id[j])
12049 11 return s->streams[i];
12050
12051 ✗ return NULL;
12052 }
12053
12054 625 static int mov_parse_cdsc_and_rndr_streams(AVFormatContext *s)
12055 {
12056 static const uint32_t tref_tags[] = {
12057 MKTAG('c','d','s','c'),
12058 MKTAG('r','n','d','r'),
12059 };
12060
12061 int err;
12062
12063 // Don't try to add a group if there's only one track
12064
2/2
✓ Branch 0 taken 503 times.
✓ Branch 1 taken 122 times.
625 if (s->nb_streams <= 1)
12065 503 return 0;
12066
12067
2/2
✓ Branch 0 taken 456 times.
✓ Branch 1 taken 122 times.
578 for (int i = 0; i < s->nb_streams; i++) {
12068 456 AVStream *st = s->streams[i];
12069 456 MOVStreamContext *sc = st->priv_data;
12070
12071
2/2
✓ Branch 0 taken 912 times.
✓ Branch 1 taken 456 times.
1368 for (int c = 0; c < FF_ARRAY_ELEMS(tref_tags); c++) {
12072 AVStreamGroup *stg;
12073 AVStream *st_ref;
12074 912 MovTref *tag = mov_find_tref_tag(sc, tref_tags[c]);
12075
12076
2/2
✓ Branch 0 taken 901 times.
✓ Branch 1 taken 11 times.
912 if (!tag)
12077 901 continue;
12078
12079 11 st_ref = mov_find_reference_track(s, st, tag->id, tag->nb_id, 0);
12080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!st_ref) {
12081 ✗ av_log(s, AV_LOG_WARNING, "Failed to find referenced stream\n");
12082 ✗ continue;
12083 }
12084
12085 11 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TREF, NULL);
12086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!stg)
12087 ✗ return AVERROR(ENOMEM);
12088
12089 11 stg->id = st_ref->id;
12090
12091 11 err = avformat_stream_group_add_stream(stg, st_ref);
12092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
12093 ✗ return err;
12094
12095 11 err = avformat_stream_group_add_stream(stg, st);
12096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
12097 ✗ return err;
12098
12099 11 stg->params.tref->metadata_index = stg->nb_entries - 1;
12100 }
12101 }
12102
12103 122 return 0;
12104 }
12105
12106 625 static int mov_parse_lcevc_streams(AVFormatContext *s)
12107 {
12108 int err;
12109
12110 // Don't try to add a group if there's only one track
12111
2/2
✓ Branch 0 taken 503 times.
✓ Branch 1 taken 122 times.
625 if (s->nb_streams <= 1)
12112 503 return 0;
12113
12114
2/2
✓ Branch 0 taken 456 times.
✓ Branch 1 taken 122 times.
578 for (int i = 0; i < s->nb_streams; i++) {
12115 AVStreamGroup *stg;
12116 456 AVStream *st = s->streams[i];
12117 AVStream *st_base;
12118 456 MOVStreamContext *sc = st->priv_data;
12119 456 MovTref *tag = mov_find_tref_tag(sc, MKTAG('s','b','a','s'));
12120 456 int j = 0;
12121
12122 /* Find an enhancement stream. */
12123
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 456 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
456 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC || !tag)
12124 456 continue;
12125
12126 ✗ stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
12127 ✗ if (!stg)
12128 ✗ return AVERROR(ENOMEM);
12129
12130 ✗ stg->id = st->id;
12131 ✗ stg->params.layered_video->width = st->codecpar->width;
12132 ✗ stg->params.layered_video->height = st->codecpar->height;
12133
12134 ✗ while (st_base = mov_find_reference_track(s, st, tag->id, tag->nb_id, j)) {
12135 ✗ err = avformat_stream_group_add_stream(stg, st_base);
12136 ✗ if (err < 0)
12137 ✗ return err;
12138
12139 ✗ j = st_base->index + 1;
12140 }
12141 ✗ if (!j) {
12142 ✗ int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
12143 ✗ av_log(s, loglevel, "Failed to find base stream for LCEVC stream\n");
12144 ✗ ff_remove_stream_group(s, stg);
12145 ✗ if (s->error_recognition & AV_EF_EXPLODE)
12146 ✗ return AVERROR_INVALIDDATA;
12147 ✗ continue;
12148 }
12149
12150 ✗ err = avformat_stream_group_add_stream(stg, st);
12151 ✗ if (err < 0)
12152 ✗ return err;
12153
12154 ✗ stg->params.layered_video->el_index = stg->nb_entries - 1;
12155 }
12156
12157 122 return 0;
12158 }
12159
12160 625 static int mov_parse_dovi_streams(AVFormatContext *s)
12161 {
12162 int err;
12163
12164
2/2
✓ Branch 0 taken 503 times.
✓ Branch 1 taken 122 times.
625 if (s->nb_streams <= 1)
12165 503 return 0;
12166
12167 /* Identify legacy dual-track Dolby Vision profile 7 carriage per Annex
12168 * C of "Dolby Vision Streams Within the ISO Base Media File Format",
12169 * v2.7.1. The 'vdep' track reference type is shared with depth video
12170 * and multi-view dependencies. The spec-mandated DV-specific sample
12171 * entry combined with the dvcC configuration record disambiguates
12172 * those uses. */
12173
2/2
✓ Branch 0 taken 456 times.
✓ Branch 1 taken 122 times.
578 for (int i = 0; i < s->nb_streams; i++) {
12174 AVStreamGroup *stg;
12175 456 AVStream *st = s->streams[i];
12176 AVStream *st_base;
12177 456 MOVStreamContext *sc = st->priv_data;
12178 456 MovTref *tag = mov_find_tref_tag(sc, MKTAG('v','d','e','p'));
12179 const AVPacketSideData *sd;
12180 const AVDOVIDecoderConfigurationRecord *dovi;
12181
12182
3/4
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 404 times.
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
456 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !tag)
12183 456 continue;
12184
12185 ✗ if (st->codecpar->codec_tag != MKTAG('d','v','h','e') &&
12186 ✗ st->codecpar->codec_tag != MKTAG('d','v','h','1'))
12187 ✗ continue;
12188
12189 ✗ sd = av_packet_side_data_get(st->codecpar->coded_side_data,
12190 ✗ st->codecpar->nb_coded_side_data,
12191 AV_PKT_DATA_DOVI_CONF);
12192 ✗ if (!sd)
12193 ✗ continue;
12194 ✗ dovi = (const AVDOVIDecoderConfigurationRecord *)sd->data;
12195
12196 /* EL track of a dual-track stream: rpu_present_flag = 1,
12197 * el_present_flag = 1, bl_present_flag = 0, dv_profile = 7. */
12198 ✗ if (dovi->dv_profile != 7 || !dovi->rpu_present_flag ||
12199 ✗ !dovi->el_present_flag || dovi->bl_present_flag)
12200 ✗ continue;
12201
12202 ✗ st_base = mov_find_reference_track(s, st, tag->id, tag->nb_id, 0);
12203 ✗ if (!st_base) {
12204 ✗ int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
12205 ✗ av_log(s, loglevel, "Failed to find base layer for Dolby Vision EL stream\n");
12206 ✗ if (s->error_recognition & AV_EF_EXPLODE)
12207 ✗ return AVERROR_INVALIDDATA;
12208 ✗ continue;
12209 }
12210
12211 ✗ stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_DOLBY_VISION, NULL);
12212 ✗ if (!stg)
12213 ✗ return AVERROR(ENOMEM);
12214
12215 ✗ stg->id = st->id;
12216
12217 ✗ err = avformat_stream_group_add_stream(stg, st_base);
12218 ✗ if (err < 0)
12219 ✗ return err;
12220
12221 ✗ err = avformat_stream_group_add_stream(stg, st);
12222 ✗ if (err < 0)
12223 ✗ return err;
12224
12225 ✗ stg->params.layered_video->el_index = stg->nb_entries - 1;
12226 ✗ stg->params.layered_video->width = st_base->codecpar->width;
12227 ✗ stg->params.layered_video->height = st_base->codecpar->height;
12228 }
12229
12230 122 return 0;
12231 }
12232
12233 625 static void fix_stream_ids(AVFormatContext *s)
12234 {
12235 625 int highest_id = 0, lowest_iamf_id = INT_MAX;
12236
12237
2/2
✓ Branch 0 taken 959 times.
✓ Branch 1 taken 625 times.
1584 for (int i = 0; i < s->nb_streams; i++) {
12238 959 const AVStream *st = s->streams[i];
12239 959 const MOVStreamContext *sc = st->priv_data;
12240
2/2
✓ Branch 0 taken 895 times.
✓ Branch 1 taken 64 times.
959 if (!sc->iamf)
12241 895 highest_id = FFMAX(highest_id, st->id);
12242 }
12243
12244
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 625 times.
701 for (int i = 0; i < s->nb_stream_groups; i++) {
12245 76 AVStreamGroup *stg = s->stream_groups[i];
12246
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
12247 64 continue;
12248
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_entries; j++) {
12249 64 AVStream *st = stg->entries[j]->stream;
12250 64 lowest_iamf_id = FFMIN(lowest_iamf_id, st->id);
12251 }
12252 }
12253
12254
2/2
✓ Branch 0 taken 617 times.
✓ Branch 1 taken 8 times.
625 if (highest_id < lowest_iamf_id)
12255 617 return;
12256
12257 8 highest_id += !lowest_iamf_id;
12258
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++) {
12259 4 AVStreamGroup *stg = s->stream_groups[i];
12260
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
12261 2 continue;
12262
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_entries; j++) {
12263 14 AVStream *st = stg->entries[j]->stream;
12264 14 MOVStreamContext *sc = st->priv_data;
12265 14 st->id += highest_id;
12266 14 sc->iamf_stream_offset = highest_id;
12267 }
12268 }
12269 }
12270
12271 625 static int mov_read_header(AVFormatContext *s)
12272 {
12273 625 MOVContext *mov = s->priv_data;
12274 625 AVIOContext *pb = s->pb;
12275 int j, err;
12276 625 MOVAtom atom = { AV_RL32("root") };
12277 int i;
12278
12279 625 mov->fc = s;
12280 625 mov->trak_index = -1;
12281 625 mov->primary_item_id = -1;
12282 625 mov->cur_item_id = -1;
12283 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
12284
2/2
✓ Branch 0 taken 623 times.
✓ Branch 1 taken 2 times.
625 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
12285 623 atom.size = avio_size(pb);
12286 else
12287 2 atom.size = INT64_MAX;
12288
12289 /* check MOV header */
12290 do {
12291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
625 if (mov->moov_retry)
12292 ✗ avio_seek(pb, 0, SEEK_SET);
12293
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 625 times.
625 if ((err = mov_read_default(mov, pb, atom)) < 0) {
12294 ✗ av_log(s, AV_LOG_ERROR, "error reading header\n");
12295 ✗ return err;
12296 }
12297 1248 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
12298
6/10
✓ Branch 0 taken 623 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 603 times.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
625 !mov->found_moov && (!mov->found_iloc || !mov->found_iinf) && !mov->moov_retry++);
12299
3/6
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 605 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
625 if (!mov->found_moov && !mov->found_iloc && !mov->found_iinf) {
12300 ✗ av_log(s, AV_LOG_ERROR, "moov atom not found\n");
12301 ✗ return AVERROR_INVALIDDATA;
12302 }
12303 625 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
12304
12305
3/4
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 605 times.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
625 if (mov->found_iloc && mov->found_iinf) {
12306 20 err = mov_parse_heif_items(s);
12307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (err < 0)
12308 ✗ return err;
12309 }
12310 // prevent iloc and iinf boxes from being parsed while reading packets.
12311 // this is needed because an iinf box may have been parsed but ignored
12312 // for having old infe boxes which create no streams.
12313 625 mov->found_iloc = mov->found_iinf = 1;
12314
12315
2/2
✓ Branch 0 taken 623 times.
✓ Branch 1 taken 2 times.
625 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
12316
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 621 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
623 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
12317 2 mov_read_chapters(s);
12318
2/2
✓ Branch 0 taken 858 times.
✓ Branch 1 taken 623 times.
1481 for (i = 0; i < s->nb_streams; i++)
12319
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 830 times.
858 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
12320 28 mov_read_timecode_track(s, s->streams[i]);
12321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 830 times.
830 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
12322 ✗ mov_read_rtmd_track(s, s->streams[i]);
12323 }
12324 }
12325
12326 /* Create metadata stream groups. */
12327 625 err = mov_parse_cdsc_and_rndr_streams(s);
12328
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
625 if (err < 0)
12329 ✗ return err;
12330
12331 /* copy timecode metadata from tmcd tracks to the related video streams */
12332 625 err = mov_parse_tmcd_streams(s);
12333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
625 if (err < 0)
12334 ✗ return err;
12335
12336 /* Create LCEVC stream groups. */
12337 625 err = mov_parse_lcevc_streams(s);
12338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
625 if (err < 0)
12339 ✗ return err;
12340
12341 /* Create Dolby Vision Profile 7 stream groups. */
12342 625 err = mov_parse_dovi_streams(s);
12343
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
625 if (err < 0)
12344 ✗ return err;
12345
12346
2/2
✓ Branch 0 taken 959 times.
✓ Branch 1 taken 625 times.
1584 for (i = 0; i < s->nb_streams; i++) {
12347 959 AVStream *st = s->streams[i];
12348 959 FFStream *const sti = ffstream(st);
12349 959 MOVStreamContext *sc = st->priv_data;
12350 959 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
12351 959 fix_timescale(mov, sc);
12352
12353 /* Set the primary extradata based on the first Sample if it doesn't reference the first stsd entry. */
12354
6/6
✓ Branch 0 taken 809 times.
✓ Branch 1 taken 150 times.
✓ Branch 2 taken 756 times.
✓ Branch 3 taken 53 times.
✓ Branch 4 taken 692 times.
✓ Branch 5 taken 64 times.
959 if (sc->stsc_count && sc->extradata_size && !sc->iamf &&
12355
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 689 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
692 sc->stsc_data[0].id > 1 && sc->stsc_data[0].id <= sc->stsd_count) {
12356 3 sc->last_stsd_index = sc->stsc_data[0].id - 1;
12357 3 av_freep(&st->codecpar->extradata);
12358 3 st->codecpar->extradata_size = sc->extradata_size[sc->last_stsd_index];
12359
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (sc->extradata_size[sc->last_stsd_index]) {
12360 3 st->codecpar->extradata = av_mallocz(sc->extradata_size[sc->last_stsd_index] + AV_INPUT_BUFFER_PADDING_SIZE);
12361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata)
12362 ✗ return AVERROR(ENOMEM);
12363 3 memcpy(st->codecpar->extradata, sc->extradata[sc->last_stsd_index], sc->extradata_size[sc->last_stsd_index]);
12364 }
12365 }
12366
12367
2/2
✓ Branch 0 taken 449 times.
✓ Branch 1 taken 510 times.
959 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
12368
2/2
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 295 times.
449 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
12369 154 sti->skip_samples = st->codecpar->initial_padding;
12370 }
12371
5/6
✓ Branch 0 taken 444 times.
✓ Branch 1 taken 515 times.
✓ Branch 2 taken 375 times.
✓ Branch 3 taken 69 times.
✓ Branch 4 taken 375 times.
✗ Branch 5 not taken.
959 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
12372 375 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
12373 375 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
12374
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 947 times.
959 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
12375
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) {
12376 8 st->codecpar->width = sc->width;
12377 8 st->codecpar->height = sc->height;
12378 }
12379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
12380 ✗ st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
12381
12382 ✗ for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
12383 ✗ dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
12384
12385 ✗ err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
12386 ✗ if (err < 0)
12387 ✗ return err;
12388
12389 ✗ av_freep(&st->codecpar->extradata);
12390 ✗ st->codecpar->extradata_size = 0;
12391
12392 ✗ err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
12393 st->codecpar);
12394 ✗ if (err < 0)
12395 ✗ return err;
12396 }
12397 }
12398
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 958 times.
959 if (mov->handbrake_version &&
12399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
12400 ✗ st->codecpar->codec_id == AV_CODEC_ID_MP3) {
12401 ✗ av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
12402 ✗ sti->need_parsing = AVSTREAM_PARSE_FULL;
12403 }
12404 }
12405
12406
3/4
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 600 times.
625 if (mov->trex_data || mov->use_mfra_for > 0) {
12407
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 25 times.
158 for (i = 0; i < s->nb_streams; i++) {
12408 133 AVStream *st = s->streams[i];
12409 133 MOVStreamContext *sc = st->priv_data;
12410
2/2
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 4 times.
133 if (sc->duration_for_fps > 0) {
12411 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
12412 129 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
12413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 129 times.
129 if (st->codecpar->bit_rate == INT64_MIN) {
12414 ✗ av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
12415 sc->data_size, sc->time_scale);
12416 ✗ st->codecpar->bit_rate = 0;
12417 ✗ if (s->error_recognition & AV_EF_EXPLODE)
12418 ✗ return AVERROR_INVALIDDATA;
12419 }
12420 }
12421 }
12422 }
12423
12424
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 625 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
625 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
12425 ✗ if (mov->bitrates[i]) {
12426 ✗ s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
12427 }
12428 }
12429
12430 625 ff_rfps_calculate(s);
12431
12432
2/2
✓ Branch 0 taken 959 times.
✓ Branch 1 taken 625 times.
1584 for (i = 0; i < s->nb_streams; i++) {
12433 959 AVStream *st = s->streams[i];
12434 959 MOVStreamContext *sc = st->priv_data;
12435
12436
3/3
✓ Branch 0 taken 449 times.
✓ Branch 1 taken 444 times.
✓ Branch 2 taken 66 times.
959 switch (st->codecpar->codec_type) {
12437 449 case AVMEDIA_TYPE_AUDIO:
12438 449 err = ff_replaygain_export(st, s->metadata);
12439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 449 times.
449 if (err < 0)
12440 ✗ return err;
12441 449 break;
12442 444 case AVMEDIA_TYPE_VIDEO:
12443
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 436 times.
444 if (sc->display_matrix) {
12444
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,
12445 AV_PKT_DATA_DISPLAYMATRIX,
12446 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
12447 ✗ return AVERROR(ENOMEM);
12448
12449 8 sc->display_matrix = NULL;
12450 }
12451
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 438 times.
444 if (sc->stereo3d) {
12452
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,
12453 AV_PKT_DATA_STEREO3D,
12454 6 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
12455 ✗ return AVERROR(ENOMEM);
12456
12457 6 sc->stereo3d = NULL;
12458 }
12459
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 440 times.
444 if (sc->spherical) {
12460
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,
12461 AV_PKT_DATA_SPHERICAL,
12462 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
12463 ✗ return AVERROR(ENOMEM);
12464
12465 4 sc->spherical = NULL;
12466 }
12467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 444 times.
444 if (sc->mastering) {
12468 ✗ if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
12469 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
12470 ✗ (uint8_t *)sc->mastering, sc->mastering_size, 0))
12471 ✗ return AVERROR(ENOMEM);
12472
12473 ✗ sc->mastering = NULL;
12474 }
12475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 444 times.
444 if (sc->coll) {
12476 ✗ if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
12477 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
12478 ✗ (uint8_t *)sc->coll, sc->coll_size, 0))
12479 ✗ return AVERROR(ENOMEM);
12480
12481 ✗ sc->coll = NULL;
12482 }
12483
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 440 times.
444 if (sc->ambient) {
12484
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,
12485 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
12486 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
12487 ✗ return AVERROR(ENOMEM);
12488
12489 4 sc->ambient = NULL;
12490 }
12491 444 break;
12492 }
12493 }
12494
12495 625 fix_stream_ids(s);
12496
12497 625 ff_configure_buffers_for_index(s, AV_TIME_BASE);
12498
12499
2/2
✓ Branch 0 taken 485 times.
✓ Branch 1 taken 625 times.
1110 for (i = 0; i < mov->frag_index.nb_items; i++)
12500
2/2
✓ Branch 0 taken 475 times.
✓ Branch 1 taken 10 times.
485 if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset)
12501 475 mov->frag_index.item[i].headers_read = 1;
12502
12503 625 return 0;
12504 }
12505
12506 121563 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
12507 {
12508 121563 AVIndexEntry *sample = NULL;
12509 121563 int64_t best_dts = INT64_MAX;
12510 int i;
12511 121563 MOVContext *mov = s->priv_data;
12512
3/4
✓ Branch 0 taken 121563 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2847 times.
✓ Branch 3 taken 118716 times.
121563 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
12513
2/2
✓ Branch 0 taken 433034 times.
✓ Branch 1 taken 121563 times.
554597 for (i = 0; i < s->nb_streams; i++) {
12514 433034 AVStream *avst = s->streams[i];
12515 433034 FFStream *const avsti = ffstream(avst);
12516 433034 MOVStreamContext *msc = avst->priv_data;
12517
4/4
✓ Branch 0 taken 423517 times.
✓ Branch 1 taken 9517 times.
✓ Branch 2 taken 281165 times.
✓ Branch 3 taken 142352 times.
433034 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
12518 281165 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
12519 281165 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
12520
2/2
✓ Branch 0 taken 255977 times.
✓ Branch 1 taken 25188 times.
281165 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
12521 281165 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
12522
5/6
✓ Branch 0 taken 160197 times.
✓ Branch 1 taken 120968 times.
✓ Branch 2 taken 138600 times.
✓ Branch 3 taken 21597 times.
✓ Branch 4 taken 138600 times.
✗ Branch 5 not taken.
281165 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
12523
2/2
✓ Branch 0 taken 21597 times.
✓ Branch 1 taken 138600 times.
160197 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
12524
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 21597 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 21597 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 21597 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19410 times.
✓ Branch 9 taken 2187 times.
21597 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
12525
4/4
✓ Branch 0 taken 11302 times.
✓ Branch 1 taken 8108 times.
✓ Branch 2 taken 2187 times.
✓ Branch 3 taken 11302 times.
21597 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
12526
3/4
✓ Branch 0 taken 760 times.
✓ Branch 1 taken 1427 times.
✓ Branch 2 taken 760 times.
✗ Branch 3 not taken.
2187 (dtsdiff > AV_TIME_BASE && dts < best_dts && mov->interleaved_read)))))) {
12527 129836 sample = current_sample;
12528 129836 best_dts = dts;
12529 129836 *st = avst;
12530 }
12531 }
12532 }
12533 121563 return sample;
12534 }
12535
12536 11 static int should_retry(AVIOContext *pb, int error_code) {
12537
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))
12538 11 return 0;
12539
12540 ✗ return 1;
12541 }
12542
12543 51 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
12544 {
12545 int ret;
12546 51 MOVContext *mov = s->priv_data;
12547
12548
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 50 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
51 if (index >= 0 && index < mov->frag_index.nb_items)
12549 1 target = mov->frag_index.item[index].moof_offset;
12550
2/4
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 51 times.
51 if (target >= 0 && avio_seek(s->pb, target, SEEK_SET) != target) {
12551 ✗ av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
12552 ✗ return AVERROR_INVALIDDATA;
12553 }
12554
12555 51 mov->next_root_atom = 0;
12556
4/6
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 50 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
51 if ((index < 0 && target >= 0) || index >= mov->frag_index.nb_items)
12557 50 index = search_frag_moof_offset(&mov->frag_index, target);
12558
3/4
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 9 times.
51 if (index >= 0 && index < mov->frag_index.nb_items &&
12559
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 mov->frag_index.item[index].moof_offset == target) {
12560
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 4 times.
42 if (index + 1 < mov->frag_index.nb_items)
12561 38 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
12562
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 6 times.
42 if (mov->frag_index.item[index].headers_read)
12563 36 return 0;
12564 6 mov->frag_index.item[index].headers_read = 1;
12565 }
12566
12567 15 mov->found_mdat = 0;
12568
12569 15 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
12570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (ret < 0)
12571 ✗ return ret;
12572
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 7 times.
15 if (avio_feof(s->pb))
12573 8 return AVERROR_EOF;
12574 7 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
12575
12576 7 return 1;
12577 }
12578
12579 17 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
12580 {
12581 17 MOVStreamContext *sc = st->priv_data;
12582 uint8_t *side, *extradata;
12583 int extradata_size;
12584
12585 /* Save the current index. */
12586 17 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
12587
12588 /* Notify the decoder that extradata changed. */
12589 17 extradata_size = sc->extradata_size[sc->last_stsd_index];
12590 17 extradata = sc->extradata[sc->last_stsd_index];
12591
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) {
12592 14 side = av_packet_new_side_data(pkt,
12593 AV_PKT_DATA_NEW_EXTRADATA,
12594 extradata_size);
12595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!side)
12596 ✗ return AVERROR(ENOMEM);
12597 14 memcpy(side, extradata, extradata_size);
12598 }
12599
12600 17 return 0;
12601 }
12602
12603 ✗ static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
12604 {
12605 /* We can't make assumptions about the structure of the payload,
12606 because it may include multiple cdat and cdt2 samples. */
12607 ✗ const uint32_t cdat = AV_RB32("cdat");
12608 ✗ const uint32_t cdt2 = AV_RB32("cdt2");
12609 ✗ int ret, out_size = 0;
12610
12611 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
12612 ✗ if (src_size < 10)
12613 ✗ return AVERROR_INVALIDDATA;
12614
12615 /* avoid an int overflow: */
12616 ✗ if ((src_size - 8) / 2 >= INT_MAX / 3)
12617 ✗ return AVERROR_INVALIDDATA;
12618
12619 ✗ ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
12620 ✗ if (ret < 0)
12621 ✗ return ret;
12622
12623 /* parse and re-format the c608 payload in one pass. */
12624 ✗ while (src_size >= 10) {
12625 ✗ const uint32_t atom_size = avio_rb32(pb);
12626 ✗ const uint32_t atom_type = avio_rb32(pb);
12627 ✗ const uint32_t data_size = atom_size - 8;
12628 ✗ const uint8_t cc_field =
12629 atom_type == cdat ? 1 :
12630 atom_type == cdt2 ? 2 :
12631 0;
12632
12633 /* account for bytes consumed for atom size and type. */
12634 ✗ src_size -= 8;
12635
12636 /* make sure the data size stays within the buffer boundaries. */
12637 ✗ if (data_size < 2 || data_size > src_size) {
12638 ✗ ret = AVERROR_INVALIDDATA;
12639 ✗ break;
12640 }
12641
12642 /* make sure the data size is consistent with N byte pairs. */
12643 ✗ if (data_size % 2 != 0) {
12644 ✗ ret = AVERROR_INVALIDDATA;
12645 ✗ break;
12646 }
12647
12648 ✗ if (!cc_field) {
12649 /* neither cdat or cdt2 ... skip it */
12650 ✗ avio_skip(pb, data_size);
12651 ✗ src_size -= data_size;
12652 ✗ continue;
12653 }
12654
12655 ✗ for (uint32_t i = 0; i < data_size; i += 2) {
12656 ✗ pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
12657 ✗ pkt->data[out_size + 1] = avio_r8(pb);
12658 ✗ pkt->data[out_size + 2] = avio_r8(pb);
12659 ✗ out_size += 3;
12660 ✗ src_size -= 2;
12661 }
12662 }
12663
12664 ✗ if (src_size > 0)
12665 /* skip any remaining unread portion of the input payload */
12666 ✗ avio_skip(pb, src_size);
12667
12668 ✗ av_shrink_packet(pkt, out_size);
12669 ✗ return ret;
12670 }
12671
12672 120921 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
12673 int64_t current_index, AVPacket *pkt)
12674 {
12675 120921 MOVContext *mov = s->priv_data;
12676 120921 MOVStreamContext *sc = st->priv_data;
12677
12678 120921 pkt->stream_index = sc->ffindex;
12679 120921 pkt->dts = sample->timestamp;
12680
2/2
✓ Branch 0 taken 301 times.
✓ Branch 1 taken 120620 times.
120921 if (sample->flags & AVINDEX_DISCARD_FRAME) {
12681 301 pkt->flags |= AV_PKT_FLAG_DISCARD;
12682 }
12683
4/4
✓ Branch 0 taken 101066 times.
✓ Branch 1 taken 19855 times.
✓ Branch 2 taken 101054 times.
✓ Branch 3 taken 12 times.
120921 if (sc->stts_count && sc->tts_index < sc->tts_count)
12684 101054 pkt->duration = sc->tts_data[sc->tts_index].duration;
12685
3/4
✓ Branch 0 taken 4628 times.
✓ Branch 1 taken 116293 times.
✓ Branch 2 taken 4628 times.
✗ Branch 3 not taken.
120921 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
12686 4628 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
12687 } else {
12688
2/2
✓ Branch 0 taken 15811 times.
✓ Branch 1 taken 100482 times.
116293 if (pkt->duration == 0) {
12689 15811 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
12690
2/2
✓ Branch 0 taken 15706 times.
✓ Branch 1 taken 105 times.
15811 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
12691
2/2
✓ Branch 0 taken 15755 times.
✓ Branch 1 taken 56 times.
15811 if (next_dts >= pkt->dts)
12692 15755 pkt->duration = next_dts - pkt->dts;
12693 }
12694 116293 pkt->pts = pkt->dts;
12695 }
12696
12697
4/4
✓ Branch 0 taken 102200 times.
✓ Branch 1 taken 18721 times.
✓ Branch 2 taken 99313 times.
✓ Branch 3 taken 2887 times.
120921 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && !mov->fragment.found_tfhd &&
12698
2/2
✓ Branch 1 taken 235 times.
✓ Branch 2 taken 99078 times.
99313 sc->current_sample >= ffstream(st)->nb_index_entries) {
12699 235 int64_t pts = av_rescale_q(pkt->pts, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12700 235 int64_t total = av_rescale_q(st->duration, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12701 235 int64_t duration = pkt->duration;
12702
12703
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 233 times.
235 if (st->duration < pkt->pts) {
12704 2 duration = 0;
12705 } else
12706 233 duration = FFMIN(duration, (uint64_t)st->duration - pkt->pts);
12707
12708 235 duration = av_rescale_q(duration, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12709
12710
2/2
✓ Branch 1 taken 196 times.
✓ Branch 2 taken 39 times.
235 if (!ffstream(st)->first_discard_sample)
12711 196 ffstream(st)->first_discard_sample = av_sat_add64(pts, duration);
12712
2/2
✓ Branch 1 taken 196 times.
✓ Branch 2 taken 39 times.
235 if (!ffstream(st)->last_discard_sample)
12713 196 ffstream(st)->last_discard_sample = total;
12714 }
12715
12716
4/4
✓ Branch 0 taken 101066 times.
✓ Branch 1 taken 19855 times.
✓ Branch 2 taken 101054 times.
✓ Branch 3 taken 12 times.
120921 if (sc->tts_data && sc->tts_index < sc->tts_count) {
12717 /* update tts context */
12718 101054 sc->tts_sample++;
12719
1/2
✓ Branch 0 taken 101054 times.
✗ Branch 1 not taken.
101054 if (sc->tts_index < sc->tts_count &&
12720
1/2
✓ Branch 0 taken 101054 times.
✗ Branch 1 not taken.
101054 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
12721 101054 sc->tts_index++;
12722 101054 sc->tts_sample = 0;
12723 }
12724 }
12725
12726
4/4
✓ Branch 0 taken 1043 times.
✓ Branch 1 taken 119878 times.
✓ Branch 2 taken 911 times.
✓ Branch 3 taken 132 times.
120921 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
12727 911 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
12728 911 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
12729
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 597 times.
911 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
12730 }
12731 120921 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
12732 120921 pkt->pos = sample->pos;
12733
12734 /* Multiple stsd handling. */
12735
2/2
✓ Branch 0 taken 114724 times.
✓ Branch 1 taken 6197 times.
120921 if (sc->stsc_data) {
12736
1/2
✓ Branch 0 taken 114724 times.
✗ Branch 1 not taken.
114724 if (sc->stsc_data[sc->stsc_index].id > 0 &&
12737
2/2
✓ Branch 0 taken 114671 times.
✓ Branch 1 taken 53 times.
114724 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
12738
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 114654 times.
114671 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
12739 17 int ret = mov_change_extradata(st, pkt);
12740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (ret < 0)
12741 ✗ return ret;
12742 }
12743
12744 /* Update the stsc index for the next sample */
12745 114724 sc->stsc_sample++;
12746
2/2
✓ Branch 1 taken 56816 times.
✓ Branch 2 taken 57908 times.
114724 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
12747
2/2
✓ Branch 1 taken 1212 times.
✓ Branch 2 taken 55604 times.
56816 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
12748 1212 sc->stsc_index++;
12749 1212 sc->stsc_sample = 0;
12750 }
12751 }
12752
12753 120921 return 0;
12754 }
12755
12756 112297 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
12757 {
12758 112297 MOVContext *mov = s->priv_data;
12759 MOVStreamContext *sc;
12760 AVIndexEntry *sample;
12761 112297 AVStream *st = NULL;
12762 112297 FFStream *avsti = NULL;
12763 int64_t current_index;
12764 int ret;
12765 int i;
12766 112297 mov->fc = s;
12767 9266 retry:
12768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 121563 times.
121563 if (s->pb->pos == 0) {
12769
12770 // Discard current fragment index
12771 ✗ if (mov->frag_index.allocated_size > 0) {
12772 ✗ for(int i = 0; i < mov->frag_index.nb_items; i++) {
12773 ✗ av_freep(&mov->frag_index.item[i].stream_info);
12774 }
12775 ✗ av_freep(&mov->frag_index.item);
12776 ✗ mov->frag_index.nb_items = 0;
12777 ✗ mov->frag_index.allocated_size = 0;
12778 ✗ mov->frag_index.current = -1;
12779 ✗ mov->frag_index.complete = 0;
12780 }
12781
12782 ✗ for (i = 0; i < s->nb_streams; i++) {
12783 ✗ AVStream *avst = s->streams[i];
12784 ✗ MOVStreamContext *msc = avst->priv_data;
12785
12786 // Clear current sample
12787 ✗ mov_current_sample_set(msc, 0);
12788 ✗ msc->tts_index = 0;
12789
12790 // Discard current index entries
12791 ✗ avsti = ffstream(avst);
12792 ✗ if (avsti->index_entries_allocated_size > 0) {
12793 ✗ av_freep(&avsti->index_entries);
12794 ✗ avsti->index_entries_allocated_size = 0;
12795 ✗ avsti->nb_index_entries = 0;
12796 }
12797 }
12798
12799 ✗ if ((ret = mov_switch_root(s, -1, -1)) < 0)
12800 ✗ return ret;
12801 }
12802 121563 sample = mov_find_next_sample(s, &st);
12803
6/6
✓ Branch 0 taken 120968 times.
✓ Branch 1 taken 595 times.
✓ Branch 2 taken 3446 times.
✓ Branch 3 taken 117522 times.
✓ Branch 4 taken 36 times.
✓ Branch 5 taken 3410 times.
121563 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
12804
2/2
✓ Branch 0 taken 581 times.
✓ Branch 1 taken 50 times.
631 if (!mov->next_root_atom)
12805 581 return AVERROR_EOF;
12806
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 42 times.
50 if ((ret = mov_switch_root(s, mov->next_root_atom, -1)) < 0)
12807 8 return ret;
12808 42 goto retry;
12809 }
12810 120932 sc = st->priv_data;
12811 /* must be done just before reading, to avoid infinite loop on sample */
12812 120932 current_index = sc->current_index;
12813 120932 mov_current_sample_inc(sc);
12814
12815
2/2
✓ Branch 0 taken 3410 times.
✓ Branch 1 taken 117522 times.
120932 if (mov->next_root_atom) {
12816 3410 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
12817 3410 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
12818 }
12819
12820
4/4
✓ Branch 0 taken 9234 times.
✓ Branch 1 taken 111698 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 9224 times.
120932 if (st->discard != AVDISCARD_ALL || sc->iamf) {
12821 111708 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
12822
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 111701 times.
111708 if (ret64 != sample->pos) {
12823 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
12824 sc->ffindex, sample->pos);
12825
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
12826 ✗ mov_current_sample_dec(sc);
12827
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
12828 7 return (int)ret64;
12829 }
12830 ✗ return AVERROR_INVALIDDATA;
12831 }
12832
12833
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 111701 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
111701 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
12834 ✗ av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
12835 ✗ goto retry;
12836 }
12837
12838
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 111701 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
111701 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
12839 ✗ ret = get_eia608_packet(sc->pb, pkt, sample->size);
12840 #if CONFIG_IAMFDEC
12841
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 111619 times.
111701 else if (sc->iamf) {
12842 int64_t pts, dts, pos, duration;
12843 82 int flags, size = sample->size;
12844 82 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
12845 82 pts = pkt->pts; dts = pkt->dts;
12846 82 pos = pkt->pos; flags = pkt->flags;
12847 82 duration = pkt->duration;
12848
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) {
12849 454 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
12850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 454 times.
454 if (ret < 0) {
12851 ✗ if (should_retry(sc->pb, ret))
12852 ✗ mov_current_sample_dec(sc);
12853 ✗ return ret;
12854 }
12855 454 size -= ret;
12856
12857
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 334 times.
454 if (pkt->flags & AV_PKT_FLAG_DISCARD) {
12858 120 av_packet_unref(pkt);
12859 120 ret = 0;
12860 120 continue;
12861 }
12862 334 pkt->pts = pts; pkt->dts = dts;
12863 334 pkt->pos = pos; pkt->flags |= flags;
12864 334 pkt->duration = duration;
12865 334 ret = ff_buffer_packet(s, pkt);
12866 }
12867
1/2
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
82 if (!ret)
12868 82 return FFERROR_REDO;
12869 }
12870 #endif
12871
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 111616 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
111622 else if (st->codecpar->codec_id == AV_CODEC_ID_APV && sample->size > 4) {
12872 3 uint32_t au_size = avio_rb32(sc->pb);
12873 3 int explode = !!(mov->fc->error_recognition & AV_EF_EXPLODE);
12874
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (au_size > sample->size - 4) {
12875 ✗ av_log(s, explode ? AV_LOG_ERROR : AV_LOG_WARNING,
12876 "APV au_size %u exceeds sample body %d\n",
12877 ✗ au_size, sample->size - 4);
12878 ✗ if (explode)
12879 ✗ return AVERROR_INVALIDDATA;
12880 ✗ au_size = sample->size - 4;
12881 }
12882 3 ret = av_get_packet(sc->pb, pkt, au_size);
12883 } else
12884 111616 ret = av_get_packet(sc->pb, pkt, sample->size);
12885
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 111615 times.
111619 if (ret < 0) {
12886
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (should_retry(sc->pb, ret)) {
12887 ✗ mov_current_sample_dec(sc);
12888 }
12889 4 return ret;
12890 }
12891 #if CONFIG_DV_DEMUXER
12892
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 111615 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
111615 if (mov->dv_demux && sc->dv_audio_container) {
12893 ✗ ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
12894 ✗ av_packet_unref(pkt);
12895 ✗ if (ret < 0)
12896 ✗ return ret;
12897 ✗ ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
12898 ✗ if (ret < 0)
12899 ✗ return ret;
12900 }
12901 #endif
12902
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 111597 times.
111615 if (sc->has_palette) {
12903 uint8_t *pal;
12904
12905 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
12906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
12907 ✗ av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
12908 } else {
12909 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
12910 18 sc->has_palette = 0;
12911 }
12912 }
12913
4/6
✓ Branch 0 taken 3129 times.
✓ Branch 1 taken 108486 times.
✓ Branch 3 taken 3129 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3129 times.
✗ Branch 6 not taken.
111615 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
12914
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3129 times.
3129 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
12915 ✗ ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
12916 }
12917 }
12918
12919 120839 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
12920
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 120839 times.
120839 if (ret < 0)
12921 ✗ return ret;
12922
12923
2/2
✓ Branch 0 taken 9224 times.
✓ Branch 1 taken 111615 times.
120839 if (st->discard == AVDISCARD_ALL)
12924 9224 goto retry;
12925
12926
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111615 times.
111615 if (mov->aax_mode)
12927 ✗ aax_filter(pkt->data, pkt->size, mov);
12928
12929 111615 ret = cenc_filter(mov, st, sc, pkt, current_index);
12930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111615 times.
111615 if (ret < 0) {
12931 ✗ return ret;
12932 }
12933
12934 111615 return 0;
12935 }
12936
12937 365 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
12938 {
12939 365 MOVContext *mov = s->priv_data;
12940 int index;
12941
12942
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 28 times.
365 if (!mov->frag_index.complete)
12943 337 return 0;
12944
12945 28 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
12946
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 24 times.
28 if (index < 0)
12947 4 index = 0;
12948
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (!mov->frag_index.item[index].headers_read)
12949 1 return mov_switch_root(s, -1, index);
12950
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (index + 1 < mov->frag_index.nb_items)
12951 27 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
12952
12953 27 return 0;
12954 }
12955
12956 ✗ static int is_open_key_sample(const MOVStreamContext *sc, int sample)
12957 {
12958 // TODO: a bisect search would scale much better
12959 ✗ for (int i = 0; i < sc->open_key_samples_count; i++) {
12960 ✗ const int oks = sc->open_key_samples[i];
12961 ✗ if (oks == sample)
12962 ✗ return 1;
12963 ✗ if (oks > sample) /* list is monotically increasing so we can stop early */
12964 ✗ break;
12965 }
12966 ✗ return 0;
12967 }
12968
12969 /*
12970 * Some key sample may be key frames but not IDR frames, so a random access to
12971 * them may not be allowed.
12972 */
12973 231 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
12974 {
12975 231 MOVStreamContext *sc = st->priv_data;
12976 231 FFStream *const sti = ffstream(st);
12977 int64_t key_sample_dts, key_sample_pts;
12978
12979
1/2
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
231 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
12980 231 return 1;
12981
12982 ✗ if (sample >= sc->sample_offsets_count)
12983 ✗ return 1;
12984
12985 ✗ av_assert0(sample >= 0);
12986 ✗ key_sample_dts = sti->index_entries[sample].timestamp;
12987 ✗ key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
12988
12989 /*
12990 * If the sample needs to be presented before an open key sample, they may
12991 * not be decodable properly, even though they come after in decoding
12992 * order.
12993 */
12994 ✗ if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
12995 ✗ return 0;
12996
12997 ✗ return 1;
12998 }
12999
13000 365 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
13001 {
13002 365 MOVStreamContext *sc = st->priv_data;
13003 365 FFStream *const sti = ffstream(st);
13004 int sample, time_sample, ret, requested_sample;
13005 int64_t next_ts;
13006 unsigned int i;
13007
13008 // Here we consider timestamp to be PTS, hence try to offset it so that we
13009 // can search over the DTS timeline.
13010 365 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
13011
13012 365 ret = mov_seek_fragment(s, st, timestamp);
13013
1/2
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
365 if (ret < 0)
13014 ✗ return ret;
13015
13016 for (;;) {
13017 365 sample = av_index_search_timestamp(st, timestamp, flags);
13018 365 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
13019
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)
13020 43 sample = 0;
13021
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 339 times.
365 if (sample < 0) /* not sure what to do */
13022 26 return AVERROR_INVALIDDATA;
13023
13024
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))
13025 break;
13026
13027 ✗ next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
13028 ✗ requested_sample = av_index_search_timestamp(st, next_ts, flags);
13029 ✗ if (requested_sample < 0)
13030 ✗ return AVERROR_INVALIDDATA;
13031
13032 // If we've reached a different sample trying to find a good pts to
13033 // seek to, give up searching because we'll end up seeking back to
13034 // sample 0 on every seek.
13035 ✗ if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
13036 ✗ break;
13037
13038 ✗ timestamp = next_ts;
13039 }
13040
13041 339 mov_current_sample_set(sc, sample);
13042 339 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
13043 /* adjust time to sample index */
13044
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 125 times.
339 if (sc->tts_data) {
13045 214 time_sample = 0;
13046
1/2
✓ Branch 0 taken 60310 times.
✗ Branch 1 not taken.
60310 for (i = 0; i < sc->tts_count; i++) {
13047 60310 int next = time_sample + sc->tts_data[i].count;
13048
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 60096 times.
60310 if (next > sc->current_sample) {
13049 214 sc->tts_index = i;
13050 214 sc->tts_sample = sc->current_sample - time_sample;
13051 214 break;
13052 }
13053 60096 time_sample = next;
13054 }
13055 }
13056
13057 /* adjust stsd index */
13058
2/2
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 28 times.
339 if (sc->chunk_count) {
13059 311 time_sample = 0;
13060
1/2
✓ Branch 0 taken 383 times.
✗ Branch 1 not taken.
383 for (i = 0; i < sc->stsc_count; i++) {
13061 383 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
13062
2/2
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 72 times.
383 if (next > sc->current_sample) {
13063 311 sc->stsc_index = i;
13064 311 sc->stsc_sample = sc->current_sample - time_sample;
13065 311 break;
13066 }
13067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
13068 72 time_sample = next;
13069 }
13070 }
13071
13072 339 return sample;
13073 }
13074
13075 339 static int64_t mov_get_skip_samples(AVStream *st, int sample)
13076 {
13077 339 FFStream *const sti = ffstream(st);
13078 339 int64_t first_ts = sti->index_entries[0].timestamp;
13079 339 int64_t ts = sti->index_entries[sample].timestamp;
13080 int64_t off;
13081
13082
2/2
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 152 times.
339 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
13083 187 return 0;
13084
13085 /* compute skip samples according to stream initial_padding, seek ts and first ts */
13086 152 off = av_rescale_q(ts - first_ts, st->time_base,
13087 152 (AVRational){1, st->codecpar->sample_rate});
13088 152 return FFMAX(st->codecpar->initial_padding - off, 0);
13089 }
13090
13091 343 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
13092 {
13093 343 MOVContext *mc = s->priv_data;
13094 AVStream *st;
13095 FFStream *sti;
13096 int sample;
13097 int i;
13098
13099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 343 times.
343 if (stream_index >= s->nb_streams)
13100 ✗ return AVERROR_INVALIDDATA;
13101
13102 343 st = s->streams[stream_index];
13103 343 sti = ffstream(st);
13104 343 sample = mov_seek_stream(s, st, sample_time, flags);
13105
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 317 times.
343 if (sample < 0)
13106 26 return sample;
13107
13108
1/2
✓ Branch 0 taken 317 times.
✗ Branch 1 not taken.
317 if (mc->seek_individually) {
13109 /* adjust seek timestamp to found sample timestamp */
13110 317 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
13111 317 sti->skip_samples = mov_get_skip_samples(st, sample);
13112
13113
2/2
✓ Branch 0 taken 339 times.
✓ Branch 1 taken 317 times.
656 for (i = 0; i < s->nb_streams; i++) {
13114 339 AVStream *const st = s->streams[i];
13115 339 FFStream *const sti = ffstream(st);
13116 int64_t timestamp;
13117
13118
2/2
✓ Branch 0 taken 317 times.
✓ Branch 1 taken 22 times.
339 if (stream_index == i)
13119 317 continue;
13120
13121 22 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
13122 22 sample = mov_seek_stream(s, st, timestamp, flags);
13123
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (sample >= 0)
13124 22 sti->skip_samples = mov_get_skip_samples(st, sample);
13125 }
13126 } else {
13127 ✗ for (i = 0; i < s->nb_streams; i++) {
13128 MOVStreamContext *sc;
13129 ✗ st = s->streams[i];
13130 ✗ sc = st->priv_data;
13131 ✗ mov_current_sample_set(sc, 0);
13132 }
13133 ✗ while (1) {
13134 MOVStreamContext *sc;
13135 ✗ AVIndexEntry *entry = mov_find_next_sample(s, &st);
13136 ✗ if (!entry)
13137 ✗ return AVERROR_INVALIDDATA;
13138 ✗ sc = st->priv_data;
13139 ✗ if (sc->ffindex == stream_index && sc->current_sample == sample)
13140 ✗ break;
13141 ✗ mov_current_sample_inc(sc);
13142 }
13143 }
13144 317 return 0;
13145 }
13146
13147 #define OFFSET(x) offsetof(MOVContext, x)
13148 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
13149 static const AVOption mov_options[] = {
13150 {"use_absolute_path",
13151 "allow using absolute path when opening alias, this is a possible security issue",
13152 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
13153 0, 1, FLAGS},
13154 {"seek_streams_individually",
13155 "Seek each stream individually to the closest point",
13156 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
13157 0, 1, FLAGS},
13158 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
13159 0, 1, FLAGS},
13160 {"advanced_editlist",
13161 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
13162 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
13163 0, 1, FLAGS},
13164 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
13165 0, 1, FLAGS},
13166 {"use_mfra_for",
13167 "use mfra for fragment timestamps",
13168 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
13169 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
13170 .unit = "use_mfra_for"},
13171 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
13172 FLAGS, .unit = "use_mfra_for" },
13173 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
13174 FLAGS, .unit = "use_mfra_for" },
13175 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
13176 FLAGS, .unit = "use_mfra_for" },
13177 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
13178 0, 1, FLAGS},
13179 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
13180 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
13181 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
13182 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
13183 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
13184 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
13185 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
13186 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
13187 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
13188 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
13189 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
13190 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
13191 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
13192 .flags = AV_OPT_FLAG_DECODING_PARAM },
13193 { "decryption_key", "The default media decryption key (hex)", OFFSET(decryption_default_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
13194 { "decryption_keys", "The media decryption keys by KID (hex)", OFFSET(decryption_keys), AV_OPT_TYPE_DICT, .flags = AV_OPT_FLAG_DECODING_PARAM },
13195 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
13196 {.i64 = 0}, 0, 1, FLAGS },
13197 { "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 },
13198 { "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 },
13199
13200 { NULL },
13201 };
13202
13203 static const AVClass mov_class = {
13204 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
13205 .item_name = av_default_item_name,
13206 .option = mov_options,
13207 .version = LIBAVUTIL_VERSION_INT,
13208 };
13209
13210 const FFInputFormat ff_mov_demuxer = {
13211 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
13212 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
13213 .p.priv_class = &mov_class,
13214 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4v,m4b,ism,ismv,isma,f4v,avif,heic,heif",
13215 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
13216 .priv_data_size = sizeof(MOVContext),
13217 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
13218 .read_probe = mov_probe,
13219 .read_header = mov_read_header,
13220 .read_packet = mov_read_packet,
13221 .read_close = mov_read_close,
13222 .read_seek = mov_read_seek,
13223 };
13224