FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2026-05-03 23:58:45
Exec Total Coverage
Lines: 4520 7086 63.8%
Functions: 180 217 82.9%
Branches: 2575 4753 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 ret = ff_alloc_extradata(st->codecpar, descriptors_size);
936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
937 return ret;
938
939 12 ret = avio_read(pb, st->codecpar->extradata, descriptors_size);
940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret != descriptors_size)
941 return ret < 0 ? ret : AVERROR_INVALIDDATA;
942
943 12 ffio_init_read_context(&b, st->codecpar->extradata, descriptors_size);
944 12 descriptor_pb = &b.pub;
945
946 12 ret = ff_iamfdec_read_descriptors(iamf, descriptor_pb, descriptors_size, c->fc);
947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
948 return ret;
949
950 12 metadata = st->metadata;
951 12 st->metadata = NULL;
952 12 start_time = st->start_time;
953 12 nb_frames = st->nb_frames;
954 12 duration = st->duration;
955 12 disposition = st->disposition;
956
957
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_audio_elements; i++) {
958 12 IAMFAudioElement *audio_element = iamf->audio_elements[i];
959 const AVIAMFAudioElement *element;
960 AVStreamGroup *stg =
961 12 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, NULL);
962
963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!stg) {
964 ret = AVERROR(ENOMEM);
965 goto fail;
966 }
967
968 12 av_iamf_audio_element_free(&stg->params.iamf_audio_element);
969 12 stg->id = audio_element->audio_element_id;
970 /* Transfer ownership */
971 12 element = stg->params.iamf_audio_element = audio_element->element;
972 12 audio_element->element = NULL;
973
974
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < audio_element->nb_substreams; j++) {
975 64 IAMFSubStream *substream = &audio_element->substreams[j];
976 AVStream *stream;
977
978
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) {
979
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
12 if (audio_element->layers[0].substream_count != 1)
980 2 disposition &= ~AV_DISPOSITION_DEFAULT;
981 12 stream = st;
982 } else
983 52 stream = avformat_new_stream(c->fc, NULL);
984
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (!stream) {
985 ret = AVERROR(ENOMEM);
986 goto fail;
987 }
988
989 64 stream->start_time = start_time;
990 64 stream->nb_frames = nb_frames;
991 64 stream->duration = duration;
992 64 stream->disposition = disposition;
993
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 12 times.
64 if (stream != st) {
994 52 stream->priv_data = sc;
995 52 sc->refcount++;
996 }
997
998
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 56 times.
64 if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
999 8 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1000
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) {
1001 52 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1002
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 6 times.
52 if (audio_element->layers[0].substream_count == 1)
1003 46 stream->disposition &= ~AV_DISPOSITION_DEFAULT;
1004 }
1005
1006 64 ret = avcodec_parameters_copy(stream->codecpar, substream->codecpar);
1007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
1008 goto fail;
1009
1010 64 stream->id = substream->audio_substream_id;
1011
1012 64 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
1013
1014 64 ret = avformat_stream_group_add_stream(stg, stream);
1015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
1016 goto fail;
1017 }
1018
1019 12 ret = av_dict_copy(&stg->metadata, metadata, 0);
1020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1021 goto fail;
1022 }
1023
1024
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1025 12 IAMFMixPresentation *mix_presentation = iamf->mix_presentations[i];
1026 12 const AVIAMFMixPresentation *mix = mix_presentation->cmix;
1027 AVStreamGroup *stg =
1028 12 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, NULL);
1029
1030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!stg) {
1031 ret = AVERROR(ENOMEM);
1032 goto fail;
1033 }
1034
1035 12 av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
1036 12 stg->id = mix_presentation->mix_presentation_id;
1037 /* Transfer ownership */
1038 12 stg->params.iamf_mix_presentation = mix_presentation->mix;
1039 12 mix_presentation->mix = NULL;
1040
1041
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 12 times.
26 for (int j = 0; j < mix->nb_submixes; j++) {
1042 14 const AVIAMFSubmix *submix = mix->submixes[j];
1043
1044
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
28 for (int k = 0; k < submix->nb_elements; k++) {
1045 14 const AVIAMFSubmixElement *submix_element = submix->elements[k];
1046 14 const AVStreamGroup *audio_element = NULL;
1047
1048
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 for (int l = 0; l < c->fc->nb_stream_groups; l++)
1049
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 &&
1050
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 c->fc->stream_groups[l]->id == submix_element->audio_element_id) {
1051 14 audio_element = c->fc->stream_groups[l];
1052 14 break;
1053 }
1054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 av_assert0(audio_element);
1055
1056
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 14 times.
80 for (int l = 0; l < audio_element->nb_streams; l++) {
1057 66 ret = avformat_stream_group_add_stream(stg, audio_element->streams[l]);
1058
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))
1059 goto fail;
1060 }
1061 }
1062 }
1063
1064 12 ret = av_dict_copy(&stg->metadata, metadata, 0);
1065
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1066 goto fail;
1067 }
1068
1069 12 ret = 0;
1070 12 fail:
1071 12 av_dict_free(&metadata);
1072
1073 12 return ret;
1074 }
1075 #endif
1076
1077 5 static int mov_read_srat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1078 {
1079 AVStream *st;
1080 int32_t sample_rate;
1081
1082
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)
1083 return 0;
1084
1085 5 st = c->fc->streams[c->fc->nb_streams-1];
1086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
1087 av_log(c->fc, AV_LOG_WARNING, "'srat' within non-audio sample entry, skip\n");
1088 return 0;
1089 }
1090
1091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!c->isom) {
1092 av_log(c->fc, AV_LOG_WARNING, "'srat' within non-isom, skip\n");
1093 return 0;
1094 }
1095
1096 5 avio_skip(pb, 4); // version+flags
1097 5 sample_rate = avio_rb32(pb);
1098
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (sample_rate > 0) {
1099 5 av_log(c->fc, AV_LOG_DEBUG,
1100 "overwrite sample rate from %d to %d by 'srat'\n",
1101 5 st->codecpar->sample_rate, sample_rate);
1102 5 st->codecpar->sample_rate = sample_rate;
1103 } else {
1104 av_log(c->fc, AV_LOG_WARNING,
1105 "ignore invalid sample rate %d in 'srat'\n", sample_rate);
1106 }
1107
1108 5 return 0;
1109 }
1110
1111 1 static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1112 {
1113 AVStream *st;
1114 AVPacketSideData *sd;
1115 enum AVAudioServiceType *ast;
1116 int eac3info, acmod, lfeon, bsmod;
1117 uint64_t mask;
1118
1119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
1120 return 0;
1121 1 st = c->fc->streams[c->fc->nb_streams-1];
1122
1123 1 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1124 1 &st->codecpar->nb_coded_side_data,
1125 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
1126 sizeof(*ast), 0);
1127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sd)
1128 return AVERROR(ENOMEM);
1129
1130 1 ast = (enum AVAudioServiceType*)sd->data;
1131
1132 /* No need to parse fields for additional independent substreams and its
1133 * associated dependent substreams since libavcodec's E-AC-3 decoder
1134 * does not support them yet. */
1135 1 avio_rb16(pb); /* data_rate and num_ind_sub */
1136 1 eac3info = avio_rb24(pb);
1137 1 bsmod = (eac3info >> 12) & 0x1f;
1138 1 acmod = (eac3info >> 9) & 0x7;
1139 1 lfeon = (eac3info >> 8) & 0x1;
1140
1141 1 mask = ff_ac3_channel_layout_tab[acmod];
1142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (lfeon)
1143 mask |= AV_CH_LOW_FREQUENCY;
1144 1 av_channel_layout_uninit(&st->codecpar->ch_layout);
1145 1 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
1146
1147 1 *ast = bsmod;
1148
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)
1149 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
1150
1151 1 return 0;
1152 }
1153
1154 static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1155 {
1156 #define DDTS_SIZE 20
1157 uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
1158 AVStream *st = NULL;
1159 uint32_t frame_duration_code = 0;
1160 uint32_t channel_layout_code = 0;
1161 GetBitContext gb;
1162 int ret;
1163
1164 if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
1165 return ret;
1166
1167 init_get_bits(&gb, buf, 8 * DDTS_SIZE);
1168
1169 if (c->fc->nb_streams < 1) {
1170 return 0;
1171 }
1172 st = c->fc->streams[c->fc->nb_streams-1];
1173
1174 st->codecpar->sample_rate = get_bits_long(&gb, 32);
1175 if (st->codecpar->sample_rate <= 0) {
1176 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
1177 return AVERROR_INVALIDDATA;
1178 }
1179 skip_bits_long(&gb, 32); /* max bitrate */
1180 st->codecpar->bit_rate = get_bits_long(&gb, 32);
1181 st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
1182 frame_duration_code = get_bits(&gb, 2);
1183 skip_bits(&gb, 30); /* various fields */
1184 channel_layout_code = get_bits(&gb, 16);
1185
1186 st->codecpar->frame_size =
1187 (frame_duration_code == 0) ? 512 :
1188 (frame_duration_code == 1) ? 1024 :
1189 (frame_duration_code == 2) ? 2048 :
1190 (frame_duration_code == 3) ? 4096 : 0;
1191
1192 if (channel_layout_code > 0xff) {
1193 av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout\n");
1194 }
1195 av_channel_layout_uninit(&st->codecpar->ch_layout);
1196 av_channel_layout_from_mask(&st->codecpar->ch_layout,
1197 ((channel_layout_code & 0x1) ? AV_CH_FRONT_CENTER : 0) |
1198 ((channel_layout_code & 0x2) ? AV_CH_FRONT_LEFT : 0) |
1199 ((channel_layout_code & 0x2) ? AV_CH_FRONT_RIGHT : 0) |
1200 ((channel_layout_code & 0x4) ? AV_CH_SIDE_LEFT : 0) |
1201 ((channel_layout_code & 0x4) ? AV_CH_SIDE_RIGHT : 0) |
1202 ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0));
1203
1204 return 0;
1205 }
1206
1207 52 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1208 {
1209 AVStream *st;
1210
1211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (c->fc->nb_streams < 1)
1212 return 0;
1213 52 st = c->fc->streams[c->fc->nb_streams-1];
1214
1215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (atom.size < 16)
1216 return 0;
1217
1218 /* skip version and flags */
1219 52 avio_skip(pb, 4);
1220
1221 52 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
1222
1223 52 return 0;
1224 }
1225
1226 5 static int mov_read_chnl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1227 {
1228 5 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
1229 int version, flags;
1230 int ret;
1231 AVStream *st;
1232
1233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
1234 return 0;
1235 5 st = c->fc->streams[c->fc->nb_streams-1];
1236
1237 5 version = avio_r8(pb);
1238 5 flags = avio_rb24(pb);
1239
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) {
1240 av_log(c->fc, AV_LOG_ERROR,
1241 "Unsupported 'chnl' box with version %d, flags: %#x",
1242 version, flags);
1243 return AVERROR_INVALIDDATA;
1244 }
1245
1246 5 ret = ff_mov_read_chnl(c->fc, pb, st);
1247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
1248 return ret;
1249
1250
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_tell(pb) != end) {
1251 av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data inside chnl\n",
1252 end - avio_tell(pb));
1253 avio_seek(pb, end, SEEK_SET);
1254 }
1255 5 return ret;
1256 }
1257
1258 2 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1259 {
1260 AVStream *st;
1261 int ret;
1262
1263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
1264 return 0;
1265 2 st = c->fc->streams[c->fc->nb_streams-1];
1266
1267
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)
1268 av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
1269
1270 2 return ret;
1271 }
1272
1273 18 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1274 {
1275 AVStream *st;
1276 HEIFItem *item;
1277 AVPacketSideData *sd;
1278 18 int width, height, err = 0;
1279 AVRational aperture_width, aperture_height, horiz_off, vert_off;
1280 AVRational pc_x, pc_y;
1281 uint64_t top, bottom, left, right;
1282
1283 18 item = get_heif_item(c, c->cur_item_id);
1284 18 st = get_curr_st(c);
1285
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!st)
1286 return 0;
1287
1288 18 width = st->codecpar->width;
1289 18 height = st->codecpar->height;
1290
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) {
1291 6 width = item->width;
1292 6 height = item->height;
1293 }
1294
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (!width || !height) {
1295 err = AVERROR_INVALIDDATA;
1296 goto fail;
1297 }
1298
1299 18 aperture_width.num = avio_rb32(pb);
1300 18 aperture_width.den = avio_rb32(pb);
1301 18 aperture_height.num = avio_rb32(pb);
1302 18 aperture_height.den = avio_rb32(pb);
1303
1304 18 horiz_off.num = avio_rb32(pb);
1305 18 horiz_off.den = avio_rb32(pb);
1306 18 vert_off.num = avio_rb32(pb);
1307 18 vert_off.den = avio_rb32(pb);
1308
1309
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 ||
1310
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 ||
1311
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) {
1312 err = AVERROR_INVALIDDATA;
1313 goto fail;
1314 }
1315
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) ||
1316 15 (av_cmp_q((AVRational) { height, 1 }, aperture_height) < 0)) {
1317 3 err = AVERROR_INVALIDDATA;
1318 3 goto fail;
1319 }
1320 15 av_log(c->fc, AV_LOG_TRACE, "clap: apertureWidth %d/%d, apertureHeight %d/%d "
1321 "horizOff %d/%d vertOff %d/%d\n",
1322 aperture_width.num, aperture_width.den, aperture_height.num, aperture_height.den,
1323 horiz_off.num, horiz_off.den, vert_off.num, vert_off.den);
1324
1325 15 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1326 15 pc_x = av_add_q(pc_x, horiz_off);
1327 15 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1328 15 pc_y = av_add_q(pc_y, vert_off);
1329
1330 15 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1331 15 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1332 15 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1333 15 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1334
1335 15 left = av_q2d(av_sub_q(pc_x, aperture_width));
1336 15 right = av_q2d(av_add_q(pc_x, aperture_width));
1337 15 top = av_q2d(av_sub_q(pc_y, aperture_height));
1338 15 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1339
1340
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (bottom > (height - 1) ||
1341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 right > (width - 1)) {
1342 err = AVERROR_INVALIDDATA;
1343 goto fail;
1344 }
1345
1346 15 bottom = height - 1 - bottom;
1347 15 right = width - 1 - right;
1348
1349
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
15 if (!(left | right | top | bottom))
1350 6 return 0;
1351
1352
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if ((left + right) >= width ||
1353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 (top + bottom) >= height) {
1354 err = AVERROR_INVALIDDATA;
1355 goto fail;
1356 }
1357
1358 9 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1359 9 &st->codecpar->nb_coded_side_data,
1360 AV_PKT_DATA_FRAME_CROPPING,
1361 sizeof(uint32_t) * 4, 0);
1362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sd)
1363 return AVERROR(ENOMEM);
1364
1365 9 AV_WL32A(sd->data, top);
1366 9 AV_WL32A(sd->data + 4, bottom);
1367 9 AV_WL32A(sd->data + 8, left);
1368 9 AV_WL32A(sd->data + 12, right);
1369
1370 12 fail:
1371
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 if (err < 0) {
1372 3 int explode = !!(c->fc->error_recognition & AV_EF_EXPLODE);
1373
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");
1374
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!explode)
1375 3 err = 0;
1376 }
1377
1378 12 return err;
1379 }
1380
1381 /* This atom overrides any previously set aspect ratio */
1382 79 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1383 {
1384 79 const int num = avio_rb32(pb);
1385 79 const int den = avio_rb32(pb);
1386 AVStream *st;
1387 MOVStreamContext *sc;
1388
1389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (c->fc->nb_streams < 1)
1390 return 0;
1391 79 st = c->fc->streams[c->fc->nb_streams-1];
1392 79 sc = st->priv_data;
1393
1394 79 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1395
1396
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 2 times.
79 if (den != 0) {
1397 77 sc->h_spacing = num;
1398 77 sc->v_spacing = den;
1399 }
1400 79 return 0;
1401 }
1402
1403 /* this atom contains actual media data */
1404 980 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1405 {
1406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 980 times.
980 if (atom.size == 0) /* wrong one (MP4) */
1407 return 0;
1408 980 c->found_mdat=1;
1409 980 return 0; /* now go for moov */
1410 }
1411
1412 #define DRM_BLOB_SIZE 56
1413
1414 static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1415 {
1416 uint8_t intermediate_key[20];
1417 uint8_t intermediate_iv[20];
1418 uint8_t input[64];
1419 uint8_t output[64];
1420 uint8_t file_checksum[20];
1421 uint8_t calculated_checksum[20];
1422 char checksum_string[2 * sizeof(file_checksum) + 1];
1423 struct AVSHA *sha;
1424 int i;
1425 int ret = 0;
1426 uint8_t *activation_bytes = c->activation_bytes;
1427 uint8_t *fixed_key = c->audible_fixed_key;
1428
1429 c->aax_mode = 1;
1430
1431 sha = av_sha_alloc();
1432 if (!sha)
1433 return AVERROR(ENOMEM);
1434 av_free(c->aes_decrypt);
1435 c->aes_decrypt = av_aes_alloc();
1436 if (!c->aes_decrypt) {
1437 ret = AVERROR(ENOMEM);
1438 goto fail;
1439 }
1440
1441 /* drm blob processing */
1442 avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1443 avio_read(pb, input, DRM_BLOB_SIZE);
1444 avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1445 ret = ffio_read_size(pb, file_checksum, 20);
1446 if (ret < 0)
1447 goto fail;
1448
1449 // required by external tools
1450 ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1);
1451 av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string);
1452
1453 /* verify activation data */
1454 if (!activation_bytes) {
1455 av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1456 ret = 0; /* allow ffprobe to continue working on .aax files */
1457 goto fail;
1458 }
1459 if (c->activation_bytes_size != 4) {
1460 av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1461 ret = AVERROR(EINVAL);
1462 goto fail;
1463 }
1464
1465 /* verify fixed key */
1466 if (c->audible_fixed_key_size != 16) {
1467 av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1468 ret = AVERROR(EINVAL);
1469 goto fail;
1470 }
1471
1472 /* AAX (and AAX+) key derivation */
1473 av_sha_init(sha, 160);
1474 av_sha_update(sha, fixed_key, 16);
1475 av_sha_update(sha, activation_bytes, 4);
1476 av_sha_final(sha, intermediate_key);
1477 av_sha_init(sha, 160);
1478 av_sha_update(sha, fixed_key, 16);
1479 av_sha_update(sha, intermediate_key, 20);
1480 av_sha_update(sha, activation_bytes, 4);
1481 av_sha_final(sha, intermediate_iv);
1482 av_sha_init(sha, 160);
1483 av_sha_update(sha, intermediate_key, 16);
1484 av_sha_update(sha, intermediate_iv, 16);
1485 av_sha_final(sha, calculated_checksum);
1486 if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1487 av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1488 ret = AVERROR_INVALIDDATA;
1489 goto fail;
1490 }
1491 av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1492 av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1493 for (i = 0; i < 4; i++) {
1494 // file data (in output) is stored in big-endian mode
1495 if (activation_bytes[i] != output[3 - i]) { // critical error
1496 av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1497 ret = AVERROR_INVALIDDATA;
1498 goto fail;
1499 }
1500 }
1501 memcpy(c->file_key, output + 8, 16);
1502 memcpy(input, output + 26, 16);
1503 av_sha_init(sha, 160);
1504 av_sha_update(sha, input, 16);
1505 av_sha_update(sha, c->file_key, 16);
1506 av_sha_update(sha, fixed_key, 16);
1507 av_sha_final(sha, c->file_iv);
1508
1509 fail:
1510 av_free(sha);
1511
1512 return ret;
1513 }
1514
1515 static int mov_aaxc_crypto(MOVContext *c)
1516 {
1517 if (c->audible_key_size != 16) {
1518 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n");
1519 return AVERROR(EINVAL);
1520 }
1521
1522 if (c->audible_iv_size != 16) {
1523 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n");
1524 return AVERROR(EINVAL);
1525 }
1526
1527 c->aes_decrypt = av_aes_alloc();
1528 if (!c->aes_decrypt) {
1529 return AVERROR(ENOMEM);
1530 }
1531
1532 memcpy(c->file_key, c->audible_key, 16);
1533 memcpy(c->file_iv, c->audible_iv, 16);
1534 c->aax_mode = 1;
1535
1536 return 0;
1537 }
1538
1539 // Audible AAX (and AAX+) bytestream decryption
1540 static int aax_filter(uint8_t *input, int size, MOVContext *c)
1541 {
1542 int blocks = 0;
1543 unsigned char iv[16];
1544
1545 memcpy(iv, c->file_iv, 16); // iv is overwritten
1546 blocks = size >> 4; // trailing bytes are not encrypted!
1547 av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1548 av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1549
1550 return 0;
1551 }
1552
1553 /* read major brand, minor version and compatible brands and store them as metadata */
1554 482 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1555 {
1556 uint32_t minor_ver;
1557 int comp_brand_size;
1558 char* comp_brands_str;
1559 482 uint8_t type[5] = {0};
1560 482 int ret = ffio_read_size(pb, type, 4);
1561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 482 times.
482 if (ret < 0)
1562 return ret;
1563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 482 times.
482 if (c->fc->nb_streams) {
1564 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1565 return AVERROR_INVALIDDATA;
1566 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate FTYP\n");
1567 return 0;
1568 }
1569
1570
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 241 times.
482 if (strcmp(type, "qt "))
1571 241 c->isom = 1;
1572 482 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1573 482 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1574 482 minor_ver = avio_rb32(pb); /* minor version */
1575 482 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1576
1577 482 comp_brand_size = atom.size - 8;
1578
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)
1579 return AVERROR_INVALIDDATA;
1580 482 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 482 times.
482 if (!comp_brands_str)
1582 return AVERROR(ENOMEM);
1583
1584 482 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1585
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 482 times.
482 if (ret < 0) {
1586 av_freep(&comp_brands_str);
1587 return ret;
1588 }
1589 482 comp_brands_str[comp_brand_size] = 0;
1590 482 av_dict_set(&c->fc->metadata, "compatible_brands",
1591 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1592
1593 // Logic for handling Audible's .aaxc files
1594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 482 times.
482 if (!strcmp(type, "aaxc")) {
1595 mov_aaxc_crypto(c);
1596 }
1597
1598 482 return 0;
1599 }
1600
1601 /* this atom should contain all header atoms */
1602 508 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1603 {
1604 int ret;
1605
1606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 508 times.
508 if (c->found_moov) {
1607 av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1608 avio_skip(pb, atom.size);
1609 return 0;
1610 }
1611
1612
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 508 times.
508 if ((ret = mov_read_default(c, pb, atom)) < 0)
1613 return ret;
1614 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1615 /* so we don't parse the whole file if over a network */
1616 508 c->found_moov=1;
1617 508 return 0; /* now go for mdat */
1618 }
1619
1620 3208 static MOVFragmentStreamInfo * get_frag_stream_info(
1621 MOVFragmentIndex *frag_index,
1622 int index,
1623 int id)
1624 {
1625 int i;
1626 MOVFragmentIndexItem * item;
1627
1628
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)
1629 return NULL;
1630 3208 item = &frag_index->item[index];
1631
1/2
✓ Branch 0 taken 3392 times.
✗ Branch 1 not taken.
3392 for (i = 0; i < item->nb_stream_info; i++)
1632
2/2
✓ Branch 0 taken 3208 times.
✓ Branch 1 taken 184 times.
3392 if (item->stream_info[i].id == id)
1633 3208 return &item->stream_info[i];
1634
1635 // This shouldn't happen
1636 return NULL;
1637 }
1638
1639 499 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1640 {
1641 int i;
1642 MOVFragmentIndexItem * item;
1643
1644
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_index->current < 0 ||
1645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 frag_index->current >= frag_index->nb_items)
1646 return;
1647
1648 499 item = &frag_index->item[frag_index->current];
1649
1/2
✓ Branch 0 taken 558 times.
✗ Branch 1 not taken.
558 for (i = 0; i < item->nb_stream_info; i++)
1650
2/2
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 59 times.
558 if (item->stream_info[i].id == id) {
1651 499 item->current = i;
1652 499 return;
1653 }
1654
1655 // id not found. This shouldn't happen.
1656 item->current = -1;
1657 }
1658
1659 1436 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1660 MOVFragmentIndex *frag_index)
1661 {
1662 MOVFragmentIndexItem *item;
1663
1/2
✓ Branch 0 taken 1436 times.
✗ Branch 1 not taken.
1436 if (frag_index->current < 0 ||
1664
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1430 times.
1436 frag_index->current >= frag_index->nb_items)
1665 6 return NULL;
1666
1667 1430 item = &frag_index->item[frag_index->current];
1668
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)
1669 1430 return &item->stream_info[item->current];
1670
1671 // This shouldn't happen
1672 return NULL;
1673 }
1674
1675 899 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1676 {
1677 int a, b, m;
1678 int64_t moof_offset;
1679
1680 // Optimize for appending new entries
1681
2/2
✓ Branch 0 taken 881 times.
✓ Branch 1 taken 18 times.
899 if (!frag_index->nb_items ||
1682
2/2
✓ Branch 0 taken 464 times.
✓ Branch 1 taken 417 times.
881 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1683 482 return frag_index->nb_items;
1684
1685 417 a = -1;
1686 417 b = frag_index->nb_items;
1687
1688
2/2
✓ Branch 0 taken 2677 times.
✓ Branch 1 taken 417 times.
3094 while (b - a > 1) {
1689 2677 m = (a + b) >> 1;
1690 2677 moof_offset = frag_index->item[m].moof_offset;
1691
2/2
✓ Branch 0 taken 747 times.
✓ Branch 1 taken 1930 times.
2677 if (moof_offset >= offset)
1692 747 b = m;
1693
2/2
✓ Branch 0 taken 2345 times.
✓ Branch 1 taken 332 times.
2677 if (moof_offset <= offset)
1694 2345 a = m;
1695 }
1696 417 return b;
1697 }
1698
1699 7 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1700 {
1701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 av_assert0(frag_stream_info);
1702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1703 return frag_stream_info->sidx_pts;
1704
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1705 4 return frag_stream_info->first_tfra_pts;
1706 3 return frag_stream_info->tfdt_dts;
1707 }
1708
1709 226 static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1710 MOVFragmentIndex *frag_index, int index)
1711 {
1712 MOVFragmentStreamInfo * frag_stream_info;
1713 226 MOVStreamContext *sc = dst_st->priv_data;
1714 int64_t timestamp;
1715 int i, j;
1716
1717 // If the stream is referenced by any sidx, limit the search
1718 // to fragments that referenced this stream in the sidx
1719
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 7 times.
226 if (sc->has_sidx) {
1720 219 frag_stream_info = get_frag_stream_info(frag_index, index, sc->id);
1721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!frag_stream_info)
1722 return AV_NOPTS_VALUE;
1723
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1724 219 return frag_stream_info->sidx_pts;
1725 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1726 return frag_stream_info->first_tfra_pts;
1727 return frag_stream_info->sidx_pts;
1728 }
1729
1730
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++) {
1731
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)
1732 5 continue;
1733 7 AVStream *frag_stream = NULL;
1734 7 frag_stream_info = &frag_index->item[index].stream_info[i];
1735
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
21 for (j = 0; j < s->nb_streams; j++) {
1736 14 MOVStreamContext *sc2 = s->streams[j]->priv_data;
1737
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (sc2->id == frag_stream_info->id)
1738 7 frag_stream = s->streams[j];
1739 }
1740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!frag_stream) {
1741 av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1742 continue;
1743 }
1744 7 timestamp = get_stream_info_time(frag_stream_info);
1745
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (timestamp != AV_NOPTS_VALUE)
1746 4 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1747 }
1748 3 return AV_NOPTS_VALUE;
1749 }
1750
1751 28 static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1752 AVStream *st, int64_t timestamp)
1753 {
1754 int a, b, m, m0;
1755 int64_t frag_time;
1756
1757 28 a = -1;
1758 28 b = frag_index->nb_items;
1759
1760
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 28 times.
252 while (b - a > 1) {
1761 224 m0 = m = (a + b) >> 1;
1762
1763
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 &&
1764 226 (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
1765 3 m++;
1766
1767
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)
1768 95 a = m;
1769 else
1770 129 b = m0;
1771 }
1772
1773 28 return a;
1774 }
1775
1776 851 static int update_frag_index(MOVContext *c, int64_t offset)
1777 {
1778 int index, i;
1779 MOVFragmentIndexItem * item;
1780 MOVFragmentStreamInfo * frag_stream_info;
1781
1782 // If moof_offset already exists in frag_index, return index to it
1783 851 index = search_frag_moof_offset(&c->frag_index, offset);
1784
2/2
✓ Branch 0 taken 376 times.
✓ Branch 1 taken 475 times.
851 if (index < c->frag_index.nb_items &&
1785
2/2
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 2 times.
376 c->frag_index.item[index].moof_offset == offset)
1786 374 return index;
1787
1788 // offset is not yet in frag index.
1789 // Insert new item at index (sorted by moof offset)
1790 477 item = av_fast_realloc(c->frag_index.item,
1791 477 &c->frag_index.allocated_size,
1792 477 (c->frag_index.nb_items + 1) *
1793 sizeof(*c->frag_index.item));
1794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 477 times.
477 if (!item)
1795 return -1;
1796 477 c->frag_index.item = item;
1797
1798 477 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1799 sizeof(*item->stream_info));
1800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 477 times.
477 if (!frag_stream_info)
1801 return -1;
1802
1803
2/2
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 477 times.
1056 for (i = 0; i < c->fc->nb_streams; i++) {
1804 // Avoid building frag index if streams lack track id.
1805 579 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 579 times.
579 if (sc->id < 0) {
1807 av_free(frag_stream_info);
1808 return AVERROR_INVALIDDATA;
1809 }
1810
1811 579 frag_stream_info[i].id = sc->id;
1812 579 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1813 579 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1814 579 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1815 579 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1816 579 frag_stream_info[i].index_base = -1;
1817 579 frag_stream_info[i].index_entry = -1;
1818 579 frag_stream_info[i].encryption_index = NULL;
1819 579 frag_stream_info[i].stsd_id = -1;
1820 }
1821
1822
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 475 times.
477 if (index < c->frag_index.nb_items)
1823 2 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1824 2 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1825
1826 477 item = &c->frag_index.item[index];
1827 477 item->headers_read = 0;
1828 477 item->current = 0;
1829 477 item->nb_stream_info = c->fc->nb_streams;
1830 477 item->moof_offset = offset;
1831 477 item->stream_info = frag_stream_info;
1832 477 c->frag_index.nb_items++;
1833
1834 477 return index;
1835 }
1836
1837 499 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1838 int id, int entries)
1839 {
1840 int i;
1841 MOVFragmentStreamInfo * frag_stream_info;
1842
1843
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (index < 0)
1844 499 return;
1845 for (i = index; i < frag_index->nb_items; i++) {
1846 frag_stream_info = get_frag_stream_info(frag_index, i, id);
1847 if (frag_stream_info && frag_stream_info->index_entry >= 0)
1848 frag_stream_info->index_entry += entries;
1849 }
1850 }
1851
1852 473 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1853 {
1854 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1855 473 c->fragment.found_tfhd = 0;
1856
1857
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) {
1858 1 c->has_looked_for_mfra = 1;
1859
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1860 int ret;
1861 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1862 "for a mfra\n");
1863
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((ret = mov_read_mfra(c, pb)) < 0) {
1864 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1865 "read the mfra (may be a live ismv)\n");
1866 }
1867 } else {
1868 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1869 "seekable, can not look for mfra\n");
1870 }
1871 }
1872 473 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1873 473 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1874 473 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1875 473 return mov_read_default(c, pb, atom);
1876 }
1877
1878 1132 static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version)
1879 {
1880 int64_t time;
1881
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1117 times.
1132 if (version == 1) {
1882 15 time = avio_rb64(pb);
1883 15 avio_rb64(pb);
1884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (time < 0) {
1885 av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n");
1886 return;
1887 }
1888 } else {
1889 1117 time = avio_rb32(pb);
1890 1117 avio_rb32(pb); /* modification time */
1891
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) {
1892 48 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1893 48 time += 2082844800;
1894 }
1895 }
1896
2/2
✓ Branch 0 taken 538 times.
✓ Branch 1 taken 594 times.
1132 if (time) {
1897 538 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1898
1899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 538 times.
538 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1900 av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n");
1901 return;
1902 }
1903
1904 538 ff_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1905 }
1906 }
1907
1908 627 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1909 {
1910 AVStream *st;
1911 MOVStreamContext *sc;
1912 int version;
1913 627 char language[4] = {0};
1914 unsigned lang;
1915
1916
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->fc->nb_streams < 1)
1917 return 0;
1918 627 st = c->fc->streams[c->fc->nb_streams-1];
1919 627 sc = st->priv_data;
1920
1921
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (sc->time_scale) {
1922 av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
1923 return AVERROR_INVALIDDATA;
1924 }
1925
1926 627 version = avio_r8(pb);
1927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (version > 1) {
1928 avpriv_request_sample(c->fc, "Version %d", version);
1929 return AVERROR_PATCHWELCOME;
1930 }
1931 627 avio_rb24(pb); /* flags */
1932 627 mov_metadata_creation_time(c, pb, &st->metadata, version);
1933
1934 627 sc->time_scale = avio_rb32(pb);
1935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (sc->time_scale <= 0) {
1936 av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
1937 sc->time_scale = 1;
1938 }
1939
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 614 times.
627 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1940
1941
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) ||
1942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 614 times.
614 (version != 1 && st->duration == UINT32_MAX)) {
1943 9 st->duration = 0;
1944 }
1945
1946 627 lang = avio_rb16(pb); /* language */
1947
2/2
✓ Branch 1 taken 452 times.
✓ Branch 2 taken 175 times.
627 if (ff_mov_lang_to_iso639(lang, language))
1948 452 av_dict_set(&st->metadata, "language", language, 0);
1949 627 avio_rb16(pb); /* quality */
1950
1951 627 return 0;
1952 }
1953
1954 505 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1955 {
1956 int i;
1957 505 int version = avio_r8(pb); /* version */
1958 505 avio_rb24(pb); /* flags */
1959
1960 505 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
1961 505 c->time_scale = avio_rb32(pb); /* time scale */
1962
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 505 times.
505 if (c->time_scale <= 0) {
1963 av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
1964 c->time_scale = 1;
1965 }
1966 505 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
1967
1968
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 503 times.
505 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1969 505 avio_rb32(pb); /* preferred scale */
1970
1971 505 avio_rb16(pb); /* preferred volume */
1972
1973 505 avio_skip(pb, 10); /* reserved */
1974
1975 /* movie display matrix, store it in main context and use it later on */
1976
2/2
✓ Branch 0 taken 1515 times.
✓ Branch 1 taken 505 times.
2020 for (i = 0; i < 3; i++) {
1977 1515 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
1978 1515 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
1979 1515 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
1980 }
1981
1982 505 avio_rb32(pb); /* preview time */
1983 505 avio_rb32(pb); /* preview duration */
1984 505 avio_rb32(pb); /* poster time */
1985 505 avio_rb32(pb); /* selection time */
1986 505 avio_rb32(pb); /* selection duration */
1987 505 avio_rb32(pb); /* current time */
1988 505 avio_rb32(pb); /* next track ID */
1989
1990 505 return 0;
1991 }
1992
1993 7 static void set_last_stream_little_endian(AVFormatContext *fc)
1994 {
1995 AVStream *st;
1996
1997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (fc->nb_streams < 1)
1998 return;
1999 7 st = fc->streams[fc->nb_streams-1];
2000
2001
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) {
2002 5 case AV_CODEC_ID_PCM_S16BE:
2003 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2004 5 break;
2005 1 case AV_CODEC_ID_PCM_S24BE:
2006 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
2007 1 break;
2008 case AV_CODEC_ID_PCM_S32BE:
2009 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
2010 break;
2011 1 case AV_CODEC_ID_PCM_F32BE:
2012 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
2013 1 break;
2014 case AV_CODEC_ID_PCM_F64BE:
2015 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
2016 break;
2017 default:
2018 break;
2019 }
2020 }
2021
2022 5 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2023 {
2024 5 int little_endian = avio_rb16(pb) & 0xFF;
2025 5 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
2026
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (little_endian == 1)
2027 1 set_last_stream_little_endian(c->fc);
2028 5 return 0;
2029 }
2030
2031 6 static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2032 {
2033 int format_flags;
2034 int version, flags;
2035 int pcm_sample_size;
2036 6 AVFormatContext *fc = c->fc;
2037 AVStream *st;
2038 MOVStreamContext *sc;
2039
2040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 6) {
2041 av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n");
2042 return AVERROR_INVALIDDATA;
2043 }
2044
2045 6 version = avio_r8(pb);
2046 6 flags = avio_rb24(pb);
2047
2048
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) {
2049 av_log(c->fc, AV_LOG_ERROR,
2050 "Unsupported 'pcmC' box with version %d, flags: %x",
2051 version, flags);
2052 return AVERROR_INVALIDDATA;
2053 }
2054
2055 6 format_flags = avio_r8(pb);
2056 6 pcm_sample_size = avio_r8(pb);
2057
2058
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fc->nb_streams < 1)
2059 return AVERROR_INVALIDDATA;
2060
2061 6 st = fc->streams[fc->nb_streams - 1];
2062 6 sc = st->priv_data;
2063
2064
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (sc->format == MOV_MP4_FPCM_TAG) {
2065
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (pcm_sample_size) {
2066 1 case 32:
2067 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE;
2068 1 break;
2069 case 64:
2070 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE;
2071 break;
2072 default:
2073 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2074 pcm_sample_size,
2075 av_fourcc2str(sc->format));
2076 return AVERROR_INVALIDDATA;
2077 }
2078
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (sc->format == MOV_MP4_IPCM_TAG) {
2079
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 switch (pcm_sample_size) {
2080 5 case 16:
2081 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2082 5 break;
2083 case 24:
2084 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
2085 break;
2086 case 32:
2087 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
2088 break;
2089 default:
2090 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2091 pcm_sample_size,
2092 av_fourcc2str(sc->format));
2093 return AVERROR_INVALIDDATA;
2094 }
2095 } else {
2096 av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n",
2097 av_fourcc2str(sc->format));
2098 return AVERROR_INVALIDDATA;
2099 }
2100
2101
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
2102 6 set_last_stream_little_endian(c->fc);
2103 6 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2104
2105 6 return 0;
2106 }
2107
2108 47 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2109 {
2110 AVStream *st;
2111 47 HEIFItem *item = NULL;
2112 47 char color_parameter_type[5] = { 0 };
2113 uint16_t color_primaries, color_trc, color_matrix;
2114 int ret;
2115
2116 47 st = get_curr_st(c);
2117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 if (!st) {
2118 item = get_heif_item(c, c->cur_item_id);
2119 if (!item)
2120 return 0;
2121 }
2122
2123 47 ret = ffio_read_size(pb, color_parameter_type, 4);
2124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 if (ret < 0)
2125 return ret;
2126
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 14 times.
47 if (strncmp(color_parameter_type, "nclx", 4) &&
2127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 strncmp(color_parameter_type, "nclc", 4) &&
2128 strncmp(color_parameter_type, "prof", 4)) {
2129 av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
2130 color_parameter_type);
2131 return 0;
2132 }
2133
2134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 if (!strncmp(color_parameter_type, "prof", 4)) {
2135 AVPacketSideData *sd;
2136 uint8_t *icc_profile;
2137 if (st) {
2138 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
2139 &st->codecpar->nb_coded_side_data,
2140 AV_PKT_DATA_ICC_PROFILE,
2141 atom.size - 4, 0);
2142 if (!sd)
2143 return AVERROR(ENOMEM);
2144 icc_profile = sd->data;
2145 } else {
2146 av_freep(&item->icc_profile);
2147 icc_profile = item->icc_profile = av_malloc(atom.size - 4);
2148 if (!icc_profile) {
2149 item->icc_profile_size = 0;
2150 return AVERROR(ENOMEM);
2151 }
2152 item->icc_profile_size = atom.size - 4;
2153 }
2154 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
2155 if (ret < 0)
2156 return ret;
2157
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 } else if (st) {
2158 47 color_primaries = avio_rb16(pb);
2159 47 color_trc = avio_rb16(pb);
2160 47 color_matrix = avio_rb16(pb);
2161
2162 47 av_log(c->fc, AV_LOG_TRACE,
2163 "%s: pri %d trc %d matrix %d",
2164 color_parameter_type, color_primaries, color_trc, color_matrix);
2165
2166
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 33 times.
47 if (!strncmp(color_parameter_type, "nclx", 4)) {
2167 14 uint8_t color_range = avio_r8(pb) >> 7;
2168 14 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2169
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (color_range)
2170 2 st->codecpar->color_range = AVCOL_RANGE_JPEG;
2171 else
2172 12 st->codecpar->color_range = AVCOL_RANGE_MPEG;
2173 }
2174
2175
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
47 if (!av_color_primaries_name(color_primaries))
2176 color_primaries = AVCOL_PRI_UNSPECIFIED;
2177
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
47 if (!av_color_transfer_name(color_trc))
2178 color_trc = AVCOL_TRC_UNSPECIFIED;
2179
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
47 if (!av_color_space_name(color_matrix))
2180 color_matrix = AVCOL_SPC_UNSPECIFIED;
2181
2182 47 st->codecpar->color_primaries = color_primaries;
2183 47 st->codecpar->color_trc = color_trc;
2184 47 st->codecpar->color_space = color_matrix;
2185 47 av_log(c->fc, AV_LOG_TRACE, "\n");
2186 }
2187 47 return 0;
2188 }
2189
2190 118 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2191 {
2192 AVStream *st;
2193 unsigned mov_field_order;
2194 118 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2195
2196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (c->fc->nb_streams < 1) // will happen with jp2 files
2197 return 0;
2198 118 st = c->fc->streams[c->fc->nb_streams-1];
2199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (atom.size < 2)
2200 return AVERROR_INVALIDDATA;
2201 118 mov_field_order = avio_rb16(pb);
2202
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 22 times.
118 if ((mov_field_order & 0xFF00) == 0x0100)
2203 96 decoded_field_order = AV_FIELD_PROGRESSIVE;
2204
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 else if ((mov_field_order & 0xFF00) == 0x0200) {
2205
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) {
2206 1 case 0x01: decoded_field_order = AV_FIELD_TT;
2207 1 break;
2208 case 0x06: decoded_field_order = AV_FIELD_BB;
2209 break;
2210 1 case 0x09: decoded_field_order = AV_FIELD_TB;
2211 1 break;
2212 20 case 0x0E: decoded_field_order = AV_FIELD_BT;
2213 20 break;
2214 }
2215 }
2216
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) {
2217 av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
2218 }
2219 118 st->codecpar->field_order = decoded_field_order;
2220
2221 118 return 0;
2222 }
2223
2224 69 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
2225 {
2226 69 int err = 0;
2227 69 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
2228
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)
2229 return AVERROR_INVALIDDATA;
2230
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
69 if ((err = av_reallocp(&par->extradata, size)) < 0) {
2231 par->extradata_size = 0;
2232 return err;
2233 }
2234 69 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
2235 69 return 0;
2236 }
2237
2238 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
2239 65 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2240 AVCodecParameters *par, uint8_t *buf)
2241 {
2242 65 int64_t result = atom.size;
2243 int err;
2244
2245 65 AV_WB32(buf , atom.size + 8);
2246 65 AV_WL32(buf + 4, atom.type);
2247 65 err = ffio_read_size(pb, buf + 8, atom.size);
2248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (err < 0) {
2249 par->extradata_size -= atom.size;
2250 return err;
2251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 } else if (err < atom.size) {
2252 av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
2253 par->extradata_size -= atom.size - err;
2254 result = err;
2255 }
2256 65 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2257 65 return result;
2258 }
2259
2260 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
2261 58 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2262 enum AVCodecID codec_id)
2263 {
2264 AVStream *st;
2265 uint64_t original_size;
2266 int err;
2267
2268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (c->fc->nb_streams < 1) // will happen with jp2 files
2269 return 0;
2270 58 st = c->fc->streams[c->fc->nb_streams-1];
2271
2272
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
58 if (st->codecpar->codec_id != codec_id)
2273 19 return 0; /* unexpected codec_id - don't mess with extradata */
2274
2275 39 original_size = st->codecpar->extradata_size;
2276 39 err = mov_realloc_extradata(st->codecpar, atom);
2277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err)
2278 return err;
2279
2280 39 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
2281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err < 0)
2282 return err;
2283 39 return 0; // Note: this is the original behavior to ignore truncation.
2284 }
2285
2286 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
2287 16 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2288 {
2289 16 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
2290 }
2291
2292 static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2293 {
2294 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS);
2295 }
2296
2297 static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2298 {
2299 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
2300 }
2301
2302 static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2303 {
2304 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
2305 }
2306
2307 19 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2308 {
2309 19 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
2310
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!ret)
2311 19 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
2312 19 return ret;
2313 }
2314
2315 static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2316 {
2317 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
2318
2319 if (!ret && c->fc->nb_streams >= 1) {
2320 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2321 if (par->extradata_size >= 40) {
2322 par->height = AV_RB16(&par->extradata[36]);
2323 par->width = AV_RB16(&par->extradata[38]);
2324 }
2325 }
2326 return ret;
2327 }
2328
2329 16 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2330 {
2331
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (c->fc->nb_streams >= 1) {
2332 16 AVStream *const st = c->fc->streams[c->fc->nb_streams - 1];
2333 16 FFStream *const sti = ffstream(st);
2334 16 AVCodecParameters *par = st->codecpar;
2335
2336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
2337 par->codec_id == AV_CODEC_ID_H264 &&
2338 atom.size > 11) {
2339 int cid;
2340 avio_skip(pb, 10);
2341 cid = avio_rb16(pb);
2342 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
2343 if (cid == 0xd4d || cid == 0xd4e)
2344 par->width = 1440;
2345 return 0;
2346
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
2347
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
2348
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
2349
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 atom.size >= 24) {
2350 int num, den;
2351 13 avio_skip(pb, 12);
2352 13 num = avio_rb32(pb);
2353 13 den = avio_rb32(pb);
2354
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)
2355 return 0;
2356
2/3
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
13 switch (avio_rb32(pb)) {
2357 12 case 2:
2358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (den >= INT_MAX / 2)
2359 return 0;
2360 12 den *= 2;
2361 av_fallthrough;
2362 13 case 1:
2363 13 sti->display_aspect_ratio = (AVRational){ num, den };
2364 av_fallthrough;
2365 13 default:
2366 13 return 0;
2367 }
2368 }
2369 }
2370
2371 3 return mov_read_avid(c, pb, atom);
2372 }
2373
2374 26 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2375 {
2376 26 int ret = 0;
2377 26 int length = 0;
2378 uint64_t original_size;
2379
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (c->fc->nb_streams >= 1) {
2380 26 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (par->codec_id == AV_CODEC_ID_H264)
2382 return 0;
2383
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (atom.size == 16) {
2384 26 original_size = par->extradata_size;
2385 26 ret = mov_realloc_extradata(par, atom);
2386
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!ret) {
2387 26 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
2388
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (length == atom.size) {
2389 26 const uint8_t range_value = par->extradata[original_size + 19];
2390
1/3
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
26 switch (range_value) {
2391 26 case 1:
2392 26 par->color_range = AVCOL_RANGE_MPEG;
2393 26 break;
2394 case 2:
2395 par->color_range = AVCOL_RANGE_JPEG;
2396 break;
2397 default:
2398 av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
2399 break;
2400 }
2401 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
2402 } else {
2403 /* For some reason the whole atom was not added to the extradata */
2404 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
2405 }
2406 } else {
2407 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
2408 }
2409 } else {
2410 av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
2411 }
2412 }
2413
2414 26 return ret;
2415 }
2416
2417 4 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2418 {
2419 4 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
2420 }
2421
2422 35 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2423 {
2424 AVStream *st;
2425 int ret;
2426
2427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (c->fc->nb_streams < 1)
2428 return 0;
2429 35 st = c->fc->streams[c->fc->nb_streams-1];
2430
2431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if ((uint64_t)atom.size > (1<<30))
2432 return AVERROR_INVALIDDATA;
2433
2434
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 2 times.
35 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2435
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
2437 // pass all frma atom to codec, needed at least for QDMC and QDM2
2438 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2440 return ret;
2441
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 } else if (atom.size > 8) { /* to read frma, esds atoms */
2442
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) {
2443 uint64_t buffer;
2444 10 ret = ffio_ensure_seekback(pb, 8);
2445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2446 return ret;
2447 10 buffer = avio_rb64(pb);
2448 10 atom.size -= 8;
2449
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
2450
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 <= atom.size
2451
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 >= 8) {
2452 10 avio_skip(pb, -8);
2453 10 atom.size += 8;
2454 } else if (!st->codecpar->extradata_size) {
2455 #define ALAC_EXTRADATA_SIZE 36
2456 st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
2457 if (!st->codecpar->extradata)
2458 return AVERROR(ENOMEM);
2459 st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
2460 AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
2461 AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
2462 AV_WB64(st->codecpar->extradata + 12, buffer);
2463 avio_read(pb, st->codecpar->extradata + 20, 16);
2464 avio_skip(pb, atom.size - 24);
2465 return 0;
2466 }
2467 }
2468
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
33 if ((ret = mov_read_default(c, pb, atom)) < 0)
2469 return ret;
2470 } else
2471 avio_skip(pb, atom.size);
2472 35 return 0;
2473 }
2474
2475 /**
2476 * This function reads atom content and puts data in extradata without tag
2477 * nor size unlike mov_read_extradata.
2478 */
2479 174 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2480 {
2481 AVStream *st;
2482 int ret;
2483
2484 174 st = get_curr_st(c);
2485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
174 if (!st)
2486 return 0;
2487
2488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
174 if ((uint64_t)atom.size > (1<<30))
2489 return AVERROR_INVALIDDATA;
2490
2491
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 173 times.
174 if (atom.type == MKTAG('v','v','c','C')) {
2492 1 avio_skip(pb, 4);
2493 1 atom.size -= 4;
2494 }
2495
2496
2/2
✓ Branch 0 taken 170 times.
✓ Branch 1 taken 4 times.
174 if (atom.size >= 10) {
2497 // Broken files created by legacy versions of libavformat will
2498 // wrap a whole fiel atom inside of a glbl atom.
2499 170 unsigned size = avio_rb32(pb);
2500 170 unsigned type = avio_rl32(pb);
2501
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 170 times.
170 if (avio_feof(pb))
2502 return AVERROR_INVALIDDATA;
2503 170 avio_seek(pb, -8, SEEK_CUR);
2504
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)
2505 10 return mov_read_default(c, pb, atom);
2506 }
2507
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) {
2508 av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
2509 return 0;
2510 }
2511 164 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 164 times.
164 if (ret < 0)
2513 return ret;
2514
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'))
2515 /* HEVC-based Dolby Vision derived from hvc1.
2516 Happens to match with an identifier
2517 previously utilized for DV. Thus, if we have
2518 the hvcC extradata box available as specified,
2519 set codec to HEVC */
2520 st->codecpar->codec_id = AV_CODEC_ID_HEVC;
2521
2522 164 return 0;
2523 }
2524
2525 2 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2526 {
2527 AVStream *st;
2528 uint8_t profile_level;
2529 int ret;
2530
2531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
2532 return 0;
2533 2 st = c->fc->streams[c->fc->nb_streams-1];
2534
2535
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)
2536 return AVERROR_INVALIDDATA;
2537
2538 2 profile_level = avio_r8(pb);
2539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((profile_level & 0xf0) != 0xc0)
2540 return 0;
2541
2542 2 avio_seek(pb, 6, SEEK_CUR);
2543 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
2544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2545 return ret;
2546
2547 2 return 0;
2548 }
2549
2550 static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2551 {
2552 AVStream* st;
2553 MOVStreamContext* sc;
2554
2555 if (c->fc->nb_streams < 1)
2556 return 0;
2557
2558 /* For SBAS this should be fine - though beware if someone implements a
2559 * tref atom processor that doesn't drop down to default then this may
2560 * be lost. */
2561 if (atom.size > 4) {
2562 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2563 return AVERROR_PATCHWELCOME;
2564 }
2565
2566 st = c->fc->streams[c->fc->nb_streams - 1];
2567 sc = st->priv_data;
2568 sc->tref_id = avio_rb32(pb);
2569 sc->tref_flags |= MOV_TREF_FLAG_ENHANCEMENT;
2570
2571 return 0;
2572 }
2573
2574 /**
2575 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2576 * but can have extradata appended at the end after the 40 bytes belonging
2577 * to the struct.
2578 */
2579 static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2580 {
2581 AVStream *st;
2582 int ret;
2583
2584 if (c->fc->nb_streams < 1)
2585 return 0;
2586 if (atom.size <= 40)
2587 return 0;
2588 st = c->fc->streams[c->fc->nb_streams-1];
2589
2590 if ((uint64_t)atom.size > (1<<30))
2591 return AVERROR_INVALIDDATA;
2592
2593 avio_skip(pb, 40);
2594 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
2595 if (ret < 0)
2596 return ret;
2597
2598 return 0;
2599 }
2600
2601 627 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2602 {
2603 AVStream *st;
2604 MOVStreamContext *sc;
2605 unsigned int i, entries;
2606
2607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->trak_index < 0) {
2608 av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
2609 return 0;
2610 }
2611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->fc->nb_streams < 1)
2612 return 0;
2613 627 st = c->fc->streams[c->fc->nb_streams-1];
2614 627 sc = st->priv_data;
2615
2616 627 avio_r8(pb); /* version */
2617 627 avio_rb24(pb); /* flags */
2618
2619 // Clamp allocation size for `chunk_offsets` -- don't throw an error for an
2620 // invalid count since the EOF path doesn't throw either.
2621 627 entries = avio_rb32(pb);
2622 627 entries =
2623
2/2
✓ Branch 0 taken 622 times.
✓ Branch 1 taken 5 times.
627 FFMIN(entries,
2624 FFMAX(0, (atom.size - 8) /
2625 (atom.type == MKTAG('s', 't', 'c', 'o') ? 4 : 8)));
2626
2627
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 598 times.
627 if (!entries)
2628 29 return 0;
2629
2630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (sc->chunk_offsets) {
2631 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2632 return 0;
2633 }
2634
2635 598 av_free(sc->chunk_offsets);
2636 598 sc->chunk_count = 0;
2637 598 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2638
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (!sc->chunk_offsets)
2639 return AVERROR(ENOMEM);
2640 598 sc->chunk_count = entries;
2641
2642
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 4 times.
598 if (atom.type == MKTAG('s','t','c','o'))
2643
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++)
2644 43404 sc->chunk_offsets[i] = avio_rb32(pb);
2645
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (atom.type == MKTAG('c','o','6','4'))
2646
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++) {
2647 136336 sc->chunk_offsets[i] = avio_rb64(pb);
2648
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136336 times.
136336 if (sc->chunk_offsets[i] < 0) {
2649 av_log(c->fc, AV_LOG_WARNING, "Impossible chunk_offset\n");
2650 sc->chunk_offsets[i] = 0;
2651 }
2652 }
2653 else
2654 return AVERROR_INVALIDDATA;
2655
2656 598 sc->chunk_count = i;
2657
2658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
598 if (pb->eof_reached) {
2659 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2660 return AVERROR_EOF;
2661 }
2662
2663 598 return 0;
2664 }
2665
2666 690 static int mov_codec_id(AVStream *st, uint32_t format)
2667 {
2668 690 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2669
2670
2/2
✓ Branch 0 taken 466 times.
✓ Branch 1 taken 224 times.
690 if (id <= 0 &&
2671
2/2
✓ Branch 0 taken 463 times.
✓ Branch 1 taken 3 times.
466 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 463 times.
463 (format & 0xFFFF) == 'T' + ('S' << 8)))
2673 3 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2674
2675
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) {
2676 227 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2677
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 &&
2678 /* skip old ASF MPEG-4 tag */
2679
2/2
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 4 times.
443 format && format != MKTAG('m','p','4','s')) {
2680 439 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2681
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 377 times.
439 if (id <= 0)
2682 62 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2683
2/2
✓ Branch 0 taken 381 times.
✓ Branch 1 taken 58 times.
439 if (id > 0)
2684 381 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2685
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 51 times.
58 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2686
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2688 51 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2689
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 6 times.
51 if (id <= 0) {
2690
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 4 times.
86 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2691
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 4 times.
86 AV_CODEC_ID_TTML : id;
2692 }
2693
2694
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 37 times.
51 if (id > 0)
2695 14 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2696 else
2697 37 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2698 }
2699 }
2700
2701 690 st->codecpar->codec_tag = format;
2702
2703 690 return id;
2704 }
2705
2706 338 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2707 AVStream *st, MOVStreamContext *sc)
2708 {
2709 338 uint8_t codec_name[32] = { 0 };
2710 int64_t stsd_start;
2711 unsigned int len;
2712 338 uint32_t id = 0;
2713
2714 /* The first 16 bytes of the video sample description are already
2715 * read in ff_mov_read_stsd_entries() */
2716 338 stsd_start = avio_tell(pb) - 16;
2717
2718
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 240 times.
338 if (c->isom) {
2719 98 avio_skip(pb, 2); /* pre_defined */
2720 98 avio_skip(pb, 2); /* reserved */
2721 98 avio_skip(pb, 12); /* pre_defined */
2722 } else {
2723 240 avio_rb16(pb); /* version */
2724 240 avio_rb16(pb); /* revision level */
2725 240 id = avio_rl32(pb); /* vendor */
2726 240 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2727 240 avio_rb32(pb); /* temporal quality */
2728 240 avio_rb32(pb); /* spatial quality */
2729 }
2730
2731 338 st->codecpar->width = avio_rb16(pb); /* width */
2732 338 st->codecpar->height = avio_rb16(pb); /* height */
2733
2734 338 avio_rb32(pb); /* horiz resolution */
2735 338 avio_rb32(pb); /* vert resolution */
2736 338 avio_rb32(pb); /* data size, always 0 */
2737 338 avio_rb16(pb); /* frames per samples */
2738
2739 338 len = avio_r8(pb); /* codec name, pascal string */
2740
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 337 times.
338 if (len > 31)
2741 1 len = 31;
2742 338 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2743
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 3 times.
338 if (len < 31)
2744 335 avio_skip(pb, 31 - len);
2745
2746
2/2
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 72 times.
338 if (codec_name[0])
2747 266 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2748
2749 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2750
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)) {
2751 st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2752 st->codecpar->width &= ~1;
2753 st->codecpar->height &= ~1;
2754 }
2755 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
338 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2757 !strncmp(codec_name, "Sorenson H263", 13))
2758 st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2759
2760 338 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2761
2762 338 avio_seek(pb, stsd_start, SEEK_SET);
2763
2764
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 320 times.
338 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2765 18 st->codecpar->bits_per_coded_sample &= 0x1F;
2766 18 sc->has_palette = 1;
2767 }
2768 338 }
2769
2770 247 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2771 AVStream *st, MOVStreamContext *sc)
2772 {
2773 int bits_per_sample, flags;
2774 247 uint16_t version = avio_rb16(pb);
2775 247 uint32_t id = 0;
2776 247 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2777 int channel_count;
2778
2779
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 87 times.
247 if (c->isom)
2780 160 avio_skip(pb, 6); /* reserved */
2781 else {
2782 87 avio_rb16(pb); /* revision level */
2783 87 id = avio_rl32(pb); /* vendor */
2784 87 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2785 }
2786
2787 247 channel_count = avio_rb16(pb);
2788
2789 247 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2790 247 st->codecpar->ch_layout.nb_channels = channel_count;
2791 247 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
2792 247 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
2793
2794 247 sc->audio_cid = avio_rb16(pb);
2795 247 avio_rb16(pb); /* packet size = 0 */
2796
2797 247 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
2798
2799 // Read QT version 1 fields. In version 0 these do not exist.
2800 247 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
2801
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 ||
2802
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
2803
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)) {
2804
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 40 times.
91 if (version == 1) {
2805 51 sc->samples_per_frame = avio_rb32(pb);
2806 51 avio_rb32(pb); /* bytes per packet */
2807 51 sc->bytes_per_frame = avio_rb32(pb);
2808 51 avio_rb32(pb); /* bytes per sample */
2809
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
40 } else if (version == 2) {
2810 4 avio_rb32(pb); /* sizeof struct only */
2811 4 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
2812 4 channel_count = avio_rb32(pb);
2813 4 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2814 4 st->codecpar->ch_layout.nb_channels = channel_count;
2815 4 avio_rb32(pb); /* always 0x7F000000 */
2816 4 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
2817
2818 4 flags = avio_rb32(pb); /* lpcm format specific flag */
2819 4 sc->bytes_per_frame = avio_rb32(pb);
2820 4 sc->samples_per_frame = avio_rb32(pb);
2821
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
2822 st->codecpar->codec_id =
2823 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
2824 flags);
2825 }
2826
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)) {
2827 /* can't correctly handle variable sized packet as audio unit */
2828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 switch (st->codecpar->codec_id) {
2829 case AV_CODEC_ID_MP2:
2830 case AV_CODEC_ID_MP3:
2831 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
2832 break;
2833 }
2834 }
2835 }
2836
2837
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 247 times.
247 if (sc->format == 0) {
2838 if (st->codecpar->bits_per_coded_sample == 8)
2839 st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
2840 else if (st->codecpar->bits_per_coded_sample == 16)
2841 st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
2842 }
2843
2844
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) {
2845 7 case AV_CODEC_ID_PCM_S8:
2846 case AV_CODEC_ID_PCM_U8:
2847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
2848 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2849 7 break;
2850 19 case AV_CODEC_ID_PCM_S16LE:
2851 case AV_CODEC_ID_PCM_S16BE:
2852
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
19 if (st->codecpar->bits_per_coded_sample == 8)
2853 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
2854
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 24)
2855 st->codecpar->codec_id =
2856 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2857 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
2858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 32)
2859 st->codecpar->codec_id =
2860 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2861 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
2862 19 break;
2863 /* set values for old format before stsd version 1 appeared */
2864 2 case AV_CODEC_ID_MACE3:
2865 2 sc->samples_per_frame = 6;
2866 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
2867 2 break;
2868 8 case AV_CODEC_ID_MACE6:
2869 8 sc->samples_per_frame = 6;
2870 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
2871 8 break;
2872 5 case AV_CODEC_ID_ADPCM_IMA_QT:
2873 5 sc->samples_per_frame = 64;
2874 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
2875 5 break;
2876 1 case AV_CODEC_ID_GSM:
2877 1 sc->samples_per_frame = 160;
2878 1 sc->bytes_per_frame = 33;
2879 1 break;
2880 205 default:
2881 205 break;
2882 }
2883
2884 247 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2885
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) {
2886 48 st->codecpar->bits_per_coded_sample = bits_per_sample;
2887 48 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
2888 }
2889 247 }
2890
2891 15 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
2892 AVStream *st, MOVStreamContext *sc,
2893 int64_t size)
2894 {
2895 // ttxt stsd contains display flags, justification, background
2896 // color, fonts, and default styles, so fake an atom to read it
2897 15 MOVAtom fake_atom = { .size = size };
2898 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
2899 // in extradata unlike stpp MP4 TTML.
2900
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
2901
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
15 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
2902 11 mov_read_glbl(c, pb, fake_atom);
2903 15 st->codecpar->width = sc->width;
2904 15 st->codecpar->height = sc->height;
2905 15 }
2906
2907 41 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
2908 AVStream *st, MOVStreamContext *sc,
2909 int64_t size)
2910 {
2911 int ret;
2912
2913
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 22 times.
41 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
2914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if ((int)size != size)
2915 return AVERROR(ENOMEM);
2916
2917 19 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
2918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
2919 return ret;
2920
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (size > 16) {
2921 19 MOVStreamContext *tmcd_ctx = st->priv_data;
2922 int val;
2923 19 val = AV_RB32(st->codecpar->extradata + 4);
2924 19 tmcd_ctx->tmcd_flags = val;
2925 19 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
2926 19 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
2927 19 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
2928
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (size > 30) {
2929 4 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
2930 4 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
2931
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) {
2932 4 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
2933
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 &&
2934
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 st->codecpar->extradata[30] /* Don't add empty string */) {
2935 4 char *reel_name = av_malloc(str_size + 1);
2936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!reel_name)
2937 return AVERROR(ENOMEM);
2938 4 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
2939 4 reel_name[str_size] = 0; /* Add null terminator */
2940 4 av_dict_set(&st->metadata, "reel_name", reel_name,
2941 AV_DICT_DONT_STRDUP_VAL);
2942 }
2943 }
2944 }
2945 }
2946 } else {
2947 /* other codec type, just skip (rtp, mp4s ...) */
2948 22 avio_skip(pb, size);
2949 }
2950 41 return 0;
2951 }
2952
2953 627 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
2954 AVStream *st, MOVStreamContext *sc)
2955 {
2956 627 FFStream *const sti = ffstream(st);
2957
2958
2/2
✓ Branch 0 taken 247 times.
✓ Branch 1 taken 380 times.
627 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
2959
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)
2960 st->codecpar->sample_rate = sc->time_scale;
2961
2962 /* special codec parameters handling */
2963
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) {
2964 #if CONFIG_DV_DEMUXER
2965 case AV_CODEC_ID_DVAUDIO:
2966 if (c->dv_fctx) {
2967 avpriv_request_sample(c->fc, "multiple DV audio streams");
2968 return AVERROR(ENOSYS);
2969 }
2970
2971 c->dv_fctx = avformat_alloc_context();
2972 if (!c->dv_fctx) {
2973 av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
2974 return AVERROR(ENOMEM);
2975 }
2976 c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
2977 if (!c->dv_demux) {
2978 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
2979 return AVERROR(ENOMEM);
2980 }
2981 sc->dv_audio_container = 1;
2982 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2983 break;
2984 #endif
2985 /* no ifdef since parameters are always those */
2986 case AV_CODEC_ID_QCELP:
2987 av_channel_layout_uninit(&st->codecpar->ch_layout);
2988 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2989 // force sample rate for qcelp when not stored in mov
2990 if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
2991 st->codecpar->sample_rate = 8000;
2992 // FIXME: Why is the following needed for some files?
2993 sc->samples_per_frame = 160;
2994 if (!sc->bytes_per_frame)
2995 sc->bytes_per_frame = 35;
2996 break;
2997 case AV_CODEC_ID_AMR_NB:
2998 av_channel_layout_uninit(&st->codecpar->ch_layout);
2999 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3000 /* force sample rate for amr, stsd in 3gp does not store sample rate */
3001 st->codecpar->sample_rate = 8000;
3002 break;
3003 11 case AV_CODEC_ID_AMR_WB:
3004 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
3005 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3006 11 st->codecpar->sample_rate = 16000;
3007 11 break;
3008 1 case AV_CODEC_ID_MP2:
3009 case AV_CODEC_ID_MP3:
3010 /* force type after stsd for m1a hdlr */
3011 1 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
3012 1 break;
3013 15 case AV_CODEC_ID_GSM:
3014 case AV_CODEC_ID_ADPCM_MS:
3015 case AV_CODEC_ID_ADPCM_IMA_WAV:
3016 case AV_CODEC_ID_ILBC:
3017 case AV_CODEC_ID_MACE3:
3018 case AV_CODEC_ID_MACE6:
3019 case AV_CODEC_ID_QDM2:
3020 15 st->codecpar->block_align = sc->bytes_per_frame;
3021 15 break;
3022 16 case AV_CODEC_ID_ALAC:
3023
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
3024 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
3025
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
3026 av_channel_layout_uninit(&st->codecpar->ch_layout);
3027 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3028 st->codecpar->ch_layout.nb_channels = channel_count;
3029 }
3030 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
3031 }
3032 16 break;
3033 10 case AV_CODEC_ID_AC3:
3034 case AV_CODEC_ID_EAC3:
3035 case AV_CODEC_ID_MPEG1VIDEO:
3036 case AV_CODEC_ID_VC1:
3037 case AV_CODEC_ID_VP8:
3038 case AV_CODEC_ID_VP9:
3039 10 sti->need_parsing = AVSTREAM_PARSE_FULL;
3040 10 break;
3041 106 case AV_CODEC_ID_PRORES_RAW:
3042 case AV_CODEC_ID_PRORES:
3043 case AV_CODEC_ID_APV:
3044 case AV_CODEC_ID_EVC:
3045 case AV_CODEC_ID_LCEVC:
3046 case AV_CODEC_ID_AV1:
3047 /* field_order detection of H264 requires parsing */
3048 case AV_CODEC_ID_H264:
3049 106 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3050 106 break;
3051 468 default:
3052 468 break;
3053 }
3054 627 return 0;
3055 }
3056
3057 641 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
3058 int codec_tag, int format,
3059 int64_t size)
3060 {
3061
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 &&
3062 (codec_tag != format &&
3063 // AVID 1:1 samples with differing data format and codec tag exist
3064 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
3065 // prores is allowed to have differing data format and codec tag
3066 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
3067 // so is dv (sigh)
3068 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
3069 (c->fc->video_codec_id ? ff_codec_get_id(ff_codec_movvideo_tags, format) != c->fc->video_codec_id
3070 : codec_tag != MKTAG('j','p','e','g')))) {
3071 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3072 * export it as a separate AVStream but this needs a few changes
3073 * in the MOV demuxer, patch welcome. */
3074
3075 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3076 avio_skip(pb, size);
3077 return 1;
3078 }
3079
3080 641 return 0;
3081 }
3082
3083 641 static int mov_finalize_stsd_entry(MOVContext *c, AVStream *st)
3084 {
3085 int ret;
3086
3087 /* special codec parameters handling */
3088
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 560 times.
641 switch (st->codecpar->codec_id) {
3089 81 case AV_CODEC_ID_H264:
3090 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
3091
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)) {
3092 ret = ff_generate_avci_extradata(st);
3093 if (ret < 0)
3094 return ret;
3095 }
3096 81 break;
3097 560 default:
3098 560 break;
3099 }
3100
3101 641 return 0;
3102 }
3103
3104 627 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3105 {
3106 AVStream *st;
3107 MOVStreamContext *sc;
3108 int pseudo_stream_id;
3109
3110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 av_assert0 (c->fc->nb_streams >= 1);
3111 627 st = c->fc->streams[c->fc->nb_streams-1];
3112 627 sc = st->priv_data;
3113
3114 627 for (pseudo_stream_id = 0;
3115
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;
3116 641 pseudo_stream_id++) {
3117 //Parsing Sample description table
3118 enum AVCodecID id;
3119 641 int ret, dref_id = 1;
3120 641 MOVAtom a = { AV_RL32("stsd") };
3121 641 int64_t start_pos = avio_tell(pb);
3122 641 int64_t size = avio_rb32(pb); /* size */
3123 641 uint32_t format = avio_rl32(pb); /* data format */
3124
3125
1/2
✓ Branch 0 taken 641 times.
✗ Branch 1 not taken.
641 if (size >= 16) {
3126 641 avio_rb32(pb); /* reserved */
3127 641 avio_rb16(pb); /* reserved */
3128 641 dref_id = avio_rb16(pb);
3129 } else if (size <= 7) {
3130 av_log(c->fc, AV_LOG_ERROR,
3131 "invalid size %"PRId64" in stsd\n", size);
3132 return AVERROR_INVALIDDATA;
3133 }
3134
3135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 641 times.
641 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3136 641 size - (avio_tell(pb) - start_pos))) {
3137 sc->stsd_count++;
3138 continue;
3139 }
3140
3141
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;
3142 641 sc->dref_id= dref_id;
3143 641 sc->format = format;
3144
3145 641 id = mov_codec_id(st, format);
3146
3147 641 av_log(c->fc, AV_LOG_TRACE,
3148 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3149 641 av_fourcc2str(format), st->codecpar->codec_type);
3150
3151 641 st->codecpar->codec_id = id;
3152
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 303 times.
641 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3153 338 mov_parse_stsd_video(c, pb, st, sc);
3154
2/2
✓ Branch 0 taken 247 times.
✓ Branch 1 taken 56 times.
303 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3155 247 mov_parse_stsd_audio(c, pb, st, sc);
3156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 247 times.
247 if (st->codecpar->sample_rate < 0) {
3157 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3158 return AVERROR_INVALIDDATA;
3159 }
3160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 247 times.
247 if (st->codecpar->ch_layout.nb_channels < 0) {
3161 av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3162 return AVERROR_INVALIDDATA;
3163 }
3164
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 41 times.
56 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3165 15 mov_parse_stsd_subtitle(c, pb, st, sc,
3166 15 size - (avio_tell(pb) - start_pos));
3167 } else {
3168 41 ret = mov_parse_stsd_data(c, pb, st, sc,
3169 41 size - (avio_tell(pb) - start_pos));
3170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ret < 0)
3171 return ret;
3172 }
3173 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3174 641 a.size = size - (avio_tell(pb) - start_pos);
3175
2/2
✓ Branch 0 taken 506 times.
✓ Branch 1 taken 135 times.
641 if (a.size > 8) {
3176
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 506 times.
506 if ((ret = mov_read_default(c, pb, a)) < 0)
3177 return ret;
3178
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 134 times.
135 } else if (a.size > 0)
3179 1 avio_skip(pb, a.size);
3180
3181 641 ret = mov_finalize_stsd_entry(c, st);
3182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 641 times.
641 if (ret < 0)
3183 return ret;
3184
3185
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) {
3186 366 int extra_size = st->codecpar->extradata_size;
3187
3188 /* Move the current stream extradata to the stream context one. */
3189 366 sc->extradata_size[pseudo_stream_id] = extra_size;
3190 366 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3191 366 st->codecpar->extradata = NULL;
3192 366 st->codecpar->extradata_size = 0;
3193 }
3194 641 sc->stsd_count++;
3195 }
3196
3197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (pb->eof_reached) {
3198 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3199 return AVERROR_EOF;
3200 }
3201
3202 627 return 0;
3203 }
3204
3205 627 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3206 {
3207 AVStream *st;
3208 MOVStreamContext *sc;
3209 int ret, entries;
3210
3211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->fc->nb_streams < 1)
3212 return 0;
3213 627 st = c->fc->streams[c->fc->nb_streams - 1];
3214 627 sc = st->priv_data;
3215
3216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (sc->extradata) {
3217 av_log(c->fc, AV_LOG_ERROR,
3218 "Duplicate stsd found in this track.\n");
3219 return AVERROR_INVALIDDATA;
3220 }
3221
3222 627 sc->stsd_version = avio_r8(pb);
3223 627 avio_rb24(pb); /* flags */
3224 627 entries = avio_rb32(pb);
3225
3226 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3227
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) {
3228 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3229 return AVERROR_INVALIDDATA;
3230 }
3231
3232 /* Prepare space for hosting multiple extradata. */
3233 627 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (!sc->extradata)
3235 return AVERROR(ENOMEM);
3236
3237 627 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (!sc->extradata_size) {
3239 ret = AVERROR(ENOMEM);
3240 goto fail;
3241 }
3242
3243 627 ret = ff_mov_read_stsd_entries(c, pb, entries);
3244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (ret < 0)
3245 goto fail;
3246
3247 /* Restore back the primary extradata. */
3248 627 av_freep(&st->codecpar->extradata);
3249 627 st->codecpar->extradata_size = sc->extradata_size[0];
3250
2/2
✓ Branch 0 taken 353 times.
✓ Branch 1 taken 274 times.
627 if (sc->extradata_size[0]) {
3251 353 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 353 times.
353 if (!st->codecpar->extradata)
3253 return AVERROR(ENOMEM);
3254 353 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3255 }
3256
3257 627 return mov_finalize_stsd_codec(c, pb, st, sc);
3258 fail:
3259 if (sc->extradata) {
3260 int j;
3261 for (j = 0; j < sc->stsd_count; j++)
3262 av_freep(&sc->extradata[j]);
3263 }
3264
3265 sc->stsd_count = 0;
3266 av_freep(&sc->extradata);
3267 av_freep(&sc->extradata_size);
3268 return ret;
3269 }
3270
3271 627 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3272 {
3273 AVStream *st;
3274 MOVStreamContext *sc;
3275 unsigned int i, entries;
3276
3277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->trak_index < 0) {
3278 av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3279 return 0;
3280 }
3281
3282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->fc->nb_streams < 1)
3283 return 0;
3284 627 st = c->fc->streams[c->fc->nb_streams-1];
3285 627 sc = st->priv_data;
3286
3287 627 avio_r8(pb); /* version */
3288 627 avio_rb24(pb); /* flags */
3289
3290 627 entries = avio_rb32(pb);
3291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if ((uint64_t)entries * 12 + 4 > atom.size)
3292 return AVERROR_INVALIDDATA;
3293
3294 627 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3295
3296
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 599 times.
627 if (!entries)
3297 28 return 0;
3298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 599 times.
599 if (sc->stsc_data) {
3299 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3300 return 0;
3301 }
3302 599 av_free(sc->stsc_data);
3303 599 sc->stsc_count = 0;
3304 599 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 599 times.
599 if (!sc->stsc_data)
3306 return AVERROR(ENOMEM);
3307
3308
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++) {
3309 3825 sc->stsc_data[i].first = avio_rb32(pb);
3310 3825 sc->stsc_data[i].count = avio_rb32(pb);
3311 3825 sc->stsc_data[i].id = avio_rb32(pb);
3312 }
3313
3314 599 sc->stsc_count = i;
3315
2/2
✓ Branch 0 taken 3825 times.
✓ Branch 1 taken 599 times.
4424 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3316 3825 int64_t first_min = i + 1;
3317
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) ||
3318
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) ||
3319
1/2
✓ Branch 0 taken 3825 times.
✗ Branch 1 not taken.
3825 sc->stsc_data[i].first < first_min ||
3320
1/2
✓ Branch 0 taken 3825 times.
✗ Branch 1 not taken.
3825 sc->stsc_data[i].count < 1 ||
3321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3825 times.
3825 sc->stsc_data[i].id < 1) {
3322 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);
3323 if (i+1 >= sc->stsc_count) {
3324 if (sc->stsc_data[i].count == 0 && i > 0) {
3325 sc->stsc_count --;
3326 continue;
3327 }
3328 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3329 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3330 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3331 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3332 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3333 continue;
3334 }
3335 av_assert0(sc->stsc_data[i+1].first >= 2);
3336 // We replace this entry by the next valid
3337 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3338 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3339 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3340 }
3341 }
3342
3343
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 599 times.
599 if (pb->eof_reached) {
3344 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3345 return AVERROR_EOF;
3346 }
3347
3348 599 return 0;
3349 }
3350
3351 341793 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3352 {
3353 341793 return index < count - 1;
3354 }
3355
3356 /* Compute the samples value for the stsc entry at the given index. */
3357 55625 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3358 {
3359 int chunk_count;
3360
3361
2/2
✓ Branch 1 taken 55429 times.
✓ Branch 2 taken 196 times.
55625 if (mov_stsc_index_valid(index, sc->stsc_count))
3362 55429 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3363 else {
3364 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3366 196 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3367 }
3368
3369 55625 return sc->stsc_data[index].count * (int64_t)chunk_count;
3370 }
3371
3372 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3373 {
3374 AVStream *st;
3375 MOVStreamContext *sc;
3376 unsigned i, entries;
3377
3378 if (c->trak_index < 0) {
3379 av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3380 return 0;
3381 }
3382
3383 if (c->fc->nb_streams < 1)
3384 return 0;
3385 st = c->fc->streams[c->fc->nb_streams-1];
3386 sc = st->priv_data;
3387
3388 avio_rb32(pb); // version + flags
3389
3390 entries = avio_rb32(pb);
3391 if (sc->stps_data)
3392 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3393 av_free(sc->stps_data);
3394 sc->stps_count = 0;
3395 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3396 if (!sc->stps_data)
3397 return AVERROR(ENOMEM);
3398
3399 for (i = 0; i < entries && !pb->eof_reached; i++) {
3400 sc->stps_data[i] = avio_rb32(pb);
3401 }
3402
3403 sc->stps_count = i;
3404
3405 if (pb->eof_reached) {
3406 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3407 return AVERROR_EOF;
3408 }
3409
3410 return 0;
3411 }
3412
3413 154 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3414 {
3415 AVStream *st;
3416 FFStream *sti;
3417 MOVStreamContext *sc;
3418 unsigned int i, entries;
3419
3420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 if (c->trak_index < 0) {
3421 av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3422 return 0;
3423 }
3424
3425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 if (c->fc->nb_streams < 1)
3426 return 0;
3427 154 st = c->fc->streams[c->fc->nb_streams-1];
3428 154 sti = ffstream(st);
3429 154 sc = st->priv_data;
3430
3431 154 avio_r8(pb); /* version */
3432 154 avio_rb24(pb); /* flags */
3433
3434 154 entries = avio_rb32(pb);
3435
3436 154 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3437
3438
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 148 times.
154 if (!entries) {
3439 6 sc->keyframe_absent = 1;
3440
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)
3441 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3442 6 return 0;
3443 }
3444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 148 times.
148 if (sc->keyframes)
3445 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 148 times.
148 if (entries >= UINT_MAX / sizeof(int))
3447 return AVERROR_INVALIDDATA;
3448 148 av_freep(&sc->keyframes);
3449 148 sc->keyframe_count = 0;
3450 148 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 148 times.
148 if (!sc->keyframes)
3452 return AVERROR(ENOMEM);
3453
3454
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++) {
3455 5732 sc->keyframes[i] = avio_rb32(pb);
3456 }
3457
3458 148 sc->keyframe_count = i;
3459
3460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 148 times.
148 if (pb->eof_reached) {
3461 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3462 return AVERROR_EOF;
3463 }
3464
3465 148 return 0;
3466 }
3467
3468 627 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3469 {
3470 AVStream *st;
3471 MOVStreamContext *sc;
3472 unsigned int i, entries, sample_size, field_size, num_bytes;
3473 GetBitContext gb;
3474 unsigned char* buf;
3475 int ret;
3476
3477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->trak_index < 0) {
3478 av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3479 return 0;
3480 }
3481
3482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->fc->nb_streams < 1)
3483 return 0;
3484 627 st = c->fc->streams[c->fc->nb_streams-1];
3485 627 sc = st->priv_data;
3486
3487 627 avio_r8(pb); /* version */
3488 627 avio_rb24(pb); /* flags */
3489
3490
1/2
✓ Branch 0 taken 627 times.
✗ Branch 1 not taken.
627 if (atom.type == MKTAG('s','t','s','z')) {
3491 627 sample_size = avio_rb32(pb);
3492
2/2
✓ Branch 0 taken 586 times.
✓ Branch 1 taken 41 times.
627 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3493 586 sc->sample_size = sample_size;
3494 627 sc->stsz_sample_size = sample_size;
3495 627 field_size = 32;
3496 } else {
3497 sample_size = 0;
3498 avio_rb24(pb); /* reserved */
3499 field_size = avio_r8(pb);
3500 }
3501 627 entries = avio_rb32(pb);
3502
3503 627 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3504
3505 627 sc->sample_count = entries;
3506
2/2
✓ Branch 0 taken 203 times.
✓ Branch 1 taken 424 times.
627 if (sample_size)
3507 203 return 0;
3508
3509
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) {
3510 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3511 return AVERROR_INVALIDDATA;
3512 }
3513
3514
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 395 times.
424 if (!entries)
3515 29 return 0;
3516
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)
3517 return AVERROR_INVALIDDATA;
3518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 395 times.
395 if (sc->sample_sizes)
3519 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3520 395 av_free(sc->sample_sizes);
3521 395 sc->sample_count = 0;
3522 395 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 395 times.
395 if (!sc->sample_sizes)
3524 return AVERROR(ENOMEM);
3525
3526 395 num_bytes = (entries*field_size+4)>>3;
3527
3528 395 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 395 times.
395 if (!buf) {
3530 av_freep(&sc->sample_sizes);
3531 return AVERROR(ENOMEM);
3532 }
3533
3534 395 ret = ffio_read_size(pb, buf, num_bytes);
3535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 395 times.
395 if (ret < 0) {
3536 av_freep(&sc->sample_sizes);
3537 av_free(buf);
3538 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3539 return 0;
3540 }
3541
3542 395 init_get_bits(&gb, buf, 8*num_bytes);
3543
3544
2/2
✓ Branch 0 taken 227737 times.
✓ Branch 1 taken 395 times.
228132 for (i = 0; i < entries; i++) {
3545 227737 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 227737 times.
227737 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3547 av_free(buf);
3548 av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3549 return AVERROR_INVALIDDATA;
3550 }
3551 227737 sc->data_size += sc->sample_sizes[i];
3552 }
3553
3554 395 sc->sample_count = i;
3555
3556 395 av_free(buf);
3557
3558 395 return 0;
3559 }
3560
3561 627 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3562 {
3563 AVStream *st;
3564 MOVStreamContext *sc;
3565 unsigned int i, entries;
3566 627 int64_t duration = 0;
3567 627 int64_t total_sample_count = 0;
3568 627 int64_t current_dts = 0;
3569 627 int64_t corrected_dts = 0;
3570
3571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->trak_index < 0) {
3572 av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3573 return 0;
3574 }
3575
3576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->fc->nb_streams < 1)
3577 return 0;
3578 627 st = c->fc->streams[c->fc->nb_streams-1];
3579 627 sc = st->priv_data;
3580
3581 627 avio_r8(pb); /* version */
3582 627 avio_rb24(pb); /* flags */
3583 627 entries = avio_rb32(pb);
3584
3585 627 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3586 627 c->fc->nb_streams-1, entries);
3587
3588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (sc->stts_data)
3589 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3590 627 av_freep(&sc->stts_data);
3591 627 sc->stts_count = 0;
3592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3593 return AVERROR(ENOMEM);
3594
3595
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++) {
3596 unsigned int sample_duration;
3597 unsigned int sample_count;
3598 2991 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3599 2991 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3600 min_entries * sizeof(*sc->stts_data));
3601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2991 times.
2991 if (!stts_data) {
3602 av_freep(&sc->stts_data);
3603 sc->stts_count = 0;
3604 return AVERROR(ENOMEM);
3605 }
3606 2991 sc->stts_count = min_entries;
3607 2991 sc->stts_data = stts_data;
3608
3609 2991 sample_count = avio_rb32(pb);
3610 2991 sample_duration = avio_rb32(pb);
3611
3612 2991 sc->stts_data[i].count= sample_count;
3613 2991 sc->stts_data[i].duration= sample_duration;
3614
3615 2991 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3616 sample_count, sample_duration);
3617
3618 /* STTS sample offsets are uint32 but some files store it as int32
3619 * with negative values used to correct DTS delays.
3620 There may be abnormally large values as well. */
3621
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2990 times.
2991 if (sample_duration > c->max_stts_delta) {
3622 // assume high delta is a correction if negative when cast as int32
3623 1 int32_t delta_magnitude = (int32_t)sample_duration;
3624 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",
3625 sample_duration, i, sample_count, st->index);
3626 1 sc->stts_data[i].duration = 1;
3627
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);
3628 } else {
3629 2990 corrected_dts += sample_duration * (uint64_t)sample_count;
3630 }
3631
3632 2991 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3633
3634
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2969 times.
2991 if (current_dts > corrected_dts) {
3635 22 int64_t drift = av_sat_sub64(current_dts, corrected_dts) / FFMAX(sample_count, 1);
3636
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;
3637 22 current_dts -= correction * (uint64_t)sample_count;
3638 22 sc->stts_data[i].duration -= correction;
3639 }
3640
3641 2991 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3642 2991 total_sample_count+=sc->stts_data[i].count;
3643 }
3644
3645 627 sc->stts_count = i;
3646
3647
2/2
✓ Branch 0 taken 598 times.
✓ Branch 1 taken 29 times.
627 if (duration > 0 &&
3648
1/2
✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
598 duration <= INT64_MAX - sc->duration_for_fps &&
3649
1/2
✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
598 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3650 598 sc->duration_for_fps += duration;
3651 598 sc->nb_frames_for_fps += total_sample_count;
3652 }
3653
3654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (pb->eof_reached) {
3655 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3656 return AVERROR_EOF;
3657 }
3658
3659 627 st->nb_frames= total_sample_count;
3660
2/2
✓ Branch 0 taken 598 times.
✓ Branch 1 taken 29 times.
627 if (duration)
3661 598 st->duration= FFMIN(st->duration, duration);
3662
3663 // All samples have zero duration. They have higher chance be chose by
3664 // mov_find_next_sample, which leads to seek again and again.
3665 //
3666 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3667 // So only mark data stream as discarded for safety.
3668
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 &&
3669 st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3670 av_log(c->fc, AV_LOG_WARNING,
3671 "All samples in data stream index:id [%d:%d] have zero "
3672 "duration, stream set to be discarded by default. Override "
3673 "using AVStream->discard or -discard for ffmpeg command.\n",
3674 st->index, sc->id);
3675 st->discard = AVDISCARD_ALL;
3676 }
3677 627 sc->track_end = duration;
3678 627 return 0;
3679 }
3680
3681 45 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3682 {
3683 AVStream *st;
3684 MOVStreamContext *sc;
3685 unsigned int i;
3686 int64_t entries;
3687
3688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (c->fc->nb_streams < 1)
3689 return 0;
3690 45 st = c->fc->streams[c->fc->nb_streams - 1];
3691 45 sc = st->priv_data;
3692
3693 45 avio_r8(pb); /* version */
3694 45 avio_rb24(pb); /* flags */
3695 45 entries = atom.size - 4;
3696
3697 45 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3698 45 c->fc->nb_streams - 1, entries);
3699
3700
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 37 times.
45 if (sc->sdtp_data)
3701 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3702 45 av_freep(&sc->sdtp_data);
3703 45 sc->sdtp_count = 0;
3704
3705
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)
3706 return AVERROR(ERANGE);
3707
3708 45 sc->sdtp_data = av_malloc(entries);
3709
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (!sc->sdtp_data)
3710 return AVERROR(ENOMEM);
3711
3712
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++)
3713 3811 sc->sdtp_data[i] = avio_r8(pb);
3714 45 sc->sdtp_count = i;
3715
3716 45 return 0;
3717 }
3718
3719 13717 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3720 {
3721
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 12581 times.
13717 if (duration < 0) {
3722
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3723 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3724 duration++;
3725 }
3726 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3727 }
3728 13717 }
3729
3730 67 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3731 {
3732 AVStream *st;
3733 MOVStreamContext *sc;
3734 67 unsigned int i, entries, ctts_count = 0;
3735
3736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
67 if (c->trak_index < 0) {
3737 av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
3738 return 0;
3739 }
3740
3741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
67 if (c->fc->nb_streams < 1)
3742 return 0;
3743 67 st = c->fc->streams[c->fc->nb_streams-1];
3744 67 sc = st->priv_data;
3745
3746 67 avio_r8(pb); /* version */
3747 67 avio_rb24(pb); /* flags */
3748 67 entries = avio_rb32(pb);
3749
3750 67 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3751
3752
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 63 times.
67 if (!entries)
3753 4 return 0;
3754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
3755 return AVERROR_INVALIDDATA;
3756 63 av_freep(&sc->ctts_data);
3757 63 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
3758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (!sc->ctts_data)
3759 return AVERROR(ENOMEM);
3760
3761
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++) {
3762 MOVCtts *ctts_data;
3763 5131 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
3764 5131 const size_t requested_size =
3765 5131 min_size_needed > sc->ctts_allocated_size ?
3766
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5131 times.
5131 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
3767 min_size_needed;
3768 5131 int count = avio_rb32(pb);
3769 5131 int duration = avio_rb32(pb);
3770
3771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5131 times.
5131 if (count <= 0) {
3772 av_log(c->fc, AV_LOG_TRACE,
3773 "ignoring CTTS entry with count=%d duration=%d\n",
3774 count, duration);
3775 continue;
3776 }
3777
3778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5131 times.
5131 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
3779 return AVERROR(ENOMEM);
3780
3781 5131 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
3782
3783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5131 times.
5131 if (!ctts_data)
3784 return AVERROR(ENOMEM);
3785
3786 5131 sc->ctts_data = ctts_data;
3787
3788 5131 ctts_data[ctts_count].count = count;
3789 5131 ctts_data[ctts_count].offset = duration;
3790 5131 ctts_count++;
3791
3792 5131 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
3793 count, duration);
3794
3795
2/2
✓ Branch 0 taken 5010 times.
✓ Branch 1 taken 121 times.
5131 if (i+2<entries)
3796 5010 mov_update_dts_shift(sc, duration, c->fc);
3797 }
3798
3799 63 sc->ctts_count = ctts_count;
3800
3801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (pb->eof_reached) {
3802 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
3803 return AVERROR_EOF;
3804 }
3805
3806 63 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
3807
3808 63 return 0;
3809 }
3810
3811 30 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3812 {
3813 AVStream *st;
3814 MOVStreamContext *sc;
3815 uint8_t version;
3816 uint32_t grouping_type;
3817 uint32_t default_length;
3818 av_unused uint32_t default_group_description_index;
3819 uint32_t entry_count;
3820
3821
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (c->fc->nb_streams < 1)
3822 return 0;
3823 30 st = c->fc->streams[c->fc->nb_streams - 1];
3824 30 sc = st->priv_data;
3825
3826 30 version = avio_r8(pb); /* version */
3827 30 avio_rb24(pb); /* flags */
3828 30 grouping_type = avio_rl32(pb);
3829
3830 /*
3831 * This function only supports "sync" boxes, but the code is able to parse
3832 * other boxes (such as "tscl", "tsas" and "stsa")
3833 */
3834
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 5 times.
30 if (grouping_type != MKTAG('s','y','n','c'))
3835 25 return 0;
3836
3837
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
3838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
3839 5 entry_count = avio_rb32(pb);
3840
3841 5 av_freep(&sc->sgpd_sync);
3842 5 sc->sgpd_sync_count = entry_count;
3843 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
3844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
3845 return AVERROR(ENOMEM);
3846
3847
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++) {
3848 8 uint32_t description_length = default_length;
3849
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)
3850 description_length = avio_rb32(pb);
3851
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
3852 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
3853 8 sc->sgpd_sync[i] = nal_unit_type;
3854 8 description_length -= 1;
3855 }
3856 8 avio_skip(pb, description_length);
3857 }
3858
3859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
3860 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
3861 return AVERROR_EOF;
3862 }
3863
3864 5 return 0;
3865 }
3866
3867 27 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3868 {
3869 AVStream *st;
3870 MOVStreamContext *sc;
3871 unsigned int i, entries;
3872 uint8_t version;
3873 uint32_t grouping_type;
3874 MOVSbgp *table, **tablep;
3875 int *table_count;
3876
3877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (c->fc->nb_streams < 1)
3878 return 0;
3879 27 st = c->fc->streams[c->fc->nb_streams-1];
3880 27 sc = st->priv_data;
3881
3882 27 version = avio_r8(pb); /* version */
3883 27 avio_rb24(pb); /* flags */
3884 27 grouping_type = avio_rl32(pb);
3885
3886
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 26 times.
27 if (grouping_type == MKTAG('r','a','p',' ')) {
3887 1 tablep = &sc->rap_group;
3888 1 table_count = &sc->rap_group_count;
3889
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 21 times.
26 } else if (grouping_type == MKTAG('s','y','n','c')) {
3890 5 tablep = &sc->sync_group;
3891 5 table_count = &sc->sync_group_count;
3892 } else {
3893 21 return 0;
3894 }
3895
3896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
3897 avio_rb32(pb); /* grouping_type_parameter */
3898
3899 6 entries = avio_rb32(pb);
3900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
3901 return 0;
3902
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
3903 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
3904 6 av_freep(tablep);
3905 6 table = av_malloc_array(entries, sizeof(*table));
3906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
3907 return AVERROR(ENOMEM);
3908 6 *tablep = table;
3909
3910
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++) {
3911 32 table[i].count = avio_rb32(pb); /* sample_count */
3912 32 table[i].index = avio_rb32(pb); /* group_description_index */
3913 }
3914
3915 6 *table_count = i;
3916
3917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
3918 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
3919 return AVERROR_EOF;
3920 }
3921
3922 6 return 0;
3923 }
3924
3925 /**
3926 * Get ith edit list entry (media time, duration).
3927 */
3928 937 static int get_edit_list_entry(MOVContext *mov,
3929 const MOVStreamContext *msc,
3930 unsigned int edit_list_index,
3931 int64_t *edit_list_media_time,
3932 int64_t *edit_list_duration,
3933 int64_t global_timescale)
3934 {
3935
2/2
✓ Branch 0 taken 454 times.
✓ Branch 1 taken 483 times.
937 if (edit_list_index == msc->elst_count) {
3936 454 return 0;
3937 }
3938 483 *edit_list_media_time = msc->elst_data[edit_list_index].time;
3939 483 *edit_list_duration = msc->elst_data[edit_list_index].duration;
3940
3941 /* duration is in global timescale units;convert to msc timescale */
3942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
483 if (global_timescale == 0) {
3943 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
3944 return 0;
3945 }
3946 483 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
3947 global_timescale);
3948
3949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
483 if (*edit_list_duration + (uint64_t)*edit_list_media_time > INT64_MAX)
3950 *edit_list_duration = 0;
3951
3952 483 return 1;
3953 }
3954
3955 /**
3956 * Find the closest previous frame to the timestamp_pts, in e_old index
3957 * entries. Searching for just any frame / just key frames can be controlled by
3958 * last argument 'flag'.
3959 * Note that if ctts_data is not NULL, we will always search for a key frame
3960 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
3961 * return the first frame of the video.
3962 *
3963 * Here the timestamp_pts is considered to be a presentation timestamp and
3964 * the timestamp of index entries are considered to be decoding timestamps.
3965 *
3966 * Returns 0 if successful in finding a frame, else returns -1.
3967 * Places the found index corresponding output arg.
3968 *
3969 * If ctts_old is not NULL, then refines the searched entry by searching
3970 * backwards from the found timestamp, to find the frame with correct PTS.
3971 *
3972 * Places the found ctts_index and ctts_sample in corresponding output args.
3973 */
3974 483 static int find_prev_closest_index(AVStream *st,
3975 AVIndexEntry *e_old,
3976 int nb_old,
3977 MOVTimeToSample *tts_data,
3978 int64_t tts_count,
3979 int64_t timestamp_pts,
3980 int flag,
3981 int64_t* index,
3982 int64_t* tts_index,
3983 int64_t* tts_sample)
3984 {
3985 483 MOVStreamContext *msc = st->priv_data;
3986 483 FFStream *const sti = ffstream(st);
3987 483 AVIndexEntry *e_keep = sti->index_entries;
3988 483 int nb_keep = sti->nb_index_entries;
3989 483 int64_t i = 0;
3990
3991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
483 av_assert0(index);
3992
3993 // If dts_shift > 0, then all the index timestamps will have to be offset by
3994 // at least dts_shift amount to obtain PTS.
3995 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
3996
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 474 times.
483 if (msc->dts_shift > 0) {
3997 9 timestamp_pts -= msc->dts_shift;
3998 }
3999
4000 483 sti->index_entries = e_old;
4001 483 sti->nb_index_entries = nb_old;
4002 483 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
4003
4004 // Keep going backwards in the index entries until the timestamp is the same.
4005
2/2
✓ Branch 0 taken 482 times.
✓ Branch 1 taken 1 times.
483 if (*index >= 0) {
4006
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;
4007 i--) {
4008 if ((flag & AVSEEK_FLAG_ANY) ||
4009 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
4010 *index = i - 1;
4011 }
4012 }
4013 }
4014
4015 // If we have CTTS then refine the search, by searching backwards over PTS
4016 // computed by adding corresponding CTTS durations to index timestamps.
4017
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) {
4018
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 av_assert0(tts_index);
4019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 av_assert0(tts_sample);
4020 // Find out the ctts_index for the found frame.
4021 70 *tts_index = 0;
4022 70 *tts_sample = 0;
4023
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++) {
4024
1/2
✓ Branch 0 taken 214 times.
✗ Branch 1 not taken.
214 if (*tts_index < tts_count) {
4025 214 (*tts_sample)++;
4026
1/2
✓ Branch 0 taken 214 times.
✗ Branch 1 not taken.
214 if (tts_data[*tts_index].count == *tts_sample) {
4027 214 (*tts_index)++;
4028 214 *tts_sample = 0;
4029 }
4030 }
4031 }
4032
4033
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) {
4034 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
4035 // No need to add dts_shift to the timestamp here because timestamp_pts has already been
4036 // compensated by dts_shift above.
4037
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 &&
4038
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 5 times.
68 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
4039 63 break;
4040 }
4041
4042 17 (*index)--;
4043
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 if (*tts_sample == 0) {
4044 17 (*tts_index)--;
4045
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 7 times.
17 if (*tts_index >= 0)
4046 10 *tts_sample = tts_data[*tts_index].count - 1;
4047 } else {
4048 (*tts_sample)--;
4049 }
4050 }
4051 }
4052
4053 /* restore AVStream state*/
4054 483 sti->index_entries = e_keep;
4055 483 sti->nb_index_entries = nb_keep;
4056
2/2
✓ Branch 0 taken 475 times.
✓ Branch 1 taken 8 times.
483 return *index >= 0 ? 0 : -1;
4057 }
4058
4059 /**
4060 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
4061 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
4062 *
4063 * This function is similar to ff_add_index_entry in libavformat/utils.c
4064 * except that here we are always unconditionally adding an index entry to
4065 * the end, instead of searching the entries list and skipping the add if
4066 * there is an existing entry with the same timestamp.
4067 * This is needed because the mov_fix_index calls this func with the same
4068 * unincremented timestamp for successive discarded frames.
4069 */
4070 350595 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
4071 int size, int distance, int flags)
4072 {
4073 350595 FFStream *const sti = ffstream(st);
4074 AVIndexEntry *entries, *ie;
4075 350595 int64_t index = -1;
4076 350595 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
4077
4078 // Double the allocation each time, to lower memory fragmentation.
4079 // Another difference from ff_add_index_entry function.
4080 350595 const size_t requested_size =
4081 350595 min_size_needed > sti->index_entries_allocated_size ?
4082
2/2
✓ Branch 0 taken 2038 times.
✓ Branch 1 taken 348557 times.
350595 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
4083 min_size_needed;
4084
4085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 350595 times.
350595 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
4086 return -1;
4087
4088 350595 entries = av_fast_realloc(sti->index_entries,
4089 &sti->index_entries_allocated_size,
4090 requested_size);
4091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 350595 times.
350595 if (!entries)
4092 return -1;
4093
4094 350595 sti->index_entries = entries;
4095
4096 350595 index = sti->nb_index_entries++;
4097 350595 ie= &entries[index];
4098
4099 350595 ie->pos = pos;
4100 350595 ie->timestamp = timestamp;
4101 350595 ie->min_distance= distance;
4102 350595 ie->size= size;
4103 350595 ie->flags = flags;
4104 350595 return index;
4105 }
4106
4107 /**
4108 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4109 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4110 */
4111 29 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4112 int64_t* frame_duration_buffer,
4113 int frame_duration_buffer_size) {
4114 29 FFStream *const sti = ffstream(st);
4115 29 int i = 0;
4116
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);
4117
2/2
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 29 times.
191 for (i = 0; i < frame_duration_buffer_size; i++) {
4118 162 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4119 162 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4120 }
4121 29 }
4122
4123 186576 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4124 int count, int offset, unsigned int duration)
4125 {
4126 MOVTimeToSample *tts_buf_new;
4127 186576 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4128 186576 const size_t requested_size =
4129 186576 min_size_needed > *allocated_size ?
4130
2/2
✓ Branch 0 taken 1394 times.
✓ Branch 1 taken 185182 times.
186576 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4131 min_size_needed;
4132
4133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186576 times.
186576 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4134 return -1;
4135
4136 186576 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4137
4138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186576 times.
186576 if (!tts_buf_new)
4139 return -1;
4140
4141 186576 *tts_data = tts_buf_new;
4142
4143 186576 tts_buf_new[*tts_count].count = count;
4144 186576 tts_buf_new[*tts_count].offset = offset;
4145 186576 tts_buf_new[*tts_count].duration = duration;
4146
4147 186576 *tts_count = (*tts_count) + 1;
4148 186576 return 0;
4149 }
4150
4151 #define MAX_REORDER_DELAY 16
4152 641 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4153 {
4154 641 MOVStreamContext *msc = st->priv_data;
4155 641 FFStream *const sti = ffstream(st);
4156 641 int ctts_ind = 0;
4157 641 int ctts_sample = 0;
4158 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4159 641 int buf_start = 0;
4160 int j, r, num_swaps;
4161
4162
2/2
✓ Branch 0 taken 10897 times.
✓ Branch 1 taken 641 times.
11538 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4163 10897 pts_buf[j] = INT64_MIN;
4164
4165
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 &&
4166
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 19 times.
63 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4167 44 st->codecpar->video_delay = 0;
4168
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) {
4169 // Point j to the last elem of the buffer and insert the current pts there.
4170 138353 j = buf_start;
4171 138353 buf_start = (buf_start + 1);
4172
2/2
✓ Branch 0 taken 8115 times.
✓ Branch 1 taken 130238 times.
138353 if (buf_start == MAX_REORDER_DELAY + 1)
4173 8115 buf_start = 0;
4174
4175 138353 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4176
4177 // The timestamps that are already in the sorted buffer, and are greater than the
4178 // current pts, are exactly the timestamps that need to be buffered to output PTS
4179 // in correct sorted order.
4180 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4181 // can be computed as the maximum no. of swaps any particular timestamp needs to
4182 // go through, to keep this buffer in sorted order.
4183 138353 num_swaps = 0;
4184
2/2
✓ Branch 0 taken 142584 times.
✓ Branch 1 taken 4 times.
142588 while (j != buf_start) {
4185 142584 r = j - 1;
4186
2/2
✓ Branch 0 taken 8406 times.
✓ Branch 1 taken 134178 times.
142584 if (r < 0) r = MAX_REORDER_DELAY;
4187
2/2
✓ Branch 0 taken 4235 times.
✓ Branch 1 taken 138349 times.
142584 if (pts_buf[j] < pts_buf[r]) {
4188 4235 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4189 4235 ++num_swaps;
4190 } else {
4191 138349 break;
4192 }
4193 4235 j = r;
4194 }
4195 138353 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4196
4197 138353 ctts_sample++;
4198
1/2
✓ Branch 0 taken 138353 times.
✗ Branch 1 not taken.
138353 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4199 138353 ctts_ind++;
4200 138353 ctts_sample = 0;
4201 }
4202 }
4203 44 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4204 44 st->codecpar->video_delay, st->index);
4205 }
4206 641 }
4207
4208 106478 static void mov_current_sample_inc(MOVStreamContext *sc)
4209 {
4210 106478 sc->current_sample++;
4211 106478 sc->current_index++;
4212
2/2
✓ Branch 0 taken 61817 times.
✓ Branch 1 taken 44661 times.
106478 if (sc->index_ranges &&
4213
2/2
✓ Branch 0 taken 438 times.
✓ Branch 1 taken 61379 times.
61817 sc->current_index >= sc->current_index_range->end &&
4214
1/2
✓ Branch 0 taken 438 times.
✗ Branch 1 not taken.
438 sc->current_index_range->end) {
4215 438 sc->current_index_range++;
4216 438 sc->current_index = sc->current_index_range->start;
4217 }
4218 106478 }
4219
4220 static void mov_current_sample_dec(MOVStreamContext *sc)
4221 {
4222 sc->current_sample--;
4223 sc->current_index--;
4224 if (sc->index_ranges &&
4225 sc->current_index < sc->current_index_range->start &&
4226 sc->current_index_range > sc->index_ranges) {
4227 sc->current_index_range--;
4228 sc->current_index = sc->current_index_range->end - 1;
4229 }
4230 }
4231
4232 337 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4233 {
4234 int64_t range_size;
4235
4236 337 sc->current_sample = current_sample;
4237 337 sc->current_index = current_sample;
4238
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 309 times.
337 if (!sc->index_ranges) {
4239 28 return;
4240 }
4241
4242 309 for (sc->current_index_range = sc->index_ranges;
4243
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 sc->current_index_range->end;
4244 sc->current_index_range++) {
4245 309 range_size = sc->current_index_range->end - sc->current_index_range->start;
4246
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 if (range_size > current_sample) {
4247 309 sc->current_index = sc->current_index_range->start + current_sample;
4248 309 break;
4249 }
4250 current_sample -= range_size;
4251 }
4252 }
4253
4254 /**
4255 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4256 * which are needed to decode them) that fall in the edit list time ranges.
4257 * Also fixes the timestamps of the index entries to match the timeline
4258 * specified the edit lists.
4259 */
4260 641 static void mov_fix_index(MOVContext *mov, AVStream *st)
4261 {
4262 641 MOVStreamContext *msc = st->priv_data;
4263 641 FFStream *const sti = ffstream(st);
4264 641 AVIndexEntry *e_old = sti->index_entries;
4265 641 int nb_old = sti->nb_index_entries;
4266 641 const AVIndexEntry *e_old_end = e_old + nb_old;
4267 641 const AVIndexEntry *current = NULL;
4268 641 MOVTimeToSample *tts_data_old = msc->tts_data;
4269 641 int64_t tts_index_old = 0;
4270 641 int64_t tts_sample_old = 0;
4271 641 int64_t tts_count_old = msc->tts_count;
4272 641 int64_t edit_list_media_time = 0;
4273 641 int64_t edit_list_duration = 0;
4274 641 int64_t frame_duration = 0;
4275 641 int64_t edit_list_dts_counter = 0;
4276 641 int64_t edit_list_dts_entry_end = 0;
4277 641 int64_t edit_list_start_tts_sample = 0;
4278 int64_t curr_cts;
4279 641 int64_t curr_ctts = 0;
4280 641 int64_t empty_edits_sum_duration = 0;
4281 641 int64_t edit_list_index = 0;
4282 int64_t index;
4283 int flags;
4284 641 int64_t start_dts = 0;
4285 641 int64_t edit_list_start_encountered = 0;
4286 641 int64_t search_timestamp = 0;
4287 641 int64_t* frame_duration_buffer = NULL;
4288 641 int num_discarded_begin = 0;
4289 641 int first_non_zero_audio_edit = -1;
4290 641 int packet_skip_samples = 0;
4291 641 MOVIndexRange *current_index_range = NULL;
4292 641 int found_keyframe_after_edit = 0;
4293 641 int found_non_empty_edit = 0;
4294
4295
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) {
4296 187 return;
4297 }
4298
4299 // allocate the index ranges array
4300 454 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4301 sizeof(msc->index_ranges[0]));
4302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 454 times.
454 if (!msc->index_ranges) {
4303 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4304 return;
4305 }
4306 454 msc->current_index_range = msc->index_ranges;
4307
4308 // Clean AVStream from traces of old index
4309 454 sti->index_entries = NULL;
4310 454 sti->index_entries_allocated_size = 0;
4311 454 sti->nb_index_entries = 0;
4312
4313 // Clean time to sample fields of MOVStreamContext
4314 454 msc->tts_data = NULL;
4315 454 msc->tts_count = 0;
4316 454 msc->tts_index = 0;
4317 454 msc->tts_sample = 0;
4318 454 msc->tts_allocated_size = 0;
4319
4320 // Reinitialize min_corrected_pts so that it can be computed again.
4321 454 msc->min_corrected_pts = -1;
4322
4323 // If the dts_shift is positive (in case of negative ctts values in mov),
4324 // then negate the DTS by dts_shift
4325
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 445 times.
454 if (msc->dts_shift > 0) {
4326 9 edit_list_dts_entry_end -= msc->dts_shift;
4327 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4328 }
4329
4330 454 start_dts = edit_list_dts_entry_end;
4331
4332
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,
4333 937 &edit_list_duration, mov->time_scale)) {
4334 483 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4335 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4336 483 edit_list_index++;
4337 483 edit_list_dts_counter = edit_list_dts_entry_end;
4338 483 edit_list_dts_entry_end = av_sat_add64(edit_list_dts_entry_end, edit_list_duration);
4339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
483 if (edit_list_dts_entry_end == INT64_MAX) {
4340 av_log(mov->fc, AV_LOG_ERROR, "Cannot calculate dts entry length with duration %"PRId64"\n",
4341 edit_list_duration);
4342 break;
4343 }
4344 483 num_discarded_begin = 0;
4345
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) {
4346 4 empty_edits_sum_duration += edit_list_duration;
4347 4 continue;
4348 }
4349 479 found_non_empty_edit = 1;
4350
4351 // If we encounter a non-negative edit list reset the skip_samples/start_pad fields and set them
4352 // according to the edit list below.
4353
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 349 times.
479 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4354
1/2
✓ Branch 0 taken 130 times.
✗ Branch 1 not taken.
130 if (first_non_zero_audio_edit < 0) {
4355 130 first_non_zero_audio_edit = 1;
4356 } else {
4357 first_non_zero_audio_edit = 0;
4358 }
4359
4360
1/2
✓ Branch 0 taken 130 times.
✗ Branch 1 not taken.
130 if (first_non_zero_audio_edit > 0)
4361 130 sti->skip_samples = msc->start_pad = 0;
4362 }
4363
4364 // While reordering frame index according to edit list we must handle properly
4365 // the scenario when edit list entry starts from none key frame.
4366 // We find closest previous key frame and preserve it and consequent frames in index.
4367 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4368 479 search_timestamp = edit_list_media_time;
4369
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 349 times.
479 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4370 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4371 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4372 // edit_list_media_time to cover the decoder delay.
4373 130 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
4374 }
4375
4376
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,
4377 &index, &tts_index_old, &tts_sample_old) < 0) {
4378 4 av_log(mov->fc, AV_LOG_WARNING,
4379 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4380 st->index, edit_list_index, search_timestamp);
4381
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,
4382 &index, &tts_index_old, &tts_sample_old) < 0) {
4383 4 av_log(mov->fc, AV_LOG_WARNING,
4384 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4385 st->index, edit_list_index, search_timestamp);
4386 4 index = 0;
4387 4 tts_index_old = 0;
4388 4 tts_sample_old = 0;
4389 }
4390 }
4391 479 current = e_old + index;
4392 479 edit_list_start_tts_sample = tts_sample_old;
4393
4394 // Iterate over index and arrange it according to edit list
4395 479 edit_list_start_encountered = 0;
4396 479 found_keyframe_after_edit = 0;
4397
2/2
✓ Branch 0 taken 350595 times.
✓ Branch 1 taken 120 times.
350715 for (; current < e_old_end; current++, index++) {
4398 // check if frame outside edit list mark it for discard
4399 701190 frame_duration = (current + 1 < e_old_end) ?
4400
2/2
✓ Branch 0 taken 350145 times.
✓ Branch 1 taken 450 times.
350595 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4401
4402 350595 flags = current->flags;
4403
4404 // frames (pts) before or after edit list
4405 350595 curr_cts = current->timestamp + msc->dts_shift;
4406 350595 curr_ctts = 0;
4407
4408
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) {
4409 186576 curr_ctts = tts_data_old[tts_index_old].offset;
4410 186576 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4411 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4412 186576 curr_cts += curr_ctts;
4413 186576 tts_sample_old++;
4414
1/2
✓ Branch 0 taken 186576 times.
✗ Branch 1 not taken.
186576 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186576 times.
186576 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4416 &msc->tts_allocated_size,
4417 186576 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4418 186576 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4419 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4420 tts_index_old,
4421 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4422 tts_data_old[tts_index_old].offset);
4423 break;
4424 }
4425 186576 tts_index_old++;
4426 186576 tts_sample_old = 0;
4427 186576 edit_list_start_tts_sample = 0;
4428 }
4429 }
4430
4431
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)) {
4432
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 &&
4433
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 &&
4434 first_non_zero_audio_edit > 0) {
4435 12 packet_skip_samples = edit_list_media_time - curr_cts;
4436 12 sti->skip_samples += packet_skip_samples;
4437
4438 // Shift the index entry timestamp by packet_skip_samples to be correct.
4439 12 edit_list_dts_counter -= packet_skip_samples;
4440
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (edit_list_start_encountered == 0) {
4441 12 edit_list_start_encountered = 1;
4442 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4443 // discarded packets.
4444
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 if (frame_duration_buffer) {
4445 7 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4446 frame_duration_buffer, num_discarded_begin);
4447 7 av_freep(&frame_duration_buffer);
4448 }
4449 }
4450
4451 12 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4452 } else {
4453 323 flags |= AVINDEX_DISCARD_FRAME;
4454 323 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4455
4456
2/2
✓ Branch 0 taken 164 times.
✓ Branch 1 taken 159 times.
323 if (edit_list_start_encountered == 0) {
4457 164 num_discarded_begin++;
4458 164 frame_duration_buffer = av_realloc(frame_duration_buffer,
4459 num_discarded_begin * sizeof(int64_t));
4460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 164 times.
164 if (!frame_duration_buffer) {
4461 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4462 break;
4463 }
4464 164 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4465
4466 // Increment skip_samples for the first non-zero audio edit list
4467
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 &&
4468
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) {
4469 21 sti->skip_samples += frame_duration;
4470 }
4471 }
4472 }
4473 } else {
4474
2/2
✓ Branch 0 taken 453 times.
✓ Branch 1 taken 349807 times.
350260 if (msc->min_corrected_pts < 0) {
4475 453 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4476 } else {
4477 349807 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4478 }
4479
2/2
✓ Branch 0 taken 465 times.
✓ Branch 1 taken 349795 times.
350260 if (edit_list_start_encountered == 0) {
4480 465 edit_list_start_encountered = 1;
4481 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4482 // discarded packets.
4483
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 443 times.
465 if (frame_duration_buffer) {
4484 22 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4485 frame_duration_buffer, num_discarded_begin);
4486 22 av_freep(&frame_duration_buffer);
4487 }
4488 }
4489 }
4490
4491
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,
4492 350595 current->min_distance, flags) == -1) {
4493 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4494 break;
4495 }
4496
4497 // Update the index ranges array
4498
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) {
4499 477 current_index_range = current_index_range ? current_index_range + 1
4500
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 454 times.
477 : msc->index_ranges;
4501 477 current_index_range->start = index;
4502 }
4503 350595 current_index_range->end = index + 1;
4504
4505 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4506
2/2
✓ Branch 0 taken 350431 times.
✓ Branch 1 taken 164 times.
350595 if (edit_list_start_encountered > 0) {
4507 350431 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4508 }
4509
4510 // Break when found first key frame after edit entry completion
4511
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)) &&
4512
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)))) {
4513
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 348 times.
373 if (msc->ctts_count) {
4514 // If we have CTTS and this is the first keyframe after edit elist,
4515 // wait for one more, because there might be trailing B-frames after this I-frame
4516 // that do belong to the edit.
4517
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) {
4518 14 found_keyframe_after_edit = 1;
4519 14 continue;
4520 }
4521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (tts_sample_old != 0) {
4522 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4523 &msc->tts_allocated_size,
4524 tts_sample_old - edit_list_start_tts_sample,
4525 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4526 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4527 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4528 tts_data_old[tts_index_old].offset);
4529 break;
4530 }
4531 }
4532 }
4533 359 break;
4534 }
4535 }
4536 }
4537 // If there are empty edits, then msc->min_corrected_pts might be positive
4538 // intentionally. So we subtract the sum duration of empty edits here.
4539 454 msc->min_corrected_pts -= empty_edits_sum_duration;
4540
4541 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4542 // dts by that amount to make the first pts zero.
4543
2/2
✓ Branch 0 taken 282 times.
✓ Branch 1 taken 172 times.
454 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4544
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 237 times.
282 if (msc->min_corrected_pts > 0) {
4545 45 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4546
2/2
✓ Branch 0 taken 3113 times.
✓ Branch 1 taken 45 times.
3158 for (int i = 0; i < sti->nb_index_entries; ++i)
4547 3113 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4548 }
4549 }
4550 // Start time should be equal to zero or the duration of any empty edits.
4551 454 st->start_time = empty_edits_sum_duration;
4552
4553 // Update av stream length, if it ends up shorter than the track's media duration
4554 454 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4555 454 msc->start_pad = sti->skip_samples;
4556
4557 // Free the old index and the old CTTS structures
4558 454 av_free(e_old);
4559 454 av_free(tts_data_old);
4560 454 av_freep(&frame_duration_buffer);
4561
4562 // Null terminate the index ranges array
4563 454 current_index_range = current_index_range ? current_index_range + 1
4564
1/2
✓ Branch 0 taken 454 times.
✗ Branch 1 not taken.
454 : msc->index_ranges;
4565 454 current_index_range->start = 0;
4566 454 current_index_range->end = 0;
4567 454 msc->current_index = msc->index_ranges[0].start;
4568 }
4569
4570 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4571 {
4572
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4573
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == nal_unit_type)
4574 5 return i + 1;
4575 return 0;
4576 }
4577
4578 670 static int build_open_gop_key_points(AVStream *st)
4579 {
4580 int k;
4581 670 int sample_id = 0;
4582 uint32_t cra_index;
4583 670 MOVStreamContext *sc = st->priv_data;
4584
4585
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)
4586 665 return 0;
4587
4588 /* Build an unrolled index of the samples */
4589 5 sc->sample_offsets_count = 0;
4590
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4592 return AVERROR(ENOMEM);
4593 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4594 }
4595 5 av_freep(&sc->sample_offsets);
4596 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4598 return AVERROR(ENOMEM);
4599 5 k = 0;
4600
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4601
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4602 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4603
4604 /* The following HEVC NAL type reveal the use of open GOP sync points
4605 * (TODO: BLA types may also be concerned) */
4606 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4608 return 0;
4609
4610 /* Build a list of open-GOP key samples */
4611 5 sc->open_key_samples_count = 0;
4612
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4613
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4614
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)
4615 return AVERROR(ENOMEM);
4616 11 sc->open_key_samples_count += sc->sync_group[i].count;
4617 }
4618 5 av_freep(&sc->open_key_samples);
4619 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4621 return AVERROR(ENOMEM);
4622 5 k = 0;
4623
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4624 28 const MOVSbgp *sg = &sc->sync_group[i];
4625
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4626
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4627 11 sc->open_key_samples[k++] = sample_id;
4628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4629 return AVERROR_PATCHWELCOME;
4630 28 sample_id += sg->count;
4631 }
4632
4633 /* Identify the minimal time step between samples */
4634 5 sc->min_sample_duration = UINT_MAX;
4635
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4636 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4637
4638 5 return 0;
4639 }
4640
4641 #define MOV_MERGE_CTTS 1
4642 #define MOV_MERGE_STTS 2
4643 /*
4644 * Merge stts and ctts arrays into a new combined array.
4645 * stts_count and ctts_count may be left untouched as they will be
4646 * used to check for the presence of either of them.
4647 */
4648 641 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4649 {
4650 641 MOVStreamContext *sc = st->priv_data;
4651
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);
4652
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);
4653 641 int idx = 0;
4654
4655
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)
4656 return 0;
4657 // Expand time to sample entries such that we have a 1-1 mapping with samples
4658
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))
4659 return -1;
4660
4661
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 578 times.
641 if (ctts) {
4662 126 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4663 63 sc->sample_count * sizeof(*sc->tts_data));
4664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (!sc->tts_data)
4665 return -1;
4666
4667 63 memset(sc->tts_data, 0, sc->tts_allocated_size);
4668
4669
2/2
✓ Branch 0 taken 5131 times.
✓ Branch 1 taken 63 times.
5194 for (int i = 0; i < sc->ctts_count &&
4670
1/2
✓ Branch 0 taken 5131 times.
✗ Branch 1 not taken.
10262 idx < sc->sample_count; i++)
4671
2/2
✓ Branch 0 taken 139275 times.
✓ Branch 1 taken 5131 times.
144406 for (int j = 0; j < sc->ctts_data[i].count &&
4672
1/2
✓ Branch 0 taken 139275 times.
✗ Branch 1 not taken.
139275 idx < sc->sample_count; j++) {
4673 139275 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4674 139275 sc->tts_data[idx++].count = 1;
4675 }
4676
4677 63 sc->tts_count = idx;
4678 } else
4679 578 sc->ctts_count = 0;
4680 641 av_freep(&sc->ctts_data);
4681 641 sc->ctts_allocated_size = 0;
4682
4683 641 idx = 0;
4684
2/2
✓ Branch 0 taken 575 times.
✓ Branch 1 taken 66 times.
641 if (stts) {
4685 575 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4686 575 sc->sample_count * sizeof(*sc->tts_data));
4687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 if (!tts_data)
4688 return -1;
4689
4690
2/2
✓ Branch 0 taken 512 times.
✓ Branch 1 taken 63 times.
575 if (!sc->tts_data)
4691 512 memset(tts_data, 0, sc->tts_allocated_size);
4692 575 sc->tts_data = tts_data;
4693
4694
2/2
✓ Branch 0 taken 2968 times.
✓ Branch 1 taken 575 times.
3543 for (int i = 0; i < sc->stts_count &&
4695
1/2
✓ Branch 0 taken 2968 times.
✗ Branch 1 not taken.
5936 idx < sc->sample_count; i++)
4696
2/2
✓ Branch 0 taken 236773 times.
✓ Branch 1 taken 2968 times.
239741 for (int j = 0; j < sc->stts_data[i].count &&
4697
1/2
✓ Branch 0 taken 236773 times.
✗ Branch 1 not taken.
236773 idx < sc->sample_count; j++) {
4698 236773 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4699 236773 sc->tts_data[idx++].count = 1;
4700 }
4701
4702 575 sc->tts_count = FFMAX(sc->tts_count, idx);
4703 } else
4704 66 sc->stts_count = 0;
4705 641 av_freep(&sc->stts_data);
4706 641 sc->stts_allocated_size = 0;
4707
4708 641 return 0;
4709 }
4710
4711 670 static void mov_build_index(MOVContext *mov, AVStream *st)
4712 {
4713 670 MOVStreamContext *sc = st->priv_data;
4714 670 FFStream *const sti = ffstream(st);
4715 int64_t current_offset;
4716 670 int64_t current_dts = 0;
4717 670 unsigned int stts_index = 0;
4718 670 unsigned int stsc_index = 0;
4719 670 unsigned int stss_index = 0;
4720 670 unsigned int stps_index = 0;
4721 unsigned int i, j;
4722 670 uint64_t stream_size = 0;
4723
4724 670 int ret = build_open_gop_key_points(st);
4725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 670 times.
670 if (ret < 0)
4726 return;
4727
4728
2/2
✓ Branch 0 taken 457 times.
✓ Branch 1 taken 213 times.
670 if (sc->elst_count) {
4729 457 int i, edit_start_index = 0, multiple_edits = 0;
4730 457 int64_t empty_duration = 0; // empty duration of the first edit list entry
4731 457 int64_t start_time = 0; // start time of the media
4732
4733
2/2
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 457 times.
943 for (i = 0; i < sc->elst_count; i++) {
4734 486 const MOVElst *e = &sc->elst_data[i];
4735
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) {
4736 /* if empty, the first entry is the start time of the stream
4737 * relative to the presentation itself */
4738 4 empty_duration = e->duration;
4739 4 edit_start_index = 1;
4740
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) {
4741 457 start_time = e->time;
4742 } else {
4743 25 multiple_edits = 1;
4744 }
4745 }
4746
4747
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) {
4748 if (mov->advanced_editlist_autodisabled)
4749 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4750 "not supported in fragmented MP4 files\n");
4751 else
4752 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4753 "Use -advanced_editlist to correctly decode otherwise "
4754 "a/v desync might occur\n");
4755 }
4756
4757 /* adjust first dts according to edit list */
4758
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) {
4759
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 75 times.
79 if (empty_duration)
4760 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
4761
4762
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)
4763 av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
4764
4765 79 sc->time_offset = start_time - (uint64_t)empty_duration;
4766 79 sc->min_corrected_pts = start_time;
4767
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 78 times.
79 if (!mov->advanced_editlist)
4768 1 current_dts = -sc->time_offset;
4769 }
4770
4771
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 &&
4772
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)
4773 sc->start_pad = av_rescale_q(start_time, st->time_base,
4774 (AVRational){1, st->codecpar->sample_rate});
4775 }
4776
4777 /* only use old uncompressed audio chunk demuxing when stts specifies it */
4778
2/2
✓ Branch 0 taken 247 times.
✓ Branch 1 taken 423 times.
670 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4779
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)) {
4780 604 unsigned int current_sample = 0;
4781 604 unsigned int stts_sample = 0;
4782 unsigned int sample_size;
4783 604 unsigned int distance = 0;
4784 604 unsigned int rap_group_index = 0;
4785 604 unsigned int rap_group_sample = 0;
4786
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;
4787
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);
4788
4789 604 current_dts -= sc->dts_shift;
4790
4791
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)
4792 29 return;
4793
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)
4794 return;
4795
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 if (av_reallocp_array(&sti->index_entries,
4796 575 sti->nb_index_entries + sc->sample_count,
4797 sizeof(*sti->index_entries)) < 0) {
4798 sti->nb_index_entries = 0;
4799 return;
4800 }
4801 575 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
4802
4803 575 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
4804
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
575 if (ret < 0)
4805 return;
4806
4807
2/2
✓ Branch 0 taken 174325 times.
✓ Branch 1 taken 575 times.
174900 for (i = 0; i < sc->chunk_count; i++) {
4808
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;
4809 174325 current_offset = sc->chunk_offsets[i];
4810
2/2
✓ Branch 1 taken 8947 times.
✓ Branch 2 taken 167947 times.
176894 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4811
2/2
✓ Branch 0 taken 2569 times.
✓ Branch 1 taken 6378 times.
8947 i + 1 == sc->stsc_data[stsc_index + 1].first)
4812 2569 stsc_index++;
4813
4814
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 &&
4815 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
4816 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
4817 sc->stsz_sample_size = sc->sample_size;
4818 }
4819
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) {
4820 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
4821 sc->stsz_sample_size = sc->sample_size;
4822 }
4823
4824
2/2
✓ Branch 0 taken 236773 times.
✓ Branch 1 taken 174325 times.
411098 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
4825 236773 int keyframe = 0;
4826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 236773 times.
236773 if (current_sample >= sc->sample_count) {
4827 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
4828 return;
4829 }
4830
4831
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])) {
4832 84678 keyframe = 1;
4833
2/2
✓ Branch 0 taken 5584 times.
✓ Branch 1 taken 79094 times.
84678 if (stss_index + 1 < sc->keyframe_count)
4834 5584 stss_index++;
4835
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]) {
4836 keyframe = 1;
4837 if (stps_index + 1 < sc->stps_count)
4838 stps_index++;
4839 }
4840
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) {
4841
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
4842 2 keyframe = 1;
4843
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
4844 4 rap_group_sample = 0;
4845 4 rap_group_index++;
4846 }
4847 }
4848
2/2
✓ Branch 0 taken 4756 times.
✓ Branch 1 taken 232017 times.
236773 if (sc->keyframe_absent
4849
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !sc->stps_count
4850
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !rap_group_present
4851
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)))
4852 3884 keyframe = 1;
4853
2/2
✓ Branch 0 taken 88562 times.
✓ Branch 1 taken 148211 times.
236773 if (keyframe)
4854 88562 distance = 0;
4855
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];
4856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 236773 times.
236773 if (current_offset > INT64_MAX - sample_size) {
4857 av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
4858 current_offset,
4859 sample_size);
4860 return;
4861 }
4862
4863
2/2
✓ Branch 0 taken 236684 times.
✓ Branch 1 taken 89 times.
236773 if (sc->pseudo_stream_id == -1 ||
4864
1/2
✓ Branch 0 taken 236684 times.
✗ Branch 1 not taken.
236684 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
4865 AVIndexEntry *e;
4866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 236773 times.
236773 if (sample_size > 0x3FFFFFFF) {
4867 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
4868 return;
4869 }
4870 236773 e = &sti->index_entries[sti->nb_index_entries++];
4871 236773 e->pos = current_offset;
4872 236773 e->timestamp = current_dts;
4873 236773 e->size = sample_size;
4874 236773 e->min_distance = distance;
4875 236773 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
4876 236773 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
4877 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
4878 current_offset, current_dts, sample_size, distance, keyframe);
4879
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)
4880 10816 ff_rfps_add_frame(mov->fc, st, current_dts);
4881 }
4882
4883 236773 current_offset += sample_size;
4884 236773 stream_size += sample_size;
4885
4886 236773 current_dts += sc->tts_data[stts_index].duration;
4887
4888 236773 distance++;
4889 236773 stts_sample++;
4890 236773 current_sample++;
4891
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) {
4892 236198 stts_sample = 0;
4893 236198 stts_index++;
4894 }
4895 }
4896 }
4897
2/2
✓ Branch 0 taken 532 times.
✓ Branch 1 taken 43 times.
575 if (st->duration > 0)
4898 532 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
4899 } else {
4900 66 unsigned chunk_samples, total = 0;
4901
4902
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)
4903 return;
4904
4905 // compute total chunk count
4906
2/2
✓ Branch 0 taken 723 times.
✓ Branch 1 taken 66 times.
789 for (i = 0; i < sc->stsc_count; i++) {
4907 unsigned count, chunk_count;
4908
4909 723 chunk_samples = sc->stsc_data[i].count;
4910
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 66 times.
723 if (i != sc->stsc_count - 1 &&
4911
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) {
4912 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
4913 return;
4914 }
4915
4916
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 648 times.
723 if (sc->samples_per_frame >= 160) { // gsm
4917 75 count = chunk_samples / sc->samples_per_frame;
4918
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 117 times.
648 } else if (sc->samples_per_frame > 1) {
4919 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
4920 531 count = (chunk_samples+samples-1) / samples;
4921 } else {
4922 117 count = (chunk_samples+1023) / 1024;
4923 }
4924
4925
2/2
✓ Branch 1 taken 657 times.
✓ Branch 2 taken 66 times.
723 if (mov_stsc_index_valid(i, sc->stsc_count))
4926 657 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
4927 else
4928 66 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
4929 723 total += chunk_count * count;
4930 }
4931
4932 66 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
4933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4934 return;
4935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (av_reallocp_array(&sti->index_entries,
4936 66 sti->nb_index_entries + total,
4937 sizeof(*sti->index_entries)) < 0) {
4938 sti->nb_index_entries = 0;
4939 return;
4940 }
4941 66 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
4942
4943 // populate index
4944
2/2
✓ Branch 0 taken 5458 times.
✓ Branch 1 taken 66 times.
5524 for (i = 0; i < sc->chunk_count; i++) {
4945 5458 current_offset = sc->chunk_offsets[i];
4946
2/2
✓ Branch 1 taken 5317 times.
✓ Branch 2 taken 141 times.
5458 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4947
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 4660 times.
5317 i + 1 == sc->stsc_data[stsc_index + 1].first)
4948 657 stsc_index++;
4949 5458 chunk_samples = sc->stsc_data[stsc_index].count;
4950
4951
2/2
✓ Branch 0 taken 164052 times.
✓ Branch 1 taken 5458 times.
169510 while (chunk_samples > 0) {
4952 AVIndexEntry *e;
4953 unsigned size, samples;
4954
4955
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) {
4956 avpriv_request_sample(mov->fc,
4957 "Zero bytes per frame, but %d samples per frame",
4958 sc->samples_per_frame);
4959 return;
4960 }
4961
4962
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 149694 times.
164052 if (sc->samples_per_frame >= 160) { // gsm
4963 14358 samples = sc->samples_per_frame;
4964 14358 size = sc->bytes_per_frame;
4965 } else {
4966
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 140131 times.
149694 if (sc->samples_per_frame > 1) {
4967 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
4968 sc->samples_per_frame, chunk_samples);
4969 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
4970 } else {
4971 140131 samples = FFMIN(1024, chunk_samples);
4972 140131 size = samples * sc->sample_size;
4973 }
4974 }
4975
4976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 164052 times.
164052 if (sti->nb_index_entries >= total) {
4977 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
4978 return;
4979 }
4980
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 164052 times.
164052 if (size > 0x3FFFFFFF) {
4981 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
4982 return;
4983 }
4984 164052 e = &sti->index_entries[sti->nb_index_entries++];
4985 164052 e->pos = current_offset;
4986 164052 e->timestamp = current_dts;
4987 164052 e->size = size;
4988 164052 e->min_distance = 0;
4989 164052 e->flags = AVINDEX_KEYFRAME;
4990 164052 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
4991 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
4992 size, samples);
4993
4994 164052 current_offset += size;
4995 164052 current_dts += samples;
4996 164052 chunk_samples -= samples;
4997 }
4998 }
4999
5000 66 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
5001
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
5002 return;
5003 }
5004
5005
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) {
5006 // Fix index according to edit lists.
5007 641 mov_fix_index(mov, st);
5008 }
5009
5010 // Update start time of the stream.
5011
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) {
5012 69 st->start_time = sti->index_entries[0].timestamp + sc->dts_shift;
5013
1/2
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
69 if (sc->tts_data) {
5014 69 st->start_time += sc->tts_data[0].offset;
5015 }
5016 }
5017
5018 641 mov_estimate_video_delay(mov, st);
5019 }
5020
5021 static int test_same_origin(const char *src, const char *ref) {
5022 char src_proto[64];
5023 char ref_proto[64];
5024 char src_auth[256];
5025 char ref_auth[256];
5026 char src_host[256];
5027 char ref_host[256];
5028 int src_port=-1;
5029 int ref_port=-1;
5030
5031 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
5032 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
5033
5034 if (strlen(src) == 0) {
5035 return -1;
5036 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
5037 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
5038 strlen(src_host) + 1 >= sizeof(src_host) ||
5039 strlen(ref_host) + 1 >= sizeof(ref_host)) {
5040 return 0;
5041 } else if (strcmp(src_proto, ref_proto) ||
5042 strcmp(src_auth, ref_auth) ||
5043 strcmp(src_host, ref_host) ||
5044 src_port != ref_port) {
5045 return 0;
5046 } else
5047 return 1;
5048 }
5049
5050 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
5051 {
5052 /* try relative path, we do not try the absolute because it can leak information about our
5053 system to an attacker */
5054 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
5055 char filename[1025];
5056 const char *src_path;
5057 int i, l;
5058
5059 /* find a source dir */
5060 src_path = strrchr(src, '/');
5061 if (src_path)
5062 src_path++;
5063 else
5064 src_path = src;
5065
5066 /* find a next level down to target */
5067 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
5068 if (ref->path[l] == '/') {
5069 if (i == ref->nlvl_to - 1)
5070 break;
5071 else
5072 i++;
5073 }
5074
5075 /* compose filename if next level down to target was found */
5076 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
5077 memcpy(filename, src, src_path - src);
5078 filename[src_path - src] = 0;
5079
5080 for (i = 1; i < ref->nlvl_from; i++)
5081 av_strlcat(filename, "../", sizeof(filename));
5082
5083 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
5084 if (!c->use_absolute_path) {
5085 int same_origin = test_same_origin(src, filename);
5086
5087 if (!same_origin) {
5088 av_log(c->fc, AV_LOG_ERROR,
5089 "Reference with mismatching origin, %s not tried for security reasons, "
5090 "set demuxer option use_absolute_path to allow it anyway\n",
5091 ref->path);
5092 return AVERROR(ENOENT);
5093 }
5094
5095 if (strstr(ref->path + l + 1, "..") ||
5096 strstr(ref->path + l + 1, ":") ||
5097 (ref->nlvl_from > 1 && same_origin < 0) ||
5098 (filename[0] == '/' && src_path == src))
5099 return AVERROR(ENOENT);
5100 }
5101
5102 if (strlen(filename) + 1 == sizeof(filename))
5103 return AVERROR(ENOENT);
5104 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5105 return 0;
5106 }
5107 } else if (c->use_absolute_path) {
5108 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5109 "this is a possible security issue\n");
5110 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5111 return 0;
5112 } else {
5113 av_log(c->fc, AV_LOG_ERROR,
5114 "Absolute path %s not tried for security reasons, "
5115 "set demuxer option use_absolute_path to allow absolute paths\n",
5116 ref->path);
5117 }
5118
5119 return AVERROR(ENOENT);
5120 }
5121
5122 1363 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5123 {
5124
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1349 times.
1363 if (sc->time_scale <= 0) {
5125 14 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5126 14 sc->time_scale = c->time_scale;
5127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (sc->time_scale <= 0)
5128 sc->time_scale = 1;
5129 }
5130 1363 }
5131
5132 #if CONFIG_IAMFDEC
5133 12 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5134 {
5135 12 const MOVStreamContext *sc = st->priv_data;
5136 12 const IAMFContext *iamf = &sc->iamf->iamf;
5137
5138
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5139 12 const AVStreamGroup *stg = NULL;
5140
5141
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5142
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)
5143 12 stg = c->fc->stream_groups[j];
5144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 av_assert0(stg);
5145
5146
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_streams; j++) {
5147 64 const FFStream *sti = cffstream(st);
5148 64 AVStream *out = stg->streams[j];
5149 64 FFStream *out_sti = ffstream(stg->streams[j]);
5150
5151 64 out->codecpar->bit_rate = 0;
5152
5153
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 52 times.
64 if (out == st)
5154 12 continue;
5155
5156 52 out->time_base = st->time_base;
5157 52 out->start_time = st->start_time;
5158 52 out->duration = st->duration;
5159 52 out->nb_frames = st->nb_frames;
5160 52 out->discard = st->discard;
5161
5162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 av_assert0(!out_sti->index_entries);
5163 52 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (!out_sti->index_entries)
5165 return AVERROR(ENOMEM);
5166
5167 52 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5168 52 out_sti->nb_index_entries = sti->nb_index_entries;
5169 52 out_sti->skip_samples = sti->skip_samples;
5170 52 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5171 }
5172 }
5173
5174 12 return 0;
5175 }
5176 #endif
5177
5178 670 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5179 {
5180
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 ||
5181
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))) ||
5182
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 ||
5183
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)))) {
5184 av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5185 index);
5186 return 1;
5187 }
5188
5189
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) {
5190 av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5191 index);
5192 return 2;
5193 }
5194 670 return 0;
5195 }
5196
5197 627 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5198 {
5199 AVStream *st;
5200 MOVStreamContext *sc;
5201 int ret;
5202
5203 627 st = avformat_new_stream(c->fc, NULL);
5204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (!st) return AVERROR(ENOMEM);
5205 627 st->id = -1;
5206 627 sc = av_mallocz(sizeof(MOVStreamContext));
5207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (!sc) return AVERROR(ENOMEM);
5208
5209 627 st->priv_data = sc;
5210 627 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5211 627 sc->ffindex = st->index;
5212 627 c->trak_index = st->index;
5213 627 sc->tref_flags = 0;
5214 627 sc->tref_id = -1;
5215 627 sc->refcount = 1;
5216
5217
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 627 times.
627 if ((ret = mov_read_default(c, pb, atom)) < 0)
5218 return ret;
5219
5220 627 c->trak_index = -1;
5221
5222 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5223 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5224
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) {
5225 1 sc->stsc_count = 0;
5226 1 av_freep(&sc->stsc_data);
5227 }
5228
5229 627 ret = sanity_checks(c->fc, sc, st->index);
5230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (ret)
5231 return ret > 1 ? AVERROR_INVALIDDATA : 0;
5232
5233 627 fix_timescale(c, sc);
5234
5235 627 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5236
5237 /*
5238 * Advanced edit list support does not work with fragemented MP4s, which
5239 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5240 * In these files, trun atoms may be streamed in.
5241 */
5242
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) {
5243
5244 20 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5245 "MP4. disabling.\n");
5246 20 c->advanced_editlist = 0;
5247 20 c->advanced_editlist_autodisabled = 1;
5248 }
5249
5250 627 mov_build_index(c, st);
5251
5252 #if CONFIG_IAMFDEC
5253
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 615 times.
627 if (sc->iamf) {
5254 12 ret = mov_update_iamf_streams(c, st);
5255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
5256 return ret;
5257 }
5258 #endif
5259
5260
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) {
5261 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5262 if (c->enable_drefs) {
5263 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5264 av_log(c->fc, AV_LOG_ERROR,
5265 "stream %d, error opening alias: path='%s', dir='%s', "
5266 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5267 st->index, dref->path, dref->dir, dref->filename,
5268 dref->volume, dref->nlvl_from, dref->nlvl_to);
5269 } else {
5270 av_log(c->fc, AV_LOG_WARNING,
5271 "Skipped opening external track: "
5272 "stream %d, alias: path='%s', dir='%s', "
5273 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5274 "Set enable_drefs to allow this.\n",
5275 st->index, dref->path, dref->dir, dref->filename,
5276 dref->volume, dref->nlvl_from, dref->nlvl_to);
5277 }
5278 } else {
5279 627 sc->pb = c->fc->pb;
5280 627 sc->pb_is_copied = 1;
5281 }
5282
5283
2/2
✓ Branch 0 taken 325 times.
✓ Branch 1 taken 302 times.
627 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5284
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;
5285
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)
5286 68 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5287 68 sc->h_spacing, sc->v_spacing, INT_MAX);
5288
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 &&
5289
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 &&
5290
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)) {
5291 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5292 (int64_t)st->codecpar->height * sc->width,
5293 (int64_t)st->codecpar->width * sc->height, INT_MAX);
5294 }
5295
5296 #if FF_API_R_FRAME_RATE
5297
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++) {
5298
2/2
✓ Branch 0 taken 152485 times.
✓ Branch 1 taken 2484 times.
154969 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5299 152485 continue;
5300 2484 stts_constant = 0;
5301 }
5302
2/2
✓ Branch 0 taken 291 times.
✓ Branch 1 taken 34 times.
325 if (stts_constant)
5303 291 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5304 291 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5305 #endif
5306 }
5307
5308 #if CONFIG_H261_DECODER || CONFIG_H263_DECODER || CONFIG_MPEG4_DECODER
5309
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 601 times.
627 switch (st->codecpar->codec_id) {
5310 #if CONFIG_H261_DECODER
5311 26 case AV_CODEC_ID_H261:
5312 #endif
5313 #if CONFIG_H263_DECODER
5314 case AV_CODEC_ID_H263:
5315 #endif
5316 #if CONFIG_MPEG4_DECODER
5317 case AV_CODEC_ID_MPEG4:
5318 #endif
5319 26 st->codecpar->width = 0; /* let decoder init width/height */
5320 26 st->codecpar->height= 0;
5321 26 break;
5322 }
5323 #endif
5324
5325 // If the duration of the mp3 packets is not constant, then they could need a parser
5326
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 626 times.
627 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5327
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 && sc->time_scale == st->codecpar->sample_rate) {
5328 1 int stts_constant = 1;
5329
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++) {
5330
1/2
✓ Branch 0 taken 287 times.
✗ Branch 1 not taken.
287 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5331 287 continue;
5332 stts_constant = 0;
5333 }
5334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!stts_constant)
5335 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5336 }
5337 /* Do not need those anymore. */
5338 627 av_freep(&sc->chunk_offsets);
5339 627 av_freep(&sc->sample_sizes);
5340 627 av_freep(&sc->keyframes);
5341 627 av_freep(&sc->stps_data);
5342 627 av_freep(&sc->elst_data);
5343 627 av_freep(&sc->rap_group);
5344 627 av_freep(&sc->sync_group);
5345 627 av_freep(&sc->sgpd_sync);
5346
5347 627 return 0;
5348 }
5349
5350 135 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5351 {
5352 int ret;
5353 135 c->itunes_metadata = 1;
5354 135 ret = mov_read_default(c, pb, atom);
5355 135 c->itunes_metadata = 0;
5356 135 return ret;
5357 }
5358
5359 11 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5360 {
5361 uint32_t count;
5362 uint32_t i;
5363
5364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
5365 return 0;
5366
5367 11 avio_skip(pb, 4);
5368 11 count = avio_rb32(pb);
5369 11 atom.size -= 8;
5370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (count >= UINT_MAX / sizeof(*c->meta_keys)) {
5371 av_log(c->fc, AV_LOG_ERROR,
5372 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5373 return AVERROR_INVALIDDATA;
5374 }
5375
5376 11 c->meta_keys_count = count + 1;
5377 11 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
5378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!c->meta_keys)
5379 return AVERROR(ENOMEM);
5380
5381
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i <= count; ++i) {
5382 58 uint32_t key_size = avio_rb32(pb);
5383 58 uint32_t type = avio_rl32(pb);
5384
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) {
5385 av_log(c->fc, AV_LOG_ERROR,
5386 "The key# %"PRIu32" in meta has invalid size:"
5387 "%"PRIu32"\n", i, key_size);
5388 return AVERROR_INVALIDDATA;
5389 }
5390 58 atom.size -= key_size;
5391 58 key_size -= 8;
5392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (type != MKTAG('m','d','t','a')) {
5393 avio_skip(pb, key_size);
5394 continue;
5395 }
5396 58 c->meta_keys[i] = av_mallocz(key_size + 1);
5397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!c->meta_keys[i])
5398 return AVERROR(ENOMEM);
5399 58 avio_read(pb, c->meta_keys[i], key_size);
5400 }
5401
5402 11 return 0;
5403 }
5404
5405 65 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5406 {
5407 65 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5408 65 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5409 int i;
5410 65 int ret = 0;
5411 AVStream *st;
5412 MOVStreamContext *sc;
5413
5414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (c->fc->nb_streams < 1)
5415 return 0;
5416 65 st = c->fc->streams[c->fc->nb_streams-1];
5417 65 sc = st->priv_data;
5418
5419
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 65 times.
260 for (i = 0; i < 3; i++) {
5420 uint8_t **p;
5421 uint32_t len, tag;
5422
5423
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 195 times.
195 if (end - avio_tell(pb) <= 12)
5424 break;
5425
5426 195 len = avio_rb32(pb);
5427 195 tag = avio_rl32(pb);
5428 195 avio_skip(pb, 4); // flags
5429
5430
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))
5431 break;
5432 195 len -= 12;
5433
5434
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 130 times.
195 if (tag == MKTAG('m', 'e', 'a', 'n'))
5435 65 p = &mean;
5436
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 65 times.
130 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5437 65 p = &key;
5438
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) {
5439 65 avio_skip(pb, 4);
5440 65 len -= 4;
5441 65 p = &val;
5442 } else
5443 break;
5444
5445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (*p)
5446 break;
5447
5448 195 *p = av_malloc(len + 1);
5449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*p) {
5450 ret = AVERROR(ENOMEM);
5451 break;
5452 }
5453 195 ret = ffio_read_size(pb, *p, len);
5454
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (ret < 0) {
5455 av_freep(p);
5456 break;
5457 }
5458 195 (*p)[len] = 0;
5459 }
5460
5461
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) {
5462
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 32 times.
65 if (strcmp(key, "iTunSMPB") == 0) {
5463 int priming, remainder, samples;
5464
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
5465
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)
5466 33 sc->start_pad = priming;
5467 }
5468 }
5469
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 10 times.
120 if (strcmp(key, "cdec") != 0) {
5470 55 av_dict_set(&c->fc->metadata, key, val,
5471 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5472 55 key = val = NULL;
5473 }
5474 } else {
5475 av_log(c->fc, AV_LOG_VERBOSE,
5476 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5477 }
5478
5479 65 avio_seek(pb, end, SEEK_SET);
5480 65 av_freep(&key);
5481 65 av_freep(&val);
5482 65 av_freep(&mean);
5483 65 return ret;
5484 }
5485
5486 43 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5487 {
5488 MOVStreamContext *sc;
5489 AVStream *st;
5490
5491 43 st = avformat_new_stream(c->fc, NULL);
5492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st)
5493 return AVERROR(ENOMEM);
5494 43 sc = av_mallocz(sizeof(MOVStreamContext));
5495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc)
5496 goto fail;
5497
5498 43 item->st = st;
5499 43 st->id = item->item_id;
5500 43 st->priv_data = sc;
5501 43 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5502 43 st->codecpar->codec_id = mov_codec_id(st, item->type);
5503 43 sc->id = st->id;
5504 43 sc->ffindex = st->index;
5505 43 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5506 43 st->time_base.num = st->time_base.den = 1;
5507 43 st->nb_frames = 1;
5508 43 sc->time_scale = 1;
5509 43 sc->pb = c->fc->pb;
5510 43 sc->pb_is_copied = 1;
5511 43 sc->refcount = 1;
5512
5513
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (item->name)
5514 43 av_dict_set(&st->metadata, "title", item->name, 0);
5515
5516 // Populate the necessary fields used by mov_build_index.
5517 43 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->stsc_data)
5519 goto fail;
5520 43 sc->stsc_count = 1;
5521 43 sc->stsc_data[0].first = 1;
5522 43 sc->stsc_data[0].count = 1;
5523 43 sc->stsc_data[0].id = 1;
5524 43 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->chunk_offsets)
5526 goto fail;
5527 43 sc->chunk_count = 1;
5528 43 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->stts_data)
5530 goto fail;
5531 43 sc->stts_count = 1;
5532 43 sc->stts_data[0].count = 1;
5533 // Not used for still images. But needed by mov_build_index.
5534 43 sc->stts_data[0].duration = 0;
5535
5536 43 return 0;
5537 fail:
5538 mov_free_stream_context(c->fc, st);
5539 ff_remove_stream(c->fc, st);
5540 item->st = NULL;
5541
5542 return AVERROR(ENOMEM);
5543 }
5544
5545 157 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5546 {
5547
1/2
✓ Branch 0 taken 457 times.
✗ Branch 1 not taken.
457 while (atom.size > 8) {
5548 uint32_t tag;
5549
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 457 times.
457 if (avio_feof(pb))
5550 return AVERROR_EOF;
5551 457 tag = avio_rl32(pb);
5552 457 atom.size -= 4;
5553
2/2
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 300 times.
457 if (tag == MKTAG('h','d','l','r')) {
5554 157 avio_seek(pb, -8, SEEK_CUR);
5555 157 atom.size += 8;
5556 157 return mov_read_default(c, pb, atom);
5557 }
5558 }
5559 return 0;
5560 }
5561
5562 // return 1 when matrix is identity, 0 otherwise
5563 #define IS_MATRIX_IDENT(matrix) \
5564 ( (matrix)[0][0] == (1 << 16) && \
5565 (matrix)[1][1] == (1 << 16) && \
5566 (matrix)[2][2] == (1 << 30) && \
5567 !(matrix)[0][1] && !(matrix)[0][2] && \
5568 !(matrix)[1][0] && !(matrix)[1][2] && \
5569 !(matrix)[2][0] && !(matrix)[2][1])
5570
5571 627 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5572 {
5573 int i, j, e;
5574 int width;
5575 int height;
5576 int display_matrix[3][3];
5577 627 int res_display_matrix[3][3] = { { 0 } };
5578 AVStream *st;
5579 MOVStreamContext *sc;
5580 int version;
5581 int flags;
5582
5583
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (c->fc->nb_streams < 1)
5584 return 0;
5585 627 st = c->fc->streams[c->fc->nb_streams-1];
5586 627 sc = st->priv_data;
5587
5588 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5589 // avoids corrupting AVStreams mapped to an earlier tkhd.
5590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if (st->id != -1)
5591 return AVERROR_INVALIDDATA;
5592
5593 627 version = avio_r8(pb);
5594 627 flags = avio_rb24(pb);
5595 627 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5596
5597
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 614 times.
627 if (version == 1) {
5598 13 avio_rb64(pb);
5599 13 avio_rb64(pb);
5600 } else {
5601 614 avio_rb32(pb); /* creation time */
5602 614 avio_rb32(pb); /* modification time */
5603 }
5604 627 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5605 627 sc->id = st->id;
5606 627 avio_rb32(pb); /* reserved */
5607
5608 /* highlevel (considering edits) duration in movie timebase */
5609
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 614 times.
627 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5610 627 avio_rb32(pb); /* reserved */
5611 627 avio_rb32(pb); /* reserved */
5612
5613 627 avio_rb16(pb); /* layer */
5614 627 avio_rb16(pb); /* alternate group */
5615 627 avio_rb16(pb); /* volume */
5616 627 avio_rb16(pb); /* reserved */
5617
5618 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
5619 // they're kept in fixed point format through all calculations
5620 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
5621 // side data, but the scale factor is not needed to calculate aspect ratio
5622
2/2
✓ Branch 0 taken 1881 times.
✓ Branch 1 taken 627 times.
2508 for (i = 0; i < 3; i++) {
5623 1881 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
5624 1881 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
5625 1881 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
5626 }
5627
5628 627 width = avio_rb32(pb); // 16.16 fixed point track width
5629 627 height = avio_rb32(pb); // 16.16 fixed point track height
5630 627 sc->width = width >> 16;
5631 627 sc->height = height >> 16;
5632
5633 // apply the moov display matrix (after the tkhd one)
5634
2/2
✓ Branch 0 taken 1881 times.
✓ Branch 1 taken 627 times.
2508 for (i = 0; i < 3; i++) {
5635 1881 const int sh[3] = { 16, 16, 30 };
5636
2/2
✓ Branch 0 taken 5643 times.
✓ Branch 1 taken 1881 times.
7524 for (j = 0; j < 3; j++) {
5637
2/2
✓ Branch 0 taken 16929 times.
✓ Branch 1 taken 5643 times.
22572 for (e = 0; e < 3; e++) {
5638 16929 res_display_matrix[i][j] +=
5639 16929 ((int64_t) display_matrix[i][e] *
5640 16929 c->movie_display_matrix[e][j]) >> sh[e];
5641 }
5642 }
5643 }
5644
5645 // save the matrix when it is not the default identity
5646
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)) {
5647 9 av_freep(&sc->display_matrix);
5648 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
5649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
5650 return AVERROR(ENOMEM);
5651
5652
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
5653
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
5654 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
5655 }
5656
5657 // transform the display width/height according to the matrix
5658 // to keep the same scale, use [width height 1<<16]
5659
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) {
5660 double disp_transform[2];
5661
5662
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
5663 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
5664 16 sc->display_matrix[3 + i]);
5665
5666
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 &&
5667
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) &&
5668
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
5669 3 st->sample_aspect_ratio = av_d2q(
5670 3 disp_transform[0] / disp_transform[1],
5671 INT_MAX);
5672 }
5673 627 return 0;
5674 }
5675
5676 499 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5677 {
5678 499 MOVFragment *frag = &c->fragment;
5679 499 MOVTrackExt *trex = NULL;
5680 int flags, track_id, i;
5681 MOVFragmentStreamInfo * frag_stream_info;
5682
5683 499 avio_r8(pb); /* version */
5684 499 flags = avio_rb24(pb);
5685
5686 499 track_id = avio_rb32(pb);
5687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!track_id)
5688 return AVERROR_INVALIDDATA;
5689
1/2
✓ Branch 0 taken 558 times.
✗ Branch 1 not taken.
558 for (i = 0; i < c->trex_count; i++)
5690
2/2
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 59 times.
558 if (c->trex_data[i].track_id == track_id) {
5691 499 trex = &c->trex_data[i];
5692 499 break;
5693 }
5694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!trex) {
5695 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
5696 return 0;
5697 }
5698 499 c->fragment.found_tfhd = 1;
5699 499 frag->track_id = track_id;
5700 499 set_frag_stream(&c->frag_index, track_id);
5701
5702 998 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
5703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
998 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
5704
2/2
✓ Branch 0 taken 426 times.
✓ Branch 1 taken 73 times.
499 frag->moof_offset : frag->implicit_offset;
5705
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;
5706
5707 998 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
5708
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 435 times.
499 avio_rb32(pb) : trex->duration;
5709 998 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
5710
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 440 times.
499 avio_rb32(pb) : trex->size;
5711 998 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
5712
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 366 times.
499 avio_rb32(pb) : trex->flags;
5713 499 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
5714
5715 499 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5716
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info) {
5717 499 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
5718 499 frag_stream_info->stsd_id = frag->stsd_id;
5719 }
5720 499 return 0;
5721 }
5722
5723 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5724 {
5725 unsigned i, num;
5726 void *new_tracks;
5727
5728 2 num = atom.size / 4;
5729
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
5730 return AVERROR(ENOMEM);
5731
5732 2 av_free(c->chapter_tracks);
5733 2 c->chapter_tracks = new_tracks;
5734 2 c->nb_chapter_tracks = num;
5735
5736
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++)
5737 2 c->chapter_tracks[i] = avio_rb32(pb);
5738
5739 2 c->nb_chapter_tracks = i;
5740
5741 2 return 0;
5742 }
5743
5744 28 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5745 {
5746 MOVTrackExt *trex;
5747 int err;
5748
5749
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))
5750 return AVERROR_INVALIDDATA;
5751
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
5752 sizeof(*c->trex_data))) < 0) {
5753 c->trex_count = 0;
5754 return err;
5755 }
5756
5757 28 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
5758
5759 28 trex = &c->trex_data[c->trex_count++];
5760 28 avio_r8(pb); /* version */
5761 28 avio_rb24(pb); /* flags */
5762 28 trex->track_id = avio_rb32(pb);
5763 28 trex->stsd_id = avio_rb32(pb);
5764 28 trex->duration = avio_rb32(pb);
5765 28 trex->size = avio_rb32(pb);
5766 28 trex->flags = avio_rb32(pb);
5767 28 return 0;
5768 }
5769
5770 426 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5771 {
5772 426 MOVFragment *frag = &c->fragment;
5773 426 AVStream *st = NULL;
5774 MOVStreamContext *sc;
5775 int version, i;
5776 MOVFragmentStreamInfo * frag_stream_info;
5777 int64_t base_media_decode_time;
5778
5779
1/2
✓ Branch 0 taken 453 times.
✗ Branch 1 not taken.
453 for (i = 0; i < c->fc->nb_streams; i++) {
5780 453 sc = c->fc->streams[i]->priv_data;
5781
2/2
✓ Branch 0 taken 426 times.
✓ Branch 1 taken 27 times.
453 if (sc->id == frag->track_id) {
5782 426 st = c->fc->streams[i];
5783 426 break;
5784 }
5785 }
5786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 426 times.
426 if (!st) {
5787 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5788 return 0;
5789 }
5790 426 sc = st->priv_data;
5791
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)
5792 return 0;
5793 426 version = avio_r8(pb);
5794 426 avio_rb24(pb); /* flags */
5795
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 370 times.
426 if (version) {
5796 56 base_media_decode_time = avio_rb64(pb);
5797 } else {
5798 370 base_media_decode_time = avio_rb32(pb);
5799 }
5800
5801 426 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5802
1/2
✓ Branch 0 taken 426 times.
✗ Branch 1 not taken.
426 if (frag_stream_info)
5803 426 frag_stream_info->tfdt_dts = base_media_decode_time;
5804 426 sc->track_end = base_media_decode_time;
5805
5806 426 return 0;
5807 }
5808
5809 499 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5810 {
5811 499 MOVFragment *frag = &c->fragment;
5812 499 AVStream *st = NULL;
5813 499 FFStream *sti = NULL;
5814 MOVStreamContext *sc;
5815 MOVTimeToSample *tts_data;
5816 uint64_t offset;
5817 499 int64_t dts, pts = AV_NOPTS_VALUE;
5818 499 int data_offset = 0;
5819 499 unsigned entries, first_sample_flags = frag->flags;
5820 int flags, distance, i;
5821 499 int64_t prev_dts = AV_NOPTS_VALUE;
5822 499 int next_frag_index = -1, index_entry_pos;
5823 size_t requested_size;
5824 size_t old_allocated_size;
5825 AVIndexEntry *new_entries;
5826 MOVFragmentStreamInfo * frag_stream_info;
5827
5828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!frag->found_tfhd) {
5829 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
5830 return AVERROR_INVALIDDATA;
5831 }
5832
5833
1/2
✓ Branch 0 taken 558 times.
✗ Branch 1 not taken.
558 for (i = 0; i < c->fc->nb_streams; i++) {
5834 558 sc = c->fc->streams[i]->priv_data;
5835
2/2
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 59 times.
558 if (sc->id == frag->track_id) {
5836 499 st = c->fc->streams[i];
5837 499 sti = ffstream(st);
5838 499 break;
5839 }
5840 }
5841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!st) {
5842 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5843 return 0;
5844 }
5845 499 sc = st->priv_data;
5846
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)
5847 return 0;
5848
5849 // Find the next frag_index index that has a valid index_entry for
5850 // the current track_id.
5851 //
5852 // A valid index_entry means the trun for the fragment was read
5853 // and it's samples are in index_entries at the given position.
5854 // New index entries will be inserted before the index_entry found.
5855 499 index_entry_pos = sti->nb_index_entries;
5856
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++) {
5857 1634 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
5858
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) {
5859 next_frag_index = i;
5860 index_entry_pos = frag_stream_info->index_entry;
5861 break;
5862 }
5863 }
5864
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 av_assert0(index_entry_pos <= sti->nb_index_entries);
5865
5866 499 avio_r8(pb); /* version */
5867 499 flags = avio_rb24(pb);
5868 499 entries = avio_rb32(pb);
5869 499 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
5870
5871
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))
5872 return AVERROR_INVALIDDATA;
5873
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
5874
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);
5875
5876 499 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5877
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info) {
5878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
5879 dts = frag_stream_info->next_trun_dts - sc->time_offset;
5880
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 496 times.
499 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5881
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
5882 3 pts = frag_stream_info->first_tfra_pts;
5883 3 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5884 ", using it for pts\n", pts);
5885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5886 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
5887 dts = frag_stream_info->first_tfra_pts;
5888 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5889 ", using it for dts\n", pts);
5890 } else {
5891 496 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
5892 496 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
5893
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;
5894
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;
5895
5896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 if (fallback_sidx) {
5897 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
5898 }
5899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 if (fallback_tfdt) {
5900 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
5901 }
5902
5903
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) {
5904 423 dts = frag_stream_info->tfdt_dts - sc->time_offset;
5905 423 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
5906 ", using it for dts\n", dts);
5907
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) {
5908 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
5909 // pts = frag_stream_info->sidx_pts;
5910 dts = frag_stream_info->sidx_pts;
5911 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
5912 ", using it for dts\n", frag_stream_info->sidx_pts);
5913 } else {
5914 73 dts = sc->track_end - sc->time_offset;
5915 73 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5916 ", using it for dts\n", dts);
5917 }
5918 }
5919 } else {
5920 dts = sc->track_end - sc->time_offset;
5921 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5922 ", using it for dts\n", dts);
5923 }
5924 499 offset = frag->base_data_offset + data_offset;
5925 499 distance = 0;
5926 499 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
5927
5928 // realloc space for new index entries
5929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
5930 entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
5931 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
5932 }
5933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (entries == 0)
5934 return 0;
5935
5936 499 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
5937 499 new_entries = av_fast_realloc(sti->index_entries,
5938 &sti->index_entries_allocated_size,
5939 requested_size);
5940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!new_entries)
5941 return AVERROR(ENOMEM);
5942 499 sti->index_entries= new_entries;
5943
5944 499 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
5945 499 old_allocated_size = sc->tts_allocated_size;
5946 499 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
5947 requested_size);
5948
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!tts_data)
5949 return AVERROR(ENOMEM);
5950 499 sc->tts_data = tts_data;
5951
5952 // In case there were samples without time to sample entries, ensure they get
5953 // zero valued entries. This ensures clips which mix boxes with and
5954 // without time to sample entries don't pickup uninitialized data.
5955 499 memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0,
5956 499 sc->tts_allocated_size - old_allocated_size);
5957
5958
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (index_entry_pos < sti->nb_index_entries) {
5959 // Make hole in index_entries and tts_data for new samples
5960 memmove(sti->index_entries + index_entry_pos + entries,
5961 sti->index_entries + index_entry_pos,
5962 sizeof(*sti->index_entries) *
5963 (sti->nb_index_entries - index_entry_pos));
5964 memmove(sc->tts_data + index_entry_pos + entries,
5965 sc->tts_data + index_entry_pos,
5966 sizeof(*sc->tts_data) * (sc->tts_count - index_entry_pos));
5967 if (index_entry_pos < sc->current_sample) {
5968 sc->current_sample += entries;
5969 }
5970 }
5971
5972 499 sti->nb_index_entries += entries;
5973 499 sc->tts_count = sti->nb_index_entries;
5974 499 sc->stts_count = sti->nb_index_entries;
5975
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 113 times.
499 if (flags & MOV_TRUN_SAMPLE_CTS)
5976 386 sc->ctts_count = sti->nb_index_entries;
5977
5978 // Record the index_entry position in frag_index of this fragment
5979
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info) {
5980 499 frag_stream_info->index_entry = index_entry_pos;
5981
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info->index_base < 0)
5982 499 frag_stream_info->index_base = index_entry_pos;
5983 }
5984
5985
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 27 times.
499 if (index_entry_pos > 0)
5986 472 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
5987
5988
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++) {
5989 8707 unsigned sample_size = frag->size;
5990
2/2
✓ Branch 0 taken 8208 times.
✓ Branch 1 taken 499 times.
8707 int sample_flags = i ? frag->flags : first_sample_flags;
5991 8707 unsigned sample_duration = frag->duration;
5992 8707 unsigned ctts_duration = 0;
5993 8707 int keyframe = 0;
5994 8707 int index_entry_flags = 0;
5995
5996
2/2
✓ Branch 0 taken 1674 times.
✓ Branch 1 taken 7033 times.
8707 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
5997
2/2
✓ Branch 0 taken 8649 times.
✓ Branch 1 taken 58 times.
8707 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
5998
2/2
✓ Branch 0 taken 981 times.
✓ Branch 1 taken 7726 times.
8707 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
5999
2/2
✓ Branch 0 taken 6576 times.
✓ Branch 1 taken 2131 times.
8707 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
6000
6001 8707 mov_update_dts_shift(sc, ctts_duration, c->fc);
6002
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8704 times.
8707 if (pts != AV_NOPTS_VALUE) {
6003 3 dts = pts - sc->dts_shift;
6004
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (flags & MOV_TRUN_SAMPLE_CTS) {
6005 dts -= ctts_duration;
6006 } else {
6007 3 dts -= sc->time_offset;
6008 }
6009 3 av_log(c->fc, AV_LOG_DEBUG,
6010 "pts %"PRId64" calculated dts %"PRId64
6011 " sc->dts_shift %d ctts.duration %d"
6012 " sc->time_offset %"PRId64
6013 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
6014 pts, dts,
6015 sc->dts_shift, ctts_duration,
6016 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
6017 3 pts = AV_NOPTS_VALUE;
6018 }
6019
6020 8707 keyframe =
6021 8707 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
6022 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
6023
2/2
✓ Branch 0 taken 646 times.
✓ Branch 1 taken 8061 times.
8707 if (keyframe) {
6024 646 distance = 0;
6025 646 index_entry_flags |= AVINDEX_KEYFRAME;
6026 }
6027 // Fragments can overlap in time. Discard overlapping frames after
6028 // decoding.
6029
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8683 times.
8707 if (prev_dts >= dts)
6030 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
6031
6032 8707 sti->index_entries[index_entry_pos].pos = offset;
6033 8707 sti->index_entries[index_entry_pos].timestamp = dts;
6034 8707 sti->index_entries[index_entry_pos].size = sample_size;
6035 8707 sti->index_entries[index_entry_pos].min_distance = distance;
6036 8707 sti->index_entries[index_entry_pos].flags = index_entry_flags;
6037
6038 8707 sc->tts_data[index_entry_pos].count = 1;
6039 8707 sc->tts_data[index_entry_pos].offset = ctts_duration;
6040 8707 sc->tts_data[index_entry_pos].duration = sample_duration;
6041 8707 index_entry_pos++;
6042
6043 8707 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
6044 "size %u, distance %d, keyframe %d\n", st->index,
6045 index_entry_pos, offset, dts, sample_size, distance, keyframe);
6046 8707 distance++;
6047
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8707 times.
8707 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
6048 return AVERROR_INVALIDDATA;
6049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8707 times.
8707 if (!sample_size)
6050 return AVERROR_INVALIDDATA;
6051 8707 dts += sample_duration;
6052 8707 offset += sample_size;
6053 8707 sc->data_size += sample_size;
6054
6055
1/2
✓ Branch 0 taken 8707 times.
✗ Branch 1 not taken.
8707 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
6056
1/2
✓ Branch 0 taken 8707 times.
✗ Branch 1 not taken.
8707 1 <= INT_MAX - sc->nb_frames_for_fps
6057 ) {
6058 8707 sc->duration_for_fps += sample_duration;
6059 8707 sc->nb_frames_for_fps ++;
6060 }
6061 }
6062
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info)
6063 499 frag_stream_info->next_trun_dts = dts + sc->time_offset;
6064
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (i < entries) {
6065 // EOF found before reading all entries. Fix the hole this would
6066 // leave in index_entries and tts_data
6067 int gap = entries - i;
6068 memmove(sti->index_entries + index_entry_pos,
6069 sti->index_entries + index_entry_pos + gap,
6070 sizeof(*sti->index_entries) *
6071 (sti->nb_index_entries - (index_entry_pos + gap)));
6072 memmove(sc->tts_data + index_entry_pos,
6073 sc->tts_data + index_entry_pos + gap,
6074 sizeof(*sc->tts_data) *
6075 (sc->tts_count - (index_entry_pos + gap)));
6076
6077 sti->nb_index_entries -= gap;
6078 sc->tts_count -= gap;
6079 if (index_entry_pos < sc->current_sample) {
6080 sc->current_sample -= gap;
6081 }
6082 entries = i;
6083 }
6084
6085 // The end of this new fragment may overlap in time with the start
6086 // of the next fragment in index_entries. Mark the samples in the next
6087 // fragment that overlap with AVINDEX_DISCARD_FRAME
6088 499 prev_dts = AV_NOPTS_VALUE;
6089
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (index_entry_pos > 0)
6090 499 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
6092 if (prev_dts < sti->index_entries[i].timestamp)
6093 break;
6094 sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6095 }
6096
6097 // If a hole was created to insert the new index_entries into,
6098 // the index_entry recorded for all subsequent moof must
6099 // be incremented by the number of entries inserted.
6100 499 fix_frag_index_entries(&c->frag_index, next_frag_index,
6101 499 frag->track_id, entries);
6102
6103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (pb->eof_reached) {
6104 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6105 return AVERROR_EOF;
6106 }
6107
6108 499 frag->implicit_offset = offset;
6109
6110 499 sc->track_end = dts + sc->time_offset;
6111
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 383 times.
499 if (st->duration < sc->track_end)
6112 116 st->duration = sc->track_end;
6113
6114 499 return 0;
6115 }
6116
6117 46 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6118 {
6119 46 int64_t stream_size = avio_size(pb);
6120 46 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6121 uint8_t version, is_complete;
6122 int64_t offadd;
6123 unsigned i, j, track_id, item_count;
6124 46 AVStream *st = NULL;
6125 46 AVStream *ref_st = NULL;
6126 46 MOVStreamContext *sc, *ref_sc = NULL;
6127 AVRational timescale;
6128
6129 46 version = avio_r8(pb);
6130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (version > 1) {
6131 avpriv_request_sample(c->fc, "sidx version %u", version);
6132 return 0;
6133 }
6134
6135 46 avio_rb24(pb); // flags
6136
6137 46 track_id = avio_rb32(pb); // Reference ID
6138
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 for (i = 0; i < c->fc->nb_streams; i++) {
6139 46 sc = c->fc->streams[i]->priv_data;
6140
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 if (sc->id == track_id) {
6141 46 st = c->fc->streams[i];
6142 46 break;
6143 }
6144 }
6145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!st) {
6146 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6147 return 0;
6148 }
6149
6150 46 sc = st->priv_data;
6151
6152 46 timescale = av_make_q(1, avio_rb32(pb));
6153
6154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (timescale.den <= 0) {
6155 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6156 return AVERROR_INVALIDDATA;
6157 }
6158
6159
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1 times.
46 if (version == 0) {
6160 45 pts = avio_rb32(pb);
6161 45 offadd= avio_rb32(pb);
6162 } else {
6163 1 pts = avio_rb64(pb);
6164 1 offadd= avio_rb64(pb);
6165 }
6166
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6167 return AVERROR_INVALIDDATA;
6168
6169 46 offset += (uint64_t)offadd;
6170
6171 46 avio_rb16(pb); // reserved
6172
6173 46 item_count = avio_rb16(pb);
6174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (item_count == 0)
6175 return AVERROR_INVALIDDATA;
6176
6177
2/2
✓ Branch 0 taken 372 times.
✓ Branch 1 taken 46 times.
418 for (i = 0; i < item_count; i++) {
6178 int index;
6179 MOVFragmentStreamInfo * frag_stream_info;
6180 372 uint32_t size = avio_rb32(pb);
6181 372 uint32_t duration = avio_rb32(pb);
6182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
372 if (size & 0x80000000) {
6183 avpriv_request_sample(c->fc, "sidx reference_type 1");
6184 return AVERROR_PATCHWELCOME;
6185 }
6186 372 avio_rb32(pb); // sap_flags
6187 372 timestamp = av_rescale_q(pts, timescale, st->time_base);
6188
6189 372 index = update_frag_index(c, offset);
6190 372 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6191
1/2
✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
372 if (frag_stream_info)
6192 372 frag_stream_info->sidx_pts = timestamp;
6193
6194
1/2
✓ Branch 1 taken 372 times.
✗ Branch 2 not taken.
372 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6195
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 372 times.
372 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6196 )
6197 return AVERROR_INVALIDDATA;
6198 372 offset += size;
6199 372 pts += duration;
6200 }
6201
6202 46 st->duration = sc->track_end = pts;
6203
6204 46 sc->has_sidx = 1;
6205
6206 // See if the remaining bytes are just an mfra which we can ignore.
6207 46 is_complete = offset == stream_size;
6208
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 ) {
6209 int64_t ret;
6210 38 int64_t original_pos = avio_tell(pb);
6211
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
38 if (!c->have_read_mfra_size) {
6212
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6213 return ret;
6214 3 c->mfra_size = avio_rb32(pb);
6215 3 c->have_read_mfra_size = 1;
6216
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6217 return ret;
6218 }
6219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (offset == stream_size - c->mfra_size)
6220 is_complete = 1;
6221 }
6222
6223
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 39 times.
46 if (is_complete) {
6224 // Find first entry in fragment index that came from an sidx.
6225 // This will pretty much always be the first entry.
6226
2/2
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 7 times.
378 for (i = 0; i < c->frag_index.nb_items; i++) {
6227 371 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6228
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++) {
6229 MOVFragmentStreamInfo * si;
6230 7 si = &item->stream_info[j];
6231
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (si->sidx_pts != AV_NOPTS_VALUE) {
6232 7 ref_st = c->fc->streams[j];
6233 7 ref_sc = ref_st->priv_data;
6234 7 break;
6235 }
6236 }
6237 }
6238
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++) {
6239 7 st = c->fc->streams[i];
6240 7 sc = st->priv_data;
6241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sc->has_sidx) {
6242 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6243 }
6244 }
6245
6246
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (offadd == 0)
6247 7 c->frag_index.complete = 1;
6248 }
6249
6250 46 return 0;
6251 }
6252
6253 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6254 /* like the files created with Adobe Premiere 5.0, for samples see */
6255 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6256 276 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6257 {
6258 int err;
6259
6260
1/2
✓ Branch 0 taken 276 times.
✗ Branch 1 not taken.
276 if (atom.size < 8)
6261 276 return 0; /* continue */
6262 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6263 avio_skip(pb, atom.size - 4);
6264 return 0;
6265 }
6266 atom.type = avio_rl32(pb);
6267 atom.size -= 8;
6268 if (atom.type != MKTAG('m','d','a','t')) {
6269 avio_skip(pb, atom.size);
6270 return 0;
6271 }
6272 err = mov_read_mdat(c, pb, atom);
6273 return err;
6274 }
6275
6276 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6277 {
6278 #if CONFIG_ZLIB
6279 FFIOContext ctx;
6280 uint8_t *cmov_data;
6281 uint8_t *moov_data; /* uncompressed data */
6282 long cmov_len, moov_len;
6283 3 int ret = -1;
6284
6285 3 avio_rb32(pb); /* dcom atom */
6286
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6287 return AVERROR_INVALIDDATA;
6288
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6289 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6290 return AVERROR_INVALIDDATA;
6291 }
6292 3 avio_rb32(pb); /* cmvd atom */
6293
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6294 return AVERROR_INVALIDDATA;
6295 3 moov_len = avio_rb32(pb); /* uncompressed size */
6296 3 cmov_len = atom.size - 6 * 4;
6297
6298 3 cmov_data = av_malloc(cmov_len);
6299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6300 return AVERROR(ENOMEM);
6301 3 moov_data = av_malloc(moov_len);
6302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6303 av_free(cmov_data);
6304 return AVERROR(ENOMEM);
6305 }
6306 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6308 goto free_and_return;
6309
6310 3 ret = AVERROR_INVALIDDATA;
6311
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)
6312 goto free_and_return;
6313 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6314 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6315 3 atom.type = MKTAG('m','o','o','v');
6316 3 atom.size = moov_len;
6317 3 ret = mov_read_default(c, &ctx.pub, atom);
6318 3 free_and_return:
6319 3 av_free(moov_data);
6320 3 av_free(cmov_data);
6321 3 return ret;
6322 #else
6323 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6324 return AVERROR(ENOSYS);
6325 #endif
6326 }
6327
6328 /* edit list atom */
6329 457 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6330 {
6331 MOVStreamContext *sc;
6332 int i, edit_count, version;
6333 int64_t elst_entry_size;
6334
6335
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)
6336 return 0;
6337 457 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6338
6339 457 version = avio_r8(pb); /* version */
6340 457 avio_rb24(pb); /* flags */
6341 457 edit_count = avio_rb32(pb); /* entries */
6342 457 atom.size -= 8;
6343
6344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 457 times.
457 elst_entry_size = version == 1 ? 20 : 12;
6345
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 456 times.
457 if (atom.size != edit_count * elst_entry_size) {
6346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6347 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6348 edit_count, atom.size + 8);
6349 return AVERROR_INVALIDDATA;
6350 } else {
6351 1 edit_count = atom.size / elst_entry_size;
6352
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6353 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6354 }
6355 }
6356 }
6357
6358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 457 times.
457 if (!edit_count)
6359 return 0;
6360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 457 times.
457 if (sc->elst_data)
6361 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6362 457 av_free(sc->elst_data);
6363 457 sc->elst_count = 0;
6364 457 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 457 times.
457 if (!sc->elst_data)
6366 return AVERROR(ENOMEM);
6367
6368 457 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6369
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++) {
6370 486 MOVElst *e = &sc->elst_data[i];
6371
6372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486 times.
486 if (version == 1) {
6373 e->duration = avio_rb64(pb);
6374 e->time = avio_rb64(pb);
6375 atom.size -= 16;
6376 } else {
6377 486 e->duration = avio_rb32(pb); /* segment duration */
6378 486 e->time = (int32_t)avio_rb32(pb); /* media time */
6379 486 atom.size -= 8;
6380 }
6381 486 e->rate = avio_rb32(pb) / 65536.0;
6382 486 atom.size -= 4;
6383 486 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6384 486 e->duration, e->time, e->rate);
6385
6386
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 &&
6387 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6388 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6389 c->fc->nb_streams-1, i, e->time);
6390 return AVERROR_INVALIDDATA;
6391 }
6392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486 times.
486 if (e->duration < 0) {
6393 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list duration=%"PRId64"\n",
6394 c->fc->nb_streams-1, i, e->duration);
6395 return AVERROR_INVALIDDATA;
6396 }
6397 }
6398 457 sc->elst_count = i;
6399
6400 457 return 0;
6401 }
6402
6403 18 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6404 {
6405 MOVStreamContext *sc;
6406
6407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->fc->nb_streams < 1)
6408 return AVERROR_INVALIDDATA;
6409 18 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6410 18 sc->timecode_track = avio_rb32(pb);
6411 18 return 0;
6412 }
6413
6414 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6415 {
6416 AVStream *st;
6417 int version, color_range, color_primaries, color_trc, color_space;
6418
6419 if (c->fc->nb_streams < 1)
6420 return 0;
6421 st = c->fc->streams[c->fc->nb_streams - 1];
6422
6423 if (atom.size < 5) {
6424 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6425 return AVERROR_INVALIDDATA;
6426 }
6427
6428 version = avio_r8(pb);
6429 if (version != 1) {
6430 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6431 return 0;
6432 }
6433 avio_skip(pb, 3); /* flags */
6434
6435 avio_skip(pb, 2); /* profile + level */
6436 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6437 color_primaries = avio_r8(pb);
6438 color_trc = avio_r8(pb);
6439 color_space = avio_r8(pb);
6440 if (avio_rb16(pb)) /* codecIntializationDataSize */
6441 return AVERROR_INVALIDDATA;
6442
6443 if (!av_color_primaries_name(color_primaries))
6444 color_primaries = AVCOL_PRI_UNSPECIFIED;
6445 if (!av_color_transfer_name(color_trc))
6446 color_trc = AVCOL_TRC_UNSPECIFIED;
6447 if (!av_color_space_name(color_space))
6448 color_space = AVCOL_SPC_UNSPECIFIED;
6449
6450 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6451 st->codecpar->color_primaries = color_primaries;
6452 st->codecpar->color_trc = color_trc;
6453 st->codecpar->color_space = color_space;
6454
6455 return 0;
6456 }
6457
6458 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6459 {
6460 MOVStreamContext *sc;
6461 int i, version;
6462
6463 if (c->fc->nb_streams < 1)
6464 return AVERROR_INVALIDDATA;
6465
6466 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6467
6468 if (atom.size < 5) {
6469 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6470 return AVERROR_INVALIDDATA;
6471 }
6472
6473 version = avio_r8(pb);
6474 if (version) {
6475 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6476 return 0;
6477 }
6478 if (sc->mastering) {
6479 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6480 return 0;
6481 }
6482
6483 avio_skip(pb, 3); /* flags */
6484
6485 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6486 if (!sc->mastering)
6487 return AVERROR(ENOMEM);
6488
6489 for (i = 0; i < 3; i++) {
6490 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6491 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6492 }
6493 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6494 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6495
6496 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6497 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6498
6499 sc->mastering->has_primaries = 1;
6500 sc->mastering->has_luminance = 1;
6501
6502 return 0;
6503 }
6504
6505 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6506 {
6507 MOVStreamContext *sc;
6508 const int mapping[3] = {1, 2, 0};
6509 const int chroma_den = 50000;
6510 const int luma_den = 10000;
6511 int i;
6512
6513 if (c->fc->nb_streams < 1)
6514 return AVERROR_INVALIDDATA;
6515
6516 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6517
6518 if (atom.size < 24) {
6519 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6520 return AVERROR_INVALIDDATA;
6521 }
6522
6523 if (sc->mastering) {
6524 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6525 return 0;
6526 }
6527
6528 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6529 if (!sc->mastering)
6530 return AVERROR(ENOMEM);
6531
6532 for (i = 0; i < 3; i++) {
6533 const int j = mapping[i];
6534 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6535 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6536 }
6537 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6538 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6539
6540 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6541 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6542
6543 sc->mastering->has_luminance = 1;
6544 sc->mastering->has_primaries = 1;
6545
6546 return 0;
6547 }
6548
6549 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6550 {
6551 MOVStreamContext *sc;
6552 int version;
6553
6554 if (c->fc->nb_streams < 1)
6555 return AVERROR_INVALIDDATA;
6556
6557 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6558
6559 if (atom.size < 5) {
6560 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
6561 return AVERROR_INVALIDDATA;
6562 }
6563
6564 version = avio_r8(pb);
6565 if (version) {
6566 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
6567 return 0;
6568 }
6569 avio_skip(pb, 3); /* flags */
6570
6571 if (sc->coll){
6572 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
6573 return 0;
6574 }
6575
6576 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6577 if (!sc->coll)
6578 return AVERROR(ENOMEM);
6579
6580 sc->coll->MaxCLL = avio_rb16(pb);
6581 sc->coll->MaxFALL = avio_rb16(pb);
6582
6583 return 0;
6584 }
6585
6586 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6587 {
6588 MOVStreamContext *sc;
6589
6590 if (c->fc->nb_streams < 1)
6591 return AVERROR_INVALIDDATA;
6592
6593 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6594
6595 if (atom.size < 4) {
6596 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
6597 return AVERROR_INVALIDDATA;
6598 }
6599
6600 if (sc->coll){
6601 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
6602 return 0;
6603 }
6604
6605 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6606 if (!sc->coll)
6607 return AVERROR(ENOMEM);
6608
6609 sc->coll->MaxCLL = avio_rb16(pb);
6610 sc->coll->MaxFALL = avio_rb16(pb);
6611
6612 return 0;
6613 }
6614
6615 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6616 {
6617 MOVStreamContext *sc;
6618 4 const int illuminance_den = 10000;
6619 4 const int ambient_den = 50000;
6620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
6621 return AVERROR_INVALIDDATA;
6622 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
6624 av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
6625 return AVERROR_INVALIDDATA;
6626 }
6627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
6628 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
6629 return 0;
6630 }
6631 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
6632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
6633 return AVERROR(ENOMEM);
6634 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
6635 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
6636 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
6637 4 return 0;
6638 }
6639
6640 1 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6641 {
6642 AVStream *st;
6643 MOVStreamContext *sc;
6644 enum AVStereo3DType type;
6645 int mode;
6646
6647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6648 return 0;
6649
6650 1 st = c->fc->streams[c->fc->nb_streams - 1];
6651 1 sc = st->priv_data;
6652
6653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 5) {
6654 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
6655 return AVERROR_INVALIDDATA;
6656 }
6657
6658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sc->stereo3d)
6659 return AVERROR_INVALIDDATA;
6660
6661 1 avio_skip(pb, 4); /* version + flags */
6662
6663 1 mode = avio_r8(pb);
6664
1/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 switch (mode) {
6665 1 case 0:
6666 1 type = AV_STEREO3D_2D;
6667 1 break;
6668 case 1:
6669 type = AV_STEREO3D_TOPBOTTOM;
6670 break;
6671 case 2:
6672 type = AV_STEREO3D_SIDEBYSIDE;
6673 break;
6674 default:
6675 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
6676 return 0;
6677 }
6678
6679 1 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->stereo3d)
6681 return AVERROR(ENOMEM);
6682
6683 1 sc->stereo3d->type = type;
6684 1 return 0;
6685 }
6686
6687 static int mov_read_pack(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6688 {
6689 AVStream *st;
6690 MOVStreamContext *sc;
6691 int size = 0;
6692 int64_t remaining;
6693 uint32_t tag = 0;
6694 enum AVStereo3DType type = AV_STEREO3D_2D;
6695
6696 if (c->fc->nb_streams < 1)
6697 return 0;
6698
6699 st = c->fc->streams[c->fc->nb_streams - 1];
6700 sc = st->priv_data;
6701
6702 remaining = atom.size;
6703 while (remaining > 0) {
6704 size = avio_rb32(pb);
6705 if (size < 8 || size > remaining ) {
6706 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in pack box\n");
6707 return AVERROR_INVALIDDATA;
6708 }
6709
6710 tag = avio_rl32(pb);
6711 switch (tag) {
6712 case MKTAG('p','k','i','n'): {
6713 if (size != 16) {
6714 av_log(c->fc, AV_LOG_ERROR, "Invalid size of pkin box: %d\n", size);
6715 return AVERROR_INVALIDDATA;
6716 }
6717 avio_skip(pb, 1); // version
6718 avio_skip(pb, 3); // flags
6719
6720 tag = avio_rl32(pb);
6721 switch (tag) {
6722 case MKTAG('s','i','d','e'):
6723 type = AV_STEREO3D_SIDEBYSIDE;
6724 break;
6725 case MKTAG('o','v','e','r'):
6726 type = AV_STEREO3D_TOPBOTTOM;
6727 break;
6728 case 0:
6729 // This means value will be set in another layer
6730 break;
6731 default:
6732 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pkin: %s\n",
6733 av_fourcc2str(tag));
6734 avio_skip(pb, size - 8);
6735 break;
6736 }
6737
6738 break;
6739 }
6740 default:
6741 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pack: %s\n",
6742 av_fourcc2str(tag));
6743 avio_skip(pb, size - 8);
6744 break;
6745 }
6746 remaining -= size;
6747 }
6748
6749 if (remaining != 0) {
6750 av_log(c->fc, AV_LOG_ERROR, "Broken pack box\n");
6751 return AVERROR_INVALIDDATA;
6752 }
6753
6754 if (type == AV_STEREO3D_2D)
6755 return 0;
6756
6757 if (!sc->stereo3d) {
6758 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6759 if (!sc->stereo3d)
6760 return AVERROR(ENOMEM);
6761 }
6762
6763 sc->stereo3d->type = type;
6764
6765 return 0;
6766 }
6767
6768 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6769 {
6770 AVStream *st;
6771 MOVStreamContext *sc;
6772 int size, version, layout;
6773 int32_t yaw, pitch, roll;
6774 1 uint32_t l = 0, t = 0, r = 0, b = 0;
6775 1 uint32_t tag, padding = 0;
6776 enum AVSphericalProjection projection;
6777
6778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6779 return 0;
6780
6781 1 st = c->fc->streams[c->fc->nb_streams - 1];
6782 1 sc = st->priv_data;
6783
6784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
6785 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
6786 return AVERROR_INVALIDDATA;
6787 }
6788
6789 1 size = avio_rb32(pb);
6790
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)
6791 return AVERROR_INVALIDDATA;
6792
6793 1 tag = avio_rl32(pb);
6794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
6795 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
6796 return 0;
6797 }
6798 1 version = avio_r8(pb);
6799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6800 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6801 version);
6802 return 0;
6803 }
6804 1 avio_skip(pb, 3); /* flags */
6805 1 avio_skip(pb, size - 12); /* metadata_source */
6806
6807 1 size = avio_rb32(pb);
6808
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6809 return AVERROR_INVALIDDATA;
6810
6811 1 tag = avio_rl32(pb);
6812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
6813 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
6814 return 0;
6815 }
6816
6817 1 size = avio_rb32(pb);
6818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6819 return AVERROR_INVALIDDATA;
6820
6821 1 tag = avio_rl32(pb);
6822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
6823 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
6824 return 0;
6825 }
6826 1 version = avio_r8(pb);
6827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6828 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6829 version);
6830 return 0;
6831 }
6832 1 avio_skip(pb, 3); /* flags */
6833
6834 /* 16.16 fixed point */
6835 1 yaw = avio_rb32(pb);
6836 1 pitch = avio_rb32(pb);
6837 1 roll = avio_rb32(pb);
6838
6839 1 size = avio_rb32(pb);
6840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6841 return AVERROR_INVALIDDATA;
6842
6843 1 tag = avio_rl32(pb);
6844 1 version = avio_r8(pb);
6845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6846 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6847 version);
6848 return 0;
6849 }
6850 1 avio_skip(pb, 3); /* flags */
6851
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
6852 case MKTAG('c','b','m','p'):
6853 layout = avio_rb32(pb);
6854 if (layout) {
6855 av_log(c->fc, AV_LOG_WARNING,
6856 "Unsupported cubemap layout %d\n", layout);
6857 return 0;
6858 }
6859 projection = AV_SPHERICAL_CUBEMAP;
6860 padding = avio_rb32(pb);
6861 break;
6862 1 case MKTAG('e','q','u','i'):
6863 1 t = avio_rb32(pb);
6864 1 b = avio_rb32(pb);
6865 1 l = avio_rb32(pb);
6866 1 r = avio_rb32(pb);
6867
6868
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) {
6869 av_log(c->fc, AV_LOG_ERROR,
6870 "Invalid bounding rectangle coordinates "
6871 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
6872 return AVERROR_INVALIDDATA;
6873 }
6874
6875
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)
6876 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
6877 else
6878 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6879 1 break;
6880 default:
6881 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
6882 return 0;
6883 }
6884
6885 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
6887 return AVERROR(ENOMEM);
6888
6889 1 sc->spherical->projection = projection;
6890
6891 1 sc->spherical->yaw = yaw;
6892 1 sc->spherical->pitch = pitch;
6893 1 sc->spherical->roll = roll;
6894
6895 1 sc->spherical->padding = padding;
6896
6897 1 sc->spherical->bound_left = l;
6898 1 sc->spherical->bound_top = t;
6899 1 sc->spherical->bound_right = r;
6900 1 sc->spherical->bound_bottom = b;
6901
6902 1 return 0;
6903 }
6904
6905 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6906 {
6907 AVStream *st;
6908 MOVStreamContext *sc;
6909 int size;
6910 uint32_t tag;
6911 enum AVSphericalProjection projection;
6912
6913
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6914 return 0;
6915
6916 3 st = c->fc->streams[c->fc->nb_streams - 1];
6917 3 sc = st->priv_data;
6918
6919
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 16) {
6920 av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
6921 return AVERROR_INVALIDDATA;
6922 }
6923
6924 3 size = avio_rb32(pb);
6925
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size < 16) {
6926 av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
6927 return AVERROR_INVALIDDATA;
6928
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (size > 16) {
6929 av_log(c->fc, AV_LOG_WARNING, "Box has more bytes (%d) than prji box required (16) \n", size);
6930 }
6931
6932 3 tag = avio_rl32(pb);
6933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
6934 av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: %s\n",
6935 av_fourcc2str(tag));
6936 return AVERROR_INVALIDDATA;
6937 }
6938
6939 // version and flags, only support (0, 0)
6940 3 unsigned n = avio_rl32(pb);
6941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (n != 0) {
6942 av_log(c->fc, AV_LOG_ERROR, "prji version %u, flag %u are not supported\n",
6943 n & 0xFF, n >> 8);
6944 return AVERROR_PATCHWELCOME;
6945 }
6946
6947 3 tag = avio_rl32(pb);
6948
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) {
6949 3 case MKTAG('r','e','c','t'):
6950 3 projection = AV_SPHERICAL_RECTILINEAR;
6951 3 break;
6952 case MKTAG('e','q','u','i'):
6953 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6954 break;
6955 case MKTAG('h','e','q','u'):
6956 projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
6957 break;
6958 case MKTAG('f','i','s','h'):
6959 projection = AV_SPHERICAL_FISHEYE;
6960 break;
6961 case MKTAG('p','r','i','m'):
6962 projection = AV_SPHERICAL_PARAMETRIC_IMMERSIVE;
6963 break;
6964 default:
6965 av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: %s\n", av_fourcc2str(tag));
6966 return AVERROR_INVALIDDATA;
6967 }
6968
6969 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
6971 return AVERROR(ENOMEM);
6972
6973 3 sc->spherical->projection = projection;
6974
6975 3 return 0;
6976 }
6977
6978 3 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6979 {
6980 AVStream *st;
6981 MOVStreamContext *sc;
6982 3 int size, flags = 0;
6983 int64_t remaining;
6984 3 uint32_t tag, baseline = 0;
6985 3 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
6986 3 enum AVStereo3DType type = AV_STEREO3D_2D;
6987 3 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
6988 3 AVRational horizontal_disparity_adjustment = { 0, 1 };
6989
6990
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6991 return 0;
6992
6993 3 st = c->fc->streams[c->fc->nb_streams - 1];
6994 3 sc = st->priv_data;
6995
6996 3 remaining = atom.size;
6997
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 while (remaining > 0) {
6998 9 size = avio_rb32(pb);
6999
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 ) {
7000 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
7001 return AVERROR_INVALIDDATA;
7002 }
7003
7004 9 tag = avio_rl32(pb);
7005
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) {
7006 3 case MKTAG('s','t','r','i'): {
7007 int has_right, has_left;
7008 uint8_t tmp;
7009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 13) {
7010 av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
7011 return AVERROR_INVALIDDATA;
7012 }
7013 3 avio_skip(pb, 1); // version
7014 3 avio_skip(pb, 3); // flags
7015
7016 3 tmp = avio_r8(pb);
7017
7018 // eye_views_reversed
7019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tmp & 8) {
7020 flags |= AV_STEREO3D_FLAG_INVERT;
7021 }
7022 // has_additional_views
7023 3 if (tmp & 4) {
7024 // skip...
7025 }
7026
7027 3 has_right = tmp & 2; // has_right_eye_view
7028 3 has_left = tmp & 1; // has_left_eye_view
7029
7030
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)
7031 3 view = AV_STEREO3D_VIEW_PACKED;
7032 else if (has_left)
7033 view = AV_STEREO3D_VIEW_LEFT;
7034 else if (has_right)
7035 view = AV_STEREO3D_VIEW_RIGHT;
7036
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)
7037 3 type = AV_STEREO3D_UNSPEC;
7038
7039 3 break;
7040 }
7041 case MKTAG('h','e','r','o'): {
7042 int tmp;
7043 if (size != 13) {
7044 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
7045 return AVERROR_INVALIDDATA;
7046 }
7047 avio_skip(pb, 1); // version
7048 avio_skip(pb, 3); // flags
7049
7050 tmp = avio_r8(pb);
7051 if (tmp == 0)
7052 primary_eye = AV_PRIMARY_EYE_NONE;
7053 else if (tmp == 1)
7054 primary_eye = AV_PRIMARY_EYE_LEFT;
7055 else if (tmp == 2)
7056 primary_eye = AV_PRIMARY_EYE_RIGHT;
7057 else
7058 av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
7059
7060 break;
7061 }
7062 3 case MKTAG('c','a','m','s'): {
7063 uint32_t subtag;
7064 int subsize;
7065
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7066 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
7067 return AVERROR_INVALIDDATA;
7068 }
7069
7070 3 subsize = avio_rb32(pb);
7071
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7072 av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
7073 return AVERROR_INVALIDDATA;
7074 }
7075
7076 3 subtag = avio_rl32(pb);
7077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
7078 av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got %s\n",
7079 av_fourcc2str(subtag));
7080 return AVERROR_INVALIDDATA;
7081 }
7082
7083 3 avio_skip(pb, 1); // version
7084 3 avio_skip(pb, 3); // flags
7085
7086 3 baseline = avio_rb32(pb);
7087
7088 3 break;
7089 }
7090 3 case MKTAG('c','m','f','y'): {
7091 uint32_t subtag;
7092 int subsize;
7093 int32_t adjustment;
7094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7095 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
7096 return AVERROR_INVALIDDATA;
7097 }
7098
7099 3 subsize = avio_rb32(pb);
7100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7101 av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
7102 return AVERROR_INVALIDDATA;
7103 }
7104
7105 3 subtag = avio_rl32(pb);
7106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
7107 av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got %s\n",
7108 av_fourcc2str(subtag));
7109 return AVERROR_INVALIDDATA;
7110 }
7111
7112 3 avio_skip(pb, 1); // version
7113 3 avio_skip(pb, 3); // flags
7114
7115 3 adjustment = (int32_t) avio_rb32(pb);
7116
7117 3 horizontal_disparity_adjustment.num = (int) adjustment;
7118 3 horizontal_disparity_adjustment.den = 10000;
7119
7120 3 break;
7121 }
7122 default:
7123 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: %s\n",
7124 av_fourcc2str(tag));
7125 avio_skip(pb, size - 8);
7126 break;
7127 }
7128 9 remaining -= size;
7129 }
7130
7131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7132 av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
7133 return AVERROR_INVALIDDATA;
7134 }
7135
7136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (type == AV_STEREO3D_2D)
7137 return 0;
7138
7139
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->stereo3d) {
7140 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7142 return AVERROR(ENOMEM);
7143 }
7144
7145 3 sc->stereo3d->flags = flags;
7146 3 sc->stereo3d->type = type;
7147 3 sc->stereo3d->view = view;
7148 3 sc->stereo3d->primary_eye = primary_eye;
7149 3 sc->stereo3d->baseline = baseline;
7150 3 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
7151
7152 3 return 0;
7153 }
7154
7155 3 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7156 {
7157 int size;
7158 int64_t remaining;
7159 uint32_t tag;
7160
7161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7162 return 0;
7163
7164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8) {
7165 av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
7166 return AVERROR_INVALIDDATA;
7167 }
7168
7169 3 remaining = atom.size;
7170
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 while (remaining > 0) {
7171 6 size = avio_rb32(pb);
7172
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 ) {
7173 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
7174 return AVERROR_INVALIDDATA;
7175 }
7176
7177 6 tag = avio_rl32(pb);
7178
2/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 switch (tag) {
7179 3 case MKTAG('p','r','o','j'): {
7180 3 MOVAtom proj = { tag, size - 8 };
7181 3 int ret = mov_read_vexu_proj(c, pb, proj);
7182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7183 return ret;
7184 3 break;
7185 }
7186 3 case MKTAG('e','y','e','s'): {
7187 3 MOVAtom eyes = { tag, size - 8 };
7188 3 int ret = mov_read_eyes(c, pb, eyes);
7189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7190 return ret;
7191 3 break;
7192 }
7193 case MKTAG('p','a','c','k'): {
7194 MOVAtom pack = { tag, size - 8 };
7195 int ret = mov_read_pack(c, pb, pack);
7196 if (ret < 0)
7197 return ret;
7198 break;
7199 }
7200 default:
7201 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: %s\n",
7202 av_fourcc2str(tag));
7203 avio_skip(pb, size - 8);
7204 break;
7205 }
7206 6 remaining -= size;
7207 }
7208
7209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7210 av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7211 return AVERROR_INVALIDDATA;
7212 }
7213
7214 3 return 0;
7215 }
7216
7217 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7218 {
7219 AVStream *st;
7220 MOVStreamContext *sc;
7221
7222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7223 return 0;
7224
7225 3 st = c->fc->streams[c->fc->nb_streams - 1];
7226 3 sc = st->priv_data;
7227
7228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7229 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7230 return AVERROR_INVALIDDATA;
7231 }
7232
7233
7234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7235 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7236 if (!sc->stereo3d)
7237 return AVERROR(ENOMEM);
7238 }
7239
7240 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7241 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7242
7243 3 return 0;
7244 }
7245
7246 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7247 {
7248 int ret = 0;
7249 uint8_t *buffer = av_malloc(len + 1);
7250 const char *val;
7251
7252 if (!buffer)
7253 return AVERROR(ENOMEM);
7254 buffer[len] = '\0';
7255
7256 ret = ffio_read_size(pb, buffer, len);
7257 if (ret < 0)
7258 goto out;
7259
7260 /* Check for mandatory keys and values, try to support XML as best-effort */
7261 if (!sc->spherical &&
7262 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7263 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7264 av_stristr(val, "true") &&
7265 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7266 av_stristr(val, "true") &&
7267 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7268 av_stristr(val, "equirectangular")) {
7269 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7270 if (!sc->spherical)
7271 goto out;
7272
7273 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7274
7275 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7276 enum AVStereo3DType mode;
7277
7278 if (av_stristr(buffer, "left-right"))
7279 mode = AV_STEREO3D_SIDEBYSIDE;
7280 else if (av_stristr(buffer, "top-bottom"))
7281 mode = AV_STEREO3D_TOPBOTTOM;
7282 else
7283 mode = AV_STEREO3D_2D;
7284
7285 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7286 if (!sc->stereo3d)
7287 goto out;
7288
7289 sc->stereo3d->type = mode;
7290 }
7291
7292 /* orientation */
7293 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7294 if (val)
7295 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7296 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7297 if (val)
7298 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7299 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7300 if (val)
7301 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7302 }
7303
7304 out:
7305 av_free(buffer);
7306 return ret;
7307 }
7308
7309 69 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7310 {
7311 AVStream *st;
7312 MOVStreamContext *sc;
7313 int64_t ret;
7314 AVUUID uuid;
7315 static const AVUUID uuid_isml_manifest = {
7316 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7317 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7318 };
7319 static const AVUUID uuid_xmp = {
7320 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7321 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7322 };
7323 static const AVUUID uuid_spherical = {
7324 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7325 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7326 };
7327
7328
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))
7329 return AVERROR_INVALIDDATA;
7330
7331
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 66 times.
69 if (c->fc->nb_streams < 1)
7332 3 return 0;
7333 66 st = c->fc->streams[c->fc->nb_streams - 1];
7334 66 sc = st->priv_data;
7335
7336 66 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
7338 return ret;
7339
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7340 uint8_t *buffer, *ptr;
7341 char *endptr;
7342 size_t len = atom.size - AV_UUID_LEN;
7343
7344 if (len < 4) {
7345 return AVERROR_INVALIDDATA;
7346 }
7347 ret = avio_skip(pb, 4); // zeroes
7348 len -= 4;
7349
7350 buffer = av_mallocz(len + 1);
7351 if (!buffer) {
7352 return AVERROR(ENOMEM);
7353 }
7354 ret = ffio_read_size(pb, buffer, len);
7355 if (ret < 0) {
7356 av_free(buffer);
7357 return ret;
7358 }
7359
7360 ptr = buffer;
7361 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7362 ptr += sizeof("systemBitrate=\"") - 1;
7363 c->bitrates_count++;
7364 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7365 if (!c->bitrates) {
7366 c->bitrates_count = 0;
7367 av_free(buffer);
7368 return AVERROR(ENOMEM);
7369 }
7370 errno = 0;
7371 ret = strtol(ptr, &endptr, 10);
7372 if (ret < 0 || errno || *endptr != '"') {
7373 c->bitrates[c->bitrates_count - 1] = 0;
7374 } else {
7375 c->bitrates[c->bitrates_count - 1] = ret;
7376 }
7377 }
7378
7379 av_free(buffer);
7380
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7381 uint8_t *buffer;
7382 size_t len = atom.size - AV_UUID_LEN;
7383 if (c->export_xmp) {
7384 buffer = av_mallocz(len + 1);
7385 if (!buffer) {
7386 return AVERROR(ENOMEM);
7387 }
7388 ret = ffio_read_size(pb, buffer, len);
7389 if (ret < 0) {
7390 av_free(buffer);
7391 return ret;
7392 }
7393 buffer[len] = '\0';
7394 av_dict_set(&c->fc->metadata, "xmp",
7395 buffer, AV_DICT_DONT_STRDUP_VAL);
7396 } else {
7397 // skip all uuid atom, which makes it fast for long uuid-xmp file
7398 ret = avio_skip(pb, len);
7399 if (ret < 0)
7400 return ret;
7401 }
7402
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7403 size_t len = atom.size - AV_UUID_LEN;
7404 ret = mov_parse_uuid_spherical(sc, pb, len);
7405 if (ret < 0)
7406 return ret;
7407 if (!sc->spherical)
7408 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7409 }
7410
7411 66 return 0;
7412 }
7413
7414 197 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7415 {
7416 int ret;
7417 uint8_t content[16];
7418
7419
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 99 times.
197 if (atom.size < 8)
7420 98 return 0;
7421
7422 99 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (ret < 0)
7424 return ret;
7425
7426
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 56 times.
99 if ( !c->found_moov
7427
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 23 times.
43 && !c->found_mdat
7428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 && !memcmp(content, "Anevia\x1A\x1A", 8)
7429 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7430 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7431 }
7432
7433 99 return 0;
7434 }
7435
7436 39 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7437 {
7438 39 uint32_t format = avio_rl32(pb);
7439 MOVStreamContext *sc;
7440 enum AVCodecID id;
7441 AVStream *st;
7442
7443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (c->fc->nb_streams < 1)
7444 return 0;
7445 39 st = c->fc->streams[c->fc->nb_streams - 1];
7446 39 sc = st->priv_data;
7447
7448
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 33 times.
39 switch (sc->format)
7449 {
7450 6 case MKTAG('e','n','c','v'): // encrypted video
7451 case MKTAG('e','n','c','a'): // encrypted audio
7452 6 id = mov_codec_id(st, format);
7453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7454 st->codecpar->codec_id != id) {
7455 av_log(c->fc, AV_LOG_WARNING,
7456 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7457 (char*)&format, st->codecpar->codec_id);
7458 break;
7459 }
7460
7461 6 st->codecpar->codec_id = id;
7462 6 sc->format = format;
7463 6 break;
7464
7465 33 default:
7466
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (format != sc->format) {
7467 av_log(c->fc, AV_LOG_WARNING,
7468 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7469 (char*)&format, (char*)&sc->format);
7470 }
7471 33 break;
7472 }
7473
7474 39 return 0;
7475 }
7476
7477 /**
7478 * Gets the current encryption info and associated current stream context. If
7479 * we are parsing a track fragment, this will return the specific encryption
7480 * info for this fragment; otherwise this will return the global encryption
7481 * info for the current stream.
7482 */
7483 12 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7484 {
7485 MOVFragmentStreamInfo *frag_stream_info;
7486 AVStream *st;
7487 int i;
7488
7489 12 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7490
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (frag_stream_info) {
7491
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 for (i = 0; i < c->fc->nb_streams; i++) {
7492 6 *sc = c->fc->streams[i]->priv_data;
7493
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if ((*sc)->id == frag_stream_info->id) {
7494 6 st = c->fc->streams[i];
7495 6 break;
7496 }
7497 }
7498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (i == c->fc->nb_streams)
7499 return 0;
7500 6 *sc = st->priv_data;
7501
7502
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (!frag_stream_info->encryption_index) {
7503 // If this stream isn't encrypted, don't create the index.
7504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(*sc)->cenc.default_encrypted_sample)
7505 return 0;
7506 2 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!frag_stream_info->encryption_index)
7508 return AVERROR(ENOMEM);
7509 }
7510 6 *encryption_index = frag_stream_info->encryption_index;
7511 6 return 1;
7512 } else {
7513 // No current track fragment, using stream level encryption info.
7514
7515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (c->fc->nb_streams < 1)
7516 return 0;
7517 6 st = c->fc->streams[c->fc->nb_streams - 1];
7518 6 *sc = st->priv_data;
7519
7520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!(*sc)->cenc.encryption_index) {
7521 // If this stream isn't encrypted, don't create the index.
7522 if (!(*sc)->cenc.default_encrypted_sample)
7523 return 0;
7524 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7525 if (!(*sc)->cenc.encryption_index)
7526 return AVERROR(ENOMEM);
7527 }
7528
7529 6 *encryption_index = (*sc)->cenc.encryption_index;
7530 6 return 1;
7531 }
7532 }
7533
7534 144 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7535 {
7536 int i, ret;
7537 unsigned int subsample_count;
7538 AVSubsampleEncryptionInfo *subsamples;
7539
7540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (!sc->cenc.default_encrypted_sample) {
7541 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7542 return AVERROR_INVALIDDATA;
7543 }
7544
7545
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) {
7546 144 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (!*sample)
7548 return AVERROR(ENOMEM);
7549 } else
7550 *sample = NULL;
7551
7552
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 if (sc->cenc.per_sample_iv_size != 0) {
7553
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) {
7554 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
7555 av_encryption_info_free(*sample);
7556 *sample = NULL;
7557 return ret;
7558 }
7559 }
7560
7561
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 if (use_subsamples) {
7562 144 subsample_count = avio_rb16(pb);
7563 144 av_free((*sample)->subsamples);
7564 144 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
7565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (!(*sample)->subsamples) {
7566 av_encryption_info_free(*sample);
7567 *sample = NULL;
7568 return AVERROR(ENOMEM);
7569 }
7570
7571
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++) {
7572 144 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
7573 144 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
7574 }
7575
7576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (pb->eof_reached) {
7577 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
7578 av_encryption_info_free(*sample);
7579 *sample = NULL;
7580 return AVERROR_INVALIDDATA;
7581 }
7582 144 (*sample)->subsample_count = subsample_count;
7583 }
7584
7585 144 return 0;
7586 }
7587
7588 4 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7589 {
7590 AVEncryptionInfo **encrypted_samples;
7591 MOVEncryptionIndex *encryption_index;
7592 MOVStreamContext *sc;
7593 int use_subsamples, ret;
7594 4 unsigned int sample_count, i, alloc_size = 0;
7595
7596 4 ret = get_current_encryption_info(c, &encryption_index, &sc);
7597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != 1)
7598 return ret;
7599
7600
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (encryption_index->nb_encrypted_samples) {
7601 // This can happen if we have both saio/saiz and senc atoms.
7602 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
7603 2 return 0;
7604 }
7605
7606 2 avio_r8(pb); /* version */
7607 2 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
7608
7609 2 sample_count = avio_rb32(pb);
7610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7611 return AVERROR(ENOMEM);
7612
7613
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 2 times.
98 for (i = 0; i < sample_count; i++) {
7614 96 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7615 96 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7616 min_samples * sizeof(*encrypted_samples));
7617
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 if (encrypted_samples) {
7618 96 encryption_index->encrypted_samples = encrypted_samples;
7619
7620 96 ret = mov_read_sample_encryption_info(
7621 96 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
7622 } else {
7623 ret = AVERROR(ENOMEM);
7624 }
7625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (pb->eof_reached) {
7626 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
7627 if (ret >= 0)
7628 av_encryption_info_free(encryption_index->encrypted_samples[i]);
7629 ret = AVERROR_INVALIDDATA;
7630 }
7631
7632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (ret < 0) {
7633 for (; i > 0; i--)
7634 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7635 av_freep(&encryption_index->encrypted_samples);
7636 return ret;
7637 }
7638 }
7639 2 encryption_index->nb_encrypted_samples = sample_count;
7640
7641 2 return 0;
7642 }
7643
7644 2 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
7645 {
7646 AVEncryptionInfo **sample, **encrypted_samples;
7647 int64_t prev_pos;
7648 size_t sample_count, sample_info_size, i;
7649 2 int ret = 0;
7650 2 unsigned int alloc_size = 0;
7651
7652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->nb_encrypted_samples)
7653 return 0;
7654 2 sample_count = encryption_index->auxiliary_info_sample_count;
7655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count != 1) {
7656 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
7657 return AVERROR_PATCHWELCOME;
7658 }
7659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7660 return AVERROR(ENOMEM);
7661
7662 2 prev_pos = avio_tell(pb);
7663
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
7664
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]) {
7665 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
7666 goto finish;
7667 }
7668
7669
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++) {
7670 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7671 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7672 min_samples * sizeof(*encrypted_samples));
7673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (!encrypted_samples) {
7674 ret = AVERROR(ENOMEM);
7675 goto finish;
7676 }
7677 48 encryption_index->encrypted_samples = encrypted_samples;
7678
7679 48 sample = &encryption_index->encrypted_samples[i];
7680 96 sample_info_size = encryption_index->auxiliary_info_default_size
7681 48 ? encryption_index->auxiliary_info_default_size
7682
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 : encryption_index->auxiliary_info_sizes[i];
7683
7684 48 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
7685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0)
7686 goto finish;
7687 }
7688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
7689 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
7690 ret = AVERROR_INVALIDDATA;
7691 } else {
7692 2 encryption_index->nb_encrypted_samples = sample_count;
7693 }
7694
7695 2 finish:
7696 2 avio_seek(pb, prev_pos, SEEK_SET);
7697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
7698 for (; i > 0; i--) {
7699 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7700 }
7701 av_freep(&encryption_index->encrypted_samples);
7702 }
7703 2 return ret;
7704 }
7705
7706 4 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7707 {
7708 MOVEncryptionIndex *encryption_index;
7709 MOVStreamContext *sc;
7710 int ret;
7711 unsigned int sample_count, aux_info_type, aux_info_param;
7712
7713 4 ret = get_current_encryption_info(c, &encryption_index, &sc);
7714
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != 1)
7715 return ret;
7716
7717
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (encryption_index->nb_encrypted_samples) {
7718 // This can happen if we have both saio/saiz and senc atoms.
7719 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
7720 2 return 0;
7721 }
7722
7723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_sample_count) {
7724 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
7725 return AVERROR_INVALIDDATA;
7726 }
7727
7728 2 avio_r8(pb); /* version */
7729
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
7730 aux_info_type = avio_rb32(pb);
7731 aux_info_param = avio_rb32(pb);
7732 if (sc->cenc.default_encrypted_sample) {
7733 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7734 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
7735 return 0;
7736 }
7737 if (aux_info_param != 0) {
7738 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
7739 return 0;
7740 }
7741 } else {
7742 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7743 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7744 aux_info_type == MKBETAG('c','e','n','s') ||
7745 aux_info_type == MKBETAG('c','b','c','1') ||
7746 aux_info_type == MKBETAG('c','b','c','s')) &&
7747 aux_info_param == 0) {
7748 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
7749 return AVERROR_INVALIDDATA;
7750 } else {
7751 return 0;
7752 }
7753 }
7754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
7755 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7756 return 0;
7757 }
7758
7759 2 encryption_index->auxiliary_info_default_size = avio_r8(pb);
7760 2 sample_count = avio_rb32(pb);
7761
7762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_default_size == 0) {
7763 if (sample_count == 0)
7764 return AVERROR_INVALIDDATA;
7765
7766 encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
7767 if (!encryption_index->auxiliary_info_sizes)
7768 return AVERROR(ENOMEM);
7769
7770 ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
7771 if (ret != sample_count) {
7772 av_freep(&encryption_index->auxiliary_info_sizes);
7773
7774 if (ret >= 0)
7775 ret = AVERROR_INVALIDDATA;
7776 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
7777 av_err2str(ret));
7778 return ret;
7779 }
7780 }
7781 2 encryption_index->auxiliary_info_sample_count = sample_count;
7782
7783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
7784 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7785 }
7786
7787 2 return 0;
7788 }
7789
7790 4 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7791 {
7792 uint64_t *auxiliary_offsets;
7793 MOVEncryptionIndex *encryption_index;
7794 MOVStreamContext *sc;
7795 int i, ret;
7796 unsigned int version, entry_count, aux_info_type, aux_info_param;
7797 4 unsigned int alloc_size = 0;
7798
7799 4 ret = get_current_encryption_info(c, &encryption_index, &sc);
7800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != 1)
7801 return ret;
7802
7803
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (encryption_index->nb_encrypted_samples) {
7804 // This can happen if we have both saio/saiz and senc atoms.
7805 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
7806 2 return 0;
7807 }
7808
7809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
7810 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
7811 return AVERROR_INVALIDDATA;
7812 }
7813
7814 2 version = avio_r8(pb); /* version */
7815
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
7816 aux_info_type = avio_rb32(pb);
7817 aux_info_param = avio_rb32(pb);
7818 if (sc->cenc.default_encrypted_sample) {
7819 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7820 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
7821 return 0;
7822 }
7823 if (aux_info_param != 0) {
7824 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
7825 return 0;
7826 }
7827 } else {
7828 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7829 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7830 aux_info_type == MKBETAG('c','e','n','s') ||
7831 aux_info_type == MKBETAG('c','b','c','1') ||
7832 aux_info_type == MKBETAG('c','b','c','s')) &&
7833 aux_info_param == 0) {
7834 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
7835 return AVERROR_INVALIDDATA;
7836 } else {
7837 return 0;
7838 }
7839 }
7840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
7841 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7842 return 0;
7843 }
7844
7845 2 entry_count = avio_rb32(pb);
7846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
7847 return AVERROR(ENOMEM);
7848
7849
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++) {
7850
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);
7851 2 auxiliary_offsets = av_fast_realloc(
7852 2 encryption_index->auxiliary_offsets, &alloc_size,
7853 min_offsets * sizeof(*auxiliary_offsets));
7854
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!auxiliary_offsets) {
7855 av_freep(&encryption_index->auxiliary_offsets);
7856 return AVERROR(ENOMEM);
7857 }
7858 2 encryption_index->auxiliary_offsets = auxiliary_offsets;
7859
7860
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version == 0) {
7861 2 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
7862 } else {
7863 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
7864 }
7865
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (c->frag_index.current >= 0) {
7866 2 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
7867 }
7868 }
7869
7870
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
7871 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
7872 av_freep(&encryption_index->auxiliary_offsets);
7873 return AVERROR_INVALIDDATA;
7874 }
7875
7876 2 encryption_index->auxiliary_offsets_count = entry_count;
7877
7878
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (encryption_index->auxiliary_info_sample_count) {
7879 2 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7880 }
7881
7882 return 0;
7883 }
7884
7885 4 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7886 {
7887 AVEncryptionInitInfo *info, *old_init_info;
7888 uint8_t **key_ids;
7889 AVStream *st;
7890 const AVPacketSideData *old_side_data;
7891 uint8_t *side_data, *extra_data;
7892 size_t side_data_size;
7893 4 int ret = 0;
7894 4 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
7895
7896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
7897 return 0;
7898 4 st = c->fc->streams[c->fc->nb_streams-1];
7899
7900 4 version = avio_r8(pb); /* version */
7901 4 avio_rb24(pb); /* flags */
7902
7903 4 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
7904 /* key_id_size */ 16, /* data_size */ 0);
7905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info)
7906 return AVERROR(ENOMEM);
7907
7908
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
7909 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
7910 goto finish;
7911 }
7912
7913
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (version > 0) {
7914 4 kid_count = avio_rb32(pb);
7915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
7916 ret = AVERROR(ENOMEM);
7917 goto finish;
7918 }
7919
7920
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++) {
7921 4 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
7922 4 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
7923 min_kid_count * sizeof(*key_ids));
7924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!key_ids) {
7925 ret = AVERROR(ENOMEM);
7926 goto finish;
7927 }
7928 4 info->key_ids = key_ids;
7929
7930 4 info->key_ids[i] = av_mallocz(16);
7931
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info->key_ids[i]) {
7932 ret = AVERROR(ENOMEM);
7933 goto finish;
7934 }
7935 4 info->num_key_ids = i + 1;
7936
7937
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
7938 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
7939 goto finish;
7940 }
7941 }
7942
7943
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pb->eof_reached) {
7944 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
7945 ret = AVERROR_INVALIDDATA;
7946 goto finish;
7947 }
7948 }
7949
7950 4 extra_data_size = avio_rb32(pb);
7951 4 extra_data = av_malloc(extra_data_size);
7952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!extra_data) {
7953 ret = AVERROR(ENOMEM);
7954 goto finish;
7955 }
7956 4 ret = avio_read(pb, extra_data, extra_data_size);
7957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != extra_data_size) {
7958 av_free(extra_data);
7959
7960 if (ret >= 0)
7961 ret = AVERROR_INVALIDDATA;
7962 goto finish;
7963 }
7964
7965 4 av_freep(&info->data); // malloc(0) may still allocate something.
7966 4 info->data = extra_data;
7967 4 info->data_size = extra_data_size;
7968
7969 // If there is existing initialization data, append to the list.
7970 4 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
7971 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
7972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (old_side_data) {
7973 old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
7974 if (old_init_info) {
7975 // Append to the end of the list.
7976 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
7977 if (!cur->next) {
7978 cur->next = info;
7979 break;
7980 }
7981 }
7982 info = old_init_info;
7983 } else {
7984 // Assume existing side-data will be valid, so the only error we could get is OOM.
7985 ret = AVERROR(ENOMEM);
7986 goto finish;
7987 }
7988 }
7989
7990 4 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
7991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!side_data) {
7992 ret = AVERROR(ENOMEM);
7993 goto finish;
7994 }
7995
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
7996 4 &st->codecpar->nb_coded_side_data,
7997 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
7998 side_data, side_data_size, 0))
7999 av_free(side_data);
8000
8001 4 finish:
8002 4 av_encryption_init_info_free(info);
8003 4 return ret;
8004 }
8005
8006 6 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8007 {
8008 AVStream *st;
8009 MOVStreamContext *sc;
8010
8011
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (c->fc->nb_streams < 1)
8012 return 0;
8013 6 st = c->fc->streams[c->fc->nb_streams-1];
8014 6 sc = st->priv_data;
8015
8016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (sc->pseudo_stream_id != 0) {
8017 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
8018 return AVERROR_PATCHWELCOME;
8019 }
8020
8021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 8)
8022 return AVERROR_INVALIDDATA;
8023
8024 6 avio_rb32(pb); /* version and flags */
8025
8026
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (!sc->cenc.default_encrypted_sample) {
8027 6 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8028
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc->cenc.default_encrypted_sample) {
8029 return AVERROR(ENOMEM);
8030 }
8031 }
8032
8033 6 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
8034 6 return 0;
8035 }
8036
8037 6 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8038 {
8039 AVStream *st;
8040 MOVStreamContext *sc;
8041 unsigned int version, pattern, is_protected, iv_size;
8042
8043
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (c->fc->nb_streams < 1)
8044 return 0;
8045 6 st = c->fc->streams[c->fc->nb_streams-1];
8046 6 sc = st->priv_data;
8047
8048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (sc->pseudo_stream_id != 0) {
8049 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
8050 return AVERROR_PATCHWELCOME;
8051 }
8052
8053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc->cenc.default_encrypted_sample) {
8054 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8055 if (!sc->cenc.default_encrypted_sample) {
8056 return AVERROR(ENOMEM);
8057 }
8058 }
8059
8060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 20)
8061 return AVERROR_INVALIDDATA;
8062
8063 6 version = avio_r8(pb); /* version */
8064 6 avio_rb24(pb); /* flags */
8065
8066 6 avio_r8(pb); /* reserved */
8067 6 pattern = avio_r8(pb);
8068
8069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version > 0) {
8070 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
8071 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
8072 }
8073
8074 6 is_protected = avio_r8(pb);
8075
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) {
8076 // The whole stream should be by-default encrypted.
8077 6 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
8078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc->cenc.encryption_index)
8079 return AVERROR(ENOMEM);
8080 }
8081 6 sc->cenc.per_sample_iv_size = avio_r8(pb);
8082
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 &&
8083 sc->cenc.per_sample_iv_size != 16) {
8084 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
8085 return AVERROR_INVALIDDATA;
8086 }
8087
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) {
8088 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
8089 return AVERROR_INVALIDDATA;
8090 }
8091
8092
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) {
8093 2 iv_size = avio_r8(pb);
8094
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) {
8095 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
8096 return AVERROR_INVALIDDATA;
8097 }
8098
8099
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) {
8100 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
8101 return AVERROR_INVALIDDATA;
8102 }
8103 }
8104
8105 6 return 0;
8106 }
8107
8108 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8109 {
8110 AVStream *st;
8111 int last, type, size, ret;
8112 uint8_t buf[4];
8113
8114 if (c->fc->nb_streams < 1)
8115 return 0;
8116 st = c->fc->streams[c->fc->nb_streams-1];
8117
8118 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
8119 return AVERROR_INVALIDDATA;
8120
8121 /* Check FlacSpecificBox version. */
8122 if (avio_r8(pb) != 0)
8123 return AVERROR_INVALIDDATA;
8124
8125 avio_rb24(pb); /* Flags */
8126
8127 if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
8128 av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
8129 return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
8130 }
8131 flac_parse_block_header(buf, &last, &type, &size);
8132
8133 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
8134 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
8135 return AVERROR_INVALIDDATA;
8136 }
8137
8138 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
8139 if (ret < 0)
8140 return ret;
8141
8142 if (!last)
8143 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
8144
8145 return 0;
8146 }
8147
8148 6 static int get_key_from_kid(uint8_t* out, int len, MOVContext *c, AVEncryptionInfo *sample) {
8149 AVDictionaryEntry *key_entry_hex;
8150 char kid_hex[16*2+1];
8151
8152
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) {
8153 av_log(c->fc, AV_LOG_ERROR, "invalid default decryption key length: got %d, expected %d\n", c->decryption_default_key_len, len);
8154 return -1;
8155 }
8156
8157
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (!c->decryption_keys) {
8158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 av_assert0(c->decryption_default_key);
8159 3 memcpy(out, c->decryption_default_key, len);
8160 3 return 0;
8161 }
8162
8163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sample->key_id_size != 16) {
8164 av_log(c->fc, AV_LOG_ERROR, "invalid key ID size: got %u, expected 16\n", sample->key_id_size);
8165 return -1;
8166 }
8167
8168 3 ff_data_to_hex(kid_hex, sample->key_id, 16, 1);
8169 3 key_entry_hex = av_dict_get(c->decryption_keys, kid_hex, NULL, AV_DICT_DONT_STRDUP_KEY|AV_DICT_DONT_STRDUP_VAL);
8170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!key_entry_hex) {
8171 if (!c->decryption_default_key) {
8172 av_log(c->fc, AV_LOG_ERROR, "unable to find KID %s\n", kid_hex);
8173 return -1;
8174 }
8175 memcpy(out, c->decryption_default_key, len);
8176 return 0;
8177 }
8178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (strlen(key_entry_hex->value) != len*2) {
8179 return -1;
8180 }
8181 3 ff_hex_to_data(out, key_entry_hex->value);
8182 3 return 0;
8183 }
8184
8185 292 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8186 {
8187 int i, ret;
8188 int bytes_of_protected_data;
8189 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8190
8191
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 286 times.
292 if (!sc->cenc.aes_ctr) {
8192 6 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0) {
8194 return ret;
8195 }
8196
8197 /* initialize the cipher */
8198 6 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc->cenc.aes_ctr) {
8200 return AVERROR(ENOMEM);
8201 }
8202
8203 6 ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0) {
8205 return ret;
8206 }
8207 }
8208
8209 292 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8210
8211
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 196 times.
292 if (!sample->subsample_count) {
8212 /* decrypt the whole packet */
8213 96 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8214 96 return 0;
8215 }
8216
8217
2/2
✓ Branch 0 taken 196 times.
✓ Branch 1 taken 196 times.
392 for (i = 0; i < sample->subsample_count; i++) {
8218
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) {
8219 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8220 return AVERROR_INVALIDDATA;
8221 }
8222
8223 /* skip the clear bytes */
8224 196 input += sample->subsamples[i].bytes_of_clear_data;
8225 196 size -= sample->subsamples[i].bytes_of_clear_data;
8226
8227 /* decrypt the encrypted bytes */
8228
8229 196 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
8230 196 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
8231
8232 196 input += bytes_of_protected_data;
8233 196 size -= bytes_of_protected_data;
8234 }
8235
8236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 if (size > 0) {
8237 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8238 return AVERROR_INVALIDDATA;
8239 }
8240
8241 196 return 0;
8242 }
8243
8244 static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8245 {
8246 int i, ret;
8247 int num_of_encrypted_blocks;
8248 uint8_t iv[16];
8249 uint8_t decryption_key[16];
8250
8251 if (!sc->cenc.aes_ctx) {
8252 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8253 if (ret < 0) {
8254 return ret;
8255 }
8256
8257 /* initialize the cipher */
8258 sc->cenc.aes_ctx = av_aes_alloc();
8259 if (!sc->cenc.aes_ctx) {
8260 return AVERROR(ENOMEM);
8261 }
8262
8263 ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8264 if (ret < 0) {
8265 return ret;
8266 }
8267 }
8268
8269 memcpy(iv, sample->iv, 16);
8270
8271 /* whole-block full sample encryption */
8272 if (!sample->subsample_count) {
8273 /* decrypt the whole packet */
8274 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8275 return 0;
8276 }
8277
8278 for (i = 0; i < sample->subsample_count; i++) {
8279 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8280 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8281 return AVERROR_INVALIDDATA;
8282 }
8283
8284 if (sample->subsamples[i].bytes_of_protected_data % 16) {
8285 av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8286 return AVERROR_INVALIDDATA;
8287 }
8288
8289 /* skip the clear bytes */
8290 input += sample->subsamples[i].bytes_of_clear_data;
8291 size -= sample->subsamples[i].bytes_of_clear_data;
8292
8293 /* decrypt the encrypted bytes */
8294 num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8295 if (num_of_encrypted_blocks > 0) {
8296 av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8297 }
8298 input += sample->subsamples[i].bytes_of_protected_data;
8299 size -= sample->subsamples[i].bytes_of_protected_data;
8300 }
8301
8302 if (size > 0) {
8303 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8304 return AVERROR_INVALIDDATA;
8305 }
8306
8307 return 0;
8308 }
8309
8310 static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8311 {
8312 int i, ret, rem_bytes;
8313 uint8_t *data;
8314 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8315
8316 if (!sc->cenc.aes_ctr) {
8317 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8318 if (ret < 0) {
8319 return ret;
8320 }
8321
8322 /* initialize the cipher */
8323 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8324 if (!sc->cenc.aes_ctr) {
8325 return AVERROR(ENOMEM);
8326 }
8327
8328 ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8329 if (ret < 0) {
8330 return ret;
8331 }
8332 }
8333
8334 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8335
8336 /* whole-block full sample encryption */
8337 if (!sample->subsample_count) {
8338 /* decrypt the whole packet */
8339 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8340 return 0;
8341 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8342 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8343 return AVERROR_INVALIDDATA;
8344 }
8345
8346 for (i = 0; i < sample->subsample_count; i++) {
8347 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8348 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8349 return AVERROR_INVALIDDATA;
8350 }
8351
8352 /* skip the clear bytes */
8353 input += sample->subsamples[i].bytes_of_clear_data;
8354 size -= sample->subsamples[i].bytes_of_clear_data;
8355
8356 /* decrypt the encrypted bytes */
8357 data = input;
8358 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8359 while (rem_bytes > 0) {
8360 if (rem_bytes < 16*sample->crypt_byte_block) {
8361 break;
8362 }
8363 av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8364 data += 16*sample->crypt_byte_block;
8365 rem_bytes -= 16*sample->crypt_byte_block;
8366 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8367 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8368 }
8369 input += sample->subsamples[i].bytes_of_protected_data;
8370 size -= sample->subsamples[i].bytes_of_protected_data;
8371 }
8372
8373 if (size > 0) {
8374 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8375 return AVERROR_INVALIDDATA;
8376 }
8377
8378 return 0;
8379 }
8380
8381 static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8382 {
8383 int i, ret, rem_bytes;
8384 uint8_t iv[16];
8385 uint8_t *data;
8386 uint8_t decryption_key[16];
8387
8388 if (!sc->cenc.aes_ctx) {
8389 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8390 if (ret < 0) {
8391 return ret;
8392 }
8393
8394 /* initialize the cipher */
8395 sc->cenc.aes_ctx = av_aes_alloc();
8396 if (!sc->cenc.aes_ctx) {
8397 return AVERROR(ENOMEM);
8398 }
8399
8400 ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8401 if (ret < 0) {
8402 return ret;
8403 }
8404 }
8405
8406 /* whole-block full sample encryption */
8407 if (!sample->subsample_count) {
8408 /* decrypt the whole packet */
8409 memcpy(iv, sample->iv, 16);
8410 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8411 return 0;
8412 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8413 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8414 return AVERROR_INVALIDDATA;
8415 }
8416
8417 for (i = 0; i < sample->subsample_count; i++) {
8418 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8419 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8420 return AVERROR_INVALIDDATA;
8421 }
8422
8423 /* skip the clear bytes */
8424 input += sample->subsamples[i].bytes_of_clear_data;
8425 size -= sample->subsamples[i].bytes_of_clear_data;
8426
8427 /* decrypt the encrypted bytes */
8428 memcpy(iv, sample->iv, 16);
8429 data = input;
8430 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8431 while (rem_bytes > 0) {
8432 if (rem_bytes < 16*sample->crypt_byte_block) {
8433 break;
8434 }
8435 av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8436 data += 16*sample->crypt_byte_block;
8437 rem_bytes -= 16*sample->crypt_byte_block;
8438 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8439 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8440 }
8441 input += sample->subsamples[i].bytes_of_protected_data;
8442 size -= sample->subsamples[i].bytes_of_protected_data;
8443 }
8444
8445 if (size > 0) {
8446 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8447 return AVERROR_INVALIDDATA;
8448 }
8449
8450 return 0;
8451 }
8452
8453 292 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8454 {
8455
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) {
8456 292 return cenc_scheme_decrypt(c, sc, sample, input, size);
8457 } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8458 return cbc1_scheme_decrypt(c, sc, sample, input, size);
8459 } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8460 return cens_scheme_decrypt(c, sc, sample, input, size);
8461 } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8462 return cbcs_scheme_decrypt(c, sc, sample, input, size);
8463 } else {
8464 av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8465 return AVERROR_INVALIDDATA;
8466 }
8467 }
8468
8469 97254 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8470 {
8471 97254 int current = frag_index->current;
8472
8473
2/2
✓ Branch 0 taken 96277 times.
✓ Branch 1 taken 977 times.
97254 if (!frag_index->nb_items)
8474 96277 return NULL;
8475
8476 // Check frag_index->current is the right one for pkt. It can out of sync.
8477
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) {
8478
2/2
✓ Branch 0 taken 951 times.
✓ Branch 1 taken 26 times.
977 if (frag_index->item[current].moof_offset < pkt->pos &&
8479
2/2
✓ Branch 0 taken 609 times.
✓ Branch 1 taken 342 times.
951 (current + 1 == frag_index->nb_items ||
8480
2/2
✓ Branch 0 taken 534 times.
✓ Branch 1 taken 75 times.
609 frag_index->item[current + 1].moof_offset > pkt->pos))
8481 876 return get_frag_stream_info(frag_index, current, id);
8482 }
8483
8484
8485
2/2
✓ Branch 0 taken 4553 times.
✓ Branch 1 taken 8 times.
4561 for (int i = 0; i < frag_index->nb_items; i++) {
8486
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 4460 times.
4553 if (frag_index->item[i].moof_offset > pkt->pos)
8487 93 break;
8488 4460 current = i;
8489 }
8490 101 frag_index->current = current;
8491 101 return get_frag_stream_info(frag_index, current, id);
8492 }
8493
8494 97254 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8495 {
8496 MOVFragmentStreamInfo *frag_stream_info;
8497 MOVEncryptionIndex *encryption_index;
8498 AVEncryptionInfo *encrypted_sample;
8499 int encrypted_index, ret;
8500
8501 97254 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8502 97254 encrypted_index = current_index;
8503 97254 encryption_index = NULL;
8504
2/2
✓ Branch 0 taken 977 times.
✓ Branch 1 taken 96277 times.
97254 if (frag_stream_info) {
8505 // Note this only supports encryption info in the first sample descriptor.
8506
2/2
✓ Branch 0 taken 929 times.
✓ Branch 1 taken 48 times.
977 if (frag_stream_info->stsd_id == 1) {
8507
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 881 times.
929 if (frag_stream_info->encryption_index) {
8508 48 encrypted_index = current_index - frag_stream_info->index_base;
8509 48 encryption_index = frag_stream_info->encryption_index;
8510 } else {
8511 881 encryption_index = sc->cenc.encryption_index;
8512 }
8513 }
8514 } else {
8515 96277 encryption_index = sc->cenc.encryption_index;
8516 }
8517
8518
2/2
✓ Branch 0 taken 292 times.
✓ Branch 1 taken 96962 times.
97254 if (encryption_index) {
8519
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 244 times.
292 if (encryption_index->auxiliary_info_sample_count &&
8520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8521 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8522 return AVERROR_INVALIDDATA;
8523 }
8524
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 244 times.
292 if (encryption_index->auxiliary_offsets_count &&
8525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8526 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8527 return AVERROR_INVALIDDATA;
8528 }
8529
8530 292 encrypted_sample = NULL;
8531
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 196 times.
292 if (!encryption_index->nb_encrypted_samples) {
8532 // Full-sample encryption with default settings.
8533 96 encrypted_sample = sc->cenc.default_encrypted_sample;
8534
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) {
8535 // Per-sample setting override.
8536 196 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 if (!encrypted_sample) {
8538 encrypted_sample = sc->cenc.default_encrypted_sample;
8539 }
8540 }
8541
8542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 292 times.
292 if (!encrypted_sample) {
8543 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8544 return AVERROR_INVALIDDATA;
8545 }
8546
8547
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) {
8548 292 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
8549 } else {
8550 size_t size;
8551 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
8552 if (!side_data)
8553 return AVERROR(ENOMEM);
8554 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
8555 if (ret < 0)
8556 av_free(side_data);
8557 return ret;
8558 }
8559 }
8560
8561 96962 return 0;
8562 }
8563
8564 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8565 {
8566 const int OPUS_SEEK_PREROLL_MS = 80;
8567 int ret;
8568 AVStream *st;
8569 size_t size;
8570 uint16_t pre_skip;
8571
8572 if (c->fc->nb_streams < 1)
8573 return 0;
8574 st = c->fc->streams[c->fc->nb_streams-1];
8575
8576 if ((uint64_t)atom.size > (1<<30) || atom.size < 11 || st->codecpar->extradata)
8577 return AVERROR_INVALIDDATA;
8578
8579 /* Check OpusSpecificBox version. */
8580 if (avio_r8(pb) != 0) {
8581 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
8582 return AVERROR_INVALIDDATA;
8583 }
8584
8585 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
8586 size = atom.size + 8;
8587
8588 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
8589 return ret;
8590
8591 AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
8592 AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
8593 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
8594 if ((ret = ffio_read_size(pb, st->codecpar->extradata + 9, size - 9)) < 0) {
8595 av_freep(&st->codecpar->extradata);
8596 st->codecpar->extradata_size = 0;
8597 return ret;
8598 }
8599
8600 /* OpusSpecificBox is stored in big-endian, but OpusHead is
8601 little-endian; aside from the preceding magic and version they're
8602 otherwise currently identical. Data after output gain at offset 16
8603 doesn't need to be bytewapped. */
8604 pre_skip = AV_RB16A(st->codecpar->extradata + 10);
8605 AV_WL16A(st->codecpar->extradata + 10, pre_skip);
8606 AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
8607 AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
8608
8609 st->codecpar->initial_padding = pre_skip;
8610 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
8611 (AVRational){1, 1000},
8612 (AVRational){1, 48000});
8613
8614 return 0;
8615 }
8616
8617 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8618 {
8619 AVStream *st;
8620 unsigned format_info;
8621 int channel_assignment, channel_assignment1, channel_assignment2;
8622 int ratebits;
8623 uint64_t chmask;
8624
8625 if (c->fc->nb_streams < 1)
8626 return 0;
8627 st = c->fc->streams[c->fc->nb_streams-1];
8628
8629 if (atom.size < 10)
8630 return AVERROR_INVALIDDATA;
8631
8632 format_info = avio_rb32(pb);
8633
8634 ratebits = (format_info >> 28) & 0xF;
8635 channel_assignment1 = (format_info >> 15) & 0x1F;
8636 channel_assignment2 = format_info & 0x1FFF;
8637 if (channel_assignment2)
8638 channel_assignment = channel_assignment2;
8639 else
8640 channel_assignment = channel_assignment1;
8641
8642 st->codecpar->frame_size = 40 << (ratebits & 0x7);
8643 st->codecpar->sample_rate = mlp_samplerate(ratebits);
8644
8645 av_channel_layout_uninit(&st->codecpar->ch_layout);
8646 chmask = truehd_layout(channel_assignment);
8647 av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
8648
8649 return 0;
8650 }
8651
8652 4 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8653 {
8654 AVStream *st;
8655 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
8656 int ret;
8657 4 int64_t read_size = atom.size;
8658
8659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8660 return 0;
8661 4 st = c->fc->streams[c->fc->nb_streams-1];
8662
8663 // At most 24 bytes
8664 4 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
8665
8666
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
8667 return ret;
8668
8669 4 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
8670 }
8671
8672 4 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8673 {
8674 AVStream *st;
8675 uint8_t *buf;
8676 int ret, old_size, num_arrays;
8677
8678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8679 return 0;
8680 4 st = c->fc->streams[c->fc->nb_streams-1];
8681
8682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!st->codecpar->extradata_size)
8683 // TODO: handle lhvC when present before hvcC
8684 return 0;
8685
8686
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if (atom.size < 6 || st->codecpar->extradata_size < 23 ||
8687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 atom.size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
8688 return AVERROR_INVALIDDATA;
8689 }
8690
8691 4 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
8692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!buf)
8693 return AVERROR(ENOMEM);
8694 4 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8695
8696 4 ret = ffio_read_size(pb, buf, atom.size);
8697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
8698 av_free(buf);
8699 av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
8700 return 0;
8701 }
8702
8703 4 num_arrays = buf[5];
8704 4 old_size = st->codecpar->extradata_size;
8705 4 atom.size -= 8 /* account for mov_realloc_extradata offsetting */
8706 + 6 /* lhvC bytes before the arrays*/;
8707
8708 4 ret = mov_realloc_extradata(st->codecpar, atom);
8709
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
8710 av_free(buf);
8711 return ret;
8712 }
8713
8714 4 st->codecpar->extradata[22] += num_arrays;
8715 4 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
8716
8717 4 st->disposition |= AV_DISPOSITION_MULTILAYER;
8718
8719 4 av_free(buf);
8720 4 return 0;
8721 }
8722
8723 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8724 {
8725 4 AVFormatContext *ctx = c->fc;
8726 4 AVStream *st = NULL;
8727 AVBPrint scheme_buf, value_buf;
8728 4 int64_t scheme_str_len = 0, value_str_len = 0;
8729 4 int version, flags, ret = AVERROR_BUG;
8730 4 int64_t size = atom.size;
8731
8732
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
8733 // 4 bytes for version + flags, 2x 1 byte for null
8734 return AVERROR_INVALIDDATA;
8735
8736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8737 return 0;
8738 4 st = c->fc->streams[c->fc->nb_streams-1];
8739
8740 4 version = avio_r8(pb);
8741 4 flags = avio_rb24(pb);
8742 4 size -= 4;
8743
8744
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) {
8745 av_log(ctx, AV_LOG_ERROR,
8746 "Unsupported 'kind' box with version %d, flags: %x",
8747 version, flags);
8748 return AVERROR_INVALIDDATA;
8749 }
8750
8751 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8752 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8753
8754
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,
8755 size)) < 0) {
8756 ret = scheme_str_len;
8757 goto cleanup;
8758 }
8759
8760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
8761 // we need to have another string, even if nullptr.
8762 // we check with + 1 since we expect that if size was not hit,
8763 // an additional null was read.
8764 ret = AVERROR_INVALIDDATA;
8765 goto cleanup;
8766 }
8767
8768 4 size -= scheme_str_len + 1;
8769
8770
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,
8771 size)) < 0) {
8772 ret = value_str_len;
8773 goto cleanup;
8774 }
8775
8776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
8777 // in case of no trailing null, box is not valid.
8778 ret = AVERROR_INVALIDDATA;
8779 goto cleanup;
8780 }
8781
8782 4 av_log(ctx, AV_LOG_TRACE,
8783 "%s stream %d KindBox(scheme: %s, value: %s)\n",
8784 4 av_get_media_type_string(st->codecpar->codec_type),
8785 st->index,
8786 scheme_buf.str, value_buf.str);
8787
8788
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++) {
8789 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
8790
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
8791 continue;
8792
8793
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
8794 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
8795
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
8796 16 continue;
8797
8798 4 st->disposition |= value_map.disposition;
8799 }
8800 }
8801
8802 4 ret = 0;
8803
8804 4 cleanup:
8805
8806 4 av_bprint_finalize(&scheme_buf, NULL);
8807 4 av_bprint_finalize(&value_buf, NULL);
8808
8809 4 return ret;
8810 }
8811
8812 static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8813 {
8814 AVStream *st;
8815 AVChannelLayout ch_layout = { 0 };
8816 int ret, i, version, type;
8817 int ambisonic_order, channel_order, normalization, channel_count;
8818 int ambi_channels, non_diegetic_channels;
8819
8820 if (c->fc->nb_streams < 1)
8821 return 0;
8822
8823 st = c->fc->streams[c->fc->nb_streams - 1];
8824
8825 if (atom.size < 16) {
8826 av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
8827 return AVERROR_INVALIDDATA;
8828 }
8829
8830 version = avio_r8(pb);
8831 if (version) {
8832 av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
8833 return 0;
8834 }
8835
8836 type = avio_r8(pb);
8837 if (type & 0x7f) {
8838 av_log(c->fc, AV_LOG_WARNING,
8839 "Unsupported ambisonic type %d\n", type & 0x7f);
8840 return 0;
8841 }
8842 non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
8843
8844 ambisonic_order = avio_rb32(pb);
8845
8846 channel_order = avio_r8(pb);
8847 if (channel_order) {
8848 av_log(c->fc, AV_LOG_WARNING,
8849 "Unsupported channel_order %d\n", channel_order);
8850 return 0;
8851 }
8852
8853 normalization = avio_r8(pb);
8854 if (normalization) {
8855 av_log(c->fc, AV_LOG_WARNING,
8856 "Unsupported normalization %d\n", normalization);
8857 return 0;
8858 }
8859
8860 channel_count = avio_rb32(pb);
8861 if (ambisonic_order < 0 || ambisonic_order > 31 ||
8862 channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
8863 non_diegetic_channels)) {
8864 av_log(c->fc, AV_LOG_ERROR,
8865 "Invalid number of channels (%d / %d)\n",
8866 channel_count, ambisonic_order);
8867 return 0;
8868 }
8869 ambi_channels = channel_count - non_diegetic_channels;
8870
8871 ret = av_channel_layout_custom_init(&ch_layout, channel_count);
8872 if (ret < 0)
8873 return 0;
8874
8875 for (i = 0; i < channel_count; i++) {
8876 unsigned channel = avio_rb32(pb);
8877
8878 if (channel >= channel_count) {
8879 av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
8880 channel, ambisonic_order);
8881 av_channel_layout_uninit(&ch_layout);
8882 return 0;
8883 }
8884 if (channel >= ambi_channels)
8885 ch_layout.u.map[i].id = channel - ambi_channels;
8886 else
8887 ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
8888 }
8889
8890 ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
8891 if (ret < 0) {
8892 av_channel_layout_uninit(&ch_layout);
8893 return 0;
8894 }
8895
8896 av_channel_layout_uninit(&st->codecpar->ch_layout);
8897 st->codecpar->ch_layout = ch_layout;
8898
8899 return 0;
8900 }
8901
8902 static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8903 {
8904 AVStream *st;
8905 int version;
8906
8907 if (c->fc->nb_streams < 1)
8908 return 0;
8909
8910 st = c->fc->streams[c->fc->nb_streams - 1];
8911
8912 if (atom.size < 5) {
8913 av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
8914 return AVERROR_INVALIDDATA;
8915 }
8916
8917 version = avio_r8(pb);
8918 if (version) {
8919 av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
8920 return 0;
8921 }
8922
8923 st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
8924
8925 return 0;
8926 }
8927
8928 171 static int rb_size(AVIOContext *pb, int64_t *value, int size)
8929 {
8930
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 160 times.
171 if (size == 0)
8931 11 *value = 0;
8932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 else if (size == 1)
8933 *value = avio_r8(pb);
8934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 else if (size == 2)
8935 *value = avio_rb16(pb);
8936
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 else if (size == 4)
8937 160 *value = avio_rb32(pb);
8938 else if (size == 8) {
8939 *value = avio_rb64(pb);
8940 if (*value < 0)
8941 return -1;
8942 } else
8943 return -1;
8944 171 return size;
8945 }
8946
8947 18 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8948 {
8949 18 avio_rb32(pb); // version & flags.
8950 18 c->primary_item_id = avio_rb16(pb);
8951 18 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
8952 18 return atom.size;
8953 }
8954
8955 9 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8956 {
8957 9 c->idat_offset = avio_tell(pb);
8958 9 return 0;
8959 }
8960
8961 18 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8962 {
8963 HEIFItem **heif_item;
8964 int version, offset_size, length_size, base_offset_size, index_size;
8965 int item_count, extent_count;
8966 int64_t base_offset, extent_offset, extent_length;
8967 uint8_t value;
8968
8969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->found_iloc) {
8970 av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
8971 return 0;
8972 }
8973
8974 18 version = avio_r8(pb);
8975 18 avio_rb24(pb); // flags.
8976
8977 18 value = avio_r8(pb);
8978 18 offset_size = (value >> 4) & 0xF;
8979 18 length_size = value & 0xF;
8980 18 value = avio_r8(pb);
8981 18 base_offset_size = (value >> 4) & 0xF;
8982
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 7 times.
18 index_size = !version ? 0 : (value & 0xF);
8983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (index_size) {
8984 avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
8985 return AVERROR_PATCHWELCOME;
8986 }
8987
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8988
8989 18 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
8990
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!heif_item)
8991 return AVERROR(ENOMEM);
8992 18 c->heif_item = heif_item;
8993
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (item_count > c->nb_heif_item)
8994 18 memset(&c->heif_item[c->nb_heif_item], 0,
8995 18 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
8996 18 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
8997
8998 18 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
8999
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (int i = 0; i < item_count; i++) {
9000 57 HEIFItem *item = NULL;
9001
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9002
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 12 times.
57 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
9003 int j;
9004
9005
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (avio_feof(pb))
9006 return AVERROR_INVALIDDATA;
9007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (offset_type > 1) {
9008 avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
9009 return AVERROR_PATCHWELCOME;
9010 }
9011
9012 57 avio_rb16(pb); // data_reference_index.
9013
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (rb_size(pb, &base_offset, base_offset_size) < 0)
9014 return AVERROR_INVALIDDATA;
9015 57 extent_count = avio_rb16(pb);
9016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (extent_count > 1) {
9017 // For still AVIF images, we only support one extent item.
9018 avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
9019 return AVERROR_PATCHWELCOME;
9020 }
9021
9022
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 ||
9023 57 rb_size(pb, &extent_length, length_size) < 0 ||
9024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 base_offset > INT64_MAX - extent_offset)
9025 return AVERROR_INVALIDDATA;
9026
9027
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 for (j = 0; j < c->nb_heif_item; j++) {
9028 140 item = c->heif_item[j];
9029
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 83 times.
140 if (!item)
9030 57 item = c->heif_item[j] = av_mallocz(sizeof(*item));
9031
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
83 else if (item->item_id != item_id)
9032 83 continue;
9033 57 break;
9034 }
9035
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item)
9036 return AVERROR(ENOMEM);
9037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (j == c->nb_heif_item)
9038 return AVERROR_INVALIDDATA;
9039
9040 57 item->item_id = item_id;
9041
9042
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 48 times.
57 if (offset_type == 1)
9043 9 item->is_idat_relative = 1;
9044 57 item->extent_length = extent_length;
9045 57 item->extent_offset = base_offset + extent_offset;
9046 57 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, item->item_id %d, offset_type %d, "
9047 "extent_offset %"PRId64", extent_length %"PRId64"\n",
9048 i, item->item_id, offset_type, item->extent_offset, item->extent_length);
9049 }
9050
9051 18 c->found_iloc = 1;
9052 18 return atom.size;
9053 }
9054
9055 57 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9056 {
9057 57 HEIFItem *item = NULL;
9058 AVBPrint item_name;
9059 57 int64_t size = atom.size;
9060 uint32_t item_type;
9061 int item_id;
9062 int i, version, ret;
9063
9064 57 version = avio_r8(pb);
9065 57 avio_rb24(pb); // flags.
9066 57 size -= 4;
9067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (size < 0)
9068 return AVERROR_INVALIDDATA;
9069
9070
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (version < 2) {
9071 avpriv_report_missing_feature(c->fc, "infe version < 2");
9072 avio_skip(pb, size);
9073 return 1;
9074 }
9075
9076
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
9077 57 avio_rb16(pb); // item_protection_index
9078 57 item_type = avio_rl32(pb);
9079 57 size -= 8;
9080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (size < 1)
9081 return AVERROR_INVALIDDATA;
9082
9083 57 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
9084 57 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
9085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (ret < 0) {
9086 av_bprint_finalize(&item_name, NULL);
9087 return ret;
9088 }
9089
9090 57 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
9091 57 item_id, av_fourcc2str(item_type), item_name.str);
9092
9093 57 size -= ret + 1;
9094
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 55 times.
57 if (size > 0)
9095 2 avio_skip(pb, size);
9096
9097
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 for (i = 0; i < c->nb_heif_item; i++) {
9098 140 item = c->heif_item[i];
9099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (!item)
9100 item = c->heif_item[i] = av_mallocz(sizeof(*item));
9101
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 57 times.
140 else if (item->item_id != item_id)
9102 83 continue;
9103 57 break;
9104 }
9105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item) {
9106 av_bprint_finalize(&item_name, NULL);
9107 return AVERROR(ENOMEM);
9108 }
9109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (i == c->nb_heif_item) {
9110 av_bprint_finalize(&item_name, NULL);
9111 return AVERROR_INVALIDDATA;
9112 }
9113
9114 57 av_freep(&item->name);
9115
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 1 times.
57 av_bprint_finalize(&item_name, ret ? &item->name : NULL);
9116 57 item->item_id = item_id;
9117 57 item->type = item_type;
9118
9119
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 14 times.
57 switch (item_type) {
9120 43 case MKTAG('a','v','0','1'):
9121 case MKTAG('j','p','e','g'):
9122 case MKTAG('h','v','c','1'):
9123 43 ret = heif_add_stream(c, item);
9124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
9125 return ret;
9126 43 break;
9127 }
9128
9129 57 return 0;
9130 }
9131
9132 18 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9133 {
9134 HEIFItem **heif_item;
9135 int entry_count;
9136 18 int version, got_stream = 0, ret, i;
9137
9138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->found_iinf) {
9139 av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
9140 return 0;
9141 }
9142
9143 18 version = avio_r8(pb);
9144 18 avio_rb24(pb); // flags.
9145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
9146
9147 18 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
9148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!heif_item)
9149 return AVERROR(ENOMEM);
9150 18 c->heif_item = heif_item;
9151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (entry_count > c->nb_heif_item)
9152 memset(&c->heif_item[c->nb_heif_item], 0,
9153 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
9154 18 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
9155
9156
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (i = 0; i < entry_count; i++) {
9157 MOVAtom infe;
9158
9159 57 infe.size = avio_rb32(pb) - 8;
9160 57 infe.type = avio_rl32(pb);
9161
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (avio_feof(pb)) {
9162 ret = AVERROR_INVALIDDATA;
9163 goto fail;
9164 }
9165 57 ret = mov_read_infe(c, pb, infe);
9166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (ret < 0)
9167 goto fail;
9168
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 if (!ret)
9169 57 got_stream = 1;
9170 }
9171
9172 18 c->found_iinf = got_stream;
9173 18 return 0;
9174 fail:
9175 for (; i >= 0; i--) {
9176 HEIFItem *item = c->heif_item[i];
9177
9178 if (!item)
9179 continue;
9180
9181 av_freep(&item->name);
9182 }
9183 return ret;
9184 }
9185
9186 9 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
9187 {
9188 9 HEIFItem *item = NULL;
9189 HEIFGrid *grid;
9190 int entries, i;
9191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9192 9 int ret = 0;
9193
9194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 for (int i = 0; i < c->nb_heif_grid; i++) {
9195 if (c->heif_grid[i].item->item_id == from_item_id) {
9196 av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
9197 "referencing the same Derived Image item\n");
9198 return AVERROR_INVALIDDATA;
9199 }
9200 }
9201
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 for (int i = 0; i < c->nb_heif_item; i++) {
9202
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)
9203 26 continue;
9204 9 item = c->heif_item[i];
9205
9206
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 switch (item->type) {
9207 9 case MKTAG('g','r','i','d'):
9208 case MKTAG('i','o','v','l'):
9209 9 break;
9210 default:
9211 avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
9212 av_fourcc2str(item->type));
9213 return 0;
9214 }
9215 9 break;
9216 }
9217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!item) {
9218 av_log(c->fc, AV_LOG_ERROR, "Missing grid information\n");
9219 return AVERROR_INVALIDDATA;
9220 }
9221
9222 9 entries = avio_rb16(pb);
9223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!entries) {
9224 av_log(c->fc, AV_LOG_ERROR,
9225 "Derived image item references no input images\n");
9226 return AVERROR_INVALIDDATA;
9227 }
9228
9229 9 grid = av_realloc_array(c->heif_grid, c->nb_heif_grid + 1U,
9230 sizeof(*c->heif_grid));
9231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!grid)
9232 return AVERROR(ENOMEM);
9233 9 c->heif_grid = grid;
9234 9 grid = &grid[c->nb_heif_grid];
9235
9236 9 grid->tile_id_list = av_malloc_array(entries, sizeof(*grid->tile_id_list));
9237 9 grid->tile_idx_list = av_calloc(entries, sizeof(*grid->tile_idx_list));
9238 9 grid->tile_item_list = av_calloc(entries, sizeof(*grid->tile_item_list));
9239
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) {
9240 ret = AVERROR(ENOMEM);
9241 goto fail;
9242 }
9243 /* 'to' item ids */
9244
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9 times.
37 for (i = 0; i < entries; i++) {
9245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 grid->tile_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
9246
9247
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if (avio_feof(pb)) {
9248 ret = AVERROR_INVALIDDATA;
9249 goto fail;
9250 }
9251 }
9252
9253 9 grid->nb_tiles = entries;
9254 9 grid->item = item;
9255 9 ++c->nb_heif_grid;
9256
9257 9 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
9258 from_item_id, entries);
9259
9260 9 return 0;
9261 fail:
9262 av_freep(&grid->tile_id_list);
9263 av_freep(&grid->tile_idx_list);
9264 av_freep(&grid->tile_item_list);
9265
9266 return ret;
9267 }
9268
9269 11 static int mov_read_iref_cdsc(MOVContext *c, AVIOContext *pb, uint32_t type, int version)
9270 {
9271 11 HEIFItem *from_item = NULL;
9272 int entries;
9273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9274 11 const HEIFItemRef ref = { type, from_item_id };
9275
9276 11 from_item = get_heif_item(c, from_item_id);
9277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!from_item) {
9278 av_log(c->fc, AV_LOG_ERROR, "Missing stream referenced by thmb item\n");
9279 return AVERROR_INVALIDDATA;
9280 }
9281
9282 11 entries = avio_rb16(pb);
9283 /* 'to' item ids */
9284
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (int i = 0; i < entries; i++) {
9285
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));
9286
9287
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (avio_feof(pb))
9288 return AVERROR_INVALIDDATA;
9289
9290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!item) {
9291 av_log(c->fc, AV_LOG_WARNING, "Missing stream referenced by %s item\n",
9292 av_fourcc2str(type));
9293 continue;
9294 }
9295
9296
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (!av_dynarray2_add((void **)&item->iref_list, &item->nb_iref_list,
9297 sizeof(*item->iref_list), (const uint8_t *)&ref))
9298 return AVERROR(ENOMEM);
9299 }
9300
9301 11 av_log(c->fc, AV_LOG_TRACE, "%s: from_item_id %d, entries %d\n",
9302 11 av_fourcc2str(type), from_item_id, entries);
9303
9304 11 return 0;
9305 }
9306
9307 14 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9308 {
9309 14 int version = avio_r8(pb);
9310 int ret;
9311
9312 14 avio_rb24(pb); // flags
9313 14 atom.size -= 4;
9314
9315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (version > 1) {
9316 av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
9317 return 0;
9318 }
9319
9320
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 14 times.
34 while (atom.size) {
9321 20 uint32_t type, size = avio_rb32(pb);
9322 20 int64_t next = avio_tell(pb);
9323
9324
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)
9325 return AVERROR_INVALIDDATA;
9326
9327 20 next += size - 4;
9328 20 type = avio_rl32(pb);
9329
2/3
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
20 switch (type) {
9330 9 case MKTAG('d','i','m','g'):
9331 9 ret = mov_read_iref_dimg(c, pb, version);
9332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret < 0)
9333 return ret;
9334 20 break;
9335 11 case MKTAG('c','d','s','c'):
9336 case MKTAG('t','h','m','b'):
9337 11 ret = mov_read_iref_cdsc(c, pb, type, version);
9338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0)
9339 return ret;
9340 11 break;
9341 default:
9342 av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
9343 av_fourcc2str(type), size);
9344 }
9345
9346 20 atom.size -= size;
9347 20 avio_seek(pb, next, SEEK_SET);
9348 }
9349 14 return 0;
9350 }
9351
9352 52 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9353 {
9354 HEIFItem *item;
9355 uint32_t width, height;
9356
9357 52 avio_r8(pb); /* version */
9358 52 avio_rb24(pb); /* flags */
9359 52 width = avio_rb32(pb);
9360 52 height = avio_rb32(pb);
9361
9362 52 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %"PRIu32", height %"PRIu32"\n",
9363 c->cur_item_id, width, height);
9364
9365 52 item = get_heif_item(c, c->cur_item_id);
9366
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 if (item) {
9367 52 item->width = width;
9368 52 item->height = height;
9369 }
9370
9371 52 return 0;
9372 }
9373
9374 8 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9375 {
9376 HEIFItem *item;
9377 int angle;
9378
9379 8 angle = avio_r8(pb) & 0x3;
9380
9381 8 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
9382 c->cur_item_id, angle);
9383
9384 8 item = get_heif_item(c, c->cur_item_id);
9385
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (item) {
9386 // angle * 90 specifies the angle (in anti-clockwise direction)
9387 // in units of degrees.
9388 8 item->rotation = angle * 90;
9389 }
9390
9391 8 return 0;
9392 }
9393
9394 6 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9395 {
9396 HEIFItem *item;
9397 int axis;
9398
9399 6 axis = avio_r8(pb) & 0x1;
9400
9401 6 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
9402 c->cur_item_id, axis);
9403
9404 6 item = get_heif_item(c, c->cur_item_id);
9405
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
9406 6 item->hflip = axis;
9407 6 item->vflip = !axis;
9408 }
9409
9410 6 return 0;
9411 }
9412
9413 18 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9414 {
9415 typedef struct MOVAtoms {
9416 FFIOContext b;
9417 uint32_t type;
9418 int64_t size;
9419 uint8_t *data;
9420 } MOVAtoms;
9421 18 MOVAtoms *atoms = NULL;
9422 MOVAtom a;
9423 unsigned count;
9424 18 int nb_atoms = 0;
9425 int version, flags;
9426 int ret;
9427
9428 18 a.size = avio_rb32(pb);
9429 18 a.type = avio_rl32(pb);
9430
9431
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'))
9432 return AVERROR_INVALIDDATA;
9433
9434 18 a.size -= 8;
9435
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 while (a.size >= 8) {
9436 80 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
9437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!ref) {
9438 ret = AVERROR(ENOMEM);
9439 goto fail;
9440 }
9441 80 ref->data = NULL;
9442 80 ref->size = avio_rb32(pb);
9443 80 ref->type = avio_rl32(pb);
9444
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)
9445 break;
9446 80 ref->data = av_malloc(ref->size);
9447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!ref->data) {
9448 ret = AVERROR_INVALIDDATA;
9449 goto fail;
9450 }
9451 80 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
9452 80 avio_seek(pb, -8, SEEK_CUR);
9453
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
80 if (avio_read(pb, ref->data, ref->size) != ref->size) {
9454 ret = AVERROR_INVALIDDATA;
9455 goto fail;
9456 }
9457 80 ffio_init_read_context(&ref->b, ref->data, ref->size);
9458 80 a.size -= ref->size;
9459 }
9460
9461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (a.size) {
9462 ret = AVERROR_INVALIDDATA;
9463 goto fail;
9464 }
9465
9466 18 a.size = avio_rb32(pb);
9467 18 a.type = avio_rl32(pb);
9468
9469
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')) {
9470 ret = AVERROR_INVALIDDATA;
9471 goto fail;
9472 }
9473
9474 18 version = avio_r8(pb);
9475 18 flags = avio_rb24(pb);
9476 18 count = avio_rb32(pb);
9477
9478
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 18 times.
70 for (int i = 0; i < count; i++) {
9479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9480 52 int assoc_count = avio_r8(pb);
9481
9482
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
52 if (avio_feof(pb)) {
9483 ret = AVERROR_INVALIDDATA;
9484 goto fail;
9485 }
9486
9487
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 52 times.
177 for (int j = 0; j < assoc_count; j++) {
9488 MOVAtoms *ref;
9489 125 int index = avio_r8(pb) & 0x7f;
9490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 if (flags & 1) {
9491 index <<= 8;
9492 index |= avio_r8(pb);
9493 }
9494
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) {
9495 ret = AVERROR_INVALIDDATA;
9496 goto fail;
9497 }
9498 125 ref = &atoms[--index];
9499
9500 125 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
9501 125 index + 1, item_id, av_fourcc2str(ref->type));
9502
9503 125 c->cur_item_id = item_id;
9504
9505 125 ret = mov_read_default(c, &ref->b.pub,
9506 125 (MOVAtom) { .size = ref->size,
9507 .type = MKTAG('i','p','c','o') });
9508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 if (ret < 0)
9509 goto fail;
9510 125 ffio_init_read_context(&ref->b, ref->data, ref->size);
9511 }
9512 }
9513
9514 18 ret = 0;
9515 18 fail:
9516 18 c->cur_item_id = -1;
9517
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 for (int i = 0; i < nb_atoms; i++)
9518 80 av_free(atoms[i].data);
9519 18 av_free(atoms);
9520
9521 18 return ret;
9522 }
9523
9524 static const MOVParseTableEntry mov_default_parse_table[] = {
9525 { MKTAG('A','C','L','R'), mov_read_aclr },
9526 { MKTAG('A','P','R','G'), mov_read_avid },
9527 { MKTAG('A','A','L','P'), mov_read_avid },
9528 { MKTAG('A','R','E','S'), mov_read_ares },
9529 { MKTAG('a','v','s','s'), mov_read_avss },
9530 { MKTAG('a','v','1','C'), mov_read_glbl },
9531 { MKTAG('c','h','p','l'), mov_read_chpl },
9532 { MKTAG('c','o','6','4'), mov_read_stco },
9533 { MKTAG('c','o','l','r'), mov_read_colr },
9534 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
9535 { MKTAG('d','i','n','f'), mov_read_default },
9536 { MKTAG('D','p','x','E'), mov_read_dpxe },
9537 { MKTAG('d','r','e','f'), mov_read_dref },
9538 { MKTAG('e','d','t','s'), mov_read_default },
9539 { MKTAG('e','l','s','t'), mov_read_elst },
9540 { MKTAG('e','n','d','a'), mov_read_enda },
9541 { MKTAG('f','i','e','l'), mov_read_fiel },
9542 { MKTAG('a','d','r','m'), mov_read_adrm },
9543 { MKTAG('f','t','y','p'), mov_read_ftyp },
9544 { MKTAG('g','l','b','l'), mov_read_glbl },
9545 { MKTAG('h','d','l','r'), mov_read_hdlr },
9546 { MKTAG('i','l','s','t'), mov_read_ilst },
9547 { MKTAG('j','p','2','h'), mov_read_jp2h },
9548 { MKTAG('m','d','a','t'), mov_read_mdat },
9549 { MKTAG('m','d','h','d'), mov_read_mdhd },
9550 { MKTAG('m','d','i','a'), mov_read_default },
9551 { MKTAG('m','e','t','a'), mov_read_meta },
9552 { MKTAG('m','i','n','f'), mov_read_default },
9553 { MKTAG('m','o','o','f'), mov_read_moof },
9554 { MKTAG('m','o','o','v'), mov_read_moov },
9555 { MKTAG('m','v','e','x'), mov_read_default },
9556 { MKTAG('m','v','h','d'), mov_read_mvhd },
9557 { MKTAG('S','M','I',' '), mov_read_svq3 },
9558 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
9559 { MKTAG('a','v','c','C'), mov_read_glbl },
9560 { MKTAG('p','a','s','p'), mov_read_pasp },
9561 { MKTAG('c','l','a','p'), mov_read_clap },
9562 { MKTAG('s','b','a','s'), mov_read_sbas },
9563 { MKTAG('s','i','d','x'), mov_read_sidx },
9564 { MKTAG('s','t','b','l'), mov_read_default },
9565 { MKTAG('s','t','c','o'), mov_read_stco },
9566 { MKTAG('s','t','p','s'), mov_read_stps },
9567 { MKTAG('s','t','r','f'), mov_read_strf },
9568 { MKTAG('s','t','s','c'), mov_read_stsc },
9569 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
9570 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
9571 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
9572 { MKTAG('s','t','t','s'), mov_read_stts },
9573 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
9574 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
9575 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
9576 { MKTAG('t','f','d','t'), mov_read_tfdt },
9577 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
9578 { MKTAG('t','r','a','k'), mov_read_trak },
9579 { MKTAG('t','r','a','f'), mov_read_default },
9580 { MKTAG('t','r','e','f'), mov_read_default },
9581 { MKTAG('t','m','c','d'), mov_read_tmcd },
9582 { MKTAG('c','h','a','p'), mov_read_chap },
9583 { MKTAG('t','r','e','x'), mov_read_trex },
9584 { MKTAG('t','r','u','n'), mov_read_trun },
9585 { MKTAG('u','d','t','a'), mov_read_default },
9586 { MKTAG('w','a','v','e'), mov_read_wave },
9587 { MKTAG('e','s','d','s'), mov_read_esds },
9588 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
9589 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
9590 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
9591 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
9592 { MKTAG('w','f','e','x'), mov_read_wfex },
9593 { MKTAG('c','m','o','v'), mov_read_cmov },
9594 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
9595 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
9596 { MKTAG('d','v','c','1'), mov_read_dvc1 },
9597 { MKTAG('s','g','p','d'), mov_read_sgpd },
9598 { MKTAG('s','b','g','p'), mov_read_sbgp },
9599 { MKTAG('h','v','c','C'), mov_read_glbl },
9600 { MKTAG('v','v','c','C'), mov_read_glbl },
9601 { MKTAG('u','u','i','d'), mov_read_uuid },
9602 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
9603 { MKTAG('f','r','e','e'), mov_read_free },
9604 { MKTAG('-','-','-','-'), mov_read_custom },
9605 { MKTAG('s','i','n','f'), mov_read_default },
9606 { MKTAG('f','r','m','a'), mov_read_frma },
9607 { MKTAG('s','e','n','c'), mov_read_senc },
9608 { MKTAG('s','a','i','z'), mov_read_saiz },
9609 { MKTAG('s','a','i','o'), mov_read_saio },
9610 { MKTAG('p','s','s','h'), mov_read_pssh },
9611 { MKTAG('s','c','h','m'), mov_read_schm },
9612 { MKTAG('s','c','h','i'), mov_read_default },
9613 { MKTAG('t','e','n','c'), mov_read_tenc },
9614 { MKTAG('d','f','L','a'), mov_read_dfla },
9615 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
9616 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
9617 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
9618 { MKTAG('h','f','o','v'), mov_read_hfov },
9619 { MKTAG('d','O','p','s'), mov_read_dops },
9620 { MKTAG('d','m','l','p'), mov_read_dmlp },
9621 { MKTAG('S','m','D','m'), mov_read_smdm },
9622 { MKTAG('C','o','L','L'), mov_read_coll },
9623 { MKTAG('v','p','c','C'), mov_read_vpcc },
9624 { MKTAG('m','d','c','v'), mov_read_mdcv },
9625 { MKTAG('c','l','l','i'), mov_read_clli },
9626 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
9627 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
9628 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
9629 { MKTAG('k','i','n','d'), mov_read_kind },
9630 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
9631 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
9632 { MKTAG('i','l','o','c'), mov_read_iloc },
9633 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
9634 { MKTAG('p','i','t','m'), mov_read_pitm },
9635 { MKTAG('e','v','c','C'), mov_read_glbl },
9636 { MKTAG('i','d','a','t'), mov_read_idat },
9637 { MKTAG('i','m','i','r'), mov_read_imir },
9638 { MKTAG('i','r','e','f'), mov_read_iref },
9639 { MKTAG('i','s','p','e'), mov_read_ispe },
9640 { MKTAG('i','r','o','t'), mov_read_irot },
9641 { MKTAG('i','p','r','p'), mov_read_iprp },
9642 { MKTAG('i','i','n','f'), mov_read_iinf },
9643 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
9644 { MKTAG('l','h','v','C'), mov_read_lhvc },
9645 { MKTAG('l','v','c','C'), mov_read_glbl },
9646 { MKTAG('a','p','v','C'), mov_read_glbl },
9647 #if CONFIG_IAMFDEC
9648 { MKTAG('i','a','c','b'), mov_read_iacb },
9649 #endif
9650 { MKTAG('s','r','a','t'), mov_read_srat },
9651 { 0, NULL }
9652 };
9653
9654 6900 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9655 {
9656 6900 int64_t total_size = 0;
9657 MOVAtom a;
9658 int i;
9659
9660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6900 times.
6900 if (c->atom_depth > 10) {
9661 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
9662 return AVERROR_INVALIDDATA;
9663 }
9664 6900 c->atom_depth ++;
9665
9666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6900 times.
6900 if (atom.size < 0)
9667 atom.size = INT64_MAX;
9668
2/2
✓ Branch 0 taken 19794 times.
✓ Branch 1 taken 6393 times.
26187 while (total_size <= atom.size - 8) {
9669 19794 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
9670 19794 a.size = avio_rb32(pb);
9671 19794 a.type = avio_rl32(pb);
9672
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 19787 times.
19794 if (avio_feof(pb))
9673 7 break;
9674
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) ||
9675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19787 times.
19787 a.type == MKTAG('h','o','o','v')) &&
9676 a.size >= 8 &&
9677 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
9678 uint32_t type;
9679 avio_skip(pb, 4);
9680 type = avio_rl32(pb);
9681 if (avio_feof(pb))
9682 break;
9683 avio_seek(pb, -8, SEEK_CUR);
9684 if (type == MKTAG('m','v','h','d') ||
9685 type == MKTAG('c','m','o','v')) {
9686 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
9687 a.type = MKTAG('m','o','o','v');
9688 }
9689 }
9690
2/2
✓ Branch 0 taken 16819 times.
✓ Branch 1 taken 2968 times.
19787 if (atom.type != MKTAG('r','o','o','t') &&
9691
2/2
✓ Branch 0 taken 15334 times.
✓ Branch 1 taken 1485 times.
16819 atom.type != MKTAG('m','o','o','v')) {
9692
1/2
✓ Branch 0 taken 15334 times.
✗ Branch 1 not taken.
15334 if (a.type == MKTAG('t','r','a','k') ||
9693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15334 times.
15334 a.type == MKTAG('m','d','a','t')) {
9694 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
9695 avio_skip(pb, -8);
9696 c->atom_depth --;
9697 500 return 0;
9698 }
9699 }
9700 19787 total_size += 8;
9701
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 */
9702 29 a.size = avio_rb64(pb) - 8;
9703 29 total_size += 8;
9704 }
9705 19787 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
9706 19787 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
9707
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19782 times.
19787 if (a.size == 0) {
9708 5 a.size = atom.size - total_size + 8;
9709 }
9710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19787 times.
19787 if (a.size < 0)
9711 break;
9712 19787 a.size -= 8;
9713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19787 times.
19787 if (a.size < 0)
9714 break;
9715 19787 a.size = FFMIN(a.size, atom.size - total_size);
9716
9717
2/2
✓ Branch 0 taken 916792 times.
✓ Branch 1 taken 2001 times.
918793 for (i = 0; mov_default_parse_table[i].type; i++)
9718
2/2
✓ Branch 0 taken 17786 times.
✓ Branch 1 taken 899006 times.
916792 if (mov_default_parse_table[i].type == a.type) {
9719 17786 parse = mov_default_parse_table[i].parse;
9720 17786 break;
9721 }
9722
9723 // container is user data
9724
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') ||
9725
2/2
✓ Branch 0 taken 301 times.
✓ Branch 1 taken 1521 times.
1822 atom.type == MKTAG('i','l','s','t')))
9726 480 parse = mov_read_udta_string;
9727
9728 // Supports parsing the QuickTime Metadata Keys.
9729 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
9730
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 &&
9731
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 atom.type == MKTAG('m','e','t','a') &&
9732
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 a.type == MKTAG('k','e','y','s') &&
9733
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 c->meta_keys_count == 0) {
9734 11 parse = mov_read_keys;
9735 }
9736
9737
2/2
✓ Branch 0 taken 1510 times.
✓ Branch 1 taken 18277 times.
19787 if (!parse) { /* skip leaf atoms data */
9738 1510 avio_skip(pb, a.size);
9739 } else {
9740 18277 int64_t start_pos = avio_tell(pb);
9741 int64_t left;
9742 18277 int err = parse(c, pb, a);
9743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18277 times.
18277 if (err < 0) {
9744 c->atom_depth --;
9745 return err;
9746 }
9747
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 &&
9748
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) ||
9749 3334 start_pos + a.size == avio_size(pb))) {
9750
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)
9751 15 c->next_root_atom = start_pos + a.size;
9752 500 c->atom_depth --;
9753 500 return 0;
9754 }
9755 17777 left = a.size - avio_tell(pb) + start_pos;
9756
2/2
✓ Branch 0 taken 1494 times.
✓ Branch 1 taken 16283 times.
17777 if (left > 0) /* skip garbage at atom end */
9757 1494 avio_skip(pb, left);
9758
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16281 times.
16283 else if (left < 0) {
9759 2 av_log(c->fc, AV_LOG_WARNING,
9760 "overread end of atom '%s' by %"PRId64" bytes\n",
9761 2 av_fourcc2str(a.type), -left);
9762 2 avio_seek(pb, left, SEEK_CUR);
9763 }
9764 }
9765
9766 19287 total_size += a.size;
9767 }
9768
9769
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)
9770 102 avio_skip(pb, atom.size - total_size);
9771
9772 6400 c->atom_depth --;
9773 6400 return 0;
9774 }
9775
9776 7480 static int mov_probe(const AVProbeData *p)
9777 {
9778 int64_t offset;
9779 uint32_t tag;
9780 7480 int score = 0;
9781 7480 int moov_offset = -1;
9782
9783 /* check file header */
9784 7480 offset = 0;
9785 9212 for (;;) {
9786 int64_t size;
9787 16692 int minsize = 8;
9788 /* ignore invalid offset */
9789
2/2
✓ Branch 0 taken 7480 times.
✓ Branch 1 taken 9212 times.
16692 if ((offset + 8ULL) > (unsigned int)p->buf_size)
9790 7480 break;
9791 9212 size = AV_RB32(p->buf + offset);
9792
3/4
✓ Branch 0 taken 529 times.
✓ Branch 1 taken 8683 times.
✓ Branch 2 taken 529 times.
✗ Branch 3 not taken.
9212 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
9793 529 size = AV_RB64(p->buf+offset + 8);
9794 529 minsize = 16;
9795
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 8628 times.
8683 } else if (size == 0) {
9796 55 size = p->buf_size - offset;
9797 }
9798
2/2
✓ Branch 0 taken 401 times.
✓ Branch 1 taken 8811 times.
9212 if (size < minsize) {
9799 401 offset += 4;
9800 401 continue;
9801 }
9802 8811 tag = AV_RL32(p->buf + offset + 4);
9803
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 7442 times.
8811 switch(tag) {
9804 /* check for obvious tags */
9805 132 case MKTAG('m','o','o','v'):
9806 132 moov_offset = offset + 4;
9807 av_fallthrough;
9808 1005 case MKTAG('m','d','a','t'):
9809 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
9810 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
9811 case MKTAG('f','t','y','p'):
9812
2/2
✓ Branch 0 taken 456 times.
✓ Branch 1 taken 549 times.
1005 if (tag == MKTAG('f','t','y','p') &&
9813
1/2
✓ Branch 0 taken 456 times.
✗ Branch 1 not taken.
456 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
9814
1/2
✓ Branch 0 taken 456 times.
✗ Branch 1 not taken.
456 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
9815
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 449 times.
456 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
9816 )) {
9817 7 score = FFMAX(score, 5);
9818 } else {
9819 998 score = AVPROBE_SCORE_MAX;
9820 }
9821 1005 break;
9822 /* those are more common words, so rate then a bit less */
9823 363 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
9824 case MKTAG('w','i','d','e'):
9825 case MKTAG('f','r','e','e'):
9826 case MKTAG('j','u','n','k'):
9827 case MKTAG('p','i','c','t'):
9828 363 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
9829 363 break;
9830 case MKTAG(0x82,0x82,0x7f,0x7d):
9831 score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
9832 break;
9833 1 case MKTAG('s','k','i','p'):
9834 case MKTAG('u','u','i','d'):
9835 case MKTAG('p','r','f','l'):
9836 /* if we only find those cause probedata is too small at least rate them */
9837 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
9838 1 break;
9839 }
9840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8811 times.
8811 if (size > INT64_MAX - offset)
9841 break;
9842 8811 offset += size;
9843 }
9844
4/4
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 6994 times.
✓ Branch 2 taken 132 times.
✓ Branch 3 taken 354 times.
7480 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
9845 /* moov atom in the header - we should make sure that this is not a
9846 * MOV-packed MPEG-PS */
9847 132 offset = moov_offset;
9848
9849
2/2
✓ Branch 0 taken 129602 times.
✓ Branch 1 taken 132 times.
129734 while (offset < (p->buf_size - 16)) { /* Sufficient space */
9850 /* We found an actual hdlr atom */
9851
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 129461 times.
129602 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
9852
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 120 times.
141 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
9853
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
9854 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
9855 /* We found a media handler reference atom describing an
9856 * MPEG-PS-in-MOV, return a
9857 * low score to force expanding the probe window until
9858 * mpegps_probe finds what it needs */
9859 return 5;
9860 } else {
9861 /* Keep looking */
9862 129602 offset += 2;
9863 }
9864 }
9865 }
9866
9867 7480 return score;
9868 }
9869
9870 // must be done after parsing all trak because there's no order requirement
9871 2 static void mov_read_chapters(AVFormatContext *s)
9872 {
9873 2 MOVContext *mov = s->priv_data;
9874 MOVStreamContext *sc;
9875 int64_t cur_pos;
9876 int i, j;
9877 int chapter_track;
9878
9879
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
9880 2 AVStream *st = NULL;
9881 2 FFStream *sti = NULL;
9882 2 chapter_track = mov->chapter_tracks[j];
9883
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
9884 4 sc = mov->fc->streams[i]->priv_data;
9885
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
9886 2 st = s->streams[i];
9887 2 break;
9888 }
9889 }
9890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
9891 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
9892 continue;
9893 }
9894 2 sti = ffstream(st);
9895
9896 2 sc = st->priv_data;
9897 2 cur_pos = avio_tell(sc->pb);
9898
9899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
9900 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
9901 if (!st->attached_pic.data && sti->nb_index_entries) {
9902 // Retrieve the first frame, if possible
9903 AVIndexEntry *sample = &sti->index_entries[0];
9904 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9905 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
9906 goto finish;
9907 }
9908
9909 if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
9910 goto finish;
9911 }
9912 } else {
9913 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
9914 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
9915 2 st->discard = AVDISCARD_ALL;
9916
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
9917 8 AVIndexEntry *sample = &sti->index_entries[i];
9918
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;
9919 uint8_t *title;
9920 uint16_t ch;
9921 int len, title_len;
9922
9923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
9924 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
9925 end = AV_NOPTS_VALUE;
9926 }
9927
9928
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9929 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
9930 goto finish;
9931 }
9932
9933 // the first two bytes are the length of the title
9934 8 len = avio_rb16(sc->pb);
9935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
9936 continue;
9937 8 title_len = 2*len + 1;
9938
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
9939 goto finish;
9940
9941 // The samples could theoretically be in any encoding if there's an encd
9942 // atom following, but in practice are only utf-8 or utf-16, distinguished
9943 // instead by the presence of a BOM
9944
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
9945 title[0] = 0;
9946 } else {
9947 8 ch = avio_rb16(sc->pb);
9948
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
9949 avio_get_str16be(sc->pb, len, title, title_len);
9950
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
9951 avio_get_str16le(sc->pb, len, title, title_len);
9952 else {
9953 8 AV_WB16(title, ch);
9954
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)
9955 title[len] = 0;
9956 else
9957 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
9958 }
9959 }
9960
9961 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
9962 8 av_freep(&title);
9963 }
9964 }
9965 2 finish:
9966 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
9967 }
9968 2 }
9969
9970 19 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
9971 int64_t value, int flags)
9972 {
9973 AVTimecode tc;
9974 char buf[AV_TIMECODE_STR_SIZE];
9975 19 AVRational rate = st->avg_frame_rate;
9976 19 int ret = av_timecode_init(&tc, rate, flags, 0, s);
9977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
9978 return ret;
9979 19 av_dict_set(&st->metadata, "timecode",
9980 19 av_timecode_make_string(&tc, buf, value), 0);
9981 19 return 0;
9982 }
9983
9984 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
9985 {
9986 MOVStreamContext *sc = st->priv_data;
9987 FFStream *const sti = ffstream(st);
9988 char buf[AV_TIMECODE_STR_SIZE];
9989 int64_t cur_pos = avio_tell(sc->pb);
9990 int hh, mm, ss, ff, drop;
9991
9992 if (!sti->nb_index_entries)
9993 return -1;
9994
9995 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9996 avio_skip(s->pb, 13);
9997 hh = avio_r8(s->pb);
9998 mm = avio_r8(s->pb);
9999 ss = avio_r8(s->pb);
10000 drop = avio_r8(s->pb);
10001 ff = avio_r8(s->pb);
10002 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
10003 hh, mm, ss, drop ? ';' : ':', ff);
10004 av_dict_set(&st->metadata, "timecode", buf, 0);
10005
10006 avio_seek(sc->pb, cur_pos, SEEK_SET);
10007 return 0;
10008 }
10009
10010 19 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
10011 {
10012 19 MOVStreamContext *sc = st->priv_data;
10013 19 FFStream *const sti = ffstream(st);
10014 19 int flags = 0;
10015 19 int64_t cur_pos = avio_tell(sc->pb);
10016 int64_t value;
10017 19 AVRational tc_rate = st->avg_frame_rate;
10018 19 int tmcd_nb_frames = sc->tmcd_nb_frames;
10019 int rounded_tc_rate;
10020
10021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!sti->nb_index_entries)
10022 return -1;
10023
10024
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)
10025 return -1;
10026
10027 19 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10028 19 value = avio_rb32(s->pb);
10029
10030
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13 times.
19 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
10031
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
10032
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
10033
10034 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
10035 * not the case) and thus assume "frame number format" instead of QT one.
10036 * No sample with tmcd track can be found with a QT timecode at the moment,
10037 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
10038 * format). */
10039
10040 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
10041 * we multiply the frame number with the quotient.
10042 * See tickets #9492, #9710. */
10043 19 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
10044 /* Work around files where tmcd_nb_frames is rounded down from frame rate
10045 * instead of up. See ticket #5978. */
10046
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
10047
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
10048 10 tmcd_nb_frames = rounded_tc_rate;
10049 19 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
10050
10051 19 parse_timecode_in_framenum_format(s, st, value, flags);
10052
10053 19 avio_seek(sc->pb, cur_pos, SEEK_SET);
10054 19 return 0;
10055 }
10056
10057 1263 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
10058 int i;
10059
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;
10060
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 8 times.
152 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
10061 144 av_encryption_info_free((*index)->encrypted_samples[i]);
10062 }
10063 8 av_freep(&(*index)->encrypted_samples);
10064 8 av_freep(&(*index)->auxiliary_info_sizes);
10065 8 av_freep(&(*index)->auxiliary_offsets);
10066 8 av_freep(index);
10067 }
10068
10069 736 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
10070 {
10071 736 MOVStreamContext *sc = st->priv_data;
10072
10073
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) {
10074 52 st->priv_data = NULL;
10075 52 return;
10076 }
10077
10078 684 av_freep(&sc->tts_data);
10079
2/2
✓ Branch 0 taken 627 times.
✓ Branch 1 taken 684 times.
1311 for (int i = 0; i < sc->drefs_count; i++) {
10080 627 av_freep(&sc->drefs[i].path);
10081 627 av_freep(&sc->drefs[i].dir);
10082 }
10083 684 av_freep(&sc->drefs);
10084
10085 684 sc->drefs_count = 0;
10086
10087
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 670 times.
684 if (!sc->pb_is_copied)
10088 14 ff_format_io_close(s, &sc->pb);
10089
10090 684 sc->pb = NULL;
10091 684 av_freep(&sc->chunk_offsets);
10092 684 av_freep(&sc->stsc_data);
10093 684 av_freep(&sc->sample_sizes);
10094 684 av_freep(&sc->keyframes);
10095 684 av_freep(&sc->ctts_data);
10096 684 av_freep(&sc->stts_data);
10097 684 av_freep(&sc->sdtp_data);
10098 684 av_freep(&sc->stps_data);
10099 684 av_freep(&sc->elst_data);
10100 684 av_freep(&sc->rap_group);
10101 684 av_freep(&sc->sync_group);
10102 684 av_freep(&sc->sgpd_sync);
10103 684 av_freep(&sc->sample_offsets);
10104 684 av_freep(&sc->open_key_samples);
10105 684 av_freep(&sc->display_matrix);
10106 684 av_freep(&sc->index_ranges);
10107
10108
2/2
✓ Branch 0 taken 627 times.
✓ Branch 1 taken 57 times.
684 if (sc->extradata)
10109
2/2
✓ Branch 0 taken 641 times.
✓ Branch 1 taken 627 times.
1268 for (int i = 0; i < sc->stsd_count; i++)
10110 641 av_free(sc->extradata[i]);
10111 684 av_freep(&sc->extradata);
10112 684 av_freep(&sc->extradata_size);
10113
10114 684 mov_free_encryption_index(&sc->cenc.encryption_index);
10115 684 av_encryption_info_free(sc->cenc.default_encrypted_sample);
10116 684 av_aes_ctr_free(sc->cenc.aes_ctr);
10117
10118 684 av_freep(&sc->stereo3d);
10119 684 av_freep(&sc->spherical);
10120 684 av_freep(&sc->mastering);
10121 684 av_freep(&sc->coll);
10122 684 av_freep(&sc->ambient);
10123
10124 #if CONFIG_IAMFDEC
10125
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 672 times.
684 if (sc->iamf)
10126 12 ff_iamf_read_deinit(sc->iamf);
10127 #endif
10128 684 av_freep(&sc->iamf);
10129 }
10130
10131 523 static int mov_read_close(AVFormatContext *s)
10132 {
10133 523 MOVContext *mov = s->priv_data;
10134 int i, j;
10135
10136
2/2
✓ Branch 0 taken 736 times.
✓ Branch 1 taken 523 times.
1259 for (i = 0; i < s->nb_streams; i++) {
10137 736 AVStream *st = s->streams[i];
10138
10139 736 mov_free_stream_context(s, st);
10140 }
10141
10142 523 av_freep(&mov->dv_demux);
10143 523 avformat_free_context(mov->dv_fctx);
10144 523 mov->dv_fctx = NULL;
10145
10146
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 512 times.
523 if (mov->meta_keys) {
10147
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i < mov->meta_keys_count; i++) {
10148 58 av_freep(&mov->meta_keys[i]);
10149 }
10150 11 av_freep(&mov->meta_keys);
10151 }
10152
10153 523 av_freep(&mov->trex_data);
10154 523 av_freep(&mov->bitrates);
10155
10156
2/2
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 523 times.
1000 for (i = 0; i < mov->frag_index.nb_items; i++) {
10157 477 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
10158
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++) {
10159 579 mov_free_encryption_index(&frag[j].encryption_index);
10160 }
10161 477 av_freep(&mov->frag_index.item[i].stream_info);
10162 }
10163 523 av_freep(&mov->frag_index.item);
10164
10165 523 av_freep(&mov->aes_decrypt);
10166 523 av_freep(&mov->chapter_tracks);
10167
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 523 times.
580 for (i = 0; i < mov->nb_heif_item; i++) {
10168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!mov->heif_item[i])
10169 continue;
10170 57 av_freep(&mov->heif_item[i]->name);
10171 57 av_freep(&mov->heif_item[i]->iref_list);
10172 57 av_freep(&mov->heif_item[i]->icc_profile);
10173 57 av_freep(&mov->heif_item[i]);
10174 }
10175 523 av_freep(&mov->heif_item);
10176
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 523 times.
532 for (i = 0; i < mov->nb_heif_grid; i++) {
10177 9 av_freep(&mov->heif_grid[i].tile_id_list);
10178 9 av_freep(&mov->heif_grid[i].tile_idx_list);
10179 9 av_freep(&mov->heif_grid[i].tile_item_list);
10180 }
10181 523 av_freep(&mov->heif_grid);
10182
10183 523 return 0;
10184 }
10185
10186 16 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
10187 {
10188 int i;
10189
10190
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 for (i = 0; i < s->nb_streams; i++) {
10191 24 AVStream *st = s->streams[i];
10192 24 MOVStreamContext *sc = st->priv_data;
10193
10194
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
10195
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 sc->timecode_track == tmcd_id)
10196 14 return 1;
10197 }
10198 2 return 0;
10199 }
10200
10201 /* look for a tmcd track not referenced by any video track, and export it globally */
10202 523 static void export_orphan_timecode(AVFormatContext *s)
10203 {
10204 int i;
10205
10206
2/2
✓ Branch 0 taken 733 times.
✓ Branch 1 taken 521 times.
1254 for (i = 0; i < s->nb_streams; i++) {
10207 733 AVStream *st = s->streams[i];
10208
10209
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') &&
10210 16 !tmcd_is_referenced(s, i + 1)) {
10211 2 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
10212
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (tcr) {
10213 2 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
10214 2 break;
10215 }
10216 }
10217 }
10218 523 }
10219
10220 3 static int read_tfra(MOVContext *mov, AVIOContext *f)
10221 {
10222 int version, fieldlength, i, j;
10223 3 int64_t pos = avio_tell(f);
10224 3 uint32_t size = avio_rb32(f);
10225 unsigned track_id, item_count;
10226
10227
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
10228 1 return 1;
10229 }
10230 2 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
10231
10232 2 version = avio_r8(f);
10233 2 avio_rb24(f);
10234 2 track_id = avio_rb32(f);
10235 2 fieldlength = avio_rb32(f);
10236 2 item_count = avio_rb32(f);
10237
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (i = 0; i < item_count; i++) {
10238 int64_t time, offset;
10239 int index;
10240 MOVFragmentStreamInfo * frag_stream_info;
10241
10242
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (avio_feof(f)) {
10243 return AVERROR_INVALIDDATA;
10244 }
10245
10246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1) {
10247 time = avio_rb64(f);
10248 offset = avio_rb64(f);
10249 } else {
10250 6 time = avio_rb32(f);
10251 6 offset = avio_rb32(f);
10252 }
10253
10254 // The first sample of each stream in a fragment is always a random
10255 // access sample. So it's entry in the tfra can be used as the
10256 // initial PTS of the fragment.
10257 6 index = update_frag_index(mov, offset);
10258 6 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
10259
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (frag_stream_info &&
10260
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
10261 6 frag_stream_info->first_tfra_pts = time;
10262
10263
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
10264 6 avio_r8(f);
10265
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
10266 6 avio_r8(f);
10267
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
10268 6 avio_r8(f);
10269 }
10270
10271 2 avio_seek(f, pos + size, SEEK_SET);
10272 2 return 0;
10273 }
10274
10275 1 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
10276 {
10277 1 int64_t stream_size = avio_size(f);
10278 1 int64_t original_pos = avio_tell(f);
10279 int64_t seek_ret;
10280 1 int ret = -1;
10281
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
10282 ret = seek_ret;
10283 goto fail;
10284 }
10285 1 c->mfra_size = avio_rb32(f);
10286 1 c->have_read_mfra_size = 1;
10287
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) {
10288 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
10289 goto fail;
10290 }
10291
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) {
10292 ret = seek_ret;
10293 goto fail;
10294 }
10295
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != c->mfra_size) {
10296 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
10297 goto fail;
10298 }
10299
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
10300 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
10301 goto fail;
10302 }
10303 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
10304 do {
10305 3 ret = read_tfra(c, f);
10306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
10307 goto fail;
10308
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 } while (!ret);
10309 1 ret = 0;
10310 1 c->frag_index.complete = 1;
10311 1 fail:
10312 1 seek_ret = avio_seek(f, original_pos, SEEK_SET);
10313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (seek_ret < 0) {
10314 av_log(c->fc, AV_LOG_ERROR,
10315 "failed to seek back after looking for mfra\n");
10316 ret = seek_ret;
10317 }
10318 1 return ret;
10319 }
10320
10321 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10322 const HEIFItem *item)
10323 {
10324 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
10325 AV_PKT_DATA_ICC_PROFILE,
10326 item->icc_profile_size, 0);
10327 if (!sd)
10328 return AVERROR(ENOMEM);
10329
10330 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
10331
10332 return 0;
10333 }
10334
10335 6 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10336 const HEIFItem *item)
10337 {
10338 int32_t *matrix;
10339 6 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data,
10340 nb_coded_side_data,
10341 AV_PKT_DATA_DISPLAYMATRIX,
10342 9 * sizeof(*matrix), 0);
10343
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sd)
10344 return AVERROR(ENOMEM);
10345
10346 6 matrix = (int32_t*)sd->data;
10347 /* rotation is in the counter-clockwise direction whereas
10348 * av_display_rotation_set() expects its argument to be
10349 * oriented clockwise, so we need to negate it. */
10350 6 av_display_rotation_set(matrix, -item->rotation);
10351 6 av_display_matrix_flip(matrix, item->hflip, item->vflip);
10352
10353 6 return 0;
10354 }
10355
10356 5 static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid,
10357 AVStreamGroupTileGrid *tile_grid)
10358 {
10359 5 MOVContext *c = s->priv_data;
10360 5 const HEIFItem *item = grid->item;
10361 5 int64_t offset = 0, pos = avio_tell(s->pb);
10362 5 int x = 0, y = 0, i = 0;
10363 int tile_rows, tile_cols;
10364 int flags, size;
10365
10366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10367 av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
10368 return AVERROR_PATCHWELCOME;
10369 }
10370
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (item->is_idat_relative) {
10371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!c->idat_offset) {
10372 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
10373 return AVERROR_INVALIDDATA;
10374 }
10375 5 offset = c->idat_offset;
10376 }
10377
10378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (offset > INT64_MAX - item->extent_offset)
10379 return AVERROR_INVALIDDATA;
10380
10381 5 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10382
10383 5 avio_r8(s->pb); /* version */
10384 5 flags = avio_r8(s->pb);
10385
10386 5 tile_rows = avio_r8(s->pb) + 1;
10387 5 tile_cols = avio_r8(s->pb) + 1;
10388 /* actual width and height of output image */
10389
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);
10390
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);
10391
10392 5 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
10393 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
10394
10395 5 avio_seek(s->pb, pos, SEEK_SET);
10396
10397 5 size = tile_rows * tile_cols;
10398 5 tile_grid->nb_tiles = grid->nb_tiles;
10399
10400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (tile_grid->nb_tiles != size)
10401 return AVERROR_INVALIDDATA;
10402
10403
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < tile_cols; i++)
10404 10 tile_grid->coded_width += grid->tile_item_list[i]->width;
10405
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < size; i += tile_cols)
10406 10 tile_grid->coded_height += grid->tile_item_list[i]->height;
10407
10408 5 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!tile_grid->offsets)
10410 return AVERROR(ENOMEM);
10411
10412
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 while (y < tile_grid->coded_height) {
10413 10 int left_col = i;
10414
10415
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 while (x < tile_grid->coded_width) {
10416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (i == tile_grid->nb_tiles)
10417 return AVERROR_INVALIDDATA;
10418
10419 20 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10420 20 tile_grid->offsets[i].horizontal = x;
10421 20 tile_grid->offsets[i].vertical = y;
10422
10423 20 x += grid->tile_item_list[i++]->width;
10424 }
10425
10426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (x > tile_grid->coded_width) {
10427 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10428 return AVERROR_INVALIDDATA;
10429 }
10430
10431 10 x = 0;
10432 10 y += grid->tile_item_list[left_col]->height;
10433 }
10434
10435
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) {
10436 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10437 return AVERROR_INVALIDDATA;
10438 }
10439
10440 5 return 0;
10441 }
10442
10443 4 static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid,
10444 AVStreamGroupTileGrid *tile_grid)
10445 {
10446 4 MOVContext *c = s->priv_data;
10447 4 const HEIFItem *item = grid->item;
10448 uint16_t canvas_fill_value[4];
10449 4 int64_t offset = 0, pos = avio_tell(s->pb);
10450 4 int ret = 0, flags;
10451
10452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10453 av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
10454 return AVERROR_PATCHWELCOME;
10455 }
10456
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
10457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
10458 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
10459 return AVERROR_INVALIDDATA;
10460 }
10461 4 offset = c->idat_offset;
10462 }
10463
10464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (offset > INT64_MAX - item->extent_offset)
10465 return AVERROR_INVALIDDATA;
10466
10467 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10468
10469 4 avio_r8(s->pb); /* version */
10470 4 flags = avio_r8(s->pb);
10471
10472
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10473 16 canvas_fill_value[i] = avio_rb16(s->pb);
10474 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
10475 4 canvas_fill_value[0], canvas_fill_value[1],
10476 4 canvas_fill_value[2], canvas_fill_value[3]);
10477
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10478 16 tile_grid->background[i] = canvas_fill_value[i];
10479
10480 /* actual width and height of output image */
10481 4 tile_grid->width =
10482
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);
10483 4 tile_grid->height =
10484
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);
10485
10486 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
10487 tile_grid->width, tile_grid->height);
10488
10489 4 tile_grid->nb_tiles = grid->nb_tiles;
10490 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
10492 ret = AVERROR(ENOMEM);
10493 goto fail;
10494 }
10495
10496
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
10497 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10498
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);
10499
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);
10500 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
10501 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
10502 8 i, tile_grid->offsets[i].idx,
10503 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
10504 }
10505
10506 4 fail:
10507 4 avio_seek(s->pb, pos, SEEK_SET);
10508
10509 4 return ret;
10510 }
10511
10512 2 static int mov_parse_exif_item(AVFormatContext *s,
10513 AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10514 const HEIFItem *ref)
10515 {
10516 2 MOVContext *c = s->priv_data;
10517 AVPacketSideData *sd;
10518 2 AVExifMetadata ifd = { 0 };
10519 AVBufferRef *buf;
10520 2 int64_t offset = 0, pos = avio_tell(s->pb);
10521 2 unsigned orientation_id = av_exif_get_tag_id("Orientation");
10522 int err;
10523
10524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10525 av_log(c->fc, AV_LOG_WARNING, "Exif metadata with non seekable input\n");
10526 return AVERROR_PATCHWELCOME;
10527 }
10528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ref->is_idat_relative) {
10529 if (!c->idat_offset) {
10530 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the Exif metadata\n");
10531 return AVERROR_INVALIDDATA;
10532 }
10533 offset = c->idat_offset;
10534 }
10535
10536 2 buf = av_buffer_alloc(ref->extent_length);
10537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!buf)
10538 return AVERROR(ENOMEM);
10539
10540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset > INT64_MAX - ref->extent_offset) {
10541 err = AVERROR(ENOMEM);
10542 goto fail;
10543 }
10544
10545 2 avio_seek(s->pb, ref->extent_offset + offset, SEEK_SET);
10546 2 err = avio_read(s->pb, buf->data, ref->extent_length);
10547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != ref->extent_length) {
10548 if (err > 0)
10549 err = AVERROR_INVALIDDATA;
10550 goto fail;
10551 }
10552
10553 // HEIF spec states that Exif metadata is informative. The irot item property is
10554 // the normative source of rotation information. So we remove any Orientation tag
10555 // present in the Exif buffer.
10556 2 err = av_exif_parse_buffer(s, buf->data, ref->extent_length, &ifd, AV_EXIF_T_OFF);
10557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0) {
10558 av_log(s, AV_LOG_ERROR, "Unable to parse Exif metadata\n");
10559 goto fail;
10560 }
10561
10562 2 err = av_exif_remove_entry(s, &ifd, orientation_id, 0);
10563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
10564 goto fail;
10565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (!err)
10566 goto finish;
10567
10568 2 av_buffer_unref(&buf);
10569 2 err = av_exif_write(s, &ifd, &buf, AV_EXIF_T_OFF);
10570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
10571 goto fail;
10572
10573 2 finish:
10574 2 offset = AV_RB32(buf->data) + 4;
10575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset >= buf->size) {
10576 err = AVERROR_INVALIDDATA;
10577 goto fail;
10578 }
10579 2 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
10580 2 AV_PKT_DATA_EXIF, buf->size - offset, 0);
10581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!sd) {
10582 err = AVERROR(ENOMEM);
10583 goto fail;
10584 }
10585 2 memcpy(sd->data, buf->data + offset, buf->size - offset);
10586
10587 2 err = 0;
10588 2 fail:
10589 2 av_buffer_unref(&buf);
10590 2 av_exif_free(&ifd);
10591 2 avio_seek(s->pb, pos, SEEK_SET);
10592
10593 2 return err;
10594 }
10595
10596 9 static int mov_parse_tiles(AVFormatContext *s)
10597 {
10598 9 MOVContext *mov = s->priv_data;
10599
10600
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for (int i = 0; i < mov->nb_heif_grid; i++) {
10601 9 AVStreamGroup *stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
10602 AVStreamGroupTileGrid *tile_grid;
10603 9 const HEIFGrid *grid = &mov->heif_grid[i];
10604 9 int err, loop = 1;
10605
10606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!stg)
10607 return AVERROR(ENOMEM);
10608
10609 9 stg->id = grid->item->item_id;
10610 9 tile_grid = stg->params.tile_grid;
10611
10612
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9 times.
37 for (int j = 0; j < grid->nb_tiles; j++) {
10613 28 int tile_id = grid->tile_id_list[j];
10614 int k;
10615
10616
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 for (k = 0; k < mov->nb_heif_item; k++) {
10617 60 HEIFItem *item = mov->heif_item[k];
10618 AVStream *st;
10619
10620
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)
10621 32 continue;
10622 28 st = item->st;
10623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!st) {
10624 av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
10625 "reference a stream\n",
10626 tile_id, grid->item->item_id);
10627 ff_remove_stream_group(s, stg);
10628 loop = 0;
10629 break;
10630 }
10631
10632 28 grid->tile_item_list[j] = item;
10633 28 grid->tile_idx_list[j] = stg->nb_streams;
10634
10635 28 err = avformat_stream_group_add_stream(stg, st);
10636
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 26 times.
28 if (err < 0) {
10637 int l;
10638
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
10639 return err;
10640
10641
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_streams; l++)
10642
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->streams[l]->index == st->index)
10643 2 break;
10644
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_streams);
10645 2 grid->tile_idx_list[j] = l;
10646 }
10647
10648
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 6 times.
28 if (item->item_id != mov->primary_item_id)
10649 22 st->disposition |= AV_DISPOSITION_DEPENDENT;
10650 28 break;
10651 }
10652
10653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (k == mov->nb_heif_item) {
10654 av_assert0(loop);
10655 av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
10656 "exist\n",
10657 tile_id, grid->item->item_id);
10658 ff_remove_stream_group(s, stg);
10659 loop = 0;
10660 }
10661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!loop)
10662 break;
10663 }
10664
10665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!loop)
10666 continue;
10667
10668
2/3
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
9 switch (grid->item->type) {
10669 5 case MKTAG('g','r','i','d'):
10670 5 err = read_image_grid(s, grid, tile_grid);
10671 5 break;
10672 4 case MKTAG('i','o','v','l'):
10673 4 err = read_image_iovl(s, grid, tile_grid);
10674 4 break;
10675 default:
10676 av_assert0(0);
10677 }
10678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err < 0)
10679 return err;
10680
10681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 for (int j = 0; j < grid->item->nb_iref_list; j++) {
10682 HEIFItem *ref = get_heif_item(mov, grid->item->iref_list[j].item_id);
10683
10684 av_assert0(ref);
10685 switch(ref->type) {
10686 case MKTAG('E','x','i','f'):
10687 err = mov_parse_exif_item(s, &tile_grid->coded_side_data,
10688 &tile_grid->nb_coded_side_data, ref);
10689 if (err < 0 && (s->error_recognition & AV_EF_EXPLODE))
10690 return err;
10691 break;
10692 default:
10693 break;
10694 }
10695 }
10696
10697 /* rotation */
10698
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) {
10699 err = set_display_matrix_from_item(&tile_grid->coded_side_data,
10700 &tile_grid->nb_coded_side_data, grid->item);
10701 if (err < 0)
10702 return err;
10703 }
10704
10705 /* ICC profile */
10706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (grid->item->icc_profile_size) {
10707 err = set_icc_profile_from_item(&tile_grid->coded_side_data,
10708 &tile_grid->nb_coded_side_data, grid->item);
10709 if (err < 0)
10710 return err;
10711 }
10712
10713
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (grid->item->name)
10714 9 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
10715
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 if (grid->item->item_id == mov->primary_item_id)
10716 5 stg->disposition |= AV_DISPOSITION_DEFAULT;
10717 }
10718
10719 9 return 0;
10720 }
10721
10722 18 static int mov_parse_heif_items(AVFormatContext *s)
10723 {
10724 18 MOVContext *mov = s->priv_data;
10725 int err;
10726
10727
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (int i = 0; i < mov->nb_heif_item; i++) {
10728 57 HEIFItem *item = mov->heif_item[i];
10729 MOVStreamContext *sc;
10730 AVStream *st;
10731 57 int64_t offset = 0;
10732
10733
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item)
10734 continue;
10735
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 43 times.
57 if (!item->st) {
10736 14 continue;
10737 }
10738
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (item->is_idat_relative) {
10739 if (!mov->idat_offset) {
10740 av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
10741 return AVERROR_INVALIDDATA;
10742 }
10743 offset = mov->idat_offset;
10744 }
10745
10746 43 st = item->st;
10747 43 sc = st->priv_data;
10748 43 st->codecpar->width = item->width;
10749 43 st->codecpar->height = item->height;
10750
10751 43 sc->sample_size = sc->stsz_sample_size = item->extent_length;
10752 43 sc->sample_count = 1;
10753
10754 43 err = sanity_checks(s, sc, st->index);
10755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (err)
10756 return AVERROR_INVALIDDATA;
10757
10758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (offset > INT64_MAX - item->extent_offset)
10759 return AVERROR_INVALIDDATA;
10760
10761 43 sc->chunk_offsets[0] = item->extent_offset + offset;
10762
10763
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 30 times.
43 if (item->item_id == mov->primary_item_id)
10764 13 st->disposition |= AV_DISPOSITION_DEFAULT;
10765
10766
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 43 times.
54 for (int j = 0; j < item->nb_iref_list; j++) {
10767 11 HEIFItem *ref = get_heif_item(mov, item->iref_list[j].item_id);
10768
10769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 av_assert0(ref);
10770
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 switch(ref->type) {
10771 2 case MKTAG('E','x','i','f'):
10772 2 err = mov_parse_exif_item(s, &st->codecpar->coded_side_data,
10773 2 &st->codecpar->nb_coded_side_data, ref);
10774
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))
10775 return err;
10776 2 break;
10777 9 default:
10778 9 break;
10779 }
10780 }
10781
10782
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) {
10783 6 err = set_display_matrix_from_item(&st->codecpar->coded_side_data,
10784 6 &st->codecpar->nb_coded_side_data, item);
10785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10786 return err;
10787 }
10788
10789 43 mov_build_index(mov, st);
10790 }
10791
10792
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (mov->nb_heif_grid) {
10793 9 err = mov_parse_tiles(s);
10794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err < 0)
10795 return err;
10796 }
10797
10798 18 return 0;
10799 }
10800
10801 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
10802 int first_index)
10803 {
10804 MOVStreamContext *sc = st->priv_data;
10805
10806 if (sc->tref_id < 0)
10807 return NULL;
10808
10809 for (int i = first_index; i < s->nb_streams; i++)
10810 if (s->streams[i]->index != st->index &&
10811 s->streams[i]->id == sc->tref_id)
10812 return s->streams[i];
10813
10814 return NULL;
10815 }
10816
10817 523 static int mov_parse_lcevc_streams(AVFormatContext *s)
10818 {
10819 int err;
10820
10821 // Don't try to add a group if there's only one track
10822
2/2
✓ Branch 0 taken 409 times.
✓ Branch 1 taken 114 times.
523 if (s->nb_streams <= 1)
10823 409 return 0;
10824
10825
2/2
✓ Branch 0 taken 327 times.
✓ Branch 1 taken 114 times.
441 for (int i = 0; i < s->nb_streams; i++) {
10826 AVStreamGroup *stg;
10827 327 AVStream *st = s->streams[i];
10828 AVStream *st_base;
10829 327 MOVStreamContext *sc = st->priv_data;
10830 327 int j = 0;
10831
10832 /* Find an enhancement stream. */
10833
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 327 times.
327 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC ||
10834 !(sc->tref_flags & MOV_TREF_FLAG_ENHANCEMENT))
10835 327 continue;
10836
10837 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
10838 if (!stg)
10839 return AVERROR(ENOMEM);
10840
10841 stg->id = st->id;
10842 stg->params.lcevc->width = st->codecpar->width;
10843 stg->params.lcevc->height = st->codecpar->height;
10844
10845 while (st_base = mov_find_reference_track(s, st, j)) {
10846 err = avformat_stream_group_add_stream(stg, st_base);
10847 if (err < 0)
10848 return err;
10849
10850 j = st_base->index + 1;
10851 }
10852 if (!j) {
10853 int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
10854 av_log(s, loglevel, "Failed to find base stream for LCEVC stream\n");
10855 ff_remove_stream_group(s, stg);
10856 if (s->error_recognition & AV_EF_EXPLODE)
10857 return AVERROR_INVALIDDATA;
10858 continue;
10859 }
10860
10861 err = avformat_stream_group_add_stream(stg, st);
10862 if (err < 0)
10863 return err;
10864
10865 stg->params.lcevc->lcevc_index = stg->nb_streams - 1;
10866 }
10867
10868 114 return 0;
10869 }
10870
10871 523 static void fix_stream_ids(AVFormatContext *s)
10872 {
10873 523 int highest_id = 0, lowest_iamf_id = INT_MAX;
10874
10875
2/2
✓ Branch 0 taken 736 times.
✓ Branch 1 taken 523 times.
1259 for (int i = 0; i < s->nb_streams; i++) {
10876 736 const AVStream *st = s->streams[i];
10877 736 const MOVStreamContext *sc = st->priv_data;
10878
2/2
✓ Branch 0 taken 672 times.
✓ Branch 1 taken 64 times.
736 if (!sc->iamf)
10879 672 highest_id = FFMAX(highest_id, st->id);
10880 }
10881
10882
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 523 times.
556 for (int i = 0; i < s->nb_stream_groups; i++) {
10883 33 AVStreamGroup *stg = s->stream_groups[i];
10884
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 12 times.
33 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
10885 21 continue;
10886
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_streams; j++) {
10887 64 AVStream *st = stg->streams[j];
10888 64 lowest_iamf_id = FFMIN(lowest_iamf_id, st->id);
10889 }
10890 }
10891
10892
2/2
✓ Branch 0 taken 515 times.
✓ Branch 1 taken 8 times.
523 if (highest_id < lowest_iamf_id)
10893 515 return;
10894
10895 8 highest_id += !lowest_iamf_id;
10896
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++) {
10897 4 AVStreamGroup *stg = s->stream_groups[i];
10898
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
10899 2 continue;
10900
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_streams; j++) {
10901 14 AVStream *st = stg->streams[j];
10902 14 MOVStreamContext *sc = st->priv_data;
10903 14 st->id += highest_id;
10904 14 sc->iamf_stream_offset = highest_id;
10905 }
10906 }
10907 }
10908
10909 523 static int mov_read_header(AVFormatContext *s)
10910 {
10911 523 MOVContext *mov = s->priv_data;
10912 523 AVIOContext *pb = s->pb;
10913 int j, err;
10914 523 MOVAtom atom = { AV_RL32("root") };
10915 int i;
10916
10917 523 mov->fc = s;
10918 523 mov->trak_index = -1;
10919 523 mov->primary_item_id = -1;
10920 523 mov->cur_item_id = -1;
10921 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
10922
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 1 times.
523 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
10923 522 atom.size = avio_size(pb);
10924 else
10925 1 atom.size = INT64_MAX;
10926
10927 /* check MOV header */
10928 do {
10929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 523 times.
523 if (mov->moov_retry)
10930 avio_seek(pb, 0, SEEK_SET);
10931
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 523 times.
523 if ((err = mov_read_default(mov, pb, atom)) < 0) {
10932 av_log(s, AV_LOG_ERROR, "error reading header\n");
10933 return err;
10934 }
10935 1045 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10936
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++);
10937
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) {
10938 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
10939 return AVERROR_INVALIDDATA;
10940 }
10941 523 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
10942
10943
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) {
10944 18 err = mov_parse_heif_items(s);
10945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (err < 0)
10946 return err;
10947 }
10948 // prevent iloc and iinf boxes from being parsed while reading packets.
10949 // this is needed because an iinf box may have been parsed but ignored
10950 // for having old infe boxes which create no streams.
10951 523 mov->found_iloc = mov->found_iinf = 1;
10952
10953
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 1 times.
523 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
10954
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)
10955 2 mov_read_chapters(s);
10956
2/2
✓ Branch 0 taken 735 times.
✓ Branch 1 taken 522 times.
1257 for (i = 0; i < s->nb_streams; i++)
10957
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 716 times.
735 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
10958 19 mov_read_timecode_track(s, s->streams[i]);
10959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 716 times.
716 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
10960 mov_read_rtmd_track(s, s->streams[i]);
10961 }
10962 }
10963
10964 /* copy timecode metadata from tmcd tracks to the related video streams */
10965
2/2
✓ Branch 0 taken 736 times.
✓ Branch 1 taken 523 times.
1259 for (i = 0; i < s->nb_streams; i++) {
10966 736 AVStream *st = s->streams[i];
10967 736 MOVStreamContext *sc = st->priv_data;
10968
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 718 times.
736 if (sc->timecode_track > 0) {
10969 AVDictionaryEntry *tcr;
10970 18 int tmcd_st_id = -1;
10971
10972
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 18 times.
66 for (j = 0; j < s->nb_streams; j++) {
10973 48 MOVStreamContext *sc2 = s->streams[j]->priv_data;
10974
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 30 times.
48 if (sc2->id == sc->timecode_track)
10975 18 tmcd_st_id = j;
10976 }
10977
10978
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)
10979 continue;
10980 18 tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
10981
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 if (tcr)
10982 16 av_dict_set(&st->metadata, "timecode", tcr->value, 0);
10983 }
10984 }
10985 523 export_orphan_timecode(s);
10986
10987 /* Create LCEVC stream groups. */
10988 523 err = mov_parse_lcevc_streams(s);
10989
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 523 times.
523 if (err < 0)
10990 return err;
10991
10992
2/2
✓ Branch 0 taken 736 times.
✓ Branch 1 taken 523 times.
1259 for (i = 0; i < s->nb_streams; i++) {
10993 736 AVStream *st = s->streams[i];
10994 736 FFStream *const sti = ffstream(st);
10995 736 MOVStreamContext *sc = st->priv_data;
10996 736 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
10997 736 fix_timescale(mov, sc);
10998
10999 /* Set the primary extradata based on the first Sample if it doesn't reference the first stsd entry. */
11000
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 &&
11001
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) {
11002 3 sc->last_stsd_index = sc->stsc_data[0].id - 1;
11003 3 av_freep(&st->codecpar->extradata);
11004 3 st->codecpar->extradata_size = sc->extradata_size[sc->last_stsd_index];
11005
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (sc->extradata_size[sc->last_stsd_index]) {
11006 3 st->codecpar->extradata = av_mallocz(sc->extradata_size[sc->last_stsd_index] + AV_INPUT_BUFFER_PADDING_SIZE);
11007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata)
11008 return AVERROR(ENOMEM);
11009 3 memcpy(st->codecpar->extradata, sc->extradata[sc->last_stsd_index], sc->extradata_size[sc->last_stsd_index]);
11010 }
11011 }
11012
11013
2/2
✓ Branch 0 taken 299 times.
✓ Branch 1 taken 437 times.
736 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
11014
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 179 times.
299 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
11015 120 sti->skip_samples = sc->start_pad;
11016 }
11017
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)
11018 325 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
11019 325 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
11020
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 724 times.
736 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
11021
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) {
11022 8 st->codecpar->width = sc->width;
11023 8 st->codecpar->height = sc->height;
11024 }
11025
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
11026 st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
11027
11028 for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
11029 dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
11030
11031 err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
11032 if (err < 0)
11033 return err;
11034
11035 av_freep(&st->codecpar->extradata);
11036 st->codecpar->extradata_size = 0;
11037
11038 err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
11039 st->codecpar);
11040 if (err < 0)
11041 return err;
11042 }
11043 }
11044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 736 times.
736 if (mov->handbrake_version &&
11045 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
11046 st->codecpar->codec_id == AV_CODEC_ID_MP3) {
11047 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
11048 sti->need_parsing = AVSTREAM_PARSE_FULL;
11049 }
11050 }
11051
11052
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) {
11053
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 19 times.
47 for (i = 0; i < s->nb_streams; i++) {
11054 28 AVStream *st = s->streams[i];
11055 28 MOVStreamContext *sc = st->priv_data;
11056
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 4 times.
28 if (sc->duration_for_fps > 0) {
11057 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
11058 24 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
11059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (st->codecpar->bit_rate == INT64_MIN) {
11060 av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
11061 sc->data_size, sc->time_scale);
11062 st->codecpar->bit_rate = 0;
11063 if (s->error_recognition & AV_EF_EXPLODE)
11064 return AVERROR_INVALIDDATA;
11065 }
11066 }
11067 }
11068 }
11069
11070
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++) {
11071 if (mov->bitrates[i]) {
11072 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
11073 }
11074 }
11075
11076 523 ff_rfps_calculate(s);
11077
11078
2/2
✓ Branch 0 taken 736 times.
✓ Branch 1 taken 523 times.
1259 for (i = 0; i < s->nb_streams; i++) {
11079 736 AVStream *st = s->streams[i];
11080 736 MOVStreamContext *sc = st->priv_data;
11081
11082
3/3
✓ Branch 0 taken 299 times.
✓ Branch 1 taken 382 times.
✓ Branch 2 taken 55 times.
736 switch (st->codecpar->codec_type) {
11083 299 case AVMEDIA_TYPE_AUDIO:
11084 299 err = ff_replaygain_export(st, s->metadata);
11085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 299 times.
299 if (err < 0)
11086 return err;
11087 299 break;
11088 382 case AVMEDIA_TYPE_VIDEO:
11089
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 374 times.
382 if (sc->display_matrix) {
11090
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,
11091 AV_PKT_DATA_DISPLAYMATRIX,
11092 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
11093 return AVERROR(ENOMEM);
11094
11095 8 sc->display_matrix = NULL;
11096 }
11097
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 378 times.
382 if (sc->stereo3d) {
11098
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,
11099 AV_PKT_DATA_STEREO3D,
11100 4 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
11101 return AVERROR(ENOMEM);
11102
11103 4 sc->stereo3d = NULL;
11104 }
11105
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 378 times.
382 if (sc->spherical) {
11106
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,
11107 AV_PKT_DATA_SPHERICAL,
11108 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
11109 return AVERROR(ENOMEM);
11110
11111 4 sc->spherical = NULL;
11112 }
11113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 382 times.
382 if (sc->mastering) {
11114 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11115 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
11116 (uint8_t *)sc->mastering, sc->mastering_size, 0))
11117 return AVERROR(ENOMEM);
11118
11119 sc->mastering = NULL;
11120 }
11121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 382 times.
382 if (sc->coll) {
11122 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11123 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
11124 (uint8_t *)sc->coll, sc->coll_size, 0))
11125 return AVERROR(ENOMEM);
11126
11127 sc->coll = NULL;
11128 }
11129
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 378 times.
382 if (sc->ambient) {
11130
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,
11131 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
11132 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
11133 return AVERROR(ENOMEM);
11134
11135 4 sc->ambient = NULL;
11136 }
11137 382 break;
11138 }
11139 }
11140
11141 523 fix_stream_ids(s);
11142
11143 523 ff_configure_buffers_for_index(s, AV_TIME_BASE);
11144
11145
2/2
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 523 times.
1000 for (i = 0; i < mov->frag_index.nb_items; i++)
11146
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)
11147 467 mov->frag_index.item[i].headers_read = 1;
11148
11149 523 return 0;
11150 }
11151
11152 107036 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
11153 {
11154 107036 AVIndexEntry *sample = NULL;
11155 107036 int64_t best_dts = INT64_MAX;
11156 int i;
11157 107036 MOVContext *mov = s->priv_data;
11158
3/4
✓ Branch 0 taken 107036 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 106991 times.
107036 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
11159
2/2
✓ Branch 0 taken 139809 times.
✓ Branch 1 taken 107036 times.
246845 for (i = 0; i < s->nb_streams; i++) {
11160 139809 AVStream *avst = s->streams[i];
11161 139809 FFStream *const avsti = ffstream(avst);
11162 139809 MOVStreamContext *msc = avst->priv_data;
11163
4/4
✓ Branch 0 taken 131571 times.
✓ Branch 1 taken 8238 times.
✓ Branch 2 taken 128126 times.
✓ Branch 3 taken 3445 times.
139809 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
11164 128126 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
11165 128126 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
11166
2/2
✓ Branch 0 taken 112824 times.
✓ Branch 1 taken 15302 times.
128126 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
11167 128126 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
11168
3/6
✓ Branch 0 taken 21612 times.
✓ Branch 1 taken 106514 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 21612 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
128126 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
11169
1/2
✓ Branch 0 taken 21612 times.
✗ Branch 1 not taken.
21612 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
11170
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 21612 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 21612 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 21612 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19410 times.
✓ Branch 9 taken 2202 times.
21612 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
11171
4/4
✓ Branch 0 taken 11278 times.
✓ Branch 1 taken 8132 times.
✓ Branch 2 taken 2202 times.
✓ Branch 3 taken 11278 times.
21612 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
11172
3/4
✓ Branch 0 taken 761 times.
✓ Branch 1 taken 1441 times.
✓ Branch 2 taken 761 times.
✗ Branch 3 not taken.
2202 (dtsdiff > AV_TIME_BASE && dts < best_dts && mov->interleaved_read)))))) {
11173 115407 sample = current_sample;
11174 115407 best_dts = dts;
11175 115407 *st = avst;
11176 }
11177 }
11178 }
11179 107036 return sample;
11180 }
11181
11182 9 static int should_retry(AVIOContext *pb, int error_code) {
11183
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))
11184 9 return 0;
11185
11186 return 1;
11187 }
11188
11189 49 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
11190 {
11191 int ret;
11192 49 MOVContext *mov = s->priv_data;
11193
11194
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)
11195 1 target = mov->frag_index.item[index].moof_offset;
11196
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) {
11197 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
11198 return AVERROR_INVALIDDATA;
11199 }
11200
11201 49 mov->next_root_atom = 0;
11202
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)
11203 48 index = search_frag_moof_offset(&mov->frag_index, target);
11204
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 &&
11205
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 mov->frag_index.item[index].moof_offset == target) {
11206
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 4 times.
42 if (index + 1 < mov->frag_index.nb_items)
11207 38 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11208
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 6 times.
42 if (mov->frag_index.item[index].headers_read)
11209 36 return 0;
11210 6 mov->frag_index.item[index].headers_read = 1;
11211 }
11212
11213 13 mov->found_mdat = 0;
11214
11215 13 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
11216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (ret < 0)
11217 return ret;
11218
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 6 times.
13 if (avio_feof(s->pb))
11219 7 return AVERROR_EOF;
11220 6 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
11221
11222 6 return 1;
11223 }
11224
11225 15 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
11226 {
11227 15 MOVStreamContext *sc = st->priv_data;
11228 uint8_t *side, *extradata;
11229 int extradata_size;
11230
11231 /* Save the current index. */
11232 15 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
11233
11234 /* Notify the decoder that extradata changed. */
11235 15 extradata_size = sc->extradata_size[sc->last_stsd_index];
11236 15 extradata = sc->extradata[sc->last_stsd_index];
11237
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) {
11238 12 side = av_packet_new_side_data(pkt,
11239 AV_PKT_DATA_NEW_EXTRADATA,
11240 extradata_size);
11241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!side)
11242 return AVERROR(ENOMEM);
11243 12 memcpy(side, extradata, extradata_size);
11244 }
11245
11246 15 return 0;
11247 }
11248
11249 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
11250 {
11251 /* We can't make assumptions about the structure of the payload,
11252 because it may include multiple cdat and cdt2 samples. */
11253 const uint32_t cdat = AV_RB32("cdat");
11254 const uint32_t cdt2 = AV_RB32("cdt2");
11255 int ret, out_size = 0;
11256
11257 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
11258 if (src_size < 10)
11259 return AVERROR_INVALIDDATA;
11260
11261 /* avoid an int overflow: */
11262 if ((src_size - 8) / 2 >= INT_MAX / 3)
11263 return AVERROR_INVALIDDATA;
11264
11265 ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
11266 if (ret < 0)
11267 return ret;
11268
11269 /* parse and re-format the c608 payload in one pass. */
11270 while (src_size >= 10) {
11271 const uint32_t atom_size = avio_rb32(pb);
11272 const uint32_t atom_type = avio_rb32(pb);
11273 const uint32_t data_size = atom_size - 8;
11274 const uint8_t cc_field =
11275 atom_type == cdat ? 1 :
11276 atom_type == cdt2 ? 2 :
11277 0;
11278
11279 /* account for bytes consumed for atom size and type. */
11280 src_size -= 8;
11281
11282 /* make sure the data size stays within the buffer boundaries. */
11283 if (data_size < 2 || data_size > src_size) {
11284 ret = AVERROR_INVALIDDATA;
11285 break;
11286 }
11287
11288 /* make sure the data size is consistent with N byte pairs. */
11289 if (data_size % 2 != 0) {
11290 ret = AVERROR_INVALIDDATA;
11291 break;
11292 }
11293
11294 if (!cc_field) {
11295 /* neither cdat or cdt2 ... skip it */
11296 avio_skip(pb, data_size);
11297 src_size -= data_size;
11298 continue;
11299 }
11300
11301 for (uint32_t i = 0; i < data_size; i += 2) {
11302 pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
11303 pkt->data[out_size + 1] = avio_r8(pb);
11304 pkt->data[out_size + 2] = avio_r8(pb);
11305 out_size += 3;
11306 src_size -= 2;
11307 }
11308 }
11309
11310 if (src_size > 0)
11311 /* skip any remaining unread portion of the input payload */
11312 avio_skip(pb, src_size);
11313
11314 av_shrink_packet(pkt, out_size);
11315 return ret;
11316 }
11317
11318 106469 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
11319 int64_t current_index, AVPacket *pkt)
11320 {
11321 106469 MOVStreamContext *sc = st->priv_data;
11322
11323 106469 pkt->stream_index = sc->ffindex;
11324 106469 pkt->dts = sample->timestamp;
11325
2/2
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 106203 times.
106469 if (sample->flags & AVINDEX_DISCARD_FRAME) {
11326 266 pkt->flags |= AV_PKT_FLAG_DISCARD;
11327 }
11328
4/4
✓ Branch 0 taken 86636 times.
✓ Branch 1 taken 19833 times.
✓ Branch 2 taken 86624 times.
✓ Branch 3 taken 12 times.
106469 if (sc->stts_count && sc->tts_index < sc->tts_count)
11329 86624 pkt->duration = sc->tts_data[sc->tts_index].duration;
11330
3/4
✓ Branch 0 taken 4480 times.
✓ Branch 1 taken 101989 times.
✓ Branch 2 taken 4480 times.
✗ Branch 3 not taken.
106469 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
11331 4480 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
11332 } else {
11333
2/2
✓ Branch 0 taken 15770 times.
✓ Branch 1 taken 86219 times.
101989 if (pkt->duration == 0) {
11334 15770 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
11335
2/2
✓ Branch 0 taken 15677 times.
✓ Branch 1 taken 93 times.
15770 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
11336
2/2
✓ Branch 0 taken 15724 times.
✓ Branch 1 taken 46 times.
15770 if (next_dts >= pkt->dts)
11337 15724 pkt->duration = next_dts - pkt->dts;
11338 }
11339 101989 pkt->pts = pkt->dts;
11340 }
11341
11342
4/4
✓ Branch 0 taken 86636 times.
✓ Branch 1 taken 19833 times.
✓ Branch 2 taken 86624 times.
✓ Branch 3 taken 12 times.
106469 if (sc->tts_data && sc->tts_index < sc->tts_count) {
11343 /* update tts context */
11344 86624 sc->tts_sample++;
11345
1/2
✓ Branch 0 taken 86624 times.
✗ Branch 1 not taken.
86624 if (sc->tts_index < sc->tts_count &&
11346
1/2
✓ Branch 0 taken 86624 times.
✗ Branch 1 not taken.
86624 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
11347 86624 sc->tts_index++;
11348 86624 sc->tts_sample = 0;
11349 }
11350 }
11351
11352
4/4
✓ Branch 0 taken 1045 times.
✓ Branch 1 taken 105424 times.
✓ Branch 2 taken 913 times.
✓ Branch 3 taken 132 times.
106469 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
11353 913 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
11354 913 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
11355
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;
11356 }
11357 106469 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
11358 106469 pkt->pos = sample->pos;
11359
11360 /* Multiple stsd handling. */
11361
2/2
✓ Branch 0 taken 103093 times.
✓ Branch 1 taken 3376 times.
106469 if (sc->stsc_data) {
11362
1/2
✓ Branch 0 taken 103093 times.
✗ Branch 1 not taken.
103093 if (sc->stsc_data[sc->stsc_index].id > 0 &&
11363
2/2
✓ Branch 0 taken 103050 times.
✓ Branch 1 taken 43 times.
103093 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
11364
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 103035 times.
103050 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
11365 15 int ret = mov_change_extradata(st, pkt);
11366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (ret < 0)
11367 return ret;
11368 }
11369
11370 /* Update the stsc index for the next sample */
11371 103093 sc->stsc_sample++;
11372
2/2
✓ Branch 1 taken 55244 times.
✓ Branch 2 taken 47849 times.
103093 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
11373
2/2
✓ Branch 1 taken 1211 times.
✓ Branch 2 taken 54033 times.
55244 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
11374 1211 sc->stsc_index++;
11375 1211 sc->stsc_sample = 0;
11376 }
11377 }
11378
11379 106469 return 0;
11380 }
11381
11382 97855 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
11383 {
11384 97855 MOVContext *mov = s->priv_data;
11385 MOVStreamContext *sc;
11386 AVIndexEntry *sample;
11387 97855 AVStream *st = NULL;
11388 97855 FFStream *avsti = NULL;
11389 int64_t current_index;
11390 int ret;
11391 int i;
11392 97855 mov->fc = s;
11393 9181 retry:
11394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107036 times.
107036 if (s->pb->pos == 0) {
11395
11396 // Discard current fragment index
11397 if (mov->frag_index.allocated_size > 0) {
11398 for(int i = 0; i < mov->frag_index.nb_items; i++) {
11399 av_freep(&mov->frag_index.item[i].stream_info);
11400 }
11401 av_freep(&mov->frag_index.item);
11402 mov->frag_index.nb_items = 0;
11403 mov->frag_index.allocated_size = 0;
11404 mov->frag_index.current = -1;
11405 mov->frag_index.complete = 0;
11406 }
11407
11408 for (i = 0; i < s->nb_streams; i++) {
11409 AVStream *avst = s->streams[i];
11410 MOVStreamContext *msc = avst->priv_data;
11411
11412 // Clear current sample
11413 mov_current_sample_set(msc, 0);
11414 msc->tts_index = 0;
11415
11416 // Discard current index entries
11417 avsti = ffstream(avst);
11418 if (avsti->index_entries_allocated_size > 0) {
11419 av_freep(&avsti->index_entries);
11420 avsti->index_entries_allocated_size = 0;
11421 avsti->nb_index_entries = 0;
11422 }
11423 }
11424
11425 if ((ret = mov_switch_root(s, -1, -1)) < 0)
11426 return ret;
11427 }
11428 107036 sample = mov_find_next_sample(s, &st);
11429
6/6
✓ Branch 0 taken 106514 times.
✓ Branch 1 taken 522 times.
✓ Branch 2 taken 654 times.
✓ Branch 3 taken 105860 times.
✓ Branch 4 taken 36 times.
✓ Branch 5 taken 618 times.
107036 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
11430
2/2
✓ Branch 0 taken 510 times.
✓ Branch 1 taken 48 times.
558 if (!mov->next_root_atom)
11431 510 return AVERROR_EOF;
11432
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)
11433 7 return ret;
11434 41 goto retry;
11435 }
11436 106478 sc = st->priv_data;
11437 /* must be done just before reading, to avoid infinite loop on sample */
11438 106478 current_index = sc->current_index;
11439 106478 mov_current_sample_inc(sc);
11440
11441
2/2
✓ Branch 0 taken 618 times.
✓ Branch 1 taken 105860 times.
106478 if (mov->next_root_atom) {
11442 618 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
11443 618 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
11444 }
11445
11446
4/4
✓ Branch 0 taken 9149 times.
✓ Branch 1 taken 97329 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 9140 times.
106478 if (st->discard != AVDISCARD_ALL || sc->iamf) {
11447 97338 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
11448
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 97331 times.
97338 if (ret64 != sample->pos) {
11449 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
11450 sc->ffindex, sample->pos);
11451
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
11452 mov_current_sample_dec(sc);
11453
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
11454 7 return (int)ret64;
11455 }
11456 return AVERROR_INVALIDDATA;
11457 }
11458
11459
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 97331 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
97331 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
11460 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
11461 goto retry;
11462 }
11463
11464
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 97331 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
97331 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
11465 ret = get_eia608_packet(sc->pb, pkt, sample->size);
11466 #if CONFIG_IAMFDEC
11467
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 97256 times.
97331 else if (sc->iamf) {
11468 int64_t pts, dts, pos, duration;
11469 75 int flags, size = sample->size;
11470 75 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11471 75 pts = pkt->pts; dts = pkt->dts;
11472 75 pos = pkt->pos; flags = pkt->flags;
11473 75 duration = pkt->duration;
11474
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) {
11475 415 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
11476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 415 times.
415 if (ret < 0) {
11477 if (should_retry(sc->pb, ret))
11478 mov_current_sample_dec(sc);
11479 return ret;
11480 }
11481 415 size -= ret;
11482
11483
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 307 times.
415 if (pkt->flags & AV_PKT_FLAG_DISCARD) {
11484 108 av_packet_unref(pkt);
11485 108 ret = 0;
11486 108 continue;
11487 }
11488 307 pkt->pts = pts; pkt->dts = dts;
11489 307 pkt->pos = pos; pkt->flags |= flags;
11490 307 pkt->duration = duration;
11491 307 ret = ff_buffer_packet(s, pkt);
11492 }
11493
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 if (!ret)
11494 75 return FFERROR_REDO;
11495 }
11496 #endif
11497
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 97253 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
97259 else if (st->codecpar->codec_id == AV_CODEC_ID_APV && sample->size > 4) {
11498 3 const uint32_t au_size = avio_rb32(sc->pb);
11499 3 ret = av_get_packet(sc->pb, pkt, au_size);
11500 } else
11501 97253 ret = av_get_packet(sc->pb, pkt, sample->size);
11502
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 97254 times.
97256 if (ret < 0) {
11503
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (should_retry(sc->pb, ret)) {
11504 mov_current_sample_dec(sc);
11505 }
11506 2 return ret;
11507 }
11508 #if CONFIG_DV_DEMUXER
11509
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 97254 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
97254 if (mov->dv_demux && sc->dv_audio_container) {
11510 ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
11511 av_packet_unref(pkt);
11512 if (ret < 0)
11513 return ret;
11514 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
11515 if (ret < 0)
11516 return ret;
11517 }
11518 #endif
11519
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 97236 times.
97254 if (sc->has_palette) {
11520 uint8_t *pal;
11521
11522 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
11523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
11524 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
11525 } else {
11526 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
11527 18 sc->has_palette = 0;
11528 }
11529 }
11530
4/6
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 96966 times.
✓ Branch 3 taken 288 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 288 times.
✗ Branch 6 not taken.
97254 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
11531
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 288 times.
288 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
11532 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
11533 }
11534 }
11535
11536 106394 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106394 times.
106394 if (ret < 0)
11538 return ret;
11539
11540
2/2
✓ Branch 0 taken 9140 times.
✓ Branch 1 taken 97254 times.
106394 if (st->discard == AVDISCARD_ALL)
11541 9140 goto retry;
11542
11543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97254 times.
97254 if (mov->aax_mode)
11544 aax_filter(pkt->data, pkt->size, mov);
11545
11546 97254 ret = cenc_filter(mov, st, sc, pkt, current_index);
11547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97254 times.
97254 if (ret < 0) {
11548 return ret;
11549 }
11550
11551 97254 return 0;
11552 }
11553
11554 363 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
11555 {
11556 363 MOVContext *mov = s->priv_data;
11557 int index;
11558
11559
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 28 times.
363 if (!mov->frag_index.complete)
11560 335 return 0;
11561
11562 28 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
11563
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 24 times.
28 if (index < 0)
11564 4 index = 0;
11565
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (!mov->frag_index.item[index].headers_read)
11566 1 return mov_switch_root(s, -1, index);
11567
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (index + 1 < mov->frag_index.nb_items)
11568 27 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11569
11570 27 return 0;
11571 }
11572
11573 static int is_open_key_sample(const MOVStreamContext *sc, int sample)
11574 {
11575 // TODO: a bisect search would scale much better
11576 for (int i = 0; i < sc->open_key_samples_count; i++) {
11577 const int oks = sc->open_key_samples[i];
11578 if (oks == sample)
11579 return 1;
11580 if (oks > sample) /* list is monotically increasing so we can stop early */
11581 break;
11582 }
11583 return 0;
11584 }
11585
11586 /*
11587 * Some key sample may be key frames but not IDR frames, so a random access to
11588 * them may not be allowed.
11589 */
11590 231 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
11591 {
11592 231 MOVStreamContext *sc = st->priv_data;
11593 231 FFStream *const sti = ffstream(st);
11594 int64_t key_sample_dts, key_sample_pts;
11595
11596
1/2
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
231 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
11597 231 return 1;
11598
11599 if (sample >= sc->sample_offsets_count)
11600 return 1;
11601
11602 key_sample_dts = sti->index_entries[sample].timestamp;
11603 key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
11604
11605 /*
11606 * If the sample needs to be presented before an open key sample, they may
11607 * not be decodable properly, even though they come after in decoding
11608 * order.
11609 */
11610 if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
11611 return 0;
11612
11613 return 1;
11614 }
11615
11616 363 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
11617 {
11618 363 MOVStreamContext *sc = st->priv_data;
11619 363 FFStream *const sti = ffstream(st);
11620 int sample, time_sample, ret, requested_sample;
11621 int64_t next_ts;
11622 unsigned int i;
11623
11624 // Here we consider timestamp to be PTS, hence try to offset it so that we
11625 // can search over the DTS timeline.
11626 363 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
11627
11628 363 ret = mov_seek_fragment(s, st, timestamp);
11629
1/2
✓ Branch 0 taken 363 times.
✗ Branch 1 not taken.
363 if (ret < 0)
11630 return ret;
11631
11632 for (;;) {
11633 363 sample = av_index_search_timestamp(st, timestamp, flags);
11634 363 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
11635
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)
11636 43 sample = 0;
11637
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 337 times.
363 if (sample < 0) /* not sure what to do */
11638 26 return AVERROR_INVALIDDATA;
11639
11640
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))
11641 break;
11642
11643 next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
11644 requested_sample = av_index_search_timestamp(st, next_ts, flags);
11645
11646 // If we've reached a different sample trying to find a good pts to
11647 // seek to, give up searching because we'll end up seeking back to
11648 // sample 0 on every seek.
11649 if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
11650 break;
11651
11652 timestamp = next_ts;
11653 }
11654
11655 337 mov_current_sample_set(sc, sample);
11656 337 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
11657 /* adjust time to sample index */
11658
2/2
✓ Branch 0 taken 212 times.
✓ Branch 1 taken 125 times.
337 if (sc->tts_data) {
11659 212 time_sample = 0;
11660
1/2
✓ Branch 0 taken 60308 times.
✗ Branch 1 not taken.
60308 for (i = 0; i < sc->tts_count; i++) {
11661 60308 int next = time_sample + sc->tts_data[i].count;
11662
2/2
✓ Branch 0 taken 212 times.
✓ Branch 1 taken 60096 times.
60308 if (next > sc->current_sample) {
11663 212 sc->tts_index = i;
11664 212 sc->tts_sample = sc->current_sample - time_sample;
11665 212 break;
11666 }
11667 60096 time_sample = next;
11668 }
11669 }
11670
11671 /* adjust stsd index */
11672
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 28 times.
337 if (sc->chunk_count) {
11673 309 time_sample = 0;
11674
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
381 for (i = 0; i < sc->stsc_count; i++) {
11675 381 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
11676
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 72 times.
381 if (next > sc->current_sample) {
11677 309 sc->stsc_index = i;
11678 309 sc->stsc_sample = sc->current_sample - time_sample;
11679 309 break;
11680 }
11681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
11682 72 time_sample = next;
11683 }
11684 }
11685
11686 337 return sample;
11687 }
11688
11689 337 static int64_t mov_get_skip_samples(AVStream *st, int sample)
11690 {
11691 337 MOVStreamContext *sc = st->priv_data;
11692 337 FFStream *const sti = ffstream(st);
11693 337 int64_t first_ts = sti->index_entries[0].timestamp;
11694 337 int64_t ts = sti->index_entries[sample].timestamp;
11695 int64_t off;
11696
11697
2/2
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 152 times.
337 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
11698 185 return 0;
11699
11700 /* compute skip samples according to stream start_pad, seek ts and first ts */
11701 152 off = av_rescale_q(ts - first_ts, st->time_base,
11702 152 (AVRational){1, st->codecpar->sample_rate});
11703 152 return FFMAX(sc->start_pad - off, 0);
11704 }
11705
11706 341 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
11707 {
11708 341 MOVContext *mc = s->priv_data;
11709 AVStream *st;
11710 FFStream *sti;
11711 int sample;
11712 int i;
11713
11714
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
341 if (stream_index >= s->nb_streams)
11715 return AVERROR_INVALIDDATA;
11716
11717 341 st = s->streams[stream_index];
11718 341 sti = ffstream(st);
11719 341 sample = mov_seek_stream(s, st, sample_time, flags);
11720
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 315 times.
341 if (sample < 0)
11721 26 return sample;
11722
11723
1/2
✓ Branch 0 taken 315 times.
✗ Branch 1 not taken.
315 if (mc->seek_individually) {
11724 /* adjust seek timestamp to found sample timestamp */
11725 315 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
11726 315 sti->skip_samples = mov_get_skip_samples(st, sample);
11727
11728
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 315 times.
652 for (i = 0; i < s->nb_streams; i++) {
11729 337 AVStream *const st = s->streams[i];
11730 337 FFStream *const sti = ffstream(st);
11731 int64_t timestamp;
11732
11733
2/2
✓ Branch 0 taken 315 times.
✓ Branch 1 taken 22 times.
337 if (stream_index == i)
11734 315 continue;
11735
11736 22 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
11737 22 sample = mov_seek_stream(s, st, timestamp, flags);
11738
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (sample >= 0)
11739 22 sti->skip_samples = mov_get_skip_samples(st, sample);
11740 }
11741 } else {
11742 for (i = 0; i < s->nb_streams; i++) {
11743 MOVStreamContext *sc;
11744 st = s->streams[i];
11745 sc = st->priv_data;
11746 mov_current_sample_set(sc, 0);
11747 }
11748 while (1) {
11749 MOVStreamContext *sc;
11750 AVIndexEntry *entry = mov_find_next_sample(s, &st);
11751 if (!entry)
11752 return AVERROR_INVALIDDATA;
11753 sc = st->priv_data;
11754 if (sc->ffindex == stream_index && sc->current_sample == sample)
11755 break;
11756 mov_current_sample_inc(sc);
11757 }
11758 }
11759 315 return 0;
11760 }
11761
11762 #define OFFSET(x) offsetof(MOVContext, x)
11763 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
11764 static const AVOption mov_options[] = {
11765 {"use_absolute_path",
11766 "allow using absolute path when opening alias, this is a possible security issue",
11767 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
11768 0, 1, FLAGS},
11769 {"seek_streams_individually",
11770 "Seek each stream individually to the closest point",
11771 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
11772 0, 1, FLAGS},
11773 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
11774 0, 1, FLAGS},
11775 {"advanced_editlist",
11776 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
11777 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
11778 0, 1, FLAGS},
11779 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
11780 0, 1, FLAGS},
11781 {"use_mfra_for",
11782 "use mfra for fragment timestamps",
11783 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
11784 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
11785 .unit = "use_mfra_for"},
11786 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
11787 FLAGS, .unit = "use_mfra_for" },
11788 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
11789 FLAGS, .unit = "use_mfra_for" },
11790 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
11791 FLAGS, .unit = "use_mfra_for" },
11792 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
11793 0, 1, FLAGS},
11794 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
11795 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11796 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
11797 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11798 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
11799 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11800 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
11801 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11802 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
11803 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11804 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
11805 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
11806 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
11807 .flags = AV_OPT_FLAG_DECODING_PARAM },
11808 { "decryption_key", "The default media decryption key (hex)", OFFSET(decryption_default_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11809 { "decryption_keys", "The media decryption keys by KID (hex)", OFFSET(decryption_keys), AV_OPT_TYPE_DICT, .flags = AV_OPT_FLAG_DECODING_PARAM },
11810 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
11811 {.i64 = 0}, 0, 1, FLAGS },
11812 { "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 },
11813 { "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 },
11814
11815 { NULL },
11816 };
11817
11818 static const AVClass mov_class = {
11819 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
11820 .item_name = av_default_item_name,
11821 .option = mov_options,
11822 .version = LIBAVUTIL_VERSION_INT,
11823 };
11824
11825 const FFInputFormat ff_mov_demuxer = {
11826 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
11827 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
11828 .p.priv_class = &mov_class,
11829 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4v,m4b,ism,ismv,isma,f4v,avif,heic,heif",
11830 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
11831 .priv_data_size = sizeof(MOVContext),
11832 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
11833 .read_probe = mov_probe,
11834 .read_header = mov_read_header,
11835 .read_packet = mov_read_packet,
11836 .read_close = mov_read_close,
11837 .read_seek = mov_read_seek,
11838 };
11839