FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2026-04-24 05:04:01
Exec Total Coverage
Lines: 4519 7080 63.8%
Functions: 180 217 82.9%
Branches: 2573 4745 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
32 #include "libavutil/attributes.h"
33 #include "libavutil/bprint.h"
34 #include "libavutil/channel_layout.h"
35 #include "libavutil/internal.h"
36 #include "libavutil/intreadwrite.h"
37 #include "libavutil/intfloat.h"
38 #include "libavutil/mathematics.h"
39 #include "libavutil/avassert.h"
40 #include "libavutil/avstring.h"
41 #include "libavutil/dict.h"
42 #include "libavutil/display.h"
43 #include "libavutil/mem.h"
44 #include "libavutil/opt.h"
45 #include "libavutil/aes.h"
46 #include "libavutil/aes_ctr.h"
47 #include "libavutil/pixdesc.h"
48 #include "libavutil/sha.h"
49 #include "libavutil/spherical.h"
50 #include "libavutil/stereo3d.h"
51 #include "libavutil/timecode.h"
52 #include "libavutil/uuid.h"
53 #include "libavcodec/ac3tab.h"
54 #include "libavcodec/exif.h"
55 #include "libavcodec/flac.h"
56 #include "libavcodec/hevc/hevc.h"
57 #include "libavcodec/mpegaudiodecheader.h"
58 #include "libavcodec/mlp_parse.h"
59 #include "avformat.h"
60 #include "internal.h"
61 #include "avio_internal.h"
62 #include "demux.h"
63 #include "dvdclut.h"
64 #include "iamf_parse.h"
65 #include "iamf_reader.h"
66 #include "dovi_isom.h"
67 #include "riff.h"
68 #include "isom.h"
69 #include "libavcodec/get_bits.h"
70 #include "id3v1.h"
71 #include "mov_chan.h"
72 #include "replaygain.h"
73
74 #if CONFIG_ZLIB
75 #include <zlib.h>
76 #endif
77
78 #include "qtpalette.h"
79
80 /* those functions parse an atom */
81 /* links atom IDs to parse functions */
82 typedef struct MOVParseTableEntry {
83 uint32_t type;
84 int (*parse)(MOVContext *ctx, AVIOContext *pb, MOVAtom atom);
85 } MOVParseTableEntry;
86
87 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom);
88 static int mov_read_mfra(MOVContext *c, AVIOContext *f);
89 static void mov_free_stream_context(AVFormatContext *s, AVStream *st);
90
91 24 static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
92 unsigned len, const char *key)
93 {
94 char buf[16];
95
96 24 short current, total = 0;
97 24 avio_rb16(pb); // unknown
98 24 current = avio_rb16(pb);
99
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (len >= 6)
100 24 total = avio_rb16(pb);
101
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19 times.
24 if (!total)
102 5 snprintf(buf, sizeof(buf), "%d", current);
103 else
104 19 snprintf(buf, sizeof(buf), "%d/%d", current, total);
105 24 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
106 24 av_dict_set(&c->fc->metadata, key, buf, 0);
107
108 24 return 0;
109 }
110
111 static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
112 unsigned len, const char *key)
113 {
114 /* bypass padding bytes */
115 avio_r8(pb);
116 avio_r8(pb);
117 avio_r8(pb);
118
119 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
120 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
121
122 return 0;
123 }
124
125 26 static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
126 unsigned len, const char *key)
127 {
128 26 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
129 26 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
130
131 26 return 0;
132 }
133
134 10 static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
135 unsigned len, const char *key)
136 {
137 short genre;
138
139 10 avio_r8(pb); // unknown
140
141 10 genre = avio_r8(pb);
142
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (genre < 1 || genre > ID3v1_GENRE_MAX)
143 return 0;
144 10 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
145 10 av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
146
147 10 return 0;
148 }
149
150 static const uint32_t mac_to_unicode[128] = {
151 0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
152 0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
153 0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,
154 0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,
155 0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,
156 0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,
157 0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,
158 0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,
159 0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,
160 0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,
161 0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,
162 0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,
163 0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,
164 0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,
165 0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,
166 0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7,
167 };
168
169 352 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
170 char *dst, int dstlen)
171 {
172 352 char *p = dst;
173 352 char *end = dst+dstlen-1;
174 int i;
175
176
2/2
✓ Branch 0 taken 3093 times.
✓ Branch 1 taken 352 times.
3445 for (i = 0; i < len; i++) {
177 3093 uint8_t t, c = avio_r8(pb);
178
179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3093 times.
3093 if (p >= end)
180 continue;
181
182
2/2
✓ Branch 0 taken 3085 times.
✓ Branch 1 taken 8 times.
3093 if (c < 0x80)
183 3085 *p++ = c;
184
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 else if (p < end)
185
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;);
186 }
187 352 *p = 0;
188 352 return p - dst;
189 }
190
191 /**
192 * Get the requested item.
193 */
194 166 static HEIFItem *get_heif_item(MOVContext *c, unsigned id)
195 {
196 166 HEIFItem *item = NULL;
197
198
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 12 times.
380 for (int i = 0; i < c->nb_heif_item; i++) {
199
3/4
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 214 times.
✓ Branch 3 taken 154 times.
368 if (!c->heif_item[i] || c->heif_item[i]->item_id != id)
200 214 continue;
201
202 154 item = c->heif_item[i];
203 154 break;
204 }
205
206 166 return item;
207 }
208
209 /**
210 * Get the current stream in the parsing process. This can either be the
211 * latest stream added to the context, or the stream referenced by an item.
212 */
213 239 static AVStream *get_curr_st(MOVContext *c)
214 {
215 239 AVStream *st = NULL;
216 HEIFItem *item;
217
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 239 times.
239 if (c->fc->nb_streams < 1)
219 return NULL;
220
221
2/2
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 49 times.
239 if (c->cur_item_id == -1)
222 190 return c->fc->streams[c->fc->nb_streams-1];
223
224 49 item = get_heif_item(c, c->cur_item_id);
225
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 if (item)
226 49 st = item->st;
227
228 49 return st;
229 }
230
231 14 static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
232 {
233 AVStream *st;
234 MOVStreamContext *sc;
235 enum AVCodecID id;
236 int ret;
237
238
2/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
14 switch (type) {
239 7 case 0xd: id = AV_CODEC_ID_MJPEG; break;
240 7 case 0xe: id = AV_CODEC_ID_PNG; break;
241 case 0x1b: id = AV_CODEC_ID_BMP; break;
242 default:
243 av_log(c->fc, AV_LOG_WARNING, "Unknown cover type: 0x%x.\n", type);
244 avio_skip(pb, len);
245 return 0;
246 }
247
248 14 sc = av_mallocz(sizeof(*sc));
249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!sc)
250 return AVERROR(ENOMEM);
251 14 ret = ff_add_attached_pic(c->fc, NULL, pb, NULL, len);
252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0) {
253 av_free(sc);
254 return ret;
255 }
256 14 st = c->fc->streams[c->fc->nb_streams - 1];
257 14 st->priv_data = sc;
258 14 sc->id = st->id;
259 14 sc->refcount = 1;
260
261
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 if (st->attached_pic.size >= 8 && id != AV_CODEC_ID_BMP) {
262
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
263 7 id = AV_CODEC_ID_PNG;
264 } else {
265 7 id = AV_CODEC_ID_MJPEG;
266 }
267 }
268 14 st->codecpar->codec_id = id;
269
270 14 return 0;
271 }
272
273 // 3GPP TS 26.244
274 static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
275 {
276 char language[4] = { 0 };
277 char buf[200], place[100];
278 uint16_t langcode = 0;
279 double longitude, latitude, altitude;
280 const char *key = "location";
281
282 if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) {
283 av_log(c->fc, AV_LOG_ERROR, "loci too short\n");
284 return AVERROR_INVALIDDATA;
285 }
286
287 avio_skip(pb, 4); // version+flags
288 langcode = avio_rb16(pb);
289 ff_mov_lang_to_iso639(langcode, language);
290 len -= 6;
291
292 len -= avio_get_str(pb, len, place, sizeof(place));
293 if (len < 1) {
294 av_log(c->fc, AV_LOG_ERROR, "place name too long\n");
295 return AVERROR_INVALIDDATA;
296 }
297 avio_skip(pb, 1); // role
298 len -= 1;
299
300 if (len < 12) {
301 av_log(c->fc, AV_LOG_ERROR,
302 "loci too short (%u bytes left, need at least %d)\n", len, 12);
303 return AVERROR_INVALIDDATA;
304 }
305 longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
306 latitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
307 altitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
308
309 // Try to output in the same format as the ?xyz field
310 snprintf(buf, sizeof(buf), "%+08.4f%+09.4f", latitude, longitude);
311 if (altitude)
312 av_strlcatf(buf, sizeof(buf), "%+f", altitude);
313 av_strlcatf(buf, sizeof(buf), "/%s", place);
314
315 if (*language && strcmp(language, "und")) {
316 char key2[16];
317 snprintf(key2, sizeof(key2), "%s-%s", key, language);
318 av_dict_set(&c->fc->metadata, key2, buf, 0);
319 }
320 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
321 return av_dict_set(&c->fc->metadata, key, buf, 0);
322 }
323
324 static int mov_metadata_hmmt(MOVContext *c, AVIOContext *pb, unsigned len)
325 {
326 int i, n_hmmt;
327
328 if (len < 2)
329 return 0;
330 if (c->ignore_chapters)
331 return 0;
332
333 n_hmmt = avio_rb32(pb);
334 if (n_hmmt > len / 4)
335 return AVERROR_INVALIDDATA;
336 for (i = 0; i < n_hmmt && !pb->eof_reached; i++) {
337 int moment_time = avio_rb32(pb);
338 avpriv_new_chapter(c->fc, i, av_make_q(1, 1000), moment_time, AV_NOPTS_VALUE, NULL);
339 }
340 if (avio_feof(pb))
341 return AVERROR_INVALIDDATA;
342 return 0;
343 }
344
345 480 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
346 {
347 480 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
348 480 char key2[32], language[4] = {0};
349 480 char *str = NULL;
350 480 const char *key = NULL;
351 480 uint16_t langcode = 0;
352 480 uint32_t data_type = 0, str_size_alloc;
353 uint64_t str_size;
354 480 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
355 480 int raw = 0;
356 480 int num = 0;
357 AVDictionary **metadata;
358
359
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 451 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
480 if (c->trak_index >= 0 && c->trak_index < c->fc->nb_streams)
360 29 metadata = &c->fc->streams[c->trak_index]->metadata;
361 else
362 451 metadata = &c->fc->metadata;
363
364
26/75
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 153 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 13 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 12 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 10 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 13 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 12 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 40 taken 17 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 16 times.
✓ Branch 43 taken 3 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 8 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 4 times.
✓ Branch 48 taken 16 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 3 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 42 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 52 times.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✓ Branch 73 taken 1 times.
✓ Branch 74 taken 5 times.
480 switch (atom.type) {
365 3 case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break;
366 3 case MKTAG( '@','P','R','Q'): key = "quicktime_version"; raw = 1; break;
367 2 case MKTAG( 'X','M','P','_'):
368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->export_xmp) { key = "xmp"; raw = 1; } break;
369 12 case MKTAG( 'a','A','R','T'): key = "album_artist"; break;
370 case MKTAG( 'a','k','I','D'): key = "account_type";
371 parse = mov_metadata_int8_no_padding; break;
372 case MKTAG( 'a','p','I','D'): key = "account_id"; break;
373 case MKTAG( 'c','a','t','g'): key = "category"; break;
374 13 case MKTAG( 'c','p','i','l'): key = "compilation";
375 13 parse = mov_metadata_int8_no_padding; break;
376 case MKTAG( 'c','p','r','t'): key = "copyright"; break;
377 case MKTAG( 'd','e','s','c'): key = "description"; break;
378 12 case MKTAG( 'd','i','s','k'): key = "disc";
379 12 parse = mov_metadata_track_or_disc_number; break;
380 case MKTAG( 'e','g','i','d'): key = "episode_uid";
381 parse = mov_metadata_int8_no_padding; break;
382 case MKTAG( 'F','I','R','M'): key = "firmware"; raw = 1; break;
383 10 case MKTAG( 'g','n','r','e'): key = "genre";
384 10 parse = mov_metadata_gnre; break;
385 case MKTAG( 'h','d','v','d'): key = "hd_video";
386 parse = mov_metadata_int8_no_padding; break;
387 case MKTAG( 'H','M','M','T'):
388 return mov_metadata_hmmt(c, pb, atom.size);
389 case MKTAG( 'k','e','y','w'): key = "keywords"; break;
390 case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
391 case MKTAG( 'l','o','c','i'):
392 return mov_metadata_loci(c, pb, atom.size);
393 case MKTAG( 'm','a','n','u'): key = "make"; break;
394 case MKTAG( 'm','o','d','l'): key = "model"; break;
395 5 case MKTAG( 'n','a','m','e'): key = "name"; break;
396 case MKTAG( 'p','c','s','t'): key = "podcast";
397 parse = mov_metadata_int8_no_padding; break;
398 13 case MKTAG( 'p','g','a','p'): key = "gapless_playback";
399 13 parse = mov_metadata_int8_no_padding; break;
400 case MKTAG( 'p','u','r','d'): key = "purchase_date"; break;
401 case MKTAG( 'r','t','n','g'): key = "rating";
402 parse = mov_metadata_int8_no_padding; break;
403 case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break;
404 case MKTAG( 's','o','a','l'): key = "sort_album"; break;
405 case MKTAG( 's','o','a','r'): key = "sort_artist"; break;
406 case MKTAG( 's','o','c','o'): key = "sort_composer"; break;
407 case MKTAG( 's','o','n','m'): key = "sort_name"; break;
408 case MKTAG( 's','o','s','n'): key = "sort_show"; break;
409 case MKTAG( 's','t','i','k'): key = "media_type";
410 parse = mov_metadata_int8_no_padding; break;
411 12 case MKTAG( 't','r','k','n'): key = "track";
412 12 parse = mov_metadata_track_or_disc_number; break;
413 case MKTAG( 't','v','e','n'): key = "episode_id"; break;
414 case MKTAG( 't','v','e','s'): key = "episode_sort";
415 parse = mov_metadata_int8_bypass_padding; break;
416 case MKTAG( 't','v','n','n'): key = "network"; break;
417 case MKTAG( 't','v','s','h'): key = "show"; break;
418 case MKTAG( 't','v','s','n'): key = "season_number";
419 parse = mov_metadata_int8_bypass_padding; break;
420 17 case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
421 case MKTAG(0xa9,'P','R','D'): key = "producer"; break;
422 16 case MKTAG(0xa9,'a','l','b'): key = "album"; break;
423 3 case MKTAG(0xa9,'a','u','t'): key = "artist"; break;
424 case MKTAG(0xa9,'c','h','p'): key = "chapter"; break;
425 8 case MKTAG(0xa9,'c','m','t'): key = "comment"; break;
426 case MKTAG(0xa9,'c','o','m'): key = "composer"; break;
427 4 case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
428 16 case MKTAG(0xa9,'d','a','y'): key = "date"; break;
429 case MKTAG(0xa9,'d','i','r'): key = "director"; break;
430 case MKTAG(0xa9,'d','i','s'): key = "disclaimer"; break;
431 case MKTAG(0xa9,'e','d','1'): key = "edit_date"; break;
432 2 case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
433 case MKTAG(0xa9,'f','m','t'): key = "original_format"; break;
434 3 case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
435 case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
436 case MKTAG(0xa9,'h','s','t'): key = "host_computer"; break;
437 case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
438 case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
439 5 case MKTAG(0xa9,'m','a','k'): key = "make"; break;
440 5 case MKTAG(0xa9,'m','o','d'): key = "model"; break;
441 42 case MKTAG(0xa9,'n','a','m'): key = "title"; break;
442 case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break;
443 case MKTAG(0xa9,'p','r','d'): key = "producer"; break;
444 case MKTAG(0xa9,'p','r','f'): key = "performers"; break;
445 case MKTAG(0xa9,'r','e','q'): key = "playback_requirements"; break;
446 case MKTAG(0xa9,'s','r','c'): key = "original_source"; break;
447 case MKTAG(0xa9,'s','t','3'): key = "subtitle"; break;
448 63 case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
449 52 case MKTAG(0xa9,'t','o','o'): key = "encoder"; break;
450 case MKTAG(0xa9,'t','r','k'): key = "track"; break;
451 case MKTAG(0xa9,'u','r','l'): key = "URL"; break;
452 case MKTAG(0xa9,'w','r','n'): key = "warning"; break;
453 1 case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
454 5 case MKTAG(0xa9,'x','y','z'): key = "location"; break;
455 }
456 7 retry:
457
3/4
✓ Branch 0 taken 303 times.
✓ Branch 1 taken 184 times.
✓ Branch 2 taken 303 times.
✗ Branch 3 not taken.
776 if (c->itunes_metadata && atom.size > 8) {
458 303 int data_size = avio_rb32(pb);
459 303 int tag = avio_rl32(pb);
460
3/6
✓ Branch 0 taken 303 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 303 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 303 times.
✗ Branch 5 not taken.
303 if (tag == MKTAG('d','a','t','a') && data_size <= atom.size && data_size >= 16) {
461 303 data_type = avio_rb32(pb); // type
462 303 avio_rb32(pb); // unknown
463 303 str_size = data_size - 16;
464 303 atom.size -= 16;
465
466
5/6
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 210 times.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 34 times.
✓ Branch 4 taken 59 times.
✗ Branch 5 not taken.
303 if (!key && c->found_hdlr_mdta && c->meta_keys) {
467 59 uint32_t index = av_bswap32(atom.type); // BE number has been read as LE
468
2/4
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
59 if (index < c->meta_keys_count && index > 0) {
469 59 key = c->meta_keys[index];
470 } else if (atom.type != MKTAG('c', 'o', 'v', 'r')) {
471 av_log(c->fc, AV_LOG_WARNING,
472 "The index of 'data' is out of range: %"PRId32" < 1 or >= %d.\n",
473 index, c->meta_keys_count);
474 }
475 }
476
4/4
✓ Branch 0 taken 289 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 269 times.
✓ Branch 3 taken 20 times.
303 if (atom.type == MKTAG('c', 'o', 'v', 'r') ||
477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 269 times.
269 (key && !strcmp(key, "com.apple.quicktime.artwork"))) {
478 14 int ret = mov_read_covr(c, pb, data_type, str_size);
479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0) {
480 av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
481 return ret;
482 }
483 14 atom.size -= str_size;
484
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (atom.size > 8)
485 2 goto retry;
486 12 return ret;
487 }
488 } else return 0;
489
8/10
✓ Branch 0 taken 166 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 120 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 46 times.
✓ Branch 6 taken 120 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 109 times.
✓ Branch 9 taken 11 times.
184 } else if (atom.size > 4 && (key || c->export_all) && !c->itunes_metadata && !raw) {
490 109 str_size = avio_rb16(pb); // string length
491
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 104 times.
109 if (str_size > atom.size) {
492 5 raw = 1;
493 5 avio_seek(pb, -2, SEEK_CUR);
494 5 av_log(c->fc, AV_LOG_WARNING, "UDTA parsing failed retrying raw\n");
495 5 goto retry;
496 }
497 104 langcode = avio_rb16(pb);
498 104 ff_mov_lang_to_iso639(langcode, language);
499 104 atom.size -= 4;
500 } else
501 75 str_size = atom.size;
502
503
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
468 if (c->export_all && !key) {
504 key = av_fourcc_make_string(tmp_key, atom.type);
505 }
506
507
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 384 times.
468 if (!key)
508 84 return 0;
509
2/4
✓ Branch 0 taken 384 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 384 times.
384 if (atom.size < 0 || str_size >= INT_MAX/2)
510 return AVERROR_INVALIDDATA;
511
512 // Allocates enough space if data_type is a int32 or float32 number, otherwise
513 // worst-case requirement for output string in case of utf8 coded input
514
3/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 343 times.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
384 num = (data_type >= 21 && data_type <= 23);
515
4/4
✓ Branch 0 taken 343 times.
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 332 times.
✓ Branch 3 taken 11 times.
384 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
516 384 str = av_mallocz(str_size_alloc);
517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 if (!str)
518 return AVERROR(ENOMEM);
519
520
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 324 times.
384 if (parse)
521 60 parse(c, pb, str_size, key);
522 else {
523
8/10
✓ Branch 0 taken 313 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 313 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 105 times.
✓ Branch 5 taken 208 times.
✓ Branch 6 taken 91 times.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 91 times.
324 if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
524 14 mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
525
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 308 times.
310 } else if (data_type == 21) { // BE signed integer, variable size
526 2 int val = 0;
527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (str_size == 1)
528 val = (int8_t)avio_r8(pb);
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 2)
530 val = (int16_t)avio_rb16(pb);
531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 3)
532 val = ((int32_t)(avio_rb24(pb)<<8))>>8;
533
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (str_size == 4)
534 2 val = (int32_t)avio_rb32(pb);
535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
536 av_log(c->fc, AV_LOG_ERROR,
537 "Failed to store the number (%d) in string.\n", val);
538 av_free(str);
539 return AVERROR_INVALIDDATA;
540 }
541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 308 times.
308 } else if (data_type == 22) { // BE unsigned integer, variable size
542 unsigned int val = 0;
543 if (str_size == 1)
544 val = avio_r8(pb);
545 else if (str_size == 2)
546 val = avio_rb16(pb);
547 else if (str_size == 3)
548 val = avio_rb24(pb);
549 else if (str_size == 4)
550 val = avio_rb32(pb);
551 if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
552 av_log(c->fc, AV_LOG_ERROR,
553 "Failed to store the number (%u) in string.\n", val);
554 av_free(str);
555 return AVERROR_INVALIDDATA;
556 }
557
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 295 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
321 } else if (data_type == 23 && str_size >= 4) { // BE float32
558 13 float val = av_int2float(avio_rb32(pb));
559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
560 av_log(c->fc, AV_LOG_ERROR,
561 "Failed to store the float32 number (%f) in string.\n", val);
562 av_free(str);
563 return AVERROR_INVALIDDATA;
564 }
565
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 295 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
295 } else if (data_type > 1 && data_type != 4) {
566 // data_type can be 0 if not set at all above. data_type 1 means
567 // UTF8 and 4 means "UTF8 sort". For any other type (UTF16 or e.g.
568 // a picture), don't return it blindly in a string that is supposed
569 // to be UTF8 text.
570 av_log(c->fc, AV_LOG_WARNING, "Skipping unhandled metadata %s of type %"PRIu32"\n", key, data_type);
571 av_free(str);
572 return 0;
573 } else {
574 295 int ret = ffio_read_size(pb, str, str_size);
575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 295 times.
295 if (ret < 0) {
576 av_free(str);
577 return ret;
578 }
579 295 str[str_size] = 0;
580 }
581 324 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
582 324 av_dict_set(metadata, key, str, 0);
583
4/4
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 220 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 67 times.
324 if (*language && strcmp(language, "und")) {
584 37 snprintf(key2, sizeof(key2), "%s-%s", key, language);
585 37 av_dict_set(metadata, key2, str, 0);
586 }
587
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 207 times.
324 if (!strcmp(key, "encoder")) {
588 int major, minor, micro;
589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117 times.
117 if (sscanf(str, "HandBrake %d.%d.%d", &major, &minor, &micro) == 3) {
590 c->handbrake_version = 1000000*major + 1000*minor + micro;
591 }
592 }
593 }
594
595 384 av_freep(&str);
596 384 return 0;
597 }
598
599 12 static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
600 {
601 int64_t start;
602 int i, nb_chapters, str_len, version;
603 char str[256+1];
604 int ret;
605
606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->ignore_chapters)
607 return 0;
608
609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if ((atom.size -= 5) < 0)
610 return 0;
611
612 12 version = avio_r8(pb);
613 12 avio_rb24(pb);
614
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (version)
615 12 avio_rb32(pb); // ???
616 12 nb_chapters = avio_r8(pb);
617
618
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
30 for (i = 0; i < nb_chapters; i++) {
619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size < 9)
620 return 0;
621
622 18 start = avio_rb64(pb);
623 18 str_len = avio_r8(pb);
624
625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if ((atom.size -= 9+str_len) < 0)
626 return 0;
627
628 18 ret = ffio_read_size(pb, str, str_len);
629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (ret < 0)
630 return ret;
631 18 str[str_len] = 0;
632 18 avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
633 }
634 12 return 0;
635 }
636
637 #define MIN_DATA_ENTRY_BOX_SIZE 12
638 627 static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
639 {
640 AVStream *st;
641 MOVStreamContext *sc;
642 int entries, i, j;
643
644
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->fc->nb_streams < 1)
645 return 0;
646 627 st = c->fc->streams[c->fc->nb_streams-1];
647 627 sc = st->priv_data;
648
649 627 avio_rb32(pb); // version + flags
650 627 entries = avio_rb32(pb);
651
1/2
✓ Branch 0 taken 627 times.
✗ Branch 1 not taken.
627 if (!entries ||
652
1/2
✓ Branch 0 taken 627 times.
✗ Branch 1 not taken.
627 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 entries >= UINT_MAX / sizeof(*sc->drefs))
654 return AVERROR_INVALIDDATA;
655
656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 for (i = 0; i < sc->drefs_count; i++) {
657 MOVDref *dref = &sc->drefs[i];
658 av_freep(&dref->path);
659 av_freep(&dref->dir);
660 }
661 627 av_free(sc->drefs);
662 627 sc->drefs_count = 0;
663 627 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (!sc->drefs)
665 return AVERROR(ENOMEM);
666 627 sc->drefs_count = entries;
667
668
2/2
✓ Branch 0 taken 627 times.
✓ Branch 1 taken 627 times.
1254 for (i = 0; i < entries; i++) {
669 627 MOVDref *dref = &sc->drefs[i];
670 627 uint32_t size = avio_rb32(pb);
671 627 int64_t next = avio_tell(pb);
672
673
3/6
✓ Branch 0 taken 627 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 627 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 627 times.
627 if (size < 12 || next < 0 || next > INT64_MAX - size)
674 return AVERROR_INVALIDDATA;
675
676 627 next += size - 4;
677
678 627 dref->type = avio_rl32(pb);
679 627 avio_rb32(pb); // version + flags
680
681
3/4
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 509 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 118 times.
627 if (dref->type == MKTAG('a','l','i','s') && size > 150) {
682 /* macintosh alias record */
683 uint16_t volume_len, len;
684 int16_t type;
685 int ret;
686
687 avio_skip(pb, 10);
688
689 volume_len = avio_r8(pb);
690 volume_len = FFMIN(volume_len, 27);
691 ret = ffio_read_size(pb, dref->volume, 27);
692 if (ret < 0)
693 return ret;
694 dref->volume[volume_len] = 0;
695 av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
696
697 avio_skip(pb, 12);
698
699 len = avio_r8(pb);
700 len = FFMIN(len, 63);
701 ret = ffio_read_size(pb, dref->filename, 63);
702 if (ret < 0)
703 return ret;
704 dref->filename[len] = 0;
705 av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
706
707 avio_skip(pb, 16);
708
709 /* read next level up_from_alias/down_to_target */
710 dref->nlvl_from = avio_rb16(pb);
711 dref->nlvl_to = avio_rb16(pb);
712 av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
713 dref->nlvl_from, dref->nlvl_to);
714
715 avio_skip(pb, 16);
716
717 for (type = 0; type != -1 && avio_tell(pb) < next; ) {
718 if (avio_feof(pb))
719 return AVERROR_EOF;
720 type = avio_rb16(pb);
721 len = avio_rb16(pb);
722 av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
723 if (len&1)
724 len += 1;
725 if (type == 2) { // absolute path
726 av_free(dref->path);
727 dref->path = av_mallocz(len+1);
728 if (!dref->path)
729 return AVERROR(ENOMEM);
730
731 ret = ffio_read_size(pb, dref->path, len);
732 if (ret < 0) {
733 av_freep(&dref->path);
734 return ret;
735 }
736 if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
737 len -= volume_len;
738 memmove(dref->path, dref->path+volume_len, len);
739 dref->path[len] = 0;
740 }
741 // trim string of any ending zeros
742 for (j = len - 1; j >= 0; j--) {
743 if (dref->path[j] == 0)
744 len--;
745 else
746 break;
747 }
748 for (j = 0; j < len; j++)
749 if (dref->path[j] == ':' || dref->path[j] == 0)
750 dref->path[j] = '/';
751 av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
752 } else if (type == 0) { // directory name
753 av_free(dref->dir);
754 dref->dir = av_malloc(len+1);
755 if (!dref->dir)
756 return AVERROR(ENOMEM);
757
758 ret = ffio_read_size(pb, dref->dir, len);
759 if (ret < 0) {
760 av_freep(&dref->dir);
761 return ret;
762 }
763 dref->dir[len] = 0;
764 for (j = 0; j < len; j++)
765 if (dref->dir[j] == ':')
766 dref->dir[j] = '/';
767 av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
768 } else
769 avio_skip(pb, len);
770 }
771 } else {
772 627 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
773 dref->type, size);
774 627 entries--;
775 627 i--;
776 }
777 627 avio_seek(pb, next, SEEK_SET);
778 }
779 627 return 0;
780 }
781
782 1149 static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
783 {
784 AVStream *st;
785 uint32_t type;
786 uint32_t ctype;
787 int64_t title_size;
788 char *title_str;
789 int ret;
790
791 1149 avio_r8(pb); /* version */
792 1149 avio_rb24(pb); /* flags */
793
794 /* component type */
795 1149 ctype = avio_rl32(pb);
796 1149 type = avio_rl32(pb); /* component subtype */
797
798 1149 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
799 1149 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
800
801
2/2
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 995 times.
1149 if (c->trak_index < 0) { // meta not inside a trak
802
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 143 times.
154 if (type == MKTAG('m','d','t','a')) {
803 11 c->found_hdlr_mdta = 1;
804 }
805 154 return 0;
806 }
807
808 995 st = c->fc->streams[c->fc->nb_streams-1];
809
810
2/2
✓ Branch 0 taken 325 times.
✓ Branch 1 taken 670 times.
995 if (type == MKTAG('v','i','d','e'))
811 325 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
812
2/2
✓ Branch 0 taken 247 times.
✓ Branch 1 taken 423 times.
670 else if (type == MKTAG('s','o','u','n'))
813 247 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 else if (type == MKTAG('m','1','a',' '))
815 st->codecpar->codec_id = AV_CODEC_ID_MP2;
816
2/4
✓ Branch 0 taken 423 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 423 times.
423 else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
817 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
818
819 995 avio_rb32(pb); /* component manufacture */
820 995 avio_rb32(pb); /* component flags */
821 995 avio_rb32(pb); /* component flags mask */
822
823 995 title_size = atom.size - 24;
824
2/2
✓ Branch 0 taken 992 times.
✓ Branch 1 taken 3 times.
995 if (title_size > 0) {
825
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 992 times.
992 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
826 return AVERROR_INVALIDDATA;
827 992 title_str = av_malloc(title_size + 1); /* Add null terminator */
828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 992 times.
992 if (!title_str)
829 return AVERROR(ENOMEM);
830
831 992 ret = ffio_read_size(pb, title_str, title_size);
832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 992 times.
992 if (ret < 0) {
833 av_freep(&title_str);
834 return ret;
835 }
836 992 title_str[title_size] = 0;
837
2/2
✓ Branch 0 taken 941 times.
✓ Branch 1 taken 51 times.
992 if (title_str[0]) {
838
4/4
✓ Branch 0 taken 712 times.
✓ Branch 1 taken 229 times.
✓ Branch 2 taken 710 times.
✓ Branch 3 taken 2 times.
941 int off = (!c->isom && title_str[0] == title_size - 1);
839 // flag added so as to not set stream handler name if already set from mdia->hdlr
840 941 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
841 }
842 992 av_freep(&title_str);
843 }
844
845 995 return 0;
846 }
847
848 160 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
849 {
850 160 return ff_mov_read_esds(c->fc, pb);
851 }
852
853 7 static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
854 {
855 AVStream *st;
856 AVPacketSideData *sd;
857 enum AVAudioServiceType *ast;
858 int ac3info, acmod, lfeon, bsmod;
859 uint64_t mask;
860
861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (c->fc->nb_streams < 1)
862 return 0;
863 7 st = c->fc->streams[c->fc->nb_streams-1];
864
865 7 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
866 7 &st->codecpar->nb_coded_side_data,
867 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
868 sizeof(*ast), 0);
869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sd)
870 return AVERROR(ENOMEM);
871
872 7 ast = (enum AVAudioServiceType*)sd->data;
873 7 ac3info = avio_rb24(pb);
874 7 bsmod = (ac3info >> 14) & 0x7;
875 7 acmod = (ac3info >> 11) & 0x7;
876 7 lfeon = (ac3info >> 10) & 0x1;
877
878 7 mask = ff_ac3_channel_layout_tab[acmod];
879
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (lfeon)
880 1 mask |= AV_CH_LOW_FREQUENCY;
881 7 av_channel_layout_uninit(&st->codecpar->ch_layout);
882 7 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
883
884 7 *ast = bsmod;
885
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
7 if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7)
886 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
887
888 7 return 0;
889 }
890
891 #if CONFIG_IAMFDEC
892 12 static int mov_read_iacb(MOVContext *c, AVIOContext *pb, MOVAtom atom)
893 {
894 AVStream *st;
895 MOVStreamContext *sc;
896 FFIOContext b;
897 AVIOContext *descriptor_pb;
898 AVDictionary *metadata;
899 IAMFContext *iamf;
900 int64_t start_time, duration;
901 unsigned descriptors_size;
902 int nb_frames, disposition;
903 int version, ret;
904
905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (atom.size < 5)
906 return AVERROR_INVALIDDATA;
907
908
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->fc->nb_streams < 1)
909 return 0;
910
911 12 version = avio_r8(pb);
912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (version != 1) {
913 av_log(c->fc, AV_LOG_ERROR, "%s configurationVersion %d",
914 version < 1 ? "invalid" : "unsupported", version);
915 return AVERROR_INVALIDDATA;
916 }
917
918 12 descriptors_size = ffio_read_leb(pb);
919
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)
920 return AVERROR_INVALIDDATA;
921
922 12 st = c->fc->streams[c->fc->nb_streams - 1];
923 12 sc = st->priv_data;
924
925
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->extradata) {
926 av_log(c->fc, AV_LOG_WARNING, "ignoring iacb\n");
927 return 0;
928 }
929
930 12 sc->iamf = av_mallocz(sizeof(*sc->iamf));
931
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!sc->iamf)
932 return AVERROR(ENOMEM);
933 12 iamf = &sc->iamf->iamf;
934
935 12 st->codecpar->extradata = av_malloc(descriptors_size);
936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!st->codecpar->extradata)
937 return AVERROR(ENOMEM);
938 12 st->codecpar->extradata_size = descriptors_size;
939
940 12 ret = avio_read(pb, st->codecpar->extradata, descriptors_size);
941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret != descriptors_size)
942 return ret < 0 ? ret : AVERROR_INVALIDDATA;
943
944 12 ffio_init_read_context(&b, st->codecpar->extradata, descriptors_size);
945 12 descriptor_pb = &b.pub;
946
947 12 ret = ff_iamfdec_read_descriptors(iamf, descriptor_pb, descriptors_size, c->fc);
948
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
949 return ret;
950
951 12 metadata = st->metadata;
952 12 st->metadata = NULL;
953 12 start_time = st->start_time;
954 12 nb_frames = st->nb_frames;
955 12 duration = st->duration;
956 12 disposition = st->disposition;
957
958
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_audio_elements; i++) {
959 12 IAMFAudioElement *audio_element = iamf->audio_elements[i];
960 const AVIAMFAudioElement *element;
961 AVStreamGroup *stg =
962 12 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, NULL);
963
964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!stg) {
965 ret = AVERROR(ENOMEM);
966 goto fail;
967 }
968
969 12 av_iamf_audio_element_free(&stg->params.iamf_audio_element);
970 12 stg->id = audio_element->audio_element_id;
971 /* Transfer ownership */
972 12 element = stg->params.iamf_audio_element = audio_element->element;
973 12 audio_element->element = NULL;
974
975
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < audio_element->nb_substreams; j++) {
976 64 IAMFSubStream *substream = &audio_element->substreams[j];
977 AVStream *stream;
978
979
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) {
980
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
12 if (audio_element->layers[0].substream_count != 1)
981 2 disposition &= ~AV_DISPOSITION_DEFAULT;
982 12 stream = st;
983 } else
984 52 stream = avformat_new_stream(c->fc, NULL);
985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (!stream) {
986 ret = AVERROR(ENOMEM);
987 goto fail;
988 }
989
990 64 stream->start_time = start_time;
991 64 stream->nb_frames = nb_frames;
992 64 stream->duration = duration;
993 64 stream->disposition = disposition;
994
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 12 times.
64 if (stream != st) {
995 52 stream->priv_data = sc;
996 52 sc->refcount++;
997 }
998
999
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 56 times.
64 if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
1000 8 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1001
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) {
1002 52 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1003
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 6 times.
52 if (audio_element->layers[0].substream_count == 1)
1004 46 stream->disposition &= ~AV_DISPOSITION_DEFAULT;
1005 }
1006
1007 64 ret = avcodec_parameters_copy(stream->codecpar, substream->codecpar);
1008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
1009 goto fail;
1010
1011 64 stream->id = substream->audio_substream_id;
1012
1013 64 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
1014
1015 64 ret = avformat_stream_group_add_stream(stg, stream);
1016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
1017 goto fail;
1018 }
1019
1020 12 ret = av_dict_copy(&stg->metadata, metadata, 0);
1021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1022 goto fail;
1023 }
1024
1025
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1026 12 IAMFMixPresentation *mix_presentation = iamf->mix_presentations[i];
1027 12 const AVIAMFMixPresentation *mix = mix_presentation->cmix;
1028 AVStreamGroup *stg =
1029 12 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, NULL);
1030
1031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!stg) {
1032 ret = AVERROR(ENOMEM);
1033 goto fail;
1034 }
1035
1036 12 av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
1037 12 stg->id = mix_presentation->mix_presentation_id;
1038 /* Transfer ownership */
1039 12 stg->params.iamf_mix_presentation = mix_presentation->mix;
1040 12 mix_presentation->mix = NULL;
1041
1042
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 12 times.
26 for (int j = 0; j < mix->nb_submixes; j++) {
1043 14 const AVIAMFSubmix *submix = mix->submixes[j];
1044
1045
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
28 for (int k = 0; k < submix->nb_elements; k++) {
1046 14 const AVIAMFSubmixElement *submix_element = submix->elements[k];
1047 14 const AVStreamGroup *audio_element = NULL;
1048
1049
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 for (int l = 0; l < c->fc->nb_stream_groups; l++)
1050
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 &&
1051
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 c->fc->stream_groups[l]->id == submix_element->audio_element_id) {
1052 14 audio_element = c->fc->stream_groups[l];
1053 14 break;
1054 }
1055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 av_assert0(audio_element);
1056
1057
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 14 times.
80 for (int l = 0; l < audio_element->nb_streams; l++) {
1058 66 ret = avformat_stream_group_add_stream(stg, audio_element->streams[l]);
1059
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))
1060 goto fail;
1061 }
1062 }
1063 }
1064
1065 12 ret = av_dict_copy(&stg->metadata, metadata, 0);
1066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1067 goto fail;
1068 }
1069
1070 12 ret = 0;
1071 12 fail:
1072 12 av_dict_free(&metadata);
1073
1074 12 return ret;
1075 }
1076 #endif
1077
1078 5 static int mov_read_srat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1079 {
1080 AVStream *st;
1081 int32_t sample_rate;
1082
1083
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)
1084 return 0;
1085
1086 5 st = c->fc->streams[c->fc->nb_streams-1];
1087
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
1088 av_log(c->fc, AV_LOG_WARNING, "'srat' within non-audio sample entry, skip\n");
1089 return 0;
1090 }
1091
1092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!c->isom) {
1093 av_log(c->fc, AV_LOG_WARNING, "'srat' within non-isom, skip\n");
1094 return 0;
1095 }
1096
1097 5 avio_skip(pb, 4); // version+flags
1098 5 sample_rate = avio_rb32(pb);
1099
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (sample_rate > 0) {
1100 5 av_log(c->fc, AV_LOG_DEBUG,
1101 "overwrite sample rate from %d to %d by 'srat'\n",
1102 5 st->codecpar->sample_rate, sample_rate);
1103 5 st->codecpar->sample_rate = sample_rate;
1104 } else {
1105 av_log(c->fc, AV_LOG_WARNING,
1106 "ignore invalid sample rate %d in 'srat'\n", sample_rate);
1107 }
1108
1109 5 return 0;
1110 }
1111
1112 1 static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1113 {
1114 AVStream *st;
1115 AVPacketSideData *sd;
1116 enum AVAudioServiceType *ast;
1117 int eac3info, acmod, lfeon, bsmod;
1118 uint64_t mask;
1119
1120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
1121 return 0;
1122 1 st = c->fc->streams[c->fc->nb_streams-1];
1123
1124 1 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1125 1 &st->codecpar->nb_coded_side_data,
1126 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
1127 sizeof(*ast), 0);
1128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sd)
1129 return AVERROR(ENOMEM);
1130
1131 1 ast = (enum AVAudioServiceType*)sd->data;
1132
1133 /* No need to parse fields for additional independent substreams and its
1134 * associated dependent substreams since libavcodec's E-AC-3 decoder
1135 * does not support them yet. */
1136 1 avio_rb16(pb); /* data_rate and num_ind_sub */
1137 1 eac3info = avio_rb24(pb);
1138 1 bsmod = (eac3info >> 12) & 0x1f;
1139 1 acmod = (eac3info >> 9) & 0x7;
1140 1 lfeon = (eac3info >> 8) & 0x1;
1141
1142 1 mask = ff_ac3_channel_layout_tab[acmod];
1143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (lfeon)
1144 mask |= AV_CH_LOW_FREQUENCY;
1145 1 av_channel_layout_uninit(&st->codecpar->ch_layout);
1146 1 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
1147
1148 1 *ast = bsmod;
1149
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7)
1150 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
1151
1152 1 return 0;
1153 }
1154
1155 static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1156 {
1157 #define DDTS_SIZE 20
1158 uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
1159 AVStream *st = NULL;
1160 uint32_t frame_duration_code = 0;
1161 uint32_t channel_layout_code = 0;
1162 GetBitContext gb;
1163 int ret;
1164
1165 if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
1166 return ret;
1167
1168 init_get_bits(&gb, buf, 8 * DDTS_SIZE);
1169
1170 if (c->fc->nb_streams < 1) {
1171 return 0;
1172 }
1173 st = c->fc->streams[c->fc->nb_streams-1];
1174
1175 st->codecpar->sample_rate = get_bits_long(&gb, 32);
1176 if (st->codecpar->sample_rate <= 0) {
1177 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
1178 return AVERROR_INVALIDDATA;
1179 }
1180 skip_bits_long(&gb, 32); /* max bitrate */
1181 st->codecpar->bit_rate = get_bits_long(&gb, 32);
1182 st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
1183 frame_duration_code = get_bits(&gb, 2);
1184 skip_bits(&gb, 30); /* various fields */
1185 channel_layout_code = get_bits(&gb, 16);
1186
1187 st->codecpar->frame_size =
1188 (frame_duration_code == 0) ? 512 :
1189 (frame_duration_code == 1) ? 1024 :
1190 (frame_duration_code == 2) ? 2048 :
1191 (frame_duration_code == 3) ? 4096 : 0;
1192
1193 if (channel_layout_code > 0xff) {
1194 av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout\n");
1195 }
1196 av_channel_layout_uninit(&st->codecpar->ch_layout);
1197 av_channel_layout_from_mask(&st->codecpar->ch_layout,
1198 ((channel_layout_code & 0x1) ? AV_CH_FRONT_CENTER : 0) |
1199 ((channel_layout_code & 0x2) ? AV_CH_FRONT_LEFT : 0) |
1200 ((channel_layout_code & 0x2) ? AV_CH_FRONT_RIGHT : 0) |
1201 ((channel_layout_code & 0x4) ? AV_CH_SIDE_LEFT : 0) |
1202 ((channel_layout_code & 0x4) ? AV_CH_SIDE_RIGHT : 0) |
1203 ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0));
1204
1205 return 0;
1206 }
1207
1208 52 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1209 {
1210 AVStream *st;
1211
1212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (c->fc->nb_streams < 1)
1213 return 0;
1214 52 st = c->fc->streams[c->fc->nb_streams-1];
1215
1216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (atom.size < 16)
1217 return 0;
1218
1219 /* skip version and flags */
1220 52 avio_skip(pb, 4);
1221
1222 52 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
1223
1224 52 return 0;
1225 }
1226
1227 5 static int mov_read_chnl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1228 {
1229 5 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
1230 int version, flags;
1231 int ret;
1232 AVStream *st;
1233
1234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
1235 return 0;
1236 5 st = c->fc->streams[c->fc->nb_streams-1];
1237
1238 5 version = avio_r8(pb);
1239 5 flags = avio_rb24(pb);
1240
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (version != 0 || flags != 0) {
1241 av_log(c->fc, AV_LOG_ERROR,
1242 "Unsupported 'chnl' box with version %d, flags: %#x",
1243 version, flags);
1244 return AVERROR_INVALIDDATA;
1245 }
1246
1247 5 ret = ff_mov_read_chnl(c->fc, pb, st);
1248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
1249 return ret;
1250
1251
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_tell(pb) != end) {
1252 av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data inside chnl\n",
1253 end - avio_tell(pb));
1254 avio_seek(pb, end, SEEK_SET);
1255 }
1256 5 return ret;
1257 }
1258
1259 2 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1260 {
1261 AVStream *st;
1262 int ret;
1263
1264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
1265 return 0;
1266 2 st = c->fc->streams[c->fc->nb_streams-1];
1267
1268
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)
1269 av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
1270
1271 2 return ret;
1272 }
1273
1274 18 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1275 {
1276 AVStream *st;
1277 HEIFItem *item;
1278 AVPacketSideData *sd;
1279 18 int width, height, err = 0;
1280 AVRational aperture_width, aperture_height, horiz_off, vert_off;
1281 AVRational pc_x, pc_y;
1282 uint64_t top, bottom, left, right;
1283
1284 18 item = get_heif_item(c, c->cur_item_id);
1285 18 st = get_curr_st(c);
1286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!st)
1287 return 0;
1288
1289 18 width = st->codecpar->width;
1290 18 height = st->codecpar->height;
1291
4/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
18 if ((!width || !height) && item) {
1292 6 width = item->width;
1293 6 height = item->height;
1294 }
1295
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (!width || !height) {
1296 err = AVERROR_INVALIDDATA;
1297 goto fail;
1298 }
1299
1300 18 aperture_width.num = avio_rb32(pb);
1301 18 aperture_width.den = avio_rb32(pb);
1302 18 aperture_height.num = avio_rb32(pb);
1303 18 aperture_height.den = avio_rb32(pb);
1304
1305 18 horiz_off.num = avio_rb32(pb);
1306 18 horiz_off.den = avio_rb32(pb);
1307 18 vert_off.num = avio_rb32(pb);
1308 18 vert_off.den = avio_rb32(pb);
1309
1310
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 if (aperture_width.num < 0 || aperture_width.den < 0 ||
1311
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 aperture_height.num < 0 || aperture_height.den < 0 ||
1312
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 horiz_off.den < 0 || vert_off.den < 0) {
1313 err = AVERROR_INVALIDDATA;
1314 goto fail;
1315 }
1316
3/4
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
33 if ((av_cmp_q((AVRational) { width, 1 }, aperture_width) < 0) ||
1317 15 (av_cmp_q((AVRational) { height, 1 }, aperture_height) < 0)) {
1318 3 err = AVERROR_INVALIDDATA;
1319 3 goto fail;
1320 }
1321 15 av_log(c->fc, AV_LOG_TRACE, "clap: apertureWidth %d/%d, apertureHeight %d/%d "
1322 "horizOff %d/%d vertOff %d/%d\n",
1323 aperture_width.num, aperture_width.den, aperture_height.num, aperture_height.den,
1324 horiz_off.num, horiz_off.den, vert_off.num, vert_off.den);
1325
1326 15 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1327 15 pc_x = av_add_q(pc_x, horiz_off);
1328 15 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1329 15 pc_y = av_add_q(pc_y, vert_off);
1330
1331 15 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1332 15 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1333 15 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1334 15 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1335
1336 15 left = av_q2d(av_sub_q(pc_x, aperture_width));
1337 15 right = av_q2d(av_add_q(pc_x, aperture_width));
1338 15 top = av_q2d(av_sub_q(pc_y, aperture_height));
1339 15 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1340
1341
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (bottom > (height - 1) ||
1342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 right > (width - 1)) {
1343 err = AVERROR_INVALIDDATA;
1344 goto fail;
1345 }
1346
1347 15 bottom = height - 1 - bottom;
1348 15 right = width - 1 - right;
1349
1350
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
15 if (!(left | right | top | bottom))
1351 6 return 0;
1352
1353
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if ((left + right) >= width ||
1354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 (top + bottom) >= height) {
1355 err = AVERROR_INVALIDDATA;
1356 goto fail;
1357 }
1358
1359 9 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1360 9 &st->codecpar->nb_coded_side_data,
1361 AV_PKT_DATA_FRAME_CROPPING,
1362 sizeof(uint32_t) * 4, 0);
1363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sd)
1364 return AVERROR(ENOMEM);
1365
1366 9 AV_WL32A(sd->data, top);
1367 9 AV_WL32A(sd->data + 4, bottom);
1368 9 AV_WL32A(sd->data + 8, left);
1369 9 AV_WL32A(sd->data + 12, right);
1370
1371 12 fail:
1372
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 if (err < 0) {
1373 3 int explode = !!(c->fc->error_recognition & AV_EF_EXPLODE);
1374
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");
1375
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!explode)
1376 3 err = 0;
1377 }
1378
1379 12 return err;
1380 }
1381
1382 /* This atom overrides any previously set aspect ratio */
1383 79 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1384 {
1385 79 const int num = avio_rb32(pb);
1386 79 const int den = avio_rb32(pb);
1387 AVStream *st;
1388 MOVStreamContext *sc;
1389
1390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (c->fc->nb_streams < 1)
1391 return 0;
1392 79 st = c->fc->streams[c->fc->nb_streams-1];
1393 79 sc = st->priv_data;
1394
1395 79 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1396
1397
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 2 times.
79 if (den != 0) {
1398 77 sc->h_spacing = num;
1399 77 sc->v_spacing = den;
1400 }
1401 79 return 0;
1402 }
1403
1404 /* this atom contains actual media data */
1405 980 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1406 {
1407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 980 times.
980 if (atom.size == 0) /* wrong one (MP4) */
1408 return 0;
1409 980 c->found_mdat=1;
1410 980 return 0; /* now go for moov */
1411 }
1412
1413 #define DRM_BLOB_SIZE 56
1414
1415 static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1416 {
1417 uint8_t intermediate_key[20];
1418 uint8_t intermediate_iv[20];
1419 uint8_t input[64];
1420 uint8_t output[64];
1421 uint8_t file_checksum[20];
1422 uint8_t calculated_checksum[20];
1423 char checksum_string[2 * sizeof(file_checksum) + 1];
1424 struct AVSHA *sha;
1425 int i;
1426 int ret = 0;
1427 uint8_t *activation_bytes = c->activation_bytes;
1428 uint8_t *fixed_key = c->audible_fixed_key;
1429
1430 c->aax_mode = 1;
1431
1432 sha = av_sha_alloc();
1433 if (!sha)
1434 return AVERROR(ENOMEM);
1435 av_free(c->aes_decrypt);
1436 c->aes_decrypt = av_aes_alloc();
1437 if (!c->aes_decrypt) {
1438 ret = AVERROR(ENOMEM);
1439 goto fail;
1440 }
1441
1442 /* drm blob processing */
1443 avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1444 avio_read(pb, input, DRM_BLOB_SIZE);
1445 avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1446 ret = ffio_read_size(pb, file_checksum, 20);
1447 if (ret < 0)
1448 goto fail;
1449
1450 // required by external tools
1451 ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1);
1452 av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string);
1453
1454 /* verify activation data */
1455 if (!activation_bytes) {
1456 av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1457 ret = 0; /* allow ffprobe to continue working on .aax files */
1458 goto fail;
1459 }
1460 if (c->activation_bytes_size != 4) {
1461 av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1462 ret = AVERROR(EINVAL);
1463 goto fail;
1464 }
1465
1466 /* verify fixed key */
1467 if (c->audible_fixed_key_size != 16) {
1468 av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1469 ret = AVERROR(EINVAL);
1470 goto fail;
1471 }
1472
1473 /* AAX (and AAX+) key derivation */
1474 av_sha_init(sha, 160);
1475 av_sha_update(sha, fixed_key, 16);
1476 av_sha_update(sha, activation_bytes, 4);
1477 av_sha_final(sha, intermediate_key);
1478 av_sha_init(sha, 160);
1479 av_sha_update(sha, fixed_key, 16);
1480 av_sha_update(sha, intermediate_key, 20);
1481 av_sha_update(sha, activation_bytes, 4);
1482 av_sha_final(sha, intermediate_iv);
1483 av_sha_init(sha, 160);
1484 av_sha_update(sha, intermediate_key, 16);
1485 av_sha_update(sha, intermediate_iv, 16);
1486 av_sha_final(sha, calculated_checksum);
1487 if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1488 av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1489 ret = AVERROR_INVALIDDATA;
1490 goto fail;
1491 }
1492 av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1493 av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1494 for (i = 0; i < 4; i++) {
1495 // file data (in output) is stored in big-endian mode
1496 if (activation_bytes[i] != output[3 - i]) { // critical error
1497 av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1498 ret = AVERROR_INVALIDDATA;
1499 goto fail;
1500 }
1501 }
1502 memcpy(c->file_key, output + 8, 16);
1503 memcpy(input, output + 26, 16);
1504 av_sha_init(sha, 160);
1505 av_sha_update(sha, input, 16);
1506 av_sha_update(sha, c->file_key, 16);
1507 av_sha_update(sha, fixed_key, 16);
1508 av_sha_final(sha, c->file_iv);
1509
1510 fail:
1511 av_free(sha);
1512
1513 return ret;
1514 }
1515
1516 static int mov_aaxc_crypto(MOVContext *c)
1517 {
1518 if (c->audible_key_size != 16) {
1519 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n");
1520 return AVERROR(EINVAL);
1521 }
1522
1523 if (c->audible_iv_size != 16) {
1524 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n");
1525 return AVERROR(EINVAL);
1526 }
1527
1528 c->aes_decrypt = av_aes_alloc();
1529 if (!c->aes_decrypt) {
1530 return AVERROR(ENOMEM);
1531 }
1532
1533 memcpy(c->file_key, c->audible_key, 16);
1534 memcpy(c->file_iv, c->audible_iv, 16);
1535 c->aax_mode = 1;
1536
1537 return 0;
1538 }
1539
1540 // Audible AAX (and AAX+) bytestream decryption
1541 static int aax_filter(uint8_t *input, int size, MOVContext *c)
1542 {
1543 int blocks = 0;
1544 unsigned char iv[16];
1545
1546 memcpy(iv, c->file_iv, 16); // iv is overwritten
1547 blocks = size >> 4; // trailing bytes are not encrypted!
1548 av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1549 av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1550
1551 return 0;
1552 }
1553
1554 /* read major brand, minor version and compatible brands and store them as metadata */
1555 482 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1556 {
1557 uint32_t minor_ver;
1558 int comp_brand_size;
1559 char* comp_brands_str;
1560 482 uint8_t type[5] = {0};
1561 482 int ret = ffio_read_size(pb, type, 4);
1562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 482 times.
482 if (ret < 0)
1563 return ret;
1564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 482 times.
482 if (c->fc->nb_streams) {
1565 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1566 return AVERROR_INVALIDDATA;
1567 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate FTYP\n");
1568 return 0;
1569 }
1570
1571
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 241 times.
482 if (strcmp(type, "qt "))
1572 241 c->isom = 1;
1573 482 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1574 482 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1575 482 minor_ver = avio_rb32(pb); /* minor version */
1576 482 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1577
1578 482 comp_brand_size = atom.size - 8;
1579
2/4
✓ Branch 0 taken 482 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 482 times.
482 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1580 return AVERROR_INVALIDDATA;
1581 482 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 482 times.
482 if (!comp_brands_str)
1583 return AVERROR(ENOMEM);
1584
1585 482 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 482 times.
482 if (ret < 0) {
1587 av_freep(&comp_brands_str);
1588 return ret;
1589 }
1590 482 comp_brands_str[comp_brand_size] = 0;
1591 482 av_dict_set(&c->fc->metadata, "compatible_brands",
1592 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1593
1594 // Logic for handling Audible's .aaxc files
1595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 482 times.
482 if (!strcmp(type, "aaxc")) {
1596 mov_aaxc_crypto(c);
1597 }
1598
1599 482 return 0;
1600 }
1601
1602 /* this atom should contain all header atoms */
1603 508 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1604 {
1605 int ret;
1606
1607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 508 times.
508 if (c->found_moov) {
1608 av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1609 avio_skip(pb, atom.size);
1610 return 0;
1611 }
1612
1613
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 508 times.
508 if ((ret = mov_read_default(c, pb, atom)) < 0)
1614 return ret;
1615 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1616 /* so we don't parse the whole file if over a network */
1617 508 c->found_moov=1;
1618 508 return 0; /* now go for mdat */
1619 }
1620
1621 3208 static MOVFragmentStreamInfo * get_frag_stream_info(
1622 MOVFragmentIndex *frag_index,
1623 int index,
1624 int id)
1625 {
1626 int i;
1627 MOVFragmentIndexItem * item;
1628
1629
2/4
✓ Branch 0 taken 3208 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3208 times.
3208 if (index < 0 || index >= frag_index->nb_items)
1630 return NULL;
1631 3208 item = &frag_index->item[index];
1632
1/2
✓ Branch 0 taken 3392 times.
✗ Branch 1 not taken.
3392 for (i = 0; i < item->nb_stream_info; i++)
1633
2/2
✓ Branch 0 taken 3208 times.
✓ Branch 1 taken 184 times.
3392 if (item->stream_info[i].id == id)
1634 3208 return &item->stream_info[i];
1635
1636 // This shouldn't happen
1637 return NULL;
1638 }
1639
1640 499 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1641 {
1642 int i;
1643 MOVFragmentIndexItem * item;
1644
1645
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_index->current < 0 ||
1646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 frag_index->current >= frag_index->nb_items)
1647 return;
1648
1649 499 item = &frag_index->item[frag_index->current];
1650
1/2
✓ Branch 0 taken 558 times.
✗ Branch 1 not taken.
558 for (i = 0; i < item->nb_stream_info; i++)
1651
2/2
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 59 times.
558 if (item->stream_info[i].id == id) {
1652 499 item->current = i;
1653 499 return;
1654 }
1655
1656 // id not found. This shouldn't happen.
1657 item->current = -1;
1658 }
1659
1660 1436 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1661 MOVFragmentIndex *frag_index)
1662 {
1663 MOVFragmentIndexItem *item;
1664
1/2
✓ Branch 0 taken 1436 times.
✗ Branch 1 not taken.
1436 if (frag_index->current < 0 ||
1665
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1430 times.
1436 frag_index->current >= frag_index->nb_items)
1666 6 return NULL;
1667
1668 1430 item = &frag_index->item[frag_index->current];
1669
2/4
✓ Branch 0 taken 1430 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1430 times.
✗ Branch 3 not taken.
1430 if (item->current >= 0 && item->current < item->nb_stream_info)
1670 1430 return &item->stream_info[item->current];
1671
1672 // This shouldn't happen
1673 return NULL;
1674 }
1675
1676 899 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1677 {
1678 int a, b, m;
1679 int64_t moof_offset;
1680
1681 // Optimize for appending new entries
1682
2/2
✓ Branch 0 taken 881 times.
✓ Branch 1 taken 18 times.
899 if (!frag_index->nb_items ||
1683
2/2
✓ Branch 0 taken 464 times.
✓ Branch 1 taken 417 times.
881 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1684 482 return frag_index->nb_items;
1685
1686 417 a = -1;
1687 417 b = frag_index->nb_items;
1688
1689
2/2
✓ Branch 0 taken 2677 times.
✓ Branch 1 taken 417 times.
3094 while (b - a > 1) {
1690 2677 m = (a + b) >> 1;
1691 2677 moof_offset = frag_index->item[m].moof_offset;
1692
2/2
✓ Branch 0 taken 747 times.
✓ Branch 1 taken 1930 times.
2677 if (moof_offset >= offset)
1693 747 b = m;
1694
2/2
✓ Branch 0 taken 2345 times.
✓ Branch 1 taken 332 times.
2677 if (moof_offset <= offset)
1695 2345 a = m;
1696 }
1697 417 return b;
1698 }
1699
1700 7 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1701 {
1702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 av_assert0(frag_stream_info);
1703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1704 return frag_stream_info->sidx_pts;
1705
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1706 4 return frag_stream_info->first_tfra_pts;
1707 3 return frag_stream_info->tfdt_dts;
1708 }
1709
1710 226 static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1711 MOVFragmentIndex *frag_index, int index)
1712 {
1713 MOVFragmentStreamInfo * frag_stream_info;
1714 226 MOVStreamContext *sc = dst_st->priv_data;
1715 int64_t timestamp;
1716 int i, j;
1717
1718 // If the stream is referenced by any sidx, limit the search
1719 // to fragments that referenced this stream in the sidx
1720
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 7 times.
226 if (sc->has_sidx) {
1721 219 frag_stream_info = get_frag_stream_info(frag_index, index, sc->id);
1722
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!frag_stream_info)
1723 return AV_NOPTS_VALUE;
1724
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1725 219 return frag_stream_info->sidx_pts;
1726 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1727 return frag_stream_info->first_tfra_pts;
1728 return frag_stream_info->sidx_pts;
1729 }
1730
1731
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++) {
1732
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)
1733 5 continue;
1734 7 AVStream *frag_stream = NULL;
1735 7 frag_stream_info = &frag_index->item[index].stream_info[i];
1736
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
21 for (j = 0; j < s->nb_streams; j++) {
1737 14 MOVStreamContext *sc2 = s->streams[j]->priv_data;
1738
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (sc2->id == frag_stream_info->id)
1739 7 frag_stream = s->streams[j];
1740 }
1741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!frag_stream) {
1742 av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1743 continue;
1744 }
1745 7 timestamp = get_stream_info_time(frag_stream_info);
1746
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (timestamp != AV_NOPTS_VALUE)
1747 4 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1748 }
1749 3 return AV_NOPTS_VALUE;
1750 }
1751
1752 28 static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1753 AVStream *st, int64_t timestamp)
1754 {
1755 int a, b, m, m0;
1756 int64_t frag_time;
1757
1758 28 a = -1;
1759 28 b = frag_index->nb_items;
1760
1761
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 28 times.
252 while (b - a > 1) {
1762 224 m0 = m = (a + b) >> 1;
1763
1764
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 &&
1765 226 (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
1766 3 m++;
1767
1768
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)
1769 95 a = m;
1770 else
1771 129 b = m0;
1772 }
1773
1774 28 return a;
1775 }
1776
1777 851 static int update_frag_index(MOVContext *c, int64_t offset)
1778 {
1779 int index, i;
1780 MOVFragmentIndexItem * item;
1781 MOVFragmentStreamInfo * frag_stream_info;
1782
1783 // If moof_offset already exists in frag_index, return index to it
1784 851 index = search_frag_moof_offset(&c->frag_index, offset);
1785
2/2
✓ Branch 0 taken 376 times.
✓ Branch 1 taken 475 times.
851 if (index < c->frag_index.nb_items &&
1786
2/2
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 2 times.
376 c->frag_index.item[index].moof_offset == offset)
1787 374 return index;
1788
1789 // offset is not yet in frag index.
1790 // Insert new item at index (sorted by moof offset)
1791 477 item = av_fast_realloc(c->frag_index.item,
1792 477 &c->frag_index.allocated_size,
1793 477 (c->frag_index.nb_items + 1) *
1794 sizeof(*c->frag_index.item));
1795
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 477 times.
477 if (!item)
1796 return -1;
1797 477 c->frag_index.item = item;
1798
1799 477 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1800 sizeof(*item->stream_info));
1801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 477 times.
477 if (!frag_stream_info)
1802 return -1;
1803
1804
2/2
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 477 times.
1056 for (i = 0; i < c->fc->nb_streams; i++) {
1805 // Avoid building frag index if streams lack track id.
1806 579 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 579 times.
579 if (sc->id < 0) {
1808 av_free(frag_stream_info);
1809 return AVERROR_INVALIDDATA;
1810 }
1811
1812 579 frag_stream_info[i].id = sc->id;
1813 579 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1814 579 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1815 579 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1816 579 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1817 579 frag_stream_info[i].index_base = -1;
1818 579 frag_stream_info[i].index_entry = -1;
1819 579 frag_stream_info[i].encryption_index = NULL;
1820 579 frag_stream_info[i].stsd_id = -1;
1821 }
1822
1823
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 475 times.
477 if (index < c->frag_index.nb_items)
1824 2 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1825 2 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1826
1827 477 item = &c->frag_index.item[index];
1828 477 item->headers_read = 0;
1829 477 item->current = 0;
1830 477 item->nb_stream_info = c->fc->nb_streams;
1831 477 item->moof_offset = offset;
1832 477 item->stream_info = frag_stream_info;
1833 477 c->frag_index.nb_items++;
1834
1835 477 return index;
1836 }
1837
1838 499 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1839 int id, int entries)
1840 {
1841 int i;
1842 MOVFragmentStreamInfo * frag_stream_info;
1843
1844
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (index < 0)
1845 499 return;
1846 for (i = index; i < frag_index->nb_items; i++) {
1847 frag_stream_info = get_frag_stream_info(frag_index, i, id);
1848 if (frag_stream_info && frag_stream_info->index_entry >= 0)
1849 frag_stream_info->index_entry += entries;
1850 }
1851 }
1852
1853 473 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1854 {
1855 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1856 473 c->fragment.found_tfhd = 0;
1857
1858
4/4
✓ Branch 0 taken 471 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 470 times.
473 if (!c->has_looked_for_mfra && c->use_mfra_for > 0) {
1859 1 c->has_looked_for_mfra = 1;
1860
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1861 int ret;
1862 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1863 "for a mfra\n");
1864
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((ret = mov_read_mfra(c, pb)) < 0) {
1865 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1866 "read the mfra (may be a live ismv)\n");
1867 }
1868 } else {
1869 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1870 "seekable, can not look for mfra\n");
1871 }
1872 }
1873 473 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1874 473 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1875 473 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1876 473 return mov_read_default(c, pb, atom);
1877 }
1878
1879 1132 static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version)
1880 {
1881 int64_t time;
1882
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1117 times.
1132 if (version == 1) {
1883 15 time = avio_rb64(pb);
1884 15 avio_rb64(pb);
1885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (time < 0) {
1886 av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n");
1887 return;
1888 }
1889 } else {
1890 1117 time = avio_rb32(pb);
1891 1117 avio_rb32(pb); /* modification time */
1892
4/4
✓ Branch 0 taken 532 times.
✓ Branch 1 taken 585 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 484 times.
1117 if (time > 0 && time < 2082844800) {
1893 48 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1894 48 time += 2082844800;
1895 }
1896 }
1897
2/2
✓ Branch 0 taken 538 times.
✓ Branch 1 taken 594 times.
1132 if (time) {
1898 538 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1899
1900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 538 times.
538 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1901 av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n");
1902 return;
1903 }
1904
1905 538 ff_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1906 }
1907 }
1908
1909 627 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1910 {
1911 AVStream *st;
1912 MOVStreamContext *sc;
1913 int version;
1914 627 char language[4] = {0};
1915 unsigned lang;
1916
1917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->fc->nb_streams < 1)
1918 return 0;
1919 627 st = c->fc->streams[c->fc->nb_streams-1];
1920 627 sc = st->priv_data;
1921
1922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (sc->time_scale) {
1923 av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
1924 return AVERROR_INVALIDDATA;
1925 }
1926
1927 627 version = avio_r8(pb);
1928
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (version > 1) {
1929 avpriv_request_sample(c->fc, "Version %d", version);
1930 return AVERROR_PATCHWELCOME;
1931 }
1932 627 avio_rb24(pb); /* flags */
1933 627 mov_metadata_creation_time(c, pb, &st->metadata, version);
1934
1935 627 sc->time_scale = avio_rb32(pb);
1936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (sc->time_scale <= 0) {
1937 av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
1938 sc->time_scale = 1;
1939 }
1940
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 614 times.
627 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1941
1942
6/6
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 614 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 614 times.
✓ Branch 5 taken 4 times.
627 if ((version == 1 && st->duration == UINT64_MAX) ||
1943
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 614 times.
614 (version != 1 && st->duration == UINT32_MAX)) {
1944 9 st->duration = 0;
1945 }
1946
1947 627 lang = avio_rb16(pb); /* language */
1948
2/2
✓ Branch 1 taken 452 times.
✓ Branch 2 taken 175 times.
627 if (ff_mov_lang_to_iso639(lang, language))
1949 452 av_dict_set(&st->metadata, "language", language, 0);
1950 627 avio_rb16(pb); /* quality */
1951
1952 627 return 0;
1953 }
1954
1955 505 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1956 {
1957 int i;
1958 505 int version = avio_r8(pb); /* version */
1959 505 avio_rb24(pb); /* flags */
1960
1961 505 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
1962 505 c->time_scale = avio_rb32(pb); /* time scale */
1963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 505 times.
505 if (c->time_scale <= 0) {
1964 av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
1965 c->time_scale = 1;
1966 }
1967 505 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
1968
1969
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 503 times.
505 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1970 505 avio_rb32(pb); /* preferred scale */
1971
1972 505 avio_rb16(pb); /* preferred volume */
1973
1974 505 avio_skip(pb, 10); /* reserved */
1975
1976 /* movie display matrix, store it in main context and use it later on */
1977
2/2
✓ Branch 0 taken 1515 times.
✓ Branch 1 taken 505 times.
2020 for (i = 0; i < 3; i++) {
1978 1515 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
1979 1515 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
1980 1515 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
1981 }
1982
1983 505 avio_rb32(pb); /* preview time */
1984 505 avio_rb32(pb); /* preview duration */
1985 505 avio_rb32(pb); /* poster time */
1986 505 avio_rb32(pb); /* selection time */
1987 505 avio_rb32(pb); /* selection duration */
1988 505 avio_rb32(pb); /* current time */
1989 505 avio_rb32(pb); /* next track ID */
1990
1991 505 return 0;
1992 }
1993
1994 7 static void set_last_stream_little_endian(AVFormatContext *fc)
1995 {
1996 AVStream *st;
1997
1998
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (fc->nb_streams < 1)
1999 return;
2000 7 st = fc->streams[fc->nb_streams-1];
2001
2002
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) {
2003 5 case AV_CODEC_ID_PCM_S16BE:
2004 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2005 5 break;
2006 1 case AV_CODEC_ID_PCM_S24BE:
2007 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
2008 1 break;
2009 case AV_CODEC_ID_PCM_S32BE:
2010 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
2011 break;
2012 1 case AV_CODEC_ID_PCM_F32BE:
2013 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
2014 1 break;
2015 case AV_CODEC_ID_PCM_F64BE:
2016 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
2017 break;
2018 default:
2019 break;
2020 }
2021 }
2022
2023 5 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2024 {
2025 5 int little_endian = avio_rb16(pb) & 0xFF;
2026 5 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
2027
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (little_endian == 1)
2028 1 set_last_stream_little_endian(c->fc);
2029 5 return 0;
2030 }
2031
2032 6 static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2033 {
2034 int format_flags;
2035 int version, flags;
2036 int pcm_sample_size;
2037 6 AVFormatContext *fc = c->fc;
2038 AVStream *st;
2039 MOVStreamContext *sc;
2040
2041
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 6) {
2042 av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n");
2043 return AVERROR_INVALIDDATA;
2044 }
2045
2046 6 version = avio_r8(pb);
2047 6 flags = avio_rb24(pb);
2048
2049
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) {
2050 av_log(c->fc, AV_LOG_ERROR,
2051 "Unsupported 'pcmC' box with version %d, flags: %x",
2052 version, flags);
2053 return AVERROR_INVALIDDATA;
2054 }
2055
2056 6 format_flags = avio_r8(pb);
2057 6 pcm_sample_size = avio_r8(pb);
2058
2059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fc->nb_streams < 1)
2060 return AVERROR_INVALIDDATA;
2061
2062 6 st = fc->streams[fc->nb_streams - 1];
2063 6 sc = st->priv_data;
2064
2065
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (sc->format == MOV_MP4_FPCM_TAG) {
2066
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (pcm_sample_size) {
2067 1 case 32:
2068 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE;
2069 1 break;
2070 case 64:
2071 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE;
2072 break;
2073 default:
2074 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2075 pcm_sample_size,
2076 av_fourcc2str(sc->format));
2077 return AVERROR_INVALIDDATA;
2078 }
2079
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (sc->format == MOV_MP4_IPCM_TAG) {
2080
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 switch (pcm_sample_size) {
2081 5 case 16:
2082 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2083 5 break;
2084 case 24:
2085 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
2086 break;
2087 case 32:
2088 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
2089 break;
2090 default:
2091 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2092 pcm_sample_size,
2093 av_fourcc2str(sc->format));
2094 return AVERROR_INVALIDDATA;
2095 }
2096 } else {
2097 av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n",
2098 av_fourcc2str(sc->format));
2099 return AVERROR_INVALIDDATA;
2100 }
2101
2102
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
2103 6 set_last_stream_little_endian(c->fc);
2104 6 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2105
2106 6 return 0;
2107 }
2108
2109 47 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2110 {
2111 AVStream *st;
2112 47 HEIFItem *item = NULL;
2113 47 char color_parameter_type[5] = { 0 };
2114 uint16_t color_primaries, color_trc, color_matrix;
2115 int ret;
2116
2117 47 st = get_curr_st(c);
2118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 if (!st) {
2119 item = get_heif_item(c, c->cur_item_id);
2120 if (!item)
2121 return 0;
2122 }
2123
2124 47 ret = ffio_read_size(pb, color_parameter_type, 4);
2125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 if (ret < 0)
2126 return ret;
2127
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 14 times.
47 if (strncmp(color_parameter_type, "nclx", 4) &&
2128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 strncmp(color_parameter_type, "nclc", 4) &&
2129 strncmp(color_parameter_type, "prof", 4)) {
2130 av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
2131 color_parameter_type);
2132 return 0;
2133 }
2134
2135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 if (!strncmp(color_parameter_type, "prof", 4)) {
2136 AVPacketSideData *sd;
2137 uint8_t *icc_profile;
2138 if (st) {
2139 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
2140 &st->codecpar->nb_coded_side_data,
2141 AV_PKT_DATA_ICC_PROFILE,
2142 atom.size - 4, 0);
2143 if (!sd)
2144 return AVERROR(ENOMEM);
2145 icc_profile = sd->data;
2146 } else {
2147 av_freep(&item->icc_profile);
2148 icc_profile = item->icc_profile = av_malloc(atom.size - 4);
2149 if (!icc_profile) {
2150 item->icc_profile_size = 0;
2151 return AVERROR(ENOMEM);
2152 }
2153 item->icc_profile_size = atom.size - 4;
2154 }
2155 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
2156 if (ret < 0)
2157 return ret;
2158
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 } else if (st) {
2159 47 color_primaries = avio_rb16(pb);
2160 47 color_trc = avio_rb16(pb);
2161 47 color_matrix = avio_rb16(pb);
2162
2163 47 av_log(c->fc, AV_LOG_TRACE,
2164 "%s: pri %d trc %d matrix %d",
2165 color_parameter_type, color_primaries, color_trc, color_matrix);
2166
2167
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 33 times.
47 if (!strncmp(color_parameter_type, "nclx", 4)) {
2168 14 uint8_t color_range = avio_r8(pb) >> 7;
2169 14 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2170
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (color_range)
2171 2 st->codecpar->color_range = AVCOL_RANGE_JPEG;
2172 else
2173 12 st->codecpar->color_range = AVCOL_RANGE_MPEG;
2174 }
2175
2176
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
47 if (!av_color_primaries_name(color_primaries))
2177 color_primaries = AVCOL_PRI_UNSPECIFIED;
2178
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
47 if (!av_color_transfer_name(color_trc))
2179 color_trc = AVCOL_TRC_UNSPECIFIED;
2180
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
47 if (!av_color_space_name(color_matrix))
2181 color_matrix = AVCOL_SPC_UNSPECIFIED;
2182
2183 47 st->codecpar->color_primaries = color_primaries;
2184 47 st->codecpar->color_trc = color_trc;
2185 47 st->codecpar->color_space = color_matrix;
2186 47 av_log(c->fc, AV_LOG_TRACE, "\n");
2187 }
2188 47 return 0;
2189 }
2190
2191 118 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2192 {
2193 AVStream *st;
2194 unsigned mov_field_order;
2195 118 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2196
2197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (c->fc->nb_streams < 1) // will happen with jp2 files
2198 return 0;
2199 118 st = c->fc->streams[c->fc->nb_streams-1];
2200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (atom.size < 2)
2201 return AVERROR_INVALIDDATA;
2202 118 mov_field_order = avio_rb16(pb);
2203
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 22 times.
118 if ((mov_field_order & 0xFF00) == 0x0100)
2204 96 decoded_field_order = AV_FIELD_PROGRESSIVE;
2205
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 else if ((mov_field_order & 0xFF00) == 0x0200) {
2206
3/5
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
22 switch (mov_field_order & 0xFF) {
2207 1 case 0x01: decoded_field_order = AV_FIELD_TT;
2208 1 break;
2209 case 0x06: decoded_field_order = AV_FIELD_BB;
2210 break;
2211 1 case 0x09: decoded_field_order = AV_FIELD_TB;
2212 1 break;
2213 20 case 0x0E: decoded_field_order = AV_FIELD_BT;
2214 20 break;
2215 }
2216 }
2217
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
118 if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) {
2218 av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
2219 }
2220 118 st->codecpar->field_order = decoded_field_order;
2221
2222 118 return 0;
2223 }
2224
2225 69 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
2226 {
2227 69 int err = 0;
2228 69 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
2229
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)
2230 return AVERROR_INVALIDDATA;
2231
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
69 if ((err = av_reallocp(&par->extradata, size)) < 0) {
2232 par->extradata_size = 0;
2233 return err;
2234 }
2235 69 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
2236 69 return 0;
2237 }
2238
2239 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
2240 65 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2241 AVCodecParameters *par, uint8_t *buf)
2242 {
2243 65 int64_t result = atom.size;
2244 int err;
2245
2246 65 AV_WB32(buf , atom.size + 8);
2247 65 AV_WL32(buf + 4, atom.type);
2248 65 err = ffio_read_size(pb, buf + 8, atom.size);
2249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (err < 0) {
2250 par->extradata_size -= atom.size;
2251 return err;
2252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 } else if (err < atom.size) {
2253 av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
2254 par->extradata_size -= atom.size - err;
2255 result = err;
2256 }
2257 65 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2258 65 return result;
2259 }
2260
2261 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
2262 58 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2263 enum AVCodecID codec_id)
2264 {
2265 AVStream *st;
2266 uint64_t original_size;
2267 int err;
2268
2269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (c->fc->nb_streams < 1) // will happen with jp2 files
2270 return 0;
2271 58 st = c->fc->streams[c->fc->nb_streams-1];
2272
2273
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
58 if (st->codecpar->codec_id != codec_id)
2274 19 return 0; /* unexpected codec_id - don't mess with extradata */
2275
2276 39 original_size = st->codecpar->extradata_size;
2277 39 err = mov_realloc_extradata(st->codecpar, atom);
2278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err)
2279 return err;
2280
2281 39 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
2282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err < 0)
2283 return err;
2284 39 return 0; // Note: this is the original behavior to ignore truncation.
2285 }
2286
2287 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
2288 16 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2289 {
2290 16 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
2291 }
2292
2293 static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2294 {
2295 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS);
2296 }
2297
2298 static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2299 {
2300 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
2301 }
2302
2303 static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2304 {
2305 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
2306 }
2307
2308 19 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2309 {
2310 19 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
2311
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!ret)
2312 19 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
2313 19 return ret;
2314 }
2315
2316 static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2317 {
2318 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
2319
2320 if (!ret && c->fc->nb_streams >= 1) {
2321 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2322 if (par->extradata_size >= 40) {
2323 par->height = AV_RB16(&par->extradata[36]);
2324 par->width = AV_RB16(&par->extradata[38]);
2325 }
2326 }
2327 return ret;
2328 }
2329
2330 16 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2331 {
2332
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (c->fc->nb_streams >= 1) {
2333 16 AVStream *const st = c->fc->streams[c->fc->nb_streams - 1];
2334 16 FFStream *const sti = ffstream(st);
2335 16 AVCodecParameters *par = st->codecpar;
2336
2337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
2338 par->codec_id == AV_CODEC_ID_H264 &&
2339 atom.size > 11) {
2340 int cid;
2341 avio_skip(pb, 10);
2342 cid = avio_rb16(pb);
2343 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
2344 if (cid == 0xd4d || cid == 0xd4e)
2345 par->width = 1440;
2346 return 0;
2347
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
2348
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
2349
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
2350
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 atom.size >= 24) {
2351 int num, den;
2352 13 avio_skip(pb, 12);
2353 13 num = avio_rb32(pb);
2354 13 den = avio_rb32(pb);
2355
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)
2356 return 0;
2357
2/3
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
13 switch (avio_rb32(pb)) {
2358 12 case 2:
2359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (den >= INT_MAX / 2)
2360 return 0;
2361 12 den *= 2;
2362 13 case 1:
2363 13 sti->display_aspect_ratio = (AVRational){ num, den };
2364 13 default:
2365 13 return 0;
2366 }
2367 }
2368 }
2369
2370 3 return mov_read_avid(c, pb, atom);
2371 }
2372
2373 26 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2374 {
2375 26 int ret = 0;
2376 26 int length = 0;
2377 uint64_t original_size;
2378
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (c->fc->nb_streams >= 1) {
2379 26 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (par->codec_id == AV_CODEC_ID_H264)
2381 return 0;
2382
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (atom.size == 16) {
2383 26 original_size = par->extradata_size;
2384 26 ret = mov_realloc_extradata(par, atom);
2385
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!ret) {
2386 26 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
2387
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (length == atom.size) {
2388 26 const uint8_t range_value = par->extradata[original_size + 19];
2389
1/3
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
26 switch (range_value) {
2390 26 case 1:
2391 26 par->color_range = AVCOL_RANGE_MPEG;
2392 26 break;
2393 case 2:
2394 par->color_range = AVCOL_RANGE_JPEG;
2395 break;
2396 default:
2397 av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
2398 break;
2399 }
2400 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
2401 } else {
2402 /* For some reason the whole atom was not added to the extradata */
2403 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
2404 }
2405 } else {
2406 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
2407 }
2408 } else {
2409 av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
2410 }
2411 }
2412
2413 26 return ret;
2414 }
2415
2416 4 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2417 {
2418 4 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
2419 }
2420
2421 35 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2422 {
2423 AVStream *st;
2424 int ret;
2425
2426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (c->fc->nb_streams < 1)
2427 return 0;
2428 35 st = c->fc->streams[c->fc->nb_streams-1];
2429
2430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if ((uint64_t)atom.size > (1<<30))
2431 return AVERROR_INVALIDDATA;
2432
2433
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 2 times.
35 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2434
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
2436 // pass all frma atom to codec, needed at least for QDMC and QDM2
2437 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2439 return ret;
2440
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 } else if (atom.size > 8) { /* to read frma, esds atoms */
2441
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
33 if (st->codecpar->codec_id == AV_CODEC_ID_ALAC && atom.size >= 24) {
2442 uint64_t buffer;
2443 10 ret = ffio_ensure_seekback(pb, 8);
2444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2445 return ret;
2446 10 buffer = avio_rb64(pb);
2447 10 atom.size -= 8;
2448
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
2449
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 <= atom.size
2450
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 >= 8) {
2451 10 avio_skip(pb, -8);
2452 10 atom.size += 8;
2453 } else if (!st->codecpar->extradata_size) {
2454 #define ALAC_EXTRADATA_SIZE 36
2455 st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
2456 if (!st->codecpar->extradata)
2457 return AVERROR(ENOMEM);
2458 st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
2459 AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
2460 AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
2461 AV_WB64(st->codecpar->extradata + 12, buffer);
2462 avio_read(pb, st->codecpar->extradata + 20, 16);
2463 avio_skip(pb, atom.size - 24);
2464 return 0;
2465 }
2466 }
2467
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
33 if ((ret = mov_read_default(c, pb, atom)) < 0)
2468 return ret;
2469 } else
2470 avio_skip(pb, atom.size);
2471 35 return 0;
2472 }
2473
2474 /**
2475 * This function reads atom content and puts data in extradata without tag
2476 * nor size unlike mov_read_extradata.
2477 */
2478 174 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2479 {
2480 AVStream *st;
2481 int ret;
2482
2483 174 st = get_curr_st(c);
2484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
174 if (!st)
2485 return 0;
2486
2487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
174 if ((uint64_t)atom.size > (1<<30))
2488 return AVERROR_INVALIDDATA;
2489
2490
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 173 times.
174 if (atom.type == MKTAG('v','v','c','C')) {
2491 1 avio_skip(pb, 4);
2492 1 atom.size -= 4;
2493 }
2494
2495
2/2
✓ Branch 0 taken 170 times.
✓ Branch 1 taken 4 times.
174 if (atom.size >= 10) {
2496 // Broken files created by legacy versions of libavformat will
2497 // wrap a whole fiel atom inside of a glbl atom.
2498 170 unsigned size = avio_rb32(pb);
2499 170 unsigned type = avio_rl32(pb);
2500
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 170 times.
170 if (avio_feof(pb))
2501 return AVERROR_INVALIDDATA;
2502 170 avio_seek(pb, -8, SEEK_CUR);
2503
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 160 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
170 if (type == MKTAG('f','i','e','l') && size == atom.size)
2504 10 return mov_read_default(c, pb, atom);
2505 }
2506
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 164 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
164 if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
2507 av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
2508 return 0;
2509 }
2510 164 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2511
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 164 times.
164 if (ret < 0)
2512 return ret;
2513
3/4
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 105 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 59 times.
164 if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
2514 /* HEVC-based Dolby Vision derived from hvc1.
2515 Happens to match with an identifier
2516 previously utilized for DV. Thus, if we have
2517 the hvcC extradata box available as specified,
2518 set codec to HEVC */
2519 st->codecpar->codec_id = AV_CODEC_ID_HEVC;
2520
2521 164 return 0;
2522 }
2523
2524 2 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2525 {
2526 AVStream *st;
2527 uint8_t profile_level;
2528 int ret;
2529
2530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
2531 return 0;
2532 2 st = c->fc->streams[c->fc->nb_streams-1];
2533
2534
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)
2535 return AVERROR_INVALIDDATA;
2536
2537 2 profile_level = avio_r8(pb);
2538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((profile_level & 0xf0) != 0xc0)
2539 return 0;
2540
2541 2 avio_seek(pb, 6, SEEK_CUR);
2542 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
2543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2544 return ret;
2545
2546 2 return 0;
2547 }
2548
2549 static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2550 {
2551 AVStream* st;
2552 MOVStreamContext* sc;
2553
2554 if (c->fc->nb_streams < 1)
2555 return 0;
2556
2557 /* For SBAS this should be fine - though beware if someone implements a
2558 * tref atom processor that doesn't drop down to default then this may
2559 * be lost. */
2560 if (atom.size > 4) {
2561 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2562 return AVERROR_PATCHWELCOME;
2563 }
2564
2565 st = c->fc->streams[c->fc->nb_streams - 1];
2566 sc = st->priv_data;
2567 sc->tref_id = avio_rb32(pb);
2568 sc->tref_flags |= MOV_TREF_FLAG_ENHANCEMENT;
2569
2570 return 0;
2571 }
2572
2573 /**
2574 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2575 * but can have extradata appended at the end after the 40 bytes belonging
2576 * to the struct.
2577 */
2578 static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2579 {
2580 AVStream *st;
2581 int ret;
2582
2583 if (c->fc->nb_streams < 1)
2584 return 0;
2585 if (atom.size <= 40)
2586 return 0;
2587 st = c->fc->streams[c->fc->nb_streams-1];
2588
2589 if ((uint64_t)atom.size > (1<<30))
2590 return AVERROR_INVALIDDATA;
2591
2592 avio_skip(pb, 40);
2593 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
2594 if (ret < 0)
2595 return ret;
2596
2597 return 0;
2598 }
2599
2600 627 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2601 {
2602 AVStream *st;
2603 MOVStreamContext *sc;
2604 unsigned int i, entries;
2605
2606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->trak_index < 0) {
2607 av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
2608 return 0;
2609 }
2610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->fc->nb_streams < 1)
2611 return 0;
2612 627 st = c->fc->streams[c->fc->nb_streams-1];
2613 627 sc = st->priv_data;
2614
2615 627 avio_r8(pb); /* version */
2616 627 avio_rb24(pb); /* flags */
2617
2618 // Clamp allocation size for `chunk_offsets` -- don't throw an error for an
2619 // invalid count since the EOF path doesn't throw either.
2620 627 entries = avio_rb32(pb);
2621 627 entries =
2622
2/2
✓ Branch 0 taken 622 times.
✓ Branch 1 taken 5 times.
627 FFMIN(entries,
2623 FFMAX(0, (atom.size - 8) /
2624 (atom.type == MKTAG('s', 't', 'c', 'o') ? 4 : 8)));
2625
2626
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 598 times.
627 if (!entries)
2627 29 return 0;
2628
2629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (sc->chunk_offsets) {
2630 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2631 return 0;
2632 }
2633
2634 598 av_free(sc->chunk_offsets);
2635 598 sc->chunk_count = 0;
2636 598 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (!sc->chunk_offsets)
2638 return AVERROR(ENOMEM);
2639 598 sc->chunk_count = entries;
2640
2641
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 4 times.
598 if (atom.type == MKTAG('s','t','c','o'))
2642
3/4
✓ Branch 0 taken 43404 times.
✓ Branch 1 taken 594 times.
✓ Branch 2 taken 43404 times.
✗ Branch 3 not taken.
43998 for (i = 0; i < entries && !pb->eof_reached; i++)
2643 43404 sc->chunk_offsets[i] = avio_rb32(pb);
2644
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (atom.type == MKTAG('c','o','6','4'))
2645
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++) {
2646 136336 sc->chunk_offsets[i] = avio_rb64(pb);
2647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136336 times.
136336 if (sc->chunk_offsets[i] < 0) {
2648 av_log(c->fc, AV_LOG_WARNING, "Impossible chunk_offset\n");
2649 sc->chunk_offsets[i] = 0;
2650 }
2651 }
2652 else
2653 return AVERROR_INVALIDDATA;
2654
2655 598 sc->chunk_count = i;
2656
2657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (pb->eof_reached) {
2658 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2659 return AVERROR_EOF;
2660 }
2661
2662 598 return 0;
2663 }
2664
2665 690 static int mov_codec_id(AVStream *st, uint32_t format)
2666 {
2667 690 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2668
2669
2/2
✓ Branch 0 taken 466 times.
✓ Branch 1 taken 224 times.
690 if (id <= 0 &&
2670
2/2
✓ Branch 0 taken 463 times.
✓ Branch 1 taken 3 times.
466 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 463 times.
463 (format & 0xFFFF) == 'T' + ('S' << 8)))
2672 3 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2673
2674
4/4
✓ Branch 0 taken 303 times.
✓ Branch 1 taken 387 times.
✓ Branch 2 taken 227 times.
✓ Branch 3 taken 76 times.
690 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2675 227 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2676
3/4
✓ Branch 0 taken 443 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 443 times.
✗ Branch 3 not taken.
463 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2677 /* skip old ASF MPEG-4 tag */
2678
2/2
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 4 times.
443 format && format != MKTAG('m','p','4','s')) {
2679 439 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2680
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 377 times.
439 if (id <= 0)
2681 62 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2682
2/2
✓ Branch 0 taken 381 times.
✓ Branch 1 taken 58 times.
439 if (id > 0)
2683 381 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2684
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 51 times.
58 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2685
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2687 51 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2688
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 6 times.
51 if (id <= 0) {
2689
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 4 times.
86 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2690
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 4 times.
86 AV_CODEC_ID_TTML : id;
2691 }
2692
2693
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 37 times.
51 if (id > 0)
2694 14 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2695 else
2696 37 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2697 }
2698 }
2699
2700 690 st->codecpar->codec_tag = format;
2701
2702 690 return id;
2703 }
2704
2705 338 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2706 AVStream *st, MOVStreamContext *sc)
2707 {
2708 338 uint8_t codec_name[32] = { 0 };
2709 int64_t stsd_start;
2710 unsigned int len;
2711 338 uint32_t id = 0;
2712
2713 /* The first 16 bytes of the video sample description are already
2714 * read in ff_mov_read_stsd_entries() */
2715 338 stsd_start = avio_tell(pb) - 16;
2716
2717
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 240 times.
338 if (c->isom) {
2718 98 avio_skip(pb, 2); /* pre_defined */
2719 98 avio_skip(pb, 2); /* reserved */
2720 98 avio_skip(pb, 12); /* pre_defined */
2721 } else {
2722 240 avio_rb16(pb); /* version */
2723 240 avio_rb16(pb); /* revision level */
2724 240 id = avio_rl32(pb); /* vendor */
2725 240 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2726 240 avio_rb32(pb); /* temporal quality */
2727 240 avio_rb32(pb); /* spatial quality */
2728 }
2729
2730 338 st->codecpar->width = avio_rb16(pb); /* width */
2731 338 st->codecpar->height = avio_rb16(pb); /* height */
2732
2733 338 avio_rb32(pb); /* horiz resolution */
2734 338 avio_rb32(pb); /* vert resolution */
2735 338 avio_rb32(pb); /* data size, always 0 */
2736 338 avio_rb16(pb); /* frames per samples */
2737
2738 338 len = avio_r8(pb); /* codec name, pascal string */
2739
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 337 times.
338 if (len > 31)
2740 1 len = 31;
2741 338 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2742
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 3 times.
338 if (len < 31)
2743 335 avio_skip(pb, 31 - len);
2744
2745
2/2
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 72 times.
338 if (codec_name[0])
2746 266 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2747
2748 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
338 if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2750 st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2751 st->codecpar->width &= ~1;
2752 st->codecpar->height &= ~1;
2753 }
2754 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
338 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2756 !strncmp(codec_name, "Sorenson H263", 13))
2757 st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2758
2759 338 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2760
2761 338 avio_seek(pb, stsd_start, SEEK_SET);
2762
2763
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 320 times.
338 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2764 18 st->codecpar->bits_per_coded_sample &= 0x1F;
2765 18 sc->has_palette = 1;
2766 }
2767 338 }
2768
2769 247 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2770 AVStream *st, MOVStreamContext *sc)
2771 {
2772 int bits_per_sample, flags;
2773 247 uint16_t version = avio_rb16(pb);
2774 247 uint32_t id = 0;
2775 247 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2776 int channel_count;
2777
2778
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 87 times.
247 if (c->isom)
2779 160 avio_skip(pb, 6); /* reserved */
2780 else {
2781 87 avio_rb16(pb); /* revision level */
2782 87 id = avio_rl32(pb); /* vendor */
2783 87 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2784 }
2785
2786 247 channel_count = avio_rb16(pb);
2787
2788 247 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2789 247 st->codecpar->ch_layout.nb_channels = channel_count;
2790 247 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
2791 247 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
2792
2793 247 sc->audio_cid = avio_rb16(pb);
2794 247 avio_rb16(pb); /* packet size = 0 */
2795
2796 247 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
2797
2798 // Read QT version 1 fields. In version 0 these do not exist.
2799 247 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
2800
3/4
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 160 times.
✗ Branch 3 not taken.
247 if (!c->isom ||
2801
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
2802
4/4
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 151 times.
160 (sc->stsd_version == 0 && version > 0)) {
2803
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 40 times.
91 if (version == 1) {
2804 51 sc->samples_per_frame = avio_rb32(pb);
2805 51 avio_rb32(pb); /* bytes per packet */
2806 51 sc->bytes_per_frame = avio_rb32(pb);
2807 51 avio_rb32(pb); /* bytes per sample */
2808
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
40 } else if (version == 2) {
2809 4 avio_rb32(pb); /* sizeof struct only */
2810 4 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
2811 4 channel_count = avio_rb32(pb);
2812 4 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2813 4 st->codecpar->ch_layout.nb_channels = channel_count;
2814 4 avio_rb32(pb); /* always 0x7F000000 */
2815 4 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
2816
2817 4 flags = avio_rb32(pb); /* lpcm format specific flag */
2818 4 sc->bytes_per_frame = avio_rb32(pb);
2819 4 sc->samples_per_frame = avio_rb32(pb);
2820
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
2821 st->codecpar->codec_id =
2822 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
2823 flags);
2824 }
2825
6/6
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 27 times.
91 if (version == 0 || (version == 1 && sc->audio_cid != -2)) {
2826 /* can't correctly handle variable sized packet as audio unit */
2827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 switch (st->codecpar->codec_id) {
2828 case AV_CODEC_ID_MP2:
2829 case AV_CODEC_ID_MP3:
2830 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
2831 break;
2832 }
2833 }
2834 }
2835
2836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 247 times.
247 if (sc->format == 0) {
2837 if (st->codecpar->bits_per_coded_sample == 8)
2838 st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
2839 else if (st->codecpar->bits_per_coded_sample == 16)
2840 st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
2841 }
2842
2843
7/7
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 205 times.
247 switch (st->codecpar->codec_id) {
2844 7 case AV_CODEC_ID_PCM_S8:
2845 case AV_CODEC_ID_PCM_U8:
2846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
2847 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2848 7 break;
2849 19 case AV_CODEC_ID_PCM_S16LE:
2850 case AV_CODEC_ID_PCM_S16BE:
2851
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
19 if (st->codecpar->bits_per_coded_sample == 8)
2852 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
2853
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 24)
2854 st->codecpar->codec_id =
2855 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2856 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
2857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 32)
2858 st->codecpar->codec_id =
2859 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2860 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
2861 19 break;
2862 /* set values for old format before stsd version 1 appeared */
2863 2 case AV_CODEC_ID_MACE3:
2864 2 sc->samples_per_frame = 6;
2865 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
2866 2 break;
2867 8 case AV_CODEC_ID_MACE6:
2868 8 sc->samples_per_frame = 6;
2869 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
2870 8 break;
2871 5 case AV_CODEC_ID_ADPCM_IMA_QT:
2872 5 sc->samples_per_frame = 64;
2873 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
2874 5 break;
2875 1 case AV_CODEC_ID_GSM:
2876 1 sc->samples_per_frame = 160;
2877 1 sc->bytes_per_frame = 33;
2878 1 break;
2879 205 default:
2880 205 break;
2881 }
2882
2883 247 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2884
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 199 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
247 if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->ch_layout.nb_channels <= INT_MAX) {
2885 48 st->codecpar->bits_per_coded_sample = bits_per_sample;
2886 48 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
2887 }
2888 247 }
2889
2890 15 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
2891 AVStream *st, MOVStreamContext *sc,
2892 int64_t size)
2893 {
2894 // ttxt stsd contains display flags, justification, background
2895 // color, fonts, and default styles, so fake an atom to read it
2896 15 MOVAtom fake_atom = { .size = size };
2897 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
2898 // in extradata unlike stpp MP4 TTML.
2899
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
2900
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
15 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
2901 11 mov_read_glbl(c, pb, fake_atom);
2902 15 st->codecpar->width = sc->width;
2903 15 st->codecpar->height = sc->height;
2904 15 }
2905
2906 41 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
2907 AVStream *st, MOVStreamContext *sc,
2908 int64_t size)
2909 {
2910 int ret;
2911
2912
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 22 times.
41 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
2913
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if ((int)size != size)
2914 return AVERROR(ENOMEM);
2915
2916 19 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
2917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
2918 return ret;
2919
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (size > 16) {
2920 19 MOVStreamContext *tmcd_ctx = st->priv_data;
2921 int val;
2922 19 val = AV_RB32(st->codecpar->extradata + 4);
2923 19 tmcd_ctx->tmcd_flags = val;
2924 19 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
2925 19 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
2926 19 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
2927
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (size > 30) {
2928 4 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
2929 4 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
2930
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if (format == AV_RB32("name") && (int64_t)size >= (int64_t)len + 18) {
2931 4 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
2932
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if (str_size > 0 && size >= (int)str_size + 30 &&
2933
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 st->codecpar->extradata[30] /* Don't add empty string */) {
2934 4 char *reel_name = av_malloc(str_size + 1);
2935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!reel_name)
2936 return AVERROR(ENOMEM);
2937 4 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
2938 4 reel_name[str_size] = 0; /* Add null terminator */
2939 4 av_dict_set(&st->metadata, "reel_name", reel_name,
2940 AV_DICT_DONT_STRDUP_VAL);
2941 }
2942 }
2943 }
2944 }
2945 } else {
2946 /* other codec type, just skip (rtp, mp4s ...) */
2947 22 avio_skip(pb, size);
2948 }
2949 41 return 0;
2950 }
2951
2952 627 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
2953 AVStream *st, MOVStreamContext *sc)
2954 {
2955 627 FFStream *const sti = ffstream(st);
2956
2957
2/2
✓ Branch 0 taken 247 times.
✓ Branch 1 taken 380 times.
627 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
2958
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 247 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
247 !st->codecpar->sample_rate && sc->time_scale > 1)
2959 st->codecpar->sample_rate = sc->time_scale;
2960
2961 /* special codec parameters handling */
2962
7/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 15 times.
✓ Branch 6 taken 16 times.
✓ Branch 7 taken 10 times.
✓ Branch 8 taken 106 times.
✓ Branch 9 taken 468 times.
627 switch (st->codecpar->codec_id) {
2963 #if CONFIG_DV_DEMUXER
2964 case AV_CODEC_ID_DVAUDIO:
2965 if (c->dv_fctx) {
2966 avpriv_request_sample(c->fc, "multiple DV audio streams");
2967 return AVERROR(ENOSYS);
2968 }
2969
2970 c->dv_fctx = avformat_alloc_context();
2971 if (!c->dv_fctx) {
2972 av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
2973 return AVERROR(ENOMEM);
2974 }
2975 c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
2976 if (!c->dv_demux) {
2977 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
2978 return AVERROR(ENOMEM);
2979 }
2980 sc->dv_audio_container = 1;
2981 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2982 break;
2983 #endif
2984 /* no ifdef since parameters are always those */
2985 case AV_CODEC_ID_QCELP:
2986 av_channel_layout_uninit(&st->codecpar->ch_layout);
2987 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2988 // force sample rate for qcelp when not stored in mov
2989 if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
2990 st->codecpar->sample_rate = 8000;
2991 // FIXME: Why is the following needed for some files?
2992 sc->samples_per_frame = 160;
2993 if (!sc->bytes_per_frame)
2994 sc->bytes_per_frame = 35;
2995 break;
2996 case AV_CODEC_ID_AMR_NB:
2997 av_channel_layout_uninit(&st->codecpar->ch_layout);
2998 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2999 /* force sample rate for amr, stsd in 3gp does not store sample rate */
3000 st->codecpar->sample_rate = 8000;
3001 break;
3002 11 case AV_CODEC_ID_AMR_WB:
3003 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
3004 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3005 11 st->codecpar->sample_rate = 16000;
3006 11 break;
3007 1 case AV_CODEC_ID_MP2:
3008 case AV_CODEC_ID_MP3:
3009 /* force type after stsd for m1a hdlr */
3010 1 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
3011 1 break;
3012 15 case AV_CODEC_ID_GSM:
3013 case AV_CODEC_ID_ADPCM_MS:
3014 case AV_CODEC_ID_ADPCM_IMA_WAV:
3015 case AV_CODEC_ID_ILBC:
3016 case AV_CODEC_ID_MACE3:
3017 case AV_CODEC_ID_MACE6:
3018 case AV_CODEC_ID_QDM2:
3019 15 st->codecpar->block_align = sc->bytes_per_frame;
3020 15 break;
3021 16 case AV_CODEC_ID_ALAC:
3022
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
3023 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
3024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
3025 av_channel_layout_uninit(&st->codecpar->ch_layout);
3026 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3027 st->codecpar->ch_layout.nb_channels = channel_count;
3028 }
3029 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
3030 }
3031 16 break;
3032 10 case AV_CODEC_ID_AC3:
3033 case AV_CODEC_ID_EAC3:
3034 case AV_CODEC_ID_MPEG1VIDEO:
3035 case AV_CODEC_ID_VC1:
3036 case AV_CODEC_ID_VP8:
3037 case AV_CODEC_ID_VP9:
3038 10 sti->need_parsing = AVSTREAM_PARSE_FULL;
3039 10 break;
3040 106 case AV_CODEC_ID_PRORES_RAW:
3041 case AV_CODEC_ID_PRORES:
3042 case AV_CODEC_ID_APV:
3043 case AV_CODEC_ID_EVC:
3044 case AV_CODEC_ID_AV1:
3045 /* field_order detection of H264 requires parsing */
3046 case AV_CODEC_ID_H264:
3047 106 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3048 106 break;
3049 468 default:
3050 468 break;
3051 }
3052 627 return 0;
3053 }
3054
3055 641 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
3056 int codec_tag, int format,
3057 int64_t size)
3058 {
3059
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 627 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
641 if (codec_tag &&
3060 (codec_tag != format &&
3061 // AVID 1:1 samples with differing data format and codec tag exist
3062 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
3063 // prores is allowed to have differing data format and codec tag
3064 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
3065 // so is dv (sigh)
3066 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
3067 (c->fc->video_codec_id ? ff_codec_get_id(ff_codec_movvideo_tags, format) != c->fc->video_codec_id
3068 : codec_tag != MKTAG('j','p','e','g')))) {
3069 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3070 * export it as a separate AVStream but this needs a few changes
3071 * in the MOV demuxer, patch welcome. */
3072
3073 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3074 avio_skip(pb, size);
3075 return 1;
3076 }
3077
3078 641 return 0;
3079 }
3080
3081 641 static int mov_finalize_stsd_entry(MOVContext *c, AVStream *st)
3082 {
3083 int ret;
3084
3085 /* special codec parameters handling */
3086
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 560 times.
641 switch (st->codecpar->codec_id) {
3087 81 case AV_CODEC_ID_H264:
3088 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
3089
1/30
✗ Branch 0 not taken.
✓ Branch 1 taken 81 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.
81 if (!st->codecpar->extradata_size && TAG_IS_AVCI(st->codecpar->codec_tag)) {
3090 ret = ff_generate_avci_extradata(st);
3091 if (ret < 0)
3092 return ret;
3093 }
3094 81 break;
3095 560 default:
3096 560 break;
3097 }
3098
3099 641 return 0;
3100 }
3101
3102 627 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3103 {
3104 AVStream *st;
3105 MOVStreamContext *sc;
3106 int pseudo_stream_id;
3107
3108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 av_assert0 (c->fc->nb_streams >= 1);
3109 627 st = c->fc->streams[c->fc->nb_streams-1];
3110 627 sc = st->priv_data;
3111
3112 627 for (pseudo_stream_id = 0;
3113
3/4
✓ Branch 0 taken 641 times.
✓ Branch 1 taken 627 times.
✓ Branch 2 taken 641 times.
✗ Branch 3 not taken.
1268 pseudo_stream_id < entries && !pb->eof_reached;
3114 641 pseudo_stream_id++) {
3115 //Parsing Sample description table
3116 enum AVCodecID id;
3117 641 int ret, dref_id = 1;
3118 641 MOVAtom a = { AV_RL32("stsd") };
3119 641 int64_t start_pos = avio_tell(pb);
3120 641 int64_t size = avio_rb32(pb); /* size */
3121 641 uint32_t format = avio_rl32(pb); /* data format */
3122
3123
1/2
✓ Branch 0 taken 641 times.
✗ Branch 1 not taken.
641 if (size >= 16) {
3124 641 avio_rb32(pb); /* reserved */
3125 641 avio_rb16(pb); /* reserved */
3126 641 dref_id = avio_rb16(pb);
3127 } else if (size <= 7) {
3128 av_log(c->fc, AV_LOG_ERROR,
3129 "invalid size %"PRId64" in stsd\n", size);
3130 return AVERROR_INVALIDDATA;
3131 }
3132
3133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 641 times.
641 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3134 641 size - (avio_tell(pb) - start_pos))) {
3135 sc->stsd_count++;
3136 continue;
3137 }
3138
3139
2/2
✓ Branch 0 taken 627 times.
✓ Branch 1 taken 14 times.
641 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
3140 641 sc->dref_id= dref_id;
3141 641 sc->format = format;
3142
3143 641 id = mov_codec_id(st, format);
3144
3145 641 av_log(c->fc, AV_LOG_TRACE,
3146 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3147 641 av_fourcc2str(format), st->codecpar->codec_type);
3148
3149 641 st->codecpar->codec_id = id;
3150
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 303 times.
641 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3151 338 mov_parse_stsd_video(c, pb, st, sc);
3152
2/2
✓ Branch 0 taken 247 times.
✓ Branch 1 taken 56 times.
303 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3153 247 mov_parse_stsd_audio(c, pb, st, sc);
3154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 247 times.
247 if (st->codecpar->sample_rate < 0) {
3155 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3156 return AVERROR_INVALIDDATA;
3157 }
3158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 247 times.
247 if (st->codecpar->ch_layout.nb_channels < 0) {
3159 av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3160 return AVERROR_INVALIDDATA;
3161 }
3162
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 41 times.
56 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3163 15 mov_parse_stsd_subtitle(c, pb, st, sc,
3164 15 size - (avio_tell(pb) - start_pos));
3165 } else {
3166 41 ret = mov_parse_stsd_data(c, pb, st, sc,
3167 41 size - (avio_tell(pb) - start_pos));
3168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ret < 0)
3169 return ret;
3170 }
3171 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3172 641 a.size = size - (avio_tell(pb) - start_pos);
3173
2/2
✓ Branch 0 taken 506 times.
✓ Branch 1 taken 135 times.
641 if (a.size > 8) {
3174
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 506 times.
506 if ((ret = mov_read_default(c, pb, a)) < 0)
3175 return ret;
3176
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 134 times.
135 } else if (a.size > 0)
3177 1 avio_skip(pb, a.size);
3178
3179 641 ret = mov_finalize_stsd_entry(c, st);
3180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 641 times.
641 if (ret < 0)
3181 return ret;
3182
3183
3/4
✓ Branch 0 taken 641 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 366 times.
✓ Branch 3 taken 275 times.
641 if (sc->extradata && st->codecpar->extradata) {
3184 366 int extra_size = st->codecpar->extradata_size;
3185
3186 /* Move the current stream extradata to the stream context one. */
3187 366 sc->extradata_size[pseudo_stream_id] = extra_size;
3188 366 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3189 366 st->codecpar->extradata = NULL;
3190 366 st->codecpar->extradata_size = 0;
3191 }
3192 641 sc->stsd_count++;
3193 }
3194
3195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (pb->eof_reached) {
3196 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3197 return AVERROR_EOF;
3198 }
3199
3200 627 return 0;
3201 }
3202
3203 627 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3204 {
3205 AVStream *st;
3206 MOVStreamContext *sc;
3207 int ret, entries;
3208
3209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->fc->nb_streams < 1)
3210 return 0;
3211 627 st = c->fc->streams[c->fc->nb_streams - 1];
3212 627 sc = st->priv_data;
3213
3214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (sc->extradata) {
3215 av_log(c->fc, AV_LOG_ERROR,
3216 "Duplicate stsd found in this track.\n");
3217 return AVERROR_INVALIDDATA;
3218 }
3219
3220 627 sc->stsd_version = avio_r8(pb);
3221 627 avio_rb24(pb); /* flags */
3222 627 entries = avio_rb32(pb);
3223
3224 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3225
3/6
✓ Branch 0 taken 627 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 627 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 627 times.
627 if (entries <= 0 || entries > atom.size / 8 || entries > 1024) {
3226 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3227 return AVERROR_INVALIDDATA;
3228 }
3229
3230 /* Prepare space for hosting multiple extradata. */
3231 627 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (!sc->extradata)
3233 return AVERROR(ENOMEM);
3234
3235 627 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (!sc->extradata_size) {
3237 ret = AVERROR(ENOMEM);
3238 goto fail;
3239 }
3240
3241 627 ret = ff_mov_read_stsd_entries(c, pb, entries);
3242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (ret < 0)
3243 goto fail;
3244
3245 /* Restore back the primary extradata. */
3246 627 av_freep(&st->codecpar->extradata);
3247 627 st->codecpar->extradata_size = sc->extradata_size[0];
3248
2/2
✓ Branch 0 taken 353 times.
✓ Branch 1 taken 274 times.
627 if (sc->extradata_size[0]) {
3249 353 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 353 times.
353 if (!st->codecpar->extradata)
3251 return AVERROR(ENOMEM);
3252 353 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3253 }
3254
3255 627 return mov_finalize_stsd_codec(c, pb, st, sc);
3256 fail:
3257 if (sc->extradata) {
3258 int j;
3259 for (j = 0; j < sc->stsd_count; j++)
3260 av_freep(&sc->extradata[j]);
3261 }
3262
3263 sc->stsd_count = 0;
3264 av_freep(&sc->extradata);
3265 av_freep(&sc->extradata_size);
3266 return ret;
3267 }
3268
3269 627 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3270 {
3271 AVStream *st;
3272 MOVStreamContext *sc;
3273 unsigned int i, entries;
3274
3275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->trak_index < 0) {
3276 av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3277 return 0;
3278 }
3279
3280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->fc->nb_streams < 1)
3281 return 0;
3282 627 st = c->fc->streams[c->fc->nb_streams-1];
3283 627 sc = st->priv_data;
3284
3285 627 avio_r8(pb); /* version */
3286 627 avio_rb24(pb); /* flags */
3287
3288 627 entries = avio_rb32(pb);
3289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if ((uint64_t)entries * 12 + 4 > atom.size)
3290 return AVERROR_INVALIDDATA;
3291
3292 627 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3293
3294
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 599 times.
627 if (!entries)
3295 28 return 0;
3296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 599 times.
599 if (sc->stsc_data) {
3297 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3298 return 0;
3299 }
3300 599 av_free(sc->stsc_data);
3301 599 sc->stsc_count = 0;
3302 599 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 599 times.
599 if (!sc->stsc_data)
3304 return AVERROR(ENOMEM);
3305
3306
3/4
✓ Branch 0 taken 3825 times.
✓ Branch 1 taken 599 times.
✓ Branch 2 taken 3825 times.
✗ Branch 3 not taken.
4424 for (i = 0; i < entries && !pb->eof_reached; i++) {
3307 3825 sc->stsc_data[i].first = avio_rb32(pb);
3308 3825 sc->stsc_data[i].count = avio_rb32(pb);
3309 3825 sc->stsc_data[i].id = avio_rb32(pb);
3310 }
3311
3312 599 sc->stsc_count = i;
3313
2/2
✓ Branch 0 taken 3825 times.
✓ Branch 1 taken 599 times.
4424 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3314 3825 int64_t first_min = i + 1;
3315
5/6
✓ Branch 0 taken 3226 times.
✓ Branch 1 taken 599 times.
✓ Branch 2 taken 3226 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3226 times.
✓ Branch 5 taken 599 times.
3825 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
3316
1/2
✓ Branch 0 taken 3226 times.
✗ Branch 1 not taken.
3226 (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) ||
3317
1/2
✓ Branch 0 taken 3825 times.
✗ Branch 1 not taken.
3825 sc->stsc_data[i].first < first_min ||
3318
1/2
✓ Branch 0 taken 3825 times.
✗ Branch 1 not taken.
3825 sc->stsc_data[i].count < 1 ||
3319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3825 times.
3825 sc->stsc_data[i].id < 1) {
3320 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);
3321 if (i+1 >= sc->stsc_count) {
3322 if (sc->stsc_data[i].count == 0 && i > 0) {
3323 sc->stsc_count --;
3324 continue;
3325 }
3326 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3327 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3328 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3329 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3330 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3331 continue;
3332 }
3333 av_assert0(sc->stsc_data[i+1].first >= 2);
3334 // We replace this entry by the next valid
3335 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3336 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3337 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3338 }
3339 }
3340
3341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 599 times.
599 if (pb->eof_reached) {
3342 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3343 return AVERROR_EOF;
3344 }
3345
3346 599 return 0;
3347 }
3348
3349 341863 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3350 {
3351 341863 return index < count - 1;
3352 }
3353
3354 /* Compute the samples value for the stsc entry at the given index. */
3355 55662 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3356 {
3357 int chunk_count;
3358
3359
2/2
✓ Branch 1 taken 55466 times.
✓ Branch 2 taken 196 times.
55662 if (mov_stsc_index_valid(index, sc->stsc_count))
3360 55466 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3361 else {
3362 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3364 196 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3365 }
3366
3367 55662 return sc->stsc_data[index].count * (int64_t)chunk_count;
3368 }
3369
3370 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3371 {
3372 AVStream *st;
3373 MOVStreamContext *sc;
3374 unsigned i, entries;
3375
3376 if (c->trak_index < 0) {
3377 av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3378 return 0;
3379 }
3380
3381 if (c->fc->nb_streams < 1)
3382 return 0;
3383 st = c->fc->streams[c->fc->nb_streams-1];
3384 sc = st->priv_data;
3385
3386 avio_rb32(pb); // version + flags
3387
3388 entries = avio_rb32(pb);
3389 if (sc->stps_data)
3390 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3391 av_free(sc->stps_data);
3392 sc->stps_count = 0;
3393 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3394 if (!sc->stps_data)
3395 return AVERROR(ENOMEM);
3396
3397 for (i = 0; i < entries && !pb->eof_reached; i++) {
3398 sc->stps_data[i] = avio_rb32(pb);
3399 }
3400
3401 sc->stps_count = i;
3402
3403 if (pb->eof_reached) {
3404 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3405 return AVERROR_EOF;
3406 }
3407
3408 return 0;
3409 }
3410
3411 154 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3412 {
3413 AVStream *st;
3414 FFStream *sti;
3415 MOVStreamContext *sc;
3416 unsigned int i, entries;
3417
3418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 if (c->trak_index < 0) {
3419 av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3420 return 0;
3421 }
3422
3423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 if (c->fc->nb_streams < 1)
3424 return 0;
3425 154 st = c->fc->streams[c->fc->nb_streams-1];
3426 154 sti = ffstream(st);
3427 154 sc = st->priv_data;
3428
3429 154 avio_r8(pb); /* version */
3430 154 avio_rb24(pb); /* flags */
3431
3432 154 entries = avio_rb32(pb);
3433
3434 154 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3435
3436
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 148 times.
154 if (!entries) {
3437 6 sc->keyframe_absent = 1;
3438
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
6 if (!sti->need_parsing && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
3439 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3440 6 return 0;
3441 }
3442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 148 times.
148 if (sc->keyframes)
3443 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 148 times.
148 if (entries >= UINT_MAX / sizeof(int))
3445 return AVERROR_INVALIDDATA;
3446 148 av_freep(&sc->keyframes);
3447 148 sc->keyframe_count = 0;
3448 148 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 148 times.
148 if (!sc->keyframes)
3450 return AVERROR(ENOMEM);
3451
3452
3/4
✓ Branch 0 taken 5732 times.
✓ Branch 1 taken 148 times.
✓ Branch 2 taken 5732 times.
✗ Branch 3 not taken.
5880 for (i = 0; i < entries && !pb->eof_reached; i++) {
3453 5732 sc->keyframes[i] = avio_rb32(pb);
3454 }
3455
3456 148 sc->keyframe_count = i;
3457
3458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 148 times.
148 if (pb->eof_reached) {
3459 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3460 return AVERROR_EOF;
3461 }
3462
3463 148 return 0;
3464 }
3465
3466 627 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3467 {
3468 AVStream *st;
3469 MOVStreamContext *sc;
3470 unsigned int i, entries, sample_size, field_size, num_bytes;
3471 GetBitContext gb;
3472 unsigned char* buf;
3473 int ret;
3474
3475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->trak_index < 0) {
3476 av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3477 return 0;
3478 }
3479
3480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->fc->nb_streams < 1)
3481 return 0;
3482 627 st = c->fc->streams[c->fc->nb_streams-1];
3483 627 sc = st->priv_data;
3484
3485 627 avio_r8(pb); /* version */
3486 627 avio_rb24(pb); /* flags */
3487
3488
1/2
✓ Branch 0 taken 627 times.
✗ Branch 1 not taken.
627 if (atom.type == MKTAG('s','t','s','z')) {
3489 627 sample_size = avio_rb32(pb);
3490
2/2
✓ Branch 0 taken 586 times.
✓ Branch 1 taken 41 times.
627 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3491 586 sc->sample_size = sample_size;
3492 627 sc->stsz_sample_size = sample_size;
3493 627 field_size = 32;
3494 } else {
3495 sample_size = 0;
3496 avio_rb24(pb); /* reserved */
3497 field_size = avio_r8(pb);
3498 }
3499 627 entries = avio_rb32(pb);
3500
3501 627 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3502
3503 627 sc->sample_count = entries;
3504
2/2
✓ Branch 0 taken 203 times.
✓ Branch 1 taken 424 times.
627 if (sample_size)
3505 203 return 0;
3506
3507
4/8
✓ Branch 0 taken 424 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 424 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 424 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 424 times.
424 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
3508 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3509 return AVERROR_INVALIDDATA;
3510 }
3511
3512
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 395 times.
424 if (!entries)
3513 29 return 0;
3514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 395 times.
395 if (entries >= (INT_MAX - 4 - 8 * AV_INPUT_BUFFER_PADDING_SIZE) / field_size)
3515 return AVERROR_INVALIDDATA;
3516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 395 times.
395 if (sc->sample_sizes)
3517 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3518 395 av_free(sc->sample_sizes);
3519 395 sc->sample_count = 0;
3520 395 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 395 times.
395 if (!sc->sample_sizes)
3522 return AVERROR(ENOMEM);
3523
3524 395 num_bytes = (entries*field_size+4)>>3;
3525
3526 395 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 395 times.
395 if (!buf) {
3528 av_freep(&sc->sample_sizes);
3529 return AVERROR(ENOMEM);
3530 }
3531
3532 395 ret = ffio_read_size(pb, buf, num_bytes);
3533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 395 times.
395 if (ret < 0) {
3534 av_freep(&sc->sample_sizes);
3535 av_free(buf);
3536 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3537 return 0;
3538 }
3539
3540 395 init_get_bits(&gb, buf, 8*num_bytes);
3541
3542
2/2
✓ Branch 0 taken 227737 times.
✓ Branch 1 taken 395 times.
228132 for (i = 0; i < entries; i++) {
3543 227737 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 227737 times.
227737 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3545 av_free(buf);
3546 av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3547 return AVERROR_INVALIDDATA;
3548 }
3549 227737 sc->data_size += sc->sample_sizes[i];
3550 }
3551
3552 395 sc->sample_count = i;
3553
3554 395 av_free(buf);
3555
3556 395 return 0;
3557 }
3558
3559 627 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3560 {
3561 AVStream *st;
3562 MOVStreamContext *sc;
3563 unsigned int i, entries;
3564 627 int64_t duration = 0;
3565 627 int64_t total_sample_count = 0;
3566 627 int64_t current_dts = 0;
3567 627 int64_t corrected_dts = 0;
3568
3569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->trak_index < 0) {
3570 av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3571 return 0;
3572 }
3573
3574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->fc->nb_streams < 1)
3575 return 0;
3576 627 st = c->fc->streams[c->fc->nb_streams-1];
3577 627 sc = st->priv_data;
3578
3579 627 avio_r8(pb); /* version */
3580 627 avio_rb24(pb); /* flags */
3581 627 entries = avio_rb32(pb);
3582
3583 627 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3584 627 c->fc->nb_streams-1, entries);
3585
3586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (sc->stts_data)
3587 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3588 627 av_freep(&sc->stts_data);
3589 627 sc->stts_count = 0;
3590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3591 return AVERROR(ENOMEM);
3592
3593
3/4
✓ Branch 0 taken 2991 times.
✓ Branch 1 taken 627 times.
✓ Branch 2 taken 2991 times.
✗ Branch 3 not taken.
3618 for (i = 0; i < entries && !pb->eof_reached; i++) {
3594 unsigned int sample_duration;
3595 unsigned int sample_count;
3596 2991 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3597 2991 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3598 min_entries * sizeof(*sc->stts_data));
3599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2991 times.
2991 if (!stts_data) {
3600 av_freep(&sc->stts_data);
3601 sc->stts_count = 0;
3602 return AVERROR(ENOMEM);
3603 }
3604 2991 sc->stts_count = min_entries;
3605 2991 sc->stts_data = stts_data;
3606
3607 2991 sample_count = avio_rb32(pb);
3608 2991 sample_duration = avio_rb32(pb);
3609
3610 2991 sc->stts_data[i].count= sample_count;
3611 2991 sc->stts_data[i].duration= sample_duration;
3612
3613 2991 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3614 sample_count, sample_duration);
3615
3616 /* STTS sample offsets are uint32 but some files store it as int32
3617 * with negative values used to correct DTS delays.
3618 There may be abnormally large values as well. */
3619
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2990 times.
2991 if (sample_duration > c->max_stts_delta) {
3620 // assume high delta is a correction if negative when cast as int32
3621 1 int32_t delta_magnitude = (int32_t)sample_duration;
3622 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",
3623 sample_duration, i, sample_count, st->index);
3624 1 sc->stts_data[i].duration = 1;
3625
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);
3626 } else {
3627 2990 corrected_dts += sample_duration * (uint64_t)sample_count;
3628 }
3629
3630 2991 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3631
3632
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2969 times.
2991 if (current_dts > corrected_dts) {
3633 22 int64_t drift = av_sat_sub64(current_dts, corrected_dts) / FFMAX(sample_count, 1);
3634
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;
3635 22 current_dts -= correction * (uint64_t)sample_count;
3636 22 sc->stts_data[i].duration -= correction;
3637 }
3638
3639 2991 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3640 2991 total_sample_count+=sc->stts_data[i].count;
3641 }
3642
3643 627 sc->stts_count = i;
3644
3645
2/2
✓ Branch 0 taken 598 times.
✓ Branch 1 taken 29 times.
627 if (duration > 0 &&
3646
1/2
✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
598 duration <= INT64_MAX - sc->duration_for_fps &&
3647
1/2
✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
598 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3648 598 sc->duration_for_fps += duration;
3649 598 sc->nb_frames_for_fps += total_sample_count;
3650 }
3651
3652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (pb->eof_reached) {
3653 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3654 return AVERROR_EOF;
3655 }
3656
3657 627 st->nb_frames= total_sample_count;
3658
2/2
✓ Branch 0 taken 598 times.
✓ Branch 1 taken 29 times.
627 if (duration)
3659 598 st->duration= FFMIN(st->duration, duration);
3660
3661 // All samples have zero duration. They have higher chance be chose by
3662 // mov_find_next_sample, which leads to seek again and again.
3663 //
3664 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3665 // So only mark data stream as discarded for safety.
3666
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 598 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 29 times.
627 if (!duration && sc->stts_count &&
3667 st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3668 av_log(c->fc, AV_LOG_WARNING,
3669 "All samples in data stream index:id [%d:%d] have zero "
3670 "duration, stream set to be discarded by default. Override "
3671 "using AVStream->discard or -discard for ffmpeg command.\n",
3672 st->index, sc->id);
3673 st->discard = AVDISCARD_ALL;
3674 }
3675 627 sc->track_end = duration;
3676 627 return 0;
3677 }
3678
3679 45 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3680 {
3681 AVStream *st;
3682 MOVStreamContext *sc;
3683 unsigned int i;
3684 int64_t entries;
3685
3686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (c->fc->nb_streams < 1)
3687 return 0;
3688 45 st = c->fc->streams[c->fc->nb_streams - 1];
3689 45 sc = st->priv_data;
3690
3691 45 avio_r8(pb); /* version */
3692 45 avio_rb24(pb); /* flags */
3693 45 entries = atom.size - 4;
3694
3695 45 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3696 45 c->fc->nb_streams - 1, entries);
3697
3698
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 37 times.
45 if (sc->sdtp_data)
3699 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3700 45 av_freep(&sc->sdtp_data);
3701 45 sc->sdtp_count = 0;
3702
3703
2/4
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 45 times.
45 if (entries < 0 || entries > UINT_MAX)
3704 return AVERROR(ERANGE);
3705
3706 45 sc->sdtp_data = av_malloc(entries);
3707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (!sc->sdtp_data)
3708 return AVERROR(ENOMEM);
3709
3710
3/4
✓ Branch 0 taken 3811 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 3811 times.
✗ Branch 3 not taken.
3856 for (i = 0; i < entries && !pb->eof_reached; i++)
3711 3811 sc->sdtp_data[i] = avio_r8(pb);
3712 45 sc->sdtp_count = i;
3713
3714 45 return 0;
3715 }
3716
3717 13717 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3718 {
3719
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 12581 times.
13717 if (duration < 0) {
3720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3721 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3722 duration++;
3723 }
3724 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3725 }
3726 13717 }
3727
3728 67 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3729 {
3730 AVStream *st;
3731 MOVStreamContext *sc;
3732 67 unsigned int i, entries, ctts_count = 0;
3733
3734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
67 if (c->trak_index < 0) {
3735 av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
3736 return 0;
3737 }
3738
3739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
67 if (c->fc->nb_streams < 1)
3740 return 0;
3741 67 st = c->fc->streams[c->fc->nb_streams-1];
3742 67 sc = st->priv_data;
3743
3744 67 avio_r8(pb); /* version */
3745 67 avio_rb24(pb); /* flags */
3746 67 entries = avio_rb32(pb);
3747
3748 67 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3749
3750
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 63 times.
67 if (!entries)
3751 4 return 0;
3752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
3753 return AVERROR_INVALIDDATA;
3754 63 av_freep(&sc->ctts_data);
3755 63 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
3756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (!sc->ctts_data)
3757 return AVERROR(ENOMEM);
3758
3759
3/4
✓ Branch 0 taken 5131 times.
✓ Branch 1 taken 63 times.
✓ Branch 2 taken 5131 times.
✗ Branch 3 not taken.
5194 for (i = 0; i < entries && !pb->eof_reached; i++) {
3760 MOVCtts *ctts_data;
3761 5131 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
3762 5131 const size_t requested_size =
3763 5131 min_size_needed > sc->ctts_allocated_size ?
3764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5131 times.
5131 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
3765 min_size_needed;
3766 5131 int count = avio_rb32(pb);
3767 5131 int duration = avio_rb32(pb);
3768
3769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5131 times.
5131 if (count <= 0) {
3770 av_log(c->fc, AV_LOG_TRACE,
3771 "ignoring CTTS entry with count=%d duration=%d\n",
3772 count, duration);
3773 continue;
3774 }
3775
3776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5131 times.
5131 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
3777 return AVERROR(ENOMEM);
3778
3779 5131 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
3780
3781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5131 times.
5131 if (!ctts_data)
3782 return AVERROR(ENOMEM);
3783
3784 5131 sc->ctts_data = ctts_data;
3785
3786 5131 ctts_data[ctts_count].count = count;
3787 5131 ctts_data[ctts_count].offset = duration;
3788 5131 ctts_count++;
3789
3790 5131 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
3791 count, duration);
3792
3793
2/2
✓ Branch 0 taken 5010 times.
✓ Branch 1 taken 121 times.
5131 if (i+2<entries)
3794 5010 mov_update_dts_shift(sc, duration, c->fc);
3795 }
3796
3797 63 sc->ctts_count = ctts_count;
3798
3799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (pb->eof_reached) {
3800 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
3801 return AVERROR_EOF;
3802 }
3803
3804 63 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
3805
3806 63 return 0;
3807 }
3808
3809 30 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3810 {
3811 AVStream *st;
3812 MOVStreamContext *sc;
3813 uint8_t version;
3814 uint32_t grouping_type;
3815 uint32_t default_length;
3816 av_unused uint32_t default_group_description_index;
3817 uint32_t entry_count;
3818
3819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (c->fc->nb_streams < 1)
3820 return 0;
3821 30 st = c->fc->streams[c->fc->nb_streams - 1];
3822 30 sc = st->priv_data;
3823
3824 30 version = avio_r8(pb); /* version */
3825 30 avio_rb24(pb); /* flags */
3826 30 grouping_type = avio_rl32(pb);
3827
3828 /*
3829 * This function only supports "sync" boxes, but the code is able to parse
3830 * other boxes (such as "tscl", "tsas" and "stsa")
3831 */
3832
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 5 times.
30 if (grouping_type != MKTAG('s','y','n','c'))
3833 25 return 0;
3834
3835
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
3836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
3837 5 entry_count = avio_rb32(pb);
3838
3839 5 av_freep(&sc->sgpd_sync);
3840 5 sc->sgpd_sync_count = entry_count;
3841 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
3842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
3843 return AVERROR(ENOMEM);
3844
3845
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++) {
3846 8 uint32_t description_length = default_length;
3847
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)
3848 description_length = avio_rb32(pb);
3849
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
3850 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
3851 8 sc->sgpd_sync[i] = nal_unit_type;
3852 8 description_length -= 1;
3853 }
3854 8 avio_skip(pb, description_length);
3855 }
3856
3857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
3858 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
3859 return AVERROR_EOF;
3860 }
3861
3862 5 return 0;
3863 }
3864
3865 27 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3866 {
3867 AVStream *st;
3868 MOVStreamContext *sc;
3869 unsigned int i, entries;
3870 uint8_t version;
3871 uint32_t grouping_type;
3872 MOVSbgp *table, **tablep;
3873 int *table_count;
3874
3875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (c->fc->nb_streams < 1)
3876 return 0;
3877 27 st = c->fc->streams[c->fc->nb_streams-1];
3878 27 sc = st->priv_data;
3879
3880 27 version = avio_r8(pb); /* version */
3881 27 avio_rb24(pb); /* flags */
3882 27 grouping_type = avio_rl32(pb);
3883
3884
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 26 times.
27 if (grouping_type == MKTAG('r','a','p',' ')) {
3885 1 tablep = &sc->rap_group;
3886 1 table_count = &sc->rap_group_count;
3887
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 21 times.
26 } else if (grouping_type == MKTAG('s','y','n','c')) {
3888 5 tablep = &sc->sync_group;
3889 5 table_count = &sc->sync_group_count;
3890 } else {
3891 21 return 0;
3892 }
3893
3894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
3895 avio_rb32(pb); /* grouping_type_parameter */
3896
3897 6 entries = avio_rb32(pb);
3898
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
3899 return 0;
3900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
3901 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
3902 6 av_freep(tablep);
3903 6 table = av_malloc_array(entries, sizeof(*table));
3904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
3905 return AVERROR(ENOMEM);
3906 6 *tablep = table;
3907
3908
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++) {
3909 32 table[i].count = avio_rb32(pb); /* sample_count */
3910 32 table[i].index = avio_rb32(pb); /* group_description_index */
3911 }
3912
3913 6 *table_count = i;
3914
3915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
3916 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
3917 return AVERROR_EOF;
3918 }
3919
3920 6 return 0;
3921 }
3922
3923 /**
3924 * Get ith edit list entry (media time, duration).
3925 */
3926 937 static int get_edit_list_entry(MOVContext *mov,
3927 const MOVStreamContext *msc,
3928 unsigned int edit_list_index,
3929 int64_t *edit_list_media_time,
3930 int64_t *edit_list_duration,
3931 int64_t global_timescale)
3932 {
3933
2/2
✓ Branch 0 taken 454 times.
✓ Branch 1 taken 483 times.
937 if (edit_list_index == msc->elst_count) {
3934 454 return 0;
3935 }
3936 483 *edit_list_media_time = msc->elst_data[edit_list_index].time;
3937 483 *edit_list_duration = msc->elst_data[edit_list_index].duration;
3938
3939 /* duration is in global timescale units;convert to msc timescale */
3940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
483 if (global_timescale == 0) {
3941 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
3942 return 0;
3943 }
3944 483 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
3945 global_timescale);
3946
3947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
483 if (*edit_list_duration + (uint64_t)*edit_list_media_time > INT64_MAX)
3948 *edit_list_duration = 0;
3949
3950 483 return 1;
3951 }
3952
3953 /**
3954 * Find the closest previous frame to the timestamp_pts, in e_old index
3955 * entries. Searching for just any frame / just key frames can be controlled by
3956 * last argument 'flag'.
3957 * Note that if ctts_data is not NULL, we will always search for a key frame
3958 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
3959 * return the first frame of the video.
3960 *
3961 * Here the timestamp_pts is considered to be a presentation timestamp and
3962 * the timestamp of index entries are considered to be decoding timestamps.
3963 *
3964 * Returns 0 if successful in finding a frame, else returns -1.
3965 * Places the found index corresponding output arg.
3966 *
3967 * If ctts_old is not NULL, then refines the searched entry by searching
3968 * backwards from the found timestamp, to find the frame with correct PTS.
3969 *
3970 * Places the found ctts_index and ctts_sample in corresponding output args.
3971 */
3972 483 static int find_prev_closest_index(AVStream *st,
3973 AVIndexEntry *e_old,
3974 int nb_old,
3975 MOVTimeToSample *tts_data,
3976 int64_t tts_count,
3977 int64_t timestamp_pts,
3978 int flag,
3979 int64_t* index,
3980 int64_t* tts_index,
3981 int64_t* tts_sample)
3982 {
3983 483 MOVStreamContext *msc = st->priv_data;
3984 483 FFStream *const sti = ffstream(st);
3985 483 AVIndexEntry *e_keep = sti->index_entries;
3986 483 int nb_keep = sti->nb_index_entries;
3987 483 int64_t i = 0;
3988
3989
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
483 av_assert0(index);
3990
3991 // If dts_shift > 0, then all the index timestamps will have to be offset by
3992 // at least dts_shift amount to obtain PTS.
3993 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
3994
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 474 times.
483 if (msc->dts_shift > 0) {
3995 9 timestamp_pts -= msc->dts_shift;
3996 }
3997
3998 483 sti->index_entries = e_old;
3999 483 sti->nb_index_entries = nb_old;
4000 483 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
4001
4002 // Keep going backwards in the index entries until the timestamp is the same.
4003
2/2
✓ Branch 0 taken 482 times.
✓ Branch 1 taken 1 times.
483 if (*index >= 0) {
4004
3/4
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 455 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
482 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
4005 i--) {
4006 if ((flag & AVSEEK_FLAG_ANY) ||
4007 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
4008 *index = i - 1;
4009 }
4010 }
4011 }
4012
4013 // If we have CTTS then refine the search, by searching backwards over PTS
4014 // computed by adding corresponding CTTS durations to index timestamps.
4015
4/4
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 412 times.
✓ Branch 2 taken 70 times.
✓ Branch 3 taken 1 times.
483 if (msc->ctts_count && *index >= 0) {
4016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 av_assert0(tts_index);
4017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 av_assert0(tts_sample);
4018 // Find out the ctts_index for the found frame.
4019 70 *tts_index = 0;
4020 70 *tts_sample = 0;
4021
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 70 times.
284 for (int64_t index_tts_count = 0; index_tts_count < *index; index_tts_count++) {
4022
1/2
✓ Branch 0 taken 214 times.
✗ Branch 1 not taken.
214 if (*tts_index < tts_count) {
4023 214 (*tts_sample)++;
4024
1/2
✓ Branch 0 taken 214 times.
✗ Branch 1 not taken.
214 if (tts_data[*tts_index].count == *tts_sample) {
4025 214 (*tts_index)++;
4026 214 *tts_sample = 0;
4027 }
4028 }
4029 }
4030
4031
4/6
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 80 times.
✗ Branch 5 not taken.
87 while (*index >= 0 && (*tts_index) >= 0 && (*tts_index) < tts_count) {
4032 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
4033 // No need to add dts_shift to the timestamp here because timestamp_pts has already been
4034 // compensated by dts_shift above.
4035
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 12 times.
80 if ((e_old[*index].timestamp + tts_data[*tts_index].offset) <= timestamp_pts &&
4036
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 5 times.
68 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
4037 63 break;
4038 }
4039
4040 17 (*index)--;
4041
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 if (*tts_sample == 0) {
4042 17 (*tts_index)--;
4043
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 7 times.
17 if (*tts_index >= 0)
4044 10 *tts_sample = tts_data[*tts_index].count - 1;
4045 } else {
4046 (*tts_sample)--;
4047 }
4048 }
4049 }
4050
4051 /* restore AVStream state*/
4052 483 sti->index_entries = e_keep;
4053 483 sti->nb_index_entries = nb_keep;
4054
2/2
✓ Branch 0 taken 475 times.
✓ Branch 1 taken 8 times.
483 return *index >= 0 ? 0 : -1;
4055 }
4056
4057 /**
4058 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
4059 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
4060 *
4061 * This function is similar to ff_add_index_entry in libavformat/utils.c
4062 * except that here we are always unconditionally adding an index entry to
4063 * the end, instead of searching the entries list and skipping the add if
4064 * there is an existing entry with the same timestamp.
4065 * This is needed because the mov_fix_index calls this func with the same
4066 * unincremented timestamp for successive discarded frames.
4067 */
4068 350595 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
4069 int size, int distance, int flags)
4070 {
4071 350595 FFStream *const sti = ffstream(st);
4072 AVIndexEntry *entries, *ie;
4073 350595 int64_t index = -1;
4074 350595 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
4075
4076 // Double the allocation each time, to lower memory fragmentation.
4077 // Another difference from ff_add_index_entry function.
4078 350595 const size_t requested_size =
4079 350595 min_size_needed > sti->index_entries_allocated_size ?
4080
2/2
✓ Branch 0 taken 2038 times.
✓ Branch 1 taken 348557 times.
350595 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
4081 min_size_needed;
4082
4083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 350595 times.
350595 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
4084 return -1;
4085
4086 350595 entries = av_fast_realloc(sti->index_entries,
4087 &sti->index_entries_allocated_size,
4088 requested_size);
4089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 350595 times.
350595 if (!entries)
4090 return -1;
4091
4092 350595 sti->index_entries = entries;
4093
4094 350595 index = sti->nb_index_entries++;
4095 350595 ie= &entries[index];
4096
4097 350595 ie->pos = pos;
4098 350595 ie->timestamp = timestamp;
4099 350595 ie->min_distance= distance;
4100 350595 ie->size= size;
4101 350595 ie->flags = flags;
4102 350595 return index;
4103 }
4104
4105 /**
4106 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4107 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4108 */
4109 29 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4110 int64_t* frame_duration_buffer,
4111 int frame_duration_buffer_size) {
4112 29 FFStream *const sti = ffstream(st);
4113 29 int i = 0;
4114
2/4
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 29 times.
29 av_assert0(end_index >= 0 && end_index <= sti->nb_index_entries);
4115
2/2
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 29 times.
191 for (i = 0; i < frame_duration_buffer_size; i++) {
4116 162 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4117 162 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4118 }
4119 29 }
4120
4121 186576 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4122 int count, int offset, unsigned int duration)
4123 {
4124 MOVTimeToSample *tts_buf_new;
4125 186576 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4126 186576 const size_t requested_size =
4127 186576 min_size_needed > *allocated_size ?
4128
2/2
✓ Branch 0 taken 1394 times.
✓ Branch 1 taken 185182 times.
186576 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4129 min_size_needed;
4130
4131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186576 times.
186576 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4132 return -1;
4133
4134 186576 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4135
4136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186576 times.
186576 if (!tts_buf_new)
4137 return -1;
4138
4139 186576 *tts_data = tts_buf_new;
4140
4141 186576 tts_buf_new[*tts_count].count = count;
4142 186576 tts_buf_new[*tts_count].offset = offset;
4143 186576 tts_buf_new[*tts_count].duration = duration;
4144
4145 186576 *tts_count = (*tts_count) + 1;
4146 186576 return 0;
4147 }
4148
4149 #define MAX_REORDER_DELAY 16
4150 641 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4151 {
4152 641 MOVStreamContext *msc = st->priv_data;
4153 641 FFStream *const sti = ffstream(st);
4154 641 int ctts_ind = 0;
4155 641 int ctts_sample = 0;
4156 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4157 641 int buf_start = 0;
4158 int j, r, num_swaps;
4159
4160
2/2
✓ Branch 0 taken 10897 times.
✓ Branch 1 taken 641 times.
11538 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4161 10897 pts_buf[j] = INT64_MIN;
4162
4163
3/4
✓ Branch 0 taken 641 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 578 times.
641 if (st->codecpar->video_delay <= 0 && msc->ctts_count &&
4164
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 19 times.
63 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4165 44 st->codecpar->video_delay = 0;
4166
3/4
✓ Branch 0 taken 138353 times.
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 138353 times.
✗ Branch 3 not taken.
138397 for (int ind = 0; ind < sti->nb_index_entries && ctts_ind < msc->tts_count; ++ind) {
4167 // Point j to the last elem of the buffer and insert the current pts there.
4168 138353 j = buf_start;
4169 138353 buf_start = (buf_start + 1);
4170
2/2
✓ Branch 0 taken 8115 times.
✓ Branch 1 taken 130238 times.
138353 if (buf_start == MAX_REORDER_DELAY + 1)
4171 8115 buf_start = 0;
4172
4173 138353 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4174
4175 // The timestamps that are already in the sorted buffer, and are greater than the
4176 // current pts, are exactly the timestamps that need to be buffered to output PTS
4177 // in correct sorted order.
4178 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4179 // can be computed as the maximum no. of swaps any particular timestamp needs to
4180 // go through, to keep this buffer in sorted order.
4181 138353 num_swaps = 0;
4182
2/2
✓ Branch 0 taken 142584 times.
✓ Branch 1 taken 4 times.
142588 while (j != buf_start) {
4183 142584 r = j - 1;
4184
2/2
✓ Branch 0 taken 8406 times.
✓ Branch 1 taken 134178 times.
142584 if (r < 0) r = MAX_REORDER_DELAY;
4185
2/2
✓ Branch 0 taken 4235 times.
✓ Branch 1 taken 138349 times.
142584 if (pts_buf[j] < pts_buf[r]) {
4186 4235 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4187 4235 ++num_swaps;
4188 } else {
4189 138349 break;
4190 }
4191 4235 j = r;
4192 }
4193 138353 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4194
4195 138353 ctts_sample++;
4196
1/2
✓ Branch 0 taken 138353 times.
✗ Branch 1 not taken.
138353 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4197 138353 ctts_ind++;
4198 138353 ctts_sample = 0;
4199 }
4200 }
4201 44 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4202 44 st->codecpar->video_delay, st->index);
4203 }
4204 641 }
4205
4206 106511 static void mov_current_sample_inc(MOVStreamContext *sc)
4207 {
4208 106511 sc->current_sample++;
4209 106511 sc->current_index++;
4210
2/2
✓ Branch 0 taken 61855 times.
✓ Branch 1 taken 44656 times.
106511 if (sc->index_ranges &&
4211
2/2
✓ Branch 0 taken 438 times.
✓ Branch 1 taken 61417 times.
61855 sc->current_index >= sc->current_index_range->end &&
4212
1/2
✓ Branch 0 taken 438 times.
✗ Branch 1 not taken.
438 sc->current_index_range->end) {
4213 438 sc->current_index_range++;
4214 438 sc->current_index = sc->current_index_range->start;
4215 }
4216 106511 }
4217
4218 static void mov_current_sample_dec(MOVStreamContext *sc)
4219 {
4220 sc->current_sample--;
4221 sc->current_index--;
4222 if (sc->index_ranges &&
4223 sc->current_index < sc->current_index_range->start &&
4224 sc->current_index_range > sc->index_ranges) {
4225 sc->current_index_range--;
4226 sc->current_index = sc->current_index_range->end - 1;
4227 }
4228 }
4229
4230 337 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4231 {
4232 int64_t range_size;
4233
4234 337 sc->current_sample = current_sample;
4235 337 sc->current_index = current_sample;
4236
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 309 times.
337 if (!sc->index_ranges) {
4237 28 return;
4238 }
4239
4240 309 for (sc->current_index_range = sc->index_ranges;
4241
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 sc->current_index_range->end;
4242 sc->current_index_range++) {
4243 309 range_size = sc->current_index_range->end - sc->current_index_range->start;
4244
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 if (range_size > current_sample) {
4245 309 sc->current_index = sc->current_index_range->start + current_sample;
4246 309 break;
4247 }
4248 current_sample -= range_size;
4249 }
4250 }
4251
4252 /**
4253 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4254 * which are needed to decode them) that fall in the edit list time ranges.
4255 * Also fixes the timestamps of the index entries to match the timeline
4256 * specified the edit lists.
4257 */
4258 641 static void mov_fix_index(MOVContext *mov, AVStream *st)
4259 {
4260 641 MOVStreamContext *msc = st->priv_data;
4261 641 FFStream *const sti = ffstream(st);
4262 641 AVIndexEntry *e_old = sti->index_entries;
4263 641 int nb_old = sti->nb_index_entries;
4264 641 const AVIndexEntry *e_old_end = e_old + nb_old;
4265 641 const AVIndexEntry *current = NULL;
4266 641 MOVTimeToSample *tts_data_old = msc->tts_data;
4267 641 int64_t tts_index_old = 0;
4268 641 int64_t tts_sample_old = 0;
4269 641 int64_t tts_count_old = msc->tts_count;
4270 641 int64_t edit_list_media_time = 0;
4271 641 int64_t edit_list_duration = 0;
4272 641 int64_t frame_duration = 0;
4273 641 int64_t edit_list_dts_counter = 0;
4274 641 int64_t edit_list_dts_entry_end = 0;
4275 641 int64_t edit_list_start_tts_sample = 0;
4276 int64_t curr_cts;
4277 641 int64_t curr_ctts = 0;
4278 641 int64_t empty_edits_sum_duration = 0;
4279 641 int64_t edit_list_index = 0;
4280 int64_t index;
4281 int flags;
4282 641 int64_t start_dts = 0;
4283 641 int64_t edit_list_start_encountered = 0;
4284 641 int64_t search_timestamp = 0;
4285 641 int64_t* frame_duration_buffer = NULL;
4286 641 int num_discarded_begin = 0;
4287 641 int first_non_zero_audio_edit = -1;
4288 641 int packet_skip_samples = 0;
4289 641 MOVIndexRange *current_index_range = NULL;
4290 641 int found_keyframe_after_edit = 0;
4291 641 int found_non_empty_edit = 0;
4292
4293
4/6
✓ Branch 0 taken 454 times.
✓ Branch 1 taken 187 times.
✓ Branch 2 taken 454 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 454 times.
641 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
4294 187 return;
4295 }
4296
4297 // allocate the index ranges array
4298 454 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4299 sizeof(msc->index_ranges[0]));
4300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 454 times.
454 if (!msc->index_ranges) {
4301 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4302 return;
4303 }
4304 454 msc->current_index_range = msc->index_ranges;
4305
4306 // Clean AVStream from traces of old index
4307 454 sti->index_entries = NULL;
4308 454 sti->index_entries_allocated_size = 0;
4309 454 sti->nb_index_entries = 0;
4310
4311 // Clean time to sample fields of MOVStreamContext
4312 454 msc->tts_data = NULL;
4313 454 msc->tts_count = 0;
4314 454 msc->tts_index = 0;
4315 454 msc->tts_sample = 0;
4316 454 msc->tts_allocated_size = 0;
4317
4318 // Reinitialize min_corrected_pts so that it can be computed again.
4319 454 msc->min_corrected_pts = -1;
4320
4321 // If the dts_shift is positive (in case of negative ctts values in mov),
4322 // then negate the DTS by dts_shift
4323
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 445 times.
454 if (msc->dts_shift > 0) {
4324 9 edit_list_dts_entry_end -= msc->dts_shift;
4325 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4326 }
4327
4328 454 start_dts = edit_list_dts_entry_end;
4329
4330
2/2
✓ Branch 0 taken 483 times.
✓ Branch 1 taken 454 times.
1391 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
4331 937 &edit_list_duration, mov->time_scale)) {
4332 483 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4333 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4334 483 edit_list_index++;
4335 483 edit_list_dts_counter = edit_list_dts_entry_end;
4336 483 edit_list_dts_entry_end = av_sat_add64(edit_list_dts_entry_end, edit_list_duration);
4337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
483 if (edit_list_dts_entry_end == INT64_MAX) {
4338 av_log(mov->fc, AV_LOG_ERROR, "Cannot calculate dts entry length with duration %"PRId64"\n",
4339 edit_list_duration);
4340 break;
4341 }
4342 483 num_discarded_begin = 0;
4343
4/4
✓ Branch 0 taken 458 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 454 times.
483 if (!found_non_empty_edit && edit_list_media_time == -1) {
4344 4 empty_edits_sum_duration += edit_list_duration;
4345 4 continue;
4346 }
4347 479 found_non_empty_edit = 1;
4348
4349 // If we encounter a non-negative edit list reset the skip_samples/start_pad fields and set them
4350 // according to the edit list below.
4351
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 349 times.
479 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4352
1/2
✓ Branch 0 taken 130 times.
✗ Branch 1 not taken.
130 if (first_non_zero_audio_edit < 0) {
4353 130 first_non_zero_audio_edit = 1;
4354 } else {
4355 first_non_zero_audio_edit = 0;
4356 }
4357
4358
1/2
✓ Branch 0 taken 130 times.
✗ Branch 1 not taken.
130 if (first_non_zero_audio_edit > 0)
4359 130 sti->skip_samples = msc->start_pad = 0;
4360 }
4361
4362 // While reordering frame index according to edit list we must handle properly
4363 // the scenario when edit list entry starts from none key frame.
4364 // We find closest previous key frame and preserve it and consequent frames in index.
4365 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4366 479 search_timestamp = edit_list_media_time;
4367
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 349 times.
479 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4368 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4369 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4370 // edit_list_media_time to cover the decoder delay.
4371 130 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
4372 }
4373
4374
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 475 times.
479 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, 0,
4375 &index, &tts_index_old, &tts_sample_old) < 0) {
4376 4 av_log(mov->fc, AV_LOG_WARNING,
4377 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4378 st->index, edit_list_index, search_timestamp);
4379
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,
4380 &index, &tts_index_old, &tts_sample_old) < 0) {
4381 4 av_log(mov->fc, AV_LOG_WARNING,
4382 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4383 st->index, edit_list_index, search_timestamp);
4384 4 index = 0;
4385 4 tts_index_old = 0;
4386 4 tts_sample_old = 0;
4387 }
4388 }
4389 479 current = e_old + index;
4390 479 edit_list_start_tts_sample = tts_sample_old;
4391
4392 // Iterate over index and arrange it according to edit list
4393 479 edit_list_start_encountered = 0;
4394 479 found_keyframe_after_edit = 0;
4395
2/2
✓ Branch 0 taken 350595 times.
✓ Branch 1 taken 120 times.
350715 for (; current < e_old_end; current++, index++) {
4396 // check if frame outside edit list mark it for discard
4397 701190 frame_duration = (current + 1 < e_old_end) ?
4398
2/2
✓ Branch 0 taken 350145 times.
✓ Branch 1 taken 450 times.
350595 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4399
4400 350595 flags = current->flags;
4401
4402 // frames (pts) before or after edit list
4403 350595 curr_cts = current->timestamp + msc->dts_shift;
4404 350595 curr_ctts = 0;
4405
4406
4/4
✓ Branch 0 taken 186588 times.
✓ Branch 1 taken 164007 times.
✓ Branch 2 taken 186576 times.
✓ Branch 3 taken 12 times.
350595 if (tts_data_old && tts_index_old < tts_count_old) {
4407 186576 curr_ctts = tts_data_old[tts_index_old].offset;
4408 186576 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4409 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4410 186576 curr_cts += curr_ctts;
4411 186576 tts_sample_old++;
4412
1/2
✓ Branch 0 taken 186576 times.
✗ Branch 1 not taken.
186576 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186576 times.
186576 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4414 &msc->tts_allocated_size,
4415 186576 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4416 186576 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4417 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4418 tts_index_old,
4419 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4420 tts_data_old[tts_index_old].offset);
4421 break;
4422 }
4423 186576 tts_index_old++;
4424 186576 tts_sample_old = 0;
4425 186576 edit_list_start_tts_sample = 0;
4426 }
4427 }
4428
4429
4/4
✓ Branch 0 taken 350417 times.
✓ Branch 1 taken 178 times.
✓ Branch 2 taken 157 times.
✓ Branch 3 taken 350260 times.
350595 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
4430
4/4
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 256 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 46 times.
335 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
4431
4/6
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 21 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
33 curr_cts < edit_list_media_time && curr_cts + frame_duration > edit_list_media_time &&
4432 first_non_zero_audio_edit > 0) {
4433 12 packet_skip_samples = edit_list_media_time - curr_cts;
4434 12 sti->skip_samples += packet_skip_samples;
4435
4436 // Shift the index entry timestamp by packet_skip_samples to be correct.
4437 12 edit_list_dts_counter -= packet_skip_samples;
4438
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (edit_list_start_encountered == 0) {
4439 12 edit_list_start_encountered = 1;
4440 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4441 // discarded packets.
4442
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 if (frame_duration_buffer) {
4443 7 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4444 frame_duration_buffer, num_discarded_begin);
4445 7 av_freep(&frame_duration_buffer);
4446 }
4447 }
4448
4449 12 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4450 } else {
4451 323 flags |= AVINDEX_DISCARD_FRAME;
4452 323 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4453
4454
2/2
✓ Branch 0 taken 164 times.
✓ Branch 1 taken 159 times.
323 if (edit_list_start_encountered == 0) {
4455 164 num_discarded_begin++;
4456 164 frame_duration_buffer = av_realloc(frame_duration_buffer,
4457 num_discarded_begin * sizeof(int64_t));
4458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 164 times.
164 if (!frame_duration_buffer) {
4459 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4460 break;
4461 }
4462 164 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4463
4464 // Increment skip_samples for the first non-zero audio edit list
4465
3/4
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 97 times.
✓ Branch 2 taken 67 times.
✗ Branch 3 not taken.
164 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4466
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 46 times.
67 first_non_zero_audio_edit > 0 && st->codecpar->codec_id != AV_CODEC_ID_VORBIS) {
4467 21 sti->skip_samples += frame_duration;
4468 }
4469 }
4470 }
4471 } else {
4472
2/2
✓ Branch 0 taken 453 times.
✓ Branch 1 taken 349807 times.
350260 if (msc->min_corrected_pts < 0) {
4473 453 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4474 } else {
4475 349807 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4476 }
4477
2/2
✓ Branch 0 taken 465 times.
✓ Branch 1 taken 349795 times.
350260 if (edit_list_start_encountered == 0) {
4478 465 edit_list_start_encountered = 1;
4479 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4480 // discarded packets.
4481
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 443 times.
465 if (frame_duration_buffer) {
4482 22 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4483 frame_duration_buffer, num_discarded_begin);
4484 22 av_freep(&frame_duration_buffer);
4485 }
4486 }
4487 }
4488
4489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 350595 times.
350595 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
4490 350595 current->min_distance, flags) == -1) {
4491 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4492 break;
4493 }
4494
4495 // Update the index ranges array
4496
4/4
✓ Branch 0 taken 350141 times.
✓ Branch 1 taken 454 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 350118 times.
350595 if (!current_index_range || index != current_index_range->end) {
4497 477 current_index_range = current_index_range ? current_index_range + 1
4498
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 454 times.
477 : msc->index_ranges;
4499 477 current_index_range->start = index;
4500 }
4501 350595 current_index_range->end = index + 1;
4502
4503 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4504
2/2
✓ Branch 0 taken 350431 times.
✓ Branch 1 taken 164 times.
350595 if (edit_list_start_encountered > 0) {
4505 350431 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4506 }
4507
4508 // Break when found first key frame after edit entry completion
4509
2/2
✓ Branch 0 taken 663 times.
✓ Branch 1 taken 349932 times.
350595 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
4510
3/4
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 373 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 290 times.
663 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
4511
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 348 times.
373 if (msc->ctts_count) {
4512 // If we have CTTS and this is the first keyframe after edit elist,
4513 // wait for one more, because there might be trailing B-frames after this I-frame
4514 // that do belong to the edit.
4515
3/4
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 11 times.
25 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO && found_keyframe_after_edit == 0) {
4516 14 found_keyframe_after_edit = 1;
4517 14 continue;
4518 }
4519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (tts_sample_old != 0) {
4520 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4521 &msc->tts_allocated_size,
4522 tts_sample_old - edit_list_start_tts_sample,
4523 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4524 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4525 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4526 tts_data_old[tts_index_old].offset);
4527 break;
4528 }
4529 }
4530 }
4531 359 break;
4532 }
4533 }
4534 }
4535 // If there are empty edits, then msc->min_corrected_pts might be positive
4536 // intentionally. So we subtract the sum duration of empty edits here.
4537 454 msc->min_corrected_pts -= empty_edits_sum_duration;
4538
4539 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4540 // dts by that amount to make the first pts zero.
4541
2/2
✓ Branch 0 taken 282 times.
✓ Branch 1 taken 172 times.
454 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4542
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 237 times.
282 if (msc->min_corrected_pts > 0) {
4543 45 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4544
2/2
✓ Branch 0 taken 3113 times.
✓ Branch 1 taken 45 times.
3158 for (int i = 0; i < sti->nb_index_entries; ++i)
4545 3113 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4546 }
4547 }
4548 // Start time should be equal to zero or the duration of any empty edits.
4549 454 st->start_time = empty_edits_sum_duration;
4550
4551 // Update av stream length, if it ends up shorter than the track's media duration
4552 454 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4553 454 msc->start_pad = sti->skip_samples;
4554
4555 // Free the old index and the old CTTS structures
4556 454 av_free(e_old);
4557 454 av_free(tts_data_old);
4558 454 av_freep(&frame_duration_buffer);
4559
4560 // Null terminate the index ranges array
4561 454 current_index_range = current_index_range ? current_index_range + 1
4562
1/2
✓ Branch 0 taken 454 times.
✗ Branch 1 not taken.
454 : msc->index_ranges;
4563 454 current_index_range->start = 0;
4564 454 current_index_range->end = 0;
4565 454 msc->current_index = msc->index_ranges[0].start;
4566 }
4567
4568 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4569 {
4570
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4571
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == nal_unit_type)
4572 5 return i + 1;
4573 return 0;
4574 }
4575
4576 670 static int build_open_gop_key_points(AVStream *st)
4577 {
4578 int k;
4579 670 int sample_id = 0;
4580 uint32_t cra_index;
4581 670 MOVStreamContext *sc = st->priv_data;
4582
4583
4/4
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 613 times.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 5 times.
670 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count)
4584 665 return 0;
4585
4586 /* Build an unrolled index of the samples */
4587 5 sc->sample_offsets_count = 0;
4588
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4590 return AVERROR(ENOMEM);
4591 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4592 }
4593 5 av_freep(&sc->sample_offsets);
4594 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4596 return AVERROR(ENOMEM);
4597 5 k = 0;
4598
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4599
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4600 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4601
4602 /* The following HEVC NAL type reveal the use of open GOP sync points
4603 * (TODO: BLA types may also be concerned) */
4604 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4606 return 0;
4607
4608 /* Build a list of open-GOP key samples */
4609 5 sc->open_key_samples_count = 0;
4610
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4611
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4612
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)
4613 return AVERROR(ENOMEM);
4614 11 sc->open_key_samples_count += sc->sync_group[i].count;
4615 }
4616 5 av_freep(&sc->open_key_samples);
4617 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4619 return AVERROR(ENOMEM);
4620 5 k = 0;
4621
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4622 28 const MOVSbgp *sg = &sc->sync_group[i];
4623
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4624
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4625 11 sc->open_key_samples[k++] = sample_id;
4626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4627 return AVERROR_PATCHWELCOME;
4628 28 sample_id += sg->count;
4629 }
4630
4631 /* Identify the minimal time step between samples */
4632 5 sc->min_sample_duration = UINT_MAX;
4633
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4634 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4635
4636 5 return 0;
4637 }
4638
4639 #define MOV_MERGE_CTTS 1
4640 #define MOV_MERGE_STTS 2
4641 /*
4642 * Merge stts and ctts arrays into a new combined array.
4643 * stts_count and ctts_count may be left untouched as they will be
4644 * used to check for the presence of either of them.
4645 */
4646 641 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4647 {
4648 641 MOVStreamContext *sc = st->priv_data;
4649
3/4
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 578 times.
✓ Branch 2 taken 63 times.
✗ Branch 3 not taken.
641 int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS);
4650
3/4
✓ Branch 0 taken 641 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 575 times.
✓ Branch 3 taken 66 times.
641 int stts = sc->stts_data && (flags & MOV_MERGE_STTS);
4651 641 int idx = 0;
4652
4653
3/4
✓ Branch 0 taken 578 times.
✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 578 times.
641 if (!sc->ctts_data && !sc->stts_data)
4654 return 0;
4655 // Expand time to sample entries such that we have a 1-1 mapping with samples
4656
2/4
✓ Branch 0 taken 641 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 641 times.
641 if (!sc->sample_count || sc->sample_count >= UINT_MAX / sizeof(*sc->tts_data))
4657 return -1;
4658
4659
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 578 times.
641 if (ctts) {
4660 126 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4661 63 sc->sample_count * sizeof(*sc->tts_data));
4662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (!sc->tts_data)
4663 return -1;
4664
4665 63 memset(sc->tts_data, 0, sc->tts_allocated_size);
4666
4667
2/2
✓ Branch 0 taken 5131 times.
✓ Branch 1 taken 63 times.
5194 for (int i = 0; i < sc->ctts_count &&
4668
1/2
✓ Branch 0 taken 5131 times.
✗ Branch 1 not taken.
10262 idx < sc->sample_count; i++)
4669
2/2
✓ Branch 0 taken 139275 times.
✓ Branch 1 taken 5131 times.
144406 for (int j = 0; j < sc->ctts_data[i].count &&
4670
1/2
✓ Branch 0 taken 139275 times.
✗ Branch 1 not taken.
139275 idx < sc->sample_count; j++) {
4671 139275 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4672 139275 sc->tts_data[idx++].count = 1;
4673 }
4674
4675 63 sc->tts_count = idx;
4676 } else
4677 578 sc->ctts_count = 0;
4678 641 av_freep(&sc->ctts_data);
4679 641 sc->ctts_allocated_size = 0;
4680
4681 641 idx = 0;
4682
2/2
✓ Branch 0 taken 575 times.
✓ Branch 1 taken 66 times.
641 if (stts) {
4683 575 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4684 575 sc->sample_count * sizeof(*sc->tts_data));
4685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 if (!tts_data)
4686 return -1;
4687
4688
2/2
✓ Branch 0 taken 512 times.
✓ Branch 1 taken 63 times.
575 if (!sc->tts_data)
4689 512 memset(tts_data, 0, sc->tts_allocated_size);
4690 575 sc->tts_data = tts_data;
4691
4692
2/2
✓ Branch 0 taken 2968 times.
✓ Branch 1 taken 575 times.
3543 for (int i = 0; i < sc->stts_count &&
4693
1/2
✓ Branch 0 taken 2968 times.
✗ Branch 1 not taken.
5936 idx < sc->sample_count; i++)
4694
2/2
✓ Branch 0 taken 236773 times.
✓ Branch 1 taken 2968 times.
239741 for (int j = 0; j < sc->stts_data[i].count &&
4695
1/2
✓ Branch 0 taken 236773 times.
✗ Branch 1 not taken.
236773 idx < sc->sample_count; j++) {
4696 236773 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4697 236773 sc->tts_data[idx++].count = 1;
4698 }
4699
4700 575 sc->tts_count = FFMAX(sc->tts_count, idx);
4701 } else
4702 66 sc->stts_count = 0;
4703 641 av_freep(&sc->stts_data);
4704 641 sc->stts_allocated_size = 0;
4705
4706 641 return 0;
4707 }
4708
4709 670 static void mov_build_index(MOVContext *mov, AVStream *st)
4710 {
4711 670 MOVStreamContext *sc = st->priv_data;
4712 670 FFStream *const sti = ffstream(st);
4713 int64_t current_offset;
4714 670 int64_t current_dts = 0;
4715 670 unsigned int stts_index = 0;
4716 670 unsigned int stsc_index = 0;
4717 670 unsigned int stss_index = 0;
4718 670 unsigned int stps_index = 0;
4719 unsigned int i, j;
4720 670 uint64_t stream_size = 0;
4721
4722 670 int ret = build_open_gop_key_points(st);
4723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 670 times.
670 if (ret < 0)
4724 return;
4725
4726
2/2
✓ Branch 0 taken 457 times.
✓ Branch 1 taken 213 times.
670 if (sc->elst_count) {
4727 457 int i, edit_start_index = 0, multiple_edits = 0;
4728 457 int64_t empty_duration = 0; // empty duration of the first edit list entry
4729 457 int64_t start_time = 0; // start time of the media
4730
4731
2/2
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 457 times.
943 for (i = 0; i < sc->elst_count; i++) {
4732 486 const MOVElst *e = &sc->elst_data[i];
4733
4/4
✓ Branch 0 taken 457 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 453 times.
486 if (i == 0 && e->time == -1) {
4734 /* if empty, the first entry is the start time of the stream
4735 * relative to the presentation itself */
4736 4 empty_duration = e->duration;
4737 4 edit_start_index = 1;
4738
3/4
✓ Branch 0 taken 457 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 457 times.
✗ Branch 3 not taken.
482 } else if (i == edit_start_index && e->time >= 0) {
4739 457 start_time = e->time;
4740 } else {
4741 25 multiple_edits = 1;
4742 }
4743 }
4744
4745
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 450 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
457 if (multiple_edits && !mov->advanced_editlist) {
4746 if (mov->advanced_editlist_autodisabled)
4747 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4748 "not supported in fragmented MP4 files\n");
4749 else
4750 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4751 "Use -advanced_editlist to correctly decode otherwise "
4752 "a/v desync might occur\n");
4753 }
4754
4755 /* adjust first dts according to edit list */
4756
5/6
✓ Branch 0 taken 453 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 75 times.
✓ Branch 3 taken 378 times.
✓ Branch 4 taken 79 times.
✗ Branch 5 not taken.
457 if ((empty_duration || start_time) && mov->time_scale > 0) {
4757
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 75 times.
79 if (empty_duration)
4758 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
4759
4760
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
79 if (av_sat_sub64(start_time, empty_duration) != start_time - (uint64_t)empty_duration)
4761 av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
4762
4763 79 sc->time_offset = start_time - (uint64_t)empty_duration;
4764 79 sc->min_corrected_pts = start_time;
4765
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 78 times.
79 if (!mov->advanced_editlist)
4766 1 current_dts = -sc->time_offset;
4767 }
4768
4769
4/4
✓ Branch 0 taken 450 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 447 times.
457 if (!multiple_edits && !mov->advanced_editlist &&
4770
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
3 st->codecpar->codec_id == AV_CODEC_ID_AAC && start_time > 0)
4771 sc->start_pad = av_rescale_q(start_time, st->time_base,
4772 (AVRational){1, st->codecpar->sample_rate});
4773 }
4774
4775 /* only use old uncompressed audio chunk demuxing when stts specifies it */
4776
2/2
✓ Branch 0 taken 247 times.
✓ Branch 1 taken 423 times.
670 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4777
5/6
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 59 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 122 times.
✓ Branch 5 taken 66 times.
822 sc->stts_count == 1 && sc->stts_data && sc->stts_data[0].duration == 1)) {
4778 604 unsigned int current_sample = 0;
4779 604 unsigned int stts_sample = 0;
4780 unsigned int sample_size;
4781 604 unsigned int distance = 0;
4782 604 unsigned int rap_group_index = 0;
4783 604 unsigned int rap_group_sample = 0;
4784
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 603 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
604 int rap_group_present = sc->rap_group_count && sc->rap_group;
4785
4/8
✓ Branch 0 taken 148 times.
✓ Branch 1 taken 456 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 148 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 456 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
604 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
4786
4787 604 current_dts -= sc->dts_shift;
4788
4789
4/6
✓ Branch 0 taken 575 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 575 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 575 times.
604 if (!sc->sample_count || sti->nb_index_entries || sc->tts_count)
4790 29 return;
4791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 if (sc->sample_count >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4792 return;
4793
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 if (av_reallocp_array(&sti->index_entries,
4794 575 sti->nb_index_entries + sc->sample_count,
4795 sizeof(*sti->index_entries)) < 0) {
4796 sti->nb_index_entries = 0;
4797 return;
4798 }
4799 575 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
4800
4801 575 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
4802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 if (ret < 0)
4803 return;
4804
4805
2/2
✓ Branch 0 taken 174325 times.
✓ Branch 1 taken 575 times.
174900 for (i = 0; i < sc->chunk_count; i++) {
4806
2/2
✓ Branch 0 taken 173750 times.
✓ Branch 1 taken 575 times.
174325 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
4807 174325 current_offset = sc->chunk_offsets[i];
4808
2/2
✓ Branch 1 taken 8947 times.
✓ Branch 2 taken 167947 times.
176894 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4809
2/2
✓ Branch 0 taken 2569 times.
✓ Branch 1 taken 6378 times.
8947 i + 1 == sc->stsc_data[stsc_index + 1].first)
4810 2569 stsc_index++;
4811
4812
4/6
✓ Branch 0 taken 174325 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7396 times.
✓ Branch 3 taken 166929 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7396 times.
174325 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
4813 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
4814 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
4815 sc->stsz_sample_size = sc->sample_size;
4816 }
4817
3/4
✓ Branch 0 taken 7396 times.
✓ Branch 1 taken 166929 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7396 times.
174325 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
4818 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
4819 sc->stsz_sample_size = sc->sample_size;
4820 }
4821
4822
2/2
✓ Branch 0 taken 236773 times.
✓ Branch 1 taken 174325 times.
411098 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
4823 236773 int keyframe = 0;
4824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 236773 times.
236773 if (current_sample >= sc->sample_count) {
4825 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
4826 return;
4827 }
4828
4829
6/6
✓ Branch 0 taken 232017 times.
✓ Branch 1 taken 4756 times.
✓ Branch 2 taken 153071 times.
✓ Branch 3 taken 78946 times.
✓ Branch 4 taken 5732 times.
✓ Branch 5 taken 147339 times.
236773 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
4830 84678 keyframe = 1;
4831
2/2
✓ Branch 0 taken 5584 times.
✓ Branch 1 taken 79094 times.
84678 if (stss_index + 1 < sc->keyframe_count)
4832 5584 stss_index++;
4833
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 152095 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
152095 } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
4834 keyframe = 1;
4835 if (stps_index + 1 < sc->stps_count)
4836 stps_index++;
4837 }
4838
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 236585 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
236773 if (rap_group_present && rap_group_index < sc->rap_group_count) {
4839
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
4840 2 keyframe = 1;
4841
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
4842 4 rap_group_sample = 0;
4843 4 rap_group_index++;
4844 }
4845 }
4846
2/2
✓ Branch 0 taken 4756 times.
✓ Branch 1 taken 232017 times.
236773 if (sc->keyframe_absent
4847
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !sc->stps_count
4848
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !rap_group_present
4849
6/6
✓ Branch 0 taken 874 times.
✓ Branch 1 taken 3882 times.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 824 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 48 times.
4756 && (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || (i==0 && j==0)))
4850 3884 keyframe = 1;
4851
2/2
✓ Branch 0 taken 88562 times.
✓ Branch 1 taken 148211 times.
236773 if (keyframe)
4852 88562 distance = 0;
4853
2/2
✓ Branch 0 taken 9036 times.
✓ Branch 1 taken 227737 times.
236773 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
4854
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 236773 times.
236773 if (current_offset > INT64_MAX - sample_size) {
4855 av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
4856 current_offset,
4857 sample_size);
4858 return;
4859 }
4860
4861
2/2
✓ Branch 0 taken 236684 times.
✓ Branch 1 taken 89 times.
236773 if (sc->pseudo_stream_id == -1 ||
4862
1/2
✓ Branch 0 taken 236684 times.
✗ Branch 1 not taken.
236684 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
4863 AVIndexEntry *e;
4864
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 236773 times.
236773 if (sample_size > 0x3FFFFFFF) {
4865 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
4866 return;
4867 }
4868 236773 e = &sti->index_entries[sti->nb_index_entries++];
4869 236773 e->pos = current_offset;
4870 236773 e->timestamp = current_dts;
4871 236773 e->size = sample_size;
4872 236773 e->min_distance = distance;
4873 236773 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
4874 236773 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
4875 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
4876 current_offset, current_dts, sample_size, distance, keyframe);
4877
4/4
✓ Branch 0 taken 155449 times.
✓ Branch 1 taken 81324 times.
✓ Branch 2 taken 10816 times.
✓ Branch 3 taken 144633 times.
236773 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries < 100)
4878 10816 ff_rfps_add_frame(mov->fc, st, current_dts);
4879 }
4880
4881 236773 current_offset += sample_size;
4882 236773 stream_size += sample_size;
4883
4884 236773 current_dts += sc->tts_data[stts_index].duration;
4885
4886 236773 distance++;
4887 236773 stts_sample++;
4888 236773 current_sample++;
4889
3/4
✓ Branch 0 taken 236198 times.
✓ Branch 1 taken 575 times.
✓ Branch 2 taken 236198 times.
✗ Branch 3 not taken.
236773 if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) {
4890 236198 stts_sample = 0;
4891 236198 stts_index++;
4892 }
4893 }
4894 }
4895
2/2
✓ Branch 0 taken 532 times.
✓ Branch 1 taken 43 times.
575 if (st->duration > 0)
4896 532 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
4897 } else {
4898 66 unsigned chunk_samples, total = 0;
4899
4900
2/4
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 66 times.
66 if (!sc->chunk_count || sc->tts_count)
4901 return;
4902
4903 // compute total chunk count
4904
2/2
✓ Branch 0 taken 723 times.
✓ Branch 1 taken 66 times.
789 for (i = 0; i < sc->stsc_count; i++) {
4905 unsigned count, chunk_count;
4906
4907 723 chunk_samples = sc->stsc_data[i].count;
4908
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 66 times.
723 if (i != sc->stsc_count - 1 &&
4909
3/4
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 594 times.
657 sc->samples_per_frame && chunk_samples % sc->samples_per_frame) {
4910 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
4911 return;
4912 }
4913
4914
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 648 times.
723 if (sc->samples_per_frame >= 160) { // gsm
4915 75 count = chunk_samples / sc->samples_per_frame;
4916
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 117 times.
648 } else if (sc->samples_per_frame > 1) {
4917 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
4918 531 count = (chunk_samples+samples-1) / samples;
4919 } else {
4920 117 count = (chunk_samples+1023) / 1024;
4921 }
4922
4923
2/2
✓ Branch 1 taken 657 times.
✓ Branch 2 taken 66 times.
723 if (mov_stsc_index_valid(i, sc->stsc_count))
4924 657 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
4925 else
4926 66 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
4927 723 total += chunk_count * count;
4928 }
4929
4930 66 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
4931
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4932 return;
4933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (av_reallocp_array(&sti->index_entries,
4934 66 sti->nb_index_entries + total,
4935 sizeof(*sti->index_entries)) < 0) {
4936 sti->nb_index_entries = 0;
4937 return;
4938 }
4939 66 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
4940
4941 // populate index
4942
2/2
✓ Branch 0 taken 5458 times.
✓ Branch 1 taken 66 times.
5524 for (i = 0; i < sc->chunk_count; i++) {
4943 5458 current_offset = sc->chunk_offsets[i];
4944
2/2
✓ Branch 1 taken 5317 times.
✓ Branch 2 taken 141 times.
5458 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4945
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 4660 times.
5317 i + 1 == sc->stsc_data[stsc_index + 1].first)
4946 657 stsc_index++;
4947 5458 chunk_samples = sc->stsc_data[stsc_index].count;
4948
4949
2/2
✓ Branch 0 taken 164052 times.
✓ Branch 1 taken 5458 times.
169510 while (chunk_samples > 0) {
4950 AVIndexEntry *e;
4951 unsigned size, samples;
4952
4953
3/4
✓ Branch 0 taken 23921 times.
✓ Branch 1 taken 140131 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 23921 times.
164052 if (sc->samples_per_frame > 1 && !sc->bytes_per_frame) {
4954 avpriv_request_sample(mov->fc,
4955 "Zero bytes per frame, but %d samples per frame",
4956 sc->samples_per_frame);
4957 return;
4958 }
4959
4960
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 149694 times.
164052 if (sc->samples_per_frame >= 160) { // gsm
4961 14358 samples = sc->samples_per_frame;
4962 14358 size = sc->bytes_per_frame;
4963 } else {
4964
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 140131 times.
149694 if (sc->samples_per_frame > 1) {
4965 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
4966 sc->samples_per_frame, chunk_samples);
4967 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
4968 } else {
4969 140131 samples = FFMIN(1024, chunk_samples);
4970 140131 size = samples * sc->sample_size;
4971 }
4972 }
4973
4974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 164052 times.
164052 if (sti->nb_index_entries >= total) {
4975 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
4976 return;
4977 }
4978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 164052 times.
164052 if (size > 0x3FFFFFFF) {
4979 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
4980 return;
4981 }
4982 164052 e = &sti->index_entries[sti->nb_index_entries++];
4983 164052 e->pos = current_offset;
4984 164052 e->timestamp = current_dts;
4985 164052 e->size = size;
4986 164052 e->min_distance = 0;
4987 164052 e->flags = AVINDEX_KEYFRAME;
4988 164052 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
4989 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
4990 size, samples);
4991
4992 164052 current_offset += size;
4993 164052 current_dts += samples;
4994 164052 chunk_samples -= samples;
4995 }
4996 }
4997
4998 66 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
4999
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
5000 return;
5001 }
5002
5003
2/4
✓ Branch 0 taken 641 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 641 times.
✗ Branch 3 not taken.
641 if (!mov->ignore_editlist && mov->advanced_editlist) {
5004 // Fix index according to edit lists.
5005 641 mov_fix_index(mov, st);
5006 }
5007
5008 // Update start time of the stream.
5009
5/6
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 454 times.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 118 times.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
641 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) {
5010 69 st->start_time = sti->index_entries[0].timestamp + sc->dts_shift;
5011
1/2
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
69 if (sc->tts_data) {
5012 69 st->start_time += sc->tts_data[0].offset;
5013 }
5014 }
5015
5016 641 mov_estimate_video_delay(mov, st);
5017 }
5018
5019 static int test_same_origin(const char *src, const char *ref) {
5020 char src_proto[64];
5021 char ref_proto[64];
5022 char src_auth[256];
5023 char ref_auth[256];
5024 char src_host[256];
5025 char ref_host[256];
5026 int src_port=-1;
5027 int ref_port=-1;
5028
5029 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
5030 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
5031
5032 if (strlen(src) == 0) {
5033 return -1;
5034 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
5035 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
5036 strlen(src_host) + 1 >= sizeof(src_host) ||
5037 strlen(ref_host) + 1 >= sizeof(ref_host)) {
5038 return 0;
5039 } else if (strcmp(src_proto, ref_proto) ||
5040 strcmp(src_auth, ref_auth) ||
5041 strcmp(src_host, ref_host) ||
5042 src_port != ref_port) {
5043 return 0;
5044 } else
5045 return 1;
5046 }
5047
5048 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
5049 {
5050 /* try relative path, we do not try the absolute because it can leak information about our
5051 system to an attacker */
5052 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
5053 char filename[1025];
5054 const char *src_path;
5055 int i, l;
5056
5057 /* find a source dir */
5058 src_path = strrchr(src, '/');
5059 if (src_path)
5060 src_path++;
5061 else
5062 src_path = src;
5063
5064 /* find a next level down to target */
5065 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
5066 if (ref->path[l] == '/') {
5067 if (i == ref->nlvl_to - 1)
5068 break;
5069 else
5070 i++;
5071 }
5072
5073 /* compose filename if next level down to target was found */
5074 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
5075 memcpy(filename, src, src_path - src);
5076 filename[src_path - src] = 0;
5077
5078 for (i = 1; i < ref->nlvl_from; i++)
5079 av_strlcat(filename, "../", sizeof(filename));
5080
5081 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
5082 if (!c->use_absolute_path) {
5083 int same_origin = test_same_origin(src, filename);
5084
5085 if (!same_origin) {
5086 av_log(c->fc, AV_LOG_ERROR,
5087 "Reference with mismatching origin, %s not tried for security reasons, "
5088 "set demuxer option use_absolute_path to allow it anyway\n",
5089 ref->path);
5090 return AVERROR(ENOENT);
5091 }
5092
5093 if (strstr(ref->path + l + 1, "..") ||
5094 strstr(ref->path + l + 1, ":") ||
5095 (ref->nlvl_from > 1 && same_origin < 0) ||
5096 (filename[0] == '/' && src_path == src))
5097 return AVERROR(ENOENT);
5098 }
5099
5100 if (strlen(filename) + 1 == sizeof(filename))
5101 return AVERROR(ENOENT);
5102 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5103 return 0;
5104 }
5105 } else if (c->use_absolute_path) {
5106 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5107 "this is a possible security issue\n");
5108 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5109 return 0;
5110 } else {
5111 av_log(c->fc, AV_LOG_ERROR,
5112 "Absolute path %s not tried for security reasons, "
5113 "set demuxer option use_absolute_path to allow absolute paths\n",
5114 ref->path);
5115 }
5116
5117 return AVERROR(ENOENT);
5118 }
5119
5120 1363 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5121 {
5122
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1349 times.
1363 if (sc->time_scale <= 0) {
5123 14 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5124 14 sc->time_scale = c->time_scale;
5125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (sc->time_scale <= 0)
5126 sc->time_scale = 1;
5127 }
5128 1363 }
5129
5130 #if CONFIG_IAMFDEC
5131 12 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5132 {
5133 12 const MOVStreamContext *sc = st->priv_data;
5134 12 const IAMFContext *iamf = &sc->iamf->iamf;
5135
5136
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5137 12 const AVStreamGroup *stg = NULL;
5138
5139
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5140
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)
5141 12 stg = c->fc->stream_groups[j];
5142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 av_assert0(stg);
5143
5144
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_streams; j++) {
5145 64 const FFStream *sti = cffstream(st);
5146 64 AVStream *out = stg->streams[j];
5147 64 FFStream *out_sti = ffstream(stg->streams[j]);
5148
5149 64 out->codecpar->bit_rate = 0;
5150
5151
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 52 times.
64 if (out == st)
5152 12 continue;
5153
5154 52 out->time_base = st->time_base;
5155 52 out->start_time = st->start_time;
5156 52 out->duration = st->duration;
5157 52 out->nb_frames = st->nb_frames;
5158 52 out->discard = st->discard;
5159
5160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 av_assert0(!out_sti->index_entries);
5161 52 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (!out_sti->index_entries)
5163 return AVERROR(ENOMEM);
5164
5165 52 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5166 52 out_sti->nb_index_entries = sti->nb_index_entries;
5167 52 out_sti->skip_samples = sti->skip_samples;
5168 52 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5169 }
5170 }
5171
5172 12 return 0;
5173 }
5174 #endif
5175
5176 670 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5177 {
5178
4/6
✓ Branch 0 taken 641 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 641 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 641 times.
✗ Branch 5 not taken.
670 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5179
3/4
✓ Branch 0 taken 395 times.
✓ Branch 1 taken 246 times.
✓ Branch 2 taken 395 times.
✗ Branch 3 not taken.
641 (!sc->sample_size && !sc->sample_count))) ||
5180
3/4
✓ Branch 0 taken 641 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 641 times.
✗ Branch 3 not taken.
670 (sc->sample_count && (!sc->chunk_count ||
5181
3/4
✓ Branch 0 taken 395 times.
✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 395 times.
641 (!sc->sample_size && !sc->sample_sizes)))) {
5182 av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5183 index);
5184 return 1;
5185 }
5186
5187
3/4
✓ Branch 0 taken 641 times.
✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 641 times.
670 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
5188 av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5189 index);
5190 return 2;
5191 }
5192 670 return 0;
5193 }
5194
5195 627 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5196 {
5197 AVStream *st;
5198 MOVStreamContext *sc;
5199 int ret;
5200
5201 627 st = avformat_new_stream(c->fc, NULL);
5202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (!st) return AVERROR(ENOMEM);
5203 627 st->id = -1;
5204 627 sc = av_mallocz(sizeof(MOVStreamContext));
5205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (!sc) return AVERROR(ENOMEM);
5206
5207 627 st->priv_data = sc;
5208 627 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5209 627 sc->ffindex = st->index;
5210 627 c->trak_index = st->index;
5211 627 sc->tref_flags = 0;
5212 627 sc->tref_id = -1;
5213 627 sc->refcount = 1;
5214
5215
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 627 times.
627 if ((ret = mov_read_default(c, pb, atom)) < 0)
5216 return ret;
5217
5218 627 c->trak_index = -1;
5219
5220 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5221 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5222
5/6
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 598 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 28 times.
627 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
5223 1 sc->stsc_count = 0;
5224 1 av_freep(&sc->stsc_data);
5225 }
5226
5227 627 ret = sanity_checks(c->fc, sc, st->index);
5228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (ret)
5229 return ret > 1 ? AVERROR_INVALIDDATA : 0;
5230
5231 627 fix_timescale(c, sc);
5232
5233 627 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5234
5235 /*
5236 * Advanced edit list support does not work with fragemented MP4s, which
5237 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5238 * In these files, trun atoms may be streamed in.
5239 */
5240
4/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 598 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 9 times.
627 if (!sc->stts_count && c->advanced_editlist) {
5241
5242 20 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5243 "MP4. disabling.\n");
5244 20 c->advanced_editlist = 0;
5245 20 c->advanced_editlist_autodisabled = 1;
5246 }
5247
5248 627 mov_build_index(c, st);
5249
5250 #if CONFIG_IAMFDEC
5251
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 615 times.
627 if (sc->iamf) {
5252 12 ret = mov_update_iamf_streams(c, st);
5253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
5254 return ret;
5255 }
5256 #endif
5257
5258
3/4
✓ Branch 0 taken 626 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 626 times.
627 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
5259 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5260 if (c->enable_drefs) {
5261 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5262 av_log(c->fc, AV_LOG_ERROR,
5263 "stream %d, error opening alias: path='%s', dir='%s', "
5264 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5265 st->index, dref->path, dref->dir, dref->filename,
5266 dref->volume, dref->nlvl_from, dref->nlvl_to);
5267 } else {
5268 av_log(c->fc, AV_LOG_WARNING,
5269 "Skipped opening external track: "
5270 "stream %d, alias: path='%s', dir='%s', "
5271 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5272 "Set enable_drefs to allow this.\n",
5273 st->index, dref->path, dref->dir, dref->filename,
5274 dref->volume, dref->nlvl_from, dref->nlvl_to);
5275 }
5276 } else {
5277 627 sc->pb = c->fc->pb;
5278 627 sc->pb_is_copied = 1;
5279 }
5280
5281
2/2
✓ Branch 0 taken 325 times.
✓ Branch 1 taken 302 times.
627 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5282
3/4
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 308 times.
✗ Branch 3 not taken.
325 int stts_constant = sc->stts_count && sc->tts_count;
5283
3/4
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 257 times.
✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
325 if (sc->h_spacing && sc->v_spacing)
5284 68 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5285 68 sc->h_spacing, sc->v_spacing, INT_MAX);
5286
4/6
✓ Branch 0 taken 254 times.
✓ Branch 1 taken 71 times.
✓ Branch 2 taken 254 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 254 times.
✗ Branch 5 not taken.
325 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
5287
2/4
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 254 times.
✗ Branch 3 not taken.
254 sc->height && sc->width &&
5288
2/4
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 254 times.
254 (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
5289 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5290 (int64_t)st->codecpar->height * sc->width,
5291 (int64_t)st->codecpar->width * sc->height, INT_MAX);
5292 }
5293
5294 #if FF_API_R_FRAME_RATE
5295
4/4
✓ Branch 0 taken 155277 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 154969 times.
✓ Branch 3 taken 308 times.
155294 for (unsigned int i = 1; sc->stts_count && i + 1 < sc->tts_count; i++) {
5296
2/2
✓ Branch 0 taken 152485 times.
✓ Branch 1 taken 2484 times.
154969 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5297 152485 continue;
5298 2484 stts_constant = 0;
5299 }
5300
2/2
✓ Branch 0 taken 291 times.
✓ Branch 1 taken 34 times.
325 if (stts_constant)
5301 291 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5302 291 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5303 #endif
5304 }
5305
5306 #if CONFIG_H261_DECODER || CONFIG_H263_DECODER || CONFIG_MPEG4_DECODER
5307
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 601 times.
627 switch (st->codecpar->codec_id) {
5308 #if CONFIG_H261_DECODER
5309 26 case AV_CODEC_ID_H261:
5310 #endif
5311 #if CONFIG_H263_DECODER
5312 case AV_CODEC_ID_H263:
5313 #endif
5314 #if CONFIG_MPEG4_DECODER
5315 case AV_CODEC_ID_MPEG4:
5316 #endif
5317 26 st->codecpar->width = 0; /* let decoder init width/height */
5318 26 st->codecpar->height= 0;
5319 26 break;
5320 }
5321 #endif
5322
5323 // If the duration of the mp3 packets is not constant, then they could need a parser
5324
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 626 times.
627 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5325
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 && sc->time_scale == st->codecpar->sample_rate) {
5326 1 int stts_constant = 1;
5327
3/4
✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 287 times.
✓ Branch 3 taken 1 times.
288 for (int i = 1; sc->stts_count && i < sc->tts_count; i++) {
5328
1/2
✓ Branch 0 taken 287 times.
✗ Branch 1 not taken.
287 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5329 287 continue;
5330 stts_constant = 0;
5331 }
5332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!stts_constant)
5333 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5334 }
5335 /* Do not need those anymore. */
5336 627 av_freep(&sc->chunk_offsets);
5337 627 av_freep(&sc->sample_sizes);
5338 627 av_freep(&sc->keyframes);
5339 627 av_freep(&sc->stps_data);
5340 627 av_freep(&sc->elst_data);
5341 627 av_freep(&sc->rap_group);
5342 627 av_freep(&sc->sync_group);
5343 627 av_freep(&sc->sgpd_sync);
5344
5345 627 return 0;
5346 }
5347
5348 135 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5349 {
5350 int ret;
5351 135 c->itunes_metadata = 1;
5352 135 ret = mov_read_default(c, pb, atom);
5353 135 c->itunes_metadata = 0;
5354 135 return ret;
5355 }
5356
5357 11 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5358 {
5359 uint32_t count;
5360 uint32_t i;
5361
5362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
5363 return 0;
5364
5365 11 avio_skip(pb, 4);
5366 11 count = avio_rb32(pb);
5367 11 atom.size -= 8;
5368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (count >= UINT_MAX / sizeof(*c->meta_keys)) {
5369 av_log(c->fc, AV_LOG_ERROR,
5370 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5371 return AVERROR_INVALIDDATA;
5372 }
5373
5374 11 c->meta_keys_count = count + 1;
5375 11 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
5376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!c->meta_keys)
5377 return AVERROR(ENOMEM);
5378
5379
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i <= count; ++i) {
5380 58 uint32_t key_size = avio_rb32(pb);
5381 58 uint32_t type = avio_rl32(pb);
5382
2/4
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 58 times.
58 if (key_size < 8 || key_size > atom.size) {
5383 av_log(c->fc, AV_LOG_ERROR,
5384 "The key# %"PRIu32" in meta has invalid size:"
5385 "%"PRIu32"\n", i, key_size);
5386 return AVERROR_INVALIDDATA;
5387 }
5388 58 atom.size -= key_size;
5389 58 key_size -= 8;
5390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (type != MKTAG('m','d','t','a')) {
5391 avio_skip(pb, key_size);
5392 continue;
5393 }
5394 58 c->meta_keys[i] = av_mallocz(key_size + 1);
5395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!c->meta_keys[i])
5396 return AVERROR(ENOMEM);
5397 58 avio_read(pb, c->meta_keys[i], key_size);
5398 }
5399
5400 11 return 0;
5401 }
5402
5403 65 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5404 {
5405 65 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5406 65 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5407 int i;
5408 65 int ret = 0;
5409 AVStream *st;
5410 MOVStreamContext *sc;
5411
5412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (c->fc->nb_streams < 1)
5413 return 0;
5414 65 st = c->fc->streams[c->fc->nb_streams-1];
5415 65 sc = st->priv_data;
5416
5417
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 65 times.
260 for (i = 0; i < 3; i++) {
5418 uint8_t **p;
5419 uint32_t len, tag;
5420
5421
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 195 times.
195 if (end - avio_tell(pb) <= 12)
5422 break;
5423
5424 195 len = avio_rb32(pb);
5425 195 tag = avio_rl32(pb);
5426 195 avio_skip(pb, 4); // flags
5427
5428
2/4
✓ Branch 0 taken 195 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 195 times.
✗ Branch 4 not taken.
195 if (len < 12 || len - 12 > end - avio_tell(pb))
5429 break;
5430 195 len -= 12;
5431
5432
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 130 times.
195 if (tag == MKTAG('m', 'e', 'a', 'n'))
5433 65 p = &mean;
5434
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 65 times.
130 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5435 65 p = &key;
5436
2/4
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
65 else if (tag == MKTAG('d', 'a', 't', 'a') && len > 4) {
5437 65 avio_skip(pb, 4);
5438 65 len -= 4;
5439 65 p = &val;
5440 } else
5441 break;
5442
5443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (*p)
5444 break;
5445
5446 195 *p = av_malloc(len + 1);
5447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*p) {
5448 ret = AVERROR(ENOMEM);
5449 break;
5450 }
5451 195 ret = ffio_read_size(pb, *p, len);
5452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (ret < 0) {
5453 av_freep(p);
5454 break;
5455 }
5456 195 (*p)[len] = 0;
5457 }
5458
5459
3/6
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 65 times.
✗ Branch 5 not taken.
65 if (mean && key && val) {
5460
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 32 times.
65 if (strcmp(key, "iTunSMPB") == 0) {
5461 int priming, remainder, samples;
5462
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
5463
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
33 if(priming>0 && priming<16384)
5464 33 sc->start_pad = priming;
5465 }
5466 }
5467
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 10 times.
120 if (strcmp(key, "cdec") != 0) {
5468 55 av_dict_set(&c->fc->metadata, key, val,
5469 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5470 55 key = val = NULL;
5471 }
5472 } else {
5473 av_log(c->fc, AV_LOG_VERBOSE,
5474 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5475 }
5476
5477 65 avio_seek(pb, end, SEEK_SET);
5478 65 av_freep(&key);
5479 65 av_freep(&val);
5480 65 av_freep(&mean);
5481 65 return ret;
5482 }
5483
5484 43 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5485 {
5486 MOVStreamContext *sc;
5487 AVStream *st;
5488
5489 43 st = avformat_new_stream(c->fc, NULL);
5490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st)
5491 return AVERROR(ENOMEM);
5492 43 sc = av_mallocz(sizeof(MOVStreamContext));
5493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc)
5494 goto fail;
5495
5496 43 item->st = st;
5497 43 st->id = item->item_id;
5498 43 st->priv_data = sc;
5499 43 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5500 43 st->codecpar->codec_id = mov_codec_id(st, item->type);
5501 43 sc->id = st->id;
5502 43 sc->ffindex = st->index;
5503 43 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5504 43 st->time_base.num = st->time_base.den = 1;
5505 43 st->nb_frames = 1;
5506 43 sc->time_scale = 1;
5507 43 sc->pb = c->fc->pb;
5508 43 sc->pb_is_copied = 1;
5509 43 sc->refcount = 1;
5510
5511
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (item->name)
5512 43 av_dict_set(&st->metadata, "title", item->name, 0);
5513
5514 // Populate the necessary fields used by mov_build_index.
5515 43 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->stsc_data)
5517 goto fail;
5518 43 sc->stsc_count = 1;
5519 43 sc->stsc_data[0].first = 1;
5520 43 sc->stsc_data[0].count = 1;
5521 43 sc->stsc_data[0].id = 1;
5522 43 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->chunk_offsets)
5524 goto fail;
5525 43 sc->chunk_count = 1;
5526 43 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->stts_data)
5528 goto fail;
5529 43 sc->stts_count = 1;
5530 43 sc->stts_data[0].count = 1;
5531 // Not used for still images. But needed by mov_build_index.
5532 43 sc->stts_data[0].duration = 0;
5533
5534 43 return 0;
5535 fail:
5536 mov_free_stream_context(c->fc, st);
5537 ff_remove_stream(c->fc, st);
5538 item->st = NULL;
5539
5540 return AVERROR(ENOMEM);
5541 }
5542
5543 157 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5544 {
5545
1/2
✓ Branch 0 taken 457 times.
✗ Branch 1 not taken.
457 while (atom.size > 8) {
5546 uint32_t tag;
5547
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 457 times.
457 if (avio_feof(pb))
5548 return AVERROR_EOF;
5549 457 tag = avio_rl32(pb);
5550 457 atom.size -= 4;
5551
2/2
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 300 times.
457 if (tag == MKTAG('h','d','l','r')) {
5552 157 avio_seek(pb, -8, SEEK_CUR);
5553 157 atom.size += 8;
5554 157 return mov_read_default(c, pb, atom);
5555 }
5556 }
5557 return 0;
5558 }
5559
5560 // return 1 when matrix is identity, 0 otherwise
5561 #define IS_MATRIX_IDENT(matrix) \
5562 ( (matrix)[0][0] == (1 << 16) && \
5563 (matrix)[1][1] == (1 << 16) && \
5564 (matrix)[2][2] == (1 << 30) && \
5565 !(matrix)[0][1] && !(matrix)[0][2] && \
5566 !(matrix)[1][0] && !(matrix)[1][2] && \
5567 !(matrix)[2][0] && !(matrix)[2][1])
5568
5569 627 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5570 {
5571 int i, j, e;
5572 int width;
5573 int height;
5574 int display_matrix[3][3];
5575 627 int res_display_matrix[3][3] = { { 0 } };
5576 AVStream *st;
5577 MOVStreamContext *sc;
5578 int version;
5579 int flags;
5580
5581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->fc->nb_streams < 1)
5582 return 0;
5583 627 st = c->fc->streams[c->fc->nb_streams-1];
5584 627 sc = st->priv_data;
5585
5586 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5587 // avoids corrupting AVStreams mapped to an earlier tkhd.
5588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (st->id != -1)
5589 return AVERROR_INVALIDDATA;
5590
5591 627 version = avio_r8(pb);
5592 627 flags = avio_rb24(pb);
5593 627 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5594
5595
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 614 times.
627 if (version == 1) {
5596 13 avio_rb64(pb);
5597 13 avio_rb64(pb);
5598 } else {
5599 614 avio_rb32(pb); /* creation time */
5600 614 avio_rb32(pb); /* modification time */
5601 }
5602 627 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5603 627 sc->id = st->id;
5604 627 avio_rb32(pb); /* reserved */
5605
5606 /* highlevel (considering edits) duration in movie timebase */
5607
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 614 times.
627 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5608 627 avio_rb32(pb); /* reserved */
5609 627 avio_rb32(pb); /* reserved */
5610
5611 627 avio_rb16(pb); /* layer */
5612 627 avio_rb16(pb); /* alternate group */
5613 627 avio_rb16(pb); /* volume */
5614 627 avio_rb16(pb); /* reserved */
5615
5616 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
5617 // they're kept in fixed point format through all calculations
5618 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
5619 // side data, but the scale factor is not needed to calculate aspect ratio
5620
2/2
✓ Branch 0 taken 1881 times.
✓ Branch 1 taken 627 times.
2508 for (i = 0; i < 3; i++) {
5621 1881 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
5622 1881 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
5623 1881 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
5624 }
5625
5626 627 width = avio_rb32(pb); // 16.16 fixed point track width
5627 627 height = avio_rb32(pb); // 16.16 fixed point track height
5628 627 sc->width = width >> 16;
5629 627 sc->height = height >> 16;
5630
5631 // apply the moov display matrix (after the tkhd one)
5632
2/2
✓ Branch 0 taken 1881 times.
✓ Branch 1 taken 627 times.
2508 for (i = 0; i < 3; i++) {
5633 1881 const int sh[3] = { 16, 16, 30 };
5634
2/2
✓ Branch 0 taken 5643 times.
✓ Branch 1 taken 1881 times.
7524 for (j = 0; j < 3; j++) {
5635
2/2
✓ Branch 0 taken 16929 times.
✓ Branch 1 taken 5643 times.
22572 for (e = 0; e < 3; e++) {
5636 16929 res_display_matrix[i][j] +=
5637 16929 ((int64_t) display_matrix[i][e] *
5638 16929 c->movie_display_matrix[e][j]) >> sh[e];
5639 }
5640 }
5641 }
5642
5643 // save the matrix when it is not the default identity
5644
10/18
✓ Branch 0 taken 618 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 618 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 618 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 618 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 618 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 618 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 618 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 618 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 618 times.
627 if (!IS_MATRIX_IDENT(res_display_matrix)) {
5645 9 av_freep(&sc->display_matrix);
5646 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
5647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
5648 return AVERROR(ENOMEM);
5649
5650
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
5651
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
5652 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
5653 }
5654
5655 // transform the display width/height according to the matrix
5656 // to keep the same scale, use [width height 1<<16]
5657
5/6
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 292 times.
✓ Branch 2 taken 335 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 327 times.
627 if (width && height && sc->display_matrix) {
5658 double disp_transform[2];
5659
5660
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
5661 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
5662 16 sc->display_matrix[3 + i]);
5663
5664
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 &&
5665
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) &&
5666
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
5667 3 st->sample_aspect_ratio = av_d2q(
5668 3 disp_transform[0] / disp_transform[1],
5669 INT_MAX);
5670 }
5671 627 return 0;
5672 }
5673
5674 499 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5675 {
5676 499 MOVFragment *frag = &c->fragment;
5677 499 MOVTrackExt *trex = NULL;
5678 int flags, track_id, i;
5679 MOVFragmentStreamInfo * frag_stream_info;
5680
5681 499 avio_r8(pb); /* version */
5682 499 flags = avio_rb24(pb);
5683
5684 499 track_id = avio_rb32(pb);
5685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!track_id)
5686 return AVERROR_INVALIDDATA;
5687
1/2
✓ Branch 0 taken 558 times.
✗ Branch 1 not taken.
558 for (i = 0; i < c->trex_count; i++)
5688
2/2
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 59 times.
558 if (c->trex_data[i].track_id == track_id) {
5689 499 trex = &c->trex_data[i];
5690 499 break;
5691 }
5692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!trex) {
5693 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
5694 return 0;
5695 }
5696 499 c->fragment.found_tfhd = 1;
5697 499 frag->track_id = track_id;
5698 499 set_frag_stream(&c->frag_index, track_id);
5699
5700 998 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
5701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
998 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
5702
2/2
✓ Branch 0 taken 426 times.
✓ Branch 1 taken 73 times.
499 frag->moof_offset : frag->implicit_offset;
5703
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 438 times.
499 frag->stsd_id = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id;
5704
5705 998 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
5706
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 435 times.
499 avio_rb32(pb) : trex->duration;
5707 998 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
5708
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 440 times.
499 avio_rb32(pb) : trex->size;
5709 998 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
5710
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 366 times.
499 avio_rb32(pb) : trex->flags;
5711 499 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
5712
5713 499 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5714
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info) {
5715 499 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
5716 499 frag_stream_info->stsd_id = frag->stsd_id;
5717 }
5718 499 return 0;
5719 }
5720
5721 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5722 {
5723 unsigned i, num;
5724 void *new_tracks;
5725
5726 2 num = atom.size / 4;
5727
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
5728 return AVERROR(ENOMEM);
5729
5730 2 av_free(c->chapter_tracks);
5731 2 c->chapter_tracks = new_tracks;
5732 2 c->nb_chapter_tracks = num;
5733
5734
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++)
5735 2 c->chapter_tracks[i] = avio_rb32(pb);
5736
5737 2 c->nb_chapter_tracks = i;
5738
5739 2 return 0;
5740 }
5741
5742 28 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5743 {
5744 MOVTrackExt *trex;
5745 int err;
5746
5747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if ((uint64_t)c->trex_count+1 >= UINT_MAX / sizeof(*c->trex_data))
5748 return AVERROR_INVALIDDATA;
5749
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
5750 sizeof(*c->trex_data))) < 0) {
5751 c->trex_count = 0;
5752 return err;
5753 }
5754
5755 28 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
5756
5757 28 trex = &c->trex_data[c->trex_count++];
5758 28 avio_r8(pb); /* version */
5759 28 avio_rb24(pb); /* flags */
5760 28 trex->track_id = avio_rb32(pb);
5761 28 trex->stsd_id = avio_rb32(pb);
5762 28 trex->duration = avio_rb32(pb);
5763 28 trex->size = avio_rb32(pb);
5764 28 trex->flags = avio_rb32(pb);
5765 28 return 0;
5766 }
5767
5768 426 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5769 {
5770 426 MOVFragment *frag = &c->fragment;
5771 426 AVStream *st = NULL;
5772 MOVStreamContext *sc;
5773 int version, i;
5774 MOVFragmentStreamInfo * frag_stream_info;
5775 int64_t base_media_decode_time;
5776
5777
1/2
✓ Branch 0 taken 453 times.
✗ Branch 1 not taken.
453 for (i = 0; i < c->fc->nb_streams; i++) {
5778 453 sc = c->fc->streams[i]->priv_data;
5779
2/2
✓ Branch 0 taken 426 times.
✓ Branch 1 taken 27 times.
453 if (sc->id == frag->track_id) {
5780 426 st = c->fc->streams[i];
5781 426 break;
5782 }
5783 }
5784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 426 times.
426 if (!st) {
5785 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5786 return 0;
5787 }
5788 426 sc = st->priv_data;
5789
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 422 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
426 if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1)
5790 return 0;
5791 426 version = avio_r8(pb);
5792 426 avio_rb24(pb); /* flags */
5793
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 370 times.
426 if (version) {
5794 56 base_media_decode_time = avio_rb64(pb);
5795 } else {
5796 370 base_media_decode_time = avio_rb32(pb);
5797 }
5798
5799 426 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5800
1/2
✓ Branch 0 taken 426 times.
✗ Branch 1 not taken.
426 if (frag_stream_info)
5801 426 frag_stream_info->tfdt_dts = base_media_decode_time;
5802 426 sc->track_end = base_media_decode_time;
5803
5804 426 return 0;
5805 }
5806
5807 499 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5808 {
5809 499 MOVFragment *frag = &c->fragment;
5810 499 AVStream *st = NULL;
5811 499 FFStream *sti = NULL;
5812 MOVStreamContext *sc;
5813 MOVTimeToSample *tts_data;
5814 uint64_t offset;
5815 499 int64_t dts, pts = AV_NOPTS_VALUE;
5816 499 int data_offset = 0;
5817 499 unsigned entries, first_sample_flags = frag->flags;
5818 int flags, distance, i;
5819 499 int64_t prev_dts = AV_NOPTS_VALUE;
5820 499 int next_frag_index = -1, index_entry_pos;
5821 size_t requested_size;
5822 size_t old_allocated_size;
5823 AVIndexEntry *new_entries;
5824 MOVFragmentStreamInfo * frag_stream_info;
5825
5826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!frag->found_tfhd) {
5827 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
5828 return AVERROR_INVALIDDATA;
5829 }
5830
5831
1/2
✓ Branch 0 taken 558 times.
✗ Branch 1 not taken.
558 for (i = 0; i < c->fc->nb_streams; i++) {
5832 558 sc = c->fc->streams[i]->priv_data;
5833
2/2
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 59 times.
558 if (sc->id == frag->track_id) {
5834 499 st = c->fc->streams[i];
5835 499 sti = ffstream(st);
5836 499 break;
5837 }
5838 }
5839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!st) {
5840 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5841 return 0;
5842 }
5843 499 sc = st->priv_data;
5844
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 495 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
499 if (sc->pseudo_stream_id+1 != frag->stsd_id && sc->pseudo_stream_id != -1)
5845 return 0;
5846
5847 // Find the next frag_index index that has a valid index_entry for
5848 // the current track_id.
5849 //
5850 // A valid index_entry means the trun for the fragment was read
5851 // and it's samples are in index_entries at the given position.
5852 // New index entries will be inserted before the index_entry found.
5853 499 index_entry_pos = sti->nb_index_entries;
5854
2/2
✓ Branch 0 taken 1634 times.
✓ Branch 1 taken 499 times.
2133 for (i = c->frag_index.current + 1; i < c->frag_index.nb_items; i++) {
5855 1634 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
5856
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) {
5857 next_frag_index = i;
5858 index_entry_pos = frag_stream_info->index_entry;
5859 break;
5860 }
5861 }
5862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 av_assert0(index_entry_pos <= sti->nb_index_entries);
5863
5864 499 avio_r8(pb); /* version */
5865 499 flags = avio_rb24(pb);
5866 499 entries = avio_rb32(pb);
5867 499 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
5868
5869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if ((uint64_t)entries+sc->tts_count >= UINT_MAX/sizeof(*sc->tts_data))
5870 return AVERROR_INVALIDDATA;
5871
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
5872
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 424 times.
499 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb);
5873
5874 499 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5875
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info) {
5876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
5877 dts = frag_stream_info->next_trun_dts - sc->time_offset;
5878
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 496 times.
499 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5879
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
5880 3 pts = frag_stream_info->first_tfra_pts;
5881 3 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5882 ", using it for pts\n", pts);
5883
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5884 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
5885 dts = frag_stream_info->first_tfra_pts;
5886 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5887 ", using it for dts\n", pts);
5888 } else {
5889 496 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
5890 496 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
5891
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
496 int fallback_tfdt = !c->use_tfdt && !has_sidx && has_tfdt;
5892
4/6
✓ Branch 0 taken 496 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 423 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
496 int fallback_sidx = c->use_tfdt && !has_tfdt && has_sidx;
5893
5894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 if (fallback_sidx) {
5895 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
5896 }
5897
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 if (fallback_tfdt) {
5898 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
5899 }
5900
5901
4/6
✓ Branch 0 taken 423 times.
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 423 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
496 if (has_tfdt && c->use_tfdt || fallback_tfdt) {
5902 423 dts = frag_stream_info->tfdt_dts - sc->time_offset;
5903 423 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
5904 ", using it for dts\n", dts);
5905
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) {
5906 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
5907 // pts = frag_stream_info->sidx_pts;
5908 dts = frag_stream_info->sidx_pts;
5909 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
5910 ", using it for dts\n", frag_stream_info->sidx_pts);
5911 } else {
5912 73 dts = sc->track_end - sc->time_offset;
5913 73 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5914 ", using it for dts\n", dts);
5915 }
5916 }
5917 } else {
5918 dts = sc->track_end - sc->time_offset;
5919 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5920 ", using it for dts\n", dts);
5921 }
5922 499 offset = frag->base_data_offset + data_offset;
5923 499 distance = 0;
5924 499 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
5925
5926 // realloc space for new index entries
5927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
5928 entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
5929 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
5930 }
5931
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (entries == 0)
5932 return 0;
5933
5934 499 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
5935 499 new_entries = av_fast_realloc(sti->index_entries,
5936 &sti->index_entries_allocated_size,
5937 requested_size);
5938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!new_entries)
5939 return AVERROR(ENOMEM);
5940 499 sti->index_entries= new_entries;
5941
5942 499 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
5943 499 old_allocated_size = sc->tts_allocated_size;
5944 499 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
5945 requested_size);
5946
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!tts_data)
5947 return AVERROR(ENOMEM);
5948 499 sc->tts_data = tts_data;
5949
5950 // In case there were samples without time to sample entries, ensure they get
5951 // zero valued entries. This ensures clips which mix boxes with and
5952 // without time to sample entries don't pickup uninitialized data.
5953 499 memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0,
5954 499 sc->tts_allocated_size - old_allocated_size);
5955
5956
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (index_entry_pos < sti->nb_index_entries) {
5957 // Make hole in index_entries and tts_data for new samples
5958 memmove(sti->index_entries + index_entry_pos + entries,
5959 sti->index_entries + index_entry_pos,
5960 sizeof(*sti->index_entries) *
5961 (sti->nb_index_entries - index_entry_pos));
5962 memmove(sc->tts_data + index_entry_pos + entries,
5963 sc->tts_data + index_entry_pos,
5964 sizeof(*sc->tts_data) * (sc->tts_count - index_entry_pos));
5965 if (index_entry_pos < sc->current_sample) {
5966 sc->current_sample += entries;
5967 }
5968 }
5969
5970 499 sti->nb_index_entries += entries;
5971 499 sc->tts_count = sti->nb_index_entries;
5972 499 sc->stts_count = sti->nb_index_entries;
5973
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 113 times.
499 if (flags & MOV_TRUN_SAMPLE_CTS)
5974 386 sc->ctts_count = sti->nb_index_entries;
5975
5976 // Record the index_entry position in frag_index of this fragment
5977
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info) {
5978 499 frag_stream_info->index_entry = index_entry_pos;
5979
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info->index_base < 0)
5980 499 frag_stream_info->index_base = index_entry_pos;
5981 }
5982
5983
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 27 times.
499 if (index_entry_pos > 0)
5984 472 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
5985
5986
3/4
✓ Branch 0 taken 8707 times.
✓ Branch 1 taken 499 times.
✓ Branch 2 taken 8707 times.
✗ Branch 3 not taken.
9206 for (i = 0; i < entries && !pb->eof_reached; i++) {
5987 8707 unsigned sample_size = frag->size;
5988
2/2
✓ Branch 0 taken 8208 times.
✓ Branch 1 taken 499 times.
8707 int sample_flags = i ? frag->flags : first_sample_flags;
5989 8707 unsigned sample_duration = frag->duration;
5990 8707 unsigned ctts_duration = 0;
5991 8707 int keyframe = 0;
5992 8707 int index_entry_flags = 0;
5993
5994
2/2
✓ Branch 0 taken 1674 times.
✓ Branch 1 taken 7033 times.
8707 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
5995
2/2
✓ Branch 0 taken 8649 times.
✓ Branch 1 taken 58 times.
8707 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
5996
2/2
✓ Branch 0 taken 981 times.
✓ Branch 1 taken 7726 times.
8707 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
5997
2/2
✓ Branch 0 taken 6576 times.
✓ Branch 1 taken 2131 times.
8707 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
5998
5999 8707 mov_update_dts_shift(sc, ctts_duration, c->fc);
6000
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8704 times.
8707 if (pts != AV_NOPTS_VALUE) {
6001 3 dts = pts - sc->dts_shift;
6002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (flags & MOV_TRUN_SAMPLE_CTS) {
6003 dts -= ctts_duration;
6004 } else {
6005 3 dts -= sc->time_offset;
6006 }
6007 3 av_log(c->fc, AV_LOG_DEBUG,
6008 "pts %"PRId64" calculated dts %"PRId64
6009 " sc->dts_shift %d ctts.duration %d"
6010 " sc->time_offset %"PRId64
6011 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
6012 pts, dts,
6013 sc->dts_shift, ctts_duration,
6014 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
6015 3 pts = AV_NOPTS_VALUE;
6016 }
6017
6018 8707 keyframe =
6019 8707 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
6020 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
6021
2/2
✓ Branch 0 taken 646 times.
✓ Branch 1 taken 8061 times.
8707 if (keyframe) {
6022 646 distance = 0;
6023 646 index_entry_flags |= AVINDEX_KEYFRAME;
6024 }
6025 // Fragments can overlap in time. Discard overlapping frames after
6026 // decoding.
6027
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8683 times.
8707 if (prev_dts >= dts)
6028 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
6029
6030 8707 sti->index_entries[index_entry_pos].pos = offset;
6031 8707 sti->index_entries[index_entry_pos].timestamp = dts;
6032 8707 sti->index_entries[index_entry_pos].size = sample_size;
6033 8707 sti->index_entries[index_entry_pos].min_distance = distance;
6034 8707 sti->index_entries[index_entry_pos].flags = index_entry_flags;
6035
6036 8707 sc->tts_data[index_entry_pos].count = 1;
6037 8707 sc->tts_data[index_entry_pos].offset = ctts_duration;
6038 8707 sc->tts_data[index_entry_pos].duration = sample_duration;
6039 8707 index_entry_pos++;
6040
6041 8707 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
6042 "size %u, distance %d, keyframe %d\n", st->index,
6043 index_entry_pos, offset, dts, sample_size, distance, keyframe);
6044 8707 distance++;
6045
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8707 times.
8707 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
6046 return AVERROR_INVALIDDATA;
6047
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8707 times.
8707 if (!sample_size)
6048 return AVERROR_INVALIDDATA;
6049 8707 dts += sample_duration;
6050 8707 offset += sample_size;
6051 8707 sc->data_size += sample_size;
6052
6053
1/2
✓ Branch 0 taken 8707 times.
✗ Branch 1 not taken.
8707 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
6054
1/2
✓ Branch 0 taken 8707 times.
✗ Branch 1 not taken.
8707 1 <= INT_MAX - sc->nb_frames_for_fps
6055 ) {
6056 8707 sc->duration_for_fps += sample_duration;
6057 8707 sc->nb_frames_for_fps ++;
6058 }
6059 }
6060
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info)
6061 499 frag_stream_info->next_trun_dts = dts + sc->time_offset;
6062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (i < entries) {
6063 // EOF found before reading all entries. Fix the hole this would
6064 // leave in index_entries and tts_data
6065 int gap = entries - i;
6066 memmove(sti->index_entries + index_entry_pos,
6067 sti->index_entries + index_entry_pos + gap,
6068 sizeof(*sti->index_entries) *
6069 (sti->nb_index_entries - (index_entry_pos + gap)));
6070 memmove(sc->tts_data + index_entry_pos,
6071 sc->tts_data + index_entry_pos + gap,
6072 sizeof(*sc->tts_data) *
6073 (sc->tts_count - (index_entry_pos + gap)));
6074
6075 sti->nb_index_entries -= gap;
6076 sc->tts_count -= gap;
6077 if (index_entry_pos < sc->current_sample) {
6078 sc->current_sample -= gap;
6079 }
6080 entries = i;
6081 }
6082
6083 // The end of this new fragment may overlap in time with the start
6084 // of the next fragment in index_entries. Mark the samples in the next
6085 // fragment that overlap with AVINDEX_DISCARD_FRAME
6086 499 prev_dts = AV_NOPTS_VALUE;
6087
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (index_entry_pos > 0)
6088 499 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
6090 if (prev_dts < sti->index_entries[i].timestamp)
6091 break;
6092 sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6093 }
6094
6095 // If a hole was created to insert the new index_entries into,
6096 // the index_entry recorded for all subsequent moof must
6097 // be incremented by the number of entries inserted.
6098 499 fix_frag_index_entries(&c->frag_index, next_frag_index,
6099 499 frag->track_id, entries);
6100
6101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (pb->eof_reached) {
6102 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6103 return AVERROR_EOF;
6104 }
6105
6106 499 frag->implicit_offset = offset;
6107
6108 499 sc->track_end = dts + sc->time_offset;
6109
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 383 times.
499 if (st->duration < sc->track_end)
6110 116 st->duration = sc->track_end;
6111
6112 499 return 0;
6113 }
6114
6115 46 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6116 {
6117 46 int64_t stream_size = avio_size(pb);
6118 46 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6119 uint8_t version, is_complete;
6120 int64_t offadd;
6121 unsigned i, j, track_id, item_count;
6122 46 AVStream *st = NULL;
6123 46 AVStream *ref_st = NULL;
6124 46 MOVStreamContext *sc, *ref_sc = NULL;
6125 AVRational timescale;
6126
6127 46 version = avio_r8(pb);
6128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (version > 1) {
6129 avpriv_request_sample(c->fc, "sidx version %u", version);
6130 return 0;
6131 }
6132
6133 46 avio_rb24(pb); // flags
6134
6135 46 track_id = avio_rb32(pb); // Reference ID
6136
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 for (i = 0; i < c->fc->nb_streams; i++) {
6137 46 sc = c->fc->streams[i]->priv_data;
6138
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 if (sc->id == track_id) {
6139 46 st = c->fc->streams[i];
6140 46 break;
6141 }
6142 }
6143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!st) {
6144 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6145 return 0;
6146 }
6147
6148 46 sc = st->priv_data;
6149
6150 46 timescale = av_make_q(1, avio_rb32(pb));
6151
6152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (timescale.den <= 0) {
6153 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6154 return AVERROR_INVALIDDATA;
6155 }
6156
6157
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1 times.
46 if (version == 0) {
6158 45 pts = avio_rb32(pb);
6159 45 offadd= avio_rb32(pb);
6160 } else {
6161 1 pts = avio_rb64(pb);
6162 1 offadd= avio_rb64(pb);
6163 }
6164
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6165 return AVERROR_INVALIDDATA;
6166
6167 46 offset += (uint64_t)offadd;
6168
6169 46 avio_rb16(pb); // reserved
6170
6171 46 item_count = avio_rb16(pb);
6172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (item_count == 0)
6173 return AVERROR_INVALIDDATA;
6174
6175
2/2
✓ Branch 0 taken 372 times.
✓ Branch 1 taken 46 times.
418 for (i = 0; i < item_count; i++) {
6176 int index;
6177 MOVFragmentStreamInfo * frag_stream_info;
6178 372 uint32_t size = avio_rb32(pb);
6179 372 uint32_t duration = avio_rb32(pb);
6180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
372 if (size & 0x80000000) {
6181 avpriv_request_sample(c->fc, "sidx reference_type 1");
6182 return AVERROR_PATCHWELCOME;
6183 }
6184 372 avio_rb32(pb); // sap_flags
6185 372 timestamp = av_rescale_q(pts, timescale, st->time_base);
6186
6187 372 index = update_frag_index(c, offset);
6188 372 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6189
1/2
✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
372 if (frag_stream_info)
6190 372 frag_stream_info->sidx_pts = timestamp;
6191
6192
1/2
✓ Branch 1 taken 372 times.
✗ Branch 2 not taken.
372 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6193
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 372 times.
372 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6194 )
6195 return AVERROR_INVALIDDATA;
6196 372 offset += size;
6197 372 pts += duration;
6198 }
6199
6200 46 st->duration = sc->track_end = pts;
6201
6202 46 sc->has_sidx = 1;
6203
6204 // See if the remaining bytes are just an mfra which we can ignore.
6205 46 is_complete = offset == stream_size;
6206
5/6
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
46 if (!is_complete && (pb->seekable & AVIO_SEEKABLE_NORMAL) && stream_size > 0 ) {
6207 int64_t ret;
6208 38 int64_t original_pos = avio_tell(pb);
6209
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
38 if (!c->have_read_mfra_size) {
6210
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6211 return ret;
6212 3 c->mfra_size = avio_rb32(pb);
6213 3 c->have_read_mfra_size = 1;
6214
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6215 return ret;
6216 }
6217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (offset == stream_size - c->mfra_size)
6218 is_complete = 1;
6219 }
6220
6221
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 39 times.
46 if (is_complete) {
6222 // Find first entry in fragment index that came from an sidx.
6223 // This will pretty much always be the first entry.
6224
2/2
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 7 times.
378 for (i = 0; i < c->frag_index.nb_items; i++) {
6225 371 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6226
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++) {
6227 MOVFragmentStreamInfo * si;
6228 7 si = &item->stream_info[j];
6229
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (si->sidx_pts != AV_NOPTS_VALUE) {
6230 7 ref_st = c->fc->streams[j];
6231 7 ref_sc = ref_st->priv_data;
6232 7 break;
6233 }
6234 }
6235 }
6236
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++) {
6237 7 st = c->fc->streams[i];
6238 7 sc = st->priv_data;
6239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sc->has_sidx) {
6240 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6241 }
6242 }
6243
6244
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (offadd == 0)
6245 7 c->frag_index.complete = 1;
6246 }
6247
6248 46 return 0;
6249 }
6250
6251 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6252 /* like the files created with Adobe Premiere 5.0, for samples see */
6253 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6254 276 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6255 {
6256 int err;
6257
6258
1/2
✓ Branch 0 taken 276 times.
✗ Branch 1 not taken.
276 if (atom.size < 8)
6259 276 return 0; /* continue */
6260 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6261 avio_skip(pb, atom.size - 4);
6262 return 0;
6263 }
6264 atom.type = avio_rl32(pb);
6265 atom.size -= 8;
6266 if (atom.type != MKTAG('m','d','a','t')) {
6267 avio_skip(pb, atom.size);
6268 return 0;
6269 }
6270 err = mov_read_mdat(c, pb, atom);
6271 return err;
6272 }
6273
6274 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6275 {
6276 #if CONFIG_ZLIB
6277 FFIOContext ctx;
6278 uint8_t *cmov_data;
6279 uint8_t *moov_data; /* uncompressed data */
6280 long cmov_len, moov_len;
6281 3 int ret = -1;
6282
6283 3 avio_rb32(pb); /* dcom atom */
6284
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6285 return AVERROR_INVALIDDATA;
6286
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6287 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6288 return AVERROR_INVALIDDATA;
6289 }
6290 3 avio_rb32(pb); /* cmvd atom */
6291
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6292 return AVERROR_INVALIDDATA;
6293 3 moov_len = avio_rb32(pb); /* uncompressed size */
6294 3 cmov_len = atom.size - 6 * 4;
6295
6296 3 cmov_data = av_malloc(cmov_len);
6297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6298 return AVERROR(ENOMEM);
6299 3 moov_data = av_malloc(moov_len);
6300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6301 av_free(cmov_data);
6302 return AVERROR(ENOMEM);
6303 }
6304 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6306 goto free_and_return;
6307
6308 3 ret = AVERROR_INVALIDDATA;
6309
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)
6310 goto free_and_return;
6311 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6312 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6313 3 atom.type = MKTAG('m','o','o','v');
6314 3 atom.size = moov_len;
6315 3 ret = mov_read_default(c, &ctx.pub, atom);
6316 3 free_and_return:
6317 3 av_free(moov_data);
6318 3 av_free(cmov_data);
6319 3 return ret;
6320 #else
6321 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6322 return AVERROR(ENOSYS);
6323 #endif
6324 }
6325
6326 /* edit list atom */
6327 457 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6328 {
6329 MOVStreamContext *sc;
6330 int i, edit_count, version;
6331 int64_t elst_entry_size;
6332
6333
2/4
✓ Branch 0 taken 457 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 457 times.
457 if (c->fc->nb_streams < 1 || c->ignore_editlist)
6334 return 0;
6335 457 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6336
6337 457 version = avio_r8(pb); /* version */
6338 457 avio_rb24(pb); /* flags */
6339 457 edit_count = avio_rb32(pb); /* entries */
6340 457 atom.size -= 8;
6341
6342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 457 times.
457 elst_entry_size = version == 1 ? 20 : 12;
6343
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 456 times.
457 if (atom.size != edit_count * elst_entry_size) {
6344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6345 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6346 edit_count, atom.size + 8);
6347 return AVERROR_INVALIDDATA;
6348 } else {
6349 1 edit_count = atom.size / elst_entry_size;
6350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6351 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6352 }
6353 }
6354 }
6355
6356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 457 times.
457 if (!edit_count)
6357 return 0;
6358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 457 times.
457 if (sc->elst_data)
6359 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6360 457 av_free(sc->elst_data);
6361 457 sc->elst_count = 0;
6362 457 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 457 times.
457 if (!sc->elst_data)
6364 return AVERROR(ENOMEM);
6365
6366 457 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6367
4/6
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 457 times.
✓ Branch 2 taken 486 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 486 times.
✗ Branch 5 not taken.
943 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
6368 486 MOVElst *e = &sc->elst_data[i];
6369
6370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486 times.
486 if (version == 1) {
6371 e->duration = avio_rb64(pb);
6372 e->time = avio_rb64(pb);
6373 atom.size -= 16;
6374 } else {
6375 486 e->duration = avio_rb32(pb); /* segment duration */
6376 486 e->time = (int32_t)avio_rb32(pb); /* media time */
6377 486 atom.size -= 8;
6378 }
6379 486 e->rate = avio_rb32(pb) / 65536.0;
6380 486 atom.size -= 4;
6381 486 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6382 486 e->duration, e->time, e->rate);
6383
6384
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 482 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
486 if (e->time < 0 && e->time != -1 &&
6385 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6386 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6387 c->fc->nb_streams-1, i, e->time);
6388 return AVERROR_INVALIDDATA;
6389 }
6390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486 times.
486 if (e->duration < 0) {
6391 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list duration=%"PRId64"\n",
6392 c->fc->nb_streams-1, i, e->duration);
6393 return AVERROR_INVALIDDATA;
6394 }
6395 }
6396 457 sc->elst_count = i;
6397
6398 457 return 0;
6399 }
6400
6401 18 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6402 {
6403 MOVStreamContext *sc;
6404
6405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->fc->nb_streams < 1)
6406 return AVERROR_INVALIDDATA;
6407 18 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6408 18 sc->timecode_track = avio_rb32(pb);
6409 18 return 0;
6410 }
6411
6412 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6413 {
6414 AVStream *st;
6415 int version, color_range, color_primaries, color_trc, color_space;
6416
6417 if (c->fc->nb_streams < 1)
6418 return 0;
6419 st = c->fc->streams[c->fc->nb_streams - 1];
6420
6421 if (atom.size < 5) {
6422 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6423 return AVERROR_INVALIDDATA;
6424 }
6425
6426 version = avio_r8(pb);
6427 if (version != 1) {
6428 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6429 return 0;
6430 }
6431 avio_skip(pb, 3); /* flags */
6432
6433 avio_skip(pb, 2); /* profile + level */
6434 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6435 color_primaries = avio_r8(pb);
6436 color_trc = avio_r8(pb);
6437 color_space = avio_r8(pb);
6438 if (avio_rb16(pb)) /* codecIntializationDataSize */
6439 return AVERROR_INVALIDDATA;
6440
6441 if (!av_color_primaries_name(color_primaries))
6442 color_primaries = AVCOL_PRI_UNSPECIFIED;
6443 if (!av_color_transfer_name(color_trc))
6444 color_trc = AVCOL_TRC_UNSPECIFIED;
6445 if (!av_color_space_name(color_space))
6446 color_space = AVCOL_SPC_UNSPECIFIED;
6447
6448 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6449 st->codecpar->color_primaries = color_primaries;
6450 st->codecpar->color_trc = color_trc;
6451 st->codecpar->color_space = color_space;
6452
6453 return 0;
6454 }
6455
6456 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6457 {
6458 MOVStreamContext *sc;
6459 int i, version;
6460
6461 if (c->fc->nb_streams < 1)
6462 return AVERROR_INVALIDDATA;
6463
6464 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6465
6466 if (atom.size < 5) {
6467 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6468 return AVERROR_INVALIDDATA;
6469 }
6470
6471 version = avio_r8(pb);
6472 if (version) {
6473 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6474 return 0;
6475 }
6476 if (sc->mastering) {
6477 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6478 return 0;
6479 }
6480
6481 avio_skip(pb, 3); /* flags */
6482
6483 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6484 if (!sc->mastering)
6485 return AVERROR(ENOMEM);
6486
6487 for (i = 0; i < 3; i++) {
6488 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6489 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6490 }
6491 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6492 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6493
6494 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6495 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6496
6497 sc->mastering->has_primaries = 1;
6498 sc->mastering->has_luminance = 1;
6499
6500 return 0;
6501 }
6502
6503 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6504 {
6505 MOVStreamContext *sc;
6506 const int mapping[3] = {1, 2, 0};
6507 const int chroma_den = 50000;
6508 const int luma_den = 10000;
6509 int i;
6510
6511 if (c->fc->nb_streams < 1)
6512 return AVERROR_INVALIDDATA;
6513
6514 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6515
6516 if (atom.size < 24) {
6517 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6518 return AVERROR_INVALIDDATA;
6519 }
6520
6521 if (sc->mastering) {
6522 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6523 return 0;
6524 }
6525
6526 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6527 if (!sc->mastering)
6528 return AVERROR(ENOMEM);
6529
6530 for (i = 0; i < 3; i++) {
6531 const int j = mapping[i];
6532 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6533 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6534 }
6535 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6536 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6537
6538 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6539 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6540
6541 sc->mastering->has_luminance = 1;
6542 sc->mastering->has_primaries = 1;
6543
6544 return 0;
6545 }
6546
6547 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6548 {
6549 MOVStreamContext *sc;
6550 int version;
6551
6552 if (c->fc->nb_streams < 1)
6553 return AVERROR_INVALIDDATA;
6554
6555 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6556
6557 if (atom.size < 5) {
6558 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
6559 return AVERROR_INVALIDDATA;
6560 }
6561
6562 version = avio_r8(pb);
6563 if (version) {
6564 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
6565 return 0;
6566 }
6567 avio_skip(pb, 3); /* flags */
6568
6569 if (sc->coll){
6570 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
6571 return 0;
6572 }
6573
6574 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6575 if (!sc->coll)
6576 return AVERROR(ENOMEM);
6577
6578 sc->coll->MaxCLL = avio_rb16(pb);
6579 sc->coll->MaxFALL = avio_rb16(pb);
6580
6581 return 0;
6582 }
6583
6584 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6585 {
6586 MOVStreamContext *sc;
6587
6588 if (c->fc->nb_streams < 1)
6589 return AVERROR_INVALIDDATA;
6590
6591 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6592
6593 if (atom.size < 4) {
6594 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
6595 return AVERROR_INVALIDDATA;
6596 }
6597
6598 if (sc->coll){
6599 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
6600 return 0;
6601 }
6602
6603 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6604 if (!sc->coll)
6605 return AVERROR(ENOMEM);
6606
6607 sc->coll->MaxCLL = avio_rb16(pb);
6608 sc->coll->MaxFALL = avio_rb16(pb);
6609
6610 return 0;
6611 }
6612
6613 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6614 {
6615 MOVStreamContext *sc;
6616 4 const int illuminance_den = 10000;
6617 4 const int ambient_den = 50000;
6618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
6619 return AVERROR_INVALIDDATA;
6620 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
6622 av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
6623 return AVERROR_INVALIDDATA;
6624 }
6625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
6626 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
6627 return 0;
6628 }
6629 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
6630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
6631 return AVERROR(ENOMEM);
6632 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
6633 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
6634 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
6635 4 return 0;
6636 }
6637
6638 1 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6639 {
6640 AVStream *st;
6641 MOVStreamContext *sc;
6642 enum AVStereo3DType type;
6643 int mode;
6644
6645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6646 return 0;
6647
6648 1 st = c->fc->streams[c->fc->nb_streams - 1];
6649 1 sc = st->priv_data;
6650
6651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 5) {
6652 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
6653 return AVERROR_INVALIDDATA;
6654 }
6655
6656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sc->stereo3d)
6657 return AVERROR_INVALIDDATA;
6658
6659 1 avio_skip(pb, 4); /* version + flags */
6660
6661 1 mode = avio_r8(pb);
6662
1/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 switch (mode) {
6663 1 case 0:
6664 1 type = AV_STEREO3D_2D;
6665 1 break;
6666 case 1:
6667 type = AV_STEREO3D_TOPBOTTOM;
6668 break;
6669 case 2:
6670 type = AV_STEREO3D_SIDEBYSIDE;
6671 break;
6672 default:
6673 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
6674 return 0;
6675 }
6676
6677 1 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->stereo3d)
6679 return AVERROR(ENOMEM);
6680
6681 1 sc->stereo3d->type = type;
6682 1 return 0;
6683 }
6684
6685 static int mov_read_pack(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6686 {
6687 AVStream *st;
6688 MOVStreamContext *sc;
6689 int size = 0;
6690 int64_t remaining;
6691 uint32_t tag = 0;
6692 enum AVStereo3DType type = AV_STEREO3D_2D;
6693
6694 if (c->fc->nb_streams < 1)
6695 return 0;
6696
6697 st = c->fc->streams[c->fc->nb_streams - 1];
6698 sc = st->priv_data;
6699
6700 remaining = atom.size;
6701 while (remaining > 0) {
6702 size = avio_rb32(pb);
6703 if (size < 8 || size > remaining ) {
6704 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in pack box\n");
6705 return AVERROR_INVALIDDATA;
6706 }
6707
6708 tag = avio_rl32(pb);
6709 switch (tag) {
6710 case MKTAG('p','k','i','n'): {
6711 if (size != 16) {
6712 av_log(c->fc, AV_LOG_ERROR, "Invalid size of pkin box: %d\n", size);
6713 return AVERROR_INVALIDDATA;
6714 }
6715 avio_skip(pb, 1); // version
6716 avio_skip(pb, 3); // flags
6717
6718 tag = avio_rl32(pb);
6719 switch (tag) {
6720 case MKTAG('s','i','d','e'):
6721 type = AV_STEREO3D_SIDEBYSIDE;
6722 break;
6723 case MKTAG('o','v','e','r'):
6724 type = AV_STEREO3D_TOPBOTTOM;
6725 break;
6726 case 0:
6727 // This means value will be set in another layer
6728 break;
6729 default:
6730 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pkin: %s\n",
6731 av_fourcc2str(tag));
6732 avio_skip(pb, size - 8);
6733 break;
6734 }
6735
6736 break;
6737 }
6738 default:
6739 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pack: %s\n",
6740 av_fourcc2str(tag));
6741 avio_skip(pb, size - 8);
6742 break;
6743 }
6744 remaining -= size;
6745 }
6746
6747 if (remaining != 0) {
6748 av_log(c->fc, AV_LOG_ERROR, "Broken pack box\n");
6749 return AVERROR_INVALIDDATA;
6750 }
6751
6752 if (type == AV_STEREO3D_2D)
6753 return 0;
6754
6755 if (!sc->stereo3d) {
6756 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6757 if (!sc->stereo3d)
6758 return AVERROR(ENOMEM);
6759 }
6760
6761 sc->stereo3d->type = type;
6762
6763 return 0;
6764 }
6765
6766 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6767 {
6768 AVStream *st;
6769 MOVStreamContext *sc;
6770 int size, version, layout;
6771 int32_t yaw, pitch, roll;
6772 1 uint32_t l = 0, t = 0, r = 0, b = 0;
6773 1 uint32_t tag, padding = 0;
6774 enum AVSphericalProjection projection;
6775
6776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6777 return 0;
6778
6779 1 st = c->fc->streams[c->fc->nb_streams - 1];
6780 1 sc = st->priv_data;
6781
6782
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
6783 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
6784 return AVERROR_INVALIDDATA;
6785 }
6786
6787 1 size = avio_rb32(pb);
6788
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)
6789 return AVERROR_INVALIDDATA;
6790
6791 1 tag = avio_rl32(pb);
6792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
6793 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
6794 return 0;
6795 }
6796 1 version = avio_r8(pb);
6797
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6798 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6799 version);
6800 return 0;
6801 }
6802 1 avio_skip(pb, 3); /* flags */
6803 1 avio_skip(pb, size - 12); /* metadata_source */
6804
6805 1 size = avio_rb32(pb);
6806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6807 return AVERROR_INVALIDDATA;
6808
6809 1 tag = avio_rl32(pb);
6810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
6811 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
6812 return 0;
6813 }
6814
6815 1 size = avio_rb32(pb);
6816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6817 return AVERROR_INVALIDDATA;
6818
6819 1 tag = avio_rl32(pb);
6820
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
6821 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
6822 return 0;
6823 }
6824 1 version = avio_r8(pb);
6825
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6826 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6827 version);
6828 return 0;
6829 }
6830 1 avio_skip(pb, 3); /* flags */
6831
6832 /* 16.16 fixed point */
6833 1 yaw = avio_rb32(pb);
6834 1 pitch = avio_rb32(pb);
6835 1 roll = avio_rb32(pb);
6836
6837 1 size = avio_rb32(pb);
6838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6839 return AVERROR_INVALIDDATA;
6840
6841 1 tag = avio_rl32(pb);
6842 1 version = avio_r8(pb);
6843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6844 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6845 version);
6846 return 0;
6847 }
6848 1 avio_skip(pb, 3); /* flags */
6849
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
6850 case MKTAG('c','b','m','p'):
6851 layout = avio_rb32(pb);
6852 if (layout) {
6853 av_log(c->fc, AV_LOG_WARNING,
6854 "Unsupported cubemap layout %d\n", layout);
6855 return 0;
6856 }
6857 projection = AV_SPHERICAL_CUBEMAP;
6858 padding = avio_rb32(pb);
6859 break;
6860 1 case MKTAG('e','q','u','i'):
6861 1 t = avio_rb32(pb);
6862 1 b = avio_rb32(pb);
6863 1 l = avio_rb32(pb);
6864 1 r = avio_rb32(pb);
6865
6866
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) {
6867 av_log(c->fc, AV_LOG_ERROR,
6868 "Invalid bounding rectangle coordinates "
6869 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
6870 return AVERROR_INVALIDDATA;
6871 }
6872
6873
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)
6874 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
6875 else
6876 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6877 1 break;
6878 default:
6879 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
6880 return 0;
6881 }
6882
6883 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
6885 return AVERROR(ENOMEM);
6886
6887 1 sc->spherical->projection = projection;
6888
6889 1 sc->spherical->yaw = yaw;
6890 1 sc->spherical->pitch = pitch;
6891 1 sc->spherical->roll = roll;
6892
6893 1 sc->spherical->padding = padding;
6894
6895 1 sc->spherical->bound_left = l;
6896 1 sc->spherical->bound_top = t;
6897 1 sc->spherical->bound_right = r;
6898 1 sc->spherical->bound_bottom = b;
6899
6900 1 return 0;
6901 }
6902
6903 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6904 {
6905 AVStream *st;
6906 MOVStreamContext *sc;
6907 int size;
6908 uint32_t tag;
6909 enum AVSphericalProjection projection;
6910
6911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6912 return 0;
6913
6914 3 st = c->fc->streams[c->fc->nb_streams - 1];
6915 3 sc = st->priv_data;
6916
6917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 16) {
6918 av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
6919 return AVERROR_INVALIDDATA;
6920 }
6921
6922 3 size = avio_rb32(pb);
6923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size < 16) {
6924 av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
6925 return AVERROR_INVALIDDATA;
6926
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (size > 16) {
6927 av_log(c->fc, AV_LOG_WARNING, "Box has more bytes (%d) than prji box required (16) \n", size);
6928 }
6929
6930 3 tag = avio_rl32(pb);
6931
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
6932 av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: %s\n",
6933 av_fourcc2str(tag));
6934 return AVERROR_INVALIDDATA;
6935 }
6936
6937 // version and flags, only support (0, 0)
6938 3 unsigned n = avio_rl32(pb);
6939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (n != 0) {
6940 av_log(c->fc, AV_LOG_ERROR, "prji version %u, flag %u are not supported\n",
6941 n & 0xFF, n >> 8);
6942 return AVERROR_PATCHWELCOME;
6943 }
6944
6945 3 tag = avio_rl32(pb);
6946
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) {
6947 3 case MKTAG('r','e','c','t'):
6948 3 projection = AV_SPHERICAL_RECTILINEAR;
6949 3 break;
6950 case MKTAG('e','q','u','i'):
6951 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6952 break;
6953 case MKTAG('h','e','q','u'):
6954 projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
6955 break;
6956 case MKTAG('f','i','s','h'):
6957 projection = AV_SPHERICAL_FISHEYE;
6958 break;
6959 case MKTAG('p','r','i','m'):
6960 projection = AV_SPHERICAL_PARAMETRIC_IMMERSIVE;
6961 break;
6962 default:
6963 av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: %s\n", av_fourcc2str(tag));
6964 return AVERROR_INVALIDDATA;
6965 }
6966
6967 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6968
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
6969 return AVERROR(ENOMEM);
6970
6971 3 sc->spherical->projection = projection;
6972
6973 3 return 0;
6974 }
6975
6976 3 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6977 {
6978 AVStream *st;
6979 MOVStreamContext *sc;
6980 3 int size, flags = 0;
6981 int64_t remaining;
6982 3 uint32_t tag, baseline = 0;
6983 3 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
6984 3 enum AVStereo3DType type = AV_STEREO3D_2D;
6985 3 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
6986 3 AVRational horizontal_disparity_adjustment = { 0, 1 };
6987
6988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6989 return 0;
6990
6991 3 st = c->fc->streams[c->fc->nb_streams - 1];
6992 3 sc = st->priv_data;
6993
6994 3 remaining = atom.size;
6995
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 while (remaining > 0) {
6996 9 size = avio_rb32(pb);
6997
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
9 if (size < 8 || size > remaining ) {
6998 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
6999 return AVERROR_INVALIDDATA;
7000 }
7001
7002 9 tag = avio_rl32(pb);
7003
3/5
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
9 switch (tag) {
7004 3 case MKTAG('s','t','r','i'): {
7005 int has_right, has_left;
7006 uint8_t tmp;
7007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 13) {
7008 av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
7009 return AVERROR_INVALIDDATA;
7010 }
7011 3 avio_skip(pb, 1); // version
7012 3 avio_skip(pb, 3); // flags
7013
7014 3 tmp = avio_r8(pb);
7015
7016 // eye_views_reversed
7017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tmp & 8) {
7018 flags |= AV_STEREO3D_FLAG_INVERT;
7019 }
7020 // has_additional_views
7021 3 if (tmp & 4) {
7022 // skip...
7023 }
7024
7025 3 has_right = tmp & 2; // has_right_eye_view
7026 3 has_left = tmp & 1; // has_left_eye_view
7027
7028
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if (has_left && has_right)
7029 3 view = AV_STEREO3D_VIEW_PACKED;
7030 else if (has_left)
7031 view = AV_STEREO3D_VIEW_LEFT;
7032 else if (has_right)
7033 view = AV_STEREO3D_VIEW_RIGHT;
7034
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if (has_left || has_right)
7035 3 type = AV_STEREO3D_UNSPEC;
7036
7037 3 break;
7038 }
7039 case MKTAG('h','e','r','o'): {
7040 int tmp;
7041 if (size != 13) {
7042 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
7043 return AVERROR_INVALIDDATA;
7044 }
7045 avio_skip(pb, 1); // version
7046 avio_skip(pb, 3); // flags
7047
7048 tmp = avio_r8(pb);
7049 if (tmp == 0)
7050 primary_eye = AV_PRIMARY_EYE_NONE;
7051 else if (tmp == 1)
7052 primary_eye = AV_PRIMARY_EYE_LEFT;
7053 else if (tmp == 2)
7054 primary_eye = AV_PRIMARY_EYE_RIGHT;
7055 else
7056 av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
7057
7058 break;
7059 }
7060 3 case MKTAG('c','a','m','s'): {
7061 uint32_t subtag;
7062 int subsize;
7063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7064 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
7065 return AVERROR_INVALIDDATA;
7066 }
7067
7068 3 subsize = avio_rb32(pb);
7069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7070 av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
7071 return AVERROR_INVALIDDATA;
7072 }
7073
7074 3 subtag = avio_rl32(pb);
7075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
7076 av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got %s\n",
7077 av_fourcc2str(subtag));
7078 return AVERROR_INVALIDDATA;
7079 }
7080
7081 3 avio_skip(pb, 1); // version
7082 3 avio_skip(pb, 3); // flags
7083
7084 3 baseline = avio_rb32(pb);
7085
7086 3 break;
7087 }
7088 3 case MKTAG('c','m','f','y'): {
7089 uint32_t subtag;
7090 int subsize;
7091 int32_t adjustment;
7092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7093 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
7094 return AVERROR_INVALIDDATA;
7095 }
7096
7097 3 subsize = avio_rb32(pb);
7098
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7099 av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
7100 return AVERROR_INVALIDDATA;
7101 }
7102
7103 3 subtag = avio_rl32(pb);
7104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
7105 av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got %s\n",
7106 av_fourcc2str(subtag));
7107 return AVERROR_INVALIDDATA;
7108 }
7109
7110 3 avio_skip(pb, 1); // version
7111 3 avio_skip(pb, 3); // flags
7112
7113 3 adjustment = (int32_t) avio_rb32(pb);
7114
7115 3 horizontal_disparity_adjustment.num = (int) adjustment;
7116 3 horizontal_disparity_adjustment.den = 10000;
7117
7118 3 break;
7119 }
7120 default:
7121 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: %s\n",
7122 av_fourcc2str(tag));
7123 avio_skip(pb, size - 8);
7124 break;
7125 }
7126 9 remaining -= size;
7127 }
7128
7129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7130 av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
7131 return AVERROR_INVALIDDATA;
7132 }
7133
7134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (type == AV_STEREO3D_2D)
7135 return 0;
7136
7137
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->stereo3d) {
7138 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7140 return AVERROR(ENOMEM);
7141 }
7142
7143 3 sc->stereo3d->flags = flags;
7144 3 sc->stereo3d->type = type;
7145 3 sc->stereo3d->view = view;
7146 3 sc->stereo3d->primary_eye = primary_eye;
7147 3 sc->stereo3d->baseline = baseline;
7148 3 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
7149
7150 3 return 0;
7151 }
7152
7153 3 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7154 {
7155 int size;
7156 int64_t remaining;
7157 uint32_t tag;
7158
7159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7160 return 0;
7161
7162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8) {
7163 av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
7164 return AVERROR_INVALIDDATA;
7165 }
7166
7167 3 remaining = atom.size;
7168
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 while (remaining > 0) {
7169 6 size = avio_rb32(pb);
7170
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (size < 8 || size > remaining ) {
7171 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
7172 return AVERROR_INVALIDDATA;
7173 }
7174
7175 6 tag = avio_rl32(pb);
7176
2/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 switch (tag) {
7177 3 case MKTAG('p','r','o','j'): {
7178 3 MOVAtom proj = { tag, size - 8 };
7179 3 int ret = mov_read_vexu_proj(c, pb, proj);
7180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7181 return ret;
7182 3 break;
7183 }
7184 3 case MKTAG('e','y','e','s'): {
7185 3 MOVAtom eyes = { tag, size - 8 };
7186 3 int ret = mov_read_eyes(c, pb, eyes);
7187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7188 return ret;
7189 3 break;
7190 }
7191 case MKTAG('p','a','c','k'): {
7192 MOVAtom pack = { tag, size - 8 };
7193 int ret = mov_read_pack(c, pb, pack);
7194 if (ret < 0)
7195 return ret;
7196 break;
7197 }
7198 default:
7199 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: %s\n",
7200 av_fourcc2str(tag));
7201 avio_skip(pb, size - 8);
7202 break;
7203 }
7204 6 remaining -= size;
7205 }
7206
7207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7208 av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7209 return AVERROR_INVALIDDATA;
7210 }
7211
7212 3 return 0;
7213 }
7214
7215 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7216 {
7217 AVStream *st;
7218 MOVStreamContext *sc;
7219
7220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7221 return 0;
7222
7223 3 st = c->fc->streams[c->fc->nb_streams - 1];
7224 3 sc = st->priv_data;
7225
7226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7227 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7228 return AVERROR_INVALIDDATA;
7229 }
7230
7231
7232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7233 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7234 if (!sc->stereo3d)
7235 return AVERROR(ENOMEM);
7236 }
7237
7238 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7239 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7240
7241 3 return 0;
7242 }
7243
7244 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7245 {
7246 int ret = 0;
7247 uint8_t *buffer = av_malloc(len + 1);
7248 const char *val;
7249
7250 if (!buffer)
7251 return AVERROR(ENOMEM);
7252 buffer[len] = '\0';
7253
7254 ret = ffio_read_size(pb, buffer, len);
7255 if (ret < 0)
7256 goto out;
7257
7258 /* Check for mandatory keys and values, try to support XML as best-effort */
7259 if (!sc->spherical &&
7260 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7261 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7262 av_stristr(val, "true") &&
7263 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7264 av_stristr(val, "true") &&
7265 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7266 av_stristr(val, "equirectangular")) {
7267 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7268 if (!sc->spherical)
7269 goto out;
7270
7271 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7272
7273 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7274 enum AVStereo3DType mode;
7275
7276 if (av_stristr(buffer, "left-right"))
7277 mode = AV_STEREO3D_SIDEBYSIDE;
7278 else if (av_stristr(buffer, "top-bottom"))
7279 mode = AV_STEREO3D_TOPBOTTOM;
7280 else
7281 mode = AV_STEREO3D_2D;
7282
7283 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7284 if (!sc->stereo3d)
7285 goto out;
7286
7287 sc->stereo3d->type = mode;
7288 }
7289
7290 /* orientation */
7291 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7292 if (val)
7293 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7294 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7295 if (val)
7296 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7297 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7298 if (val)
7299 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7300 }
7301
7302 out:
7303 av_free(buffer);
7304 return ret;
7305 }
7306
7307 69 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7308 {
7309 AVStream *st;
7310 MOVStreamContext *sc;
7311 int64_t ret;
7312 AVUUID uuid;
7313 static const AVUUID uuid_isml_manifest = {
7314 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7315 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7316 };
7317 static const AVUUID uuid_xmp = {
7318 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7319 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7320 };
7321 static const AVUUID uuid_spherical = {
7322 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7323 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7324 };
7325
7326
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))
7327 return AVERROR_INVALIDDATA;
7328
7329
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 66 times.
69 if (c->fc->nb_streams < 1)
7330 3 return 0;
7331 66 st = c->fc->streams[c->fc->nb_streams - 1];
7332 66 sc = st->priv_data;
7333
7334 66 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
7336 return ret;
7337
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7338 uint8_t *buffer, *ptr;
7339 char *endptr;
7340 size_t len = atom.size - AV_UUID_LEN;
7341
7342 if (len < 4) {
7343 return AVERROR_INVALIDDATA;
7344 }
7345 ret = avio_skip(pb, 4); // zeroes
7346 len -= 4;
7347
7348 buffer = av_mallocz(len + 1);
7349 if (!buffer) {
7350 return AVERROR(ENOMEM);
7351 }
7352 ret = ffio_read_size(pb, buffer, len);
7353 if (ret < 0) {
7354 av_free(buffer);
7355 return ret;
7356 }
7357
7358 ptr = buffer;
7359 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7360 ptr += sizeof("systemBitrate=\"") - 1;
7361 c->bitrates_count++;
7362 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7363 if (!c->bitrates) {
7364 c->bitrates_count = 0;
7365 av_free(buffer);
7366 return AVERROR(ENOMEM);
7367 }
7368 errno = 0;
7369 ret = strtol(ptr, &endptr, 10);
7370 if (ret < 0 || errno || *endptr != '"') {
7371 c->bitrates[c->bitrates_count - 1] = 0;
7372 } else {
7373 c->bitrates[c->bitrates_count - 1] = ret;
7374 }
7375 }
7376
7377 av_free(buffer);
7378
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7379 uint8_t *buffer;
7380 size_t len = atom.size - AV_UUID_LEN;
7381 if (c->export_xmp) {
7382 buffer = av_mallocz(len + 1);
7383 if (!buffer) {
7384 return AVERROR(ENOMEM);
7385 }
7386 ret = ffio_read_size(pb, buffer, len);
7387 if (ret < 0) {
7388 av_free(buffer);
7389 return ret;
7390 }
7391 buffer[len] = '\0';
7392 av_dict_set(&c->fc->metadata, "xmp",
7393 buffer, AV_DICT_DONT_STRDUP_VAL);
7394 } else {
7395 // skip all uuid atom, which makes it fast for long uuid-xmp file
7396 ret = avio_skip(pb, len);
7397 if (ret < 0)
7398 return ret;
7399 }
7400
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7401 size_t len = atom.size - AV_UUID_LEN;
7402 ret = mov_parse_uuid_spherical(sc, pb, len);
7403 if (ret < 0)
7404 return ret;
7405 if (!sc->spherical)
7406 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7407 }
7408
7409 66 return 0;
7410 }
7411
7412 197 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7413 {
7414 int ret;
7415 uint8_t content[16];
7416
7417
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 99 times.
197 if (atom.size < 8)
7418 98 return 0;
7419
7420 99 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (ret < 0)
7422 return ret;
7423
7424
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 56 times.
99 if ( !c->found_moov
7425
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 23 times.
43 && !c->found_mdat
7426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 && !memcmp(content, "Anevia\x1A\x1A", 8)
7427 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7428 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7429 }
7430
7431 99 return 0;
7432 }
7433
7434 39 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7435 {
7436 39 uint32_t format = avio_rl32(pb);
7437 MOVStreamContext *sc;
7438 enum AVCodecID id;
7439 AVStream *st;
7440
7441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (c->fc->nb_streams < 1)
7442 return 0;
7443 39 st = c->fc->streams[c->fc->nb_streams - 1];
7444 39 sc = st->priv_data;
7445
7446
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 33 times.
39 switch (sc->format)
7447 {
7448 6 case MKTAG('e','n','c','v'): // encrypted video
7449 case MKTAG('e','n','c','a'): // encrypted audio
7450 6 id = mov_codec_id(st, format);
7451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7452 st->codecpar->codec_id != id) {
7453 av_log(c->fc, AV_LOG_WARNING,
7454 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7455 (char*)&format, st->codecpar->codec_id);
7456 break;
7457 }
7458
7459 6 st->codecpar->codec_id = id;
7460 6 sc->format = format;
7461 6 break;
7462
7463 33 default:
7464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (format != sc->format) {
7465 av_log(c->fc, AV_LOG_WARNING,
7466 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7467 (char*)&format, (char*)&sc->format);
7468 }
7469 33 break;
7470 }
7471
7472 39 return 0;
7473 }
7474
7475 /**
7476 * Gets the current encryption info and associated current stream context. If
7477 * we are parsing a track fragment, this will return the specific encryption
7478 * info for this fragment; otherwise this will return the global encryption
7479 * info for the current stream.
7480 */
7481 12 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7482 {
7483 MOVFragmentStreamInfo *frag_stream_info;
7484 AVStream *st;
7485 int i;
7486
7487 12 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7488
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (frag_stream_info) {
7489
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 for (i = 0; i < c->fc->nb_streams; i++) {
7490 6 *sc = c->fc->streams[i]->priv_data;
7491
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if ((*sc)->id == frag_stream_info->id) {
7492 6 st = c->fc->streams[i];
7493 6 break;
7494 }
7495 }
7496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (i == c->fc->nb_streams)
7497 return 0;
7498 6 *sc = st->priv_data;
7499
7500
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (!frag_stream_info->encryption_index) {
7501 // If this stream isn't encrypted, don't create the index.
7502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(*sc)->cenc.default_encrypted_sample)
7503 return 0;
7504 2 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!frag_stream_info->encryption_index)
7506 return AVERROR(ENOMEM);
7507 }
7508 6 *encryption_index = frag_stream_info->encryption_index;
7509 6 return 1;
7510 } else {
7511 // No current track fragment, using stream level encryption info.
7512
7513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (c->fc->nb_streams < 1)
7514 return 0;
7515 6 st = c->fc->streams[c->fc->nb_streams - 1];
7516 6 *sc = st->priv_data;
7517
7518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!(*sc)->cenc.encryption_index) {
7519 // If this stream isn't encrypted, don't create the index.
7520 if (!(*sc)->cenc.default_encrypted_sample)
7521 return 0;
7522 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7523 if (!(*sc)->cenc.encryption_index)
7524 return AVERROR(ENOMEM);
7525 }
7526
7527 6 *encryption_index = (*sc)->cenc.encryption_index;
7528 6 return 1;
7529 }
7530 }
7531
7532 144 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7533 {
7534 int i, ret;
7535 unsigned int subsample_count;
7536 AVSubsampleEncryptionInfo *subsamples;
7537
7538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (!sc->cenc.default_encrypted_sample) {
7539 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7540 return AVERROR_INVALIDDATA;
7541 }
7542
7543
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
144 if (sc->cenc.per_sample_iv_size || use_subsamples) {
7544 144 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7545
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (!*sample)
7546 return AVERROR(ENOMEM);
7547 } else
7548 *sample = NULL;
7549
7550
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 if (sc->cenc.per_sample_iv_size != 0) {
7551
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 144 times.
144 if ((ret = ffio_read_size(pb, (*sample)->iv, sc->cenc.per_sample_iv_size)) < 0) {
7552 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
7553 av_encryption_info_free(*sample);
7554 *sample = NULL;
7555 return ret;
7556 }
7557 }
7558
7559
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 if (use_subsamples) {
7560 144 subsample_count = avio_rb16(pb);
7561 144 av_free((*sample)->subsamples);
7562 144 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
7563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (!(*sample)->subsamples) {
7564 av_encryption_info_free(*sample);
7565 *sample = NULL;
7566 return AVERROR(ENOMEM);
7567 }
7568
7569
3/4
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
288 for (i = 0; i < subsample_count && !pb->eof_reached; i++) {
7570 144 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
7571 144 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
7572 }
7573
7574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (pb->eof_reached) {
7575 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
7576 av_encryption_info_free(*sample);
7577 *sample = NULL;
7578 return AVERROR_INVALIDDATA;
7579 }
7580 144 (*sample)->subsample_count = subsample_count;
7581 }
7582
7583 144 return 0;
7584 }
7585
7586 4 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7587 {
7588 AVEncryptionInfo **encrypted_samples;
7589 MOVEncryptionIndex *encryption_index;
7590 MOVStreamContext *sc;
7591 int use_subsamples, ret;
7592 4 unsigned int sample_count, i, alloc_size = 0;
7593
7594 4 ret = get_current_encryption_info(c, &encryption_index, &sc);
7595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != 1)
7596 return ret;
7597
7598
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (encryption_index->nb_encrypted_samples) {
7599 // This can happen if we have both saio/saiz and senc atoms.
7600 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
7601 2 return 0;
7602 }
7603
7604 2 avio_r8(pb); /* version */
7605 2 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
7606
7607 2 sample_count = avio_rb32(pb);
7608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7609 return AVERROR(ENOMEM);
7610
7611
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 2 times.
98 for (i = 0; i < sample_count; i++) {
7612 96 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7613 96 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7614 min_samples * sizeof(*encrypted_samples));
7615
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 if (encrypted_samples) {
7616 96 encryption_index->encrypted_samples = encrypted_samples;
7617
7618 96 ret = mov_read_sample_encryption_info(
7619 96 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
7620 } else {
7621 ret = AVERROR(ENOMEM);
7622 }
7623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (pb->eof_reached) {
7624 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
7625 if (ret >= 0)
7626 av_encryption_info_free(encryption_index->encrypted_samples[i]);
7627 ret = AVERROR_INVALIDDATA;
7628 }
7629
7630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (ret < 0) {
7631 for (; i > 0; i--)
7632 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7633 av_freep(&encryption_index->encrypted_samples);
7634 return ret;
7635 }
7636 }
7637 2 encryption_index->nb_encrypted_samples = sample_count;
7638
7639 2 return 0;
7640 }
7641
7642 2 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
7643 {
7644 AVEncryptionInfo **sample, **encrypted_samples;
7645 int64_t prev_pos;
7646 size_t sample_count, sample_info_size, i;
7647 2 int ret = 0;
7648 2 unsigned int alloc_size = 0;
7649
7650
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->nb_encrypted_samples)
7651 return 0;
7652 2 sample_count = encryption_index->auxiliary_info_sample_count;
7653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count != 1) {
7654 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
7655 return AVERROR_PATCHWELCOME;
7656 }
7657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7658 return AVERROR(ENOMEM);
7659
7660 2 prev_pos = avio_tell(pb);
7661
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
7662
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]) {
7663 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
7664 goto finish;
7665 }
7666
7667
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++) {
7668 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7669 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7670 min_samples * sizeof(*encrypted_samples));
7671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (!encrypted_samples) {
7672 ret = AVERROR(ENOMEM);
7673 goto finish;
7674 }
7675 48 encryption_index->encrypted_samples = encrypted_samples;
7676
7677 48 sample = &encryption_index->encrypted_samples[i];
7678 96 sample_info_size = encryption_index->auxiliary_info_default_size
7679 48 ? encryption_index->auxiliary_info_default_size
7680
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 : encryption_index->auxiliary_info_sizes[i];
7681
7682 48 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
7683
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0)
7684 goto finish;
7685 }
7686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
7687 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
7688 ret = AVERROR_INVALIDDATA;
7689 } else {
7690 2 encryption_index->nb_encrypted_samples = sample_count;
7691 }
7692
7693 2 finish:
7694 2 avio_seek(pb, prev_pos, SEEK_SET);
7695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
7696 for (; i > 0; i--) {
7697 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7698 }
7699 av_freep(&encryption_index->encrypted_samples);
7700 }
7701 2 return ret;
7702 }
7703
7704 4 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7705 {
7706 MOVEncryptionIndex *encryption_index;
7707 MOVStreamContext *sc;
7708 int ret;
7709 unsigned int sample_count, aux_info_type, aux_info_param;
7710
7711 4 ret = get_current_encryption_info(c, &encryption_index, &sc);
7712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != 1)
7713 return ret;
7714
7715
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (encryption_index->nb_encrypted_samples) {
7716 // This can happen if we have both saio/saiz and senc atoms.
7717 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
7718 2 return 0;
7719 }
7720
7721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_sample_count) {
7722 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
7723 return AVERROR_INVALIDDATA;
7724 }
7725
7726 2 avio_r8(pb); /* version */
7727
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
7728 aux_info_type = avio_rb32(pb);
7729 aux_info_param = avio_rb32(pb);
7730 if (sc->cenc.default_encrypted_sample) {
7731 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7732 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
7733 return 0;
7734 }
7735 if (aux_info_param != 0) {
7736 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
7737 return 0;
7738 }
7739 } else {
7740 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7741 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7742 aux_info_type == MKBETAG('c','e','n','s') ||
7743 aux_info_type == MKBETAG('c','b','c','1') ||
7744 aux_info_type == MKBETAG('c','b','c','s')) &&
7745 aux_info_param == 0) {
7746 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
7747 return AVERROR_INVALIDDATA;
7748 } else {
7749 return 0;
7750 }
7751 }
7752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
7753 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7754 return 0;
7755 }
7756
7757 2 encryption_index->auxiliary_info_default_size = avio_r8(pb);
7758 2 sample_count = avio_rb32(pb);
7759
7760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_default_size == 0) {
7761 if (sample_count == 0)
7762 return AVERROR_INVALIDDATA;
7763
7764 encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
7765 if (!encryption_index->auxiliary_info_sizes)
7766 return AVERROR(ENOMEM);
7767
7768 ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
7769 if (ret != sample_count) {
7770 av_freep(&encryption_index->auxiliary_info_sizes);
7771
7772 if (ret >= 0)
7773 ret = AVERROR_INVALIDDATA;
7774 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
7775 av_err2str(ret));
7776 return ret;
7777 }
7778 }
7779 2 encryption_index->auxiliary_info_sample_count = sample_count;
7780
7781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
7782 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7783 }
7784
7785 2 return 0;
7786 }
7787
7788 4 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7789 {
7790 uint64_t *auxiliary_offsets;
7791 MOVEncryptionIndex *encryption_index;
7792 MOVStreamContext *sc;
7793 int i, ret;
7794 unsigned int version, entry_count, aux_info_type, aux_info_param;
7795 4 unsigned int alloc_size = 0;
7796
7797 4 ret = get_current_encryption_info(c, &encryption_index, &sc);
7798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != 1)
7799 return ret;
7800
7801
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (encryption_index->nb_encrypted_samples) {
7802 // This can happen if we have both saio/saiz and senc atoms.
7803 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
7804 2 return 0;
7805 }
7806
7807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
7808 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
7809 return AVERROR_INVALIDDATA;
7810 }
7811
7812 2 version = avio_r8(pb); /* version */
7813
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
7814 aux_info_type = avio_rb32(pb);
7815 aux_info_param = avio_rb32(pb);
7816 if (sc->cenc.default_encrypted_sample) {
7817 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7818 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
7819 return 0;
7820 }
7821 if (aux_info_param != 0) {
7822 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
7823 return 0;
7824 }
7825 } else {
7826 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7827 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7828 aux_info_type == MKBETAG('c','e','n','s') ||
7829 aux_info_type == MKBETAG('c','b','c','1') ||
7830 aux_info_type == MKBETAG('c','b','c','s')) &&
7831 aux_info_param == 0) {
7832 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
7833 return AVERROR_INVALIDDATA;
7834 } else {
7835 return 0;
7836 }
7837 }
7838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
7839 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7840 return 0;
7841 }
7842
7843 2 entry_count = avio_rb32(pb);
7844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
7845 return AVERROR(ENOMEM);
7846
7847
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++) {
7848
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);
7849 2 auxiliary_offsets = av_fast_realloc(
7850 2 encryption_index->auxiliary_offsets, &alloc_size,
7851 min_offsets * sizeof(*auxiliary_offsets));
7852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!auxiliary_offsets) {
7853 av_freep(&encryption_index->auxiliary_offsets);
7854 return AVERROR(ENOMEM);
7855 }
7856 2 encryption_index->auxiliary_offsets = auxiliary_offsets;
7857
7858
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version == 0) {
7859 2 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
7860 } else {
7861 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
7862 }
7863
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (c->frag_index.current >= 0) {
7864 2 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
7865 }
7866 }
7867
7868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
7869 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
7870 av_freep(&encryption_index->auxiliary_offsets);
7871 return AVERROR_INVALIDDATA;
7872 }
7873
7874 2 encryption_index->auxiliary_offsets_count = entry_count;
7875
7876
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (encryption_index->auxiliary_info_sample_count) {
7877 2 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7878 }
7879
7880 return 0;
7881 }
7882
7883 4 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7884 {
7885 AVEncryptionInitInfo *info, *old_init_info;
7886 uint8_t **key_ids;
7887 AVStream *st;
7888 const AVPacketSideData *old_side_data;
7889 uint8_t *side_data, *extra_data;
7890 size_t side_data_size;
7891 4 int ret = 0;
7892 4 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
7893
7894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
7895 return 0;
7896 4 st = c->fc->streams[c->fc->nb_streams-1];
7897
7898 4 version = avio_r8(pb); /* version */
7899 4 avio_rb24(pb); /* flags */
7900
7901 4 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
7902 /* key_id_size */ 16, /* data_size */ 0);
7903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info)
7904 return AVERROR(ENOMEM);
7905
7906
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
7907 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
7908 goto finish;
7909 }
7910
7911
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (version > 0) {
7912 4 kid_count = avio_rb32(pb);
7913
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
7914 ret = AVERROR(ENOMEM);
7915 goto finish;
7916 }
7917
7918
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++) {
7919 4 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
7920 4 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
7921 min_kid_count * sizeof(*key_ids));
7922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!key_ids) {
7923 ret = AVERROR(ENOMEM);
7924 goto finish;
7925 }
7926 4 info->key_ids = key_ids;
7927
7928 4 info->key_ids[i] = av_mallocz(16);
7929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info->key_ids[i]) {
7930 ret = AVERROR(ENOMEM);
7931 goto finish;
7932 }
7933 4 info->num_key_ids = i + 1;
7934
7935
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
7936 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
7937 goto finish;
7938 }
7939 }
7940
7941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pb->eof_reached) {
7942 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
7943 ret = AVERROR_INVALIDDATA;
7944 goto finish;
7945 }
7946 }
7947
7948 4 extra_data_size = avio_rb32(pb);
7949 4 extra_data = av_malloc(extra_data_size);
7950
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!extra_data) {
7951 ret = AVERROR(ENOMEM);
7952 goto finish;
7953 }
7954 4 ret = avio_read(pb, extra_data, extra_data_size);
7955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != extra_data_size) {
7956 av_free(extra_data);
7957
7958 if (ret >= 0)
7959 ret = AVERROR_INVALIDDATA;
7960 goto finish;
7961 }
7962
7963 4 av_freep(&info->data); // malloc(0) may still allocate something.
7964 4 info->data = extra_data;
7965 4 info->data_size = extra_data_size;
7966
7967 // If there is existing initialization data, append to the list.
7968 4 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
7969 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
7970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (old_side_data) {
7971 old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
7972 if (old_init_info) {
7973 // Append to the end of the list.
7974 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
7975 if (!cur->next) {
7976 cur->next = info;
7977 break;
7978 }
7979 }
7980 info = old_init_info;
7981 } else {
7982 // Assume existing side-data will be valid, so the only error we could get is OOM.
7983 ret = AVERROR(ENOMEM);
7984 goto finish;
7985 }
7986 }
7987
7988 4 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
7989
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!side_data) {
7990 ret = AVERROR(ENOMEM);
7991 goto finish;
7992 }
7993
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
7994 4 &st->codecpar->nb_coded_side_data,
7995 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
7996 side_data, side_data_size, 0))
7997 av_free(side_data);
7998
7999 4 finish:
8000 4 av_encryption_init_info_free(info);
8001 4 return ret;
8002 }
8003
8004 6 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8005 {
8006 AVStream *st;
8007 MOVStreamContext *sc;
8008
8009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (c->fc->nb_streams < 1)
8010 return 0;
8011 6 st = c->fc->streams[c->fc->nb_streams-1];
8012 6 sc = st->priv_data;
8013
8014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (sc->pseudo_stream_id != 0) {
8015 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
8016 return AVERROR_PATCHWELCOME;
8017 }
8018
8019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 8)
8020 return AVERROR_INVALIDDATA;
8021
8022 6 avio_rb32(pb); /* version and flags */
8023
8024
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (!sc->cenc.default_encrypted_sample) {
8025 6 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8026
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc->cenc.default_encrypted_sample) {
8027 return AVERROR(ENOMEM);
8028 }
8029 }
8030
8031 6 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
8032 6 return 0;
8033 }
8034
8035 6 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8036 {
8037 AVStream *st;
8038 MOVStreamContext *sc;
8039 unsigned int version, pattern, is_protected, iv_size;
8040
8041
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (c->fc->nb_streams < 1)
8042 return 0;
8043 6 st = c->fc->streams[c->fc->nb_streams-1];
8044 6 sc = st->priv_data;
8045
8046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (sc->pseudo_stream_id != 0) {
8047 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
8048 return AVERROR_PATCHWELCOME;
8049 }
8050
8051
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc->cenc.default_encrypted_sample) {
8052 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8053 if (!sc->cenc.default_encrypted_sample) {
8054 return AVERROR(ENOMEM);
8055 }
8056 }
8057
8058
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 20)
8059 return AVERROR_INVALIDDATA;
8060
8061 6 version = avio_r8(pb); /* version */
8062 6 avio_rb24(pb); /* flags */
8063
8064 6 avio_r8(pb); /* reserved */
8065 6 pattern = avio_r8(pb);
8066
8067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version > 0) {
8068 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
8069 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
8070 }
8071
8072 6 is_protected = avio_r8(pb);
8073
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 if (is_protected && !sc->cenc.encryption_index) {
8074 // The whole stream should be by-default encrypted.
8075 6 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
8076
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc->cenc.encryption_index)
8077 return AVERROR(ENOMEM);
8078 }
8079 6 sc->cenc.per_sample_iv_size = avio_r8(pb);
8080
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
6 if (sc->cenc.per_sample_iv_size != 0 && sc->cenc.per_sample_iv_size != 8 &&
8081 sc->cenc.per_sample_iv_size != 16) {
8082 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
8083 return AVERROR_INVALIDDATA;
8084 }
8085
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (avio_read(pb, sc->cenc.default_encrypted_sample->key_id, 16) != 16) {
8086 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
8087 return AVERROR_INVALIDDATA;
8088 }
8089
8090
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
6 if (is_protected && !sc->cenc.per_sample_iv_size) {
8091 2 iv_size = avio_r8(pb);
8092
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) {
8093 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
8094 return AVERROR_INVALIDDATA;
8095 }
8096
8097
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) {
8098 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
8099 return AVERROR_INVALIDDATA;
8100 }
8101 }
8102
8103 6 return 0;
8104 }
8105
8106 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8107 {
8108 AVStream *st;
8109 int last, type, size, ret;
8110 uint8_t buf[4];
8111
8112 if (c->fc->nb_streams < 1)
8113 return 0;
8114 st = c->fc->streams[c->fc->nb_streams-1];
8115
8116 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
8117 return AVERROR_INVALIDDATA;
8118
8119 /* Check FlacSpecificBox version. */
8120 if (avio_r8(pb) != 0)
8121 return AVERROR_INVALIDDATA;
8122
8123 avio_rb24(pb); /* Flags */
8124
8125 if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
8126 av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
8127 return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
8128 }
8129 flac_parse_block_header(buf, &last, &type, &size);
8130
8131 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
8132 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
8133 return AVERROR_INVALIDDATA;
8134 }
8135
8136 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
8137 if (ret < 0)
8138 return ret;
8139
8140 if (!last)
8141 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
8142
8143 return 0;
8144 }
8145
8146 6 static int get_key_from_kid(uint8_t* out, int len, MOVContext *c, AVEncryptionInfo *sample) {
8147 AVDictionaryEntry *key_entry_hex;
8148 char kid_hex[16*2+1];
8149
8150
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
6 if (c->decryption_default_key && c->decryption_default_key_len != len) {
8151 av_log(c->fc, AV_LOG_ERROR, "invalid default decryption key length: got %d, expected %d\n", c->decryption_default_key_len, len);
8152 return -1;
8153 }
8154
8155
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (!c->decryption_keys) {
8156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 av_assert0(c->decryption_default_key);
8157 3 memcpy(out, c->decryption_default_key, len);
8158 3 return 0;
8159 }
8160
8161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sample->key_id_size != 16) {
8162 av_log(c->fc, AV_LOG_ERROR, "invalid key ID size: got %u, expected 16\n", sample->key_id_size);
8163 return -1;
8164 }
8165
8166 3 ff_data_to_hex(kid_hex, sample->key_id, 16, 1);
8167 3 key_entry_hex = av_dict_get(c->decryption_keys, kid_hex, NULL, AV_DICT_DONT_STRDUP_KEY|AV_DICT_DONT_STRDUP_VAL);
8168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!key_entry_hex) {
8169 if (!c->decryption_default_key) {
8170 av_log(c->fc, AV_LOG_ERROR, "unable to find KID %s\n", kid_hex);
8171 return -1;
8172 }
8173 memcpy(out, c->decryption_default_key, len);
8174 return 0;
8175 }
8176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (strlen(key_entry_hex->value) != len*2) {
8177 return -1;
8178 }
8179 3 ff_hex_to_data(out, key_entry_hex->value);
8180 3 return 0;
8181 }
8182
8183 292 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8184 {
8185 int i, ret;
8186 int bytes_of_protected_data;
8187 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8188
8189
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 286 times.
292 if (!sc->cenc.aes_ctr) {
8190 6 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0) {
8192 return ret;
8193 }
8194
8195 /* initialize the cipher */
8196 6 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc->cenc.aes_ctr) {
8198 return AVERROR(ENOMEM);
8199 }
8200
8201 6 ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0) {
8203 return ret;
8204 }
8205 }
8206
8207 292 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8208
8209
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 196 times.
292 if (!sample->subsample_count) {
8210 /* decrypt the whole packet */
8211 96 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8212 96 return 0;
8213 }
8214
8215
2/2
✓ Branch 0 taken 196 times.
✓ Branch 1 taken 196 times.
392 for (i = 0; i < sample->subsample_count; i++) {
8216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8217 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8218 return AVERROR_INVALIDDATA;
8219 }
8220
8221 /* skip the clear bytes */
8222 196 input += sample->subsamples[i].bytes_of_clear_data;
8223 196 size -= sample->subsamples[i].bytes_of_clear_data;
8224
8225 /* decrypt the encrypted bytes */
8226
8227 196 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
8228 196 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
8229
8230 196 input += bytes_of_protected_data;
8231 196 size -= bytes_of_protected_data;
8232 }
8233
8234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 if (size > 0) {
8235 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8236 return AVERROR_INVALIDDATA;
8237 }
8238
8239 196 return 0;
8240 }
8241
8242 static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8243 {
8244 int i, ret;
8245 int num_of_encrypted_blocks;
8246 uint8_t iv[16];
8247 uint8_t decryption_key[16];
8248
8249 if (!sc->cenc.aes_ctx) {
8250 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8251 if (ret < 0) {
8252 return ret;
8253 }
8254
8255 /* initialize the cipher */
8256 sc->cenc.aes_ctx = av_aes_alloc();
8257 if (!sc->cenc.aes_ctx) {
8258 return AVERROR(ENOMEM);
8259 }
8260
8261 ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8262 if (ret < 0) {
8263 return ret;
8264 }
8265 }
8266
8267 memcpy(iv, sample->iv, 16);
8268
8269 /* whole-block full sample encryption */
8270 if (!sample->subsample_count) {
8271 /* decrypt the whole packet */
8272 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8273 return 0;
8274 }
8275
8276 for (i = 0; i < sample->subsample_count; i++) {
8277 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8278 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8279 return AVERROR_INVALIDDATA;
8280 }
8281
8282 if (sample->subsamples[i].bytes_of_protected_data % 16) {
8283 av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8284 return AVERROR_INVALIDDATA;
8285 }
8286
8287 /* skip the clear bytes */
8288 input += sample->subsamples[i].bytes_of_clear_data;
8289 size -= sample->subsamples[i].bytes_of_clear_data;
8290
8291 /* decrypt the encrypted bytes */
8292 num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8293 if (num_of_encrypted_blocks > 0) {
8294 av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8295 }
8296 input += sample->subsamples[i].bytes_of_protected_data;
8297 size -= sample->subsamples[i].bytes_of_protected_data;
8298 }
8299
8300 if (size > 0) {
8301 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8302 return AVERROR_INVALIDDATA;
8303 }
8304
8305 return 0;
8306 }
8307
8308 static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8309 {
8310 int i, ret, rem_bytes;
8311 uint8_t *data;
8312 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8313
8314 if (!sc->cenc.aes_ctr) {
8315 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8316 if (ret < 0) {
8317 return ret;
8318 }
8319
8320 /* initialize the cipher */
8321 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8322 if (!sc->cenc.aes_ctr) {
8323 return AVERROR(ENOMEM);
8324 }
8325
8326 ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8327 if (ret < 0) {
8328 return ret;
8329 }
8330 }
8331
8332 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8333
8334 /* whole-block full sample encryption */
8335 if (!sample->subsample_count) {
8336 /* decrypt the whole packet */
8337 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8338 return 0;
8339 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8340 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8341 return AVERROR_INVALIDDATA;
8342 }
8343
8344 for (i = 0; i < sample->subsample_count; i++) {
8345 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8346 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8347 return AVERROR_INVALIDDATA;
8348 }
8349
8350 /* skip the clear bytes */
8351 input += sample->subsamples[i].bytes_of_clear_data;
8352 size -= sample->subsamples[i].bytes_of_clear_data;
8353
8354 /* decrypt the encrypted bytes */
8355 data = input;
8356 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8357 while (rem_bytes > 0) {
8358 if (rem_bytes < 16*sample->crypt_byte_block) {
8359 break;
8360 }
8361 av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8362 data += 16*sample->crypt_byte_block;
8363 rem_bytes -= 16*sample->crypt_byte_block;
8364 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8365 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8366 }
8367 input += sample->subsamples[i].bytes_of_protected_data;
8368 size -= sample->subsamples[i].bytes_of_protected_data;
8369 }
8370
8371 if (size > 0) {
8372 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8373 return AVERROR_INVALIDDATA;
8374 }
8375
8376 return 0;
8377 }
8378
8379 static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8380 {
8381 int i, ret, rem_bytes;
8382 uint8_t iv[16];
8383 uint8_t *data;
8384 uint8_t decryption_key[16];
8385
8386 if (!sc->cenc.aes_ctx) {
8387 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8388 if (ret < 0) {
8389 return ret;
8390 }
8391
8392 /* initialize the cipher */
8393 sc->cenc.aes_ctx = av_aes_alloc();
8394 if (!sc->cenc.aes_ctx) {
8395 return AVERROR(ENOMEM);
8396 }
8397
8398 ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8399 if (ret < 0) {
8400 return ret;
8401 }
8402 }
8403
8404 /* whole-block full sample encryption */
8405 if (!sample->subsample_count) {
8406 /* decrypt the whole packet */
8407 memcpy(iv, sample->iv, 16);
8408 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8409 return 0;
8410 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8411 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8412 return AVERROR_INVALIDDATA;
8413 }
8414
8415 for (i = 0; i < sample->subsample_count; i++) {
8416 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8417 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8418 return AVERROR_INVALIDDATA;
8419 }
8420
8421 /* skip the clear bytes */
8422 input += sample->subsamples[i].bytes_of_clear_data;
8423 size -= sample->subsamples[i].bytes_of_clear_data;
8424
8425 /* decrypt the encrypted bytes */
8426 memcpy(iv, sample->iv, 16);
8427 data = input;
8428 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8429 while (rem_bytes > 0) {
8430 if (rem_bytes < 16*sample->crypt_byte_block) {
8431 break;
8432 }
8433 av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8434 data += 16*sample->crypt_byte_block;
8435 rem_bytes -= 16*sample->crypt_byte_block;
8436 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8437 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8438 }
8439 input += sample->subsamples[i].bytes_of_protected_data;
8440 size -= sample->subsamples[i].bytes_of_protected_data;
8441 }
8442
8443 if (size > 0) {
8444 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8445 return AVERROR_INVALIDDATA;
8446 }
8447
8448 return 0;
8449 }
8450
8451 292 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8452 {
8453
3/6
✓ Branch 0 taken 292 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 292 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 292 times.
✗ Branch 5 not taken.
292 if (sample->scheme == MKBETAG('c','e','n','c') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8454 292 return cenc_scheme_decrypt(c, sc, sample, input, size);
8455 } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8456 return cbc1_scheme_decrypt(c, sc, sample, input, size);
8457 } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8458 return cens_scheme_decrypt(c, sc, sample, input, size);
8459 } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8460 return cbcs_scheme_decrypt(c, sc, sample, input, size);
8461 } else {
8462 av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8463 return AVERROR_INVALIDDATA;
8464 }
8465 }
8466
8467 97287 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8468 {
8469 97287 int current = frag_index->current;
8470
8471
2/2
✓ Branch 0 taken 96310 times.
✓ Branch 1 taken 977 times.
97287 if (!frag_index->nb_items)
8472 96310 return NULL;
8473
8474 // Check frag_index->current is the right one for pkt. It can out of sync.
8475
2/4
✓ Branch 0 taken 977 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 977 times.
✗ Branch 3 not taken.
977 if (current >= 0 && current < frag_index->nb_items) {
8476
2/2
✓ Branch 0 taken 951 times.
✓ Branch 1 taken 26 times.
977 if (frag_index->item[current].moof_offset < pkt->pos &&
8477
2/2
✓ Branch 0 taken 609 times.
✓ Branch 1 taken 342 times.
951 (current + 1 == frag_index->nb_items ||
8478
2/2
✓ Branch 0 taken 534 times.
✓ Branch 1 taken 75 times.
609 frag_index->item[current + 1].moof_offset > pkt->pos))
8479 876 return get_frag_stream_info(frag_index, current, id);
8480 }
8481
8482
8483
2/2
✓ Branch 0 taken 4553 times.
✓ Branch 1 taken 8 times.
4561 for (int i = 0; i < frag_index->nb_items; i++) {
8484
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 4460 times.
4553 if (frag_index->item[i].moof_offset > pkt->pos)
8485 93 break;
8486 4460 current = i;
8487 }
8488 101 frag_index->current = current;
8489 101 return get_frag_stream_info(frag_index, current, id);
8490 }
8491
8492 97287 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8493 {
8494 MOVFragmentStreamInfo *frag_stream_info;
8495 MOVEncryptionIndex *encryption_index;
8496 AVEncryptionInfo *encrypted_sample;
8497 int encrypted_index, ret;
8498
8499 97287 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8500 97287 encrypted_index = current_index;
8501 97287 encryption_index = NULL;
8502
2/2
✓ Branch 0 taken 977 times.
✓ Branch 1 taken 96310 times.
97287 if (frag_stream_info) {
8503 // Note this only supports encryption info in the first sample descriptor.
8504
2/2
✓ Branch 0 taken 929 times.
✓ Branch 1 taken 48 times.
977 if (frag_stream_info->stsd_id == 1) {
8505
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 881 times.
929 if (frag_stream_info->encryption_index) {
8506 48 encrypted_index = current_index - frag_stream_info->index_base;
8507 48 encryption_index = frag_stream_info->encryption_index;
8508 } else {
8509 881 encryption_index = sc->cenc.encryption_index;
8510 }
8511 }
8512 } else {
8513 96310 encryption_index = sc->cenc.encryption_index;
8514 }
8515
8516
2/2
✓ Branch 0 taken 292 times.
✓ Branch 1 taken 96995 times.
97287 if (encryption_index) {
8517
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 244 times.
292 if (encryption_index->auxiliary_info_sample_count &&
8518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8519 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8520 return AVERROR_INVALIDDATA;
8521 }
8522
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 244 times.
292 if (encryption_index->auxiliary_offsets_count &&
8523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8524 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8525 return AVERROR_INVALIDDATA;
8526 }
8527
8528 292 encrypted_sample = NULL;
8529
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 196 times.
292 if (!encryption_index->nb_encrypted_samples) {
8530 // Full-sample encryption with default settings.
8531 96 encrypted_sample = sc->cenc.default_encrypted_sample;
8532
2/4
✓ Branch 0 taken 196 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 196 times.
✗ Branch 3 not taken.
196 } else if (encrypted_index >= 0 && encrypted_index < encryption_index->nb_encrypted_samples) {
8533 // Per-sample setting override.
8534 196 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 if (!encrypted_sample) {
8536 encrypted_sample = sc->cenc.default_encrypted_sample;
8537 }
8538 }
8539
8540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 292 times.
292 if (!encrypted_sample) {
8541 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8542 return AVERROR_INVALIDDATA;
8543 }
8544
8545
3/4
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 146 times.
✓ Branch 2 taken 146 times.
✗ Branch 3 not taken.
292 if (mov->decryption_keys || mov->decryption_default_key) {
8546 292 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
8547 } else {
8548 size_t size;
8549 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
8550 if (!side_data)
8551 return AVERROR(ENOMEM);
8552 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
8553 if (ret < 0)
8554 av_free(side_data);
8555 return ret;
8556 }
8557 }
8558
8559 96995 return 0;
8560 }
8561
8562 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8563 {
8564 const int OPUS_SEEK_PREROLL_MS = 80;
8565 int ret;
8566 AVStream *st;
8567 size_t size;
8568 uint16_t pre_skip;
8569
8570 if (c->fc->nb_streams < 1)
8571 return 0;
8572 st = c->fc->streams[c->fc->nb_streams-1];
8573
8574 if ((uint64_t)atom.size > (1<<30) || atom.size < 11)
8575 return AVERROR_INVALIDDATA;
8576
8577 /* Check OpusSpecificBox version. */
8578 if (avio_r8(pb) != 0) {
8579 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
8580 return AVERROR_INVALIDDATA;
8581 }
8582
8583 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
8584 size = atom.size + 8;
8585
8586 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
8587 return ret;
8588
8589 AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
8590 AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
8591 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
8592 avio_read(pb, st->codecpar->extradata + 9, size - 9);
8593
8594 /* OpusSpecificBox is stored in big-endian, but OpusHead is
8595 little-endian; aside from the preceding magic and version they're
8596 otherwise currently identical. Data after output gain at offset 16
8597 doesn't need to be bytewapped. */
8598 pre_skip = AV_RB16A(st->codecpar->extradata + 10);
8599 AV_WL16A(st->codecpar->extradata + 10, pre_skip);
8600 AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
8601 AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
8602
8603 st->codecpar->initial_padding = pre_skip;
8604 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
8605 (AVRational){1, 1000},
8606 (AVRational){1, 48000});
8607
8608 return 0;
8609 }
8610
8611 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8612 {
8613 AVStream *st;
8614 unsigned format_info;
8615 int channel_assignment, channel_assignment1, channel_assignment2;
8616 int ratebits;
8617 uint64_t chmask;
8618
8619 if (c->fc->nb_streams < 1)
8620 return 0;
8621 st = c->fc->streams[c->fc->nb_streams-1];
8622
8623 if (atom.size < 10)
8624 return AVERROR_INVALIDDATA;
8625
8626 format_info = avio_rb32(pb);
8627
8628 ratebits = (format_info >> 28) & 0xF;
8629 channel_assignment1 = (format_info >> 15) & 0x1F;
8630 channel_assignment2 = format_info & 0x1FFF;
8631 if (channel_assignment2)
8632 channel_assignment = channel_assignment2;
8633 else
8634 channel_assignment = channel_assignment1;
8635
8636 st->codecpar->frame_size = 40 << (ratebits & 0x7);
8637 st->codecpar->sample_rate = mlp_samplerate(ratebits);
8638
8639 av_channel_layout_uninit(&st->codecpar->ch_layout);
8640 chmask = truehd_layout(channel_assignment);
8641 av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
8642
8643 return 0;
8644 }
8645
8646 4 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8647 {
8648 AVStream *st;
8649 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
8650 int ret;
8651 4 int64_t read_size = atom.size;
8652
8653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8654 return 0;
8655 4 st = c->fc->streams[c->fc->nb_streams-1];
8656
8657 // At most 24 bytes
8658 4 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
8659
8660
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
8661 return ret;
8662
8663 4 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
8664 }
8665
8666 4 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8667 {
8668 AVStream *st;
8669 uint8_t *buf;
8670 int ret, old_size, num_arrays;
8671
8672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8673 return 0;
8674 4 st = c->fc->streams[c->fc->nb_streams-1];
8675
8676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!st->codecpar->extradata_size)
8677 // TODO: handle lhvC when present before hvcC
8678 return 0;
8679
8680
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (atom.size < 6 || st->codecpar->extradata_size < 23)
8681 return AVERROR_INVALIDDATA;
8682
8683 4 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
8684
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!buf)
8685 return AVERROR(ENOMEM);
8686 4 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8687
8688 4 ret = ffio_read_size(pb, buf, atom.size);
8689
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
8690 av_free(buf);
8691 av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
8692 return 0;
8693 }
8694
8695 4 num_arrays = buf[5];
8696 4 old_size = st->codecpar->extradata_size;
8697 4 atom.size -= 8 /* account for mov_realloc_extradata offsetting */
8698 + 6 /* lhvC bytes before the arrays*/;
8699
8700 4 ret = mov_realloc_extradata(st->codecpar, atom);
8701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
8702 av_free(buf);
8703 return ret;
8704 }
8705
8706 4 st->codecpar->extradata[22] += num_arrays;
8707 4 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
8708
8709 4 st->disposition |= AV_DISPOSITION_MULTILAYER;
8710
8711 4 av_free(buf);
8712 4 return 0;
8713 }
8714
8715 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8716 {
8717 4 AVFormatContext *ctx = c->fc;
8718 4 AVStream *st = NULL;
8719 AVBPrint scheme_buf, value_buf;
8720 4 int64_t scheme_str_len = 0, value_str_len = 0;
8721 4 int version, flags, ret = AVERROR_BUG;
8722 4 int64_t size = atom.size;
8723
8724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
8725 // 4 bytes for version + flags, 2x 1 byte for null
8726 return AVERROR_INVALIDDATA;
8727
8728
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8729 return 0;
8730 4 st = c->fc->streams[c->fc->nb_streams-1];
8731
8732 4 version = avio_r8(pb);
8733 4 flags = avio_rb24(pb);
8734 4 size -= 4;
8735
8736
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) {
8737 av_log(ctx, AV_LOG_ERROR,
8738 "Unsupported 'kind' box with version %d, flags: %x",
8739 version, flags);
8740 return AVERROR_INVALIDDATA;
8741 }
8742
8743 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8744 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8745
8746
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,
8747 size)) < 0) {
8748 ret = scheme_str_len;
8749 goto cleanup;
8750 }
8751
8752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
8753 // we need to have another string, even if nullptr.
8754 // we check with + 1 since we expect that if size was not hit,
8755 // an additional null was read.
8756 ret = AVERROR_INVALIDDATA;
8757 goto cleanup;
8758 }
8759
8760 4 size -= scheme_str_len + 1;
8761
8762
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,
8763 size)) < 0) {
8764 ret = value_str_len;
8765 goto cleanup;
8766 }
8767
8768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
8769 // in case of no trailing null, box is not valid.
8770 ret = AVERROR_INVALIDDATA;
8771 goto cleanup;
8772 }
8773
8774 4 av_log(ctx, AV_LOG_TRACE,
8775 "%s stream %d KindBox(scheme: %s, value: %s)\n",
8776 4 av_get_media_type_string(st->codecpar->codec_type),
8777 st->index,
8778 scheme_buf.str, value_buf.str);
8779
8780
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++) {
8781 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
8782
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
8783 continue;
8784
8785
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
8786 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
8787
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
8788 16 continue;
8789
8790 4 st->disposition |= value_map.disposition;
8791 }
8792 }
8793
8794 4 ret = 0;
8795
8796 4 cleanup:
8797
8798 4 av_bprint_finalize(&scheme_buf, NULL);
8799 4 av_bprint_finalize(&value_buf, NULL);
8800
8801 4 return ret;
8802 }
8803
8804 static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8805 {
8806 AVStream *st;
8807 AVChannelLayout ch_layout = { 0 };
8808 int ret, i, version, type;
8809 int ambisonic_order, channel_order, normalization, channel_count;
8810 int ambi_channels, non_diegetic_channels;
8811
8812 if (c->fc->nb_streams < 1)
8813 return 0;
8814
8815 st = c->fc->streams[c->fc->nb_streams - 1];
8816
8817 if (atom.size < 16) {
8818 av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
8819 return AVERROR_INVALIDDATA;
8820 }
8821
8822 version = avio_r8(pb);
8823 if (version) {
8824 av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
8825 return 0;
8826 }
8827
8828 type = avio_r8(pb);
8829 if (type & 0x7f) {
8830 av_log(c->fc, AV_LOG_WARNING,
8831 "Unsupported ambisonic type %d\n", type & 0x7f);
8832 return 0;
8833 }
8834 non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
8835
8836 ambisonic_order = avio_rb32(pb);
8837
8838 channel_order = avio_r8(pb);
8839 if (channel_order) {
8840 av_log(c->fc, AV_LOG_WARNING,
8841 "Unsupported channel_order %d\n", channel_order);
8842 return 0;
8843 }
8844
8845 normalization = avio_r8(pb);
8846 if (normalization) {
8847 av_log(c->fc, AV_LOG_WARNING,
8848 "Unsupported normalization %d\n", normalization);
8849 return 0;
8850 }
8851
8852 channel_count = avio_rb32(pb);
8853 if (ambisonic_order < 0 || ambisonic_order > 31 ||
8854 channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
8855 non_diegetic_channels)) {
8856 av_log(c->fc, AV_LOG_ERROR,
8857 "Invalid number of channels (%d / %d)\n",
8858 channel_count, ambisonic_order);
8859 return 0;
8860 }
8861 ambi_channels = channel_count - non_diegetic_channels;
8862
8863 ret = av_channel_layout_custom_init(&ch_layout, channel_count);
8864 if (ret < 0)
8865 return 0;
8866
8867 for (i = 0; i < channel_count; i++) {
8868 unsigned channel = avio_rb32(pb);
8869
8870 if (channel >= channel_count) {
8871 av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
8872 channel, ambisonic_order);
8873 av_channel_layout_uninit(&ch_layout);
8874 return 0;
8875 }
8876 if (channel >= ambi_channels)
8877 ch_layout.u.map[i].id = channel - ambi_channels;
8878 else
8879 ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
8880 }
8881
8882 ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
8883 if (ret < 0) {
8884 av_channel_layout_uninit(&ch_layout);
8885 return 0;
8886 }
8887
8888 av_channel_layout_uninit(&st->codecpar->ch_layout);
8889 st->codecpar->ch_layout = ch_layout;
8890
8891 return 0;
8892 }
8893
8894 static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8895 {
8896 AVStream *st;
8897 int version;
8898
8899 if (c->fc->nb_streams < 1)
8900 return 0;
8901
8902 st = c->fc->streams[c->fc->nb_streams - 1];
8903
8904 if (atom.size < 5) {
8905 av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
8906 return AVERROR_INVALIDDATA;
8907 }
8908
8909 version = avio_r8(pb);
8910 if (version) {
8911 av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
8912 return 0;
8913 }
8914
8915 st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
8916
8917 return 0;
8918 }
8919
8920 171 static int rb_size(AVIOContext *pb, int64_t *value, int size)
8921 {
8922
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 160 times.
171 if (size == 0)
8923 11 *value = 0;
8924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 else if (size == 1)
8925 *value = avio_r8(pb);
8926
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 else if (size == 2)
8927 *value = avio_rb16(pb);
8928
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 else if (size == 4)
8929 160 *value = avio_rb32(pb);
8930 else if (size == 8) {
8931 *value = avio_rb64(pb);
8932 if (*value < 0)
8933 return -1;
8934 } else
8935 return -1;
8936 171 return size;
8937 }
8938
8939 18 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8940 {
8941 18 avio_rb32(pb); // version & flags.
8942 18 c->primary_item_id = avio_rb16(pb);
8943 18 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
8944 18 return atom.size;
8945 }
8946
8947 9 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8948 {
8949 9 c->idat_offset = avio_tell(pb);
8950 9 return 0;
8951 }
8952
8953 18 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8954 {
8955 HEIFItem **heif_item;
8956 int version, offset_size, length_size, base_offset_size, index_size;
8957 int item_count, extent_count;
8958 int64_t base_offset, extent_offset, extent_length;
8959 uint8_t value;
8960
8961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->found_iloc) {
8962 av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
8963 return 0;
8964 }
8965
8966 18 version = avio_r8(pb);
8967 18 avio_rb24(pb); // flags.
8968
8969 18 value = avio_r8(pb);
8970 18 offset_size = (value >> 4) & 0xF;
8971 18 length_size = value & 0xF;
8972 18 value = avio_r8(pb);
8973 18 base_offset_size = (value >> 4) & 0xF;
8974
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 7 times.
18 index_size = !version ? 0 : (value & 0xF);
8975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (index_size) {
8976 avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
8977 return AVERROR_PATCHWELCOME;
8978 }
8979
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8980
8981 18 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
8982
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!heif_item)
8983 return AVERROR(ENOMEM);
8984 18 c->heif_item = heif_item;
8985
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (item_count > c->nb_heif_item)
8986 18 memset(&c->heif_item[c->nb_heif_item], 0,
8987 18 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
8988 18 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
8989
8990 18 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
8991
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (int i = 0; i < item_count; i++) {
8992 57 HEIFItem *item = NULL;
8993
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8994
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 12 times.
57 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
8995 int j;
8996
8997
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (avio_feof(pb))
8998 return AVERROR_INVALIDDATA;
8999
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (offset_type > 1) {
9000 avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
9001 return AVERROR_PATCHWELCOME;
9002 }
9003
9004 57 avio_rb16(pb); // data_reference_index.
9005
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (rb_size(pb, &base_offset, base_offset_size) < 0)
9006 return AVERROR_INVALIDDATA;
9007 57 extent_count = avio_rb16(pb);
9008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (extent_count > 1) {
9009 // For still AVIF images, we only support one extent item.
9010 avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
9011 return AVERROR_PATCHWELCOME;
9012 }
9013
9014
2/4
✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 57 times.
✗ Branch 4 not taken.
114 if (rb_size(pb, &extent_offset, offset_size) < 0 ||
9015 57 rb_size(pb, &extent_length, length_size) < 0 ||
9016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 base_offset > INT64_MAX - extent_offset)
9017 return AVERROR_INVALIDDATA;
9018
9019
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 for (j = 0; j < c->nb_heif_item; j++) {
9020 140 item = c->heif_item[j];
9021
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 83 times.
140 if (!item)
9022 57 item = c->heif_item[j] = av_mallocz(sizeof(*item));
9023
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
83 else if (item->item_id != item_id)
9024 83 continue;
9025 57 break;
9026 }
9027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item)
9028 return AVERROR(ENOMEM);
9029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (j == c->nb_heif_item)
9030 return AVERROR_INVALIDDATA;
9031
9032 57 item->item_id = item_id;
9033
9034
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 48 times.
57 if (offset_type == 1)
9035 9 item->is_idat_relative = 1;
9036 57 item->extent_length = extent_length;
9037 57 item->extent_offset = base_offset + extent_offset;
9038 57 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, item->item_id %d, offset_type %d, "
9039 "extent_offset %"PRId64", extent_length %"PRId64"\n",
9040 i, item->item_id, offset_type, item->extent_offset, item->extent_length);
9041 }
9042
9043 18 c->found_iloc = 1;
9044 18 return atom.size;
9045 }
9046
9047 57 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9048 {
9049 57 HEIFItem *item = NULL;
9050 AVBPrint item_name;
9051 57 int64_t size = atom.size;
9052 uint32_t item_type;
9053 int item_id;
9054 int i, version, ret;
9055
9056 57 version = avio_r8(pb);
9057 57 avio_rb24(pb); // flags.
9058 57 size -= 4;
9059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (size < 0)
9060 return AVERROR_INVALIDDATA;
9061
9062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (version < 2) {
9063 avpriv_report_missing_feature(c->fc, "infe version < 2");
9064 avio_skip(pb, size);
9065 return 1;
9066 }
9067
9068
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
9069 57 avio_rb16(pb); // item_protection_index
9070 57 item_type = avio_rl32(pb);
9071 57 size -= 8;
9072
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (size < 1)
9073 return AVERROR_INVALIDDATA;
9074
9075 57 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
9076 57 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
9077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (ret < 0) {
9078 av_bprint_finalize(&item_name, NULL);
9079 return ret;
9080 }
9081
9082 57 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
9083 57 item_id, av_fourcc2str(item_type), item_name.str);
9084
9085 57 size -= ret + 1;
9086
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 55 times.
57 if (size > 0)
9087 2 avio_skip(pb, size);
9088
9089
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 for (i = 0; i < c->nb_heif_item; i++) {
9090 140 item = c->heif_item[i];
9091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (!item)
9092 item = c->heif_item[i] = av_mallocz(sizeof(*item));
9093
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 57 times.
140 else if (item->item_id != item_id)
9094 83 continue;
9095 57 break;
9096 }
9097
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item) {
9098 av_bprint_finalize(&item_name, NULL);
9099 return AVERROR(ENOMEM);
9100 }
9101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (i == c->nb_heif_item) {
9102 av_bprint_finalize(&item_name, NULL);
9103 return AVERROR_INVALIDDATA;
9104 }
9105
9106 57 av_freep(&item->name);
9107
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 1 times.
57 av_bprint_finalize(&item_name, ret ? &item->name : NULL);
9108 57 item->item_id = item_id;
9109 57 item->type = item_type;
9110
9111
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 14 times.
57 switch (item_type) {
9112 43 case MKTAG('a','v','0','1'):
9113 case MKTAG('j','p','e','g'):
9114 case MKTAG('h','v','c','1'):
9115 43 ret = heif_add_stream(c, item);
9116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
9117 return ret;
9118 43 break;
9119 }
9120
9121 57 return 0;
9122 }
9123
9124 18 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9125 {
9126 HEIFItem **heif_item;
9127 int entry_count;
9128 18 int version, got_stream = 0, ret, i;
9129
9130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->found_iinf) {
9131 av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
9132 return 0;
9133 }
9134
9135 18 version = avio_r8(pb);
9136 18 avio_rb24(pb); // flags.
9137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
9138
9139 18 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
9140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!heif_item)
9141 return AVERROR(ENOMEM);
9142 18 c->heif_item = heif_item;
9143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (entry_count > c->nb_heif_item)
9144 memset(&c->heif_item[c->nb_heif_item], 0,
9145 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
9146 18 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
9147
9148
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (i = 0; i < entry_count; i++) {
9149 MOVAtom infe;
9150
9151 57 infe.size = avio_rb32(pb) - 8;
9152 57 infe.type = avio_rl32(pb);
9153
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (avio_feof(pb)) {
9154 ret = AVERROR_INVALIDDATA;
9155 goto fail;
9156 }
9157 57 ret = mov_read_infe(c, pb, infe);
9158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (ret < 0)
9159 goto fail;
9160
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 if (!ret)
9161 57 got_stream = 1;
9162 }
9163
9164 18 c->found_iinf = got_stream;
9165 18 return 0;
9166 fail:
9167 for (; i >= 0; i--) {
9168 HEIFItem *item = c->heif_item[i];
9169
9170 if (!item)
9171 continue;
9172
9173 av_freep(&item->name);
9174 }
9175 return ret;
9176 }
9177
9178 9 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
9179 {
9180 9 HEIFItem *item = NULL;
9181 HEIFGrid *grid;
9182 int entries, i;
9183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9184 9 int ret = 0;
9185
9186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 for (int i = 0; i < c->nb_heif_grid; i++) {
9187 if (c->heif_grid[i].item->item_id == from_item_id) {
9188 av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
9189 "referencing the same Derived Image item\n");
9190 return AVERROR_INVALIDDATA;
9191 }
9192 }
9193
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 for (int i = 0; i < c->nb_heif_item; i++) {
9194
3/4
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 9 times.
35 if (!c->heif_item[i] || c->heif_item[i]->item_id != from_item_id)
9195 26 continue;
9196 9 item = c->heif_item[i];
9197
9198
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 switch (item->type) {
9199 9 case MKTAG('g','r','i','d'):
9200 case MKTAG('i','o','v','l'):
9201 9 break;
9202 default:
9203 avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
9204 av_fourcc2str(item->type));
9205 return 0;
9206 }
9207 9 break;
9208 }
9209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!item) {
9210 av_log(c->fc, AV_LOG_ERROR, "Missing grid information\n");
9211 return AVERROR_INVALIDDATA;
9212 }
9213
9214 9 grid = av_realloc_array(c->heif_grid, c->nb_heif_grid + 1U,
9215 sizeof(*c->heif_grid));
9216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!grid)
9217 return AVERROR(ENOMEM);
9218 9 c->heif_grid = grid;
9219 9 grid = &grid[c->nb_heif_grid];
9220
9221 9 entries = avio_rb16(pb);
9222 9 grid->tile_id_list = av_malloc_array(entries, sizeof(*grid->tile_id_list));
9223 9 grid->tile_idx_list = av_calloc(entries, sizeof(*grid->tile_idx_list));
9224 9 grid->tile_item_list = av_calloc(entries, sizeof(*grid->tile_item_list));
9225
3/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
9 if (!grid->tile_id_list || !grid->tile_item_list || !grid->tile_idx_list) {
9226 ret = AVERROR(ENOMEM);
9227 goto fail;
9228 }
9229 /* 'to' item ids */
9230
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9 times.
37 for (i = 0; i < entries; i++) {
9231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 grid->tile_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
9232
9233
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if (avio_feof(pb)) {
9234 ret = AVERROR_INVALIDDATA;
9235 goto fail;
9236 }
9237 }
9238
9239 9 grid->nb_tiles = entries;
9240 9 grid->item = item;
9241 9 ++c->nb_heif_grid;
9242
9243 9 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
9244 from_item_id, entries);
9245
9246 9 return 0;
9247 fail:
9248 av_freep(&grid->tile_id_list);
9249 av_freep(&grid->tile_idx_list);
9250 av_freep(&grid->tile_item_list);
9251
9252 return ret;
9253 }
9254
9255 11 static int mov_read_iref_cdsc(MOVContext *c, AVIOContext *pb, uint32_t type, int version)
9256 {
9257 11 HEIFItem *from_item = NULL;
9258 int entries;
9259
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9260 11 const HEIFItemRef ref = { type, from_item_id };
9261
9262 11 from_item = get_heif_item(c, from_item_id);
9263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!from_item) {
9264 av_log(c->fc, AV_LOG_ERROR, "Missing stream referenced by thmb item\n");
9265 return AVERROR_INVALIDDATA;
9266 }
9267
9268 11 entries = avio_rb16(pb);
9269 /* 'to' item ids */
9270
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (int i = 0; i < entries; i++) {
9271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 HEIFItem *item = get_heif_item(c, version ? avio_rb32(pb) : avio_rb16(pb));
9272
9273
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (avio_feof(pb))
9274 return AVERROR_INVALIDDATA;
9275
9276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!item) {
9277 av_log(c->fc, AV_LOG_WARNING, "Missing stream referenced by %s item\n",
9278 av_fourcc2str(type));
9279 continue;
9280 }
9281
9282
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (!av_dynarray2_add((void **)&item->iref_list, &item->nb_iref_list,
9283 sizeof(*item->iref_list), (const uint8_t *)&ref))
9284 return AVERROR(ENOMEM);
9285 }
9286
9287 11 av_log(c->fc, AV_LOG_TRACE, "%s: from_item_id %d, entries %d\n",
9288 11 av_fourcc2str(type), from_item_id, entries);
9289
9290 11 return 0;
9291 }
9292
9293 14 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9294 {
9295 14 int version = avio_r8(pb);
9296 int ret;
9297
9298 14 avio_rb24(pb); // flags
9299 14 atom.size -= 4;
9300
9301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (version > 1) {
9302 av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
9303 return 0;
9304 }
9305
9306
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 14 times.
34 while (atom.size) {
9307 20 uint32_t type, size = avio_rb32(pb);
9308 20 int64_t next = avio_tell(pb);
9309
9310
3/6
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
20 if (size < 14 || next < 0 || next > INT64_MAX - size)
9311 return AVERROR_INVALIDDATA;
9312
9313 20 next += size - 4;
9314 20 type = avio_rl32(pb);
9315
2/3
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
20 switch (type) {
9316 9 case MKTAG('d','i','m','g'):
9317 9 ret = mov_read_iref_dimg(c, pb, version);
9318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret < 0)
9319 return ret;
9320 20 break;
9321 11 case MKTAG('c','d','s','c'):
9322 case MKTAG('t','h','m','b'):
9323 11 ret = mov_read_iref_cdsc(c, pb, type, version);
9324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0)
9325 return ret;
9326 11 break;
9327 default:
9328 av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
9329 av_fourcc2str(type), size);
9330 }
9331
9332 20 atom.size -= size;
9333 20 avio_seek(pb, next, SEEK_SET);
9334 }
9335 14 return 0;
9336 }
9337
9338 52 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9339 {
9340 HEIFItem *item;
9341 uint32_t width, height;
9342
9343 52 avio_r8(pb); /* version */
9344 52 avio_rb24(pb); /* flags */
9345 52 width = avio_rb32(pb);
9346 52 height = avio_rb32(pb);
9347
9348 52 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %"PRIu32", height %"PRIu32"\n",
9349 c->cur_item_id, width, height);
9350
9351 52 item = get_heif_item(c, c->cur_item_id);
9352
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 if (item) {
9353 52 item->width = width;
9354 52 item->height = height;
9355 }
9356
9357 52 return 0;
9358 }
9359
9360 8 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9361 {
9362 HEIFItem *item;
9363 int angle;
9364
9365 8 angle = avio_r8(pb) & 0x3;
9366
9367 8 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
9368 c->cur_item_id, angle);
9369
9370 8 item = get_heif_item(c, c->cur_item_id);
9371
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (item) {
9372 // angle * 90 specifies the angle (in anti-clockwise direction)
9373 // in units of degrees.
9374 8 item->rotation = angle * 90;
9375 }
9376
9377 8 return 0;
9378 }
9379
9380 6 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9381 {
9382 HEIFItem *item;
9383 int axis;
9384
9385 6 axis = avio_r8(pb) & 0x1;
9386
9387 6 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
9388 c->cur_item_id, axis);
9389
9390 6 item = get_heif_item(c, c->cur_item_id);
9391
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
9392 6 item->hflip = axis;
9393 6 item->vflip = !axis;
9394 }
9395
9396 6 return 0;
9397 }
9398
9399 18 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9400 {
9401 typedef struct MOVAtoms {
9402 FFIOContext b;
9403 uint32_t type;
9404 int64_t size;
9405 uint8_t *data;
9406 } MOVAtoms;
9407 18 MOVAtoms *atoms = NULL;
9408 MOVAtom a;
9409 unsigned count;
9410 18 int nb_atoms = 0;
9411 int version, flags;
9412 int ret;
9413
9414 18 a.size = avio_rb32(pb);
9415 18 a.type = avio_rl32(pb);
9416
9417
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (a.size < 8 || a.type != MKTAG('i','p','c','o'))
9418 return AVERROR_INVALIDDATA;
9419
9420 18 a.size -= 8;
9421
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 while (a.size >= 8) {
9422 80 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
9423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!ref) {
9424 ret = AVERROR(ENOMEM);
9425 goto fail;
9426 }
9427 80 ref->data = NULL;
9428 80 ref->size = avio_rb32(pb);
9429 80 ref->type = avio_rl32(pb);
9430
2/4
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
80 if (ref->size > a.size || ref->size < 8)
9431 break;
9432 80 ref->data = av_malloc(ref->size);
9433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!ref->data) {
9434 ret = AVERROR_INVALIDDATA;
9435 goto fail;
9436 }
9437 80 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
9438 80 avio_seek(pb, -8, SEEK_CUR);
9439
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
80 if (avio_read(pb, ref->data, ref->size) != ref->size) {
9440 ret = AVERROR_INVALIDDATA;
9441 goto fail;
9442 }
9443 80 ffio_init_read_context(&ref->b, ref->data, ref->size);
9444 80 a.size -= ref->size;
9445 }
9446
9447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (a.size) {
9448 ret = AVERROR_INVALIDDATA;
9449 goto fail;
9450 }
9451
9452 18 a.size = avio_rb32(pb);
9453 18 a.type = avio_rl32(pb);
9454
9455
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (a.size < 8 || a.type != MKTAG('i','p','m','a')) {
9456 ret = AVERROR_INVALIDDATA;
9457 goto fail;
9458 }
9459
9460 18 version = avio_r8(pb);
9461 18 flags = avio_rb24(pb);
9462 18 count = avio_rb32(pb);
9463
9464
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 18 times.
70 for (int i = 0; i < count; i++) {
9465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9466 52 int assoc_count = avio_r8(pb);
9467
9468
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
52 if (avio_feof(pb)) {
9469 ret = AVERROR_INVALIDDATA;
9470 goto fail;
9471 }
9472
9473
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 52 times.
177 for (int j = 0; j < assoc_count; j++) {
9474 MOVAtoms *ref;
9475 125 int index = avio_r8(pb) & 0x7f;
9476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 if (flags & 1) {
9477 index <<= 8;
9478 index |= avio_r8(pb);
9479 }
9480
2/4
✓ Branch 0 taken 125 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 125 times.
125 if (index > nb_atoms || index <= 0) {
9481 ret = AVERROR_INVALIDDATA;
9482 goto fail;
9483 }
9484 125 ref = &atoms[--index];
9485
9486 125 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
9487 125 index + 1, item_id, av_fourcc2str(ref->type));
9488
9489 125 c->cur_item_id = item_id;
9490
9491 125 ret = mov_read_default(c, &ref->b.pub,
9492 125 (MOVAtom) { .size = ref->size,
9493 .type = MKTAG('i','p','c','o') });
9494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 if (ret < 0)
9495 goto fail;
9496 125 ffio_init_read_context(&ref->b, ref->data, ref->size);
9497 }
9498 }
9499
9500 18 ret = 0;
9501 18 fail:
9502 18 c->cur_item_id = -1;
9503
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 for (int i = 0; i < nb_atoms; i++)
9504 80 av_free(atoms[i].data);
9505 18 av_free(atoms);
9506
9507 18 return ret;
9508 }
9509
9510 static const MOVParseTableEntry mov_default_parse_table[] = {
9511 { MKTAG('A','C','L','R'), mov_read_aclr },
9512 { MKTAG('A','P','R','G'), mov_read_avid },
9513 { MKTAG('A','A','L','P'), mov_read_avid },
9514 { MKTAG('A','R','E','S'), mov_read_ares },
9515 { MKTAG('a','v','s','s'), mov_read_avss },
9516 { MKTAG('a','v','1','C'), mov_read_glbl },
9517 { MKTAG('c','h','p','l'), mov_read_chpl },
9518 { MKTAG('c','o','6','4'), mov_read_stco },
9519 { MKTAG('c','o','l','r'), mov_read_colr },
9520 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
9521 { MKTAG('d','i','n','f'), mov_read_default },
9522 { MKTAG('D','p','x','E'), mov_read_dpxe },
9523 { MKTAG('d','r','e','f'), mov_read_dref },
9524 { MKTAG('e','d','t','s'), mov_read_default },
9525 { MKTAG('e','l','s','t'), mov_read_elst },
9526 { MKTAG('e','n','d','a'), mov_read_enda },
9527 { MKTAG('f','i','e','l'), mov_read_fiel },
9528 { MKTAG('a','d','r','m'), mov_read_adrm },
9529 { MKTAG('f','t','y','p'), mov_read_ftyp },
9530 { MKTAG('g','l','b','l'), mov_read_glbl },
9531 { MKTAG('h','d','l','r'), mov_read_hdlr },
9532 { MKTAG('i','l','s','t'), mov_read_ilst },
9533 { MKTAG('j','p','2','h'), mov_read_jp2h },
9534 { MKTAG('m','d','a','t'), mov_read_mdat },
9535 { MKTAG('m','d','h','d'), mov_read_mdhd },
9536 { MKTAG('m','d','i','a'), mov_read_default },
9537 { MKTAG('m','e','t','a'), mov_read_meta },
9538 { MKTAG('m','i','n','f'), mov_read_default },
9539 { MKTAG('m','o','o','f'), mov_read_moof },
9540 { MKTAG('m','o','o','v'), mov_read_moov },
9541 { MKTAG('m','v','e','x'), mov_read_default },
9542 { MKTAG('m','v','h','d'), mov_read_mvhd },
9543 { MKTAG('S','M','I',' '), mov_read_svq3 },
9544 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
9545 { MKTAG('a','v','c','C'), mov_read_glbl },
9546 { MKTAG('p','a','s','p'), mov_read_pasp },
9547 { MKTAG('c','l','a','p'), mov_read_clap },
9548 { MKTAG('s','b','a','s'), mov_read_sbas },
9549 { MKTAG('s','i','d','x'), mov_read_sidx },
9550 { MKTAG('s','t','b','l'), mov_read_default },
9551 { MKTAG('s','t','c','o'), mov_read_stco },
9552 { MKTAG('s','t','p','s'), mov_read_stps },
9553 { MKTAG('s','t','r','f'), mov_read_strf },
9554 { MKTAG('s','t','s','c'), mov_read_stsc },
9555 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
9556 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
9557 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
9558 { MKTAG('s','t','t','s'), mov_read_stts },
9559 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
9560 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
9561 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
9562 { MKTAG('t','f','d','t'), mov_read_tfdt },
9563 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
9564 { MKTAG('t','r','a','k'), mov_read_trak },
9565 { MKTAG('t','r','a','f'), mov_read_default },
9566 { MKTAG('t','r','e','f'), mov_read_default },
9567 { MKTAG('t','m','c','d'), mov_read_tmcd },
9568 { MKTAG('c','h','a','p'), mov_read_chap },
9569 { MKTAG('t','r','e','x'), mov_read_trex },
9570 { MKTAG('t','r','u','n'), mov_read_trun },
9571 { MKTAG('u','d','t','a'), mov_read_default },
9572 { MKTAG('w','a','v','e'), mov_read_wave },
9573 { MKTAG('e','s','d','s'), mov_read_esds },
9574 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
9575 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
9576 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
9577 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
9578 { MKTAG('w','f','e','x'), mov_read_wfex },
9579 { MKTAG('c','m','o','v'), mov_read_cmov },
9580 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
9581 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
9582 { MKTAG('d','v','c','1'), mov_read_dvc1 },
9583 { MKTAG('s','g','p','d'), mov_read_sgpd },
9584 { MKTAG('s','b','g','p'), mov_read_sbgp },
9585 { MKTAG('h','v','c','C'), mov_read_glbl },
9586 { MKTAG('v','v','c','C'), mov_read_glbl },
9587 { MKTAG('u','u','i','d'), mov_read_uuid },
9588 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
9589 { MKTAG('f','r','e','e'), mov_read_free },
9590 { MKTAG('-','-','-','-'), mov_read_custom },
9591 { MKTAG('s','i','n','f'), mov_read_default },
9592 { MKTAG('f','r','m','a'), mov_read_frma },
9593 { MKTAG('s','e','n','c'), mov_read_senc },
9594 { MKTAG('s','a','i','z'), mov_read_saiz },
9595 { MKTAG('s','a','i','o'), mov_read_saio },
9596 { MKTAG('p','s','s','h'), mov_read_pssh },
9597 { MKTAG('s','c','h','m'), mov_read_schm },
9598 { MKTAG('s','c','h','i'), mov_read_default },
9599 { MKTAG('t','e','n','c'), mov_read_tenc },
9600 { MKTAG('d','f','L','a'), mov_read_dfla },
9601 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
9602 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
9603 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
9604 { MKTAG('h','f','o','v'), mov_read_hfov },
9605 { MKTAG('d','O','p','s'), mov_read_dops },
9606 { MKTAG('d','m','l','p'), mov_read_dmlp },
9607 { MKTAG('S','m','D','m'), mov_read_smdm },
9608 { MKTAG('C','o','L','L'), mov_read_coll },
9609 { MKTAG('v','p','c','C'), mov_read_vpcc },
9610 { MKTAG('m','d','c','v'), mov_read_mdcv },
9611 { MKTAG('c','l','l','i'), mov_read_clli },
9612 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
9613 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
9614 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
9615 { MKTAG('k','i','n','d'), mov_read_kind },
9616 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
9617 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
9618 { MKTAG('i','l','o','c'), mov_read_iloc },
9619 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
9620 { MKTAG('p','i','t','m'), mov_read_pitm },
9621 { MKTAG('e','v','c','C'), mov_read_glbl },
9622 { MKTAG('i','d','a','t'), mov_read_idat },
9623 { MKTAG('i','m','i','r'), mov_read_imir },
9624 { MKTAG('i','r','e','f'), mov_read_iref },
9625 { MKTAG('i','s','p','e'), mov_read_ispe },
9626 { MKTAG('i','r','o','t'), mov_read_irot },
9627 { MKTAG('i','p','r','p'), mov_read_iprp },
9628 { MKTAG('i','i','n','f'), mov_read_iinf },
9629 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
9630 { MKTAG('l','h','v','C'), mov_read_lhvc },
9631 { MKTAG('l','v','c','C'), mov_read_glbl },
9632 { MKTAG('a','p','v','C'), mov_read_glbl },
9633 #if CONFIG_IAMFDEC
9634 { MKTAG('i','a','c','b'), mov_read_iacb },
9635 #endif
9636 { MKTAG('s','r','a','t'), mov_read_srat },
9637 { 0, NULL }
9638 };
9639
9640 6900 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9641 {
9642 6900 int64_t total_size = 0;
9643 MOVAtom a;
9644 int i;
9645
9646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6900 times.
6900 if (c->atom_depth > 10) {
9647 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
9648 return AVERROR_INVALIDDATA;
9649 }
9650 6900 c->atom_depth ++;
9651
9652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6900 times.
6900 if (atom.size < 0)
9653 atom.size = INT64_MAX;
9654
2/2
✓ Branch 0 taken 19794 times.
✓ Branch 1 taken 6393 times.
26187 while (total_size <= atom.size - 8) {
9655 19794 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
9656 19794 a.size = avio_rb32(pb);
9657 19794 a.type = avio_rl32(pb);
9658
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 19787 times.
19794 if (avio_feof(pb))
9659 7 break;
9660
3/4
✓ Branch 0 taken 197 times.
✓ Branch 1 taken 19590 times.
✓ Branch 2 taken 197 times.
✗ Branch 3 not taken.
19787 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
9661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19787 times.
19787 a.type == MKTAG('h','o','o','v')) &&
9662 a.size >= 8 &&
9663 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
9664 uint32_t type;
9665 avio_skip(pb, 4);
9666 type = avio_rl32(pb);
9667 if (avio_feof(pb))
9668 break;
9669 avio_seek(pb, -8, SEEK_CUR);
9670 if (type == MKTAG('m','v','h','d') ||
9671 type == MKTAG('c','m','o','v')) {
9672 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
9673 a.type = MKTAG('m','o','o','v');
9674 }
9675 }
9676
2/2
✓ Branch 0 taken 16819 times.
✓ Branch 1 taken 2968 times.
19787 if (atom.type != MKTAG('r','o','o','t') &&
9677
2/2
✓ Branch 0 taken 15334 times.
✓ Branch 1 taken 1485 times.
16819 atom.type != MKTAG('m','o','o','v')) {
9678
1/2
✓ Branch 0 taken 15334 times.
✗ Branch 1 not taken.
15334 if (a.type == MKTAG('t','r','a','k') ||
9679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15334 times.
15334 a.type == MKTAG('m','d','a','t')) {
9680 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
9681 avio_skip(pb, -8);
9682 c->atom_depth --;
9683 500 return 0;
9684 }
9685 }
9686 19787 total_size += 8;
9687
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 19758 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
19787 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
9688 29 a.size = avio_rb64(pb) - 8;
9689 29 total_size += 8;
9690 }
9691 19787 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
9692 19787 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
9693
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19782 times.
19787 if (a.size == 0) {
9694 5 a.size = atom.size - total_size + 8;
9695 }
9696
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19787 times.
19787 if (a.size < 0)
9697 break;
9698 19787 a.size -= 8;
9699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19787 times.
19787 if (a.size < 0)
9700 break;
9701 19787 a.size = FFMIN(a.size, atom.size - total_size);
9702
9703
2/2
✓ Branch 0 taken 916792 times.
✓ Branch 1 taken 2001 times.
918793 for (i = 0; mov_default_parse_table[i].type; i++)
9704
2/2
✓ Branch 0 taken 17786 times.
✓ Branch 1 taken 899006 times.
916792 if (mov_default_parse_table[i].type == a.type) {
9705 17786 parse = mov_default_parse_table[i].parse;
9706 17786 break;
9707 }
9708
9709 // container is user data
9710
4/4
✓ Branch 0 taken 2001 times.
✓ Branch 1 taken 17786 times.
✓ Branch 2 taken 1822 times.
✓ Branch 3 taken 179 times.
19787 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
9711
2/2
✓ Branch 0 taken 301 times.
✓ Branch 1 taken 1521 times.
1822 atom.type == MKTAG('i','l','s','t')))
9712 480 parse = mov_read_udta_string;
9713
9714 // Supports parsing the QuickTime Metadata Keys.
9715 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
9716
4/4
✓ Branch 0 taken 1521 times.
✓ Branch 1 taken 18266 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 1510 times.
19787 if (!parse && c->found_hdlr_mdta &&
9717
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 atom.type == MKTAG('m','e','t','a') &&
9718
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 a.type == MKTAG('k','e','y','s') &&
9719
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 c->meta_keys_count == 0) {
9720 11 parse = mov_read_keys;
9721 }
9722
9723
2/2
✓ Branch 0 taken 1510 times.
✓ Branch 1 taken 18277 times.
19787 if (!parse) { /* skip leaf atoms data */
9724 1510 avio_skip(pb, a.size);
9725 } else {
9726 18277 int64_t start_pos = avio_tell(pb);
9727 int64_t left;
9728 18277 int err = parse(c, pb, a);
9729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18277 times.
18277 if (err < 0) {
9730 c->atom_depth --;
9731 return err;
9732 }
9733
5/6
✓ Branch 0 taken 3725 times.
✓ Branch 1 taken 14552 times.
✓ Branch 2 taken 3349 times.
✓ Branch 3 taken 376 times.
✓ Branch 4 taken 3349 times.
✗ Branch 5 not taken.
18277 if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos &&
9734
7/8
✓ Branch 0 taken 3348 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3348 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3334 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 485 times.
✓ Branch 7 taken 2849 times.
6683 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
9735 3334 start_pos + a.size == avio_size(pb))) {
9736
5/6
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 499 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 485 times.
500 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
9737 15 c->next_root_atom = start_pos + a.size;
9738 500 c->atom_depth --;
9739 500 return 0;
9740 }
9741 17777 left = a.size - avio_tell(pb) + start_pos;
9742
2/2
✓ Branch 0 taken 1494 times.
✓ Branch 1 taken 16283 times.
17777 if (left > 0) /* skip garbage at atom end */
9743 1494 avio_skip(pb, left);
9744
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16281 times.
16283 else if (left < 0) {
9745 2 av_log(c->fc, AV_LOG_WARNING,
9746 "overread end of atom '%s' by %"PRId64" bytes\n",
9747 2 av_fourcc2str(a.type), -left);
9748 2 avio_seek(pb, left, SEEK_CUR);
9749 }
9750 }
9751
9752 19287 total_size += a.size;
9753 }
9754
9755
4/4
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 6291 times.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 7 times.
6400 if (total_size < atom.size && atom.size < 0x7ffff)
9756 102 avio_skip(pb, atom.size - total_size);
9757
9758 6400 c->atom_depth --;
9759 6400 return 0;
9760 }
9761
9762 7474 static int mov_probe(const AVProbeData *p)
9763 {
9764 int64_t offset;
9765 uint32_t tag;
9766 7474 int score = 0;
9767 7474 int moov_offset = -1;
9768
9769 /* check file header */
9770 7474 offset = 0;
9771 9206 for (;;) {
9772 int64_t size;
9773 16680 int minsize = 8;
9774 /* ignore invalid offset */
9775
2/2
✓ Branch 0 taken 7474 times.
✓ Branch 1 taken 9206 times.
16680 if ((offset + 8ULL) > (unsigned int)p->buf_size)
9776 7474 break;
9777 9206 size = AV_RB32(p->buf + offset);
9778
3/4
✓ Branch 0 taken 529 times.
✓ Branch 1 taken 8677 times.
✓ Branch 2 taken 529 times.
✗ Branch 3 not taken.
9206 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
9779 529 size = AV_RB64(p->buf+offset + 8);
9780 529 minsize = 16;
9781
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 8622 times.
8677 } else if (size == 0) {
9782 55 size = p->buf_size - offset;
9783 }
9784
2/2
✓ Branch 0 taken 401 times.
✓ Branch 1 taken 8805 times.
9206 if (size < minsize) {
9785 401 offset += 4;
9786 401 continue;
9787 }
9788 8805 tag = AV_RL32(p->buf + offset + 4);
9789
5/6
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 873 times.
✓ Branch 2 taken 363 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7436 times.
8805 switch(tag) {
9790 /* check for obvious tags */
9791 132 case MKTAG('m','o','o','v'):
9792 132 moov_offset = offset + 4;
9793 1005 case MKTAG('m','d','a','t'):
9794 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
9795 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
9796 case MKTAG('f','t','y','p'):
9797
2/2
✓ Branch 0 taken 456 times.
✓ Branch 1 taken 549 times.
1005 if (tag == MKTAG('f','t','y','p') &&
9798
1/2
✓ Branch 0 taken 456 times.
✗ Branch 1 not taken.
456 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
9799
1/2
✓ Branch 0 taken 456 times.
✗ Branch 1 not taken.
456 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
9800
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 449 times.
456 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
9801 )) {
9802 7 score = FFMAX(score, 5);
9803 } else {
9804 998 score = AVPROBE_SCORE_MAX;
9805 }
9806 1005 break;
9807 /* those are more common words, so rate then a bit less */
9808 363 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
9809 case MKTAG('w','i','d','e'):
9810 case MKTAG('f','r','e','e'):
9811 case MKTAG('j','u','n','k'):
9812 case MKTAG('p','i','c','t'):
9813 363 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
9814 363 break;
9815 case MKTAG(0x82,0x82,0x7f,0x7d):
9816 score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
9817 break;
9818 1 case MKTAG('s','k','i','p'):
9819 case MKTAG('u','u','i','d'):
9820 case MKTAG('p','r','f','l'):
9821 /* if we only find those cause probedata is too small at least rate them */
9822 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
9823 1 break;
9824 }
9825
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8805 times.
8805 if (size > INT64_MAX - offset)
9826 break;
9827 8805 offset += size;
9828 }
9829
4/4
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 6988 times.
✓ Branch 2 taken 132 times.
✓ Branch 3 taken 354 times.
7474 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
9830 /* moov atom in the header - we should make sure that this is not a
9831 * MOV-packed MPEG-PS */
9832 132 offset = moov_offset;
9833
9834
2/2
✓ Branch 0 taken 129602 times.
✓ Branch 1 taken 132 times.
129734 while (offset < (p->buf_size - 16)) { /* Sufficient space */
9835 /* We found an actual hdlr atom */
9836
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 129461 times.
129602 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
9837
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 120 times.
141 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
9838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
9839 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
9840 /* We found a media handler reference atom describing an
9841 * MPEG-PS-in-MOV, return a
9842 * low score to force expanding the probe window until
9843 * mpegps_probe finds what it needs */
9844 return 5;
9845 } else {
9846 /* Keep looking */
9847 129602 offset += 2;
9848 }
9849 }
9850 }
9851
9852 7474 return score;
9853 }
9854
9855 // must be done after parsing all trak because there's no order requirement
9856 2 static void mov_read_chapters(AVFormatContext *s)
9857 {
9858 2 MOVContext *mov = s->priv_data;
9859 MOVStreamContext *sc;
9860 int64_t cur_pos;
9861 int i, j;
9862 int chapter_track;
9863
9864
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
9865 2 AVStream *st = NULL;
9866 2 FFStream *sti = NULL;
9867 2 chapter_track = mov->chapter_tracks[j];
9868
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
9869 4 sc = mov->fc->streams[i]->priv_data;
9870
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
9871 2 st = s->streams[i];
9872 2 break;
9873 }
9874 }
9875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
9876 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
9877 continue;
9878 }
9879 2 sti = ffstream(st);
9880
9881 2 sc = st->priv_data;
9882 2 cur_pos = avio_tell(sc->pb);
9883
9884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
9885 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
9886 if (!st->attached_pic.data && sti->nb_index_entries) {
9887 // Retrieve the first frame, if possible
9888 AVIndexEntry *sample = &sti->index_entries[0];
9889 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9890 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
9891 goto finish;
9892 }
9893
9894 if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
9895 goto finish;
9896 }
9897 } else {
9898 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
9899 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
9900 2 st->discard = AVDISCARD_ALL;
9901
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
9902 8 AVIndexEntry *sample = &sti->index_entries[i];
9903
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;
9904 uint8_t *title;
9905 uint16_t ch;
9906 int len, title_len;
9907
9908
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
9909 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
9910 end = AV_NOPTS_VALUE;
9911 }
9912
9913
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9914 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
9915 goto finish;
9916 }
9917
9918 // the first two bytes are the length of the title
9919 8 len = avio_rb16(sc->pb);
9920
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
9921 continue;
9922 8 title_len = 2*len + 1;
9923
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
9924 goto finish;
9925
9926 // The samples could theoretically be in any encoding if there's an encd
9927 // atom following, but in practice are only utf-8 or utf-16, distinguished
9928 // instead by the presence of a BOM
9929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
9930 title[0] = 0;
9931 } else {
9932 8 ch = avio_rb16(sc->pb);
9933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
9934 avio_get_str16be(sc->pb, len, title, title_len);
9935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
9936 avio_get_str16le(sc->pb, len, title, title_len);
9937 else {
9938 8 AV_WB16(title, ch);
9939
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)
9940 title[len] = 0;
9941 else
9942 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
9943 }
9944 }
9945
9946 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
9947 8 av_freep(&title);
9948 }
9949 }
9950 2 finish:
9951 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
9952 }
9953 2 }
9954
9955 19 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
9956 int64_t value, int flags)
9957 {
9958 AVTimecode tc;
9959 char buf[AV_TIMECODE_STR_SIZE];
9960 19 AVRational rate = st->avg_frame_rate;
9961 19 int ret = av_timecode_init(&tc, rate, flags, 0, s);
9962
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
9963 return ret;
9964 19 av_dict_set(&st->metadata, "timecode",
9965 19 av_timecode_make_string(&tc, buf, value), 0);
9966 19 return 0;
9967 }
9968
9969 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
9970 {
9971 MOVStreamContext *sc = st->priv_data;
9972 FFStream *const sti = ffstream(st);
9973 char buf[AV_TIMECODE_STR_SIZE];
9974 int64_t cur_pos = avio_tell(sc->pb);
9975 int hh, mm, ss, ff, drop;
9976
9977 if (!sti->nb_index_entries)
9978 return -1;
9979
9980 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9981 avio_skip(s->pb, 13);
9982 hh = avio_r8(s->pb);
9983 mm = avio_r8(s->pb);
9984 ss = avio_r8(s->pb);
9985 drop = avio_r8(s->pb);
9986 ff = avio_r8(s->pb);
9987 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
9988 hh, mm, ss, drop ? ';' : ':', ff);
9989 av_dict_set(&st->metadata, "timecode", buf, 0);
9990
9991 avio_seek(sc->pb, cur_pos, SEEK_SET);
9992 return 0;
9993 }
9994
9995 19 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
9996 {
9997 19 MOVStreamContext *sc = st->priv_data;
9998 19 FFStream *const sti = ffstream(st);
9999 19 int flags = 0;
10000 19 int64_t cur_pos = avio_tell(sc->pb);
10001 int64_t value;
10002 19 AVRational tc_rate = st->avg_frame_rate;
10003 19 int tmcd_nb_frames = sc->tmcd_nb_frames;
10004 int rounded_tc_rate;
10005
10006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!sti->nb_index_entries)
10007 return -1;
10008
10009
3/6
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 19 times.
19 if (!tc_rate.num || !tc_rate.den || !tmcd_nb_frames)
10010 return -1;
10011
10012 19 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10013 19 value = avio_rb32(s->pb);
10014
10015
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13 times.
19 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
10016
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
10017
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
10018
10019 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
10020 * not the case) and thus assume "frame number format" instead of QT one.
10021 * No sample with tmcd track can be found with a QT timecode at the moment,
10022 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
10023 * format). */
10024
10025 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
10026 * we multiply the frame number with the quotient.
10027 * See tickets #9492, #9710. */
10028 19 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
10029 /* Work around files where tmcd_nb_frames is rounded down from frame rate
10030 * instead of up. See ticket #5978. */
10031
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
10032
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
10033 10 tmcd_nb_frames = rounded_tc_rate;
10034 19 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
10035
10036 19 parse_timecode_in_framenum_format(s, st, value, flags);
10037
10038 19 avio_seek(sc->pb, cur_pos, SEEK_SET);
10039 19 return 0;
10040 }
10041
10042 1263 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
10043 int i;
10044
3/4
✓ Branch 0 taken 1263 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1255 times.
✓ Branch 3 taken 8 times.
1263 if (!index || !*index) return;
10045
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 8 times.
152 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
10046 144 av_encryption_info_free((*index)->encrypted_samples[i]);
10047 }
10048 8 av_freep(&(*index)->encrypted_samples);
10049 8 av_freep(&(*index)->auxiliary_info_sizes);
10050 8 av_freep(&(*index)->auxiliary_offsets);
10051 8 av_freep(index);
10052 }
10053
10054 736 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
10055 {
10056 736 MOVStreamContext *sc = st->priv_data;
10057
10058
3/4
✓ Branch 0 taken 736 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 684 times.
736 if (!sc || --sc->refcount) {
10059 52 st->priv_data = NULL;
10060 52 return;
10061 }
10062
10063 684 av_freep(&sc->tts_data);
10064
2/2
✓ Branch 0 taken 627 times.
✓ Branch 1 taken 684 times.
1311 for (int i = 0; i < sc->drefs_count; i++) {
10065 627 av_freep(&sc->drefs[i].path);
10066 627 av_freep(&sc->drefs[i].dir);
10067 }
10068 684 av_freep(&sc->drefs);
10069
10070 684 sc->drefs_count = 0;
10071
10072
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 670 times.
684 if (!sc->pb_is_copied)
10073 14 ff_format_io_close(s, &sc->pb);
10074
10075 684 sc->pb = NULL;
10076 684 av_freep(&sc->chunk_offsets);
10077 684 av_freep(&sc->stsc_data);
10078 684 av_freep(&sc->sample_sizes);
10079 684 av_freep(&sc->keyframes);
10080 684 av_freep(&sc->ctts_data);
10081 684 av_freep(&sc->stts_data);
10082 684 av_freep(&sc->sdtp_data);
10083 684 av_freep(&sc->stps_data);
10084 684 av_freep(&sc->elst_data);
10085 684 av_freep(&sc->rap_group);
10086 684 av_freep(&sc->sync_group);
10087 684 av_freep(&sc->sgpd_sync);
10088 684 av_freep(&sc->sample_offsets);
10089 684 av_freep(&sc->open_key_samples);
10090 684 av_freep(&sc->display_matrix);
10091 684 av_freep(&sc->index_ranges);
10092
10093
2/2
✓ Branch 0 taken 627 times.
✓ Branch 1 taken 57 times.
684 if (sc->extradata)
10094
2/2
✓ Branch 0 taken 641 times.
✓ Branch 1 taken 627 times.
1268 for (int i = 0; i < sc->stsd_count; i++)
10095 641 av_free(sc->extradata[i]);
10096 684 av_freep(&sc->extradata);
10097 684 av_freep(&sc->extradata_size);
10098
10099 684 mov_free_encryption_index(&sc->cenc.encryption_index);
10100 684 av_encryption_info_free(sc->cenc.default_encrypted_sample);
10101 684 av_aes_ctr_free(sc->cenc.aes_ctr);
10102
10103 684 av_freep(&sc->stereo3d);
10104 684 av_freep(&sc->spherical);
10105 684 av_freep(&sc->mastering);
10106 684 av_freep(&sc->coll);
10107 684 av_freep(&sc->ambient);
10108
10109 #if CONFIG_IAMFDEC
10110
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 672 times.
684 if (sc->iamf)
10111 12 ff_iamf_read_deinit(sc->iamf);
10112 #endif
10113 684 av_freep(&sc->iamf);
10114 }
10115
10116 523 static int mov_read_close(AVFormatContext *s)
10117 {
10118 523 MOVContext *mov = s->priv_data;
10119 int i, j;
10120
10121
2/2
✓ Branch 0 taken 736 times.
✓ Branch 1 taken 523 times.
1259 for (i = 0; i < s->nb_streams; i++) {
10122 736 AVStream *st = s->streams[i];
10123
10124 736 mov_free_stream_context(s, st);
10125 }
10126
10127 523 av_freep(&mov->dv_demux);
10128 523 avformat_free_context(mov->dv_fctx);
10129 523 mov->dv_fctx = NULL;
10130
10131
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 512 times.
523 if (mov->meta_keys) {
10132
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i < mov->meta_keys_count; i++) {
10133 58 av_freep(&mov->meta_keys[i]);
10134 }
10135 11 av_freep(&mov->meta_keys);
10136 }
10137
10138 523 av_freep(&mov->trex_data);
10139 523 av_freep(&mov->bitrates);
10140
10141
2/2
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 523 times.
1000 for (i = 0; i < mov->frag_index.nb_items; i++) {
10142 477 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
10143
2/2
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 477 times.
1056 for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) {
10144 579 mov_free_encryption_index(&frag[j].encryption_index);
10145 }
10146 477 av_freep(&mov->frag_index.item[i].stream_info);
10147 }
10148 523 av_freep(&mov->frag_index.item);
10149
10150 523 av_freep(&mov->aes_decrypt);
10151 523 av_freep(&mov->chapter_tracks);
10152
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 523 times.
580 for (i = 0; i < mov->nb_heif_item; i++) {
10153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!mov->heif_item[i])
10154 continue;
10155 57 av_freep(&mov->heif_item[i]->name);
10156 57 av_freep(&mov->heif_item[i]->iref_list);
10157 57 av_freep(&mov->heif_item[i]->icc_profile);
10158 57 av_freep(&mov->heif_item[i]);
10159 }
10160 523 av_freep(&mov->heif_item);
10161
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 523 times.
532 for (i = 0; i < mov->nb_heif_grid; i++) {
10162 9 av_freep(&mov->heif_grid[i].tile_id_list);
10163 9 av_freep(&mov->heif_grid[i].tile_idx_list);
10164 9 av_freep(&mov->heif_grid[i].tile_item_list);
10165 }
10166 523 av_freep(&mov->heif_grid);
10167
10168 523 return 0;
10169 }
10170
10171 16 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
10172 {
10173 int i;
10174
10175
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 for (i = 0; i < s->nb_streams; i++) {
10176 24 AVStream *st = s->streams[i];
10177 24 MOVStreamContext *sc = st->priv_data;
10178
10179
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
10180
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 sc->timecode_track == tmcd_id)
10181 14 return 1;
10182 }
10183 2 return 0;
10184 }
10185
10186 /* look for a tmcd track not referenced by any video track, and export it globally */
10187 523 static void export_orphan_timecode(AVFormatContext *s)
10188 {
10189 int i;
10190
10191
2/2
✓ Branch 0 taken 733 times.
✓ Branch 1 taken 521 times.
1254 for (i = 0; i < s->nb_streams; i++) {
10192 733 AVStream *st = s->streams[i];
10193
10194
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 717 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 14 times.
749 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
10195 16 !tmcd_is_referenced(s, i + 1)) {
10196 2 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
10197
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (tcr) {
10198 2 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
10199 2 break;
10200 }
10201 }
10202 }
10203 523 }
10204
10205 3 static int read_tfra(MOVContext *mov, AVIOContext *f)
10206 {
10207 int version, fieldlength, i, j;
10208 3 int64_t pos = avio_tell(f);
10209 3 uint32_t size = avio_rb32(f);
10210 unsigned track_id, item_count;
10211
10212
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
10213 1 return 1;
10214 }
10215 2 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
10216
10217 2 version = avio_r8(f);
10218 2 avio_rb24(f);
10219 2 track_id = avio_rb32(f);
10220 2 fieldlength = avio_rb32(f);
10221 2 item_count = avio_rb32(f);
10222
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (i = 0; i < item_count; i++) {
10223 int64_t time, offset;
10224 int index;
10225 MOVFragmentStreamInfo * frag_stream_info;
10226
10227
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (avio_feof(f)) {
10228 return AVERROR_INVALIDDATA;
10229 }
10230
10231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1) {
10232 time = avio_rb64(f);
10233 offset = avio_rb64(f);
10234 } else {
10235 6 time = avio_rb32(f);
10236 6 offset = avio_rb32(f);
10237 }
10238
10239 // The first sample of each stream in a fragment is always a random
10240 // access sample. So it's entry in the tfra can be used as the
10241 // initial PTS of the fragment.
10242 6 index = update_frag_index(mov, offset);
10243 6 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
10244
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (frag_stream_info &&
10245
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
10246 6 frag_stream_info->first_tfra_pts = time;
10247
10248
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
10249 6 avio_r8(f);
10250
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
10251 6 avio_r8(f);
10252
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
10253 6 avio_r8(f);
10254 }
10255
10256 2 avio_seek(f, pos + size, SEEK_SET);
10257 2 return 0;
10258 }
10259
10260 1 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
10261 {
10262 1 int64_t stream_size = avio_size(f);
10263 1 int64_t original_pos = avio_tell(f);
10264 int64_t seek_ret;
10265 1 int ret = -1;
10266
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
10267 ret = seek_ret;
10268 goto fail;
10269 }
10270 1 c->mfra_size = avio_rb32(f);
10271 1 c->have_read_mfra_size = 1;
10272
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) {
10273 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
10274 goto fail;
10275 }
10276
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) {
10277 ret = seek_ret;
10278 goto fail;
10279 }
10280
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != c->mfra_size) {
10281 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
10282 goto fail;
10283 }
10284
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
10285 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
10286 goto fail;
10287 }
10288 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
10289 do {
10290 3 ret = read_tfra(c, f);
10291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
10292 goto fail;
10293
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 } while (!ret);
10294 1 ret = 0;
10295 1 c->frag_index.complete = 1;
10296 1 fail:
10297 1 seek_ret = avio_seek(f, original_pos, SEEK_SET);
10298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (seek_ret < 0) {
10299 av_log(c->fc, AV_LOG_ERROR,
10300 "failed to seek back after looking for mfra\n");
10301 ret = seek_ret;
10302 }
10303 1 return ret;
10304 }
10305
10306 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10307 const HEIFItem *item)
10308 {
10309 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
10310 AV_PKT_DATA_ICC_PROFILE,
10311 item->icc_profile_size, 0);
10312 if (!sd)
10313 return AVERROR(ENOMEM);
10314
10315 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
10316
10317 return 0;
10318 }
10319
10320 6 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10321 const HEIFItem *item)
10322 {
10323 int32_t *matrix;
10324 6 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data,
10325 nb_coded_side_data,
10326 AV_PKT_DATA_DISPLAYMATRIX,
10327 9 * sizeof(*matrix), 0);
10328
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sd)
10329 return AVERROR(ENOMEM);
10330
10331 6 matrix = (int32_t*)sd->data;
10332 /* rotation is in the counter-clockwise direction whereas
10333 * av_display_rotation_set() expects its argument to be
10334 * oriented clockwise, so we need to negate it. */
10335 6 av_display_rotation_set(matrix, -item->rotation);
10336 6 av_display_matrix_flip(matrix, item->hflip, item->vflip);
10337
10338 6 return 0;
10339 }
10340
10341 5 static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid,
10342 AVStreamGroupTileGrid *tile_grid)
10343 {
10344 5 MOVContext *c = s->priv_data;
10345 5 const HEIFItem *item = grid->item;
10346 5 int64_t offset = 0, pos = avio_tell(s->pb);
10347 5 int x = 0, y = 0, i = 0;
10348 int tile_rows, tile_cols;
10349 int flags, size;
10350
10351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10352 av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
10353 return AVERROR_PATCHWELCOME;
10354 }
10355
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (item->is_idat_relative) {
10356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!c->idat_offset) {
10357 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
10358 return AVERROR_INVALIDDATA;
10359 }
10360 5 offset = c->idat_offset;
10361 }
10362
10363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (offset > INT64_MAX - item->extent_offset)
10364 return AVERROR_INVALIDDATA;
10365
10366 5 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10367
10368 5 avio_r8(s->pb); /* version */
10369 5 flags = avio_r8(s->pb);
10370
10371 5 tile_rows = avio_r8(s->pb) + 1;
10372 5 tile_cols = avio_r8(s->pb) + 1;
10373 /* actual width and height of output image */
10374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 tile_grid->width = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
10375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 tile_grid->height = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
10376
10377 5 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
10378 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
10379
10380 5 avio_seek(s->pb, pos, SEEK_SET);
10381
10382 5 size = tile_rows * tile_cols;
10383 5 tile_grid->nb_tiles = grid->nb_tiles;
10384
10385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (tile_grid->nb_tiles != size)
10386 return AVERROR_INVALIDDATA;
10387
10388
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < tile_cols; i++)
10389 10 tile_grid->coded_width += grid->tile_item_list[i]->width;
10390
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < size; i += tile_cols)
10391 10 tile_grid->coded_height += grid->tile_item_list[i]->height;
10392
10393 5 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!tile_grid->offsets)
10395 return AVERROR(ENOMEM);
10396
10397
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 while (y < tile_grid->coded_height) {
10398 10 int left_col = i;
10399
10400
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 while (x < tile_grid->coded_width) {
10401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (i == tile_grid->nb_tiles)
10402 return AVERROR_INVALIDDATA;
10403
10404 20 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10405 20 tile_grid->offsets[i].horizontal = x;
10406 20 tile_grid->offsets[i].vertical = y;
10407
10408 20 x += grid->tile_item_list[i++]->width;
10409 }
10410
10411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (x > tile_grid->coded_width) {
10412 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10413 return AVERROR_INVALIDDATA;
10414 }
10415
10416 10 x = 0;
10417 10 y += grid->tile_item_list[left_col]->height;
10418 }
10419
10420
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (y > tile_grid->coded_height || i != tile_grid->nb_tiles) {
10421 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10422 return AVERROR_INVALIDDATA;
10423 }
10424
10425 5 return 0;
10426 }
10427
10428 4 static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid,
10429 AVStreamGroupTileGrid *tile_grid)
10430 {
10431 4 MOVContext *c = s->priv_data;
10432 4 const HEIFItem *item = grid->item;
10433 uint16_t canvas_fill_value[4];
10434 4 int64_t offset = 0, pos = avio_tell(s->pb);
10435 4 int ret = 0, flags;
10436
10437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10438 av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
10439 return AVERROR_PATCHWELCOME;
10440 }
10441
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
10442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
10443 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
10444 return AVERROR_INVALIDDATA;
10445 }
10446 4 offset = c->idat_offset;
10447 }
10448
10449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (offset > INT64_MAX - item->extent_offset)
10450 return AVERROR_INVALIDDATA;
10451
10452 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10453
10454 4 avio_r8(s->pb); /* version */
10455 4 flags = avio_r8(s->pb);
10456
10457
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10458 16 canvas_fill_value[i] = avio_rb16(s->pb);
10459 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
10460 4 canvas_fill_value[0], canvas_fill_value[1],
10461 4 canvas_fill_value[2], canvas_fill_value[3]);
10462
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10463 16 tile_grid->background[i] = canvas_fill_value[i];
10464
10465 /* actual width and height of output image */
10466 4 tile_grid->width =
10467
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);
10468 4 tile_grid->height =
10469
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);
10470
10471 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
10472 tile_grid->width, tile_grid->height);
10473
10474 4 tile_grid->nb_tiles = grid->nb_tiles;
10475 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
10477 ret = AVERROR(ENOMEM);
10478 goto fail;
10479 }
10480
10481
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
10482 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10483
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);
10484
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);
10485 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
10486 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
10487 8 i, tile_grid->offsets[i].idx,
10488 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
10489 }
10490
10491 4 fail:
10492 4 avio_seek(s->pb, pos, SEEK_SET);
10493
10494 4 return ret;
10495 }
10496
10497 2 static int mov_parse_exif_item(AVFormatContext *s,
10498 AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10499 const HEIFItem *ref)
10500 {
10501 2 MOVContext *c = s->priv_data;
10502 AVPacketSideData *sd;
10503 2 AVExifMetadata ifd = { 0 };
10504 AVBufferRef *buf;
10505 2 int64_t offset = 0, pos = avio_tell(s->pb);
10506 2 unsigned orientation_id = av_exif_get_tag_id("Orientation");
10507 int err;
10508
10509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10510 av_log(c->fc, AV_LOG_WARNING, "Exif metadata with non seekable input\n");
10511 return AVERROR_PATCHWELCOME;
10512 }
10513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ref->is_idat_relative) {
10514 if (!c->idat_offset) {
10515 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the Exif metadata\n");
10516 return AVERROR_INVALIDDATA;
10517 }
10518 offset = c->idat_offset;
10519 }
10520
10521 2 buf = av_buffer_alloc(ref->extent_length);
10522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!buf)
10523 return AVERROR(ENOMEM);
10524
10525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset > INT64_MAX - ref->extent_offset) {
10526 err = AVERROR(ENOMEM);
10527 goto fail;
10528 }
10529
10530 2 avio_seek(s->pb, ref->extent_offset + offset, SEEK_SET);
10531 2 err = avio_read(s->pb, buf->data, ref->extent_length);
10532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != ref->extent_length) {
10533 if (err > 0)
10534 err = AVERROR_INVALIDDATA;
10535 goto fail;
10536 }
10537
10538 // HEIF spec states that Exif metadata is informative. The irot item property is
10539 // the normative source of rotation information. So we remove any Orientation tag
10540 // present in the Exif buffer.
10541 2 err = av_exif_parse_buffer(s, buf->data, ref->extent_length, &ifd, AV_EXIF_T_OFF);
10542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0) {
10543 av_log(s, AV_LOG_ERROR, "Unable to parse Exif metadata\n");
10544 goto fail;
10545 }
10546
10547 2 err = av_exif_remove_entry(s, &ifd, orientation_id, 0);
10548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
10549 goto fail;
10550
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (!err)
10551 goto finish;
10552
10553 2 av_buffer_unref(&buf);
10554 2 err = av_exif_write(s, &ifd, &buf, AV_EXIF_T_OFF);
10555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
10556 goto fail;
10557
10558 2 finish:
10559 2 offset = AV_RB32(buf->data) + 4;
10560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset >= buf->size) {
10561 err = AVERROR_INVALIDDATA;
10562 goto fail;
10563 }
10564 2 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
10565 2 AV_PKT_DATA_EXIF, buf->size - offset, 0);
10566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!sd) {
10567 err = AVERROR(ENOMEM);
10568 goto fail;
10569 }
10570 2 memcpy(sd->data, buf->data + offset, buf->size - offset);
10571
10572 2 err = 0;
10573 2 fail:
10574 2 av_buffer_unref(&buf);
10575 2 av_exif_free(&ifd);
10576 2 avio_seek(s->pb, pos, SEEK_SET);
10577
10578 2 return err;
10579 }
10580
10581 9 static int mov_parse_tiles(AVFormatContext *s)
10582 {
10583 9 MOVContext *mov = s->priv_data;
10584
10585
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for (int i = 0; i < mov->nb_heif_grid; i++) {
10586 9 AVStreamGroup *stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
10587 AVStreamGroupTileGrid *tile_grid;
10588 9 const HEIFGrid *grid = &mov->heif_grid[i];
10589 9 int err, loop = 1;
10590
10591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!stg)
10592 return AVERROR(ENOMEM);
10593
10594 9 stg->id = grid->item->item_id;
10595 9 tile_grid = stg->params.tile_grid;
10596
10597
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9 times.
37 for (int j = 0; j < grid->nb_tiles; j++) {
10598 28 int tile_id = grid->tile_id_list[j];
10599 int k;
10600
10601
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 for (k = 0; k < mov->nb_heif_item; k++) {
10602 60 HEIFItem *item = mov->heif_item[k];
10603 AVStream *st;
10604
10605
3/4
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 28 times.
60 if (!item || item->item_id != tile_id)
10606 32 continue;
10607 28 st = item->st;
10608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!st) {
10609 av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
10610 "reference a stream\n",
10611 tile_id, grid->item->item_id);
10612 ff_remove_stream_group(s, stg);
10613 loop = 0;
10614 break;
10615 }
10616
10617 28 grid->tile_item_list[j] = item;
10618 28 grid->tile_idx_list[j] = stg->nb_streams;
10619
10620 28 err = avformat_stream_group_add_stream(stg, st);
10621
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 26 times.
28 if (err < 0) {
10622 int l;
10623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
10624 return err;
10625
10626
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_streams; l++)
10627
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->streams[l]->index == st->index)
10628 2 break;
10629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_streams);
10630 2 grid->tile_idx_list[j] = l;
10631 }
10632
10633
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 6 times.
28 if (item->item_id != mov->primary_item_id)
10634 22 st->disposition |= AV_DISPOSITION_DEPENDENT;
10635 28 break;
10636 }
10637
10638
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (k == mov->nb_heif_item) {
10639 av_assert0(loop);
10640 av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
10641 "exist\n",
10642 tile_id, grid->item->item_id);
10643 ff_remove_stream_group(s, stg);
10644 loop = 0;
10645 }
10646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!loop)
10647 break;
10648 }
10649
10650
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!loop)
10651 continue;
10652
10653
2/3
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
9 switch (grid->item->type) {
10654 5 case MKTAG('g','r','i','d'):
10655 5 err = read_image_grid(s, grid, tile_grid);
10656 5 break;
10657 4 case MKTAG('i','o','v','l'):
10658 4 err = read_image_iovl(s, grid, tile_grid);
10659 4 break;
10660 default:
10661 av_assert0(0);
10662 }
10663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err < 0)
10664 return err;
10665
10666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 for (int j = 0; j < grid->item->nb_iref_list; j++) {
10667 HEIFItem *ref = get_heif_item(mov, grid->item->iref_list[j].item_id);
10668
10669 av_assert0(ref);
10670 switch(ref->type) {
10671 case MKTAG('E','x','i','f'):
10672 err = mov_parse_exif_item(s, &tile_grid->coded_side_data,
10673 &tile_grid->nb_coded_side_data, ref);
10674 if (err < 0 && (s->error_recognition & AV_EF_EXPLODE))
10675 return err;
10676 break;
10677 default:
10678 break;
10679 }
10680 }
10681
10682 /* rotation */
10683
3/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
9 if (grid->item->rotation || grid->item->hflip || grid->item->vflip) {
10684 err = set_display_matrix_from_item(&tile_grid->coded_side_data,
10685 &tile_grid->nb_coded_side_data, grid->item);
10686 if (err < 0)
10687 return err;
10688 }
10689
10690 /* ICC profile */
10691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (grid->item->icc_profile_size) {
10692 err = set_icc_profile_from_item(&tile_grid->coded_side_data,
10693 &tile_grid->nb_coded_side_data, grid->item);
10694 if (err < 0)
10695 return err;
10696 }
10697
10698
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (grid->item->name)
10699 9 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
10700
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 if (grid->item->item_id == mov->primary_item_id)
10701 5 stg->disposition |= AV_DISPOSITION_DEFAULT;
10702 }
10703
10704 9 return 0;
10705 }
10706
10707 18 static int mov_parse_heif_items(AVFormatContext *s)
10708 {
10709 18 MOVContext *mov = s->priv_data;
10710 int err;
10711
10712
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (int i = 0; i < mov->nb_heif_item; i++) {
10713 57 HEIFItem *item = mov->heif_item[i];
10714 MOVStreamContext *sc;
10715 AVStream *st;
10716 57 int64_t offset = 0;
10717
10718
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item)
10719 continue;
10720
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 43 times.
57 if (!item->st) {
10721 14 continue;
10722 }
10723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (item->is_idat_relative) {
10724 if (!mov->idat_offset) {
10725 av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
10726 return AVERROR_INVALIDDATA;
10727 }
10728 offset = mov->idat_offset;
10729 }
10730
10731 43 st = item->st;
10732 43 sc = st->priv_data;
10733 43 st->codecpar->width = item->width;
10734 43 st->codecpar->height = item->height;
10735
10736 43 sc->sample_size = sc->stsz_sample_size = item->extent_length;
10737 43 sc->sample_count = 1;
10738
10739 43 err = sanity_checks(s, sc, st->index);
10740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (err)
10741 return AVERROR_INVALIDDATA;
10742
10743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (offset > INT64_MAX - item->extent_offset)
10744 return AVERROR_INVALIDDATA;
10745
10746 43 sc->chunk_offsets[0] = item->extent_offset + offset;
10747
10748
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 30 times.
43 if (item->item_id == mov->primary_item_id)
10749 13 st->disposition |= AV_DISPOSITION_DEFAULT;
10750
10751
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 43 times.
54 for (int j = 0; j < item->nb_iref_list; j++) {
10752 11 HEIFItem *ref = get_heif_item(mov, item->iref_list[j].item_id);
10753
10754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 av_assert0(ref);
10755
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 switch(ref->type) {
10756 2 case MKTAG('E','x','i','f'):
10757 2 err = mov_parse_exif_item(s, &st->codecpar->coded_side_data,
10758 2 &st->codecpar->nb_coded_side_data, ref);
10759
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (err < 0 && (s->error_recognition & AV_EF_EXPLODE))
10760 return err;
10761 2 break;
10762 9 default:
10763 9 break;
10764 }
10765 }
10766
10767
4/6
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 37 times.
43 if (item->rotation || item->hflip || item->vflip) {
10768 6 err = set_display_matrix_from_item(&st->codecpar->coded_side_data,
10769 6 &st->codecpar->nb_coded_side_data, item);
10770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10771 return err;
10772 }
10773
10774 43 mov_build_index(mov, st);
10775 }
10776
10777
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (mov->nb_heif_grid) {
10778 9 err = mov_parse_tiles(s);
10779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err < 0)
10780 return err;
10781 }
10782
10783 18 return 0;
10784 }
10785
10786 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
10787 int first_index)
10788 {
10789 MOVStreamContext *sc = st->priv_data;
10790
10791 if (sc->tref_id < 0)
10792 return NULL;
10793
10794 for (int i = first_index; i < s->nb_streams; i++)
10795 if (s->streams[i]->index != st->index &&
10796 s->streams[i]->id == sc->tref_id)
10797 return s->streams[i];
10798
10799 return NULL;
10800 }
10801
10802 523 static int mov_parse_lcevc_streams(AVFormatContext *s)
10803 {
10804 int err;
10805
10806 // Don't try to add a group if there's only one track
10807
2/2
✓ Branch 0 taken 409 times.
✓ Branch 1 taken 114 times.
523 if (s->nb_streams <= 1)
10808 409 return 0;
10809
10810
2/2
✓ Branch 0 taken 327 times.
✓ Branch 1 taken 114 times.
441 for (int i = 0; i < s->nb_streams; i++) {
10811 AVStreamGroup *stg;
10812 327 AVStream *st = s->streams[i];
10813 AVStream *st_base;
10814 327 MOVStreamContext *sc = st->priv_data;
10815 327 int j = 0;
10816
10817 /* Find an enhancement stream. */
10818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 327 times.
327 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC ||
10819 !(sc->tref_flags & MOV_TREF_FLAG_ENHANCEMENT))
10820 327 continue;
10821
10822 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
10823 if (!stg)
10824 return AVERROR(ENOMEM);
10825
10826 stg->id = st->id;
10827 stg->params.lcevc->width = st->codecpar->width;
10828 stg->params.lcevc->height = st->codecpar->height;
10829
10830 while (st_base = mov_find_reference_track(s, st, j)) {
10831 err = avformat_stream_group_add_stream(stg, st_base);
10832 if (err < 0)
10833 return err;
10834
10835 j = st_base->index + 1;
10836 }
10837 if (!j) {
10838 int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
10839 av_log(s, loglevel, "Failed to find base stream for LCEVC stream\n");
10840 ff_remove_stream_group(s, stg);
10841 if (s->error_recognition & AV_EF_EXPLODE)
10842 return AVERROR_INVALIDDATA;
10843 continue;
10844 }
10845
10846 err = avformat_stream_group_add_stream(stg, st);
10847 if (err < 0)
10848 return err;
10849
10850 stg->params.lcevc->lcevc_index = stg->nb_streams - 1;
10851 }
10852
10853 114 return 0;
10854 }
10855
10856 523 static void fix_stream_ids(AVFormatContext *s)
10857 {
10858 523 int highest_id = 0, lowest_iamf_id = INT_MAX;
10859
10860
2/2
✓ Branch 0 taken 736 times.
✓ Branch 1 taken 523 times.
1259 for (int i = 0; i < s->nb_streams; i++) {
10861 736 const AVStream *st = s->streams[i];
10862 736 const MOVStreamContext *sc = st->priv_data;
10863
2/2
✓ Branch 0 taken 672 times.
✓ Branch 1 taken 64 times.
736 if (!sc->iamf)
10864 672 highest_id = FFMAX(highest_id, st->id);
10865 }
10866
10867
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 523 times.
556 for (int i = 0; i < s->nb_stream_groups; i++) {
10868 33 AVStreamGroup *stg = s->stream_groups[i];
10869
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 12 times.
33 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
10870 21 continue;
10871
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_streams; j++) {
10872 64 AVStream *st = stg->streams[j];
10873 64 lowest_iamf_id = FFMIN(lowest_iamf_id, st->id);
10874 }
10875 }
10876
10877
2/2
✓ Branch 0 taken 515 times.
✓ Branch 1 taken 8 times.
523 if (highest_id < lowest_iamf_id)
10878 515 return;
10879
10880 8 highest_id += !lowest_iamf_id;
10881
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++) {
10882 4 AVStreamGroup *stg = s->stream_groups[i];
10883
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
10884 2 continue;
10885
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_streams; j++) {
10886 14 AVStream *st = stg->streams[j];
10887 14 MOVStreamContext *sc = st->priv_data;
10888 14 st->id += highest_id;
10889 14 sc->iamf_stream_offset = highest_id;
10890 }
10891 }
10892 }
10893
10894 523 static int mov_read_header(AVFormatContext *s)
10895 {
10896 523 MOVContext *mov = s->priv_data;
10897 523 AVIOContext *pb = s->pb;
10898 int j, err;
10899 523 MOVAtom atom = { AV_RL32("root") };
10900 int i;
10901
10902 523 mov->fc = s;
10903 523 mov->trak_index = -1;
10904 523 mov->primary_item_id = -1;
10905 523 mov->cur_item_id = -1;
10906 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
10907
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 1 times.
523 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
10908 522 atom.size = avio_size(pb);
10909 else
10910 1 atom.size = INT64_MAX;
10911
10912 /* check MOV header */
10913 do {
10914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 523 times.
523 if (mov->moov_retry)
10915 avio_seek(pb, 0, SEEK_SET);
10916
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 523 times.
523 if ((err = mov_read_default(mov, pb, atom)) < 0) {
10917 av_log(s, AV_LOG_ERROR, "error reading header\n");
10918 return err;
10919 }
10920 1045 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10921
6/10
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 504 times.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
523 !mov->found_moov && (!mov->found_iloc || !mov->found_iinf) && !mov->moov_retry++);
10922
3/6
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 505 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
523 if (!mov->found_moov && !mov->found_iloc && !mov->found_iinf) {
10923 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
10924 return AVERROR_INVALIDDATA;
10925 }
10926 523 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
10927
10928
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 505 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
523 if (mov->found_iloc && mov->found_iinf) {
10929 18 err = mov_parse_heif_items(s);
10930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (err < 0)
10931 return err;
10932 }
10933 // prevent iloc and iinf boxes from being parsed while reading packets.
10934 // this is needed because an iinf box may have been parsed but ignored
10935 // for having old infe boxes which create no streams.
10936 523 mov->found_iloc = mov->found_iinf = 1;
10937
10938
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 1 times.
523 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
10939
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 520 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
522 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
10940 2 mov_read_chapters(s);
10941
2/2
✓ Branch 0 taken 735 times.
✓ Branch 1 taken 522 times.
1257 for (i = 0; i < s->nb_streams; i++)
10942
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 716 times.
735 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
10943 19 mov_read_timecode_track(s, s->streams[i]);
10944
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 716 times.
716 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
10945 mov_read_rtmd_track(s, s->streams[i]);
10946 }
10947 }
10948
10949 /* copy timecode metadata from tmcd tracks to the related video streams */
10950
2/2
✓ Branch 0 taken 736 times.
✓ Branch 1 taken 523 times.
1259 for (i = 0; i < s->nb_streams; i++) {
10951 736 AVStream *st = s->streams[i];
10952 736 MOVStreamContext *sc = st->priv_data;
10953
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 718 times.
736 if (sc->timecode_track > 0) {
10954 AVDictionaryEntry *tcr;
10955 18 int tmcd_st_id = -1;
10956
10957
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 18 times.
66 for (j = 0; j < s->nb_streams; j++) {
10958 48 MOVStreamContext *sc2 = s->streams[j]->priv_data;
10959
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 30 times.
48 if (sc2->id == sc->timecode_track)
10960 18 tmcd_st_id = j;
10961 }
10962
10963
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (tmcd_st_id < 0 || tmcd_st_id == i)
10964 continue;
10965 18 tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
10966
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 if (tcr)
10967 16 av_dict_set(&st->metadata, "timecode", tcr->value, 0);
10968 }
10969 }
10970 523 export_orphan_timecode(s);
10971
10972 /* Create LCEVC stream groups. */
10973 523 err = mov_parse_lcevc_streams(s);
10974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 523 times.
523 if (err < 0)
10975 return err;
10976
10977
2/2
✓ Branch 0 taken 736 times.
✓ Branch 1 taken 523 times.
1259 for (i = 0; i < s->nb_streams; i++) {
10978 736 AVStream *st = s->streams[i];
10979 736 FFStream *const sti = ffstream(st);
10980 736 MOVStreamContext *sc = st->priv_data;
10981 736 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
10982 736 fix_timescale(mov, sc);
10983
10984 /* Set the primary extradata based on the first Sample if it doesn't reference the first stsd entry. */
10985
6/6
✓ Branch 0 taken 693 times.
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 650 times.
✓ Branch 3 taken 43 times.
✓ Branch 4 taken 586 times.
✓ Branch 5 taken 64 times.
736 if (sc->stsc_count && sc->extradata_size && !sc->iamf &&
10986
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 583 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
586 sc->stsc_data[0].id > 1 && sc->stsc_data[0].id <= sc->stsd_count) {
10987 3 sc->last_stsd_index = sc->stsc_data[0].id - 1;
10988 3 av_freep(&st->codecpar->extradata);
10989 3 st->codecpar->extradata_size = sc->extradata_size[sc->last_stsd_index];
10990
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (sc->extradata_size[sc->last_stsd_index]) {
10991 3 st->codecpar->extradata = av_mallocz(sc->extradata_size[sc->last_stsd_index] + AV_INPUT_BUFFER_PADDING_SIZE);
10992
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata)
10993 return AVERROR(ENOMEM);
10994 3 memcpy(st->codecpar->extradata, sc->extradata[sc->last_stsd_index], sc->extradata_size[sc->last_stsd_index]);
10995 }
10996 }
10997
10998
2/2
✓ Branch 0 taken 299 times.
✓ Branch 1 taken 437 times.
736 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
10999
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 179 times.
299 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
11000 120 sti->skip_samples = sc->start_pad;
11001 }
11002
5/6
✓ Branch 0 taken 382 times.
✓ Branch 1 taken 354 times.
✓ Branch 2 taken 325 times.
✓ Branch 3 taken 57 times.
✓ Branch 4 taken 325 times.
✗ Branch 5 not taken.
736 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
11003 325 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
11004 325 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
11005
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 724 times.
736 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
11006
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) {
11007 8 st->codecpar->width = sc->width;
11008 8 st->codecpar->height = sc->height;
11009 }
11010
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
11011 st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
11012
11013 for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
11014 dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
11015
11016 err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
11017 if (err < 0)
11018 return err;
11019
11020 av_freep(&st->codecpar->extradata);
11021 st->codecpar->extradata_size = 0;
11022
11023 err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
11024 st->codecpar);
11025 if (err < 0)
11026 return err;
11027 }
11028 }
11029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 736 times.
736 if (mov->handbrake_version &&
11030 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
11031 st->codecpar->codec_id == AV_CODEC_ID_MP3) {
11032 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
11033 sti->need_parsing = AVSTREAM_PARSE_FULL;
11034 }
11035 }
11036
11037
3/4
✓ Branch 0 taken 504 times.
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 504 times.
523 if (mov->trex_data || mov->use_mfra_for > 0) {
11038
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 19 times.
47 for (i = 0; i < s->nb_streams; i++) {
11039 28 AVStream *st = s->streams[i];
11040 28 MOVStreamContext *sc = st->priv_data;
11041
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 4 times.
28 if (sc->duration_for_fps > 0) {
11042 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
11043 24 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
11044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (st->codecpar->bit_rate == INT64_MIN) {
11045 av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
11046 sc->data_size, sc->time_scale);
11047 st->codecpar->bit_rate = 0;
11048 if (s->error_recognition & AV_EF_EXPLODE)
11049 return AVERROR_INVALIDDATA;
11050 }
11051 }
11052 }
11053 }
11054
11055
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 523 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
523 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
11056 if (mov->bitrates[i]) {
11057 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
11058 }
11059 }
11060
11061 523 ff_rfps_calculate(s);
11062
11063
2/2
✓ Branch 0 taken 736 times.
✓ Branch 1 taken 523 times.
1259 for (i = 0; i < s->nb_streams; i++) {
11064 736 AVStream *st = s->streams[i];
11065 736 MOVStreamContext *sc = st->priv_data;
11066
11067
3/3
✓ Branch 0 taken 299 times.
✓ Branch 1 taken 382 times.
✓ Branch 2 taken 55 times.
736 switch (st->codecpar->codec_type) {
11068 299 case AVMEDIA_TYPE_AUDIO:
11069 299 err = ff_replaygain_export(st, s->metadata);
11070
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 299 times.
299 if (err < 0)
11071 return err;
11072 299 break;
11073 382 case AVMEDIA_TYPE_VIDEO:
11074
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 374 times.
382 if (sc->display_matrix) {
11075
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,
11076 AV_PKT_DATA_DISPLAYMATRIX,
11077 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
11078 return AVERROR(ENOMEM);
11079
11080 8 sc->display_matrix = NULL;
11081 }
11082
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 378 times.
382 if (sc->stereo3d) {
11083
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,
11084 AV_PKT_DATA_STEREO3D,
11085 4 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
11086 return AVERROR(ENOMEM);
11087
11088 4 sc->stereo3d = NULL;
11089 }
11090
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 378 times.
382 if (sc->spherical) {
11091
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,
11092 AV_PKT_DATA_SPHERICAL,
11093 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
11094 return AVERROR(ENOMEM);
11095
11096 4 sc->spherical = NULL;
11097 }
11098
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 382 times.
382 if (sc->mastering) {
11099 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11100 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
11101 (uint8_t *)sc->mastering, sc->mastering_size, 0))
11102 return AVERROR(ENOMEM);
11103
11104 sc->mastering = NULL;
11105 }
11106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 382 times.
382 if (sc->coll) {
11107 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11108 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
11109 (uint8_t *)sc->coll, sc->coll_size, 0))
11110 return AVERROR(ENOMEM);
11111
11112 sc->coll = NULL;
11113 }
11114
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 378 times.
382 if (sc->ambient) {
11115
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,
11116 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
11117 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
11118 return AVERROR(ENOMEM);
11119
11120 4 sc->ambient = NULL;
11121 }
11122 382 break;
11123 }
11124 }
11125
11126 523 fix_stream_ids(s);
11127
11128 523 ff_configure_buffers_for_index(s, AV_TIME_BASE);
11129
11130
2/2
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 523 times.
1000 for (i = 0; i < mov->frag_index.nb_items; i++)
11131
2/2
✓ Branch 0 taken 467 times.
✓ Branch 1 taken 10 times.
477 if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset)
11132 467 mov->frag_index.item[i].headers_read = 1;
11133
11134 523 return 0;
11135 }
11136
11137 107069 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
11138 {
11139 107069 AVIndexEntry *sample = NULL;
11140 107069 int64_t best_dts = INT64_MAX;
11141 int i;
11142 107069 MOVContext *mov = s->priv_data;
11143
3/4
✓ Branch 0 taken 107069 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 107024 times.
107069 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
11144
2/2
✓ Branch 0 taken 139990 times.
✓ Branch 1 taken 107069 times.
247059 for (i = 0; i < s->nb_streams; i++) {
11145 139990 AVStream *avst = s->streams[i];
11146 139990 FFStream *const avsti = ffstream(avst);
11147 139990 MOVStreamContext *msc = avst->priv_data;
11148
4/4
✓ Branch 0 taken 131752 times.
✓ Branch 1 taken 8238 times.
✓ Branch 2 taken 128307 times.
✓ Branch 3 taken 3445 times.
139990 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
11149 128307 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
11150 128307 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
11151
2/2
✓ Branch 0 taken 112953 times.
✓ Branch 1 taken 15354 times.
128307 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
11152 128307 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
11153
3/6
✓ Branch 0 taken 21760 times.
✓ Branch 1 taken 106547 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 21760 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
128307 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
11154
1/2
✓ Branch 0 taken 21760 times.
✗ Branch 1 not taken.
21760 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
11155
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 21760 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 21760 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 21760 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19557 times.
✓ Branch 9 taken 2203 times.
21760 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
11156
4/4
✓ Branch 0 taken 11399 times.
✓ Branch 1 taken 8158 times.
✓ Branch 2 taken 2203 times.
✓ Branch 3 taken 11399 times.
21760 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
11157
3/4
✓ Branch 0 taken 761 times.
✓ Branch 1 taken 1442 times.
✓ Branch 2 taken 761 times.
✗ Branch 3 not taken.
2203 (dtsdiff > AV_TIME_BASE && dts < best_dts && mov->interleaved_read)))))) {
11158 115466 sample = current_sample;
11159 115466 best_dts = dts;
11160 115466 *st = avst;
11161 }
11162 }
11163 }
11164 107069 return sample;
11165 }
11166
11167 9 static int should_retry(AVIOContext *pb, int error_code) {
11168
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
9 if (error_code == AVERROR_EOF || avio_feof(pb))
11169 9 return 0;
11170
11171 return 1;
11172 }
11173
11174 49 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
11175 {
11176 int ret;
11177 49 MOVContext *mov = s->priv_data;
11178
11179
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
49 if (index >= 0 && index < mov->frag_index.nb_items)
11180 1 target = mov->frag_index.item[index].moof_offset;
11181
2/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 49 times.
49 if (target >= 0 && avio_seek(s->pb, target, SEEK_SET) != target) {
11182 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
11183 return AVERROR_INVALIDDATA;
11184 }
11185
11186 49 mov->next_root_atom = 0;
11187
4/6
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
49 if ((index < 0 && target >= 0) || index >= mov->frag_index.nb_items)
11188 48 index = search_frag_moof_offset(&mov->frag_index, target);
11189
3/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 7 times.
49 if (index >= 0 && index < mov->frag_index.nb_items &&
11190
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 mov->frag_index.item[index].moof_offset == target) {
11191
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 4 times.
42 if (index + 1 < mov->frag_index.nb_items)
11192 38 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11193
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 6 times.
42 if (mov->frag_index.item[index].headers_read)
11194 36 return 0;
11195 6 mov->frag_index.item[index].headers_read = 1;
11196 }
11197
11198 13 mov->found_mdat = 0;
11199
11200 13 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
11201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (ret < 0)
11202 return ret;
11203
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 6 times.
13 if (avio_feof(s->pb))
11204 7 return AVERROR_EOF;
11205 6 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
11206
11207 6 return 1;
11208 }
11209
11210 15 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
11211 {
11212 15 MOVStreamContext *sc = st->priv_data;
11213 uint8_t *side, *extradata;
11214 int extradata_size;
11215
11216 /* Save the current index. */
11217 15 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
11218
11219 /* Notify the decoder that extradata changed. */
11220 15 extradata_size = sc->extradata_size[sc->last_stsd_index];
11221 15 extradata = sc->extradata[sc->last_stsd_index];
11222
4/6
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
15 if (st->discard != AVDISCARD_ALL && extradata_size > 0 && extradata) {
11223 12 side = av_packet_new_side_data(pkt,
11224 AV_PKT_DATA_NEW_EXTRADATA,
11225 extradata_size);
11226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!side)
11227 return AVERROR(ENOMEM);
11228 12 memcpy(side, extradata, extradata_size);
11229 }
11230
11231 15 return 0;
11232 }
11233
11234 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
11235 {
11236 /* We can't make assumptions about the structure of the payload,
11237 because it may include multiple cdat and cdt2 samples. */
11238 const uint32_t cdat = AV_RB32("cdat");
11239 const uint32_t cdt2 = AV_RB32("cdt2");
11240 int ret, out_size = 0;
11241
11242 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
11243 if (src_size < 10)
11244 return AVERROR_INVALIDDATA;
11245
11246 /* avoid an int overflow: */
11247 if ((src_size - 8) / 2 >= INT_MAX / 3)
11248 return AVERROR_INVALIDDATA;
11249
11250 ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
11251 if (ret < 0)
11252 return ret;
11253
11254 /* parse and re-format the c608 payload in one pass. */
11255 while (src_size >= 10) {
11256 const uint32_t atom_size = avio_rb32(pb);
11257 const uint32_t atom_type = avio_rb32(pb);
11258 const uint32_t data_size = atom_size - 8;
11259 const uint8_t cc_field =
11260 atom_type == cdat ? 1 :
11261 atom_type == cdt2 ? 2 :
11262 0;
11263
11264 /* account for bytes consumed for atom size and type. */
11265 src_size -= 8;
11266
11267 /* make sure the data size stays within the buffer boundaries. */
11268 if (data_size < 2 || data_size > src_size) {
11269 ret = AVERROR_INVALIDDATA;
11270 break;
11271 }
11272
11273 /* make sure the data size is consistent with N byte pairs. */
11274 if (data_size % 2 != 0) {
11275 ret = AVERROR_INVALIDDATA;
11276 break;
11277 }
11278
11279 if (!cc_field) {
11280 /* neither cdat or cdt2 ... skip it */
11281 avio_skip(pb, data_size);
11282 src_size -= data_size;
11283 continue;
11284 }
11285
11286 for (uint32_t i = 0; i < data_size; i += 2) {
11287 pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
11288 pkt->data[out_size + 1] = avio_r8(pb);
11289 pkt->data[out_size + 2] = avio_r8(pb);
11290 out_size += 3;
11291 src_size -= 2;
11292 }
11293 }
11294
11295 if (src_size > 0)
11296 /* skip any remaining unread portion of the input payload */
11297 avio_skip(pb, src_size);
11298
11299 av_shrink_packet(pkt, out_size);
11300 return ret;
11301 }
11302
11303 106502 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
11304 int64_t current_index, AVPacket *pkt)
11305 {
11306 106502 MOVStreamContext *sc = st->priv_data;
11307
11308 106502 pkt->stream_index = sc->ffindex;
11309 106502 pkt->dts = sample->timestamp;
11310
2/2
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 106236 times.
106502 if (sample->flags & AVINDEX_DISCARD_FRAME) {
11311 266 pkt->flags |= AV_PKT_FLAG_DISCARD;
11312 }
11313
4/4
✓ Branch 0 taken 86623 times.
✓ Branch 1 taken 19879 times.
✓ Branch 2 taken 86611 times.
✓ Branch 3 taken 12 times.
106502 if (sc->stts_count && sc->tts_index < sc->tts_count)
11314 86611 pkt->duration = sc->tts_data[sc->tts_index].duration;
11315
3/4
✓ Branch 0 taken 4475 times.
✓ Branch 1 taken 102027 times.
✓ Branch 2 taken 4475 times.
✗ Branch 3 not taken.
106502 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
11316 4475 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
11317 } else {
11318
2/2
✓ Branch 0 taken 15816 times.
✓ Branch 1 taken 86211 times.
102027 if (pkt->duration == 0) {
11319 15816 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
11320
2/2
✓ Branch 0 taken 15723 times.
✓ Branch 1 taken 93 times.
15816 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
11321
2/2
✓ Branch 0 taken 15770 times.
✓ Branch 1 taken 46 times.
15816 if (next_dts >= pkt->dts)
11322 15770 pkt->duration = next_dts - pkt->dts;
11323 }
11324 102027 pkt->pts = pkt->dts;
11325 }
11326
11327
4/4
✓ Branch 0 taken 86623 times.
✓ Branch 1 taken 19879 times.
✓ Branch 2 taken 86611 times.
✓ Branch 3 taken 12 times.
106502 if (sc->tts_data && sc->tts_index < sc->tts_count) {
11328 /* update tts context */
11329 86611 sc->tts_sample++;
11330
1/2
✓ Branch 0 taken 86611 times.
✗ Branch 1 not taken.
86611 if (sc->tts_index < sc->tts_count &&
11331
1/2
✓ Branch 0 taken 86611 times.
✗ Branch 1 not taken.
86611 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
11332 86611 sc->tts_index++;
11333 86611 sc->tts_sample = 0;
11334 }
11335 }
11336
11337
4/4
✓ Branch 0 taken 1045 times.
✓ Branch 1 taken 105457 times.
✓ Branch 2 taken 913 times.
✓ Branch 3 taken 132 times.
106502 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
11338 913 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
11339 913 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
11340
2/2
✓ Branch 0 taken 316 times.
✓ Branch 1 taken 597 times.
913 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
11341 }
11342 106502 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
11343 106502 pkt->pos = sample->pos;
11344
11345 /* Multiple stsd handling. */
11346
2/2
✓ Branch 0 taken 103126 times.
✓ Branch 1 taken 3376 times.
106502 if (sc->stsc_data) {
11347
1/2
✓ Branch 0 taken 103126 times.
✗ Branch 1 not taken.
103126 if (sc->stsc_data[sc->stsc_index].id > 0 &&
11348
2/2
✓ Branch 0 taken 103083 times.
✓ Branch 1 taken 43 times.
103126 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
11349
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 103068 times.
103083 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
11350 15 int ret = mov_change_extradata(st, pkt);
11351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (ret < 0)
11352 return ret;
11353 }
11354
11355 /* Update the stsc index for the next sample */
11356 103126 sc->stsc_sample++;
11357
2/2
✓ Branch 1 taken 55281 times.
✓ Branch 2 taken 47845 times.
103126 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
11358
2/2
✓ Branch 1 taken 1211 times.
✓ Branch 2 taken 54070 times.
55281 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
11359 1211 sc->stsc_index++;
11360 1211 sc->stsc_sample = 0;
11361 }
11362 }
11363
11364 106502 return 0;
11365 }
11366
11367 97888 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
11368 {
11369 97888 MOVContext *mov = s->priv_data;
11370 MOVStreamContext *sc;
11371 AVIndexEntry *sample;
11372 97888 AVStream *st = NULL;
11373 97888 FFStream *avsti = NULL;
11374 int64_t current_index;
11375 int ret;
11376 int i;
11377 97888 mov->fc = s;
11378 9181 retry:
11379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107069 times.
107069 if (s->pb->pos == 0) {
11380
11381 // Discard current fragment index
11382 if (mov->frag_index.allocated_size > 0) {
11383 for(int i = 0; i < mov->frag_index.nb_items; i++) {
11384 av_freep(&mov->frag_index.item[i].stream_info);
11385 }
11386 av_freep(&mov->frag_index.item);
11387 mov->frag_index.nb_items = 0;
11388 mov->frag_index.allocated_size = 0;
11389 mov->frag_index.current = -1;
11390 mov->frag_index.complete = 0;
11391 }
11392
11393 for (i = 0; i < s->nb_streams; i++) {
11394 AVStream *avst = s->streams[i];
11395 MOVStreamContext *msc = avst->priv_data;
11396
11397 // Clear current sample
11398 mov_current_sample_set(msc, 0);
11399 msc->tts_index = 0;
11400
11401 // Discard current index entries
11402 avsti = ffstream(avst);
11403 if (avsti->index_entries_allocated_size > 0) {
11404 av_freep(&avsti->index_entries);
11405 avsti->index_entries_allocated_size = 0;
11406 avsti->nb_index_entries = 0;
11407 }
11408 }
11409
11410 if ((ret = mov_switch_root(s, -1, -1)) < 0)
11411 return ret;
11412 }
11413 107069 sample = mov_find_next_sample(s, &st);
11414
6/6
✓ Branch 0 taken 106547 times.
✓ Branch 1 taken 522 times.
✓ Branch 2 taken 654 times.
✓ Branch 3 taken 105893 times.
✓ Branch 4 taken 36 times.
✓ Branch 5 taken 618 times.
107069 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
11415
2/2
✓ Branch 0 taken 510 times.
✓ Branch 1 taken 48 times.
558 if (!mov->next_root_atom)
11416 510 return AVERROR_EOF;
11417
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 41 times.
48 if ((ret = mov_switch_root(s, mov->next_root_atom, -1)) < 0)
11418 7 return ret;
11419 41 goto retry;
11420 }
11421 106511 sc = st->priv_data;
11422 /* must be done just before reading, to avoid infinite loop on sample */
11423 106511 current_index = sc->current_index;
11424 106511 mov_current_sample_inc(sc);
11425
11426
2/2
✓ Branch 0 taken 618 times.
✓ Branch 1 taken 105893 times.
106511 if (mov->next_root_atom) {
11427 618 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
11428 618 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
11429 }
11430
11431
4/4
✓ Branch 0 taken 9149 times.
✓ Branch 1 taken 97362 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 9140 times.
106511 if (st->discard != AVDISCARD_ALL || sc->iamf) {
11432 97371 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
11433
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 97364 times.
97371 if (ret64 != sample->pos) {
11434 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
11435 sc->ffindex, sample->pos);
11436
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
11437 mov_current_sample_dec(sc);
11438
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
11439 7 return (int)ret64;
11440 }
11441 return AVERROR_INVALIDDATA;
11442 }
11443
11444
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 97364 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
97364 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
11445 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
11446 goto retry;
11447 }
11448
11449
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 97364 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
97364 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
11450 ret = get_eia608_packet(sc->pb, pkt, sample->size);
11451 #if CONFIG_IAMFDEC
11452
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 97289 times.
97364 else if (sc->iamf) {
11453 int64_t pts, dts, pos, duration;
11454 75 int flags, size = sample->size;
11455 75 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11456 75 pts = pkt->pts; dts = pkt->dts;
11457 75 pos = pkt->pos; flags = pkt->flags;
11458 75 duration = pkt->duration;
11459
3/4
✓ Branch 0 taken 490 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 415 times.
✓ Branch 3 taken 75 times.
490 while (!ret && size > 0) {
11460 415 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
11461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 415 times.
415 if (ret < 0) {
11462 if (should_retry(sc->pb, ret))
11463 mov_current_sample_dec(sc);
11464 return ret;
11465 }
11466 415 size -= ret;
11467
11468
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 307 times.
415 if (pkt->flags & AV_PKT_FLAG_DISCARD) {
11469 108 av_packet_unref(pkt);
11470 108 ret = 0;
11471 108 continue;
11472 }
11473 307 pkt->pts = pts; pkt->dts = dts;
11474 307 pkt->pos = pos; pkt->flags |= flags;
11475 307 pkt->duration = duration;
11476 307 ret = ff_buffer_packet(s, pkt);
11477 }
11478
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 if (!ret)
11479 75 return FFERROR_REDO;
11480 }
11481 #endif
11482
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 97286 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
97292 else if (st->codecpar->codec_id == AV_CODEC_ID_APV && sample->size > 4) {
11483 3 const uint32_t au_size = avio_rb32(sc->pb);
11484 3 ret = av_get_packet(sc->pb, pkt, au_size);
11485 } else
11486 97286 ret = av_get_packet(sc->pb, pkt, sample->size);
11487
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 97287 times.
97289 if (ret < 0) {
11488
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (should_retry(sc->pb, ret)) {
11489 mov_current_sample_dec(sc);
11490 }
11491 2 return ret;
11492 }
11493 #if CONFIG_DV_DEMUXER
11494
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 97287 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
97287 if (mov->dv_demux && sc->dv_audio_container) {
11495 ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
11496 av_packet_unref(pkt);
11497 if (ret < 0)
11498 return ret;
11499 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
11500 if (ret < 0)
11501 return ret;
11502 }
11503 #endif
11504
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 97269 times.
97287 if (sc->has_palette) {
11505 uint8_t *pal;
11506
11507 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
11508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
11509 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
11510 } else {
11511 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
11512 18 sc->has_palette = 0;
11513 }
11514 }
11515
4/6
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 96999 times.
✓ Branch 3 taken 288 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 288 times.
✗ Branch 6 not taken.
97287 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
11516
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 288 times.
288 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
11517 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
11518 }
11519 }
11520
11521 106427 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106427 times.
106427 if (ret < 0)
11523 return ret;
11524
11525
2/2
✓ Branch 0 taken 9140 times.
✓ Branch 1 taken 97287 times.
106427 if (st->discard == AVDISCARD_ALL)
11526 9140 goto retry;
11527
11528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97287 times.
97287 if (mov->aax_mode)
11529 aax_filter(pkt->data, pkt->size, mov);
11530
11531 97287 ret = cenc_filter(mov, st, sc, pkt, current_index);
11532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97287 times.
97287 if (ret < 0) {
11533 return ret;
11534 }
11535
11536 97287 return 0;
11537 }
11538
11539 363 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
11540 {
11541 363 MOVContext *mov = s->priv_data;
11542 int index;
11543
11544
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 28 times.
363 if (!mov->frag_index.complete)
11545 335 return 0;
11546
11547 28 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
11548
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 24 times.
28 if (index < 0)
11549 4 index = 0;
11550
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (!mov->frag_index.item[index].headers_read)
11551 1 return mov_switch_root(s, -1, index);
11552
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (index + 1 < mov->frag_index.nb_items)
11553 27 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11554
11555 27 return 0;
11556 }
11557
11558 static int is_open_key_sample(const MOVStreamContext *sc, int sample)
11559 {
11560 // TODO: a bisect search would scale much better
11561 for (int i = 0; i < sc->open_key_samples_count; i++) {
11562 const int oks = sc->open_key_samples[i];
11563 if (oks == sample)
11564 return 1;
11565 if (oks > sample) /* list is monotically increasing so we can stop early */
11566 break;
11567 }
11568 return 0;
11569 }
11570
11571 /*
11572 * Some key sample may be key frames but not IDR frames, so a random access to
11573 * them may not be allowed.
11574 */
11575 231 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
11576 {
11577 231 MOVStreamContext *sc = st->priv_data;
11578 231 FFStream *const sti = ffstream(st);
11579 int64_t key_sample_dts, key_sample_pts;
11580
11581
1/2
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
231 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
11582 231 return 1;
11583
11584 if (sample >= sc->sample_offsets_count)
11585 return 1;
11586
11587 key_sample_dts = sti->index_entries[sample].timestamp;
11588 key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
11589
11590 /*
11591 * If the sample needs to be presented before an open key sample, they may
11592 * not be decodable properly, even though they come after in decoding
11593 * order.
11594 */
11595 if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
11596 return 0;
11597
11598 return 1;
11599 }
11600
11601 363 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
11602 {
11603 363 MOVStreamContext *sc = st->priv_data;
11604 363 FFStream *const sti = ffstream(st);
11605 int sample, time_sample, ret, requested_sample;
11606 int64_t next_ts;
11607 unsigned int i;
11608
11609 // Here we consider timestamp to be PTS, hence try to offset it so that we
11610 // can search over the DTS timeline.
11611 363 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
11612
11613 363 ret = mov_seek_fragment(s, st, timestamp);
11614
1/2
✓ Branch 0 taken 363 times.
✗ Branch 1 not taken.
363 if (ret < 0)
11615 return ret;
11616
11617 for (;;) {
11618 363 sample = av_index_search_timestamp(st, timestamp, flags);
11619 363 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
11620
5/6
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 294 times.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
✓ Branch 5 taken 26 times.
363 if (sample < 0 && sti->nb_index_entries && timestamp < sti->index_entries[0].timestamp)
11621 43 sample = 0;
11622
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 337 times.
363 if (sample < 0) /* not sure what to do */
11623 26 return AVERROR_INVALIDDATA;
11624
11625
3/4
✓ Branch 0 taken 231 times.
✓ Branch 1 taken 106 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 231 times.
337 if (!sample || can_seek_to_key_sample(st, sample, timestamp))
11626 break;
11627
11628 next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
11629 requested_sample = av_index_search_timestamp(st, next_ts, flags);
11630
11631 // If we've reached a different sample trying to find a good pts to
11632 // seek to, give up searching because we'll end up seeking back to
11633 // sample 0 on every seek.
11634 if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
11635 break;
11636
11637 timestamp = next_ts;
11638 }
11639
11640 337 mov_current_sample_set(sc, sample);
11641 337 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
11642 /* adjust time to sample index */
11643
2/2
✓ Branch 0 taken 212 times.
✓ Branch 1 taken 125 times.
337 if (sc->tts_data) {
11644 212 time_sample = 0;
11645
1/2
✓ Branch 0 taken 60308 times.
✗ Branch 1 not taken.
60308 for (i = 0; i < sc->tts_count; i++) {
11646 60308 int next = time_sample + sc->tts_data[i].count;
11647
2/2
✓ Branch 0 taken 212 times.
✓ Branch 1 taken 60096 times.
60308 if (next > sc->current_sample) {
11648 212 sc->tts_index = i;
11649 212 sc->tts_sample = sc->current_sample - time_sample;
11650 212 break;
11651 }
11652 60096 time_sample = next;
11653 }
11654 }
11655
11656 /* adjust stsd index */
11657
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 28 times.
337 if (sc->chunk_count) {
11658 309 time_sample = 0;
11659
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
381 for (i = 0; i < sc->stsc_count; i++) {
11660 381 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
11661
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 72 times.
381 if (next > sc->current_sample) {
11662 309 sc->stsc_index = i;
11663 309 sc->stsc_sample = sc->current_sample - time_sample;
11664 309 break;
11665 }
11666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
11667 72 time_sample = next;
11668 }
11669 }
11670
11671 337 return sample;
11672 }
11673
11674 337 static int64_t mov_get_skip_samples(AVStream *st, int sample)
11675 {
11676 337 MOVStreamContext *sc = st->priv_data;
11677 337 FFStream *const sti = ffstream(st);
11678 337 int64_t first_ts = sti->index_entries[0].timestamp;
11679 337 int64_t ts = sti->index_entries[sample].timestamp;
11680 int64_t off;
11681
11682
2/2
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 152 times.
337 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
11683 185 return 0;
11684
11685 /* compute skip samples according to stream start_pad, seek ts and first ts */
11686 152 off = av_rescale_q(ts - first_ts, st->time_base,
11687 152 (AVRational){1, st->codecpar->sample_rate});
11688 152 return FFMAX(sc->start_pad - off, 0);
11689 }
11690
11691 341 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
11692 {
11693 341 MOVContext *mc = s->priv_data;
11694 AVStream *st;
11695 FFStream *sti;
11696 int sample;
11697 int i;
11698
11699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
341 if (stream_index >= s->nb_streams)
11700 return AVERROR_INVALIDDATA;
11701
11702 341 st = s->streams[stream_index];
11703 341 sti = ffstream(st);
11704 341 sample = mov_seek_stream(s, st, sample_time, flags);
11705
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 315 times.
341 if (sample < 0)
11706 26 return sample;
11707
11708
1/2
✓ Branch 0 taken 315 times.
✗ Branch 1 not taken.
315 if (mc->seek_individually) {
11709 /* adjust seek timestamp to found sample timestamp */
11710 315 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
11711 315 sti->skip_samples = mov_get_skip_samples(st, sample);
11712
11713
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 315 times.
652 for (i = 0; i < s->nb_streams; i++) {
11714 337 AVStream *const st = s->streams[i];
11715 337 FFStream *const sti = ffstream(st);
11716 int64_t timestamp;
11717
11718
2/2
✓ Branch 0 taken 315 times.
✓ Branch 1 taken 22 times.
337 if (stream_index == i)
11719 315 continue;
11720
11721 22 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
11722 22 sample = mov_seek_stream(s, st, timestamp, flags);
11723
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (sample >= 0)
11724 22 sti->skip_samples = mov_get_skip_samples(st, sample);
11725 }
11726 } else {
11727 for (i = 0; i < s->nb_streams; i++) {
11728 MOVStreamContext *sc;
11729 st = s->streams[i];
11730 sc = st->priv_data;
11731 mov_current_sample_set(sc, 0);
11732 }
11733 while (1) {
11734 MOVStreamContext *sc;
11735 AVIndexEntry *entry = mov_find_next_sample(s, &st);
11736 if (!entry)
11737 return AVERROR_INVALIDDATA;
11738 sc = st->priv_data;
11739 if (sc->ffindex == stream_index && sc->current_sample == sample)
11740 break;
11741 mov_current_sample_inc(sc);
11742 }
11743 }
11744 315 return 0;
11745 }
11746
11747 #define OFFSET(x) offsetof(MOVContext, x)
11748 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
11749 static const AVOption mov_options[] = {
11750 {"use_absolute_path",
11751 "allow using absolute path when opening alias, this is a possible security issue",
11752 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
11753 0, 1, FLAGS},
11754 {"seek_streams_individually",
11755 "Seek each stream individually to the closest point",
11756 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
11757 0, 1, FLAGS},
11758 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
11759 0, 1, FLAGS},
11760 {"advanced_editlist",
11761 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
11762 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
11763 0, 1, FLAGS},
11764 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
11765 0, 1, FLAGS},
11766 {"use_mfra_for",
11767 "use mfra for fragment timestamps",
11768 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
11769 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
11770 .unit = "use_mfra_for"},
11771 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
11772 FLAGS, .unit = "use_mfra_for" },
11773 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
11774 FLAGS, .unit = "use_mfra_for" },
11775 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
11776 FLAGS, .unit = "use_mfra_for" },
11777 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
11778 0, 1, FLAGS},
11779 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
11780 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11781 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
11782 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11783 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
11784 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11785 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
11786 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11787 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
11788 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11789 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
11790 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
11791 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
11792 .flags = AV_OPT_FLAG_DECODING_PARAM },
11793 { "decryption_key", "The default media decryption key (hex)", OFFSET(decryption_default_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11794 { "decryption_keys", "The media decryption keys by KID (hex)", OFFSET(decryption_keys), AV_OPT_TYPE_DICT, .flags = AV_OPT_FLAG_DECODING_PARAM },
11795 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
11796 {.i64 = 0}, 0, 1, FLAGS },
11797 { "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 },
11798 { "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 },
11799
11800 { NULL },
11801 };
11802
11803 static const AVClass mov_class = {
11804 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
11805 .item_name = av_default_item_name,
11806 .option = mov_options,
11807 .version = LIBAVUTIL_VERSION_INT,
11808 };
11809
11810 const FFInputFormat ff_mov_demuxer = {
11811 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
11812 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
11813 .p.priv_class = &mov_class,
11814 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4v,m4b,ism,ismv,isma,f4v,avif,heic,heif",
11815 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
11816 .priv_data_size = sizeof(MOVContext),
11817 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
11818 .read_probe = mov_probe,
11819 .read_header = mov_read_header,
11820 .read_packet = mov_read_packet,
11821 .read_close = mov_read_close,
11822 .read_seek = mov_read_seek,
11823 };
11824