FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2025-06-01 09:29:47
Exec Total Coverage
Lines: 4280 6782 63.1%
Functions: 173 212 81.6%
Branches: 2409 4556 52.9%

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/flac.h"
55 #include "libavcodec/hevc/hevc.h"
56 #include "libavcodec/mpegaudiodecheader.h"
57 #include "libavcodec/mlp_parse.h"
58 #include "avformat.h"
59 #include "internal.h"
60 #include "avio_internal.h"
61 #include "demux.h"
62 #include "dvdclut.h"
63 #include "iamf_parse.h"
64 #include "iamf_reader.h"
65 #include "dovi_isom.h"
66 #include "riff.h"
67 #include "isom.h"
68 #include "libavcodec/get_bits.h"
69 #include "id3v1.h"
70 #include "mov_chan.h"
71 #include "replaygain.h"
72
73 #if CONFIG_ZLIB
74 #include <zlib.h>
75 #endif
76
77 #include "qtpalette.h"
78
79 /* those functions parse an atom */
80 /* links atom IDs to parse functions */
81 typedef struct MOVParseTableEntry {
82 uint32_t type;
83 int (*parse)(MOVContext *ctx, AVIOContext *pb, MOVAtom atom);
84 } MOVParseTableEntry;
85
86 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom);
87 static int mov_read_mfra(MOVContext *c, AVIOContext *f);
88 static void mov_free_stream_context(AVFormatContext *s, AVStream *st);
89
90 24 static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
91 unsigned len, const char *key)
92 {
93 char buf[16];
94
95 24 short current, total = 0;
96 24 avio_rb16(pb); // unknown
97 24 current = avio_rb16(pb);
98
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (len >= 6)
99 24 total = avio_rb16(pb);
100
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19 times.
24 if (!total)
101 5 snprintf(buf, sizeof(buf), "%d", current);
102 else
103 19 snprintf(buf, sizeof(buf), "%d/%d", current, total);
104 24 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
105 24 av_dict_set(&c->fc->metadata, key, buf, 0);
106
107 24 return 0;
108 }
109
110 static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
111 unsigned len, const char *key)
112 {
113 /* bypass padding bytes */
114 avio_r8(pb);
115 avio_r8(pb);
116 avio_r8(pb);
117
118 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
119 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
120
121 return 0;
122 }
123
124 26 static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
125 unsigned len, const char *key)
126 {
127 26 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
128 26 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
129
130 26 return 0;
131 }
132
133 10 static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
134 unsigned len, const char *key)
135 {
136 short genre;
137
138 10 avio_r8(pb); // unknown
139
140 10 genre = avio_r8(pb);
141
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)
142 return 0;
143 10 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
144 10 av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
145
146 10 return 0;
147 }
148
149 static const uint32_t mac_to_unicode[128] = {
150 0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
151 0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
152 0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,
153 0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,
154 0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,
155 0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,
156 0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,
157 0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,
158 0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,
159 0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,
160 0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,
161 0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,
162 0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,
163 0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,
164 0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,
165 0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7,
166 };
167
168 326 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
169 char *dst, int dstlen)
170 {
171 326 char *p = dst;
172 326 char *end = dst+dstlen-1;
173 int i;
174
175
2/2
✓ Branch 0 taken 2889 times.
✓ Branch 1 taken 326 times.
3215 for (i = 0; i < len; i++) {
176 2889 uint8_t t, c = avio_r8(pb);
177
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2889 times.
2889 if (p >= end)
179 continue;
180
181
2/2
✓ Branch 0 taken 2886 times.
✓ Branch 1 taken 3 times.
2889 if (c < 0x80)
182 2886 *p++ = c;
183
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 else if (p < end)
184
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 3 times.
6 PUT_UTF8(mac_to_unicode[c-0x80], t, if (p < end) *p++ = t;);
185 }
186 326 *p = 0;
187 326 return p - dst;
188 }
189
190 /**
191 * Get the current item in the parsing process.
192 */
193 94 static HEIFItem *heif_cur_item(MOVContext *c)
194 {
195 94 HEIFItem *item = NULL;
196
197
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 12 times.
156 for (int i = 0; i < c->nb_heif_item; i++) {
198
3/4
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 82 times.
144 if (!c->heif_item[i] || c->heif_item[i]->item_id != c->cur_item_id)
199 62 continue;
200
201 82 item = c->heif_item[i];
202 82 break;
203 }
204
205 94 return item;
206 }
207
208 /**
209 * Get the current stream in the parsing process. This can either be the
210 * latest stream added to the context, or the stream referenced by an item.
211 */
212 202 static AVStream *get_curr_st(MOVContext *c)
213 {
214 202 AVStream *st = NULL;
215 HEIFItem *item;
216
217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 202 times.
202 if (c->fc->nb_streams < 1)
218 return NULL;
219
220
2/2
✓ Branch 0 taken 169 times.
✓ Branch 1 taken 33 times.
202 if (c->cur_item_id == -1)
221 169 return c->fc->streams[c->fc->nb_streams-1];
222
223 33 item = heif_cur_item(c);
224
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if (item)
225 33 st = item->st;
226
227 33 return st;
228 }
229
230 14 static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
231 {
232 AVStream *st;
233 MOVStreamContext *sc;
234 enum AVCodecID id;
235 int ret;
236
237
2/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
14 switch (type) {
238 7 case 0xd: id = AV_CODEC_ID_MJPEG; break;
239 7 case 0xe: id = AV_CODEC_ID_PNG; break;
240 case 0x1b: id = AV_CODEC_ID_BMP; break;
241 default:
242 av_log(c->fc, AV_LOG_WARNING, "Unknown cover type: 0x%x.\n", type);
243 avio_skip(pb, len);
244 return 0;
245 }
246
247 14 sc = av_mallocz(sizeof(*sc));
248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!sc)
249 return AVERROR(ENOMEM);
250 14 ret = ff_add_attached_pic(c->fc, NULL, pb, NULL, len);
251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0) {
252 av_free(sc);
253 return ret;
254 }
255 14 st = c->fc->streams[c->fc->nb_streams - 1];
256 14 st->priv_data = sc;
257 14 sc->id = st->id;
258 14 sc->refcount = 1;
259
260
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) {
261
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
262 7 id = AV_CODEC_ID_PNG;
263 } else {
264 7 id = AV_CODEC_ID_MJPEG;
265 }
266 }
267 14 st->codecpar->codec_id = id;
268
269 14 return 0;
270 }
271
272 // 3GPP TS 26.244
273 static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
274 {
275 char language[4] = { 0 };
276 char buf[200], place[100];
277 uint16_t langcode = 0;
278 double longitude, latitude, altitude;
279 const char *key = "location";
280
281 if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) {
282 av_log(c->fc, AV_LOG_ERROR, "loci too short\n");
283 return AVERROR_INVALIDDATA;
284 }
285
286 avio_skip(pb, 4); // version+flags
287 langcode = avio_rb16(pb);
288 ff_mov_lang_to_iso639(langcode, language);
289 len -= 6;
290
291 len -= avio_get_str(pb, len, place, sizeof(place));
292 if (len < 1) {
293 av_log(c->fc, AV_LOG_ERROR, "place name too long\n");
294 return AVERROR_INVALIDDATA;
295 }
296 avio_skip(pb, 1); // role
297 len -= 1;
298
299 if (len < 12) {
300 av_log(c->fc, AV_LOG_ERROR,
301 "loci too short (%u bytes left, need at least %d)\n", len, 12);
302 return AVERROR_INVALIDDATA;
303 }
304 longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
305 latitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
306 altitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
307
308 // Try to output in the same format as the ?xyz field
309 snprintf(buf, sizeof(buf), "%+08.4f%+09.4f", latitude, longitude);
310 if (altitude)
311 av_strlcatf(buf, sizeof(buf), "%+f", altitude);
312 av_strlcatf(buf, sizeof(buf), "/%s", place);
313
314 if (*language && strcmp(language, "und")) {
315 char key2[16];
316 snprintf(key2, sizeof(key2), "%s-%s", key, language);
317 av_dict_set(&c->fc->metadata, key2, buf, 0);
318 }
319 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
320 return av_dict_set(&c->fc->metadata, key, buf, 0);
321 }
322
323 static int mov_metadata_hmmt(MOVContext *c, AVIOContext *pb, unsigned len)
324 {
325 int i, n_hmmt;
326
327 if (len < 2)
328 return 0;
329 if (c->ignore_chapters)
330 return 0;
331
332 n_hmmt = avio_rb32(pb);
333 if (n_hmmt > len / 4)
334 return AVERROR_INVALIDDATA;
335 for (i = 0; i < n_hmmt && !pb->eof_reached; i++) {
336 int moment_time = avio_rb32(pb);
337 avpriv_new_chapter(c->fc, i, av_make_q(1, 1000), moment_time, AV_NOPTS_VALUE, NULL);
338 }
339 if (avio_feof(pb))
340 return AVERROR_INVALIDDATA;
341 return 0;
342 }
343
344 472 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
345 {
346 472 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
347 472 char key2[32], language[4] = {0};
348 472 char *str = NULL;
349 472 const char *key = NULL;
350 472 uint16_t langcode = 0;
351 472 uint32_t data_type = 0, str_size_alloc;
352 uint64_t str_size;
353 472 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
354 472 int raw = 0;
355 472 int num = 0;
356 AVDictionary **metadata;
357
358
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 443 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
472 if (c->trak_index >= 0 && c->trak_index < c->fc->nb_streams)
359 29 metadata = &c->fc->streams[c->trak_index]->metadata;
360 else
361 443 metadata = &c->fc->metadata;
362
363
25/74
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 158 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 not taken.
✓ Branch 23 taken 13 times.
✗ Branch 24 not taken.
✗ 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 taken 12 times.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✓ Branch 39 taken 17 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 16 times.
✓ Branch 42 taken 3 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 8 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 4 times.
✓ Branch 47 taken 16 times.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✓ Branch 51 taken 2 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 3 times.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✓ Branch 58 taken 5 times.
✓ Branch 59 taken 5 times.
✓ Branch 60 taken 41 times.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✓ Branch 67 taken 58 times.
✓ Branch 68 taken 50 times.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✓ Branch 72 taken 1 times.
✓ Branch 73 taken 5 times.
472 switch (atom.type) {
364 3 case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break;
365 3 case MKTAG( '@','P','R','Q'): key = "quicktime_version"; raw = 1; break;
366 2 case MKTAG( 'X','M','P','_'):
367
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->export_xmp) { key = "xmp"; raw = 1; } break;
368 12 case MKTAG( 'a','A','R','T'): key = "album_artist"; break;
369 case MKTAG( 'a','k','I','D'): key = "account_type";
370 parse = mov_metadata_int8_no_padding; break;
371 case MKTAG( 'a','p','I','D'): key = "account_id"; break;
372 case MKTAG( 'c','a','t','g'): key = "category"; break;
373 13 case MKTAG( 'c','p','i','l'): key = "compilation";
374 13 parse = mov_metadata_int8_no_padding; break;
375 case MKTAG( 'c','p','r','t'): key = "copyright"; break;
376 case MKTAG( 'd','e','s','c'): key = "description"; break;
377 12 case MKTAG( 'd','i','s','k'): key = "disc";
378 12 parse = mov_metadata_track_or_disc_number; break;
379 case MKTAG( 'e','g','i','d'): key = "episode_uid";
380 parse = mov_metadata_int8_no_padding; break;
381 case MKTAG( 'F','I','R','M'): key = "firmware"; raw = 1; break;
382 10 case MKTAG( 'g','n','r','e'): key = "genre";
383 10 parse = mov_metadata_gnre; break;
384 case MKTAG( 'h','d','v','d'): key = "hd_video";
385 parse = mov_metadata_int8_no_padding; break;
386 case MKTAG( 'H','M','M','T'):
387 return mov_metadata_hmmt(c, pb, atom.size);
388 case MKTAG( 'k','e','y','w'): key = "keywords"; break;
389 case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
390 case MKTAG( 'l','o','c','i'):
391 return mov_metadata_loci(c, pb, atom.size);
392 case MKTAG( 'm','a','n','u'): key = "make"; break;
393 case MKTAG( 'm','o','d','l'): key = "model"; break;
394 case MKTAG( 'p','c','s','t'): key = "podcast";
395 parse = mov_metadata_int8_no_padding; break;
396 13 case MKTAG( 'p','g','a','p'): key = "gapless_playback";
397 13 parse = mov_metadata_int8_no_padding; break;
398 case MKTAG( 'p','u','r','d'): key = "purchase_date"; break;
399 case MKTAG( 'r','t','n','g'): key = "rating";
400 parse = mov_metadata_int8_no_padding; break;
401 case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break;
402 case MKTAG( 's','o','a','l'): key = "sort_album"; break;
403 case MKTAG( 's','o','a','r'): key = "sort_artist"; break;
404 case MKTAG( 's','o','c','o'): key = "sort_composer"; break;
405 case MKTAG( 's','o','n','m'): key = "sort_name"; break;
406 case MKTAG( 's','o','s','n'): key = "sort_show"; break;
407 case MKTAG( 's','t','i','k'): key = "media_type";
408 parse = mov_metadata_int8_no_padding; break;
409 12 case MKTAG( 't','r','k','n'): key = "track";
410 12 parse = mov_metadata_track_or_disc_number; break;
411 case MKTAG( 't','v','e','n'): key = "episode_id"; break;
412 case MKTAG( 't','v','e','s'): key = "episode_sort";
413 parse = mov_metadata_int8_bypass_padding; break;
414 case MKTAG( 't','v','n','n'): key = "network"; break;
415 case MKTAG( 't','v','s','h'): key = "show"; break;
416 case MKTAG( 't','v','s','n'): key = "season_number";
417 parse = mov_metadata_int8_bypass_padding; break;
418 17 case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
419 case MKTAG(0xa9,'P','R','D'): key = "producer"; break;
420 16 case MKTAG(0xa9,'a','l','b'): key = "album"; break;
421 3 case MKTAG(0xa9,'a','u','t'): key = "artist"; break;
422 case MKTAG(0xa9,'c','h','p'): key = "chapter"; break;
423 8 case MKTAG(0xa9,'c','m','t'): key = "comment"; break;
424 case MKTAG(0xa9,'c','o','m'): key = "composer"; break;
425 4 case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
426 16 case MKTAG(0xa9,'d','a','y'): key = "date"; break;
427 case MKTAG(0xa9,'d','i','r'): key = "director"; break;
428 case MKTAG(0xa9,'d','i','s'): key = "disclaimer"; break;
429 case MKTAG(0xa9,'e','d','1'): key = "edit_date"; break;
430 2 case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
431 case MKTAG(0xa9,'f','m','t'): key = "original_format"; break;
432 3 case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
433 case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
434 case MKTAG(0xa9,'h','s','t'): key = "host_computer"; break;
435 case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
436 case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
437 5 case MKTAG(0xa9,'m','a','k'): key = "make"; break;
438 5 case MKTAG(0xa9,'m','o','d'): key = "model"; break;
439 41 case MKTAG(0xa9,'n','a','m'): key = "title"; break;
440 case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break;
441 case MKTAG(0xa9,'p','r','d'): key = "producer"; break;
442 case MKTAG(0xa9,'p','r','f'): key = "performers"; break;
443 case MKTAG(0xa9,'r','e','q'): key = "playback_requirements"; break;
444 case MKTAG(0xa9,'s','r','c'): key = "original_source"; break;
445 case MKTAG(0xa9,'s','t','3'): key = "subtitle"; break;
446 58 case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
447 50 case MKTAG(0xa9,'t','o','o'): key = "encoder"; break;
448 case MKTAG(0xa9,'t','r','k'): key = "track"; break;
449 case MKTAG(0xa9,'u','r','l'): key = "URL"; break;
450 case MKTAG(0xa9,'w','r','n'): key = "warning"; break;
451 1 case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
452 5 case MKTAG(0xa9,'x','y','z'): key = "location"; break;
453 }
454 2 retry:
455
3/4
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 174 times.
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
760 if (c->itunes_metadata && atom.size > 8) {
456 300 int data_size = avio_rb32(pb);
457 300 int tag = avio_rl32(pb);
458
3/6
✓ Branch 0 taken 300 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 300 times.
✗ Branch 5 not taken.
300 if (tag == MKTAG('d','a','t','a') && data_size <= atom.size && data_size >= 16) {
459 300 data_type = avio_rb32(pb); // type
460 300 avio_rb32(pb); // unknown
461 300 str_size = data_size - 16;
462 300 atom.size -= 16;
463
464
5/6
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 207 times.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 34 times.
✓ Branch 4 taken 59 times.
✗ Branch 5 not taken.
300 if (!key && c->found_hdlr_mdta && c->meta_keys) {
465 59 uint32_t index = av_bswap32(atom.type); // BE number has been read as LE
466
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) {
467 59 key = c->meta_keys[index];
468 } else if (atom.type != MKTAG('c', 'o', 'v', 'r')) {
469 av_log(c->fc, AV_LOG_WARNING,
470 "The index of 'data' is out of range: %"PRId32" < 1 or >= %d.\n",
471 index, c->meta_keys_count);
472 }
473 }
474
4/4
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 266 times.
✓ Branch 3 taken 20 times.
300 if (atom.type == MKTAG('c', 'o', 'v', 'r') ||
475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 266 times.
266 (key && !strcmp(key, "com.apple.quicktime.artwork"))) {
476 14 int ret = mov_read_covr(c, pb, data_type, str_size);
477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0) {
478 av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
479 return ret;
480 }
481 14 atom.size -= str_size;
482
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (atom.size > 8)
483 2 goto retry;
484 12 return ret;
485 }
486 } else return 0;
487
7/8
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 105 times.
✓ Branch 3 taken 51 times.
✓ Branch 4 taken 105 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 99 times.
✓ Branch 7 taken 6 times.
174 } else if (atom.size > 4 && key && !c->itunes_metadata && !raw) {
488 99 str_size = avio_rb16(pb); // string length
489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (str_size > atom.size) {
490 raw = 1;
491 avio_seek(pb, -2, SEEK_CUR);
492 av_log(c->fc, AV_LOG_WARNING, "UDTA parsing failed retrying raw\n");
493 goto retry;
494 }
495 99 langcode = avio_rb16(pb);
496 99 ff_mov_lang_to_iso639(langcode, language);
497 99 atom.size -= 4;
498 } else
499 75 str_size = atom.size;
500
501
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 460 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
460 if (c->export_all && !key) {
502 key = av_fourcc_make_string(tmp_key, atom.type);
503 }
504
505
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 371 times.
460 if (!key)
506 89 return 0;
507
2/4
✓ Branch 0 taken 371 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 371 times.
371 if (atom.size < 0 || str_size >= INT_MAX/2)
508 return AVERROR_INVALIDDATA;
509
510 // Allocates enough space if data_type is a int32 or float32 number, otherwise
511 // worst-case requirement for output string in case of utf8 coded input
512
3/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 330 times.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
371 num = (data_type >= 21 && data_type <= 23);
513
4/4
✓ Branch 0 taken 330 times.
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 324 times.
✓ Branch 3 taken 6 times.
371 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
514 371 str = av_mallocz(str_size_alloc);
515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 371 times.
371 if (!str)
516 return AVERROR(ENOMEM);
517
518
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 311 times.
371 if (parse)
519 60 parse(c, pb, str_size, key);
520 else {
521
8/10
✓ Branch 0 taken 305 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 305 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 100 times.
✓ Branch 5 taken 205 times.
✓ Branch 6 taken 86 times.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 86 times.
311 if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
522 14 mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
523
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 295 times.
297 } else if (data_type == 21) { // BE signed integer, variable size
524 2 int val = 0;
525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (str_size == 1)
526 val = (int8_t)avio_r8(pb);
527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 2)
528 val = (int16_t)avio_rb16(pb);
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 3)
530 val = ((int32_t)(avio_rb24(pb)<<8))>>8;
531
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (str_size == 4)
532 2 val = (int32_t)avio_rb32(pb);
533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
534 av_log(c->fc, AV_LOG_ERROR,
535 "Failed to store the number (%d) in string.\n", val);
536 av_free(str);
537 return AVERROR_INVALIDDATA;
538 }
539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 295 times.
295 } else if (data_type == 22) { // BE unsigned integer, variable size
540 unsigned int val = 0;
541 if (str_size == 1)
542 val = avio_r8(pb);
543 else if (str_size == 2)
544 val = avio_rb16(pb);
545 else if (str_size == 3)
546 val = avio_rb24(pb);
547 else if (str_size == 4)
548 val = avio_rb32(pb);
549 if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
550 av_log(c->fc, AV_LOG_ERROR,
551 "Failed to store the number (%u) in string.\n", val);
552 av_free(str);
553 return AVERROR_INVALIDDATA;
554 }
555
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 282 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
308 } else if (data_type == 23 && str_size >= 4) { // BE float32
556 13 float val = av_int2float(avio_rb32(pb));
557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
558 av_log(c->fc, AV_LOG_ERROR,
559 "Failed to store the float32 number (%f) in string.\n", val);
560 av_free(str);
561 return AVERROR_INVALIDDATA;
562 }
563
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
282 } else if (data_type > 1 && data_type != 4) {
564 // data_type can be 0 if not set at all above. data_type 1 means
565 // UTF8 and 4 means "UTF8 sort". For any other type (UTF16 or e.g.
566 // a picture), don't return it blindly in a string that is supposed
567 // to be UTF8 text.
568 av_log(c->fc, AV_LOG_WARNING, "Skipping unhandled metadata %s of type %d\n", key, data_type);
569 av_free(str);
570 return 0;
571 } else {
572 282 int ret = ffio_read_size(pb, str, str_size);
573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 282 times.
282 if (ret < 0) {
574 av_free(str);
575 return ret;
576 }
577 282 str[str_size] = 0;
578 }
579 311 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
580 311 av_dict_set(metadata, key, str, 0);
581
4/4
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 212 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 62 times.
311 if (*language && strcmp(language, "und")) {
582 37 snprintf(key2, sizeof(key2), "%s-%s", key, language);
583 37 av_dict_set(metadata, key2, str, 0);
584 }
585
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 201 times.
311 if (!strcmp(key, "encoder")) {
586 int major, minor, micro;
587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
110 if (sscanf(str, "HandBrake %d.%d.%d", &major, &minor, &micro) == 3) {
588 c->handbrake_version = 1000000*major + 1000*minor + micro;
589 }
590 }
591 }
592
593 371 av_freep(&str);
594 371 return 0;
595 }
596
597 12 static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
598 {
599 int64_t start;
600 int i, nb_chapters, str_len, version;
601 char str[256+1];
602 int ret;
603
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->ignore_chapters)
605 return 0;
606
607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if ((atom.size -= 5) < 0)
608 return 0;
609
610 12 version = avio_r8(pb);
611 12 avio_rb24(pb);
612
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (version)
613 12 avio_rb32(pb); // ???
614 12 nb_chapters = avio_r8(pb);
615
616
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
30 for (i = 0; i < nb_chapters; i++) {
617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size < 9)
618 return 0;
619
620 18 start = avio_rb64(pb);
621 18 str_len = avio_r8(pb);
622
623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if ((atom.size -= 9+str_len) < 0)
624 return 0;
625
626 18 ret = ffio_read_size(pb, str, str_len);
627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (ret < 0)
628 return ret;
629 18 str[str_len] = 0;
630 18 avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
631 }
632 12 return 0;
633 }
634
635 #define MIN_DATA_ENTRY_BOX_SIZE 12
636 594 static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
637 {
638 AVStream *st;
639 MOVStreamContext *sc;
640 int entries, i, j;
641
642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
643 return 0;
644 594 st = c->fc->streams[c->fc->nb_streams-1];
645 594 sc = st->priv_data;
646
647 594 avio_rb32(pb); // version + flags
648 594 entries = avio_rb32(pb);
649
1/2
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
594 if (!entries ||
650
1/2
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
594 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 entries >= UINT_MAX / sizeof(*sc->drefs))
652 return AVERROR_INVALIDDATA;
653
654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 for (i = 0; i < sc->drefs_count; i++) {
655 MOVDref *dref = &sc->drefs[i];
656 av_freep(&dref->path);
657 av_freep(&dref->dir);
658 }
659 594 av_free(sc->drefs);
660 594 sc->drefs_count = 0;
661 594 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (!sc->drefs)
663 return AVERROR(ENOMEM);
664 594 sc->drefs_count = entries;
665
666
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 594 times.
1188 for (i = 0; i < entries; i++) {
667 594 MOVDref *dref = &sc->drefs[i];
668 594 uint32_t size = avio_rb32(pb);
669 594 int64_t next = avio_tell(pb);
670
671
3/6
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 594 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 594 times.
594 if (size < 12 || next < 0 || next > INT64_MAX - size)
672 return AVERROR_INVALIDDATA;
673
674 594 next += size - 4;
675
676 594 dref->type = avio_rl32(pb);
677 594 avio_rb32(pb); // version + flags
678
679
3/4
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 476 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 118 times.
594 if (dref->type == MKTAG('a','l','i','s') && size > 150) {
680 /* macintosh alias record */
681 uint16_t volume_len, len;
682 int16_t type;
683 int ret;
684
685 avio_skip(pb, 10);
686
687 volume_len = avio_r8(pb);
688 volume_len = FFMIN(volume_len, 27);
689 ret = ffio_read_size(pb, dref->volume, 27);
690 if (ret < 0)
691 return ret;
692 dref->volume[volume_len] = 0;
693 av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
694
695 avio_skip(pb, 12);
696
697 len = avio_r8(pb);
698 len = FFMIN(len, 63);
699 ret = ffio_read_size(pb, dref->filename, 63);
700 if (ret < 0)
701 return ret;
702 dref->filename[len] = 0;
703 av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
704
705 avio_skip(pb, 16);
706
707 /* read next level up_from_alias/down_to_target */
708 dref->nlvl_from = avio_rb16(pb);
709 dref->nlvl_to = avio_rb16(pb);
710 av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
711 dref->nlvl_from, dref->nlvl_to);
712
713 avio_skip(pb, 16);
714
715 for (type = 0; type != -1 && avio_tell(pb) < next; ) {
716 if (avio_feof(pb))
717 return AVERROR_EOF;
718 type = avio_rb16(pb);
719 len = avio_rb16(pb);
720 av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
721 if (len&1)
722 len += 1;
723 if (type == 2) { // absolute path
724 av_free(dref->path);
725 dref->path = av_mallocz(len+1);
726 if (!dref->path)
727 return AVERROR(ENOMEM);
728
729 ret = ffio_read_size(pb, dref->path, len);
730 if (ret < 0) {
731 av_freep(&dref->path);
732 return ret;
733 }
734 if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
735 len -= volume_len;
736 memmove(dref->path, dref->path+volume_len, len);
737 dref->path[len] = 0;
738 }
739 // trim string of any ending zeros
740 for (j = len - 1; j >= 0; j--) {
741 if (dref->path[j] == 0)
742 len--;
743 else
744 break;
745 }
746 for (j = 0; j < len; j++)
747 if (dref->path[j] == ':' || dref->path[j] == 0)
748 dref->path[j] = '/';
749 av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
750 } else if (type == 0) { // directory name
751 av_free(dref->dir);
752 dref->dir = av_malloc(len+1);
753 if (!dref->dir)
754 return AVERROR(ENOMEM);
755
756 ret = ffio_read_size(pb, dref->dir, len);
757 if (ret < 0) {
758 av_freep(&dref->dir);
759 return ret;
760 }
761 dref->dir[len] = 0;
762 for (j = 0; j < len; j++)
763 if (dref->dir[j] == ':')
764 dref->dir[j] = '/';
765 av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
766 } else
767 avio_skip(pb, len);
768 }
769 } else {
770 594 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
771 dref->type, size);
772 594 entries--;
773 594 i--;
774 }
775 594 avio_seek(pb, next, SEEK_SET);
776 }
777 594 return 0;
778 }
779
780 1088 static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
781 {
782 AVStream *st;
783 uint32_t type;
784 uint32_t ctype;
785 int64_t title_size;
786 char *title_str;
787 int ret;
788
789 1088 avio_r8(pb); /* version */
790 1088 avio_rb24(pb); /* flags */
791
792 /* component type */
793 1088 ctype = avio_rl32(pb);
794 1088 type = avio_rl32(pb); /* component subtype */
795
796 1088 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
797 1088 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
798
799
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 951 times.
1088 if (c->trak_index < 0) { // meta not inside a trak
800
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 126 times.
137 if (type == MKTAG('m','d','t','a')) {
801 11 c->found_hdlr_mdta = 1;
802 }
803 137 return 0;
804 }
805
806 951 st = c->fc->streams[c->fc->nb_streams-1];
807
808
2/2
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 649 times.
951 if (type == MKTAG('v','i','d','e'))
809 302 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
810
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 408 times.
649 else if (type == MKTAG('s','o','u','n'))
811 241 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 408 times.
408 else if (type == MKTAG('m','1','a',' '))
813 st->codecpar->codec_id = AV_CODEC_ID_MP2;
814
2/4
✓ Branch 0 taken 408 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 408 times.
408 else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
815 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
816
817 951 avio_rb32(pb); /* component manufacture */
818 951 avio_rb32(pb); /* component flags */
819 951 avio_rb32(pb); /* component flags mask */
820
821 951 title_size = atom.size - 24;
822
2/2
✓ Branch 0 taken 948 times.
✓ Branch 1 taken 3 times.
951 if (title_size > 0) {
823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 948 times.
948 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
824 return AVERROR_INVALIDDATA;
825 948 title_str = av_malloc(title_size + 1); /* Add null terminator */
826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 948 times.
948 if (!title_str)
827 return AVERROR(ENOMEM);
828
829 948 ret = ffio_read_size(pb, title_str, title_size);
830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 948 times.
948 if (ret < 0) {
831 av_freep(&title_str);
832 return ret;
833 }
834 948 title_str[title_size] = 0;
835
2/2
✓ Branch 0 taken 897 times.
✓ Branch 1 taken 51 times.
948 if (title_str[0]) {
836
4/4
✓ Branch 0 taken 690 times.
✓ Branch 1 taken 207 times.
✓ Branch 2 taken 688 times.
✓ Branch 3 taken 2 times.
897 int off = (!c->isom && title_str[0] == title_size - 1);
837 // flag added so as to not set stream handler name if already set from mdia->hdlr
838 897 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
839 }
840 948 av_freep(&title_str);
841 }
842
843 951 return 0;
844 }
845
846 150 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
847 {
848 150 return ff_mov_read_esds(c->fc, pb);
849 }
850
851 7 static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
852 {
853 AVStream *st;
854 AVPacketSideData *sd;
855 enum AVAudioServiceType *ast;
856 int ac3info, acmod, lfeon, bsmod;
857 uint64_t mask;
858
859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (c->fc->nb_streams < 1)
860 return 0;
861 7 st = c->fc->streams[c->fc->nb_streams-1];
862
863 7 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
864 7 &st->codecpar->nb_coded_side_data,
865 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
866 sizeof(*ast), 0);
867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sd)
868 return AVERROR(ENOMEM);
869
870 7 ast = (enum AVAudioServiceType*)sd->data;
871 7 ac3info = avio_rb24(pb);
872 7 bsmod = (ac3info >> 14) & 0x7;
873 7 acmod = (ac3info >> 11) & 0x7;
874 7 lfeon = (ac3info >> 10) & 0x1;
875
876 7 mask = ff_ac3_channel_layout_tab[acmod];
877
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (lfeon)
878 1 mask |= AV_CH_LOW_FREQUENCY;
879 7 av_channel_layout_uninit(&st->codecpar->ch_layout);
880 7 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
881
882 7 *ast = bsmod;
883
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)
884 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
885
886 7 return 0;
887 }
888
889 #if CONFIG_IAMFDEC
890 10 static int mov_read_iacb(MOVContext *c, AVIOContext *pb, MOVAtom atom)
891 {
892 AVStream *st;
893 MOVStreamContext *sc;
894 FFIOContext b;
895 AVIOContext *descriptor_pb;
896 AVDictionary *metadata;
897 IAMFContext *iamf;
898 int64_t start_time, duration;
899 unsigned descriptors_size;
900 int nb_frames, disposition;
901 int version, ret;
902
903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (atom.size < 5)
904 return AVERROR_INVALIDDATA;
905
906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (c->fc->nb_streams < 1)
907 return 0;
908
909 10 version = avio_r8(pb);
910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (version != 1) {
911 av_log(c->fc, AV_LOG_ERROR, "%s configurationVersion %d",
912 version < 1 ? "invalid" : "unsupported", version);
913 return AVERROR_INVALIDDATA;
914 }
915
916 10 descriptors_size = ffio_read_leb(pb);
917
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (!descriptors_size || descriptors_size > INT_MAX)
918 return AVERROR_INVALIDDATA;
919
920 10 st = c->fc->streams[c->fc->nb_streams - 1];
921 10 sc = st->priv_data;
922
923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (st->codecpar->extradata) {
924 av_log(c->fc, AV_LOG_WARNING, "ignoring iacb\n");
925 return 0;
926 }
927
928 10 sc->iamf = av_mallocz(sizeof(*sc->iamf));
929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!sc->iamf)
930 return AVERROR(ENOMEM);
931 10 iamf = &sc->iamf->iamf;
932
933 10 st->codecpar->extradata = av_malloc(descriptors_size);
934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!st->codecpar->extradata)
935 return AVERROR(ENOMEM);
936 10 st->codecpar->extradata_size = descriptors_size;
937
938 10 ret = avio_read(pb, st->codecpar->extradata, descriptors_size);
939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret != descriptors_size)
940 return ret < 0 ? ret : AVERROR_INVALIDDATA;
941
942 10 ffio_init_read_context(&b, st->codecpar->extradata, descriptors_size);
943 10 descriptor_pb = &b.pub;
944
945 10 ret = ff_iamfdec_read_descriptors(iamf, descriptor_pb, descriptors_size, c->fc);
946
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
947 return ret;
948
949 10 metadata = st->metadata;
950 10 st->metadata = NULL;
951 10 start_time = st->start_time;
952 10 nb_frames = st->nb_frames;
953 10 duration = st->duration;
954 10 disposition = st->disposition;
955
956
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_audio_elements; i++) {
957 10 IAMFAudioElement *audio_element = iamf->audio_elements[i];
958 const AVIAMFAudioElement *element;
959 AVStreamGroup *stg =
960 10 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, NULL);
961
962
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!stg) {
963 ret = AVERROR(ENOMEM);
964 goto fail;
965 }
966
967 10 av_iamf_audio_element_free(&stg->params.iamf_audio_element);
968 10 stg->id = audio_element->audio_element_id;
969 /* Transfer ownership */
970 10 element = stg->params.iamf_audio_element = audio_element->element;
971 10 audio_element->element = NULL;
972
973
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int j = 0; j < audio_element->nb_substreams; j++) {
974 50 IAMFSubStream *substream = &audio_element->substreams[j];
975 AVStream *stream;
976
977
3/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 40 times.
50 if (!i && !j) {
978
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (audio_element->layers[0].substream_count != 1)
979 2 disposition &= ~AV_DISPOSITION_DEFAULT;
980 10 stream = st;
981 } else
982 40 stream = avformat_new_stream(c->fc, NULL);
983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (!stream) {
984 ret = AVERROR(ENOMEM);
985 goto fail;
986 }
987
988 50 stream->start_time = start_time;
989 50 stream->nb_frames = nb_frames;
990 50 stream->duration = duration;
991 50 stream->disposition = disposition;
992
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 10 times.
50 if (stream != st) {
993 40 stream->priv_data = sc;
994 40 sc->refcount++;
995 }
996
997
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 42 times.
50 if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
998 8 stream->disposition |= AV_DISPOSITION_DEPENDENT;
999
3/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 10 times.
50 if (i || j) {
1000 40 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1001
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 6 times.
40 if (audio_element->layers[0].substream_count == 1)
1002 34 stream->disposition &= ~AV_DISPOSITION_DEFAULT;
1003 }
1004
1005 50 ret = avcodec_parameters_copy(stream->codecpar, substream->codecpar);
1006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (ret < 0)
1007 goto fail;
1008
1009 50 stream->id = substream->audio_substream_id;
1010
1011 50 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
1012
1013 50 ret = avformat_stream_group_add_stream(stg, stream);
1014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (ret < 0)
1015 goto fail;
1016 }
1017
1018 10 ret = av_dict_copy(&stg->metadata, metadata, 0);
1019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
1020 goto fail;
1021 }
1022
1023
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1024 10 IAMFMixPresentation *mix_presentation = iamf->mix_presentations[i];
1025 10 const AVIAMFMixPresentation *mix = mix_presentation->cmix;
1026 AVStreamGroup *stg =
1027 10 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, NULL);
1028
1029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!stg) {
1030 ret = AVERROR(ENOMEM);
1031 goto fail;
1032 }
1033
1034 10 av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
1035 10 stg->id = mix_presentation->mix_presentation_id;
1036 /* Transfer ownership */
1037 10 stg->params.iamf_mix_presentation = mix_presentation->mix;
1038 10 mix_presentation->mix = NULL;
1039
1040
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 10 times.
22 for (int j = 0; j < mix->nb_submixes; j++) {
1041 12 const AVIAMFSubmix *submix = mix->submixes[j];
1042
1043
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int k = 0; k < submix->nb_elements; k++) {
1044 12 const AVIAMFSubmixElement *submix_element = submix->elements[k];
1045 12 const AVStreamGroup *audio_element = NULL;
1046
1047
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 for (int l = 0; l < c->fc->nb_stream_groups; l++)
1048
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (c->fc->stream_groups[l]->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT &&
1049
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 c->fc->stream_groups[l]->id == submix_element->audio_element_id) {
1050 12 audio_element = c->fc->stream_groups[l];
1051 12 break;
1052 }
1053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 av_assert0(audio_element);
1054
1055
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 12 times.
64 for (int l = 0; l < audio_element->nb_streams; l++) {
1056 52 ret = avformat_stream_group_add_stream(stg, audio_element->streams[l]);
1057
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
52 if (ret < 0 && ret != AVERROR(EEXIST))
1058 goto fail;
1059 }
1060 }
1061 }
1062
1063 10 ret = av_dict_copy(&stg->metadata, metadata, 0);
1064
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
1065 goto fail;
1066 }
1067
1068 10 ret = 0;
1069 10 fail:
1070 10 av_dict_free(&metadata);
1071
1072 10 return ret;
1073 }
1074 #endif
1075
1076 1 static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1077 {
1078 AVStream *st;
1079 AVPacketSideData *sd;
1080 enum AVAudioServiceType *ast;
1081 int eac3info, acmod, lfeon, bsmod;
1082 uint64_t mask;
1083
1084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
1085 return 0;
1086 1 st = c->fc->streams[c->fc->nb_streams-1];
1087
1088 1 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1089 1 &st->codecpar->nb_coded_side_data,
1090 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
1091 sizeof(*ast), 0);
1092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sd)
1093 return AVERROR(ENOMEM);
1094
1095 1 ast = (enum AVAudioServiceType*)sd->data;
1096
1097 /* No need to parse fields for additional independent substreams and its
1098 * associated dependent substreams since libavcodec's E-AC-3 decoder
1099 * does not support them yet. */
1100 1 avio_rb16(pb); /* data_rate and num_ind_sub */
1101 1 eac3info = avio_rb24(pb);
1102 1 bsmod = (eac3info >> 12) & 0x1f;
1103 1 acmod = (eac3info >> 9) & 0x7;
1104 1 lfeon = (eac3info >> 8) & 0x1;
1105
1106 1 mask = ff_ac3_channel_layout_tab[acmod];
1107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (lfeon)
1108 mask |= AV_CH_LOW_FREQUENCY;
1109 1 av_channel_layout_uninit(&st->codecpar->ch_layout);
1110 1 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
1111
1112 1 *ast = bsmod;
1113
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)
1114 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
1115
1116 1 return 0;
1117 }
1118
1119 static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1120 {
1121 #define DDTS_SIZE 20
1122 uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
1123 AVStream *st = NULL;
1124 uint32_t frame_duration_code = 0;
1125 uint32_t channel_layout_code = 0;
1126 GetBitContext gb;
1127 int ret;
1128
1129 if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
1130 return ret;
1131
1132 init_get_bits(&gb, buf, 8 * DDTS_SIZE);
1133
1134 if (c->fc->nb_streams < 1) {
1135 return 0;
1136 }
1137 st = c->fc->streams[c->fc->nb_streams-1];
1138
1139 st->codecpar->sample_rate = get_bits_long(&gb, 32);
1140 if (st->codecpar->sample_rate <= 0) {
1141 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
1142 return AVERROR_INVALIDDATA;
1143 }
1144 skip_bits_long(&gb, 32); /* max bitrate */
1145 st->codecpar->bit_rate = get_bits_long(&gb, 32);
1146 st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
1147 frame_duration_code = get_bits(&gb, 2);
1148 skip_bits(&gb, 30); /* various fields */
1149 channel_layout_code = get_bits(&gb, 16);
1150
1151 st->codecpar->frame_size =
1152 (frame_duration_code == 0) ? 512 :
1153 (frame_duration_code == 1) ? 1024 :
1154 (frame_duration_code == 2) ? 2048 :
1155 (frame_duration_code == 3) ? 4096 : 0;
1156
1157 if (channel_layout_code > 0xff) {
1158 av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout\n");
1159 }
1160 av_channel_layout_uninit(&st->codecpar->ch_layout);
1161 av_channel_layout_from_mask(&st->codecpar->ch_layout,
1162 ((channel_layout_code & 0x1) ? AV_CH_FRONT_CENTER : 0) |
1163 ((channel_layout_code & 0x2) ? AV_CH_FRONT_LEFT : 0) |
1164 ((channel_layout_code & 0x2) ? AV_CH_FRONT_RIGHT : 0) |
1165 ((channel_layout_code & 0x4) ? AV_CH_SIDE_LEFT : 0) |
1166 ((channel_layout_code & 0x4) ? AV_CH_SIDE_RIGHT : 0) |
1167 ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0));
1168
1169 return 0;
1170 }
1171
1172 51 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1173 {
1174 AVStream *st;
1175
1176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (c->fc->nb_streams < 1)
1177 return 0;
1178 51 st = c->fc->streams[c->fc->nb_streams-1];
1179
1180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (atom.size < 16)
1181 return 0;
1182
1183 /* skip version and flags */
1184 51 avio_skip(pb, 4);
1185
1186 51 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
1187
1188 51 return 0;
1189 }
1190
1191 5 static int mov_read_chnl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1192 {
1193 5 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
1194 int version, flags;
1195 int ret;
1196 AVStream *st;
1197
1198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
1199 return 0;
1200 5 st = c->fc->streams[c->fc->nb_streams-1];
1201
1202 5 version = avio_r8(pb);
1203 5 flags = avio_rb24(pb);
1204
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) {
1205 av_log(c->fc, AV_LOG_ERROR,
1206 "Unsupported 'chnl' box with version %d, flags: %#x",
1207 version, flags);
1208 return AVERROR_INVALIDDATA;
1209 }
1210
1211 5 ret = ff_mov_read_chnl(c->fc, pb, st);
1212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
1213 return ret;
1214
1215
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_tell(pb) != end) {
1216 av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data inside chnl\n",
1217 end - avio_tell(pb));
1218 avio_seek(pb, end, SEEK_SET);
1219 }
1220 5 return ret;
1221 }
1222
1223 2 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1224 {
1225 AVStream *st;
1226 int ret;
1227
1228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
1229 return 0;
1230 2 st = c->fc->streams[c->fc->nb_streams-1];
1231
1232
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)
1233 av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
1234
1235 2 return ret;
1236 }
1237
1238 18 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1239 {
1240 AVStream *st;
1241 HEIFItem *item;
1242 AVPacketSideData *sd;
1243 18 int width, height, err = 0;
1244 AVRational aperture_width, aperture_height, horiz_off, vert_off;
1245 AVRational pc_x, pc_y;
1246 uint64_t top, bottom, left, right;
1247
1248 18 item = heif_cur_item(c);
1249 18 st = get_curr_st(c);
1250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!st)
1251 return 0;
1252
1253 18 width = st->codecpar->width;
1254 18 height = st->codecpar->height;
1255
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) {
1256 6 width = item->width;
1257 6 height = item->height;
1258 }
1259
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (!width || !height) {
1260 err = AVERROR_INVALIDDATA;
1261 goto fail;
1262 }
1263
1264 18 aperture_width.num = avio_rb32(pb);
1265 18 aperture_width.den = avio_rb32(pb);
1266 18 aperture_height.num = avio_rb32(pb);
1267 18 aperture_height.den = avio_rb32(pb);
1268
1269 18 horiz_off.num = avio_rb32(pb);
1270 18 horiz_off.den = avio_rb32(pb);
1271 18 vert_off.num = avio_rb32(pb);
1272 18 vert_off.den = avio_rb32(pb);
1273
1274
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 ||
1275
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 ||
1276
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) {
1277 err = AVERROR_INVALIDDATA;
1278 goto fail;
1279 }
1280 18 av_log(c->fc, AV_LOG_TRACE, "clap: apertureWidth %d/%d, apertureHeight %d/%d "
1281 "horizOff %d/%d vertOff %d/%d\n",
1282 aperture_width.num, aperture_width.den, aperture_height.num, aperture_height.den,
1283 horiz_off.num, horiz_off.den, vert_off.num, vert_off.den);
1284
1285 18 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1286 18 pc_x = av_add_q(pc_x, horiz_off);
1287 18 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1288 18 pc_y = av_add_q(pc_y, vert_off);
1289
1290 18 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1291 18 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1292 18 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1293 18 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1294
1295 18 left = av_q2d(av_sub_q(pc_x, aperture_width));
1296 18 right = av_q2d(av_add_q(pc_x, aperture_width));
1297 18 top = av_q2d(av_sub_q(pc_y, aperture_height));
1298 18 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1299
1300
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 3 times.
18 if (bottom > (height - 1) ||
1301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 right > (width - 1)) {
1302 3 err = AVERROR_INVALIDDATA;
1303 3 goto fail;
1304 }
1305
1306 15 bottom = height - 1 - bottom;
1307 15 right = width - 1 - right;
1308
1309
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
15 if (!(left | right | top | bottom))
1310 6 return 0;
1311
1312
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if ((left + right) >= width ||
1313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 (top + bottom) >= height) {
1314 err = AVERROR_INVALIDDATA;
1315 goto fail;
1316 }
1317
1318 9 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1319 9 &st->codecpar->nb_coded_side_data,
1320 AV_PKT_DATA_FRAME_CROPPING,
1321 sizeof(uint32_t) * 4, 0);
1322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sd)
1323 return AVERROR(ENOMEM);
1324
1325 9 AV_WL32A(sd->data, top);
1326 9 AV_WL32A(sd->data + 4, bottom);
1327 9 AV_WL32A(sd->data + 8, left);
1328 9 AV_WL32A(sd->data + 12, right);
1329
1330 12 fail:
1331
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 if (err < 0) {
1332 3 int explode = !!(c->fc->error_recognition & AV_EF_EXPLODE);
1333
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");
1334
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!explode)
1335 3 err = 0;
1336 }
1337
1338 12 return err;
1339 }
1340
1341 /* This atom overrides any previously set aspect ratio */
1342 66 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1343 {
1344 66 const int num = avio_rb32(pb);
1345 66 const int den = avio_rb32(pb);
1346 AVStream *st;
1347 MOVStreamContext *sc;
1348
1349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (c->fc->nb_streams < 1)
1350 return 0;
1351 66 st = c->fc->streams[c->fc->nb_streams-1];
1352 66 sc = st->priv_data;
1353
1354 66 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1355
1356
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 2 times.
66 if (den != 0) {
1357 64 sc->h_spacing = num;
1358 64 sc->v_spacing = den;
1359 }
1360 66 return 0;
1361 }
1362
1363 /* this atom contains actual media data */
1364 874 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1365 {
1366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 874 times.
874 if (atom.size == 0) /* wrong one (MP4) */
1367 return 0;
1368 874 c->found_mdat=1;
1369 874 return 0; /* now go for moov */
1370 }
1371
1372 #define DRM_BLOB_SIZE 56
1373
1374 static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1375 {
1376 uint8_t intermediate_key[20];
1377 uint8_t intermediate_iv[20];
1378 uint8_t input[64];
1379 uint8_t output[64];
1380 uint8_t file_checksum[20];
1381 uint8_t calculated_checksum[20];
1382 char checksum_string[2 * sizeof(file_checksum) + 1];
1383 struct AVSHA *sha;
1384 int i;
1385 int ret = 0;
1386 uint8_t *activation_bytes = c->activation_bytes;
1387 uint8_t *fixed_key = c->audible_fixed_key;
1388
1389 c->aax_mode = 1;
1390
1391 sha = av_sha_alloc();
1392 if (!sha)
1393 return AVERROR(ENOMEM);
1394 av_free(c->aes_decrypt);
1395 c->aes_decrypt = av_aes_alloc();
1396 if (!c->aes_decrypt) {
1397 ret = AVERROR(ENOMEM);
1398 goto fail;
1399 }
1400
1401 /* drm blob processing */
1402 avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1403 avio_read(pb, input, DRM_BLOB_SIZE);
1404 avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1405 avio_read(pb, file_checksum, 20);
1406
1407 // required by external tools
1408 ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1);
1409 av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string);
1410
1411 /* verify activation data */
1412 if (!activation_bytes) {
1413 av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1414 ret = 0; /* allow ffprobe to continue working on .aax files */
1415 goto fail;
1416 }
1417 if (c->activation_bytes_size != 4) {
1418 av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1419 ret = AVERROR(EINVAL);
1420 goto fail;
1421 }
1422
1423 /* verify fixed key */
1424 if (c->audible_fixed_key_size != 16) {
1425 av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1426 ret = AVERROR(EINVAL);
1427 goto fail;
1428 }
1429
1430 /* AAX (and AAX+) key derivation */
1431 av_sha_init(sha, 160);
1432 av_sha_update(sha, fixed_key, 16);
1433 av_sha_update(sha, activation_bytes, 4);
1434 av_sha_final(sha, intermediate_key);
1435 av_sha_init(sha, 160);
1436 av_sha_update(sha, fixed_key, 16);
1437 av_sha_update(sha, intermediate_key, 20);
1438 av_sha_update(sha, activation_bytes, 4);
1439 av_sha_final(sha, intermediate_iv);
1440 av_sha_init(sha, 160);
1441 av_sha_update(sha, intermediate_key, 16);
1442 av_sha_update(sha, intermediate_iv, 16);
1443 av_sha_final(sha, calculated_checksum);
1444 if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1445 av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1446 ret = AVERROR_INVALIDDATA;
1447 goto fail;
1448 }
1449 av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1450 av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1451 for (i = 0; i < 4; i++) {
1452 // file data (in output) is stored in big-endian mode
1453 if (activation_bytes[i] != output[3 - i]) { // critical error
1454 av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1455 ret = AVERROR_INVALIDDATA;
1456 goto fail;
1457 }
1458 }
1459 memcpy(c->file_key, output + 8, 16);
1460 memcpy(input, output + 26, 16);
1461 av_sha_init(sha, 160);
1462 av_sha_update(sha, input, 16);
1463 av_sha_update(sha, c->file_key, 16);
1464 av_sha_update(sha, fixed_key, 16);
1465 av_sha_final(sha, c->file_iv);
1466
1467 fail:
1468 av_free(sha);
1469
1470 return ret;
1471 }
1472
1473 static int mov_aaxc_crypto(MOVContext *c)
1474 {
1475 if (c->audible_key_size != 16) {
1476 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n");
1477 return AVERROR(EINVAL);
1478 }
1479
1480 if (c->audible_iv_size != 16) {
1481 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n");
1482 return AVERROR(EINVAL);
1483 }
1484
1485 c->aes_decrypt = av_aes_alloc();
1486 if (!c->aes_decrypt) {
1487 return AVERROR(ENOMEM);
1488 }
1489
1490 memcpy(c->file_key, c->audible_key, 16);
1491 memcpy(c->file_iv, c->audible_iv, 16);
1492 c->aax_mode = 1;
1493
1494 return 0;
1495 }
1496
1497 // Audible AAX (and AAX+) bytestream decryption
1498 static int aax_filter(uint8_t *input, int size, MOVContext *c)
1499 {
1500 int blocks = 0;
1501 unsigned char iv[16];
1502
1503 memcpy(iv, c->file_iv, 16); // iv is overwritten
1504 blocks = size >> 4; // trailing bytes are not encrypted!
1505 av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1506 av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1507
1508 return 0;
1509 }
1510
1511 /* read major brand, minor version and compatible brands and store them as metadata */
1512 453 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1513 {
1514 uint32_t minor_ver;
1515 int comp_brand_size;
1516 char* comp_brands_str;
1517 453 uint8_t type[5] = {0};
1518 453 int ret = ffio_read_size(pb, type, 4);
1519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 453 times.
453 if (ret < 0)
1520 return ret;
1521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 453 times.
453 if (c->fc->nb_streams) {
1522 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1523 return AVERROR_INVALIDDATA;
1524 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate FTYP\n");
1525 return 0;
1526 }
1527
1528
2/2
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 232 times.
453 if (strcmp(type, "qt "))
1529 221 c->isom = 1;
1530 453 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1531 453 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1532 453 minor_ver = avio_rb32(pb); /* minor version */
1533 453 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1534
1535 453 comp_brand_size = atom.size - 8;
1536
2/4
✓ Branch 0 taken 453 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 453 times.
453 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1537 return AVERROR_INVALIDDATA;
1538 453 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 453 times.
453 if (!comp_brands_str)
1540 return AVERROR(ENOMEM);
1541
1542 453 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 453 times.
453 if (ret < 0) {
1544 av_freep(&comp_brands_str);
1545 return ret;
1546 }
1547 453 comp_brands_str[comp_brand_size] = 0;
1548 453 av_dict_set(&c->fc->metadata, "compatible_brands",
1549 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1550
1551 // Logic for handling Audible's .aaxc files
1552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 453 times.
453 if (!strcmp(type, "aaxc")) {
1553 mov_aaxc_crypto(c);
1554 }
1555
1556 453 return 0;
1557 }
1558
1559 /* this atom should contain all header atoms */
1560 484 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1561 {
1562 int ret;
1563
1564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
484 if (c->found_moov) {
1565 av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1566 avio_skip(pb, atom.size);
1567 return 0;
1568 }
1569
1570
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 484 times.
484 if ((ret = mov_read_default(c, pb, atom)) < 0)
1571 return ret;
1572 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1573 /* so we don't parse the whole file if over a network */
1574 484 c->found_moov=1;
1575 484 return 0; /* now go for mdat */
1576 }
1577
1578 2869 static MOVFragmentStreamInfo * get_frag_stream_info(
1579 MOVFragmentIndex *frag_index,
1580 int index,
1581 int id)
1582 {
1583 int i;
1584 MOVFragmentIndexItem * item;
1585
1586
2/4
✓ Branch 0 taken 2869 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2869 times.
2869 if (index < 0 || index >= frag_index->nb_items)
1587 return NULL;
1588 2869 item = &frag_index->item[index];
1589
1/2
✓ Branch 0 taken 2993 times.
✗ Branch 1 not taken.
2993 for (i = 0; i < item->nb_stream_info; i++)
1590
2/2
✓ Branch 0 taken 2869 times.
✓ Branch 1 taken 124 times.
2993 if (item->stream_info[i].id == id)
1591 2869 return &item->stream_info[i];
1592
1593 // This shouldn't happen
1594 return NULL;
1595 }
1596
1597 388 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1598 {
1599 int i;
1600 MOVFragmentIndexItem * item;
1601
1602
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_index->current < 0 ||
1603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 frag_index->current >= frag_index->nb_items)
1604 return;
1605
1606 388 item = &frag_index->item[frag_index->current];
1607
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < item->nb_stream_info; i++)
1608
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (item->stream_info[i].id == id) {
1609 388 item->current = i;
1610 388 return;
1611 }
1612
1613 // id not found. This shouldn't happen.
1614 item->current = -1;
1615 }
1616
1617 1149 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1618 MOVFragmentIndex *frag_index)
1619 {
1620 MOVFragmentIndexItem *item;
1621
1/2
✓ Branch 0 taken 1149 times.
✗ Branch 1 not taken.
1149 if (frag_index->current < 0 ||
1622
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1146 times.
1149 frag_index->current >= frag_index->nb_items)
1623 3 return NULL;
1624
1625 1146 item = &frag_index->item[frag_index->current];
1626
2/4
✓ Branch 0 taken 1146 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1146 times.
✗ Branch 3 not taken.
1146 if (item->current >= 0 && item->current < item->nb_stream_info)
1627 1146 return &item->stream_info[item->current];
1628
1629 // This shouldn't happen
1630 return NULL;
1631 }
1632
1633 798 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1634 {
1635 int a, b, m;
1636 int64_t moof_offset;
1637
1638 // Optimize for appending new entries
1639
2/2
✓ Branch 0 taken 788 times.
✓ Branch 1 taken 10 times.
798 if (!frag_index->nb_items ||
1640
2/2
✓ Branch 0 taken 383 times.
✓ Branch 1 taken 405 times.
788 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1641 393 return frag_index->nb_items;
1642
1643 405 a = -1;
1644 405 b = frag_index->nb_items;
1645
1646
2/2
✓ Branch 0 taken 2655 times.
✓ Branch 1 taken 405 times.
3060 while (b - a > 1) {
1647 2655 m = (a + b) >> 1;
1648 2655 moof_offset = frag_index->item[m].moof_offset;
1649
2/2
✓ Branch 0 taken 732 times.
✓ Branch 1 taken 1923 times.
2655 if (moof_offset >= offset)
1650 732 b = m;
1651
2/2
✓ Branch 0 taken 2328 times.
✓ Branch 1 taken 327 times.
2655 if (moof_offset <= offset)
1652 2328 a = m;
1653 }
1654 405 return b;
1655 }
1656
1657 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1658 {
1659 av_assert0(frag_stream_info);
1660 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1661 return frag_stream_info->sidx_pts;
1662 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1663 return frag_stream_info->first_tfra_pts;
1664 return frag_stream_info->tfdt_dts;
1665 }
1666
1667 219 static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1668 MOVFragmentIndex *frag_index, int index)
1669 {
1670 MOVFragmentStreamInfo * frag_stream_info;
1671 219 MOVStreamContext *sc = dst_st->priv_data;
1672 int64_t timestamp;
1673 int i, j;
1674
1675 // If the stream is referenced by any sidx, limit the search
1676 // to fragments that referenced this stream in the sidx
1677
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (sc->has_sidx) {
1678 219 frag_stream_info = get_frag_stream_info(frag_index, index, sc->id);
1679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!frag_stream_info)
1680 return AV_NOPTS_VALUE;
1681
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1682 219 return frag_stream_info->sidx_pts;
1683 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1684 return frag_stream_info->first_tfra_pts;
1685 return frag_stream_info->sidx_pts;
1686 }
1687
1688 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
1689 AVStream *frag_stream = NULL;
1690 frag_stream_info = &frag_index->item[index].stream_info[i];
1691 for (j = 0; j < s->nb_streams; j++) {
1692 MOVStreamContext *sc2 = s->streams[j]->priv_data;
1693 if (sc2->id == frag_stream_info->id)
1694 frag_stream = s->streams[j];
1695 }
1696 if (!frag_stream) {
1697 av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1698 continue;
1699 }
1700 timestamp = get_stream_info_time(frag_stream_info);
1701 if (timestamp != AV_NOPTS_VALUE)
1702 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1703 }
1704 return AV_NOPTS_VALUE;
1705 }
1706
1707 26 static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1708 AVStream *st, int64_t timestamp)
1709 {
1710 int a, b, m, m0;
1711 int64_t frag_time;
1712
1713 26 a = -1;
1714 26 b = frag_index->nb_items;
1715
1716
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 26 times.
245 while (b - a > 1) {
1717 219 m0 = m = (a + b) >> 1;
1718
1719
2/4
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 219 times.
438 while (m < b &&
1720 219 (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
1721 m++;
1722
1723
3/4
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 93 times.
✓ Branch 3 taken 126 times.
219 if (m < b && frag_time <= timestamp)
1724 93 a = m;
1725 else
1726 126 b = m0;
1727 }
1728
1729 26 return a;
1730 }
1731
1732 756 static int update_frag_index(MOVContext *c, int64_t offset)
1733 {
1734 int index, i;
1735 MOVFragmentIndexItem * item;
1736 MOVFragmentStreamInfo * frag_stream_info;
1737
1738 // If moof_offset already exists in frag_index, return index to it
1739 756 index = search_frag_moof_offset(&c->frag_index, offset);
1740
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 389 times.
756 if (index < c->frag_index.nb_items &&
1741
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 c->frag_index.item[index].moof_offset == offset)
1742 367 return index;
1743
1744 // offset is not yet in frag index.
1745 // Insert new item at index (sorted by moof offset)
1746 389 item = av_fast_realloc(c->frag_index.item,
1747 389 &c->frag_index.allocated_size,
1748 389 (c->frag_index.nb_items + 1) *
1749 sizeof(*c->frag_index.item));
1750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (!item)
1751 return -1;
1752 389 c->frag_index.item = item;
1753
1754 389 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1755 sizeof(*item->stream_info));
1756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (!frag_stream_info)
1757 return -1;
1758
1759
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 389 times.
796 for (i = 0; i < c->fc->nb_streams; i++) {
1760 // Avoid building frag index if streams lack track id.
1761 407 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 407 times.
407 if (sc->id < 0) {
1763 av_free(frag_stream_info);
1764 return AVERROR_INVALIDDATA;
1765 }
1766
1767 407 frag_stream_info[i].id = sc->id;
1768 407 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1769 407 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1770 407 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1771 407 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1772 407 frag_stream_info[i].index_base = -1;
1773 407 frag_stream_info[i].index_entry = -1;
1774 407 frag_stream_info[i].encryption_index = NULL;
1775 407 frag_stream_info[i].stsd_id = -1;
1776 }
1777
1778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
389 if (index < c->frag_index.nb_items)
1779 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1780 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1781
1782 389 item = &c->frag_index.item[index];
1783 389 item->headers_read = 0;
1784 389 item->current = 0;
1785 389 item->nb_stream_info = c->fc->nb_streams;
1786 389 item->moof_offset = offset;
1787 389 item->stream_info = frag_stream_info;
1788 389 c->frag_index.nb_items++;
1789
1790 389 return index;
1791 }
1792
1793 388 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1794 int id, int entries)
1795 {
1796 int i;
1797 MOVFragmentStreamInfo * frag_stream_info;
1798
1799
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (index < 0)
1800 388 return;
1801 for (i = index; i < frag_index->nb_items; i++) {
1802 frag_stream_info = get_frag_stream_info(frag_index, i, id);
1803 if (frag_stream_info && frag_stream_info->index_entry >= 0)
1804 frag_stream_info->index_entry += entries;
1805 }
1806 }
1807
1808 388 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1809 {
1810 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1811 388 c->fragment.found_tfhd = 0;
1812
1813
2/4
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 388 times.
388 if (!c->has_looked_for_mfra && c->use_mfra_for > 0) {
1814 c->has_looked_for_mfra = 1;
1815 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1816 int ret;
1817 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1818 "for a mfra\n");
1819 if ((ret = mov_read_mfra(c, pb)) < 0) {
1820 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1821 "read the mfra (may be a live ismv)\n");
1822 }
1823 } else {
1824 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1825 "seekable, can not look for mfra\n");
1826 }
1827 }
1828 388 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1829 388 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1830 388 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1831 388 return mov_read_default(c, pb, atom);
1832 }
1833
1834 1075 static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version)
1835 {
1836 int64_t time;
1837
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1064 times.
1075 if (version == 1) {
1838 11 time = avio_rb64(pb);
1839 11 avio_rb64(pb);
1840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (time < 0) {
1841 av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n");
1842 return;
1843 }
1844 } else {
1845 1064 time = avio_rb32(pb);
1846 1064 avio_rb32(pb); /* modification time */
1847
4/4
✓ Branch 0 taken 519 times.
✓ Branch 1 taken 545 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 471 times.
1064 if (time > 0 && time < 2082844800) {
1848 48 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1849 48 time += 2082844800;
1850 }
1851 }
1852
2/2
✓ Branch 0 taken 525 times.
✓ Branch 1 taken 550 times.
1075 if (time) {
1853 525 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1854
1855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 525 times.
525 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1856 av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n");
1857 return;
1858 }
1859
1860 525 ff_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1861 }
1862 }
1863
1864 594 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1865 {
1866 AVStream *st;
1867 MOVStreamContext *sc;
1868 int version;
1869 594 char language[4] = {0};
1870 unsigned lang;
1871
1872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
1873 return 0;
1874 594 st = c->fc->streams[c->fc->nb_streams-1];
1875 594 sc = st->priv_data;
1876
1877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (sc->time_scale) {
1878 av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
1879 return AVERROR_INVALIDDATA;
1880 }
1881
1882 594 version = avio_r8(pb);
1883
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (version > 1) {
1884 avpriv_request_sample(c->fc, "Version %d", version);
1885 return AVERROR_PATCHWELCOME;
1886 }
1887 594 avio_rb24(pb); /* flags */
1888 594 mov_metadata_creation_time(c, pb, &st->metadata, version);
1889
1890 594 sc->time_scale = avio_rb32(pb);
1891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (sc->time_scale <= 0) {
1892 av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
1893 sc->time_scale = 1;
1894 }
1895
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 585 times.
594 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1896
1897
6/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 585 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 585 times.
✓ Branch 5 taken 4 times.
594 if ((version == 1 && st->duration == UINT64_MAX) ||
1898
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 585 times.
585 (version != 1 && st->duration == UINT32_MAX)) {
1899 5 st->duration = 0;
1900 }
1901
1902 594 lang = avio_rb16(pb); /* language */
1903
2/2
✓ Branch 1 taken 422 times.
✓ Branch 2 taken 172 times.
594 if (ff_mov_lang_to_iso639(lang, language))
1904 422 av_dict_set(&st->metadata, "language", language, 0);
1905 594 avio_rb16(pb); /* quality */
1906
1907 594 return 0;
1908 }
1909
1910 481 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1911 {
1912 int i;
1913 481 int version = avio_r8(pb); /* version */
1914 481 avio_rb24(pb); /* flags */
1915
1916 481 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
1917 481 c->time_scale = avio_rb32(pb); /* time scale */
1918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 481 times.
481 if (c->time_scale <= 0) {
1919 av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
1920 c->time_scale = 1;
1921 }
1922 481 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
1923
1924
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 479 times.
481 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1925 481 avio_rb32(pb); /* preferred scale */
1926
1927 481 avio_rb16(pb); /* preferred volume */
1928
1929 481 avio_skip(pb, 10); /* reserved */
1930
1931 /* movie display matrix, store it in main context and use it later on */
1932
2/2
✓ Branch 0 taken 1443 times.
✓ Branch 1 taken 481 times.
1924 for (i = 0; i < 3; i++) {
1933 1443 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
1934 1443 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
1935 1443 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
1936 }
1937
1938 481 avio_rb32(pb); /* preview time */
1939 481 avio_rb32(pb); /* preview duration */
1940 481 avio_rb32(pb); /* poster time */
1941 481 avio_rb32(pb); /* selection time */
1942 481 avio_rb32(pb); /* selection duration */
1943 481 avio_rb32(pb); /* current time */
1944 481 avio_rb32(pb); /* next track ID */
1945
1946 481 return 0;
1947 }
1948
1949 7 static void set_last_stream_little_endian(AVFormatContext *fc)
1950 {
1951 AVStream *st;
1952
1953
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (fc->nb_streams < 1)
1954 return;
1955 7 st = fc->streams[fc->nb_streams-1];
1956
1957
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) {
1958 5 case AV_CODEC_ID_PCM_S16BE:
1959 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
1960 5 break;
1961 1 case AV_CODEC_ID_PCM_S24BE:
1962 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
1963 1 break;
1964 case AV_CODEC_ID_PCM_S32BE:
1965 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
1966 break;
1967 1 case AV_CODEC_ID_PCM_F32BE:
1968 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
1969 1 break;
1970 case AV_CODEC_ID_PCM_F64BE:
1971 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
1972 break;
1973 default:
1974 break;
1975 }
1976 }
1977
1978 5 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1979 {
1980 5 int little_endian = avio_rb16(pb) & 0xFF;
1981 5 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
1982
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (little_endian == 1)
1983 1 set_last_stream_little_endian(c->fc);
1984 5 return 0;
1985 }
1986
1987 6 static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1988 {
1989 int format_flags;
1990 int version, flags;
1991 int pcm_sample_size;
1992 6 AVFormatContext *fc = c->fc;
1993 AVStream *st;
1994 MOVStreamContext *sc;
1995
1996
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 6) {
1997 av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n");
1998 return AVERROR_INVALIDDATA;
1999 }
2000
2001 6 version = avio_r8(pb);
2002 6 flags = avio_rb24(pb);
2003
2004
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) {
2005 av_log(c->fc, AV_LOG_ERROR,
2006 "Unsupported 'pcmC' box with version %d, flags: %x",
2007 version, flags);
2008 return AVERROR_INVALIDDATA;
2009 }
2010
2011 6 format_flags = avio_r8(pb);
2012 6 pcm_sample_size = avio_r8(pb);
2013
2014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fc->nb_streams < 1)
2015 return AVERROR_INVALIDDATA;
2016
2017 6 st = fc->streams[fc->nb_streams - 1];
2018 6 sc = st->priv_data;
2019
2020
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (sc->format == MOV_MP4_FPCM_TAG) {
2021
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (pcm_sample_size) {
2022 1 case 32:
2023 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE;
2024 1 break;
2025 case 64:
2026 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE;
2027 break;
2028 default:
2029 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2030 pcm_sample_size,
2031 av_fourcc2str(sc->format));
2032 return AVERROR_INVALIDDATA;
2033 }
2034
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (sc->format == MOV_MP4_IPCM_TAG) {
2035
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 switch (pcm_sample_size) {
2036 5 case 16:
2037 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2038 5 break;
2039 case 24:
2040 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
2041 break;
2042 case 32:
2043 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
2044 break;
2045 default:
2046 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2047 pcm_sample_size,
2048 av_fourcc2str(sc->format));
2049 return AVERROR_INVALIDDATA;
2050 }
2051 } else {
2052 av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n",
2053 av_fourcc2str(sc->format));
2054 return AVERROR_INVALIDDATA;
2055 }
2056
2057
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
2058 6 set_last_stream_little_endian(c->fc);
2059 6 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2060
2061 6 return 0;
2062 }
2063
2064 43 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2065 {
2066 AVStream *st;
2067 43 HEIFItem *item = NULL;
2068 43 char color_parameter_type[5] = { 0 };
2069 uint16_t color_primaries, color_trc, color_matrix;
2070 int ret;
2071
2072 43 st = get_curr_st(c);
2073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st) {
2074 item = heif_cur_item(c);
2075 if (!item)
2076 return 0;
2077 }
2078
2079 43 ret = ffio_read_size(pb, color_parameter_type, 4);
2080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
2081 return ret;
2082
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 10 times.
43 if (strncmp(color_parameter_type, "nclx", 4) &&
2083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 strncmp(color_parameter_type, "nclc", 4) &&
2084 strncmp(color_parameter_type, "prof", 4)) {
2085 av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
2086 color_parameter_type);
2087 return 0;
2088 }
2089
2090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!strncmp(color_parameter_type, "prof", 4)) {
2091 AVPacketSideData *sd;
2092 uint8_t *icc_profile;
2093 if (st) {
2094 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
2095 &st->codecpar->nb_coded_side_data,
2096 AV_PKT_DATA_ICC_PROFILE,
2097 atom.size - 4, 0);
2098 if (!sd)
2099 return AVERROR(ENOMEM);
2100 icc_profile = sd->data;
2101 } else {
2102 av_freep(&item->icc_profile);
2103 icc_profile = item->icc_profile = av_malloc(atom.size - 4);
2104 if (!icc_profile) {
2105 item->icc_profile_size = 0;
2106 return AVERROR(ENOMEM);
2107 }
2108 item->icc_profile_size = atom.size - 4;
2109 }
2110 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
2111 if (ret < 0)
2112 return ret;
2113
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 } else if (st) {
2114 43 color_primaries = avio_rb16(pb);
2115 43 color_trc = avio_rb16(pb);
2116 43 color_matrix = avio_rb16(pb);
2117
2118 43 av_log(c->fc, AV_LOG_TRACE,
2119 "%s: pri %d trc %d matrix %d",
2120 color_parameter_type, color_primaries, color_trc, color_matrix);
2121
2122
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 33 times.
43 if (!strncmp(color_parameter_type, "nclx", 4)) {
2123 10 uint8_t color_range = avio_r8(pb) >> 7;
2124 10 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (color_range)
2126 st->codecpar->color_range = AVCOL_RANGE_JPEG;
2127 else
2128 10 st->codecpar->color_range = AVCOL_RANGE_MPEG;
2129 }
2130
2131
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_primaries_name(color_primaries))
2132 color_primaries = AVCOL_PRI_UNSPECIFIED;
2133
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_transfer_name(color_trc))
2134 color_trc = AVCOL_TRC_UNSPECIFIED;
2135
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (!av_color_space_name(color_matrix))
2136 color_matrix = AVCOL_SPC_UNSPECIFIED;
2137
2138 43 st->codecpar->color_primaries = color_primaries;
2139 43 st->codecpar->color_trc = color_trc;
2140 43 st->codecpar->color_space = color_matrix;
2141 43 av_log(c->fc, AV_LOG_TRACE, "\n");
2142 }
2143 43 return 0;
2144 }
2145
2146 112 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2147 {
2148 AVStream *st;
2149 unsigned mov_field_order;
2150 112 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2151
2152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (c->fc->nb_streams < 1) // will happen with jp2 files
2153 return 0;
2154 112 st = c->fc->streams[c->fc->nb_streams-1];
2155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (atom.size < 2)
2156 return AVERROR_INVALIDDATA;
2157 112 mov_field_order = avio_rb16(pb);
2158
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 20 times.
112 if ((mov_field_order & 0xFF00) == 0x0100)
2159 92 decoded_field_order = AV_FIELD_PROGRESSIVE;
2160
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 else if ((mov_field_order & 0xFF00) == 0x0200) {
2161
3/5
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
20 switch (mov_field_order & 0xFF) {
2162 1 case 0x01: decoded_field_order = AV_FIELD_TT;
2163 1 break;
2164 case 0x06: decoded_field_order = AV_FIELD_BB;
2165 break;
2166 1 case 0x09: decoded_field_order = AV_FIELD_TB;
2167 1 break;
2168 18 case 0x0E: decoded_field_order = AV_FIELD_BT;
2169 18 break;
2170 }
2171 }
2172
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
112 if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) {
2173 av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
2174 }
2175 112 st->codecpar->field_order = decoded_field_order;
2176
2177 112 return 0;
2178 }
2179
2180 68 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
2181 {
2182 68 int err = 0;
2183 68 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
2184
2/4
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 68 times.
68 if (size > INT_MAX || (uint64_t)atom.size > INT_MAX)
2185 return AVERROR_INVALIDDATA;
2186
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
68 if ((err = av_reallocp(&par->extradata, size)) < 0) {
2187 par->extradata_size = 0;
2188 return err;
2189 }
2190 68 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
2191 68 return 0;
2192 }
2193
2194 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
2195 65 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2196 AVCodecParameters *par, uint8_t *buf)
2197 {
2198 65 int64_t result = atom.size;
2199 int err;
2200
2201 65 AV_WB32(buf , atom.size + 8);
2202 65 AV_WL32(buf + 4, atom.type);
2203 65 err = ffio_read_size(pb, buf + 8, atom.size);
2204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (err < 0) {
2205 par->extradata_size -= atom.size;
2206 return err;
2207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 } else if (err < atom.size) {
2208 av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
2209 par->extradata_size -= atom.size - err;
2210 result = err;
2211 }
2212 65 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2213 65 return result;
2214 }
2215
2216 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
2217 58 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2218 enum AVCodecID codec_id)
2219 {
2220 AVStream *st;
2221 uint64_t original_size;
2222 int err;
2223
2224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (c->fc->nb_streams < 1) // will happen with jp2 files
2225 return 0;
2226 58 st = c->fc->streams[c->fc->nb_streams-1];
2227
2228
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
58 if (st->codecpar->codec_id != codec_id)
2229 19 return 0; /* unexpected codec_id - don't mess with extradata */
2230
2231 39 original_size = st->codecpar->extradata_size;
2232 39 err = mov_realloc_extradata(st->codecpar, atom);
2233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err)
2234 return err;
2235
2236 39 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
2237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err < 0)
2238 return err;
2239 39 return 0; // Note: this is the original behavior to ignore truncation.
2240 }
2241
2242 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
2243 16 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2244 {
2245 16 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
2246 }
2247
2248 static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2249 {
2250 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS);
2251 }
2252
2253 static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2254 {
2255 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
2256 }
2257
2258 static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2259 {
2260 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
2261 }
2262
2263 19 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2264 {
2265 19 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
2266
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!ret)
2267 19 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
2268 19 return ret;
2269 }
2270
2271 static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2272 {
2273 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
2274
2275 if (!ret && c->fc->nb_streams >= 1) {
2276 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2277 if (par->extradata_size >= 40) {
2278 par->height = AV_RB16(&par->extradata[36]);
2279 par->width = AV_RB16(&par->extradata[38]);
2280 }
2281 }
2282 return ret;
2283 }
2284
2285 16 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2286 {
2287
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (c->fc->nb_streams >= 1) {
2288 16 AVStream *const st = c->fc->streams[c->fc->nb_streams - 1];
2289 16 FFStream *const sti = ffstream(st);
2290 16 AVCodecParameters *par = st->codecpar;
2291
2292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
2293 par->codec_id == AV_CODEC_ID_H264 &&
2294 atom.size > 11) {
2295 int cid;
2296 avio_skip(pb, 10);
2297 cid = avio_rb16(pb);
2298 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
2299 if (cid == 0xd4d || cid == 0xd4e)
2300 par->width = 1440;
2301 return 0;
2302
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
2303
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
2304
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
2305
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 atom.size >= 24) {
2306 int num, den;
2307 13 avio_skip(pb, 12);
2308 13 num = avio_rb32(pb);
2309 13 den = avio_rb32(pb);
2310
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)
2311 return 0;
2312
2/3
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
13 switch (avio_rb32(pb)) {
2313 12 case 2:
2314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (den >= INT_MAX / 2)
2315 return 0;
2316 12 den *= 2;
2317 13 case 1:
2318 13 sti->display_aspect_ratio = (AVRational){ num, den };
2319 13 default:
2320 13 return 0;
2321 }
2322 }
2323 }
2324
2325 3 return mov_read_avid(c, pb, atom);
2326 }
2327
2328 26 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2329 {
2330 26 int ret = 0;
2331 26 int length = 0;
2332 uint64_t original_size;
2333
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (c->fc->nb_streams >= 1) {
2334 26 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (par->codec_id == AV_CODEC_ID_H264)
2336 return 0;
2337
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (atom.size == 16) {
2338 26 original_size = par->extradata_size;
2339 26 ret = mov_realloc_extradata(par, atom);
2340
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!ret) {
2341 26 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
2342
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (length == atom.size) {
2343 26 const uint8_t range_value = par->extradata[original_size + 19];
2344
1/3
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
26 switch (range_value) {
2345 26 case 1:
2346 26 par->color_range = AVCOL_RANGE_MPEG;
2347 26 break;
2348 case 2:
2349 par->color_range = AVCOL_RANGE_JPEG;
2350 break;
2351 default:
2352 av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
2353 break;
2354 }
2355 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
2356 } else {
2357 /* For some reason the whole atom was not added to the extradata */
2358 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
2359 }
2360 } else {
2361 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
2362 }
2363 } else {
2364 av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
2365 }
2366 }
2367
2368 26 return ret;
2369 }
2370
2371 4 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2372 {
2373 4 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
2374 }
2375
2376 34 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2377 {
2378 AVStream *st;
2379 int ret;
2380
2381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (c->fc->nb_streams < 1)
2382 return 0;
2383 34 st = c->fc->streams[c->fc->nb_streams-1];
2384
2385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if ((uint64_t)atom.size > (1<<30))
2386 return AVERROR_INVALIDDATA;
2387
2388
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2 times.
34 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2389
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
2391 // pass all frma atom to codec, needed at least for QDMC and QDM2
2392 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2394 return ret;
2395
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 } else if (atom.size > 8) { /* to read frma, esds atoms */
2396
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
32 if (st->codecpar->codec_id == AV_CODEC_ID_ALAC && atom.size >= 24) {
2397 uint64_t buffer;
2398 10 ret = ffio_ensure_seekback(pb, 8);
2399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2400 return ret;
2401 10 buffer = avio_rb64(pb);
2402 10 atom.size -= 8;
2403
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
2404
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 <= atom.size
2405
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 >= 8) {
2406 10 avio_skip(pb, -8);
2407 10 atom.size += 8;
2408 } else if (!st->codecpar->extradata_size) {
2409 #define ALAC_EXTRADATA_SIZE 36
2410 st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
2411 if (!st->codecpar->extradata)
2412 return AVERROR(ENOMEM);
2413 st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
2414 AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
2415 AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
2416 AV_WB64(st->codecpar->extradata + 12, buffer);
2417 avio_read(pb, st->codecpar->extradata + 20, 16);
2418 avio_skip(pb, atom.size - 24);
2419 return 0;
2420 }
2421 }
2422
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if ((ret = mov_read_default(c, pb, atom)) < 0)
2423 return ret;
2424 } else
2425 avio_skip(pb, atom.size);
2426 34 return 0;
2427 }
2428
2429 /**
2430 * This function reads atom content and puts data in extradata without tag
2431 * nor size unlike mov_read_extradata.
2432 */
2433 141 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2434 {
2435 AVStream *st;
2436 int ret;
2437
2438 141 st = get_curr_st(c);
2439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
141 if (!st)
2440 return 0;
2441
2442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
141 if ((uint64_t)atom.size > (1<<30))
2443 return AVERROR_INVALIDDATA;
2444
2445
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 140 times.
141 if (atom.type == MKTAG('v','v','c','C')) {
2446 1 avio_skip(pb, 4);
2447 1 atom.size -= 4;
2448 }
2449
2450
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 4 times.
141 if (atom.size >= 10) {
2451 // Broken files created by legacy versions of libavformat will
2452 // wrap a whole fiel atom inside of a glbl atom.
2453 137 unsigned size = avio_rb32(pb);
2454 137 unsigned type = avio_rl32(pb);
2455
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 137 times.
137 if (avio_feof(pb))
2456 return AVERROR_INVALIDDATA;
2457 137 avio_seek(pb, -8, SEEK_CUR);
2458
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 129 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
137 if (type == MKTAG('f','i','e','l') && size == atom.size)
2459 8 return mov_read_default(c, pb, atom);
2460 }
2461
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
133 if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
2462 av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
2463 return 0;
2464 }
2465 133 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2466
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
133 if (ret < 0)
2467 return ret;
2468
3/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 41 times.
133 if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
2469 /* HEVC-based Dolby Vision derived from hvc1.
2470 Happens to match with an identifier
2471 previously utilized for DV. Thus, if we have
2472 the hvcC extradata box available as specified,
2473 set codec to HEVC */
2474 st->codecpar->codec_id = AV_CODEC_ID_HEVC;
2475
2476 133 return 0;
2477 }
2478
2479 2 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2480 {
2481 AVStream *st;
2482 uint8_t profile_level;
2483 int ret;
2484
2485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
2486 return 0;
2487 2 st = c->fc->streams[c->fc->nb_streams-1];
2488
2489
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)
2490 return AVERROR_INVALIDDATA;
2491
2492 2 profile_level = avio_r8(pb);
2493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((profile_level & 0xf0) != 0xc0)
2494 return 0;
2495
2496 2 avio_seek(pb, 6, SEEK_CUR);
2497 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
2498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2499 return ret;
2500
2501 2 return 0;
2502 }
2503
2504 static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2505 {
2506 AVStream* st;
2507 MOVStreamContext* sc;
2508
2509 if (c->fc->nb_streams < 1)
2510 return 0;
2511
2512 /* For SBAS this should be fine - though beware if someone implements a
2513 * tref atom processor that doesn't drop down to default then this may
2514 * be lost. */
2515 if (atom.size > 4) {
2516 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2517 return AVERROR_PATCHWELCOME;
2518 }
2519
2520 st = c->fc->streams[c->fc->nb_streams - 1];
2521 sc = st->priv_data;
2522 sc->tref_id = avio_rb32(pb);
2523 sc->tref_flags |= MOV_TREF_FLAG_ENHANCEMENT;
2524
2525 return 0;
2526 }
2527
2528 /**
2529 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2530 * but can have extradata appended at the end after the 40 bytes belonging
2531 * to the struct.
2532 */
2533 static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2534 {
2535 AVStream *st;
2536 int ret;
2537
2538 if (c->fc->nb_streams < 1)
2539 return 0;
2540 if (atom.size <= 40)
2541 return 0;
2542 st = c->fc->streams[c->fc->nb_streams-1];
2543
2544 if ((uint64_t)atom.size > (1<<30))
2545 return AVERROR_INVALIDDATA;
2546
2547 avio_skip(pb, 40);
2548 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
2549 if (ret < 0)
2550 return ret;
2551
2552 return 0;
2553 }
2554
2555 594 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2556 {
2557 AVStream *st;
2558 MOVStreamContext *sc;
2559 unsigned int i, entries;
2560
2561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->trak_index < 0) {
2562 av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
2563 return 0;
2564 }
2565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
2566 return 0;
2567 594 st = c->fc->streams[c->fc->nb_streams-1];
2568 594 sc = st->priv_data;
2569
2570 594 avio_r8(pb); /* version */
2571 594 avio_rb24(pb); /* flags */
2572
2573 // Clamp allocation size for `chunk_offsets` -- don't throw an error for an
2574 // invalid count since the EOF path doesn't throw either.
2575 594 entries = avio_rb32(pb);
2576 594 entries =
2577
2/2
✓ Branch 0 taken 589 times.
✓ Branch 1 taken 5 times.
594 FFMIN(entries,
2578 FFMAX(0, (atom.size - 8) /
2579 (atom.type == MKTAG('s', 't', 'c', 'o') ? 4 : 8)));
2580
2581
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 578 times.
594 if (!entries)
2582 16 return 0;
2583
2584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (sc->chunk_offsets) {
2585 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2586 return 0;
2587 }
2588
2589 578 av_free(sc->chunk_offsets);
2590 578 sc->chunk_count = 0;
2591 578 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (!sc->chunk_offsets)
2593 return AVERROR(ENOMEM);
2594 578 sc->chunk_count = entries;
2595
2596
2/2
✓ Branch 0 taken 574 times.
✓ Branch 1 taken 4 times.
578 if (atom.type == MKTAG('s','t','c','o'))
2597
3/4
✓ Branch 0 taken 42907 times.
✓ Branch 1 taken 574 times.
✓ Branch 2 taken 42907 times.
✗ Branch 3 not taken.
43481 for (i = 0; i < entries && !pb->eof_reached; i++)
2598 42907 sc->chunk_offsets[i] = avio_rb32(pb);
2599
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (atom.type == MKTAG('c','o','6','4'))
2600
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++) {
2601 136336 sc->chunk_offsets[i] = avio_rb64(pb);
2602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136336 times.
136336 if (sc->chunk_offsets[i] < 0) {
2603 av_log(c->fc, AV_LOG_WARNING, "Impossible chunk_offset\n");
2604 sc->chunk_offsets[i] = 0;
2605 }
2606 }
2607 else
2608 return AVERROR_INVALIDDATA;
2609
2610 578 sc->chunk_count = i;
2611
2612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (pb->eof_reached) {
2613 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2614 return AVERROR_EOF;
2615 }
2616
2617 578 return 0;
2618 }
2619
2620 633 static int mov_codec_id(AVStream *st, uint32_t format)
2621 {
2622 633 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2623
2624
2/2
✓ Branch 0 taken 413 times.
✓ Branch 1 taken 220 times.
633 if (id <= 0 &&
2625
2/2
✓ Branch 0 taken 410 times.
✓ Branch 1 taken 3 times.
413 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 410 times.
410 (format & 0xFFFF) == 'T' + ('S' << 8)))
2627 3 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2628
2629
4/4
✓ Branch 0 taken 293 times.
✓ Branch 1 taken 340 times.
✓ Branch 2 taken 223 times.
✓ Branch 3 taken 70 times.
633 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2630 223 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2631
3/4
✓ Branch 0 taken 392 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 392 times.
✗ Branch 3 not taken.
410 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2632 /* skip old ASF MPEG-4 tag */
2633
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 4 times.
392 format && format != MKTAG('m','p','4','s')) {
2634 388 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2635
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 333 times.
388 if (id <= 0)
2636 55 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2637
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 51 times.
388 if (id > 0)
2638 337 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2639
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 47 times.
51 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2640
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2642 47 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2643
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6 times.
47 if (id <= 0) {
2644
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 2 times.
80 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2645
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 2 times.
80 AV_CODEC_ID_TTML : id;
2646 }
2647
2648
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 37 times.
47 if (id > 0)
2649 10 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2650 else
2651 37 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2652 }
2653 }
2654
2655 633 st->codecpar->codec_tag = format;
2656
2657 633 return id;
2658 }
2659
2660 312 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2661 AVStream *st, MOVStreamContext *sc)
2662 {
2663 312 uint8_t codec_name[32] = { 0 };
2664 int64_t stsd_start;
2665 unsigned int len;
2666 312 uint32_t id = 0;
2667
2668 /* The first 16 bytes of the video sample description are already
2669 * read in ff_mov_read_stsd_entries() */
2670 312 stsd_start = avio_tell(pb) - 16;
2671
2672 312 avio_rb16(pb); /* version */
2673 312 avio_rb16(pb); /* revision level */
2674 312 id = avio_rl32(pb); /* vendor */
2675 312 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2676 312 avio_rb32(pb); /* temporal quality */
2677 312 avio_rb32(pb); /* spatial quality */
2678
2679 312 st->codecpar->width = avio_rb16(pb); /* width */
2680 312 st->codecpar->height = avio_rb16(pb); /* height */
2681
2682 312 avio_rb32(pb); /* horiz resolution */
2683 312 avio_rb32(pb); /* vert resolution */
2684 312 avio_rb32(pb); /* data size, always 0 */
2685 312 avio_rb16(pb); /* frames per samples */
2686
2687 312 len = avio_r8(pb); /* codec name, pascal string */
2688
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 311 times.
312 if (len > 31)
2689 1 len = 31;
2690 312 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2691
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 3 times.
312 if (len < 31)
2692 309 avio_skip(pb, 31 - len);
2693
2694
2/2
✓ Branch 0 taken 250 times.
✓ Branch 1 taken 62 times.
312 if (codec_name[0])
2695 250 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2696
2697 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 312 times.
312 if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2699 st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2700 st->codecpar->width &= ~1;
2701 st->codecpar->height &= ~1;
2702 }
2703 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 312 times.
312 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2705 !strncmp(codec_name, "Sorenson H263", 13))
2706 st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2707
2708 312 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2709
2710 312 avio_seek(pb, stsd_start, SEEK_SET);
2711
2712
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 294 times.
312 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2713 18 st->codecpar->bits_per_coded_sample &= 0x1F;
2714 18 sc->has_palette = 1;
2715 }
2716 312 }
2717
2718 241 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2719 AVStream *st, MOVStreamContext *sc)
2720 {
2721 int bits_per_sample, flags;
2722 241 uint16_t version = avio_rb16(pb);
2723 241 uint32_t id = 0;
2724 241 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2725 int channel_count;
2726
2727 241 avio_rb16(pb); /* revision level */
2728 241 id = avio_rl32(pb); /* vendor */
2729 241 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2730
2731 241 channel_count = avio_rb16(pb);
2732
2733 241 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2734 241 st->codecpar->ch_layout.nb_channels = channel_count;
2735 241 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
2736 241 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
2737
2738 241 sc->audio_cid = avio_rb16(pb);
2739 241 avio_rb16(pb); /* packet size = 0 */
2740
2741 241 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
2742
2743 // Read QT version 1 fields. In version 0 these do not exist.
2744 241 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
2745
3/4
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 86 times.
✓ Branch 2 taken 155 times.
✗ Branch 3 not taken.
241 if (!c->isom ||
2746
1/2
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
155 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
2747
3/4
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 151 times.
155 (sc->stsd_version == 0 && version > 0)) {
2748
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 40 times.
90 if (version == 1) {
2749 50 sc->samples_per_frame = avio_rb32(pb);
2750 50 avio_rb32(pb); /* bytes per packet */
2751 50 sc->bytes_per_frame = avio_rb32(pb);
2752 50 avio_rb32(pb); /* bytes per sample */
2753
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
40 } else if (version == 2) {
2754 4 avio_rb32(pb); /* sizeof struct only */
2755 4 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
2756 4 channel_count = avio_rb32(pb);
2757 4 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2758 4 st->codecpar->ch_layout.nb_channels = channel_count;
2759 4 avio_rb32(pb); /* always 0x7F000000 */
2760 4 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
2761
2762 4 flags = avio_rb32(pb); /* lpcm format specific flag */
2763 4 sc->bytes_per_frame = avio_rb32(pb);
2764 4 sc->samples_per_frame = avio_rb32(pb);
2765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
2766 st->codecpar->codec_id =
2767 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
2768 flags);
2769 }
2770
6/6
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 26 times.
90 if (version == 0 || (version == 1 && sc->audio_cid != -2)) {
2771 /* can't correctly handle variable sized packet as audio unit */
2772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 switch (st->codecpar->codec_id) {
2773 case AV_CODEC_ID_MP2:
2774 case AV_CODEC_ID_MP3:
2775 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
2776 break;
2777 }
2778 }
2779 }
2780
2781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (sc->format == 0) {
2782 if (st->codecpar->bits_per_coded_sample == 8)
2783 st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
2784 else if (st->codecpar->bits_per_coded_sample == 16)
2785 st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
2786 }
2787
2788
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 199 times.
241 switch (st->codecpar->codec_id) {
2789 7 case AV_CODEC_ID_PCM_S8:
2790 case AV_CODEC_ID_PCM_U8:
2791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
2792 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2793 7 break;
2794 19 case AV_CODEC_ID_PCM_S16LE:
2795 case AV_CODEC_ID_PCM_S16BE:
2796
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
19 if (st->codecpar->bits_per_coded_sample == 8)
2797 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
2798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 24)
2799 st->codecpar->codec_id =
2800 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2801 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
2802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 else if (st->codecpar->bits_per_coded_sample == 32)
2803 st->codecpar->codec_id =
2804 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2805 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
2806 19 break;
2807 /* set values for old format before stsd version 1 appeared */
2808 2 case AV_CODEC_ID_MACE3:
2809 2 sc->samples_per_frame = 6;
2810 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
2811 2 break;
2812 8 case AV_CODEC_ID_MACE6:
2813 8 sc->samples_per_frame = 6;
2814 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
2815 8 break;
2816 5 case AV_CODEC_ID_ADPCM_IMA_QT:
2817 5 sc->samples_per_frame = 64;
2818 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
2819 5 break;
2820 1 case AV_CODEC_ID_GSM:
2821 1 sc->samples_per_frame = 160;
2822 1 sc->bytes_per_frame = 33;
2823 1 break;
2824 199 default:
2825 199 break;
2826 }
2827
2828 241 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2829
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 193 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
241 if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->ch_layout.nb_channels <= INT_MAX) {
2830 48 st->codecpar->bits_per_coded_sample = bits_per_sample;
2831 48 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
2832 }
2833 241 }
2834
2835 11 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
2836 AVStream *st, MOVStreamContext *sc,
2837 int64_t size)
2838 {
2839 // ttxt stsd contains display flags, justification, background
2840 // color, fonts, and default styles, so fake an atom to read it
2841 11 MOVAtom fake_atom = { .size = size };
2842 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
2843 // in extradata unlike stpp MP4 TTML.
2844
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
2845
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
2846 9 mov_read_glbl(c, pb, fake_atom);
2847 11 st->codecpar->width = sc->width;
2848 11 st->codecpar->height = sc->height;
2849 11 }
2850
2851 41 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
2852 AVStream *st, MOVStreamContext *sc,
2853 int64_t size)
2854 {
2855 int ret;
2856
2857
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 22 times.
41 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
2858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if ((int)size != size)
2859 return AVERROR(ENOMEM);
2860
2861 19 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
2862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
2863 return ret;
2864
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (size > 16) {
2865 19 MOVStreamContext *tmcd_ctx = st->priv_data;
2866 int val;
2867 19 val = AV_RB32(st->codecpar->extradata + 4);
2868 19 tmcd_ctx->tmcd_flags = val;
2869 19 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
2870 19 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
2871 19 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
2872
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (size > 30) {
2873 4 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
2874 4 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
2875
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) {
2876 4 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
2877
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 &&
2878
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 st->codecpar->extradata[30] /* Don't add empty string */) {
2879 4 char *reel_name = av_malloc(str_size + 1);
2880
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!reel_name)
2881 return AVERROR(ENOMEM);
2882 4 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
2883 4 reel_name[str_size] = 0; /* Add null terminator */
2884 4 av_dict_set(&st->metadata, "reel_name", reel_name,
2885 AV_DICT_DONT_STRDUP_VAL);
2886 }
2887 }
2888 }
2889 }
2890 } else {
2891 /* other codec type, just skip (rtp, mp4s ...) */
2892 22 avio_skip(pb, size);
2893 }
2894 41 return 0;
2895 }
2896
2897 594 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
2898 AVStream *st, MOVStreamContext *sc)
2899 {
2900 594 FFStream *const sti = ffstream(st);
2901
2902
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 353 times.
594 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
2903
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
241 !st->codecpar->sample_rate && sc->time_scale > 1)
2904 st->codecpar->sample_rate = sc->time_scale;
2905
2906 /* special codec parameters handling */
2907
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 66 times.
✓ Branch 9 taken 475 times.
594 switch (st->codecpar->codec_id) {
2908 #if CONFIG_DV_DEMUXER
2909 case AV_CODEC_ID_DVAUDIO:
2910 if (c->dv_fctx) {
2911 avpriv_request_sample(c->fc, "multiple DV audio streams");
2912 return AVERROR(ENOSYS);
2913 }
2914
2915 c->dv_fctx = avformat_alloc_context();
2916 if (!c->dv_fctx) {
2917 av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
2918 return AVERROR(ENOMEM);
2919 }
2920 c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
2921 if (!c->dv_demux) {
2922 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
2923 return AVERROR(ENOMEM);
2924 }
2925 sc->dv_audio_container = 1;
2926 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2927 break;
2928 #endif
2929 /* no ifdef since parameters are always those */
2930 case AV_CODEC_ID_QCELP:
2931 av_channel_layout_uninit(&st->codecpar->ch_layout);
2932 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2933 // force sample rate for qcelp when not stored in mov
2934 if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
2935 st->codecpar->sample_rate = 8000;
2936 // FIXME: Why is the following needed for some files?
2937 sc->samples_per_frame = 160;
2938 if (!sc->bytes_per_frame)
2939 sc->bytes_per_frame = 35;
2940 break;
2941 case AV_CODEC_ID_AMR_NB:
2942 av_channel_layout_uninit(&st->codecpar->ch_layout);
2943 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2944 /* force sample rate for amr, stsd in 3gp does not store sample rate */
2945 st->codecpar->sample_rate = 8000;
2946 break;
2947 11 case AV_CODEC_ID_AMR_WB:
2948 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
2949 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
2950 11 st->codecpar->sample_rate = 16000;
2951 11 break;
2952 1 case AV_CODEC_ID_MP2:
2953 case AV_CODEC_ID_MP3:
2954 /* force type after stsd for m1a hdlr */
2955 1 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2956 1 break;
2957 15 case AV_CODEC_ID_GSM:
2958 case AV_CODEC_ID_ADPCM_MS:
2959 case AV_CODEC_ID_ADPCM_IMA_WAV:
2960 case AV_CODEC_ID_ILBC:
2961 case AV_CODEC_ID_MACE3:
2962 case AV_CODEC_ID_MACE6:
2963 case AV_CODEC_ID_QDM2:
2964 15 st->codecpar->block_align = sc->bytes_per_frame;
2965 15 break;
2966 16 case AV_CODEC_ID_ALAC:
2967
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
2968 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
2969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
2970 av_channel_layout_uninit(&st->codecpar->ch_layout);
2971 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2972 st->codecpar->ch_layout.nb_channels = channel_count;
2973 }
2974 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
2975 }
2976 16 break;
2977 10 case AV_CODEC_ID_AC3:
2978 case AV_CODEC_ID_EAC3:
2979 case AV_CODEC_ID_MPEG1VIDEO:
2980 case AV_CODEC_ID_VC1:
2981 case AV_CODEC_ID_VP8:
2982 case AV_CODEC_ID_VP9:
2983 10 sti->need_parsing = AVSTREAM_PARSE_FULL;
2984 10 break;
2985 66 case AV_CODEC_ID_EVC:
2986 case AV_CODEC_ID_AV1:
2987 /* field_order detection of H264 requires parsing */
2988 case AV_CODEC_ID_H264:
2989 66 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
2990 66 break;
2991 475 default:
2992 475 break;
2993 }
2994 594 return 0;
2995 }
2996
2997 605 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
2998 int codec_tag, int format,
2999 int64_t size)
3000 {
3001
3/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 594 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
605 if (codec_tag &&
3002 (codec_tag != format &&
3003 // AVID 1:1 samples with differing data format and codec tag exist
3004 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
3005 // prores is allowed to have differing data format and codec tag
3006 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
3007 // so is dv (sigh)
3008 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
3009 (c->fc->video_codec_id ? ff_codec_get_id(ff_codec_movvideo_tags, format) != c->fc->video_codec_id
3010 : codec_tag != MKTAG('j','p','e','g')))) {
3011 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3012 * export it as a separate AVStream but this needs a few changes
3013 * in the MOV demuxer, patch welcome. */
3014
3015 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3016 avio_skip(pb, size);
3017 return 1;
3018 }
3019
3020 605 return 0;
3021 }
3022
3023 594 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3024 {
3025 AVStream *st;
3026 MOVStreamContext *sc;
3027 int pseudo_stream_id;
3028
3029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 av_assert0 (c->fc->nb_streams >= 1);
3030 594 st = c->fc->streams[c->fc->nb_streams-1];
3031 594 sc = st->priv_data;
3032
3033 594 for (pseudo_stream_id = 0;
3034
3/4
✓ Branch 0 taken 605 times.
✓ Branch 1 taken 594 times.
✓ Branch 2 taken 605 times.
✗ Branch 3 not taken.
1199 pseudo_stream_id < entries && !pb->eof_reached;
3035 605 pseudo_stream_id++) {
3036 //Parsing Sample description table
3037 enum AVCodecID id;
3038 605 int ret, dref_id = 1;
3039 605 MOVAtom a = { AV_RL32("stsd") };
3040 605 int64_t start_pos = avio_tell(pb);
3041 605 int64_t size = avio_rb32(pb); /* size */
3042 605 uint32_t format = avio_rl32(pb); /* data format */
3043
3044
1/2
✓ Branch 0 taken 605 times.
✗ Branch 1 not taken.
605 if (size >= 16) {
3045 605 avio_rb32(pb); /* reserved */
3046 605 avio_rb16(pb); /* reserved */
3047 605 dref_id = avio_rb16(pb);
3048 } else if (size <= 7) {
3049 av_log(c->fc, AV_LOG_ERROR,
3050 "invalid size %"PRId64" in stsd\n", size);
3051 return AVERROR_INVALIDDATA;
3052 }
3053
3054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 605 times.
605 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3055 605 size - (avio_tell(pb) - start_pos))) {
3056 sc->stsd_count++;
3057 continue;
3058 }
3059
3060
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 11 times.
605 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
3061 605 sc->dref_id= dref_id;
3062 605 sc->format = format;
3063
3064 605 id = mov_codec_id(st, format);
3065
3066 605 av_log(c->fc, AV_LOG_TRACE,
3067 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3068 605 av_fourcc2str(format), st->codecpar->codec_type);
3069
3070 605 st->codecpar->codec_id = id;
3071
2/2
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 293 times.
605 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3072 312 mov_parse_stsd_video(c, pb, st, sc);
3073
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 52 times.
293 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3074 241 mov_parse_stsd_audio(c, pb, st, sc);
3075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (st->codecpar->sample_rate < 0) {
3076 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3077 return AVERROR_INVALIDDATA;
3078 }
3079
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (st->codecpar->ch_layout.nb_channels < 0) {
3080 av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3081 return AVERROR_INVALIDDATA;
3082 }
3083
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 41 times.
52 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3084 11 mov_parse_stsd_subtitle(c, pb, st, sc,
3085 11 size - (avio_tell(pb) - start_pos));
3086 } else {
3087 41 ret = mov_parse_stsd_data(c, pb, st, sc,
3088 41 size - (avio_tell(pb) - start_pos));
3089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ret < 0)
3090 return ret;
3091 }
3092 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3093 605 a.size = size - (avio_tell(pb) - start_pos);
3094
2/2
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 128 times.
605 if (a.size > 8) {
3095
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 477 times.
477 if ((ret = mov_read_default(c, pb, a)) < 0)
3096 return ret;
3097
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 127 times.
128 } else if (a.size > 0)
3098 1 avio_skip(pb, a.size);
3099
3100
3/4
✓ Branch 0 taken 605 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 341 times.
✓ Branch 3 taken 264 times.
605 if (sc->extradata && st->codecpar->extradata) {
3101 341 int extra_size = st->codecpar->extradata_size;
3102
3103 /* Move the current stream extradata to the stream context one. */
3104 341 sc->extradata_size[pseudo_stream_id] = extra_size;
3105 341 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3106 341 st->codecpar->extradata = NULL;
3107 341 st->codecpar->extradata_size = 0;
3108 }
3109 605 sc->stsd_count++;
3110 }
3111
3112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (pb->eof_reached) {
3113 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3114 return AVERROR_EOF;
3115 }
3116
3117 594 return 0;
3118 }
3119
3120 594 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3121 {
3122 AVStream *st;
3123 MOVStreamContext *sc;
3124 int ret, entries;
3125
3126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
3127 return 0;
3128 594 st = c->fc->streams[c->fc->nb_streams - 1];
3129 594 sc = st->priv_data;
3130
3131 594 sc->stsd_version = avio_r8(pb);
3132 594 avio_rb24(pb); /* flags */
3133 594 entries = avio_rb32(pb);
3134
3135 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3136
3/6
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 594 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 594 times.
594 if (entries <= 0 || entries > atom.size / 8 || entries > 1024) {
3137 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3138 return AVERROR_INVALIDDATA;
3139 }
3140
3141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (sc->extradata) {
3142 av_log(c->fc, AV_LOG_ERROR,
3143 "Duplicate stsd found in this track.\n");
3144 return AVERROR_INVALIDDATA;
3145 }
3146
3147 /* Prepare space for hosting multiple extradata. */
3148 594 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (!sc->extradata)
3150 return AVERROR(ENOMEM);
3151
3152 594 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (!sc->extradata_size) {
3154 ret = AVERROR(ENOMEM);
3155 goto fail;
3156 }
3157
3158 594 ret = ff_mov_read_stsd_entries(c, pb, entries);
3159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (ret < 0)
3160 goto fail;
3161
3162 /* Restore back the primary extradata. */
3163 594 av_freep(&st->codecpar->extradata);
3164 594 st->codecpar->extradata_size = sc->extradata_size[0];
3165
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 263 times.
594 if (sc->extradata_size[0]) {
3166 331 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 331 times.
331 if (!st->codecpar->extradata)
3168 return AVERROR(ENOMEM);
3169 331 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3170 }
3171
3172 594 return mov_finalize_stsd_codec(c, pb, st, sc);
3173 fail:
3174 if (sc->extradata) {
3175 int j;
3176 for (j = 0; j < sc->stsd_count; j++)
3177 av_freep(&sc->extradata[j]);
3178 }
3179
3180 av_freep(&sc->extradata);
3181 av_freep(&sc->extradata_size);
3182 return ret;
3183 }
3184
3185 594 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3186 {
3187 AVStream *st;
3188 MOVStreamContext *sc;
3189 unsigned int i, entries;
3190
3191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->trak_index < 0) {
3192 av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3193 return 0;
3194 }
3195
3196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
3197 return 0;
3198 594 st = c->fc->streams[c->fc->nb_streams-1];
3199 594 sc = st->priv_data;
3200
3201 594 avio_r8(pb); /* version */
3202 594 avio_rb24(pb); /* flags */
3203
3204 594 entries = avio_rb32(pb);
3205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if ((uint64_t)entries * 12 + 4 > atom.size)
3206 return AVERROR_INVALIDDATA;
3207
3208 594 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3209
3210
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 579 times.
594 if (!entries)
3211 15 return 0;
3212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 579 times.
579 if (sc->stsc_data) {
3213 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3214 return 0;
3215 }
3216 579 av_free(sc->stsc_data);
3217 579 sc->stsc_count = 0;
3218 579 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 579 times.
579 if (!sc->stsc_data)
3220 return AVERROR(ENOMEM);
3221
3222
3/4
✓ Branch 0 taken 3779 times.
✓ Branch 1 taken 579 times.
✓ Branch 2 taken 3779 times.
✗ Branch 3 not taken.
4358 for (i = 0; i < entries && !pb->eof_reached; i++) {
3223 3779 sc->stsc_data[i].first = avio_rb32(pb);
3224 3779 sc->stsc_data[i].count = avio_rb32(pb);
3225 3779 sc->stsc_data[i].id = avio_rb32(pb);
3226 }
3227
3228 579 sc->stsc_count = i;
3229
2/2
✓ Branch 0 taken 3779 times.
✓ Branch 1 taken 579 times.
4358 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3230 3779 int64_t first_min = i + 1;
3231
5/6
✓ Branch 0 taken 3200 times.
✓ Branch 1 taken 579 times.
✓ Branch 2 taken 3200 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3200 times.
✓ Branch 5 taken 579 times.
3779 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
3232
1/2
✓ Branch 0 taken 3200 times.
✗ Branch 1 not taken.
3200 (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) ||
3233
1/2
✓ Branch 0 taken 3779 times.
✗ Branch 1 not taken.
3779 sc->stsc_data[i].first < first_min ||
3234
1/2
✓ Branch 0 taken 3779 times.
✗ Branch 1 not taken.
3779 sc->stsc_data[i].count < 1 ||
3235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3779 times.
3779 sc->stsc_data[i].id < 1) {
3236 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);
3237 if (i+1 >= sc->stsc_count) {
3238 if (sc->stsc_data[i].count == 0 && i > 0) {
3239 sc->stsc_count --;
3240 continue;
3241 }
3242 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3243 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3244 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3245 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3246 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3247 continue;
3248 }
3249 av_assert0(sc->stsc_data[i+1].first >= 2);
3250 // We replace this entry by the next valid
3251 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3252 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3253 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3254 }
3255 }
3256
3257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 579 times.
579 if (pb->eof_reached) {
3258 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3259 return AVERROR_EOF;
3260 }
3261
3262 579 return 0;
3263 }
3264
3265 340657 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3266 {
3267 340657 return index < count - 1;
3268 }
3269
3270 /* Compute the samples value for the stsc entry at the given index. */
3271 55524 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3272 {
3273 int chunk_count;
3274
3275
2/2
✓ Branch 1 taken 55328 times.
✓ Branch 2 taken 196 times.
55524 if (mov_stsc_index_valid(index, sc->stsc_count))
3276 55328 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3277 else {
3278 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3280 196 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3281 }
3282
3283 55524 return sc->stsc_data[index].count * (int64_t)chunk_count;
3284 }
3285
3286 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3287 {
3288 AVStream *st;
3289 MOVStreamContext *sc;
3290 unsigned i, entries;
3291
3292 if (c->trak_index < 0) {
3293 av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3294 return 0;
3295 }
3296
3297 if (c->fc->nb_streams < 1)
3298 return 0;
3299 st = c->fc->streams[c->fc->nb_streams-1];
3300 sc = st->priv_data;
3301
3302 avio_rb32(pb); // version + flags
3303
3304 entries = avio_rb32(pb);
3305 if (sc->stps_data)
3306 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3307 av_free(sc->stps_data);
3308 sc->stps_count = 0;
3309 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3310 if (!sc->stps_data)
3311 return AVERROR(ENOMEM);
3312
3313 for (i = 0; i < entries && !pb->eof_reached; i++) {
3314 sc->stps_data[i] = avio_rb32(pb);
3315 }
3316
3317 sc->stps_count = i;
3318
3319 if (pb->eof_reached) {
3320 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3321 return AVERROR_EOF;
3322 }
3323
3324 return 0;
3325 }
3326
3327 144 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3328 {
3329 AVStream *st;
3330 FFStream *sti;
3331 MOVStreamContext *sc;
3332 unsigned int i, entries;
3333
3334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (c->trak_index < 0) {
3335 av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3336 return 0;
3337 }
3338
3339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (c->fc->nb_streams < 1)
3340 return 0;
3341 144 st = c->fc->streams[c->fc->nb_streams-1];
3342 144 sti = ffstream(st);
3343 144 sc = st->priv_data;
3344
3345 144 avio_r8(pb); /* version */
3346 144 avio_rb24(pb); /* flags */
3347
3348 144 entries = avio_rb32(pb);
3349
3350 144 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3351
3352
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 138 times.
144 if (!entries) {
3353 6 sc->keyframe_absent = 1;
3354
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)
3355 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3356 6 return 0;
3357 }
3358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (sc->keyframes)
3359 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (entries >= UINT_MAX / sizeof(int))
3361 return AVERROR_INVALIDDATA;
3362 138 av_freep(&sc->keyframes);
3363 138 sc->keyframe_count = 0;
3364 138 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (!sc->keyframes)
3366 return AVERROR(ENOMEM);
3367
3368
3/4
✓ Branch 0 taken 5706 times.
✓ Branch 1 taken 138 times.
✓ Branch 2 taken 5706 times.
✗ Branch 3 not taken.
5844 for (i = 0; i < entries && !pb->eof_reached; i++) {
3369 5706 sc->keyframes[i] = avio_rb32(pb);
3370 }
3371
3372 138 sc->keyframe_count = i;
3373
3374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if (pb->eof_reached) {
3375 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3376 return AVERROR_EOF;
3377 }
3378
3379 138 return 0;
3380 }
3381
3382 594 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3383 {
3384 AVStream *st;
3385 MOVStreamContext *sc;
3386 unsigned int i, entries, sample_size, field_size, num_bytes;
3387 GetBitContext gb;
3388 unsigned char* buf;
3389 int ret;
3390
3391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->trak_index < 0) {
3392 av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3393 return 0;
3394 }
3395
3396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
3397 return 0;
3398 594 st = c->fc->streams[c->fc->nb_streams-1];
3399 594 sc = st->priv_data;
3400
3401 594 avio_r8(pb); /* version */
3402 594 avio_rb24(pb); /* flags */
3403
3404
1/2
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
594 if (atom.type == MKTAG('s','t','s','z')) {
3405 594 sample_size = avio_rb32(pb);
3406
2/2
✓ Branch 0 taken 553 times.
✓ Branch 1 taken 41 times.
594 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3407 553 sc->sample_size = sample_size;
3408 594 sc->stsz_sample_size = sample_size;
3409 594 field_size = 32;
3410 } else {
3411 sample_size = 0;
3412 avio_rb24(pb); /* reserved */
3413 field_size = avio_r8(pb);
3414 }
3415 594 entries = avio_rb32(pb);
3416
3417 594 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3418
3419 594 sc->sample_count = entries;
3420
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 396 times.
594 if (sample_size)
3421 198 return 0;
3422
3423
4/8
✓ Branch 0 taken 396 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 396 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 396 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 396 times.
396 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
3424 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3425 return AVERROR_INVALIDDATA;
3426 }
3427
3428
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 380 times.
396 if (!entries)
3429 16 return 0;
3430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (entries >= (INT_MAX - 4 - 8 * AV_INPUT_BUFFER_PADDING_SIZE) / field_size)
3431 return AVERROR_INVALIDDATA;
3432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (sc->sample_sizes)
3433 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3434 380 av_free(sc->sample_sizes);
3435 380 sc->sample_count = 0;
3436 380 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (!sc->sample_sizes)
3438 return AVERROR(ENOMEM);
3439
3440 380 num_bytes = (entries*field_size+4)>>3;
3441
3442 380 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (!buf) {
3444 av_freep(&sc->sample_sizes);
3445 return AVERROR(ENOMEM);
3446 }
3447
3448 380 ret = ffio_read_size(pb, buf, num_bytes);
3449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (ret < 0) {
3450 av_freep(&sc->sample_sizes);
3451 av_free(buf);
3452 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3453 return 0;
3454 }
3455
3456 380 init_get_bits(&gb, buf, 8*num_bytes);
3457
3458
2/2
✓ Branch 0 taken 226883 times.
✓ Branch 1 taken 380 times.
227263 for (i = 0; i < entries; i++) {
3459 226883 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 226883 times.
226883 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3461 av_free(buf);
3462 av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3463 return AVERROR_INVALIDDATA;
3464 }
3465 226883 sc->data_size += sc->sample_sizes[i];
3466 }
3467
3468 380 sc->sample_count = i;
3469
3470 380 av_free(buf);
3471
3472 380 return 0;
3473 }
3474
3475 594 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3476 {
3477 AVStream *st;
3478 MOVStreamContext *sc;
3479 unsigned int i, entries;
3480 594 int64_t duration = 0;
3481 594 int64_t total_sample_count = 0;
3482 594 int64_t current_dts = 0;
3483 594 int64_t corrected_dts = 0;
3484
3485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->trak_index < 0) {
3486 av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3487 return 0;
3488 }
3489
3490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
3491 return 0;
3492 594 st = c->fc->streams[c->fc->nb_streams-1];
3493 594 sc = st->priv_data;
3494
3495 594 avio_r8(pb); /* version */
3496 594 avio_rb24(pb); /* flags */
3497 594 entries = avio_rb32(pb);
3498
3499 594 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3500 594 c->fc->nb_streams-1, entries);
3501
3502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (sc->stts_data)
3503 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3504 594 av_freep(&sc->stts_data);
3505 594 sc->stts_count = 0;
3506
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3507 return AVERROR(ENOMEM);
3508
3509
3/4
✓ Branch 0 taken 2941 times.
✓ Branch 1 taken 594 times.
✓ Branch 2 taken 2941 times.
✗ Branch 3 not taken.
3535 for (i = 0; i < entries && !pb->eof_reached; i++) {
3510 unsigned int sample_duration;
3511 unsigned int sample_count;
3512 2941 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3513 2941 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3514 min_entries * sizeof(*sc->stts_data));
3515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2941 times.
2941 if (!stts_data) {
3516 av_freep(&sc->stts_data);
3517 sc->stts_count = 0;
3518 return AVERROR(ENOMEM);
3519 }
3520 2941 sc->stts_count = min_entries;
3521 2941 sc->stts_data = stts_data;
3522
3523 2941 sample_count = avio_rb32(pb);
3524 2941 sample_duration = avio_rb32(pb);
3525
3526 2941 sc->stts_data[i].count= sample_count;
3527 2941 sc->stts_data[i].duration= sample_duration;
3528
3529 2941 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3530 sample_count, sample_duration);
3531
3532 /* STTS sample offsets are uint32 but some files store it as int32
3533 * with negative values used to correct DTS delays.
3534 There may be abnormally large values as well. */
3535
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2940 times.
2941 if (sample_duration > c->max_stts_delta) {
3536 // assume high delta is a correction if negative when cast as int32
3537 1 int32_t delta_magnitude = (int32_t)sample_duration;
3538 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",
3539 sample_duration, i, sample_count, st->index);
3540 1 sc->stts_data[i].duration = 1;
3541
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);
3542 } else {
3543 2940 corrected_dts += sample_duration * (uint64_t)sample_count;
3544 }
3545
3546 2941 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3547
3548
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2919 times.
2941 if (current_dts > corrected_dts) {
3549 22 int64_t drift = av_sat_sub64(current_dts, corrected_dts) / FFMAX(sample_count, 1);
3550
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;
3551 22 current_dts -= correction * (uint64_t)sample_count;
3552 22 sc->stts_data[i].duration -= correction;
3553 }
3554
3555 2941 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3556 2941 total_sample_count+=sc->stts_data[i].count;
3557 }
3558
3559 594 sc->stts_count = i;
3560
3561
2/2
✓ Branch 0 taken 578 times.
✓ Branch 1 taken 16 times.
594 if (duration > 0 &&
3562
1/2
✓ Branch 0 taken 578 times.
✗ Branch 1 not taken.
578 duration <= INT64_MAX - sc->duration_for_fps &&
3563
1/2
✓ Branch 0 taken 578 times.
✗ Branch 1 not taken.
578 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3564 578 sc->duration_for_fps += duration;
3565 578 sc->nb_frames_for_fps += total_sample_count;
3566 }
3567
3568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (pb->eof_reached) {
3569 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3570 return AVERROR_EOF;
3571 }
3572
3573 594 st->nb_frames= total_sample_count;
3574
2/2
✓ Branch 0 taken 578 times.
✓ Branch 1 taken 16 times.
594 if (duration)
3575 578 st->duration= FFMIN(st->duration, duration);
3576
3577 // All samples have zero duration. They have higher chance be chose by
3578 // mov_find_next_sample, which leads to seek again and again.
3579 //
3580 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3581 // So only mark data stream as discarded for safety.
3582
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 578 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
594 if (!duration && sc->stts_count &&
3583 st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3584 av_log(c->fc, AV_LOG_WARNING,
3585 "All samples in data stream index:id [%d:%d] have zero "
3586 "duration, stream set to be discarded by default. Override "
3587 "using AVStream->discard or -discard for ffmpeg command.\n",
3588 st->index, sc->id);
3589 st->discard = AVDISCARD_ALL;
3590 }
3591 594 sc->track_end = duration;
3592 594 return 0;
3593 }
3594
3595 44 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3596 {
3597 AVStream *st;
3598 MOVStreamContext *sc;
3599 int64_t i, entries;
3600
3601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (c->fc->nb_streams < 1)
3602 return 0;
3603 44 st = c->fc->streams[c->fc->nb_streams - 1];
3604 44 sc = st->priv_data;
3605
3606 44 avio_r8(pb); /* version */
3607 44 avio_rb24(pb); /* flags */
3608 44 entries = atom.size - 4;
3609
3610 44 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3611 44 c->fc->nb_streams - 1, entries);
3612
3613
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 36 times.
44 if (sc->sdtp_data)
3614 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3615 44 av_freep(&sc->sdtp_data);
3616 44 sc->sdtp_count = 0;
3617
3618 44 sc->sdtp_data = av_malloc(entries);
3619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (!sc->sdtp_data)
3620 return AVERROR(ENOMEM);
3621
3622
3/4
✓ Branch 0 taken 3807 times.
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 3807 times.
✗ Branch 3 not taken.
3851 for (i = 0; i < entries && !pb->eof_reached; i++)
3623 3807 sc->sdtp_data[i] = avio_r8(pb);
3624 44 sc->sdtp_count = i;
3625
3626 44 return 0;
3627 }
3628
3629 10827 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3630 {
3631
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 9691 times.
10827 if (duration < 0) {
3632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3633 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3634 duration++;
3635 }
3636 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3637 }
3638 10827 }
3639
3640 63 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3641 {
3642 AVStream *st;
3643 MOVStreamContext *sc;
3644 63 unsigned int i, entries, ctts_count = 0;
3645
3646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->trak_index < 0) {
3647 av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
3648 return 0;
3649 }
3650
3651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (c->fc->nb_streams < 1)
3652 return 0;
3653 63 st = c->fc->streams[c->fc->nb_streams-1];
3654 63 sc = st->priv_data;
3655
3656 63 avio_r8(pb); /* version */
3657 63 avio_rb24(pb); /* flags */
3658 63 entries = avio_rb32(pb);
3659
3660 63 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3661
3662
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 59 times.
63 if (!entries)
3663 4 return 0;
3664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
3665 return AVERROR_INVALIDDATA;
3666 59 av_freep(&sc->ctts_data);
3667 59 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
3668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->ctts_data)
3669 return AVERROR(ENOMEM);
3670
3671
3/4
✓ Branch 0 taken 4874 times.
✓ Branch 1 taken 59 times.
✓ Branch 2 taken 4874 times.
✗ Branch 3 not taken.
4933 for (i = 0; i < entries && !pb->eof_reached; i++) {
3672 MOVCtts *ctts_data;
3673 4874 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
3674 4874 const size_t requested_size =
3675 4874 min_size_needed > sc->ctts_allocated_size ?
3676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
3677 min_size_needed;
3678 4874 int count = avio_rb32(pb);
3679 4874 int duration = avio_rb32(pb);
3680
3681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (count <= 0) {
3682 av_log(c->fc, AV_LOG_TRACE,
3683 "ignoring CTTS entry with count=%d duration=%d\n",
3684 count, duration);
3685 continue;
3686 }
3687
3688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
3689 return AVERROR(ENOMEM);
3690
3691 4874 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
3692
3693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4874 times.
4874 if (!ctts_data)
3694 return AVERROR(ENOMEM);
3695
3696 4874 sc->ctts_data = ctts_data;
3697
3698 4874 ctts_data[ctts_count].count = count;
3699 4874 ctts_data[ctts_count].offset = duration;
3700 4874 ctts_count++;
3701
3702 4874 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
3703 count, duration);
3704
3705
2/2
✓ Branch 0 taken 4761 times.
✓ Branch 1 taken 113 times.
4874 if (i+2<entries)
3706 4761 mov_update_dts_shift(sc, duration, c->fc);
3707 }
3708
3709 59 sc->ctts_count = ctts_count;
3710
3711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (pb->eof_reached) {
3712 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
3713 return AVERROR_EOF;
3714 }
3715
3716 59 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
3717
3718 59 return 0;
3719 }
3720
3721 28 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3722 {
3723 AVStream *st;
3724 MOVStreamContext *sc;
3725 uint8_t version;
3726 uint32_t grouping_type;
3727 uint32_t default_length;
3728 av_unused uint32_t default_group_description_index;
3729 uint32_t entry_count;
3730
3731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (c->fc->nb_streams < 1)
3732 return 0;
3733 28 st = c->fc->streams[c->fc->nb_streams - 1];
3734 28 sc = st->priv_data;
3735
3736 28 version = avio_r8(pb); /* version */
3737 28 avio_rb24(pb); /* flags */
3738 28 grouping_type = avio_rl32(pb);
3739
3740 /*
3741 * This function only supports "sync" boxes, but the code is able to parse
3742 * other boxes (such as "tscl", "tsas" and "stsa")
3743 */
3744
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 5 times.
28 if (grouping_type != MKTAG('s','y','n','c'))
3745 23 return 0;
3746
3747
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
3748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
3749 5 entry_count = avio_rb32(pb);
3750
3751 5 av_freep(&sc->sgpd_sync);
3752 5 sc->sgpd_sync_count = entry_count;
3753 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
3754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
3755 return AVERROR(ENOMEM);
3756
3757
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++) {
3758 8 uint32_t description_length = default_length;
3759
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)
3760 description_length = avio_rb32(pb);
3761
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
3762 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
3763 8 sc->sgpd_sync[i] = nal_unit_type;
3764 8 description_length -= 1;
3765 }
3766 8 avio_skip(pb, description_length);
3767 }
3768
3769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
3770 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
3771 return AVERROR_EOF;
3772 }
3773
3774 5 return 0;
3775 }
3776
3777 25 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3778 {
3779 AVStream *st;
3780 MOVStreamContext *sc;
3781 unsigned int i, entries;
3782 uint8_t version;
3783 uint32_t grouping_type;
3784 MOVSbgp *table, **tablep;
3785 int *table_count;
3786
3787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (c->fc->nb_streams < 1)
3788 return 0;
3789 25 st = c->fc->streams[c->fc->nb_streams-1];
3790 25 sc = st->priv_data;
3791
3792 25 version = avio_r8(pb); /* version */
3793 25 avio_rb24(pb); /* flags */
3794 25 grouping_type = avio_rl32(pb);
3795
3796
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 24 times.
25 if (grouping_type == MKTAG('r','a','p',' ')) {
3797 1 tablep = &sc->rap_group;
3798 1 table_count = &sc->rap_group_count;
3799
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19 times.
24 } else if (grouping_type == MKTAG('s','y','n','c')) {
3800 5 tablep = &sc->sync_group;
3801 5 table_count = &sc->sync_group_count;
3802 } else {
3803 19 return 0;
3804 }
3805
3806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
3807 avio_rb32(pb); /* grouping_type_parameter */
3808
3809 6 entries = avio_rb32(pb);
3810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
3811 return 0;
3812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
3813 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
3814 6 av_freep(tablep);
3815 6 table = av_malloc_array(entries, sizeof(*table));
3816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
3817 return AVERROR(ENOMEM);
3818 6 *tablep = table;
3819
3820
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++) {
3821 32 table[i].count = avio_rb32(pb); /* sample_count */
3822 32 table[i].index = avio_rb32(pb); /* group_description_index */
3823 }
3824
3825 6 *table_count = i;
3826
3827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
3828 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
3829 return AVERROR_EOF;
3830 }
3831
3832 6 return 0;
3833 }
3834
3835 /**
3836 * Get ith edit list entry (media time, duration).
3837 */
3838 901 static int get_edit_list_entry(MOVContext *mov,
3839 const MOVStreamContext *msc,
3840 unsigned int edit_list_index,
3841 int64_t *edit_list_media_time,
3842 int64_t *edit_list_duration,
3843 int64_t global_timescale)
3844 {
3845
2/2
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 464 times.
901 if (edit_list_index == msc->elst_count) {
3846 437 return 0;
3847 }
3848 464 *edit_list_media_time = msc->elst_data[edit_list_index].time;
3849 464 *edit_list_duration = msc->elst_data[edit_list_index].duration;
3850
3851 /* duration is in global timescale units;convert to msc timescale */
3852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 464 times.
464 if (global_timescale == 0) {
3853 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
3854 return 0;
3855 }
3856 464 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
3857 global_timescale);
3858
3859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 464 times.
464 if (*edit_list_duration + (uint64_t)*edit_list_media_time > INT64_MAX)
3860 *edit_list_duration = 0;
3861
3862 464 return 1;
3863 }
3864
3865 /**
3866 * Find the closest previous frame to the timestamp_pts, in e_old index
3867 * entries. Searching for just any frame / just key frames can be controlled by
3868 * last argument 'flag'.
3869 * Note that if ctts_data is not NULL, we will always search for a key frame
3870 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
3871 * return the first frame of the video.
3872 *
3873 * Here the timestamp_pts is considered to be a presentation timestamp and
3874 * the timestamp of index entries are considered to be decoding timestamps.
3875 *
3876 * Returns 0 if successful in finding a frame, else returns -1.
3877 * Places the found index corresponding output arg.
3878 *
3879 * If ctts_old is not NULL, then refines the searched entry by searching
3880 * backwards from the found timestamp, to find the frame with correct PTS.
3881 *
3882 * Places the found ctts_index and ctts_sample in corresponding output args.
3883 */
3884 463 static int find_prev_closest_index(AVStream *st,
3885 AVIndexEntry *e_old,
3886 int nb_old,
3887 MOVTimeToSample *tts_data,
3888 int64_t tts_count,
3889 int64_t timestamp_pts,
3890 int flag,
3891 int64_t* index,
3892 int64_t* tts_index,
3893 int64_t* tts_sample)
3894 {
3895 463 MOVStreamContext *msc = st->priv_data;
3896 463 FFStream *const sti = ffstream(st);
3897 463 AVIndexEntry *e_keep = sti->index_entries;
3898 463 int nb_keep = sti->nb_index_entries;
3899 463 int64_t i = 0;
3900
3901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 463 times.
463 av_assert0(index);
3902
3903 // If dts_shift > 0, then all the index timestamps will have to be offset by
3904 // at least dts_shift amount to obtain PTS.
3905 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
3906
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 454 times.
463 if (msc->dts_shift > 0) {
3907 9 timestamp_pts -= msc->dts_shift;
3908 }
3909
3910 463 sti->index_entries = e_old;
3911 463 sti->nb_index_entries = nb_old;
3912 463 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
3913
3914 // Keep going backwards in the index entries until the timestamp is the same.
3915
2/2
✓ Branch 0 taken 462 times.
✓ Branch 1 taken 1 times.
463 if (*index >= 0) {
3916
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 438 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
462 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
3917 i--) {
3918 if ((flag & AVSEEK_FLAG_ANY) ||
3919 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
3920 *index = i - 1;
3921 }
3922 }
3923 }
3924
3925 // If we have CTTS then refine the search, by searching backwards over PTS
3926 // computed by adding corresponding CTTS durations to index timestamps.
3927
4/4
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 399 times.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 1 times.
463 if (msc->ctts_count && *index >= 0) {
3928
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(tts_index);
3929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 av_assert0(tts_sample);
3930 // Find out the ctts_index for the found frame.
3931 63 *tts_index = 0;
3932 63 *tts_sample = 0;
3933
2/2
✓ Branch 0 taken 175 times.
✓ Branch 1 taken 63 times.
238 for (int64_t index_tts_count = 0; index_tts_count < *index; index_tts_count++) {
3934
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (*tts_index < tts_count) {
3935 175 (*tts_sample)++;
3936
1/2
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
175 if (tts_data[*tts_index].count == *tts_sample) {
3937 175 (*tts_index)++;
3938 175 *tts_sample = 0;
3939 }
3940 }
3941 }
3942
3943
4/6
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 70 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 70 times.
✗ Branch 5 not taken.
75 while (*index >= 0 && (*tts_index) >= 0 && (*tts_index) < tts_count) {
3944 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
3945 // No need to add dts_shift to the timestamp here becase timestamp_pts has already been
3946 // compensated by dts_shift above.
3947
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 8 times.
70 if ((e_old[*index].timestamp + tts_data[*tts_index].offset) <= timestamp_pts &&
3948
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 4 times.
62 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
3949 58 break;
3950 }
3951
3952 12 (*index)--;
3953
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (*tts_sample == 0) {
3954 12 (*tts_index)--;
3955
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 if (*tts_index >= 0)
3956 7 *tts_sample = tts_data[*tts_index].count - 1;
3957 } else {
3958 (*tts_sample)--;
3959 }
3960 }
3961 }
3962
3963 /* restore AVStream state*/
3964 463 sti->index_entries = e_keep;
3965 463 sti->nb_index_entries = nb_keep;
3966
2/2
✓ Branch 0 taken 457 times.
✓ Branch 1 taken 6 times.
463 return *index >= 0 ? 0 : -1;
3967 }
3968
3969 /**
3970 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
3971 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
3972 *
3973 * This function is similar to ff_add_index_entry in libavformat/utils.c
3974 * except that here we are always unconditionally adding an index entry to
3975 * the end, instead of searching the entries list and skipping the add if
3976 * there is an existing entry with the same timestamp.
3977 * This is needed because the mov_fix_index calls this func with the same
3978 * unincremented timestamp for successive discarded frames.
3979 */
3980 348547 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
3981 int size, int distance, int flags)
3982 {
3983 348547 FFStream *const sti = ffstream(st);
3984 AVIndexEntry *entries, *ie;
3985 348547 int64_t index = -1;
3986 348547 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
3987
3988 // Double the allocation each time, to lower memory fragmentation.
3989 // Another difference from ff_add_index_entry function.
3990 348547 const size_t requested_size =
3991 348547 min_size_needed > sti->index_entries_allocated_size ?
3992
2/2
✓ Branch 0 taken 1973 times.
✓ Branch 1 taken 346574 times.
348547 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
3993 min_size_needed;
3994
3995
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348547 times.
348547 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
3996 return -1;
3997
3998 348547 entries = av_fast_realloc(sti->index_entries,
3999 &sti->index_entries_allocated_size,
4000 requested_size);
4001
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348547 times.
348547 if (!entries)
4002 return -1;
4003
4004 348547 sti->index_entries = entries;
4005
4006 348547 index = sti->nb_index_entries++;
4007 348547 ie= &entries[index];
4008
4009 348547 ie->pos = pos;
4010 348547 ie->timestamp = timestamp;
4011 348547 ie->min_distance= distance;
4012 348547 ie->size= size;
4013 348547 ie->flags = flags;
4014 348547 return index;
4015 }
4016
4017 /**
4018 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4019 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4020 */
4021 27 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4022 int64_t* frame_duration_buffer,
4023 int frame_duration_buffer_size) {
4024 27 FFStream *const sti = ffstream(st);
4025 27 int i = 0;
4026
2/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
27 av_assert0(end_index >= 0 && end_index <= sti->nb_index_entries);
4027
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 27 times.
164 for (i = 0; i < frame_duration_buffer_size; i++) {
4028 137 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4029 137 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4030 }
4031 27 }
4032
4033 186048 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4034 int count, int offset, unsigned int duration)
4035 {
4036 MOVTimeToSample *tts_buf_new;
4037 186048 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4038 186048 const size_t requested_size =
4039 186048 min_size_needed > *allocated_size ?
4040
2/2
✓ Branch 0 taken 1341 times.
✓ Branch 1 taken 184707 times.
186048 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4041 min_size_needed;
4042
4043
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186048 times.
186048 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4044 return -1;
4045
4046 186048 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4047
4048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186048 times.
186048 if (!tts_buf_new)
4049 return -1;
4050
4051 186048 *tts_data = tts_buf_new;
4052
4053 186048 tts_buf_new[*tts_count].count = count;
4054 186048 tts_buf_new[*tts_count].offset = offset;
4055 186048 tts_buf_new[*tts_count].duration = duration;
4056
4057 186048 *tts_count = (*tts_count) + 1;
4058 186048 return 0;
4059 }
4060
4061 #define MAX_REORDER_DELAY 16
4062 603 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4063 {
4064 603 MOVStreamContext *msc = st->priv_data;
4065 603 FFStream *const sti = ffstream(st);
4066 603 int ctts_ind = 0;
4067 603 int ctts_sample = 0;
4068 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4069 603 int buf_start = 0;
4070 int j, r, num_swaps;
4071
4072
2/2
✓ Branch 0 taken 10251 times.
✓ Branch 1 taken 603 times.
10854 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4073 10251 pts_buf[j] = INT64_MIN;
4074
4075
3/4
✓ Branch 0 taken 603 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 544 times.
603 if (st->codecpar->video_delay <= 0 && msc->ctts_count &&
4076
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 16 times.
59 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4077 43 st->codecpar->video_delay = 0;
4078
3/4
✓ Branch 0 taken 138279 times.
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 138279 times.
✗ Branch 3 not taken.
138322 for (int ind = 0; ind < sti->nb_index_entries && ctts_ind < msc->tts_count; ++ind) {
4079 // Point j to the last elem of the buffer and insert the current pts there.
4080 138279 j = buf_start;
4081 138279 buf_start = (buf_start + 1);
4082
2/2
✓ Branch 0 taken 8111 times.
✓ Branch 1 taken 130168 times.
138279 if (buf_start == MAX_REORDER_DELAY + 1)
4083 8111 buf_start = 0;
4084
4085 138279 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4086
4087 // The timestamps that are already in the sorted buffer, and are greater than the
4088 // current pts, are exactly the timestamps that need to be buffered to output PTS
4089 // in correct sorted order.
4090 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4091 // can be computed as the maximum no. of swaps any particular timestamp needs to
4092 // go through, to keep this buffer in sorted order.
4093 138279 num_swaps = 0;
4094
2/2
✓ Branch 0 taken 142294 times.
✓ Branch 1 taken 4 times.
142298 while (j != buf_start) {
4095 142294 r = j - 1;
4096
2/2
✓ Branch 0 taken 8389 times.
✓ Branch 1 taken 133905 times.
142294 if (r < 0) r = MAX_REORDER_DELAY;
4097
2/2
✓ Branch 0 taken 4019 times.
✓ Branch 1 taken 138275 times.
142294 if (pts_buf[j] < pts_buf[r]) {
4098 4019 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4099 4019 ++num_swaps;
4100 } else {
4101 138275 break;
4102 }
4103 4019 j = r;
4104 }
4105 138279 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4106
4107 138279 ctts_sample++;
4108
1/2
✓ Branch 0 taken 138279 times.
✗ Branch 1 not taken.
138279 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4109 138279 ctts_ind++;
4110 138279 ctts_sample = 0;
4111 }
4112 }
4113 43 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4114 43 st->codecpar->video_delay, st->index);
4115 }
4116 603 }
4117
4118 103399 static void mov_current_sample_inc(MOVStreamContext *sc)
4119 {
4120 103399 sc->current_sample++;
4121 103399 sc->current_index++;
4122
2/2
✓ Branch 0 taken 61399 times.
✓ Branch 1 taken 42000 times.
103399 if (sc->index_ranges &&
4123
2/2
✓ Branch 0 taken 421 times.
✓ Branch 1 taken 60978 times.
61399 sc->current_index >= sc->current_index_range->end &&
4124
1/2
✓ Branch 0 taken 421 times.
✗ Branch 1 not taken.
421 sc->current_index_range->end) {
4125 421 sc->current_index_range++;
4126 421 sc->current_index = sc->current_index_range->start;
4127 }
4128 103399 }
4129
4130 static void mov_current_sample_dec(MOVStreamContext *sc)
4131 {
4132 sc->current_sample--;
4133 sc->current_index--;
4134 if (sc->index_ranges &&
4135 sc->current_index < sc->current_index_range->start &&
4136 sc->current_index_range > sc->index_ranges) {
4137 sc->current_index_range--;
4138 sc->current_index = sc->current_index_range->end - 1;
4139 }
4140 }
4141
4142 335 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4143 {
4144 int64_t range_size;
4145
4146 335 sc->current_sample = current_sample;
4147 335 sc->current_index = current_sample;
4148
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 309 times.
335 if (!sc->index_ranges) {
4149 26 return;
4150 }
4151
4152 309 for (sc->current_index_range = sc->index_ranges;
4153
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 sc->current_index_range->end;
4154 sc->current_index_range++) {
4155 309 range_size = sc->current_index_range->end - sc->current_index_range->start;
4156
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 if (range_size > current_sample) {
4157 309 sc->current_index = sc->current_index_range->start + current_sample;
4158 309 break;
4159 }
4160 current_sample -= range_size;
4161 }
4162 }
4163
4164 /**
4165 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4166 * which are needed to decode them) that fall in the edit list time ranges.
4167 * Also fixes the timestamps of the index entries to match the timeline
4168 * specified the edit lists.
4169 */
4170 603 static void mov_fix_index(MOVContext *mov, AVStream *st)
4171 {
4172 603 MOVStreamContext *msc = st->priv_data;
4173 603 FFStream *const sti = ffstream(st);
4174 603 AVIndexEntry *e_old = sti->index_entries;
4175 603 int nb_old = sti->nb_index_entries;
4176 603 const AVIndexEntry *e_old_end = e_old + nb_old;
4177 603 const AVIndexEntry *current = NULL;
4178 603 MOVTimeToSample *tts_data_old = msc->tts_data;
4179 603 int64_t tts_index_old = 0;
4180 603 int64_t tts_sample_old = 0;
4181 603 int64_t tts_count_old = msc->tts_count;
4182 603 int64_t edit_list_media_time = 0;
4183 603 int64_t edit_list_duration = 0;
4184 603 int64_t frame_duration = 0;
4185 603 int64_t edit_list_dts_counter = 0;
4186 603 int64_t edit_list_dts_entry_end = 0;
4187 603 int64_t edit_list_start_tts_sample = 0;
4188 int64_t curr_cts;
4189 603 int64_t curr_ctts = 0;
4190 603 int64_t empty_edits_sum_duration = 0;
4191 603 int64_t edit_list_index = 0;
4192 int64_t index;
4193 int flags;
4194 603 int64_t start_dts = 0;
4195 603 int64_t edit_list_start_encountered = 0;
4196 603 int64_t search_timestamp = 0;
4197 603 int64_t* frame_duration_buffer = NULL;
4198 603 int num_discarded_begin = 0;
4199 603 int first_non_zero_audio_edit = -1;
4200 603 int packet_skip_samples = 0;
4201 603 MOVIndexRange *current_index_range = NULL;
4202 603 int found_keyframe_after_edit = 0;
4203 603 int found_non_empty_edit = 0;
4204
4205
4/6
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 166 times.
✓ Branch 2 taken 437 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 437 times.
603 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
4206 166 return;
4207 }
4208
4209 // allocate the index ranges array
4210 437 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4211 sizeof(msc->index_ranges[0]));
4212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 437 times.
437 if (!msc->index_ranges) {
4213 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4214 return;
4215 }
4216 437 msc->current_index_range = msc->index_ranges;
4217
4218 // Clean AVStream from traces of old index
4219 437 sti->index_entries = NULL;
4220 437 sti->index_entries_allocated_size = 0;
4221 437 sti->nb_index_entries = 0;
4222
4223 // Clean time to sample fields of MOVStreamContext
4224 437 msc->tts_data = NULL;
4225 437 msc->tts_count = 0;
4226 437 msc->tts_index = 0;
4227 437 msc->tts_sample = 0;
4228 437 msc->tts_allocated_size = 0;
4229
4230 // Reinitialize min_corrected_pts so that it can be computed again.
4231 437 msc->min_corrected_pts = -1;
4232
4233 // If the dts_shift is positive (in case of negative ctts values in mov),
4234 // then negate the DTS by dts_shift
4235
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 428 times.
437 if (msc->dts_shift > 0) {
4236 9 edit_list_dts_entry_end -= msc->dts_shift;
4237 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4238 }
4239
4240 437 start_dts = edit_list_dts_entry_end;
4241
4242
2/2
✓ Branch 0 taken 464 times.
✓ Branch 1 taken 437 times.
1338 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
4243 901 &edit_list_duration, mov->time_scale)) {
4244 464 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4245 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4246 464 edit_list_index++;
4247 464 edit_list_dts_counter = edit_list_dts_entry_end;
4248 464 edit_list_dts_entry_end += edit_list_duration;
4249 464 num_discarded_begin = 0;
4250
4/4
✓ Branch 0 taken 441 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 437 times.
464 if (!found_non_empty_edit && edit_list_media_time == -1) {
4251 4 empty_edits_sum_duration += edit_list_duration;
4252 4 continue;
4253 }
4254 460 found_non_empty_edit = 1;
4255
4256 // If we encounter a non-negative edit list reset the skip_samples/start_pad fields and set them
4257 // according to the edit list below.
4258
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 333 times.
460 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4259
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit < 0) {
4260 127 first_non_zero_audio_edit = 1;
4261 } else {
4262 first_non_zero_audio_edit = 0;
4263 }
4264
4265
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 if (first_non_zero_audio_edit > 0)
4266 127 sti->skip_samples = msc->start_pad = 0;
4267 }
4268
4269 // While reordering frame index according to edit list we must handle properly
4270 // the scenario when edit list entry starts from none key frame.
4271 // We find closest previous key frame and preserve it and consequent frames in index.
4272 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4273 460 search_timestamp = edit_list_media_time;
4274
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 333 times.
460 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4275 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4276 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4277 // edit_list_media_time to cover the decoder delay.
4278 127 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
4279 }
4280
4281
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 457 times.
460 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, 0,
4282 &index, &tts_index_old, &tts_sample_old) < 0) {
4283 3 av_log(mov->fc, AV_LOG_WARNING,
4284 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4285 st->index, edit_list_index, search_timestamp);
4286
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, AVSEEK_FLAG_ANY,
4287 &index, &tts_index_old, &tts_sample_old) < 0) {
4288 3 av_log(mov->fc, AV_LOG_WARNING,
4289 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4290 st->index, edit_list_index, search_timestamp);
4291 3 index = 0;
4292 3 tts_index_old = 0;
4293 3 tts_sample_old = 0;
4294 }
4295 }
4296 460 current = e_old + index;
4297 460 edit_list_start_tts_sample = tts_sample_old;
4298
4299 // Iterate over index and arrange it according to edit list
4300 460 edit_list_start_encountered = 0;
4301 460 found_keyframe_after_edit = 0;
4302
2/2
✓ Branch 0 taken 348547 times.
✓ Branch 1 taken 112 times.
348659 for (; current < e_old_end; current++, index++) {
4303 // check if frame outside edit list mark it for discard
4304 697094 frame_duration = (current + 1 < e_old_end) ?
4305
2/2
✓ Branch 0 taken 348114 times.
✓ Branch 1 taken 433 times.
348547 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4306
4307 348547 flags = current->flags;
4308
4309 // frames (pts) before or after edit list
4310 348547 curr_cts = current->timestamp + msc->dts_shift;
4311 348547 curr_ctts = 0;
4312
4313
4/4
✓ Branch 0 taken 186060 times.
✓ Branch 1 taken 162487 times.
✓ Branch 2 taken 186048 times.
✓ Branch 3 taken 12 times.
348547 if (tts_data_old && tts_index_old < tts_count_old) {
4314 186048 curr_ctts = tts_data_old[tts_index_old].offset;
4315 186048 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4316 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4317 186048 curr_cts += curr_ctts;
4318 186048 tts_sample_old++;
4319
1/2
✓ Branch 0 taken 186048 times.
✗ Branch 1 not taken.
186048 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186048 times.
186048 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4321 &msc->tts_allocated_size,
4322 186048 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4323 186048 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4324 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4325 tts_index_old,
4326 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4327 tts_data_old[tts_index_old].offset);
4328 break;
4329 }
4330 186048 tts_index_old++;
4331 186048 tts_sample_old = 0;
4332 186048 edit_list_start_tts_sample = 0;
4333 }
4334 }
4335
4336
4/4
✓ Branch 0 taken 348395 times.
✓ Branch 1 taken 152 times.
✓ Branch 2 taken 130 times.
✓ Branch 3 taken 348265 times.
348547 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
4337
4/4
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 205 times.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 46 times.
282 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
4338
4/6
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
31 curr_cts < edit_list_media_time && curr_cts + frame_duration > edit_list_media_time &&
4339 first_non_zero_audio_edit > 0) {
4340 11 packet_skip_samples = edit_list_media_time - curr_cts;
4341 11 sti->skip_samples += packet_skip_samples;
4342
4343 // Shift the index entry timestamp by packet_skip_samples to be correct.
4344 11 edit_list_dts_counter -= packet_skip_samples;
4345
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (edit_list_start_encountered == 0) {
4346 11 edit_list_start_encountered = 1;
4347 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4348 // discarded packets.
4349
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 if (frame_duration_buffer) {
4350 6 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4351 frame_duration_buffer, num_discarded_begin);
4352 6 av_freep(&frame_duration_buffer);
4353 }
4354 }
4355
4356 11 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4357 } else {
4358 271 flags |= AVINDEX_DISCARD_FRAME;
4359 271 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4360
4361
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 132 times.
271 if (edit_list_start_encountered == 0) {
4362 139 num_discarded_begin++;
4363 139 frame_duration_buffer = av_realloc(frame_duration_buffer,
4364 num_discarded_begin * sizeof(int64_t));
4365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if (!frame_duration_buffer) {
4366 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4367 break;
4368 }
4369 139 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4370
4371 // Increment skip_samples for the first non-zero audio edit list
4372
3/4
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 73 times.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
139 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4373
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 46 times.
66 first_non_zero_audio_edit > 0 && st->codecpar->codec_id != AV_CODEC_ID_VORBIS) {
4374 20 sti->skip_samples += frame_duration;
4375 }
4376 }
4377 }
4378 } else {
4379
2/2
✓ Branch 0 taken 436 times.
✓ Branch 1 taken 347829 times.
348265 if (msc->min_corrected_pts < 0) {
4380 436 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4381 } else {
4382 347829 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4383 }
4384
2/2
✓ Branch 0 taken 447 times.
✓ Branch 1 taken 347818 times.
348265 if (edit_list_start_encountered == 0) {
4385 447 edit_list_start_encountered = 1;
4386 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4387 // discarded packets.
4388
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 426 times.
447 if (frame_duration_buffer) {
4389 21 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4390 frame_duration_buffer, num_discarded_begin);
4391 21 av_freep(&frame_duration_buffer);
4392 }
4393 }
4394 }
4395
4396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348547 times.
348547 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
4397 348547 current->min_distance, flags) == -1) {
4398 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4399 break;
4400 }
4401
4402 // Update the index ranges array
4403
4/4
✓ Branch 0 taken 348110 times.
✓ Branch 1 taken 437 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 348089 times.
348547 if (!current_index_range || index != current_index_range->end) {
4404 458 current_index_range = current_index_range ? current_index_range + 1
4405
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 437 times.
458 : msc->index_ranges;
4406 458 current_index_range->start = index;
4407 }
4408 348547 current_index_range->end = index + 1;
4409
4410 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4411
2/2
✓ Branch 0 taken 348408 times.
✓ Branch 1 taken 139 times.
348547 if (edit_list_start_encountered > 0) {
4412 348408 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4413 }
4414
4415 // Break when found first key frame after edit entry completion
4416
2/2
✓ Branch 0 taken 616 times.
✓ Branch 1 taken 347931 times.
348547 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
4417
3/4
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 256 times.
616 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
4418
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 339 times.
360 if (msc->ctts_count) {
4419 // If we have CTTS and this is the first keyframe after edit elist,
4420 // wait for one more, because there might be trailing B-frames after this I-frame
4421 // that do belong to the edit.
4422
3/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 9 times.
21 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO && found_keyframe_after_edit == 0) {
4423 12 found_keyframe_after_edit = 1;
4424 12 continue;
4425 }
4426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (tts_sample_old != 0) {
4427 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4428 &msc->tts_allocated_size,
4429 tts_sample_old - edit_list_start_tts_sample,
4430 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4431 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4432 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4433 tts_data_old[tts_index_old].offset);
4434 break;
4435 }
4436 }
4437 }
4438 348 break;
4439 }
4440 }
4441 }
4442 // If there are empty edits, then msc->min_corrected_pts might be positive
4443 // intentionally. So we subtract the sum duration of emtpy edits here.
4444 437 msc->min_corrected_pts -= empty_edits_sum_duration;
4445
4446 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4447 // dts by that amount to make the first pts zero.
4448
2/2
✓ Branch 0 taken 268 times.
✓ Branch 1 taken 169 times.
437 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4449
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 227 times.
268 if (msc->min_corrected_pts > 0) {
4450 41 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4451
2/2
✓ Branch 0 taken 2829 times.
✓ Branch 1 taken 41 times.
2870 for (int i = 0; i < sti->nb_index_entries; ++i)
4452 2829 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4453 }
4454 }
4455 // Start time should be equal to zero or the duration of any empty edits.
4456 437 st->start_time = empty_edits_sum_duration;
4457
4458 // Update av stream length, if it ends up shorter than the track's media duration
4459 437 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4460 437 msc->start_pad = sti->skip_samples;
4461
4462 // Free the old index and the old CTTS structures
4463 437 av_free(e_old);
4464 437 av_free(tts_data_old);
4465 437 av_freep(&frame_duration_buffer);
4466
4467 // Null terminate the index ranges array
4468 437 current_index_range = current_index_range ? current_index_range + 1
4469
1/2
✓ Branch 0 taken 437 times.
✗ Branch 1 not taken.
437 : msc->index_ranges;
4470 437 current_index_range->start = 0;
4471 437 current_index_range->end = 0;
4472 437 msc->current_index = msc->index_ranges[0].start;
4473 }
4474
4475 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4476 {
4477
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4478
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == nal_unit_type)
4479 5 return i + 1;
4480 return 0;
4481 }
4482
4483 619 static int build_open_gop_key_points(AVStream *st)
4484 {
4485 int k;
4486 619 int sample_id = 0;
4487 uint32_t cra_index;
4488 619 MOVStreamContext *sc = st->priv_data;
4489
4490
4/4
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 580 times.
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 5 times.
619 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count)
4491 614 return 0;
4492
4493 /* Build an unrolled index of the samples */
4494 5 sc->sample_offsets_count = 0;
4495
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4497 return AVERROR(ENOMEM);
4498 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4499 }
4500 5 av_freep(&sc->sample_offsets);
4501 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4503 return AVERROR(ENOMEM);
4504 5 k = 0;
4505
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4506
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4507 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4508
4509 /* The following HEVC NAL type reveal the use of open GOP sync points
4510 * (TODO: BLA types may also be concerned) */
4511 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4513 return 0;
4514
4515 /* Build a list of open-GOP key samples */
4516 5 sc->open_key_samples_count = 0;
4517
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4518
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4519
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)
4520 return AVERROR(ENOMEM);
4521 11 sc->open_key_samples_count += sc->sync_group[i].count;
4522 }
4523 5 av_freep(&sc->open_key_samples);
4524 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4526 return AVERROR(ENOMEM);
4527 5 k = 0;
4528
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4529 28 const MOVSbgp *sg = &sc->sync_group[i];
4530
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4531
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4532 11 sc->open_key_samples[k++] = sample_id;
4533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4534 return AVERROR_PATCHWELCOME;
4535 28 sample_id += sg->count;
4536 }
4537
4538 /* Identify the minimal time step between samples */
4539 5 sc->min_sample_duration = UINT_MAX;
4540
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4541 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4542
4543 5 return 0;
4544 }
4545
4546 #define MOV_MERGE_CTTS 1
4547 #define MOV_MERGE_STTS 2
4548 /*
4549 * Merge stts and ctts arrays into a new combined array.
4550 * stts_count and ctts_count may be left untouched as they will be
4551 * used to check for the presence of either of them.
4552 */
4553 603 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4554 {
4555 603 MOVStreamContext *sc = st->priv_data;
4556
3/4
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 544 times.
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
603 int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS);
4557
3/4
✓ Branch 0 taken 603 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 537 times.
✓ Branch 3 taken 66 times.
603 int stts = sc->stts_data && (flags & MOV_MERGE_STTS);
4558 603 int idx = 0;
4559
4560
3/4
✓ Branch 0 taken 544 times.
✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 544 times.
603 if (!sc->ctts_data && !sc->stts_data)
4561 return 0;
4562 // Expand time to sample entries such that we have a 1-1 mapping with samples
4563
2/4
✓ Branch 0 taken 603 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 603 times.
603 if (!sc->sample_count || sc->sample_count >= UINT_MAX / sizeof(*sc->tts_data))
4564 return -1;
4565
4566
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 544 times.
603 if (ctts) {
4567 118 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4568 59 sc->sample_count * sizeof(*sc->tts_data));
4569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!sc->tts_data)
4570 return -1;
4571
4572 59 memset(sc->tts_data, 0, sc->tts_allocated_size);
4573
4574
2/2
✓ Branch 0 taken 4874 times.
✓ Branch 1 taken 59 times.
4933 for (int i = 0; i < sc->ctts_count &&
4575
1/2
✓ Branch 0 taken 4874 times.
✗ Branch 1 not taken.
9748 idx < sc->sample_count; i++)
4576
2/2
✓ Branch 0 taken 139017 times.
✓ Branch 1 taken 4874 times.
143891 for (int j = 0; j < sc->ctts_data[i].count &&
4577
1/2
✓ Branch 0 taken 139017 times.
✗ Branch 1 not taken.
139017 idx < sc->sample_count; j++) {
4578 139017 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4579 139017 sc->tts_data[idx++].count = 1;
4580 }
4581
4582 59 sc->tts_count = idx;
4583 } else
4584 544 sc->ctts_count = 0;
4585 603 av_freep(&sc->ctts_data);
4586 603 sc->ctts_allocated_size = 0;
4587
4588 603 idx = 0;
4589
2/2
✓ Branch 0 taken 537 times.
✓ Branch 1 taken 66 times.
603 if (stts) {
4590 537 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4591 537 sc->sample_count * sizeof(*sc->tts_data));
4592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 537 times.
537 if (!tts_data)
4593 return -1;
4594
4595
2/2
✓ Branch 0 taken 478 times.
✓ Branch 1 taken 59 times.
537 if (!sc->tts_data)
4596 478 memset(tts_data, 0, sc->tts_allocated_size);
4597 537 sc->tts_data = tts_data;
4598
4599
2/2
✓ Branch 0 taken 2900 times.
✓ Branch 1 taken 537 times.
3437 for (int i = 0; i < sc->stts_count &&
4600
1/2
✓ Branch 0 taken 2900 times.
✗ Branch 1 not taken.
5800 idx < sc->sample_count; i++)
4601
2/2
✓ Branch 0 taken 235894 times.
✓ Branch 1 taken 2900 times.
238794 for (int j = 0; j < sc->stts_data[i].count &&
4602
1/2
✓ Branch 0 taken 235894 times.
✗ Branch 1 not taken.
235894 idx < sc->sample_count; j++) {
4603 235894 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4604 235894 sc->tts_data[idx++].count = 1;
4605 }
4606
4607 537 sc->tts_count = FFMAX(sc->tts_count, idx);
4608 } else
4609 66 sc->stts_count = 0;
4610 603 av_freep(&sc->stts_data);
4611 603 sc->stts_allocated_size = 0;
4612
4613 603 return 0;
4614 }
4615
4616 619 static void mov_build_index(MOVContext *mov, AVStream *st)
4617 {
4618 619 MOVStreamContext *sc = st->priv_data;
4619 619 FFStream *const sti = ffstream(st);
4620 int64_t current_offset;
4621 619 int64_t current_dts = 0;
4622 619 unsigned int stts_index = 0;
4623 619 unsigned int stsc_index = 0;
4624 619 unsigned int stss_index = 0;
4625 619 unsigned int stps_index = 0;
4626 unsigned int i, j;
4627 619 uint64_t stream_size = 0;
4628
4629 619 int ret = build_open_gop_key_points(st);
4630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 619 times.
619 if (ret < 0)
4631 return;
4632
4633
2/2
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 180 times.
619 if (sc->elst_count) {
4634 439 int i, edit_start_index = 0, multiple_edits = 0;
4635 439 int64_t empty_duration = 0; // empty duration of the first edit list entry
4636 439 int64_t start_time = 0; // start time of the media
4637
4638
2/2
✓ Branch 0 taken 466 times.
✓ Branch 1 taken 439 times.
905 for (i = 0; i < sc->elst_count; i++) {
4639 466 const MOVElst *e = &sc->elst_data[i];
4640
4/4
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 435 times.
466 if (i == 0 && e->time == -1) {
4641 /* if empty, the first entry is the start time of the stream
4642 * relative to the presentation itself */
4643 4 empty_duration = e->duration;
4644 4 edit_start_index = 1;
4645
3/4
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 439 times.
✗ Branch 3 not taken.
462 } else if (i == edit_start_index && e->time >= 0) {
4646 439 start_time = e->time;
4647 } else {
4648 23 multiple_edits = 1;
4649 }
4650 }
4651
4652
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 433 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
439 if (multiple_edits && !mov->advanced_editlist) {
4653 if (mov->advanced_editlist_autodisabled)
4654 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4655 "not supported in fragmented MP4 files\n");
4656 else
4657 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4658 "Use -advanced_editlist to correctly decode otherwise "
4659 "a/v desync might occur\n");
4660 }
4661
4662 /* adjust first dts according to edit list */
4663
5/6
✓ Branch 0 taken 435 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 366 times.
✓ Branch 4 taken 73 times.
✗ Branch 5 not taken.
439 if ((empty_duration || start_time) && mov->time_scale > 0) {
4664
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 69 times.
73 if (empty_duration)
4665 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
4666
4667
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
73 if (av_sat_sub64(start_time, empty_duration) != start_time - (uint64_t)empty_duration)
4668 av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
4669
4670 73 sc->time_offset = start_time - (uint64_t)empty_duration;
4671 73 sc->min_corrected_pts = start_time;
4672
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 72 times.
73 if (!mov->advanced_editlist)
4673 1 current_dts = -sc->time_offset;
4674 }
4675
4676
4/4
✓ Branch 0 taken 433 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 431 times.
439 if (!multiple_edits && !mov->advanced_editlist &&
4677
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 st->codecpar->codec_id == AV_CODEC_ID_AAC && start_time > 0)
4678 sc->start_pad = start_time;
4679 }
4680
4681 /* only use old uncompressed audio chunk demuxing when stts specifies it */
4682
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 378 times.
619 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4683
5/6
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 187 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 121 times.
✓ Branch 5 taken 66 times.
778 sc->stts_count == 1 && sc->stts_data && sc->stts_data[0].duration == 1)) {
4684 553 unsigned int current_sample = 0;
4685 553 unsigned int stts_sample = 0;
4686 unsigned int sample_size;
4687 553 unsigned int distance = 0;
4688 553 unsigned int rap_group_index = 0;
4689 553 unsigned int rap_group_sample = 0;
4690
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 552 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
553 int rap_group_present = sc->rap_group_count && sc->rap_group;
4691
4/8
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 415 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 138 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 415 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
553 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
4692
4693 553 current_dts -= sc->dts_shift;
4694
4695
4/6
✓ Branch 0 taken 537 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 537 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 537 times.
553 if (!sc->sample_count || sti->nb_index_entries || sc->tts_count)
4696 16 return;
4697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 537 times.
537 if (sc->sample_count >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4698 return;
4699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 537 times.
537 if (av_reallocp_array(&sti->index_entries,
4700 537 sti->nb_index_entries + sc->sample_count,
4701 sizeof(*sti->index_entries)) < 0) {
4702 sti->nb_index_entries = 0;
4703 return;
4704 }
4705 537 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
4706
4707 537 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
4708
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 537 times.
537 if (ret < 0)
4709 return;
4710
4711
2/2
✓ Branch 0 taken 173840 times.
✓ Branch 1 taken 537 times.
174377 for (i = 0; i < sc->chunk_count; i++) {
4712
2/2
✓ Branch 0 taken 173303 times.
✓ Branch 1 taken 537 times.
173840 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
4713 173840 current_offset = sc->chunk_offsets[i];
4714
2/2
✓ Branch 1 taken 8859 times.
✓ Branch 2 taken 167524 times.
176383 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4715
2/2
✓ Branch 0 taken 2543 times.
✓ Branch 1 taken 6316 times.
8859 i + 1 == sc->stsc_data[stsc_index + 1].first)
4716 2543 stsc_index++;
4717
4718
4/6
✓ Branch 0 taken 173840 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7346 times.
✓ Branch 3 taken 166494 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7346 times.
173840 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
4719 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
4720 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
4721 sc->stsz_sample_size = sc->sample_size;
4722 }
4723
3/4
✓ Branch 0 taken 7346 times.
✓ Branch 1 taken 166494 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7346 times.
173840 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
4724 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
4725 sc->stsz_sample_size = sc->sample_size;
4726 }
4727
4728
2/2
✓ Branch 0 taken 235894 times.
✓ Branch 1 taken 173840 times.
409734 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
4729 235894 int keyframe = 0;
4730
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235894 times.
235894 if (current_sample >= sc->sample_count) {
4731 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
4732 return;
4733 }
4734
4735
6/6
✓ Branch 0 taken 231138 times.
✓ Branch 1 taken 4756 times.
✓ Branch 2 taken 152644 times.
✓ Branch 3 taken 78494 times.
✓ Branch 4 taken 5706 times.
✓ Branch 5 taken 146938 times.
235894 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
4736 84200 keyframe = 1;
4737
2/2
✓ Branch 0 taken 5568 times.
✓ Branch 1 taken 78632 times.
84200 if (stss_index + 1 < sc->keyframe_count)
4738 5568 stss_index++;
4739
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 151694 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
151694 } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
4740 keyframe = 1;
4741 if (stps_index + 1 < sc->stps_count)
4742 stps_index++;
4743 }
4744
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 235706 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
235894 if (rap_group_present && rap_group_index < sc->rap_group_count) {
4745
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
4746 2 keyframe = 1;
4747
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
4748 4 rap_group_sample = 0;
4749 4 rap_group_index++;
4750 }
4751 }
4752
2/2
✓ Branch 0 taken 4756 times.
✓ Branch 1 taken 231138 times.
235894 if (sc->keyframe_absent
4753
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !sc->stps_count
4754
1/2
✓ Branch 0 taken 4756 times.
✗ Branch 1 not taken.
4756 && !rap_group_present
4755
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)))
4756 3884 keyframe = 1;
4757
2/2
✓ Branch 0 taken 88084 times.
✓ Branch 1 taken 147810 times.
235894 if (keyframe)
4758 88084 distance = 0;
4759
2/2
✓ Branch 0 taken 8986 times.
✓ Branch 1 taken 226908 times.
235894 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
4760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235894 times.
235894 if (current_offset > INT64_MAX - sample_size) {
4761 av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
4762 current_offset,
4763 sample_size);
4764 return;
4765 }
4766
4767
2/2
✓ Branch 0 taken 235813 times.
✓ Branch 1 taken 81 times.
235894 if (sc->pseudo_stream_id == -1 ||
4768
1/2
✓ Branch 0 taken 235813 times.
✗ Branch 1 not taken.
235813 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
4769 AVIndexEntry *e;
4770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235894 times.
235894 if (sample_size > 0x3FFFFFFF) {
4771 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
4772 return;
4773 }
4774 235894 e = &sti->index_entries[sti->nb_index_entries++];
4775 235894 e->pos = current_offset;
4776 235894 e->timestamp = current_dts;
4777 235894 e->size = sample_size;
4778 235894 e->min_distance = distance;
4779 235894 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
4780 235894 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
4781 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
4782 current_offset, current_dts, sample_size, distance, keyframe);
4783
4/4
✓ Branch 0 taken 154994 times.
✓ Branch 1 taken 80900 times.
✓ Branch 2 taken 10361 times.
✓ Branch 3 taken 144633 times.
235894 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries < 100)
4784 10361 ff_rfps_add_frame(mov->fc, st, current_dts);
4785 }
4786
4787 235894 current_offset += sample_size;
4788 235894 stream_size += sample_size;
4789
4790 235894 current_dts += sc->tts_data[stts_index].duration;
4791
4792 235894 distance++;
4793 235894 stts_sample++;
4794 235894 current_sample++;
4795
3/4
✓ Branch 0 taken 235357 times.
✓ Branch 1 taken 537 times.
✓ Branch 2 taken 235357 times.
✗ Branch 3 not taken.
235894 if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) {
4796 235357 stts_sample = 0;
4797 235357 stts_index++;
4798 }
4799 }
4800 }
4801
2/2
✓ Branch 0 taken 512 times.
✓ Branch 1 taken 25 times.
537 if (st->duration > 0)
4802 512 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
4803 } else {
4804 66 unsigned chunk_samples, total = 0;
4805
4806
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)
4807 return;
4808
4809 66 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
4810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
4811 return;
4812
4813 // compute total chunk count
4814
2/2
✓ Branch 0 taken 723 times.
✓ Branch 1 taken 66 times.
789 for (i = 0; i < sc->stsc_count; i++) {
4815 unsigned count, chunk_count;
4816
4817 723 chunk_samples = sc->stsc_data[i].count;
4818
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 66 times.
723 if (i != sc->stsc_count - 1 &&
4819
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) {
4820 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
4821 return;
4822 }
4823
4824
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 648 times.
723 if (sc->samples_per_frame >= 160) { // gsm
4825 75 count = chunk_samples / sc->samples_per_frame;
4826
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 117 times.
648 } else if (sc->samples_per_frame > 1) {
4827 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
4828 531 count = (chunk_samples+samples-1) / samples;
4829 } else {
4830 117 count = (chunk_samples+1023) / 1024;
4831 }
4832
4833
2/2
✓ Branch 1 taken 657 times.
✓ Branch 2 taken 66 times.
723 if (mov_stsc_index_valid(i, sc->stsc_count))
4834 657 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
4835 else
4836 66 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
4837 723 total += chunk_count * count;
4838 }
4839
4840 66 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
4841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4842 return;
4843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (av_reallocp_array(&sti->index_entries,
4844 66 sti->nb_index_entries + total,
4845 sizeof(*sti->index_entries)) < 0) {
4846 sti->nb_index_entries = 0;
4847 return;
4848 }
4849 66 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
4850
4851 // populate index
4852
2/2
✓ Branch 0 taken 5428 times.
✓ Branch 1 taken 66 times.
5494 for (i = 0; i < sc->chunk_count; i++) {
4853 5428 current_offset = sc->chunk_offsets[i];
4854
2/2
✓ Branch 1 taken 5287 times.
✓ Branch 2 taken 141 times.
5428 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4855
2/2
✓ Branch 0 taken 657 times.
✓ Branch 1 taken 4630 times.
5287 i + 1 == sc->stsc_data[stsc_index + 1].first)
4856 657 stsc_index++;
4857 5428 chunk_samples = sc->stsc_data[stsc_index].count;
4858
4859
2/2
✓ Branch 0 taken 162532 times.
✓ Branch 1 taken 5428 times.
167960 while (chunk_samples > 0) {
4860 AVIndexEntry *e;
4861 unsigned size, samples;
4862
4863
3/4
✓ Branch 0 taken 23921 times.
✓ Branch 1 taken 138611 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 23921 times.
162532 if (sc->samples_per_frame > 1 && !sc->bytes_per_frame) {
4864 avpriv_request_sample(mov->fc,
4865 "Zero bytes per frame, but %d samples per frame",
4866 sc->samples_per_frame);
4867 return;
4868 }
4869
4870
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 148174 times.
162532 if (sc->samples_per_frame >= 160) { // gsm
4871 14358 samples = sc->samples_per_frame;
4872 14358 size = sc->bytes_per_frame;
4873 } else {
4874
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 138611 times.
148174 if (sc->samples_per_frame > 1) {
4875 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
4876 sc->samples_per_frame, chunk_samples);
4877 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
4878 } else {
4879 138611 samples = FFMIN(1024, chunk_samples);
4880 138611 size = samples * sc->sample_size;
4881 }
4882 }
4883
4884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (sti->nb_index_entries >= total) {
4885 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
4886 return;
4887 }
4888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162532 times.
162532 if (size > 0x3FFFFFFF) {
4889 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
4890 return;
4891 }
4892 162532 e = &sti->index_entries[sti->nb_index_entries++];
4893 162532 e->pos = current_offset;
4894 162532 e->timestamp = current_dts;
4895 162532 e->size = size;
4896 162532 e->min_distance = 0;
4897 162532 e->flags = AVINDEX_KEYFRAME;
4898 162532 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
4899 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
4900 size, samples);
4901
4902 162532 current_offset += size;
4903 162532 current_dts += samples;
4904 162532 chunk_samples -= samples;
4905 }
4906 }
4907 }
4908
4909
2/4
✓ Branch 0 taken 603 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 603 times.
✗ Branch 3 not taken.
603 if (!mov->ignore_editlist && mov->advanced_editlist) {
4910 // Fix index according to edit lists.
4911 603 mov_fix_index(mov, st);
4912 }
4913
4914 // Update start time of the stream.
4915
5/6
✓ Branch 0 taken 166 times.
✓ Branch 1 taken 437 times.
✓ Branch 2 taken 49 times.
✓ Branch 3 taken 117 times.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
603 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) {
4916 49 st->start_time = sti->index_entries[0].timestamp + sc->dts_shift;
4917
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 if (sc->tts_data) {
4918 49 st->start_time += sc->tts_data[0].offset;
4919 }
4920 }
4921
4922 603 mov_estimate_video_delay(mov, st);
4923 }
4924
4925 static int test_same_origin(const char *src, const char *ref) {
4926 char src_proto[64];
4927 char ref_proto[64];
4928 char src_auth[256];
4929 char ref_auth[256];
4930 char src_host[256];
4931 char ref_host[256];
4932 int src_port=-1;
4933 int ref_port=-1;
4934
4935 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
4936 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
4937
4938 if (strlen(src) == 0) {
4939 return -1;
4940 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
4941 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
4942 strlen(src_host) + 1 >= sizeof(src_host) ||
4943 strlen(ref_host) + 1 >= sizeof(ref_host)) {
4944 return 0;
4945 } else if (strcmp(src_proto, ref_proto) ||
4946 strcmp(src_auth, ref_auth) ||
4947 strcmp(src_host, ref_host) ||
4948 src_port != ref_port) {
4949 return 0;
4950 } else
4951 return 1;
4952 }
4953
4954 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
4955 {
4956 /* try relative path, we do not try the absolute because it can leak information about our
4957 system to an attacker */
4958 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
4959 char filename[1025];
4960 const char *src_path;
4961 int i, l;
4962
4963 /* find a source dir */
4964 src_path = strrchr(src, '/');
4965 if (src_path)
4966 src_path++;
4967 else
4968 src_path = src;
4969
4970 /* find a next level down to target */
4971 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
4972 if (ref->path[l] == '/') {
4973 if (i == ref->nlvl_to - 1)
4974 break;
4975 else
4976 i++;
4977 }
4978
4979 /* compose filename if next level down to target was found */
4980 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
4981 memcpy(filename, src, src_path - src);
4982 filename[src_path - src] = 0;
4983
4984 for (i = 1; i < ref->nlvl_from; i++)
4985 av_strlcat(filename, "../", sizeof(filename));
4986
4987 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
4988 if (!c->use_absolute_path) {
4989 int same_origin = test_same_origin(src, filename);
4990
4991 if (!same_origin) {
4992 av_log(c->fc, AV_LOG_ERROR,
4993 "Reference with mismatching origin, %s not tried for security reasons, "
4994 "set demuxer option use_absolute_path to allow it anyway\n",
4995 ref->path);
4996 return AVERROR(ENOENT);
4997 }
4998
4999 if (strstr(ref->path + l + 1, "..") ||
5000 strstr(ref->path + l + 1, ":") ||
5001 (ref->nlvl_from > 1 && same_origin < 0) ||
5002 (filename[0] == '/' && src_path == src))
5003 return AVERROR(ENOENT);
5004 }
5005
5006 if (strlen(filename) + 1 == sizeof(filename))
5007 return AVERROR(ENOENT);
5008 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5009 return 0;
5010 }
5011 } else if (c->use_absolute_path) {
5012 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5013 "this is a possible security issue\n");
5014 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5015 return 0;
5016 } else {
5017 av_log(c->fc, AV_LOG_ERROR,
5018 "Absolute path %s not tried for security reasons, "
5019 "set demuxer option use_absolute_path to allow absolute paths\n",
5020 ref->path);
5021 }
5022
5023 return AVERROR(ENOENT);
5024 }
5025
5026 1267 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5027 {
5028
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1253 times.
1267 if (sc->time_scale <= 0) {
5029 14 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5030 14 sc->time_scale = c->time_scale;
5031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (sc->time_scale <= 0)
5032 sc->time_scale = 1;
5033 }
5034 1267 }
5035
5036 #if CONFIG_IAMFDEC
5037 10 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5038 {
5039 10 const MOVStreamContext *sc = st->priv_data;
5040 10 const IAMFContext *iamf = &sc->iamf->iamf;
5041
5042
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5043 10 const AVStreamGroup *stg = NULL;
5044
5045
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5046
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (c->fc->stream_groups[j]->id == iamf->audio_elements[i]->audio_element_id)
5047 10 stg = c->fc->stream_groups[j];
5048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 av_assert0(stg);
5049
5050
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int j = 0; j < stg->nb_streams; j++) {
5051 50 const FFStream *sti = cffstream(st);
5052 50 AVStream *out = stg->streams[j];
5053 50 FFStream *out_sti = ffstream(stg->streams[j]);
5054
5055 50 out->codecpar->bit_rate = 0;
5056
5057
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 40 times.
50 if (out == st)
5058 10 continue;
5059
5060 40 out->time_base = st->time_base;
5061 40 out->start_time = st->start_time;
5062 40 out->duration = st->duration;
5063 40 out->nb_frames = st->nb_frames;
5064 40 out->discard = st->discard;
5065
5066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 av_assert0(!out_sti->index_entries);
5067 40 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5068
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (!out_sti->index_entries)
5069 return AVERROR(ENOMEM);
5070
5071 40 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5072 40 out_sti->nb_index_entries = sti->nb_index_entries;
5073 40 out_sti->skip_samples = sti->skip_samples;
5074 40 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5075 }
5076 }
5077
5078 10 return 0;
5079 }
5080 #endif
5081
5082 619 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5083 {
5084
4/6
✓ Branch 0 taken 603 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 603 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 603 times.
✗ Branch 5 not taken.
619 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5085
3/4
✓ Branch 0 taken 405 times.
✓ Branch 1 taken 198 times.
✓ Branch 2 taken 405 times.
✗ Branch 3 not taken.
603 (!sc->sample_size && !sc->sample_count))) ||
5086
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 603 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
619 (!sc->chunk_count && sc->sample_count)) {
5087 av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5088 index);
5089 return 1;
5090 }
5091
5092
3/4
✓ Branch 0 taken 603 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 603 times.
619 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
5093 av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5094 index);
5095 return 2;
5096 }
5097 619 return 0;
5098 }
5099
5100 594 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5101 {
5102 AVStream *st;
5103 MOVStreamContext *sc;
5104 int ret;
5105
5106 594 st = avformat_new_stream(c->fc, NULL);
5107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (!st) return AVERROR(ENOMEM);
5108 594 st->id = -1;
5109 594 sc = av_mallocz(sizeof(MOVStreamContext));
5110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (!sc) return AVERROR(ENOMEM);
5111
5112 594 st->priv_data = sc;
5113 594 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5114 594 sc->ffindex = st->index;
5115 594 c->trak_index = st->index;
5116 594 sc->tref_flags = 0;
5117 594 sc->tref_id = -1;
5118 594 sc->refcount = 1;
5119
5120
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 594 times.
594 if ((ret = mov_read_default(c, pb, atom)) < 0)
5121 return ret;
5122
5123 594 c->trak_index = -1;
5124
5125 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5126 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5127
5/6
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 578 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 15 times.
594 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
5128 1 sc->stsc_count = 0;
5129 1 av_freep(&sc->stsc_data);
5130 }
5131
5132 594 ret = sanity_checks(c->fc, sc, st->index);
5133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (ret)
5134 return ret > 1 ? AVERROR_INVALIDDATA : 0;
5135
5136 594 fix_timescale(c, sc);
5137
5138 594 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5139
5140 /*
5141 * Advanced edit list support does not work with fragemented MP4s, which
5142 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5143 * In these files, trun atoms may be streamed in.
5144 */
5145
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 578 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 4 times.
594 if (!sc->stts_count && c->advanced_editlist) {
5146
5147 12 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5148 "MP4. disabling.\n");
5149 12 c->advanced_editlist = 0;
5150 12 c->advanced_editlist_autodisabled = 1;
5151 }
5152
5153 594 mov_build_index(c, st);
5154
5155 #if CONFIG_IAMFDEC
5156
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 584 times.
594 if (sc->iamf) {
5157 10 ret = mov_update_iamf_streams(c, st);
5158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
5159 return ret;
5160 }
5161 #endif
5162
5163
3/4
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 593 times.
594 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
5164 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5165 if (c->enable_drefs) {
5166 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5167 av_log(c->fc, AV_LOG_ERROR,
5168 "stream %d, error opening alias: path='%s', dir='%s', "
5169 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5170 st->index, dref->path, dref->dir, dref->filename,
5171 dref->volume, dref->nlvl_from, dref->nlvl_to);
5172 } else {
5173 av_log(c->fc, AV_LOG_WARNING,
5174 "Skipped opening external track: "
5175 "stream %d, alias: path='%s', dir='%s', "
5176 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5177 "Set enable_drefs to allow this.\n",
5178 st->index, dref->path, dref->dir, dref->filename,
5179 dref->volume, dref->nlvl_from, dref->nlvl_to);
5180 }
5181 } else {
5182 594 sc->pb = c->fc->pb;
5183 594 sc->pb_is_copied = 1;
5184 }
5185
5186
2/2
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 292 times.
594 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5187
3/4
✓ Branch 0 taken 292 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 292 times.
✗ Branch 3 not taken.
302 int stts_constant = sc->stts_count && sc->tts_count;
5188
3/4
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 244 times.
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
302 if (sc->h_spacing && sc->v_spacing)
5189 58 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5190 58 sc->h_spacing, sc->v_spacing, INT_MAX);
5191
4/6
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 61 times.
✓ Branch 2 taken 241 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 241 times.
✗ Branch 5 not taken.
302 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
5192
2/4
✓ Branch 0 taken 241 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241 times.
✗ Branch 3 not taken.
241 sc->height && sc->width &&
5193
2/4
✓ Branch 0 taken 241 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 241 times.
241 (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
5194 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5195 (int64_t)st->codecpar->height * sc->width,
5196 (int64_t)st->codecpar->width * sc->height, INT_MAX);
5197 }
5198
5199 #if FF_API_R_FRAME_RATE
5200
4/4
✓ Branch 0 taken 154827 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 154535 times.
✓ Branch 3 taken 292 times.
154837 for (unsigned int i = 1; sc->stts_count && i + 1 < sc->tts_count; i++) {
5201
2/2
✓ Branch 0 taken 152108 times.
✓ Branch 1 taken 2427 times.
154535 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5202 152108 continue;
5203 2427 stts_constant = 0;
5204 }
5205
2/2
✓ Branch 0 taken 278 times.
✓ Branch 1 taken 24 times.
302 if (stts_constant)
5206 278 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5207 278 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5208 #endif
5209 }
5210
5211 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
5212
3/4
✓ Branch 0 taken 263 times.
✓ Branch 1 taken 331 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 263 times.
594 if (!st->codecpar->extradata_size && st->codecpar->codec_id == AV_CODEC_ID_H264 &&
5213 TAG_IS_AVCI(st->codecpar->codec_tag)) {
5214 ret = ff_generate_avci_extradata(st);
5215 if (ret < 0)
5216 return ret;
5217 }
5218
5219
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 570 times.
594 switch (st->codecpar->codec_id) {
5220 #if CONFIG_H261_DECODER
5221 24 case AV_CODEC_ID_H261:
5222 #endif
5223 #if CONFIG_H263_DECODER
5224 case AV_CODEC_ID_H263:
5225 #endif
5226 #if CONFIG_MPEG4_DECODER
5227 case AV_CODEC_ID_MPEG4:
5228 #endif
5229 24 st->codecpar->width = 0; /* let decoder init width/height */
5230 24 st->codecpar->height= 0;
5231 24 break;
5232 }
5233
5234 // If the duration of the mp3 packets is not constant, then they could need a parser
5235
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 593 times.
594 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5236
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 && sc->time_scale == st->codecpar->sample_rate) {
5237 1 int stts_constant = 1;
5238
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++) {
5239
1/2
✓ Branch 0 taken 287 times.
✗ Branch 1 not taken.
287 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5240 287 continue;
5241 stts_constant = 0;
5242 }
5243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!stts_constant)
5244 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5245 }
5246 /* Do not need those anymore. */
5247 594 av_freep(&sc->chunk_offsets);
5248 594 av_freep(&sc->sample_sizes);
5249 594 av_freep(&sc->keyframes);
5250 594 av_freep(&sc->stps_data);
5251 594 av_freep(&sc->elst_data);
5252 594 av_freep(&sc->rap_group);
5253 594 av_freep(&sc->sync_group);
5254 594 av_freep(&sc->sgpd_sync);
5255
5256 594 return 0;
5257 }
5258
5259 125 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5260 {
5261 int ret;
5262 125 c->itunes_metadata = 1;
5263 125 ret = mov_read_default(c, pb, atom);
5264 125 c->itunes_metadata = 0;
5265 125 return ret;
5266 }
5267
5268 11 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5269 {
5270 uint32_t count;
5271 uint32_t i;
5272
5273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
5274 return 0;
5275
5276 11 avio_skip(pb, 4);
5277 11 count = avio_rb32(pb);
5278 11 atom.size -= 8;
5279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (count >= UINT_MAX / sizeof(*c->meta_keys)) {
5280 av_log(c->fc, AV_LOG_ERROR,
5281 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5282 return AVERROR_INVALIDDATA;
5283 }
5284
5285 11 c->meta_keys_count = count + 1;
5286 11 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
5287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!c->meta_keys)
5288 return AVERROR(ENOMEM);
5289
5290
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i <= count; ++i) {
5291 58 uint32_t key_size = avio_rb32(pb);
5292 58 uint32_t type = avio_rl32(pb);
5293
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) {
5294 av_log(c->fc, AV_LOG_ERROR,
5295 "The key# %"PRIu32" in meta has invalid size:"
5296 "%"PRIu32"\n", i, key_size);
5297 return AVERROR_INVALIDDATA;
5298 }
5299 58 atom.size -= key_size;
5300 58 key_size -= 8;
5301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (type != MKTAG('m','d','t','a')) {
5302 avio_skip(pb, key_size);
5303 continue;
5304 }
5305 58 c->meta_keys[i] = av_mallocz(key_size + 1);
5306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!c->meta_keys[i])
5307 return AVERROR(ENOMEM);
5308 58 avio_read(pb, c->meta_keys[i], key_size);
5309 }
5310
5311 11 return 0;
5312 }
5313
5314 65 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5315 {
5316 65 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5317 65 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5318 int i;
5319 65 int ret = 0;
5320 AVStream *st;
5321 MOVStreamContext *sc;
5322
5323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (c->fc->nb_streams < 1)
5324 return 0;
5325 65 st = c->fc->streams[c->fc->nb_streams-1];
5326 65 sc = st->priv_data;
5327
5328
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 65 times.
260 for (i = 0; i < 3; i++) {
5329 uint8_t **p;
5330 uint32_t len, tag;
5331
5332
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 195 times.
195 if (end - avio_tell(pb) <= 12)
5333 break;
5334
5335 195 len = avio_rb32(pb);
5336 195 tag = avio_rl32(pb);
5337 195 avio_skip(pb, 4); // flags
5338
5339
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))
5340 break;
5341 195 len -= 12;
5342
5343
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 130 times.
195 if (tag == MKTAG('m', 'e', 'a', 'n'))
5344 65 p = &mean;
5345
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 65 times.
130 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5346 65 p = &key;
5347
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) {
5348 65 avio_skip(pb, 4);
5349 65 len -= 4;
5350 65 p = &val;
5351 } else
5352 break;
5353
5354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (*p)
5355 break;
5356
5357 195 *p = av_malloc(len + 1);
5358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (!*p) {
5359 ret = AVERROR(ENOMEM);
5360 break;
5361 }
5362 195 ret = ffio_read_size(pb, *p, len);
5363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 if (ret < 0) {
5364 av_freep(p);
5365 break;
5366 }
5367 195 (*p)[len] = 0;
5368 }
5369
5370
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) {
5371
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 32 times.
65 if (strcmp(key, "iTunSMPB") == 0) {
5372 int priming, remainder, samples;
5373
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
5374
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)
5375 33 sc->start_pad = priming;
5376 }
5377 }
5378
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 10 times.
120 if (strcmp(key, "cdec") != 0) {
5379 55 av_dict_set(&c->fc->metadata, key, val,
5380 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5381 55 key = val = NULL;
5382 }
5383 } else {
5384 av_log(c->fc, AV_LOG_VERBOSE,
5385 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5386 }
5387
5388 65 avio_seek(pb, end, SEEK_SET);
5389 65 av_freep(&key);
5390 65 av_freep(&val);
5391 65 av_freep(&mean);
5392 65 return ret;
5393 }
5394
5395 25 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5396 {
5397 MOVStreamContext *sc;
5398 AVStream *st;
5399
5400 25 st = avformat_new_stream(c->fc, NULL);
5401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!st)
5402 return AVERROR(ENOMEM);
5403 25 sc = av_mallocz(sizeof(MOVStreamContext));
5404
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!sc)
5405 return AVERROR(ENOMEM);
5406
5407 25 item->st = st;
5408 25 st->id = item->item_id;
5409 25 st->priv_data = sc;
5410 25 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5411 25 st->codecpar->codec_id = mov_codec_id(st, item->type);
5412 25 sc->id = st->id;
5413 25 sc->ffindex = st->index;
5414 25 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5415 25 st->time_base.num = st->time_base.den = 1;
5416 25 st->nb_frames = 1;
5417 25 sc->time_scale = 1;
5418 25 sc->pb = c->fc->pb;
5419 25 sc->pb_is_copied = 1;
5420 25 sc->refcount = 1;
5421
5422
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 if (item->name)
5423 25 av_dict_set(&st->metadata, "title", item->name, 0);
5424
5425 // Populate the necessary fields used by mov_build_index.
5426 25 sc->stsc_count = 1;
5427 25 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!sc->stsc_data)
5429 return AVERROR(ENOMEM);
5430 25 sc->stsc_data[0].first = 1;
5431 25 sc->stsc_data[0].count = 1;
5432 25 sc->stsc_data[0].id = 1;
5433 25 sc->chunk_count = 1;
5434 25 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!sc->chunk_offsets)
5436 return AVERROR(ENOMEM);
5437 25 sc->sample_count = 1;
5438 25 sc->sample_sizes = av_malloc_array(1, sizeof(*sc->sample_sizes));
5439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!sc->sample_sizes)
5440 return AVERROR(ENOMEM);
5441 25 sc->stts_count = 1;
5442 25 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!sc->stts_data)
5444 return AVERROR(ENOMEM);
5445 25 sc->stts_data[0].count = 1;
5446 // Not used for still images. But needed by mov_build_index.
5447 25 sc->stts_data[0].duration = 0;
5448
5449 25 return 0;
5450 }
5451
5452 140 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5453 {
5454
1/2
✓ Branch 0 taken 406 times.
✗ Branch 1 not taken.
406 while (atom.size > 8) {
5455 uint32_t tag;
5456
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 406 times.
406 if (avio_feof(pb))
5457 return AVERROR_EOF;
5458 406 tag = avio_rl32(pb);
5459 406 atom.size -= 4;
5460
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 266 times.
406 if (tag == MKTAG('h','d','l','r')) {
5461 140 avio_seek(pb, -8, SEEK_CUR);
5462 140 atom.size += 8;
5463 140 return mov_read_default(c, pb, atom);
5464 }
5465 }
5466 return 0;
5467 }
5468
5469 // return 1 when matrix is identity, 0 otherwise
5470 #define IS_MATRIX_IDENT(matrix) \
5471 ( (matrix)[0][0] == (1 << 16) && \
5472 (matrix)[1][1] == (1 << 16) && \
5473 (matrix)[2][2] == (1 << 30) && \
5474 !(matrix)[0][1] && !(matrix)[0][2] && \
5475 !(matrix)[1][0] && !(matrix)[1][2] && \
5476 !(matrix)[2][0] && !(matrix)[2][1])
5477
5478 594 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5479 {
5480 int i, j, e;
5481 int width;
5482 int height;
5483 int display_matrix[3][3];
5484 594 int res_display_matrix[3][3] = { { 0 } };
5485 AVStream *st;
5486 MOVStreamContext *sc;
5487 int version;
5488 int flags;
5489
5490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (c->fc->nb_streams < 1)
5491 return 0;
5492 594 st = c->fc->streams[c->fc->nb_streams-1];
5493 594 sc = st->priv_data;
5494
5495 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5496 // avoids corrupting AVStreams mapped to an earlier tkhd.
5497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 594 times.
594 if (st->id != -1)
5498 return AVERROR_INVALIDDATA;
5499
5500 594 version = avio_r8(pb);
5501 594 flags = avio_rb24(pb);
5502 594 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5503
5504
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 585 times.
594 if (version == 1) {
5505 9 avio_rb64(pb);
5506 9 avio_rb64(pb);
5507 } else {
5508 585 avio_rb32(pb); /* creation time */
5509 585 avio_rb32(pb); /* modification time */
5510 }
5511 594 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5512 594 sc->id = st->id;
5513 594 avio_rb32(pb); /* reserved */
5514
5515 /* highlevel (considering edits) duration in movie timebase */
5516
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 585 times.
594 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5517 594 avio_rb32(pb); /* reserved */
5518 594 avio_rb32(pb); /* reserved */
5519
5520 594 avio_rb16(pb); /* layer */
5521 594 avio_rb16(pb); /* alternate group */
5522 594 avio_rb16(pb); /* volume */
5523 594 avio_rb16(pb); /* reserved */
5524
5525 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
5526 // they're kept in fixed point format through all calculations
5527 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
5528 // side data, but the scale factor is not needed to calculate aspect ratio
5529
2/2
✓ Branch 0 taken 1782 times.
✓ Branch 1 taken 594 times.
2376 for (i = 0; i < 3; i++) {
5530 1782 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
5531 1782 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
5532 1782 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
5533 }
5534
5535 594 width = avio_rb32(pb); // 16.16 fixed point track width
5536 594 height = avio_rb32(pb); // 16.16 fixed point track height
5537 594 sc->width = width >> 16;
5538 594 sc->height = height >> 16;
5539
5540 // apply the moov display matrix (after the tkhd one)
5541
2/2
✓ Branch 0 taken 1782 times.
✓ Branch 1 taken 594 times.
2376 for (i = 0; i < 3; i++) {
5542 1782 const int sh[3] = { 16, 16, 30 };
5543
2/2
✓ Branch 0 taken 5346 times.
✓ Branch 1 taken 1782 times.
7128 for (j = 0; j < 3; j++) {
5544
2/2
✓ Branch 0 taken 16038 times.
✓ Branch 1 taken 5346 times.
21384 for (e = 0; e < 3; e++) {
5545 16038 res_display_matrix[i][j] +=
5546 16038 ((int64_t) display_matrix[i][e] *
5547 16038 c->movie_display_matrix[e][j]) >> sh[e];
5548 }
5549 }
5550 }
5551
5552 // save the matrix when it is not the default identity
5553
10/18
✓ Branch 0 taken 585 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 585 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 585 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 585 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 585 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 585 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 585 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 585 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 585 times.
594 if (!IS_MATRIX_IDENT(res_display_matrix)) {
5554 9 av_freep(&sc->display_matrix);
5555 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
5556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
5557 return AVERROR(ENOMEM);
5558
5559
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
5560
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
5561 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
5562 }
5563
5564 // transform the display width/height according to the matrix
5565 // to keep the same scale, use [width height 1<<16]
5566
5/6
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 282 times.
✓ Branch 2 taken 312 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 304 times.
594 if (width && height && sc->display_matrix) {
5567 double disp_transform[2];
5568
5569
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
5570 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
5571 16 sc->display_matrix[3 + i]);
5572
5573
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 &&
5574
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) &&
5575
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
5576 3 st->sample_aspect_ratio = av_d2q(
5577 3 disp_transform[0] / disp_transform[1],
5578 INT_MAX);
5579 }
5580 594 return 0;
5581 }
5582
5583 388 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5584 {
5585 388 MOVFragment *frag = &c->fragment;
5586 388 MOVTrackExt *trex = NULL;
5587 int flags, track_id, i;
5588 MOVFragmentStreamInfo * frag_stream_info;
5589
5590 388 avio_r8(pb); /* version */
5591 388 flags = avio_rb24(pb);
5592
5593 388 track_id = avio_rb32(pb);
5594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!track_id)
5595 return AVERROR_INVALIDDATA;
5596
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < c->trex_count; i++)
5597
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (c->trex_data[i].track_id == track_id) {
5598 388 trex = &c->trex_data[i];
5599 388 break;
5600 }
5601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!trex) {
5602 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
5603 return 0;
5604 }
5605 388 c->fragment.found_tfhd = 1;
5606 388 frag->track_id = track_id;
5607 388 set_frag_stream(&c->frag_index, track_id);
5608
5609 776 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
5610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
776 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
5611
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 21 times.
388 frag->moof_offset : frag->implicit_offset;
5612
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 385 times.
388 frag->stsd_id = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id;
5613
5614 776 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
5615
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 383 times.
388 avio_rb32(pb) : trex->duration;
5616 776 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
5617
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 382 times.
388 avio_rb32(pb) : trex->size;
5618 776 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
5619
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 365 times.
388 avio_rb32(pb) : trex->flags;
5620 388 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
5621
5622 388 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5623
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5624 388 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
5625 388 frag_stream_info->stsd_id = frag->stsd_id;
5626 }
5627 388 return 0;
5628 }
5629
5630 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5631 {
5632 unsigned i, num;
5633 void *new_tracks;
5634
5635 2 num = atom.size / 4;
5636
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
5637 return AVERROR(ENOMEM);
5638
5639 2 av_free(c->chapter_tracks);
5640 2 c->chapter_tracks = new_tracks;
5641 2 c->nb_chapter_tracks = num;
5642
5643
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++)
5644 2 c->chapter_tracks[i] = avio_rb32(pb);
5645
5646 2 c->nb_chapter_tracks = i;
5647
5648 2 return 0;
5649 }
5650
5651 17 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5652 {
5653 MOVTrackExt *trex;
5654 int err;
5655
5656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if ((uint64_t)c->trex_count+1 >= UINT_MAX / sizeof(*c->trex_data))
5657 return AVERROR_INVALIDDATA;
5658
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
5659 sizeof(*c->trex_data))) < 0) {
5660 c->trex_count = 0;
5661 return err;
5662 }
5663
5664 17 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
5665
5666 17 trex = &c->trex_data[c->trex_count++];
5667 17 avio_r8(pb); /* version */
5668 17 avio_rb24(pb); /* flags */
5669 17 trex->track_id = avio_rb32(pb);
5670 17 trex->stsd_id = avio_rb32(pb);
5671 17 trex->duration = avio_rb32(pb);
5672 17 trex->size = avio_rb32(pb);
5673 17 trex->flags = avio_rb32(pb);
5674 17 return 0;
5675 }
5676
5677 367 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5678 {
5679 367 MOVFragment *frag = &c->fragment;
5680 367 AVStream *st = NULL;
5681 MOVStreamContext *sc;
5682 int version, i;
5683 MOVFragmentStreamInfo * frag_stream_info;
5684 int64_t base_media_decode_time;
5685
5686
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 for (i = 0; i < c->fc->nb_streams; i++) {
5687 367 sc = c->fc->streams[i]->priv_data;
5688
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 if (sc->id == frag->track_id) {
5689 367 st = c->fc->streams[i];
5690 367 break;
5691 }
5692 }
5693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367 times.
367 if (!st) {
5694 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5695 return 0;
5696 }
5697 367 sc = st->priv_data;
5698
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 365 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
367 if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1)
5699 return 0;
5700 367 version = avio_r8(pb);
5701 367 avio_rb24(pb); /* flags */
5702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367 times.
367 if (version) {
5703 base_media_decode_time = avio_rb64(pb);
5704 } else {
5705 367 base_media_decode_time = avio_rb32(pb);
5706 }
5707
5708 367 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5709
1/2
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
367 if (frag_stream_info)
5710 367 frag_stream_info->tfdt_dts = base_media_decode_time;
5711 367 sc->track_end = base_media_decode_time;
5712
5713 367 return 0;
5714 }
5715
5716 388 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5717 {
5718 388 MOVFragment *frag = &c->fragment;
5719 388 AVStream *st = NULL;
5720 388 FFStream *sti = NULL;
5721 MOVStreamContext *sc;
5722 MOVTimeToSample *tts_data;
5723 uint64_t offset;
5724 388 int64_t dts, pts = AV_NOPTS_VALUE;
5725 388 int data_offset = 0;
5726 388 unsigned entries, first_sample_flags = frag->flags;
5727 int flags, distance, i;
5728 388 int64_t prev_dts = AV_NOPTS_VALUE;
5729 388 int next_frag_index = -1, index_entry_pos;
5730 size_t requested_size;
5731 size_t old_allocated_size;
5732 AVIndexEntry *new_entries;
5733 MOVFragmentStreamInfo * frag_stream_info;
5734
5735
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!frag->found_tfhd) {
5736 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
5737 return AVERROR_INVALIDDATA;
5738 }
5739
5740
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 for (i = 0; i < c->fc->nb_streams; i++) {
5741 394 sc = c->fc->streams[i]->priv_data;
5742
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 6 times.
394 if (sc->id == frag->track_id) {
5743 388 st = c->fc->streams[i];
5744 388 sti = ffstream(st);
5745 388 break;
5746 }
5747 }
5748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!st) {
5749 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5750 return 0;
5751 }
5752 388 sc = st->priv_data;
5753
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 386 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
388 if (sc->pseudo_stream_id+1 != frag->stsd_id && sc->pseudo_stream_id != -1)
5754 return 0;
5755
5756 // Find the next frag_index index that has a valid index_entry for
5757 // the current track_id.
5758 //
5759 // A valid index_entry means the trun for the fragment was read
5760 // and it's samples are in index_entries at the given position.
5761 // New index entries will be inserted before the index_entry found.
5762 388 index_entry_pos = sti->nb_index_entries;
5763
2/2
✓ Branch 0 taken 1621 times.
✓ Branch 1 taken 388 times.
2009 for (i = c->frag_index.current + 1; i < c->frag_index.nb_items; i++) {
5764 1621 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
5765
2/4
✓ Branch 0 taken 1621 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1621 times.
1621 if (frag_stream_info && frag_stream_info->index_entry >= 0) {
5766 next_frag_index = i;
5767 index_entry_pos = frag_stream_info->index_entry;
5768 break;
5769 }
5770 }
5771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 av_assert0(index_entry_pos <= sti->nb_index_entries);
5772
5773 388 avio_r8(pb); /* version */
5774 388 flags = avio_rb24(pb);
5775 388 entries = avio_rb32(pb);
5776 388 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
5777
5778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if ((uint64_t)entries+sc->tts_count >= UINT_MAX/sizeof(*sc->tts_data))
5779 return AVERROR_INVALIDDATA;
5780
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
5781
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 367 times.
388 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb);
5782
5783 388 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5784
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
5786 dts = frag_stream_info->next_trun_dts - sc->time_offset;
5787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5788 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
5789 pts = frag_stream_info->first_tfra_pts;
5790 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5791 ", using it for pts\n", pts);
5792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
5793 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
5794 dts = frag_stream_info->first_tfra_pts;
5795 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
5796 ", using it for dts\n", pts);
5797 } else {
5798 388 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
5799 388 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
5800
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
388 int fallback_tfdt = !c->use_tfdt && !has_sidx && has_tfdt;
5801
4/6
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 367 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
388 int fallback_sidx = c->use_tfdt && !has_tfdt && has_sidx;
5802
5803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (fallback_sidx) {
5804 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
5805 }
5806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (fallback_tfdt) {
5807 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
5808 }
5809
5810
4/6
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 367 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
388 if (has_tfdt && c->use_tfdt || fallback_tfdt) {
5811 367 dts = frag_stream_info->tfdt_dts - sc->time_offset;
5812 367 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
5813 ", using it for dts\n", dts);
5814
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
21 } else if (has_sidx && !c->use_tfdt || fallback_sidx) {
5815 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
5816 // pts = frag_stream_info->sidx_pts;
5817 dts = frag_stream_info->sidx_pts - sc->time_offset;
5818 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
5819 ", using it for dts\n", frag_stream_info->sidx_pts);
5820 } else {
5821 21 dts = sc->track_end - sc->time_offset;
5822 21 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5823 ", using it for dts\n", dts);
5824 }
5825 }
5826 } else {
5827 dts = sc->track_end - sc->time_offset;
5828 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
5829 ", using it for dts\n", dts);
5830 }
5831 388 offset = frag->base_data_offset + data_offset;
5832 388 distance = 0;
5833 388 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
5834
5835 // realloc space for new index entries
5836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
5837 entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
5838 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
5839 }
5840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (entries == 0)
5841 return 0;
5842
5843 388 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
5844 388 new_entries = av_fast_realloc(sti->index_entries,
5845 &sti->index_entries_allocated_size,
5846 requested_size);
5847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!new_entries)
5848 return AVERROR(ENOMEM);
5849 388 sti->index_entries= new_entries;
5850
5851 388 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
5852 388 old_allocated_size = sc->tts_allocated_size;
5853 388 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
5854 requested_size);
5855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (!tts_data)
5856 return AVERROR(ENOMEM);
5857 388 sc->tts_data = tts_data;
5858
5859 // In case there were samples without time to sample entries, ensure they get
5860 // zero valued entries. This ensures clips which mix boxes with and
5861 // without time to sample entries don't pickup uninitialized data.
5862 388 memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0,
5863 388 sc->tts_allocated_size - old_allocated_size);
5864
5865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (index_entry_pos < sti->nb_index_entries) {
5866 // Make hole in index_entries and tts_data for new samples
5867 memmove(sti->index_entries + index_entry_pos + entries,
5868 sti->index_entries + index_entry_pos,
5869 sizeof(*sti->index_entries) *
5870 (sti->nb_index_entries - index_entry_pos));
5871 memmove(sc->tts_data + index_entry_pos + entries,
5872 sc->tts_data + index_entry_pos,
5873 sizeof(*sc->tts_data) * (sc->tts_count - index_entry_pos));
5874 if (index_entry_pos < sc->current_sample) {
5875 sc->current_sample += entries;
5876 }
5877 }
5878
5879 388 sti->nb_index_entries += entries;
5880 388 sc->tts_count = sti->nb_index_entries;
5881 388 sc->stts_count = sti->nb_index_entries;
5882
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 28 times.
388 if (flags & MOV_TRUN_SAMPLE_CTS)
5883 360 sc->ctts_count = sti->nb_index_entries;
5884
5885 // Record the index_entry position in frag_index of this fragment
5886
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info) {
5887 388 frag_stream_info->index_entry = index_entry_pos;
5888
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info->index_base < 0)
5889 388 frag_stream_info->index_base = index_entry_pos;
5890 }
5891
5892
2/2
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 14 times.
388 if (index_entry_pos > 0)
5893 374 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
5894
5895
3/4
✓ Branch 0 taken 6066 times.
✓ Branch 1 taken 388 times.
✓ Branch 2 taken 6066 times.
✗ Branch 3 not taken.
6454 for (i = 0; i < entries && !pb->eof_reached; i++) {
5896 6066 unsigned sample_size = frag->size;
5897
2/2
✓ Branch 0 taken 5678 times.
✓ Branch 1 taken 388 times.
6066 int sample_flags = i ? frag->flags : first_sample_flags;
5898 6066 unsigned sample_duration = frag->duration;
5899 6066 unsigned ctts_duration = 0;
5900 6066 int keyframe = 0;
5901 6066 int index_entry_flags = 0;
5902
5903
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 5594 times.
6066 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
5904
2/2
✓ Branch 0 taken 6034 times.
✓ Branch 1 taken 32 times.
6066 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
5905
2/2
✓ Branch 0 taken 933 times.
✓ Branch 1 taken 5133 times.
6066 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
5906
2/2
✓ Branch 0 taken 5400 times.
✓ Branch 1 taken 666 times.
6066 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
5907
5908 6066 mov_update_dts_shift(sc, ctts_duration, c->fc);
5909
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6066 times.
6066 if (pts != AV_NOPTS_VALUE) {
5910 dts = pts - sc->dts_shift;
5911 if (flags & MOV_TRUN_SAMPLE_CTS) {
5912 dts -= ctts_duration;
5913 } else {
5914 dts -= sc->time_offset;
5915 }
5916 av_log(c->fc, AV_LOG_DEBUG,
5917 "pts %"PRId64" calculated dts %"PRId64
5918 " sc->dts_shift %d ctts.duration %d"
5919 " sc->time_offset %"PRId64
5920 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
5921 pts, dts,
5922 sc->dts_shift, ctts_duration,
5923 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
5924 pts = AV_NOPTS_VALUE;
5925 }
5926
5927 6066 keyframe =
5928 6066 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
5929 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
5930
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 5666 times.
6066 if (keyframe) {
5931 400 distance = 0;
5932 400 index_entry_flags |= AVINDEX_KEYFRAME;
5933 }
5934 // Fragments can overlap in time. Discard overlapping frames after
5935 // decoding.
5936
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6042 times.
6066 if (prev_dts >= dts)
5937 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
5938
5939 6066 sti->index_entries[index_entry_pos].pos = offset;
5940 6066 sti->index_entries[index_entry_pos].timestamp = dts;
5941 6066 sti->index_entries[index_entry_pos].size = sample_size;
5942 6066 sti->index_entries[index_entry_pos].min_distance = distance;
5943 6066 sti->index_entries[index_entry_pos].flags = index_entry_flags;
5944
5945 6066 sc->tts_data[index_entry_pos].count = 1;
5946 6066 sc->tts_data[index_entry_pos].offset = ctts_duration;
5947 6066 sc->tts_data[index_entry_pos].duration = sample_duration;
5948 6066 index_entry_pos++;
5949
5950 6066 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
5951 "size %u, distance %d, keyframe %d\n", st->index,
5952 index_entry_pos, offset, dts, sample_size, distance, keyframe);
5953 6066 distance++;
5954
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6066 times.
6066 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
5955 return AVERROR_INVALIDDATA;
5956
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6066 times.
6066 if (!sample_size)
5957 return AVERROR_INVALIDDATA;
5958 6066 dts += sample_duration;
5959 6066 offset += sample_size;
5960 6066 sc->data_size += sample_size;
5961
5962
1/2
✓ Branch 0 taken 6066 times.
✗ Branch 1 not taken.
6066 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
5963
1/2
✓ Branch 0 taken 6066 times.
✗ Branch 1 not taken.
6066 1 <= INT_MAX - sc->nb_frames_for_fps
5964 ) {
5965 6066 sc->duration_for_fps += sample_duration;
5966 6066 sc->nb_frames_for_fps ++;
5967 }
5968 }
5969
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (frag_stream_info)
5970 388 frag_stream_info->next_trun_dts = dts + sc->time_offset;
5971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (i < entries) {
5972 // EOF found before reading all entries. Fix the hole this would
5973 // leave in index_entries and tts_data
5974 int gap = entries - i;
5975 memmove(sti->index_entries + index_entry_pos,
5976 sti->index_entries + index_entry_pos + gap,
5977 sizeof(*sti->index_entries) *
5978 (sti->nb_index_entries - (index_entry_pos + gap)));
5979 memmove(sc->tts_data + index_entry_pos,
5980 sc->tts_data + index_entry_pos + gap,
5981 sizeof(*sc->tts_data) *
5982 (sc->tts_count - (index_entry_pos + gap)));
5983
5984 sti->nb_index_entries -= gap;
5985 sc->tts_count -= gap;
5986 if (index_entry_pos < sc->current_sample) {
5987 sc->current_sample -= gap;
5988 }
5989 entries = i;
5990 }
5991
5992 // The end of this new fragment may overlap in time with the start
5993 // of the next fragment in index_entries. Mark the samples in the next
5994 // fragment that overlap with AVINDEX_DISCARD_FRAME
5995 388 prev_dts = AV_NOPTS_VALUE;
5996
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 if (index_entry_pos > 0)
5997 388 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
5998
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
5999 if (prev_dts < sti->index_entries[i].timestamp)
6000 break;
6001 sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6002 }
6003
6004 // If a hole was created to insert the new index_entries into,
6005 // the index_entry recorded for all subsequent moof must
6006 // be incremented by the number of entries inserted.
6007 388 fix_frag_index_entries(&c->frag_index, next_frag_index,
6008 388 frag->track_id, entries);
6009
6010
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 388 times.
388 if (pb->eof_reached) {
6011 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6012 return AVERROR_EOF;
6013 }
6014
6015 388 frag->implicit_offset = offset;
6016
6017 388 sc->track_end = dts + sc->time_offset;
6018
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 379 times.
388 if (st->duration < sc->track_end)
6019 9 st->duration = sc->track_end;
6020
6021 388 return 0;
6022 }
6023
6024 43 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6025 {
6026 43 int64_t stream_size = avio_size(pb);
6027 43 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6028 uint8_t version, is_complete;
6029 int64_t offadd;
6030 unsigned i, j, track_id, item_count;
6031 43 AVStream *st = NULL;
6032 43 AVStream *ref_st = NULL;
6033 43 MOVStreamContext *sc, *ref_sc = NULL;
6034 AVRational timescale;
6035
6036 43 version = avio_r8(pb);
6037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (version > 1) {
6038 avpriv_request_sample(c->fc, "sidx version %u", version);
6039 return 0;
6040 }
6041
6042 43 avio_rb24(pb); // flags
6043
6044 43 track_id = avio_rb32(pb); // Reference ID
6045
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 for (i = 0; i < c->fc->nb_streams; i++) {
6046 43 sc = c->fc->streams[i]->priv_data;
6047
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (sc->id == track_id) {
6048 43 st = c->fc->streams[i];
6049 43 break;
6050 }
6051 }
6052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st) {
6053 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6054 return 0;
6055 }
6056
6057 43 sc = st->priv_data;
6058
6059 43 timescale = av_make_q(1, avio_rb32(pb));
6060
6061
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (timescale.den <= 0) {
6062 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6063 return AVERROR_INVALIDDATA;
6064 }
6065
6066
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (version == 0) {
6067 43 pts = avio_rb32(pb);
6068 43 offadd= avio_rb32(pb);
6069 } else {
6070 pts = avio_rb64(pb);
6071 offadd= avio_rb64(pb);
6072 }
6073
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6074 return AVERROR_INVALIDDATA;
6075
6076 43 offset += (uint64_t)offadd;
6077
6078 43 avio_rb16(pb); // reserved
6079
6080 43 item_count = avio_rb16(pb);
6081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (item_count == 0)
6082 return AVERROR_INVALIDDATA;
6083
6084
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 43 times.
411 for (i = 0; i < item_count; i++) {
6085 int index;
6086 MOVFragmentStreamInfo * frag_stream_info;
6087 368 uint32_t size = avio_rb32(pb);
6088 368 uint32_t duration = avio_rb32(pb);
6089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 368 times.
368 if (size & 0x80000000) {
6090 avpriv_request_sample(c->fc, "sidx reference_type 1");
6091 return AVERROR_PATCHWELCOME;
6092 }
6093 368 avio_rb32(pb); // sap_flags
6094 368 timestamp = av_rescale_q(pts, timescale, st->time_base);
6095
6096 368 index = update_frag_index(c, offset);
6097 368 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6098
1/2
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
368 if (frag_stream_info)
6099 368 frag_stream_info->sidx_pts = timestamp;
6100
6101
1/2
✓ Branch 1 taken 368 times.
✗ Branch 2 not taken.
368 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6102
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 368 times.
368 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6103 )
6104 return AVERROR_INVALIDDATA;
6105 368 offset += size;
6106 368 pts += duration;
6107 }
6108
6109 43 st->duration = sc->track_end = pts;
6110
6111 43 sc->has_sidx = 1;
6112
6113 // See if the remaining bytes are just an mfra which we can ignore.
6114 43 is_complete = offset == stream_size;
6115
4/6
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
43 if (!is_complete && (pb->seekable & AVIO_SEEKABLE_NORMAL) && stream_size > 0 ) {
6116 int64_t ret;
6117 38 int64_t original_pos = avio_tell(pb);
6118
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
38 if (!c->have_read_mfra_size) {
6119
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6120 return ret;
6121 3 c->mfra_size = avio_rb32(pb);
6122 3 c->have_read_mfra_size = 1;
6123
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6124 return ret;
6125 }
6126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (offset == stream_size - c->mfra_size)
6127 is_complete = 1;
6128 }
6129
6130
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 38 times.
43 if (is_complete) {
6131 // Find first entry in fragment index that came from an sidx.
6132 // This will pretty much always be the first entry.
6133
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 5 times.
373 for (i = 0; i < c->frag_index.nb_items; i++) {
6134 368 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6135
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 363 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
368 for (j = 0; ref_st == NULL && j < item->nb_stream_info; j++) {
6136 MOVFragmentStreamInfo * si;
6137 5 si = &item->stream_info[j];
6138
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (si->sidx_pts != AV_NOPTS_VALUE) {
6139 5 ref_st = c->fc->streams[j];
6140 5 ref_sc = ref_st->priv_data;
6141 5 break;
6142 }
6143 }
6144 }
6145
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 5 times.
10 if (ref_st) for (i = 0; i < c->fc->nb_streams; i++) {
6146 5 st = c->fc->streams[i];
6147 5 sc = st->priv_data;
6148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->has_sidx) {
6149 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6150 }
6151 }
6152
6153 5 c->frag_index.complete = 1;
6154 }
6155
6156 43 return 0;
6157 }
6158
6159 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6160 /* like the files created with Adobe Premiere 5.0, for samples see */
6161 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6162 267 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6163 {
6164 int err;
6165
6166
1/2
✓ Branch 0 taken 267 times.
✗ Branch 1 not taken.
267 if (atom.size < 8)
6167 267 return 0; /* continue */
6168 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6169 avio_skip(pb, atom.size - 4);
6170 return 0;
6171 }
6172 atom.type = avio_rl32(pb);
6173 atom.size -= 8;
6174 if (atom.type != MKTAG('m','d','a','t')) {
6175 avio_skip(pb, atom.size);
6176 return 0;
6177 }
6178 err = mov_read_mdat(c, pb, atom);
6179 return err;
6180 }
6181
6182 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6183 {
6184 #if CONFIG_ZLIB
6185 FFIOContext ctx;
6186 uint8_t *cmov_data;
6187 uint8_t *moov_data; /* uncompressed data */
6188 long cmov_len, moov_len;
6189 3 int ret = -1;
6190
6191 3 avio_rb32(pb); /* dcom atom */
6192
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6193 return AVERROR_INVALIDDATA;
6194
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6195 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6196 return AVERROR_INVALIDDATA;
6197 }
6198 3 avio_rb32(pb); /* cmvd atom */
6199
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6200 return AVERROR_INVALIDDATA;
6201 3 moov_len = avio_rb32(pb); /* uncompressed size */
6202 3 cmov_len = atom.size - 6 * 4;
6203
6204 3 cmov_data = av_malloc(cmov_len);
6205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6206 return AVERROR(ENOMEM);
6207 3 moov_data = av_malloc(moov_len);
6208
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6209 av_free(cmov_data);
6210 return AVERROR(ENOMEM);
6211 }
6212 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6214 goto free_and_return;
6215
6216 3 ret = AVERROR_INVALIDDATA;
6217
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)
6218 goto free_and_return;
6219 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6220 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6221 3 atom.type = MKTAG('m','o','o','v');
6222 3 atom.size = moov_len;
6223 3 ret = mov_read_default(c, &ctx.pub, atom);
6224 3 free_and_return:
6225 3 av_free(moov_data);
6226 3 av_free(cmov_data);
6227 3 return ret;
6228 #else
6229 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6230 return AVERROR(ENOSYS);
6231 #endif
6232 }
6233
6234 /* edit list atom */
6235 439 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6236 {
6237 MOVStreamContext *sc;
6238 int i, edit_count, version;
6239 int64_t elst_entry_size;
6240
6241
2/4
✓ Branch 0 taken 439 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 439 times.
439 if (c->fc->nb_streams < 1 || c->ignore_editlist)
6242 return 0;
6243 439 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6244
6245 439 version = avio_r8(pb); /* version */
6246 439 avio_rb24(pb); /* flags */
6247 439 edit_count = avio_rb32(pb); /* entries */
6248 439 atom.size -= 8;
6249
6250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
439 elst_entry_size = version == 1 ? 20 : 12;
6251
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 438 times.
439 if (atom.size != edit_count * elst_entry_size) {
6252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6253 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6254 edit_count, atom.size + 8);
6255 return AVERROR_INVALIDDATA;
6256 } else {
6257 1 edit_count = atom.size / elst_entry_size;
6258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6259 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6260 }
6261 }
6262 }
6263
6264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
439 if (!edit_count)
6265 return 0;
6266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
439 if (sc->elst_data)
6267 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6268 439 av_free(sc->elst_data);
6269 439 sc->elst_count = 0;
6270 439 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
439 if (!sc->elst_data)
6272 return AVERROR(ENOMEM);
6273
6274 439 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6275
4/6
✓ Branch 0 taken 466 times.
✓ Branch 1 taken 439 times.
✓ Branch 2 taken 466 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 466 times.
✗ Branch 5 not taken.
905 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
6276 466 MOVElst *e = &sc->elst_data[i];
6277
6278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 466 times.
466 if (version == 1) {
6279 e->duration = avio_rb64(pb);
6280 e->time = avio_rb64(pb);
6281 atom.size -= 16;
6282 } else {
6283 466 e->duration = avio_rb32(pb); /* segment duration */
6284 466 e->time = (int32_t)avio_rb32(pb); /* media time */
6285 466 atom.size -= 8;
6286 }
6287 466 e->rate = avio_rb32(pb) / 65536.0;
6288 466 atom.size -= 4;
6289 466 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6290 466 e->duration, e->time, e->rate);
6291
6292
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 462 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
466 if (e->time < 0 && e->time != -1 &&
6293 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6294 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6295 c->fc->nb_streams-1, i, e->time);
6296 return AVERROR_INVALIDDATA;
6297 }
6298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 466 times.
466 if (e->duration < 0) {
6299 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list duration=%"PRId64"\n",
6300 c->fc->nb_streams-1, i, e->duration);
6301 return AVERROR_INVALIDDATA;
6302 }
6303 }
6304 439 sc->elst_count = i;
6305
6306 439 return 0;
6307 }
6308
6309 18 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6310 {
6311 MOVStreamContext *sc;
6312
6313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->fc->nb_streams < 1)
6314 return AVERROR_INVALIDDATA;
6315 18 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6316 18 sc->timecode_track = avio_rb32(pb);
6317 18 return 0;
6318 }
6319
6320 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6321 {
6322 AVStream *st;
6323 int version, color_range, color_primaries, color_trc, color_space;
6324
6325 if (c->fc->nb_streams < 1)
6326 return 0;
6327 st = c->fc->streams[c->fc->nb_streams - 1];
6328
6329 if (atom.size < 5) {
6330 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6331 return AVERROR_INVALIDDATA;
6332 }
6333
6334 version = avio_r8(pb);
6335 if (version != 1) {
6336 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6337 return 0;
6338 }
6339 avio_skip(pb, 3); /* flags */
6340
6341 avio_skip(pb, 2); /* profile + level */
6342 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6343 color_primaries = avio_r8(pb);
6344 color_trc = avio_r8(pb);
6345 color_space = avio_r8(pb);
6346 if (avio_rb16(pb)) /* codecIntializationDataSize */
6347 return AVERROR_INVALIDDATA;
6348
6349 if (!av_color_primaries_name(color_primaries))
6350 color_primaries = AVCOL_PRI_UNSPECIFIED;
6351 if (!av_color_transfer_name(color_trc))
6352 color_trc = AVCOL_TRC_UNSPECIFIED;
6353 if (!av_color_space_name(color_space))
6354 color_space = AVCOL_SPC_UNSPECIFIED;
6355
6356 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6357 st->codecpar->color_primaries = color_primaries;
6358 st->codecpar->color_trc = color_trc;
6359 st->codecpar->color_space = color_space;
6360
6361 return 0;
6362 }
6363
6364 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6365 {
6366 MOVStreamContext *sc;
6367 int i, version;
6368
6369 if (c->fc->nb_streams < 1)
6370 return AVERROR_INVALIDDATA;
6371
6372 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6373
6374 if (atom.size < 5) {
6375 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6376 return AVERROR_INVALIDDATA;
6377 }
6378
6379 version = avio_r8(pb);
6380 if (version) {
6381 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6382 return 0;
6383 }
6384 if (sc->mastering) {
6385 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6386 return 0;
6387 }
6388
6389 avio_skip(pb, 3); /* flags */
6390
6391 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6392 if (!sc->mastering)
6393 return AVERROR(ENOMEM);
6394
6395 for (i = 0; i < 3; i++) {
6396 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6397 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6398 }
6399 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6400 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6401
6402 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6403 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6404
6405 sc->mastering->has_primaries = 1;
6406 sc->mastering->has_luminance = 1;
6407
6408 return 0;
6409 }
6410
6411 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6412 {
6413 MOVStreamContext *sc;
6414 const int mapping[3] = {1, 2, 0};
6415 const int chroma_den = 50000;
6416 const int luma_den = 10000;
6417 int i;
6418
6419 if (c->fc->nb_streams < 1)
6420 return AVERROR_INVALIDDATA;
6421
6422 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6423
6424 if (atom.size < 24) {
6425 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6426 return AVERROR_INVALIDDATA;
6427 }
6428
6429 if (sc->mastering) {
6430 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6431 return 0;
6432 }
6433
6434 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6435 if (!sc->mastering)
6436 return AVERROR(ENOMEM);
6437
6438 for (i = 0; i < 3; i++) {
6439 const int j = mapping[i];
6440 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6441 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6442 }
6443 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6444 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6445
6446 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6447 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6448
6449 sc->mastering->has_luminance = 1;
6450 sc->mastering->has_primaries = 1;
6451
6452 return 0;
6453 }
6454
6455 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6456 {
6457 MOVStreamContext *sc;
6458 int version;
6459
6460 if (c->fc->nb_streams < 1)
6461 return AVERROR_INVALIDDATA;
6462
6463 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6464
6465 if (atom.size < 5) {
6466 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
6467 return AVERROR_INVALIDDATA;
6468 }
6469
6470 version = avio_r8(pb);
6471 if (version) {
6472 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
6473 return 0;
6474 }
6475 avio_skip(pb, 3); /* flags */
6476
6477 if (sc->coll){
6478 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
6479 return 0;
6480 }
6481
6482 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6483 if (!sc->coll)
6484 return AVERROR(ENOMEM);
6485
6486 sc->coll->MaxCLL = avio_rb16(pb);
6487 sc->coll->MaxFALL = avio_rb16(pb);
6488
6489 return 0;
6490 }
6491
6492 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6493 {
6494 MOVStreamContext *sc;
6495
6496 if (c->fc->nb_streams < 1)
6497 return AVERROR_INVALIDDATA;
6498
6499 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6500
6501 if (atom.size < 4) {
6502 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
6503 return AVERROR_INVALIDDATA;
6504 }
6505
6506 if (sc->coll){
6507 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
6508 return 0;
6509 }
6510
6511 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6512 if (!sc->coll)
6513 return AVERROR(ENOMEM);
6514
6515 sc->coll->MaxCLL = avio_rb16(pb);
6516 sc->coll->MaxFALL = avio_rb16(pb);
6517
6518 return 0;
6519 }
6520
6521 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6522 {
6523 MOVStreamContext *sc;
6524 4 const int illuminance_den = 10000;
6525 4 const int ambient_den = 50000;
6526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
6527 return AVERROR_INVALIDDATA;
6528 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
6530 av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
6531 return AVERROR_INVALIDDATA;
6532 }
6533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
6534 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
6535 return 0;
6536 }
6537 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
6538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
6539 return AVERROR(ENOMEM);
6540 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
6541 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
6542 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
6543 4 return 0;
6544 }
6545
6546 1 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6547 {
6548 AVStream *st;
6549 MOVStreamContext *sc;
6550 enum AVStereo3DType type;
6551 int mode;
6552
6553
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6554 return 0;
6555
6556 1 st = c->fc->streams[c->fc->nb_streams - 1];
6557 1 sc = st->priv_data;
6558
6559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 5) {
6560 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
6561 return AVERROR_INVALIDDATA;
6562 }
6563
6564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sc->stereo3d)
6565 return AVERROR_INVALIDDATA;
6566
6567 1 avio_skip(pb, 4); /* version + flags */
6568
6569 1 mode = avio_r8(pb);
6570
1/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 switch (mode) {
6571 1 case 0:
6572 1 type = AV_STEREO3D_2D;
6573 1 break;
6574 case 1:
6575 type = AV_STEREO3D_TOPBOTTOM;
6576 break;
6577 case 2:
6578 type = AV_STEREO3D_SIDEBYSIDE;
6579 break;
6580 default:
6581 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
6582 return 0;
6583 }
6584
6585 1 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->stereo3d)
6587 return AVERROR(ENOMEM);
6588
6589 1 sc->stereo3d->type = type;
6590 1 return 0;
6591 }
6592
6593 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6594 {
6595 AVStream *st;
6596 MOVStreamContext *sc;
6597 int size, version, layout;
6598 int32_t yaw, pitch, roll;
6599 1 uint32_t l = 0, t = 0, r = 0, b = 0;
6600 1 uint32_t tag, padding = 0;
6601 enum AVSphericalProjection projection;
6602
6603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6604 return 0;
6605
6606 1 st = c->fc->streams[c->fc->nb_streams - 1];
6607 1 sc = st->priv_data;
6608
6609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
6610 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
6611 return AVERROR_INVALIDDATA;
6612 }
6613
6614 1 size = avio_rb32(pb);
6615
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)
6616 return AVERROR_INVALIDDATA;
6617
6618 1 tag = avio_rl32(pb);
6619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
6620 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
6621 return 0;
6622 }
6623 1 version = avio_r8(pb);
6624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6625 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6626 version);
6627 return 0;
6628 }
6629 1 avio_skip(pb, 3); /* flags */
6630 1 avio_skip(pb, size - 12); /* metadata_source */
6631
6632 1 size = avio_rb32(pb);
6633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6634 return AVERROR_INVALIDDATA;
6635
6636 1 tag = avio_rl32(pb);
6637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
6638 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
6639 return 0;
6640 }
6641
6642 1 size = avio_rb32(pb);
6643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6644 return AVERROR_INVALIDDATA;
6645
6646 1 tag = avio_rl32(pb);
6647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
6648 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
6649 return 0;
6650 }
6651 1 version = avio_r8(pb);
6652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6653 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6654 version);
6655 return 0;
6656 }
6657 1 avio_skip(pb, 3); /* flags */
6658
6659 /* 16.16 fixed point */
6660 1 yaw = avio_rb32(pb);
6661 1 pitch = avio_rb32(pb);
6662 1 roll = avio_rb32(pb);
6663
6664 1 size = avio_rb32(pb);
6665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
6666 return AVERROR_INVALIDDATA;
6667
6668 1 tag = avio_rl32(pb);
6669 1 version = avio_r8(pb);
6670
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
6671 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
6672 version);
6673 return 0;
6674 }
6675 1 avio_skip(pb, 3); /* flags */
6676
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
6677 case MKTAG('c','b','m','p'):
6678 layout = avio_rb32(pb);
6679 if (layout) {
6680 av_log(c->fc, AV_LOG_WARNING,
6681 "Unsupported cubemap layout %d\n", layout);
6682 return 0;
6683 }
6684 projection = AV_SPHERICAL_CUBEMAP;
6685 padding = avio_rb32(pb);
6686 break;
6687 1 case MKTAG('e','q','u','i'):
6688 1 t = avio_rb32(pb);
6689 1 b = avio_rb32(pb);
6690 1 l = avio_rb32(pb);
6691 1 r = avio_rb32(pb);
6692
6693
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) {
6694 av_log(c->fc, AV_LOG_ERROR,
6695 "Invalid bounding rectangle coordinates "
6696 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
6697 return AVERROR_INVALIDDATA;
6698 }
6699
6700
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)
6701 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
6702 else
6703 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6704 1 break;
6705 default:
6706 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
6707 return 0;
6708 }
6709
6710 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
6712 return AVERROR(ENOMEM);
6713
6714 1 sc->spherical->projection = projection;
6715
6716 1 sc->spherical->yaw = yaw;
6717 1 sc->spherical->pitch = pitch;
6718 1 sc->spherical->roll = roll;
6719
6720 1 sc->spherical->padding = padding;
6721
6722 1 sc->spherical->bound_left = l;
6723 1 sc->spherical->bound_top = t;
6724 1 sc->spherical->bound_right = r;
6725 1 sc->spherical->bound_bottom = b;
6726
6727 1 return 0;
6728 }
6729
6730 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6731 {
6732 AVStream *st;
6733 MOVStreamContext *sc;
6734 int size;
6735 uint32_t tag;
6736 enum AVSphericalProjection projection;
6737
6738
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6739 return 0;
6740
6741 3 st = c->fc->streams[c->fc->nb_streams - 1];
6742 3 sc = st->priv_data;
6743
6744
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 16) {
6745 av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
6746 return AVERROR_INVALIDDATA;
6747 }
6748
6749 3 size = avio_rb32(pb);
6750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 16) {
6751 av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
6752 return AVERROR_INVALIDDATA;
6753 }
6754
6755 3 tag = avio_rl32(pb);
6756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
6757 av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: 0x%08X\n", tag);
6758 return AVERROR_INVALIDDATA;
6759 }
6760
6761 3 avio_skip(pb, 1); // version
6762 3 avio_skip(pb, 3); // flags
6763
6764 3 tag = avio_rl32(pb);
6765
1/5
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
3 switch (tag) {
6766 3 case MKTAG('r','e','c','t'):
6767 3 projection = AV_SPHERICAL_RECTILINEAR;
6768 3 break;
6769 case MKTAG('e','q','u','i'):
6770 projection = AV_SPHERICAL_EQUIRECTANGULAR;
6771 break;
6772 case MKTAG('h','e','q','u'):
6773 projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
6774 break;
6775 case MKTAG('f','i','s','h'):
6776 projection = AV_SPHERICAL_FISHEYE;
6777 break;
6778 default:
6779 av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: 0x%08X\n", tag);
6780 return AVERROR_INVALIDDATA;
6781 }
6782
6783 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
6784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
6785 return AVERROR(ENOMEM);
6786
6787 3 sc->spherical->projection = projection;
6788
6789 3 return 0;
6790 }
6791
6792 3 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6793 {
6794 AVStream *st;
6795 MOVStreamContext *sc;
6796 3 int size, flags = 0;
6797 int64_t remaining;
6798 3 uint32_t tag, baseline = 0;
6799 3 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
6800 3 enum AVStereo3DType type = AV_STEREO3D_2D;
6801 3 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
6802 3 AVRational horizontal_disparity_adjustment = { 0, 1 };
6803
6804
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6805 return 0;
6806
6807 3 st = c->fc->streams[c->fc->nb_streams - 1];
6808 3 sc = st->priv_data;
6809
6810 3 remaining = atom.size;
6811
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 while (remaining > 0) {
6812 9 size = avio_rb32(pb);
6813
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 ) {
6814 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
6815 return AVERROR_INVALIDDATA;
6816 }
6817
6818 9 tag = avio_rl32(pb);
6819
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) {
6820 3 case MKTAG('s','t','r','i'): {
6821 int has_right, has_left;
6822 uint8_t tmp;
6823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 13) {
6824 av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
6825 return AVERROR_INVALIDDATA;
6826 }
6827 3 avio_skip(pb, 1); // version
6828 3 avio_skip(pb, 3); // flags
6829
6830 3 tmp = avio_r8(pb);
6831
6832 // eye_views_reversed
6833
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tmp & 8) {
6834 flags |= AV_STEREO3D_FLAG_INVERT;
6835 }
6836 // has_additional_views
6837 3 if (tmp & 4) {
6838 // skip...
6839 }
6840
6841 3 has_right = tmp & 2; // has_right_eye_view
6842 3 has_left = tmp & 1; // has_left_eye_view
6843
6844
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)
6845 3 view = AV_STEREO3D_VIEW_PACKED;
6846 else if (has_left)
6847 view = AV_STEREO3D_VIEW_LEFT;
6848 else if (has_right)
6849 view = AV_STEREO3D_VIEW_RIGHT;
6850
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)
6851 3 type = AV_STEREO3D_UNSPEC;
6852
6853 3 break;
6854 }
6855 case MKTAG('h','e','r','o'): {
6856 int tmp;
6857 if (size != 13) {
6858 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
6859 return AVERROR_INVALIDDATA;
6860 }
6861 avio_skip(pb, 1); // version
6862 avio_skip(pb, 3); // flags
6863
6864 tmp = avio_r8(pb);
6865 if (tmp == 0)
6866 primary_eye = AV_PRIMARY_EYE_NONE;
6867 else if (tmp == 1)
6868 primary_eye = AV_PRIMARY_EYE_LEFT;
6869 else if (tmp == 2)
6870 primary_eye = AV_PRIMARY_EYE_RIGHT;
6871 else
6872 av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
6873
6874 break;
6875 }
6876 3 case MKTAG('c','a','m','s'): {
6877 uint32_t subtag;
6878 int subsize;
6879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
6880 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
6881 return AVERROR_INVALIDDATA;
6882 }
6883
6884 3 subsize = avio_rb32(pb);
6885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
6886 av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
6887 return AVERROR_INVALIDDATA;
6888 }
6889
6890 3 subtag = avio_rl32(pb);
6891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
6892 av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got 0x%08X\n", subtag);
6893 return AVERROR_INVALIDDATA;
6894 }
6895
6896 3 avio_skip(pb, 1); // version
6897 3 avio_skip(pb, 3); // flags
6898
6899 3 baseline = avio_rb32(pb);
6900
6901 3 break;
6902 }
6903 3 case MKTAG('c','m','f','y'): {
6904 uint32_t subtag;
6905 int subsize;
6906 int32_t adjustment;
6907
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
6908 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
6909 return AVERROR_INVALIDDATA;
6910 }
6911
6912 3 subsize = avio_rb32(pb);
6913
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
6914 av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
6915 return AVERROR_INVALIDDATA;
6916 }
6917
6918 3 subtag = avio_rl32(pb);
6919
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
6920 av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got 0x%08X\n", subtag);
6921 return AVERROR_INVALIDDATA;
6922 }
6923
6924 3 avio_skip(pb, 1); // version
6925 3 avio_skip(pb, 3); // flags
6926
6927 3 adjustment = (int32_t) avio_rb32(pb);
6928
6929 3 horizontal_disparity_adjustment.num = (int) adjustment;
6930 3 horizontal_disparity_adjustment.den = 10000;
6931
6932 3 break;
6933 }
6934 default:
6935 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: 0x%08X\n", tag);
6936 avio_skip(pb, size - 8);
6937 break;
6938 }
6939 9 remaining -= size;
6940 }
6941
6942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
6943 av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
6944 return AVERROR_INVALIDDATA;
6945 }
6946
6947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (type == AV_STEREO3D_2D)
6948 return 0;
6949
6950
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->stereo3d) {
6951 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
6953 return AVERROR(ENOMEM);
6954 }
6955
6956 3 sc->stereo3d->flags = flags;
6957 3 sc->stereo3d->type = type;
6958 3 sc->stereo3d->view = view;
6959 3 sc->stereo3d->primary_eye = primary_eye;
6960 3 sc->stereo3d->baseline = baseline;
6961 3 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
6962
6963 3 return 0;
6964 }
6965
6966 3 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6967 {
6968 int size;
6969 int64_t remaining;
6970 uint32_t tag;
6971
6972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
6973 return 0;
6974
6975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8) {
6976 av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
6977 return AVERROR_INVALIDDATA;
6978 }
6979
6980 3 remaining = atom.size;
6981
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 while (remaining > 0) {
6982 6 size = avio_rb32(pb);
6983
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 ) {
6984 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
6985 return AVERROR_INVALIDDATA;
6986 }
6987
6988 6 tag = avio_rl32(pb);
6989
2/3
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 switch (tag) {
6990 3 case MKTAG('p','r','o','j'): {
6991 3 MOVAtom proj = { tag, size - 8 };
6992 3 int ret = mov_read_vexu_proj(c, pb, proj);
6993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6994 return ret;
6995 3 break;
6996 }
6997 3 case MKTAG('e','y','e','s'): {
6998 3 MOVAtom eyes = { tag, size - 8 };
6999 3 int ret = mov_read_eyes(c, pb, eyes);
7000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7001 return ret;
7002 3 break;
7003 }
7004 default:
7005 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: 0x%08X\n", tag);
7006 avio_skip(pb, size - 8);
7007 break;
7008 }
7009 6 remaining -= size;
7010 }
7011
7012
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7013 av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7014 return AVERROR_INVALIDDATA;
7015 }
7016
7017 3 return 0;
7018 }
7019
7020 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7021 {
7022 AVStream *st;
7023 MOVStreamContext *sc;
7024
7025
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7026 return 0;
7027
7028 3 st = c->fc->streams[c->fc->nb_streams - 1];
7029 3 sc = st->priv_data;
7030
7031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7032 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7033 return AVERROR_INVALIDDATA;
7034 }
7035
7036
7037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7038 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7039 if (!sc->stereo3d)
7040 return AVERROR(ENOMEM);
7041 }
7042
7043 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7044 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7045
7046 3 return 0;
7047 }
7048
7049 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7050 {
7051 int ret = 0;
7052 uint8_t *buffer = av_malloc(len + 1);
7053 const char *val;
7054
7055 if (!buffer)
7056 return AVERROR(ENOMEM);
7057 buffer[len] = '\0';
7058
7059 ret = ffio_read_size(pb, buffer, len);
7060 if (ret < 0)
7061 goto out;
7062
7063 /* Check for mandatory keys and values, try to support XML as best-effort */
7064 if (!sc->spherical &&
7065 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7066 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7067 av_stristr(val, "true") &&
7068 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7069 av_stristr(val, "true") &&
7070 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7071 av_stristr(val, "equirectangular")) {
7072 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7073 if (!sc->spherical)
7074 goto out;
7075
7076 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7077
7078 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7079 enum AVStereo3DType mode;
7080
7081 if (av_stristr(buffer, "left-right"))
7082 mode = AV_STEREO3D_SIDEBYSIDE;
7083 else if (av_stristr(buffer, "top-bottom"))
7084 mode = AV_STEREO3D_TOPBOTTOM;
7085 else
7086 mode = AV_STEREO3D_2D;
7087
7088 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7089 if (!sc->stereo3d)
7090 goto out;
7091
7092 sc->stereo3d->type = mode;
7093 }
7094
7095 /* orientation */
7096 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7097 if (val)
7098 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7099 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7100 if (val)
7101 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7102 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7103 if (val)
7104 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7105 }
7106
7107 out:
7108 av_free(buffer);
7109 return ret;
7110 }
7111
7112 15 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7113 {
7114 AVStream *st;
7115 MOVStreamContext *sc;
7116 int64_t ret;
7117 AVUUID uuid;
7118 static const AVUUID uuid_isml_manifest = {
7119 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7120 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7121 };
7122 static const AVUUID uuid_xmp = {
7123 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7124 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7125 };
7126 static const AVUUID uuid_spherical = {
7127 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7128 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7129 };
7130
7131
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 if (atom.size < AV_UUID_LEN || atom.size >= FFMIN(INT_MAX, SIZE_MAX))
7132 return AVERROR_INVALIDDATA;
7133
7134
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 14 times.
15 if (c->fc->nb_streams < 1)
7135 1 return 0;
7136 14 st = c->fc->streams[c->fc->nb_streams - 1];
7137 14 sc = st->priv_data;
7138
7139 14 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0)
7141 return ret;
7142
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7143 uint8_t *buffer, *ptr;
7144 char *endptr;
7145 size_t len = atom.size - AV_UUID_LEN;
7146
7147 if (len < 4) {
7148 return AVERROR_INVALIDDATA;
7149 }
7150 ret = avio_skip(pb, 4); // zeroes
7151 len -= 4;
7152
7153 buffer = av_mallocz(len + 1);
7154 if (!buffer) {
7155 return AVERROR(ENOMEM);
7156 }
7157 ret = ffio_read_size(pb, buffer, len);
7158 if (ret < 0) {
7159 av_free(buffer);
7160 return ret;
7161 }
7162
7163 ptr = buffer;
7164 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7165 ptr += sizeof("systemBitrate=\"") - 1;
7166 c->bitrates_count++;
7167 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7168 if (!c->bitrates) {
7169 c->bitrates_count = 0;
7170 av_free(buffer);
7171 return AVERROR(ENOMEM);
7172 }
7173 errno = 0;
7174 ret = strtol(ptr, &endptr, 10);
7175 if (ret < 0 || errno || *endptr != '"') {
7176 c->bitrates[c->bitrates_count - 1] = 0;
7177 } else {
7178 c->bitrates[c->bitrates_count - 1] = ret;
7179 }
7180 }
7181
7182 av_free(buffer);
7183
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7184 uint8_t *buffer;
7185 size_t len = atom.size - AV_UUID_LEN;
7186 if (c->export_xmp) {
7187 buffer = av_mallocz(len + 1);
7188 if (!buffer) {
7189 return AVERROR(ENOMEM);
7190 }
7191 ret = ffio_read_size(pb, buffer, len);
7192 if (ret < 0) {
7193 av_free(buffer);
7194 return ret;
7195 }
7196 buffer[len] = '\0';
7197 av_dict_set(&c->fc->metadata, "xmp",
7198 buffer, AV_DICT_DONT_STRDUP_VAL);
7199 } else {
7200 // skip all uuid atom, which makes it fast for long uuid-xmp file
7201 ret = avio_skip(pb, len);
7202 if (ret < 0)
7203 return ret;
7204 }
7205
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7206 size_t len = atom.size - AV_UUID_LEN;
7207 ret = mov_parse_uuid_spherical(sc, pb, len);
7208 if (ret < 0)
7209 return ret;
7210 if (!sc->spherical)
7211 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7212 }
7213
7214 14 return 0;
7215 }
7216
7217 188 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7218 {
7219 int ret;
7220 uint8_t content[16];
7221
7222
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 96 times.
188 if (atom.size < 8)
7223 92 return 0;
7224
7225 96 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (ret < 0)
7227 return ret;
7228
7229
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 55 times.
96 if ( !c->found_moov
7230
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 23 times.
41 && !c->found_mdat
7231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 && !memcmp(content, "Anevia\x1A\x1A", 8)
7232 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7233 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7234 }
7235
7236 96 return 0;
7237 }
7238
7239 35 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7240 {
7241 35 uint32_t format = avio_rl32(pb);
7242 MOVStreamContext *sc;
7243 enum AVCodecID id;
7244 AVStream *st;
7245
7246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (c->fc->nb_streams < 1)
7247 return 0;
7248 35 st = c->fc->streams[c->fc->nb_streams - 1];
7249 35 sc = st->priv_data;
7250
7251
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 32 times.
35 switch (sc->format)
7252 {
7253 3 case MKTAG('e','n','c','v'): // encrypted video
7254 case MKTAG('e','n','c','a'): // encrypted audio
7255 3 id = mov_codec_id(st, format);
7256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7257 st->codecpar->codec_id != id) {
7258 av_log(c->fc, AV_LOG_WARNING,
7259 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7260 (char*)&format, st->codecpar->codec_id);
7261 break;
7262 }
7263
7264 3 st->codecpar->codec_id = id;
7265 3 sc->format = format;
7266 3 break;
7267
7268 32 default:
7269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (format != sc->format) {
7270 av_log(c->fc, AV_LOG_WARNING,
7271 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7272 (char*)&format, (char*)&sc->format);
7273 }
7274 32 break;
7275 }
7276
7277 35 return 0;
7278 }
7279
7280 /**
7281 * Gets the current encryption info and associated current stream context. If
7282 * we are parsing a track fragment, this will return the specific encryption
7283 * info for this fragment; otherwise this will return the global encryption
7284 * info for the current stream.
7285 */
7286 6 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7287 {
7288 MOVFragmentStreamInfo *frag_stream_info;
7289 AVStream *st;
7290 int i;
7291
7292 6 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7293
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (frag_stream_info) {
7294
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 for (i = 0; i < c->fc->nb_streams; i++) {
7295 3 *sc = c->fc->streams[i]->priv_data;
7296
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if ((*sc)->id == frag_stream_info->id) {
7297 3 st = c->fc->streams[i];
7298 3 break;
7299 }
7300 }
7301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (i == c->fc->nb_streams)
7302 return 0;
7303 3 *sc = st->priv_data;
7304
7305
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!frag_stream_info->encryption_index) {
7306 // If this stream isn't encrypted, don't create the index.
7307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!(*sc)->cenc.default_encrypted_sample)
7308 return 0;
7309 1 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!frag_stream_info->encryption_index)
7311 return AVERROR(ENOMEM);
7312 }
7313 3 *encryption_index = frag_stream_info->encryption_index;
7314 3 return 1;
7315 } else {
7316 // No current track fragment, using stream level encryption info.
7317
7318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7319 return 0;
7320 3 st = c->fc->streams[c->fc->nb_streams - 1];
7321 3 *sc = st->priv_data;
7322
7323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!(*sc)->cenc.encryption_index) {
7324 // If this stream isn't encrypted, don't create the index.
7325 if (!(*sc)->cenc.default_encrypted_sample)
7326 return 0;
7327 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7328 if (!(*sc)->cenc.encryption_index)
7329 return AVERROR(ENOMEM);
7330 }
7331
7332 3 *encryption_index = (*sc)->cenc.encryption_index;
7333 3 return 1;
7334 }
7335 }
7336
7337 72 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7338 {
7339 int i, ret;
7340 unsigned int subsample_count;
7341 AVSubsampleEncryptionInfo *subsamples;
7342
7343
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!sc->cenc.default_encrypted_sample) {
7344 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7345 return AVERROR_INVALIDDATA;
7346 }
7347
7348
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
72 if (sc->cenc.per_sample_iv_size || use_subsamples) {
7349 72 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!*sample)
7351 return AVERROR(ENOMEM);
7352 } else
7353 *sample = NULL;
7354
7355
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (sc->cenc.per_sample_iv_size != 0) {
7356
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
72 if ((ret = ffio_read_size(pb, (*sample)->iv, sc->cenc.per_sample_iv_size)) < 0) {
7357 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
7358 av_encryption_info_free(*sample);
7359 *sample = NULL;
7360 return ret;
7361 }
7362 }
7363
7364
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (use_subsamples) {
7365 72 subsample_count = avio_rb16(pb);
7366 72 av_free((*sample)->subsamples);
7367 72 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
7368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!(*sample)->subsamples) {
7369 av_encryption_info_free(*sample);
7370 *sample = NULL;
7371 return AVERROR(ENOMEM);
7372 }
7373
7374
3/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
144 for (i = 0; i < subsample_count && !pb->eof_reached; i++) {
7375 72 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
7376 72 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
7377 }
7378
7379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (pb->eof_reached) {
7380 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
7381 av_encryption_info_free(*sample);
7382 *sample = NULL;
7383 return AVERROR_INVALIDDATA;
7384 }
7385 72 (*sample)->subsample_count = subsample_count;
7386 }
7387
7388 72 return 0;
7389 }
7390
7391 2 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7392 {
7393 AVEncryptionInfo **encrypted_samples;
7394 MOVEncryptionIndex *encryption_index;
7395 MOVStreamContext *sc;
7396 int use_subsamples, ret;
7397 2 unsigned int sample_count, i, alloc_size = 0;
7398
7399 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7401 return ret;
7402
7403
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7404 // This can happen if we have both saio/saiz and senc atoms.
7405 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
7406 1 return 0;
7407 }
7408
7409 1 avio_r8(pb); /* version */
7410 1 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
7411
7412 1 sample_count = avio_rb32(pb);
7413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7414 return AVERROR(ENOMEM);
7415
7416
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1 times.
49 for (i = 0; i < sample_count; i++) {
7417 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7418 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7419 min_samples * sizeof(*encrypted_samples));
7420
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (encrypted_samples) {
7421 48 encryption_index->encrypted_samples = encrypted_samples;
7422
7423 48 ret = mov_read_sample_encryption_info(
7424 48 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
7425 } else {
7426 ret = AVERROR(ENOMEM);
7427 }
7428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (pb->eof_reached) {
7429 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
7430 if (ret >= 0)
7431 av_encryption_info_free(encryption_index->encrypted_samples[i]);
7432 ret = AVERROR_INVALIDDATA;
7433 }
7434
7435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0) {
7436 for (; i > 0; i--)
7437 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7438 av_freep(&encryption_index->encrypted_samples);
7439 return ret;
7440 }
7441 }
7442 1 encryption_index->nb_encrypted_samples = sample_count;
7443
7444 1 return 0;
7445 }
7446
7447 1 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
7448 {
7449 AVEncryptionInfo **sample, **encrypted_samples;
7450 int64_t prev_pos;
7451 size_t sample_count, sample_info_size, i;
7452 1 int ret = 0;
7453 1 unsigned int alloc_size = 0;
7454
7455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->nb_encrypted_samples)
7456 return 0;
7457 1 sample_count = encryption_index->auxiliary_info_sample_count;
7458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count != 1) {
7459 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
7460 return AVERROR_PATCHWELCOME;
7461 }
7462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7463 return AVERROR(ENOMEM);
7464
7465 1 prev_pos = avio_tell(pb);
7466
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
7467
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 avio_seek(pb, encryption_index->auxiliary_offsets[0], SEEK_SET) != encryption_index->auxiliary_offsets[0]) {
7468 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
7469 goto finish;
7470 }
7471
7472
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
25 for (i = 0; i < sample_count && !pb->eof_reached; i++) {
7473 24 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7474 24 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7475 min_samples * sizeof(*encrypted_samples));
7476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!encrypted_samples) {
7477 ret = AVERROR(ENOMEM);
7478 goto finish;
7479 }
7480 24 encryption_index->encrypted_samples = encrypted_samples;
7481
7482 24 sample = &encryption_index->encrypted_samples[i];
7483 48 sample_info_size = encryption_index->auxiliary_info_default_size
7484 24 ? encryption_index->auxiliary_info_default_size
7485
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 : encryption_index->auxiliary_info_sizes[i];
7486
7487 24 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
7488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (ret < 0)
7489 goto finish;
7490 }
7491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7492 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
7493 ret = AVERROR_INVALIDDATA;
7494 } else {
7495 1 encryption_index->nb_encrypted_samples = sample_count;
7496 }
7497
7498 1 finish:
7499 1 avio_seek(pb, prev_pos, SEEK_SET);
7500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
7501 for (; i > 0; i--) {
7502 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7503 }
7504 av_freep(&encryption_index->encrypted_samples);
7505 }
7506 1 return ret;
7507 }
7508
7509 2 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7510 {
7511 MOVEncryptionIndex *encryption_index;
7512 MOVStreamContext *sc;
7513 int ret;
7514 unsigned int sample_count, aux_info_type, aux_info_param;
7515
7516 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7518 return ret;
7519
7520
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7521 // This can happen if we have both saio/saiz and senc atoms.
7522 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
7523 1 return 0;
7524 }
7525
7526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_sample_count) {
7527 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
7528 return AVERROR_INVALIDDATA;
7529 }
7530
7531 1 avio_r8(pb); /* version */
7532
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7533 aux_info_type = avio_rb32(pb);
7534 aux_info_param = avio_rb32(pb);
7535 if (sc->cenc.default_encrypted_sample) {
7536 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7537 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
7538 return 0;
7539 }
7540 if (aux_info_param != 0) {
7541 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
7542 return 0;
7543 }
7544 } else {
7545 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7546 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7547 aux_info_type == MKBETAG('c','e','n','s') ||
7548 aux_info_type == MKBETAG('c','b','c','1') ||
7549 aux_info_type == MKBETAG('c','b','c','s')) &&
7550 aux_info_param == 0) {
7551 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
7552 return AVERROR_INVALIDDATA;
7553 } else {
7554 return 0;
7555 }
7556 }
7557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7558 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7559 return 0;
7560 }
7561
7562 1 encryption_index->auxiliary_info_default_size = avio_r8(pb);
7563 1 sample_count = avio_rb32(pb);
7564
7565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_info_default_size == 0) {
7566 if (sample_count == 0)
7567 return AVERROR_INVALIDDATA;
7568
7569 encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
7570 if (!encryption_index->auxiliary_info_sizes)
7571 return AVERROR(ENOMEM);
7572
7573 ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
7574 if (ret != sample_count) {
7575 av_freep(&encryption_index->auxiliary_info_sizes);
7576
7577 if (ret >= 0)
7578 ret = AVERROR_INVALIDDATA;
7579 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
7580 av_err2str(ret));
7581 return ret;
7582 }
7583 }
7584 1 encryption_index->auxiliary_info_sample_count = sample_count;
7585
7586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7587 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7588 }
7589
7590 1 return 0;
7591 }
7592
7593 2 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7594 {
7595 uint64_t *auxiliary_offsets;
7596 MOVEncryptionIndex *encryption_index;
7597 MOVStreamContext *sc;
7598 int i, ret;
7599 unsigned int version, entry_count, aux_info_type, aux_info_param;
7600 2 unsigned int alloc_size = 0;
7601
7602 2 ret = get_current_encryption_info(c, &encryption_index, &sc);
7603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != 1)
7604 return ret;
7605
7606
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (encryption_index->nb_encrypted_samples) {
7607 // This can happen if we have both saio/saiz and senc atoms.
7608 1 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
7609 1 return 0;
7610 }
7611
7612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (encryption_index->auxiliary_offsets_count) {
7613 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
7614 return AVERROR_INVALIDDATA;
7615 }
7616
7617 1 version = avio_r8(pb); /* version */
7618
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb24(pb) & 0x01) { /* flags */
7619 aux_info_type = avio_rb32(pb);
7620 aux_info_param = avio_rb32(pb);
7621 if (sc->cenc.default_encrypted_sample) {
7622 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7623 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
7624 return 0;
7625 }
7626 if (aux_info_param != 0) {
7627 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
7628 return 0;
7629 }
7630 } else {
7631 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7632 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7633 aux_info_type == MKBETAG('c','e','n','s') ||
7634 aux_info_type == MKBETAG('c','b','c','1') ||
7635 aux_info_type == MKBETAG('c','b','c','s')) &&
7636 aux_info_param == 0) {
7637 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
7638 return AVERROR_INVALIDDATA;
7639 } else {
7640 return 0;
7641 }
7642 }
7643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (!sc->cenc.default_encrypted_sample) {
7644 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7645 return 0;
7646 }
7647
7648 1 entry_count = avio_rb32(pb);
7649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
7650 return AVERROR(ENOMEM);
7651
7652
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 for (i = 0; i < entry_count && !pb->eof_reached; i++) {
7653
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 unsigned int min_offsets = FFMIN(FFMAX(i + 1, 1024), entry_count);
7654 1 auxiliary_offsets = av_fast_realloc(
7655 1 encryption_index->auxiliary_offsets, &alloc_size,
7656 min_offsets * sizeof(*auxiliary_offsets));
7657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!auxiliary_offsets) {
7658 av_freep(&encryption_index->auxiliary_offsets);
7659 return AVERROR(ENOMEM);
7660 }
7661 1 encryption_index->auxiliary_offsets = auxiliary_offsets;
7662
7663
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (version == 0) {
7664 1 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
7665 } else {
7666 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
7667 }
7668
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (c->frag_index.current >= 0) {
7669 1 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
7670 }
7671 }
7672
7673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pb->eof_reached) {
7674 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
7675 av_freep(&encryption_index->auxiliary_offsets);
7676 return AVERROR_INVALIDDATA;
7677 }
7678
7679 1 encryption_index->auxiliary_offsets_count = entry_count;
7680
7681
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (encryption_index->auxiliary_info_sample_count) {
7682 1 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7683 }
7684
7685 return 0;
7686 }
7687
7688 2 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7689 {
7690 AVEncryptionInitInfo *info, *old_init_info;
7691 uint8_t **key_ids;
7692 AVStream *st;
7693 const AVPacketSideData *old_side_data;
7694 uint8_t *side_data, *extra_data;
7695 size_t side_data_size;
7696 2 int ret = 0;
7697 2 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
7698
7699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
7700 return 0;
7701 2 st = c->fc->streams[c->fc->nb_streams-1];
7702
7703 2 version = avio_r8(pb); /* version */
7704 2 avio_rb24(pb); /* flags */
7705
7706 2 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
7707 /* key_id_size */ 16, /* data_size */ 0);
7708
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info)
7709 return AVERROR(ENOMEM);
7710
7711
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
7712 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
7713 goto finish;
7714 }
7715
7716
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version > 0) {
7717 2 kid_count = avio_rb32(pb);
7718
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
7719 ret = AVERROR(ENOMEM);
7720 goto finish;
7721 }
7722
7723
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 for (unsigned int i = 0; i < kid_count && !pb->eof_reached; i++) {
7724 2 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
7725 2 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
7726 min_kid_count * sizeof(*key_ids));
7727
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!key_ids) {
7728 ret = AVERROR(ENOMEM);
7729 goto finish;
7730 }
7731 2 info->key_ids = key_ids;
7732
7733 2 info->key_ids[i] = av_mallocz(16);
7734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!info->key_ids[i]) {
7735 ret = AVERROR(ENOMEM);
7736 goto finish;
7737 }
7738 2 info->num_key_ids = i + 1;
7739
7740
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
7741 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
7742 goto finish;
7743 }
7744 }
7745
7746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
7747 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
7748 ret = AVERROR_INVALIDDATA;
7749 goto finish;
7750 }
7751 }
7752
7753 2 extra_data_size = avio_rb32(pb);
7754 2 extra_data = av_malloc(extra_data_size);
7755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!extra_data) {
7756 ret = AVERROR(ENOMEM);
7757 goto finish;
7758 }
7759 2 ret = avio_read(pb, extra_data, extra_data_size);
7760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret != extra_data_size) {
7761 av_free(extra_data);
7762
7763 if (ret >= 0)
7764 ret = AVERROR_INVALIDDATA;
7765 goto finish;
7766 }
7767
7768 2 av_freep(&info->data); // malloc(0) may still allocate something.
7769 2 info->data = extra_data;
7770 2 info->data_size = extra_data_size;
7771
7772 // If there is existing initialization data, append to the list.
7773 2 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
7774 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
7775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (old_side_data) {
7776 old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
7777 if (old_init_info) {
7778 // Append to the end of the list.
7779 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
7780 if (!cur->next) {
7781 cur->next = info;
7782 break;
7783 }
7784 }
7785 info = old_init_info;
7786 } else {
7787 // Assume existing side-data will be valid, so the only error we could get is OOM.
7788 ret = AVERROR(ENOMEM);
7789 goto finish;
7790 }
7791 }
7792
7793 2 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
7794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!side_data) {
7795 ret = AVERROR(ENOMEM);
7796 goto finish;
7797 }
7798
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
7799 2 &st->codecpar->nb_coded_side_data,
7800 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
7801 side_data, side_data_size, 0))
7802 av_free(side_data);
7803
7804 2 finish:
7805 2 av_encryption_init_info_free(info);
7806 2 return ret;
7807 }
7808
7809 3 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7810 {
7811 AVStream *st;
7812 MOVStreamContext *sc;
7813
7814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7815 return 0;
7816 3 st = c->fc->streams[c->fc->nb_streams-1];
7817 3 sc = st->priv_data;
7818
7819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7820 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
7821 return AVERROR_PATCHWELCOME;
7822 }
7823
7824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8)
7825 return AVERROR_INVALIDDATA;
7826
7827 3 avio_rb32(pb); /* version and flags */
7828
7829
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->cenc.default_encrypted_sample) {
7830 3 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7832 return AVERROR(ENOMEM);
7833 }
7834 }
7835
7836 3 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
7837 3 return 0;
7838 }
7839
7840 3 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7841 {
7842 AVStream *st;
7843 MOVStreamContext *sc;
7844 unsigned int version, pattern, is_protected, iv_size;
7845
7846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7847 return 0;
7848 3 st = c->fc->streams[c->fc->nb_streams-1];
7849 3 sc = st->priv_data;
7850
7851
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->pseudo_stream_id != 0) {
7852 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
7853 return AVERROR_PATCHWELCOME;
7854 }
7855
7856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.default_encrypted_sample) {
7857 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
7858 if (!sc->cenc.default_encrypted_sample) {
7859 return AVERROR(ENOMEM);
7860 }
7861 }
7862
7863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 20)
7864 return AVERROR_INVALIDDATA;
7865
7866 3 version = avio_r8(pb); /* version */
7867 3 avio_rb24(pb); /* flags */
7868
7869 3 avio_r8(pb); /* reserved */
7870 3 pattern = avio_r8(pb);
7871
7872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (version > 0) {
7873 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
7874 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
7875 }
7876
7877 3 is_protected = avio_r8(pb);
7878
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if (is_protected && !sc->cenc.encryption_index) {
7879 // The whole stream should be by-default encrypted.
7880 3 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
7881
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.encryption_index)
7882 return AVERROR(ENOMEM);
7883 }
7884 3 sc->cenc.per_sample_iv_size = avio_r8(pb);
7885
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
3 if (sc->cenc.per_sample_iv_size != 0 && sc->cenc.per_sample_iv_size != 8 &&
7886 sc->cenc.per_sample_iv_size != 16) {
7887 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
7888 return AVERROR_INVALIDDATA;
7889 }
7890
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_read(pb, sc->cenc.default_encrypted_sample->key_id, 16) != 16) {
7891 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
7892 return AVERROR_INVALIDDATA;
7893 }
7894
7895
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
3 if (is_protected && !sc->cenc.per_sample_iv_size) {
7896 1 iv_size = avio_r8(pb);
7897
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (iv_size != 8 && iv_size != 16) {
7898 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
7899 return AVERROR_INVALIDDATA;
7900 }
7901
7902
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_read(pb, sc->cenc.default_encrypted_sample->iv, iv_size) != iv_size) {
7903 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
7904 return AVERROR_INVALIDDATA;
7905 }
7906 }
7907
7908 3 return 0;
7909 }
7910
7911 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7912 {
7913 AVStream *st;
7914 int last, type, size, ret;
7915 uint8_t buf[4];
7916
7917 if (c->fc->nb_streams < 1)
7918 return 0;
7919 st = c->fc->streams[c->fc->nb_streams-1];
7920
7921 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
7922 return AVERROR_INVALIDDATA;
7923
7924 /* Check FlacSpecificBox version. */
7925 if (avio_r8(pb) != 0)
7926 return AVERROR_INVALIDDATA;
7927
7928 avio_rb24(pb); /* Flags */
7929
7930 if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
7931 av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
7932 return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
7933 }
7934 flac_parse_block_header(buf, &last, &type, &size);
7935
7936 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
7937 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
7938 return AVERROR_INVALIDDATA;
7939 }
7940
7941 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
7942 if (ret < 0)
7943 return ret;
7944
7945 if (!last)
7946 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
7947
7948 return 0;
7949 }
7950
7951 146 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
7952 {
7953 int i, ret;
7954 int bytes_of_protected_data;
7955
7956
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 143 times.
146 if (!sc->cenc.aes_ctr) {
7957 /* initialize the cipher */
7958 3 sc->cenc.aes_ctr = av_aes_ctr_alloc();
7959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->cenc.aes_ctr) {
7960 return AVERROR(ENOMEM);
7961 }
7962
7963 3 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
7964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
7965 return ret;
7966 }
7967 }
7968
7969 146 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
7970
7971
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!sample->subsample_count) {
7972 /* decrypt the whole packet */
7973 48 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
7974 48 return 0;
7975 }
7976
7977
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 98 times.
196 for (i = 0; i < sample->subsample_count; i++) {
7978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
7979 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
7980 return AVERROR_INVALIDDATA;
7981 }
7982
7983 /* skip the clear bytes */
7984 98 input += sample->subsamples[i].bytes_of_clear_data;
7985 98 size -= sample->subsamples[i].bytes_of_clear_data;
7986
7987 /* decrypt the encrypted bytes */
7988
7989 98 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
7990 98 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
7991
7992 98 input += bytes_of_protected_data;
7993 98 size -= bytes_of_protected_data;
7994 }
7995
7996
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (size > 0) {
7997 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
7998 return AVERROR_INVALIDDATA;
7999 }
8000
8001 98 return 0;
8002 }
8003
8004 static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8005 {
8006 int i, ret;
8007 int num_of_encrypted_blocks;
8008 uint8_t iv[16];
8009
8010 if (!sc->cenc.aes_ctx) {
8011 /* initialize the cipher */
8012 sc->cenc.aes_ctx = av_aes_alloc();
8013 if (!sc->cenc.aes_ctx) {
8014 return AVERROR(ENOMEM);
8015 }
8016
8017 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8018 if (ret < 0) {
8019 return ret;
8020 }
8021 }
8022
8023 memcpy(iv, sample->iv, 16);
8024
8025 /* whole-block full sample encryption */
8026 if (!sample->subsample_count) {
8027 /* decrypt the whole packet */
8028 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8029 return 0;
8030 }
8031
8032 for (i = 0; i < sample->subsample_count; i++) {
8033 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8034 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8035 return AVERROR_INVALIDDATA;
8036 }
8037
8038 if (sample->subsamples[i].bytes_of_protected_data % 16) {
8039 av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8040 return AVERROR_INVALIDDATA;
8041 }
8042
8043 /* skip the clear bytes */
8044 input += sample->subsamples[i].bytes_of_clear_data;
8045 size -= sample->subsamples[i].bytes_of_clear_data;
8046
8047 /* decrypt the encrypted bytes */
8048 num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8049 if (num_of_encrypted_blocks > 0) {
8050 av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8051 }
8052 input += sample->subsamples[i].bytes_of_protected_data;
8053 size -= sample->subsamples[i].bytes_of_protected_data;
8054 }
8055
8056 if (size > 0) {
8057 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8058 return AVERROR_INVALIDDATA;
8059 }
8060
8061 return 0;
8062 }
8063
8064 static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8065 {
8066 int i, ret, rem_bytes;
8067 uint8_t *data;
8068
8069 if (!sc->cenc.aes_ctr) {
8070 /* initialize the cipher */
8071 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8072 if (!sc->cenc.aes_ctr) {
8073 return AVERROR(ENOMEM);
8074 }
8075
8076 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
8077 if (ret < 0) {
8078 return ret;
8079 }
8080 }
8081
8082 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8083
8084 /* whole-block full sample encryption */
8085 if (!sample->subsample_count) {
8086 /* decrypt the whole packet */
8087 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8088 return 0;
8089 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8090 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8091 return AVERROR_INVALIDDATA;
8092 }
8093
8094 for (i = 0; i < sample->subsample_count; i++) {
8095 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8096 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8097 return AVERROR_INVALIDDATA;
8098 }
8099
8100 /* skip the clear bytes */
8101 input += sample->subsamples[i].bytes_of_clear_data;
8102 size -= sample->subsamples[i].bytes_of_clear_data;
8103
8104 /* decrypt the encrypted bytes */
8105 data = input;
8106 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8107 while (rem_bytes > 0) {
8108 if (rem_bytes < 16*sample->crypt_byte_block) {
8109 break;
8110 }
8111 av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8112 data += 16*sample->crypt_byte_block;
8113 rem_bytes -= 16*sample->crypt_byte_block;
8114 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8115 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8116 }
8117 input += sample->subsamples[i].bytes_of_protected_data;
8118 size -= sample->subsamples[i].bytes_of_protected_data;
8119 }
8120
8121 if (size > 0) {
8122 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8123 return AVERROR_INVALIDDATA;
8124 }
8125
8126 return 0;
8127 }
8128
8129 static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8130 {
8131 int i, ret, rem_bytes;
8132 uint8_t iv[16];
8133 uint8_t *data;
8134
8135 if (!sc->cenc.aes_ctx) {
8136 /* initialize the cipher */
8137 sc->cenc.aes_ctx = av_aes_alloc();
8138 if (!sc->cenc.aes_ctx) {
8139 return AVERROR(ENOMEM);
8140 }
8141
8142 ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1);
8143 if (ret < 0) {
8144 return ret;
8145 }
8146 }
8147
8148 /* whole-block full sample encryption */
8149 if (!sample->subsample_count) {
8150 /* decrypt the whole packet */
8151 memcpy(iv, sample->iv, 16);
8152 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8153 return 0;
8154 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8155 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8156 return AVERROR_INVALIDDATA;
8157 }
8158
8159 for (i = 0; i < sample->subsample_count; i++) {
8160 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
8161 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8162 return AVERROR_INVALIDDATA;
8163 }
8164
8165 /* skip the clear bytes */
8166 input += sample->subsamples[i].bytes_of_clear_data;
8167 size -= sample->subsamples[i].bytes_of_clear_data;
8168
8169 /* decrypt the encrypted bytes */
8170 memcpy(iv, sample->iv, 16);
8171 data = input;
8172 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8173 while (rem_bytes > 0) {
8174 if (rem_bytes < 16*sample->crypt_byte_block) {
8175 break;
8176 }
8177 av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8178 data += 16*sample->crypt_byte_block;
8179 rem_bytes -= 16*sample->crypt_byte_block;
8180 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8181 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8182 }
8183 input += sample->subsamples[i].bytes_of_protected_data;
8184 size -= sample->subsamples[i].bytes_of_protected_data;
8185 }
8186
8187 if (size > 0) {
8188 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8189 return AVERROR_INVALIDDATA;
8190 }
8191
8192 return 0;
8193 }
8194
8195 146 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8196 {
8197
3/6
✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 146 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 146 times.
✗ Branch 5 not taken.
146 if (sample->scheme == MKBETAG('c','e','n','c') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8198 146 return cenc_scheme_decrypt(c, sc, sample, input, size);
8199 } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8200 return cbc1_scheme_decrypt(c, sc, sample, input, size);
8201 } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8202 return cens_scheme_decrypt(c, sc, sample, input, size);
8203 } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8204 return cbcs_scheme_decrypt(c, sc, sample, input, size);
8205 } else {
8206 av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8207 return AVERROR_INVALIDDATA;
8208 }
8209 }
8210
8211 96512 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8212 {
8213 96512 int current = frag_index->current;
8214
8215
2/2
✓ Branch 0 taken 95851 times.
✓ Branch 1 taken 661 times.
96512 if (!frag_index->nb_items)
8216 95851 return NULL;
8217
8218 // Check frag_index->current is the right one for pkt. It can out of sync.
8219
2/4
✓ Branch 0 taken 661 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 661 times.
✗ Branch 3 not taken.
661 if (current >= 0 && current < frag_index->nb_items) {
8220
2/2
✓ Branch 0 taken 639 times.
✓ Branch 1 taken 22 times.
661 if (frag_index->item[current].moof_offset < pkt->pos &&
8221
2/2
✓ Branch 0 taken 413 times.
✓ Branch 1 taken 226 times.
639 (current + 1 == frag_index->nb_items ||
8222
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 25 times.
413 frag_index->item[current + 1].moof_offset > pkt->pos))
8223 614 return get_frag_stream_info(frag_index, current, id);
8224 }
8225
8226
8227
2/2
✓ Branch 0 taken 3955 times.
✓ Branch 1 taken 4 times.
3959 for (int i = 0; i < frag_index->nb_items; i++) {
8228
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 3912 times.
3955 if (frag_index->item[i].moof_offset > pkt->pos)
8229 43 break;
8230 3912 current = i;
8231 }
8232 47 frag_index->current = current;
8233 47 return get_frag_stream_info(frag_index, current, id);
8234 }
8235
8236 96512 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8237 {
8238 MOVFragmentStreamInfo *frag_stream_info;
8239 MOVEncryptionIndex *encryption_index;
8240 AVEncryptionInfo *encrypted_sample;
8241 int encrypted_index, ret;
8242
8243 96512 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8244 96512 encrypted_index = current_index;
8245 96512 encryption_index = NULL;
8246
2/2
✓ Branch 0 taken 661 times.
✓ Branch 1 taken 95851 times.
96512 if (frag_stream_info) {
8247 // Note this only supports encryption info in the first sample descriptor.
8248
2/2
✓ Branch 0 taken 637 times.
✓ Branch 1 taken 24 times.
661 if (frag_stream_info->stsd_id == 1) {
8249
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 613 times.
637 if (frag_stream_info->encryption_index) {
8250 24 encrypted_index = current_index - frag_stream_info->index_base;
8251 24 encryption_index = frag_stream_info->encryption_index;
8252 } else {
8253 613 encryption_index = sc->cenc.encryption_index;
8254 }
8255 }
8256 } else {
8257 95851 encryption_index = sc->cenc.encryption_index;
8258 }
8259
8260
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 96366 times.
96512 if (encryption_index) {
8261
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_info_sample_count &&
8262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8263 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8264 return AVERROR_INVALIDDATA;
8265 }
8266
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 122 times.
146 if (encryption_index->auxiliary_offsets_count &&
8267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 !encryption_index->nb_encrypted_samples) {
8268 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8269 return AVERROR_INVALIDDATA;
8270 }
8271
8272 146 encrypted_sample = NULL;
8273
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 98 times.
146 if (!encryption_index->nb_encrypted_samples) {
8274 // Full-sample encryption with default settings.
8275 48 encrypted_sample = sc->cenc.default_encrypted_sample;
8276
2/4
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 98 times.
✗ Branch 3 not taken.
98 } else if (encrypted_index >= 0 && encrypted_index < encryption_index->nb_encrypted_samples) {
8277 // Per-sample setting override.
8278 98 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (!encrypted_sample) {
8280 encrypted_sample = sc->cenc.default_encrypted_sample;
8281 }
8282 }
8283
8284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (!encrypted_sample) {
8285 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8286 return AVERROR_INVALIDDATA;
8287 }
8288
8289
1/2
✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
146 if (mov->decryption_key) {
8290 146 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
8291 } else {
8292 size_t size;
8293 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
8294 if (!side_data)
8295 return AVERROR(ENOMEM);
8296 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
8297 if (ret < 0)
8298 av_free(side_data);
8299 return ret;
8300 }
8301 }
8302
8303 96366 return 0;
8304 }
8305
8306 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8307 {
8308 const int OPUS_SEEK_PREROLL_MS = 80;
8309 int ret;
8310 AVStream *st;
8311 size_t size;
8312 uint16_t pre_skip;
8313
8314 if (c->fc->nb_streams < 1)
8315 return 0;
8316 st = c->fc->streams[c->fc->nb_streams-1];
8317
8318 if ((uint64_t)atom.size > (1<<30) || atom.size < 11)
8319 return AVERROR_INVALIDDATA;
8320
8321 /* Check OpusSpecificBox version. */
8322 if (avio_r8(pb) != 0) {
8323 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
8324 return AVERROR_INVALIDDATA;
8325 }
8326
8327 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
8328 size = atom.size + 8;
8329
8330 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
8331 return ret;
8332
8333 AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
8334 AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
8335 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
8336 avio_read(pb, st->codecpar->extradata + 9, size - 9);
8337
8338 /* OpusSpecificBox is stored in big-endian, but OpusHead is
8339 little-endian; aside from the preceeding magic and version they're
8340 otherwise currently identical. Data after output gain at offset 16
8341 doesn't need to be bytewapped. */
8342 pre_skip = AV_RB16A(st->codecpar->extradata + 10);
8343 AV_WL16A(st->codecpar->extradata + 10, pre_skip);
8344 AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
8345 AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
8346
8347 st->codecpar->initial_padding = pre_skip;
8348 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
8349 (AVRational){1, 1000},
8350 (AVRational){1, 48000});
8351
8352 return 0;
8353 }
8354
8355 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8356 {
8357 AVStream *st;
8358 unsigned format_info;
8359 int channel_assignment, channel_assignment1, channel_assignment2;
8360 int ratebits;
8361 uint64_t chmask;
8362
8363 if (c->fc->nb_streams < 1)
8364 return 0;
8365 st = c->fc->streams[c->fc->nb_streams-1];
8366
8367 if (atom.size < 10)
8368 return AVERROR_INVALIDDATA;
8369
8370 format_info = avio_rb32(pb);
8371
8372 ratebits = (format_info >> 28) & 0xF;
8373 channel_assignment1 = (format_info >> 15) & 0x1F;
8374 channel_assignment2 = format_info & 0x1FFF;
8375 if (channel_assignment2)
8376 channel_assignment = channel_assignment2;
8377 else
8378 channel_assignment = channel_assignment1;
8379
8380 st->codecpar->frame_size = 40 << (ratebits & 0x7);
8381 st->codecpar->sample_rate = mlp_samplerate(ratebits);
8382
8383 av_channel_layout_uninit(&st->codecpar->ch_layout);
8384 chmask = truehd_layout(channel_assignment);
8385 av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
8386
8387 return 0;
8388 }
8389
8390 4 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8391 {
8392 AVStream *st;
8393 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
8394 int ret;
8395 4 int64_t read_size = atom.size;
8396
8397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8398 return 0;
8399 4 st = c->fc->streams[c->fc->nb_streams-1];
8400
8401 // At most 24 bytes
8402 4 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
8403
8404
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
8405 return ret;
8406
8407 4 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
8408 }
8409
8410 3 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8411 {
8412 AVStream *st;
8413 uint8_t *buf;
8414 int ret, old_size, num_arrays;
8415
8416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
8417 return 0;
8418 3 st = c->fc->streams[c->fc->nb_streams-1];
8419
8420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata_size)
8421 // TODO: handle lhvC when present before hvcC
8422 return 0;
8423
8424
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (atom.size < 6 || st->codecpar->extradata_size < 23)
8425 return AVERROR_INVALIDDATA;
8426
8427 3 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
8428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!buf)
8429 return AVERROR(ENOMEM);
8430 3 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8431
8432 3 ret = ffio_read_size(pb, buf, atom.size);
8433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8434 av_free(buf);
8435 av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
8436 return 0;
8437 }
8438
8439 3 num_arrays = buf[5];
8440 3 old_size = st->codecpar->extradata_size;
8441 3 atom.size -= 8 /* account for mov_realloc_extradata offseting */
8442 + 6 /* lhvC bytes before the arrays*/;
8443
8444 3 ret = mov_realloc_extradata(st->codecpar, atom);
8445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
8446 av_free(buf);
8447 return ret;
8448 }
8449
8450 3 st->codecpar->extradata[22] += num_arrays;
8451 3 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
8452
8453 3 st->disposition |= AV_DISPOSITION_MULTILAYER;
8454
8455 3 av_free(buf);
8456 3 return 0;
8457 }
8458
8459 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8460 {
8461 4 AVFormatContext *ctx = c->fc;
8462 4 AVStream *st = NULL;
8463 AVBPrint scheme_buf, value_buf;
8464 4 int64_t scheme_str_len = 0, value_str_len = 0;
8465 4 int version, flags, ret = AVERROR_BUG;
8466 4 int64_t size = atom.size;
8467
8468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
8469 // 4 bytes for version + flags, 2x 1 byte for null
8470 return AVERROR_INVALIDDATA;
8471
8472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8473 return 0;
8474 4 st = c->fc->streams[c->fc->nb_streams-1];
8475
8476 4 version = avio_r8(pb);
8477 4 flags = avio_rb24(pb);
8478 4 size -= 4;
8479
8480
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) {
8481 av_log(ctx, AV_LOG_ERROR,
8482 "Unsupported 'kind' box with version %d, flags: %x",
8483 version, flags);
8484 return AVERROR_INVALIDDATA;
8485 }
8486
8487 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8488 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8489
8490
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,
8491 size)) < 0) {
8492 ret = scheme_str_len;
8493 goto cleanup;
8494 }
8495
8496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
8497 // we need to have another string, even if nullptr.
8498 // we check with + 1 since we expect that if size was not hit,
8499 // an additional null was read.
8500 ret = AVERROR_INVALIDDATA;
8501 goto cleanup;
8502 }
8503
8504 4 size -= scheme_str_len + 1;
8505
8506
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,
8507 size)) < 0) {
8508 ret = value_str_len;
8509 goto cleanup;
8510 }
8511
8512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
8513 // in case of no trailing null, box is not valid.
8514 ret = AVERROR_INVALIDDATA;
8515 goto cleanup;
8516 }
8517
8518 4 av_log(ctx, AV_LOG_TRACE,
8519 "%s stream %d KindBox(scheme: %s, value: %s)\n",
8520 4 av_get_media_type_string(st->codecpar->codec_type),
8521 st->index,
8522 scheme_buf.str, value_buf.str);
8523
8524
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++) {
8525 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
8526
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
8527 continue;
8528
8529
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
8530 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
8531
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
8532 16 continue;
8533
8534 4 st->disposition |= value_map.disposition;
8535 }
8536 }
8537
8538 4 ret = 0;
8539
8540 4 cleanup:
8541
8542 4 av_bprint_finalize(&scheme_buf, NULL);
8543 4 av_bprint_finalize(&value_buf, NULL);
8544
8545 4 return ret;
8546 }
8547
8548 static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8549 {
8550 AVStream *st;
8551 AVChannelLayout ch_layout = { 0 };
8552 int ret, i, version, type;
8553 int ambisonic_order, channel_order, normalization, channel_count;
8554 int ambi_channels, non_diegetic_channels;
8555
8556 if (c->fc->nb_streams < 1)
8557 return 0;
8558
8559 st = c->fc->streams[c->fc->nb_streams - 1];
8560
8561 if (atom.size < 16) {
8562 av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
8563 return AVERROR_INVALIDDATA;
8564 }
8565
8566 version = avio_r8(pb);
8567 if (version) {
8568 av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
8569 return 0;
8570 }
8571
8572 type = avio_r8(pb);
8573 if (type & 0x7f) {
8574 av_log(c->fc, AV_LOG_WARNING,
8575 "Unsupported ambisonic type %d\n", type & 0x7f);
8576 return 0;
8577 }
8578 non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
8579
8580 ambisonic_order = avio_rb32(pb);
8581
8582 channel_order = avio_r8(pb);
8583 if (channel_order) {
8584 av_log(c->fc, AV_LOG_WARNING,
8585 "Unsupported channel_order %d\n", channel_order);
8586 return 0;
8587 }
8588
8589 normalization = avio_r8(pb);
8590 if (normalization) {
8591 av_log(c->fc, AV_LOG_WARNING,
8592 "Unsupported normalization %d\n", normalization);
8593 return 0;
8594 }
8595
8596 channel_count = avio_rb32(pb);
8597 if (ambisonic_order < 0 || ambisonic_order > 31 ||
8598 channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
8599 non_diegetic_channels)) {
8600 av_log(c->fc, AV_LOG_ERROR,
8601 "Invalid number of channels (%d / %d)\n",
8602 channel_count, ambisonic_order);
8603 return 0;
8604 }
8605 ambi_channels = channel_count - non_diegetic_channels;
8606
8607 ret = av_channel_layout_custom_init(&ch_layout, channel_count);
8608 if (ret < 0)
8609 return 0;
8610
8611 for (i = 0; i < channel_count; i++) {
8612 unsigned channel = avio_rb32(pb);
8613
8614 if (channel >= channel_count) {
8615 av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
8616 channel, ambisonic_order);
8617 av_channel_layout_uninit(&ch_layout);
8618 return 0;
8619 }
8620 if (channel >= ambi_channels)
8621 ch_layout.u.map[i].id = channel - ambi_channels;
8622 else
8623 ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
8624 }
8625
8626 ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
8627 if (ret < 0) {
8628 av_channel_layout_uninit(&ch_layout);
8629 return 0;
8630 }
8631
8632 av_channel_layout_uninit(&st->codecpar->ch_layout);
8633 st->codecpar->ch_layout = ch_layout;
8634
8635 return 0;
8636 }
8637
8638 static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8639 {
8640 AVStream *st;
8641 int version;
8642
8643 if (c->fc->nb_streams < 1)
8644 return 0;
8645
8646 st = c->fc->streams[c->fc->nb_streams - 1];
8647
8648 if (atom.size < 5) {
8649 av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
8650 return AVERROR_INVALIDDATA;
8651 }
8652
8653 version = avio_r8(pb);
8654 if (version) {
8655 av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
8656 return 0;
8657 }
8658
8659 st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
8660
8661 return 0;
8662 }
8663
8664 96 static int rb_size(AVIOContext *pb, int64_t *value, int size)
8665 {
8666
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 95 times.
96 if (size == 0)
8667 1 *value = 0;
8668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
95 else if (size == 1)
8669 *value = avio_r8(pb);
8670
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
95 else if (size == 2)
8671 *value = avio_rb16(pb);
8672
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 else if (size == 4)
8673 95 *value = avio_rb32(pb);
8674 else if (size == 8) {
8675 *value = avio_rb64(pb);
8676 if (*value < 0)
8677 return -1;
8678 } else
8679 return -1;
8680 96 return size;
8681 }
8682
8683 13 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8684 {
8685 13 avio_rb32(pb); // version & flags.
8686 13 c->primary_item_id = avio_rb16(pb);
8687 13 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
8688 13 return atom.size;
8689 }
8690
8691 6 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8692 {
8693 6 c->idat_offset = avio_tell(pb);
8694 6 return 0;
8695 }
8696
8697 13 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8698 {
8699 HEIFItem **heif_item;
8700 int version, offset_size, length_size, base_offset_size, index_size;
8701 int item_count, extent_count;
8702 int64_t base_offset, extent_offset, extent_length;
8703 uint8_t value;
8704
8705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (c->found_iloc) {
8706 av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
8707 return 0;
8708 }
8709
8710 13 version = avio_r8(pb);
8711 13 avio_rb24(pb); // flags.
8712
8713 13 value = avio_r8(pb);
8714 13 offset_size = (value >> 4) & 0xF;
8715 13 length_size = value & 0xF;
8716 13 value = avio_r8(pb);
8717 13 base_offset_size = (value >> 4) & 0xF;
8718
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 7 times.
13 index_size = !version ? 0 : (value & 0xF);
8719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (index_size) {
8720 avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
8721 return AVERROR_PATCHWELCOME;
8722 }
8723
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8724
8725 13 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
8726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!heif_item)
8727 return AVERROR(ENOMEM);
8728 13 c->heif_item = heif_item;
8729
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (item_count > c->nb_heif_item)
8730 13 memset(&c->heif_item[c->nb_heif_item], 0,
8731 13 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
8732 13 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
8733
8734 13 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
8735
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 13 times.
45 for (int i = 0; i < item_count; i++) {
8736 32 HEIFItem *item = c->heif_item[i];
8737
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
8738
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 12 times.
32 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
8739
8740
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if (avio_feof(pb))
8741 return AVERROR_INVALIDDATA;
8742
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (offset_type > 1) {
8743 avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
8744 return AVERROR_PATCHWELCOME;
8745 }
8746
8747 32 avio_rb16(pb); // data_reference_index.
8748
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if (rb_size(pb, &base_offset, base_offset_size) < 0)
8749 return AVERROR_INVALIDDATA;
8750 32 extent_count = avio_rb16(pb);
8751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (extent_count > 1) {
8752 // For still AVIF images, we only support one extent item.
8753 avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
8754 return AVERROR_PATCHWELCOME;
8755 }
8756
8757
2/4
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
64 if (rb_size(pb, &extent_offset, offset_size) < 0 ||
8758 32 rb_size(pb, &extent_length, length_size) < 0 ||
8759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 base_offset > INT64_MAX - extent_offset)
8760 return AVERROR_INVALIDDATA;
8761
8762
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (!item)
8763 32 item = c->heif_item[i] = av_mallocz(sizeof(*item));
8764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!item)
8765 return AVERROR(ENOMEM);
8766
8767 32 item->item_id = item_id;
8768
8769
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 26 times.
32 if (offset_type == 1)
8770 6 item->is_idat_relative = 1;
8771 32 item->extent_length = extent_length;
8772 32 item->extent_offset = base_offset + extent_offset;
8773 32 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, offset_type %d, "
8774 "extent_offset %"PRId64", extent_length %"PRId64"\n",
8775 i, offset_type, item->extent_offset, item->extent_length);
8776 }
8777
8778 13 c->found_iloc = 1;
8779 13 return atom.size;
8780 }
8781
8782 32 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom, int idx)
8783 {
8784 HEIFItem *item;
8785 AVBPrint item_name;
8786 32 int64_t size = atom.size;
8787 uint32_t item_type;
8788 int item_id;
8789 int version, ret;
8790
8791 32 version = avio_r8(pb);
8792 32 avio_rb24(pb); // flags.
8793 32 size -= 4;
8794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (size < 0)
8795 return AVERROR_INVALIDDATA;
8796
8797
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (version < 2) {
8798 avpriv_report_missing_feature(c->fc, "infe version < 2");
8799 avio_skip(pb, size);
8800 return 1;
8801 }
8802
8803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
8804 32 avio_rb16(pb); // item_protection_index
8805 32 item_type = avio_rl32(pb);
8806 32 size -= 8;
8807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (size < 1)
8808 return AVERROR_INVALIDDATA;
8809
8810 32 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
8811 32 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
8812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (ret < 0) {
8813 av_bprint_finalize(&item_name, NULL);
8814 return ret;
8815 }
8816
8817 32 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
8818 32 item_id, av_fourcc2str(item_type), item_name.str);
8819
8820 32 size -= ret + 1;
8821
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (size > 0)
8822 avio_skip(pb, size);
8823
8824 32 item = c->heif_item[idx];
8825
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!item)
8826 item = c->heif_item[idx] = av_mallocz(sizeof(*item));
8827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!item)
8828 return AVERROR(ENOMEM);
8829
8830
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 1 times.
32 if (ret)
8831 31 av_bprint_finalize(&item_name, &c->heif_item[idx]->name);
8832 32 c->heif_item[idx]->item_id = item_id;
8833 32 c->heif_item[idx]->type = item_type;
8834
8835
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 7 times.
32 switch (item_type) {
8836 25 case MKTAG('a','v','0','1'):
8837 case MKTAG('h','v','c','1'):
8838 25 ret = heif_add_stream(c, c->heif_item[idx]);
8839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (ret < 0)
8840 return ret;
8841 25 break;
8842 }
8843
8844 32 return 0;
8845 }
8846
8847 13 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8848 {
8849 HEIFItem **heif_item;
8850 int entry_count;
8851 13 int version, got_stream = 0, ret, i;
8852
8853
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (c->found_iinf) {
8854 av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
8855 return 0;
8856 }
8857
8858 13 version = avio_r8(pb);
8859 13 avio_rb24(pb); // flags.
8860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
8861
8862 13 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
8863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!heif_item)
8864 return AVERROR(ENOMEM);
8865 13 c->heif_item = heif_item;
8866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (entry_count > c->nb_heif_item)
8867 memset(&c->heif_item[c->nb_heif_item], 0,
8868 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
8869 13 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
8870
8871
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 13 times.
45 for (i = 0; i < entry_count; i++) {
8872 MOVAtom infe;
8873
8874 32 infe.size = avio_rb32(pb) - 8;
8875 32 infe.type = avio_rl32(pb);
8876
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if (avio_feof(pb)) {
8877 ret = AVERROR_INVALIDDATA;
8878 goto fail;
8879 }
8880 32 ret = mov_read_infe(c, pb, infe, i);
8881
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (ret < 0)
8882 goto fail;
8883
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (!ret)
8884 32 got_stream = 1;
8885 }
8886
8887 13 c->found_iinf = got_stream;
8888 13 return 0;
8889 fail:
8890 for (; i >= 0; i--) {
8891 HEIFItem *item = c->heif_item[i];
8892
8893 if (!item)
8894 continue;
8895
8896 av_freep(&item->name);
8897 if (!item->st)
8898 continue;
8899
8900 mov_free_stream_context(c->fc, item->st);
8901 ff_remove_stream(c->fc, item->st);
8902 item->st = NULL;
8903 }
8904 return ret;
8905 }
8906
8907 6 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
8908 {
8909 6 HEIFItem *item = NULL;
8910 HEIFGrid *grid;
8911 int entries, i;
8912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8913
8914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 for (int i = 0; i < c->nb_heif_grid; i++) {
8915 if (c->heif_grid[i].item->item_id == from_item_id) {
8916 av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
8917 "referencing the same Derived Image item\n");
8918 return AVERROR_INVALIDDATA;
8919 }
8920 }
8921
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 for (int i = 0; i < c->nb_heif_item; i++) {
8922
3/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 6 times.
20 if (!c->heif_item[i] || c->heif_item[i]->item_id != from_item_id)
8923 14 continue;
8924 6 item = c->heif_item[i];
8925
8926
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 switch (item->type) {
8927 6 case MKTAG('g','r','i','d'):
8928 case MKTAG('i','o','v','l'):
8929 6 break;
8930 default:
8931 avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
8932 av_fourcc2str(item->type));
8933 return 0;
8934 }
8935 6 break;
8936 }
8937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!item) {
8938 av_log(c->fc, AV_LOG_ERROR, "Missing grid information\n");
8939 return AVERROR_INVALIDDATA;
8940 }
8941
8942 6 grid = av_realloc_array(c->heif_grid, c->nb_heif_grid + 1U,
8943 sizeof(*c->heif_grid));
8944
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!grid)
8945 return AVERROR(ENOMEM);
8946 6 c->heif_grid = grid;
8947 6 grid = &grid[c->nb_heif_grid++];
8948
8949 6 entries = avio_rb16(pb);
8950 6 grid->tile_id_list = av_malloc_array(entries, sizeof(*grid->tile_id_list));
8951 6 grid->tile_idx_list = av_calloc(entries, sizeof(*grid->tile_idx_list));
8952 6 grid->tile_item_list = av_calloc(entries, sizeof(*grid->tile_item_list));
8953
3/6
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
6 if (!grid->tile_id_list || !grid->tile_item_list || !grid->tile_idx_list)
8954 return AVERROR(ENOMEM);
8955 /* 'to' item ids */
8956
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (i = 0; i < entries; i++)
8957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 grid->tile_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
8958 6 grid->nb_tiles = entries;
8959 6 grid->item = item;
8960
8961 6 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
8962 from_item_id, entries);
8963
8964 6 return 0;
8965 }
8966
8967 3 static int mov_read_iref_thmb(MOVContext *c, AVIOContext *pb, int version)
8968 {
8969 int entries;
8970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 int to_item_id, from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8971
8972 3 entries = avio_rb16(pb);
8973
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (entries > 1) {
8974 avpriv_request_sample(c->fc, "thmb in iref referencing several items");
8975 return AVERROR_PATCHWELCOME;
8976 }
8977 /* 'to' item ids */
8978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 to_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
8979
8980
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (to_item_id != c->primary_item_id)
8981 return 0;
8982
8983 3 c->thmb_item_id = from_item_id;
8984
8985 3 av_log(c->fc, AV_LOG_TRACE, "thmb: from_item_id %d, entries %d\n",
8986 from_item_id, entries);
8987
8988 3 return 0;
8989 }
8990
8991 9 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8992 {
8993 9 int version = avio_r8(pb);
8994 9 avio_rb24(pb); // flags
8995 9 atom.size -= 4;
8996
8997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (version > 1) {
8998 av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
8999 return 0;
9000 }
9001
9002
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 while (atom.size) {
9003 9 uint32_t type, size = avio_rb32(pb);
9004 9 int64_t next = avio_tell(pb);
9005
9006
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 (size < 14 || next < 0 || next > INT64_MAX - size)
9007 return AVERROR_INVALIDDATA;
9008
9009 9 next += size - 4;
9010 9 type = avio_rl32(pb);
9011
2/3
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
9 switch (type) {
9012 6 case MKTAG('d','i','m','g'):
9013 6 mov_read_iref_dimg(c, pb, version);
9014 9 break;
9015 3 case MKTAG('t','h','m','b'):
9016 3 mov_read_iref_thmb(c, pb, version);
9017 3 break;
9018 default:
9019 av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
9020 av_fourcc2str(type), size);
9021 }
9022
9023 9 atom.size -= size;
9024 9 avio_seek(pb, next, SEEK_SET);
9025 }
9026 9 return 0;
9027 }
9028
9029 31 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9030 {
9031 HEIFItem *item;
9032 uint32_t width, height;
9033
9034 31 avio_r8(pb); /* version */
9035 31 avio_rb24(pb); /* flags */
9036 31 width = avio_rb32(pb);
9037 31 height = avio_rb32(pb);
9038
9039 31 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %u, height %u\n",
9040 c->cur_item_id, width, height);
9041
9042 31 item = heif_cur_item(c);
9043
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 if (item) {
9044 31 item->width = width;
9045 31 item->height = height;
9046 }
9047
9048 31 return 0;
9049 }
9050
9051 6 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9052 {
9053 HEIFItem *item;
9054 int angle;
9055
9056 6 angle = avio_r8(pb) & 0x3;
9057
9058 6 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
9059 c->cur_item_id, angle);
9060
9061 6 item = heif_cur_item(c);
9062
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
9063 // angle * 90 specifies the angle (in anti-clockwise direction)
9064 // in units of degrees.
9065 6 item->rotation = angle * 90;
9066 }
9067
9068 6 return 0;
9069 }
9070
9071 6 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9072 {
9073 HEIFItem *item;
9074 int axis;
9075
9076 6 axis = avio_r8(pb) & 0x1;
9077
9078 6 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
9079 c->cur_item_id, axis);
9080
9081 6 item = heif_cur_item(c);
9082
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
9083 6 item->hflip = axis;
9084 6 item->vflip = !axis;
9085 }
9086
9087 6 return 0;
9088 }
9089
9090 13 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9091 {
9092 typedef struct MOVAtoms {
9093 FFIOContext b;
9094 uint32_t type;
9095 int64_t size;
9096 uint8_t *data;
9097 } MOVAtoms;
9098 13 MOVAtoms *atoms = NULL;
9099 MOVAtom a;
9100 unsigned count;
9101 13 int nb_atoms = 0;
9102 int version, flags;
9103 int ret;
9104
9105 13 a.size = avio_rb32(pb);
9106 13 a.type = avio_rl32(pb);
9107
9108
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
13 if (a.size < 8 || a.type != MKTAG('i','p','c','o'))
9109 return AVERROR_INVALIDDATA;
9110
9111 13 a.size -= 8;
9112
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 13 times.
70 while (a.size >= 8) {
9113 57 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
9114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!ref) {
9115 ret = AVERROR(ENOMEM);
9116 goto fail;
9117 }
9118 57 ref->data = NULL;
9119 57 ref->size = avio_rb32(pb);
9120 57 ref->type = avio_rl32(pb);
9121
2/4
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
57 if (ref->size > a.size || ref->size < 8)
9122 break;
9123 57 ref->data = av_malloc(ref->size);
9124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!ref->data) {
9125 ret = AVERROR_INVALIDDATA;
9126 goto fail;
9127 }
9128 57 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
9129 57 avio_seek(pb, -8, SEEK_CUR);
9130
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (avio_read(pb, ref->data, ref->size) != ref->size) {
9131 ret = AVERROR_INVALIDDATA;
9132 goto fail;
9133 }
9134 57 ffio_init_read_context(&ref->b, ref->data, ref->size);
9135 57 a.size -= ref->size;
9136 }
9137
9138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (a.size) {
9139 ret = AVERROR_INVALIDDATA;
9140 goto fail;
9141 }
9142
9143 13 a.size = avio_rb32(pb);
9144 13 a.type = avio_rl32(pb);
9145
9146
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
13 if (a.size < 8 || a.type != MKTAG('i','p','m','a')) {
9147 ret = AVERROR_INVALIDDATA;
9148 goto fail;
9149 }
9150
9151 13 version = avio_r8(pb);
9152 13 flags = avio_rb24(pb);
9153 13 count = avio_rb32(pb);
9154
9155
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 13 times.
44 for (int i = 0; i < count; i++) {
9156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9157 31 int assoc_count = avio_r8(pb);
9158
9159
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 if (avio_feof(pb)) {
9160 ret = AVERROR_INVALIDDATA;
9161 goto fail;
9162 }
9163
9164
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 31 times.
115 for (int j = 0; j < assoc_count; j++) {
9165 MOVAtoms *ref;
9166 84 int index = avio_r8(pb) & 0x7f;
9167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (flags & 1) {
9168 index <<= 8;
9169 index |= avio_r8(pb);
9170 }
9171
2/4
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 84 times.
84 if (index > nb_atoms || index <= 0) {
9172 ret = AVERROR_INVALIDDATA;
9173 goto fail;
9174 }
9175 84 ref = &atoms[--index];
9176
9177 84 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
9178 84 index + 1, item_id, av_fourcc2str(ref->type));
9179
9180 84 c->cur_item_id = item_id;
9181
9182 84 ret = mov_read_default(c, &ref->b.pub,
9183 84 (MOVAtom) { .size = ref->size,
9184 .type = MKTAG('i','p','c','o') });
9185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (ret < 0)
9186 goto fail;
9187 84 ffio_init_read_context(&ref->b, ref->data, ref->size);
9188 }
9189 }
9190
9191 13 ret = 0;
9192 13 fail:
9193 13 c->cur_item_id = -1;
9194
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 13 times.
70 for (int i = 0; i < nb_atoms; i++)
9195 57 av_free(atoms[i].data);
9196 13 av_free(atoms);
9197
9198 13 return ret;
9199 }
9200
9201 static const MOVParseTableEntry mov_default_parse_table[] = {
9202 { MKTAG('A','C','L','R'), mov_read_aclr },
9203 { MKTAG('A','P','R','G'), mov_read_avid },
9204 { MKTAG('A','A','L','P'), mov_read_avid },
9205 { MKTAG('A','R','E','S'), mov_read_ares },
9206 { MKTAG('a','v','s','s'), mov_read_avss },
9207 { MKTAG('a','v','1','C'), mov_read_glbl },
9208 { MKTAG('c','h','p','l'), mov_read_chpl },
9209 { MKTAG('c','o','6','4'), mov_read_stco },
9210 { MKTAG('c','o','l','r'), mov_read_colr },
9211 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
9212 { MKTAG('d','i','n','f'), mov_read_default },
9213 { MKTAG('D','p','x','E'), mov_read_dpxe },
9214 { MKTAG('d','r','e','f'), mov_read_dref },
9215 { MKTAG('e','d','t','s'), mov_read_default },
9216 { MKTAG('e','l','s','t'), mov_read_elst },
9217 { MKTAG('e','n','d','a'), mov_read_enda },
9218 { MKTAG('f','i','e','l'), mov_read_fiel },
9219 { MKTAG('a','d','r','m'), mov_read_adrm },
9220 { MKTAG('f','t','y','p'), mov_read_ftyp },
9221 { MKTAG('g','l','b','l'), mov_read_glbl },
9222 { MKTAG('h','d','l','r'), mov_read_hdlr },
9223 { MKTAG('i','l','s','t'), mov_read_ilst },
9224 { MKTAG('j','p','2','h'), mov_read_jp2h },
9225 { MKTAG('m','d','a','t'), mov_read_mdat },
9226 { MKTAG('m','d','h','d'), mov_read_mdhd },
9227 { MKTAG('m','d','i','a'), mov_read_default },
9228 { MKTAG('m','e','t','a'), mov_read_meta },
9229 { MKTAG('m','i','n','f'), mov_read_default },
9230 { MKTAG('m','o','o','f'), mov_read_moof },
9231 { MKTAG('m','o','o','v'), mov_read_moov },
9232 { MKTAG('m','v','e','x'), mov_read_default },
9233 { MKTAG('m','v','h','d'), mov_read_mvhd },
9234 { MKTAG('S','M','I',' '), mov_read_svq3 },
9235 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
9236 { MKTAG('a','v','c','C'), mov_read_glbl },
9237 { MKTAG('p','a','s','p'), mov_read_pasp },
9238 { MKTAG('c','l','a','p'), mov_read_clap },
9239 { MKTAG('s','b','a','s'), mov_read_sbas },
9240 { MKTAG('s','i','d','x'), mov_read_sidx },
9241 { MKTAG('s','t','b','l'), mov_read_default },
9242 { MKTAG('s','t','c','o'), mov_read_stco },
9243 { MKTAG('s','t','p','s'), mov_read_stps },
9244 { MKTAG('s','t','r','f'), mov_read_strf },
9245 { MKTAG('s','t','s','c'), mov_read_stsc },
9246 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
9247 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
9248 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
9249 { MKTAG('s','t','t','s'), mov_read_stts },
9250 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
9251 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
9252 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
9253 { MKTAG('t','f','d','t'), mov_read_tfdt },
9254 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
9255 { MKTAG('t','r','a','k'), mov_read_trak },
9256 { MKTAG('t','r','a','f'), mov_read_default },
9257 { MKTAG('t','r','e','f'), mov_read_default },
9258 { MKTAG('t','m','c','d'), mov_read_tmcd },
9259 { MKTAG('c','h','a','p'), mov_read_chap },
9260 { MKTAG('t','r','e','x'), mov_read_trex },
9261 { MKTAG('t','r','u','n'), mov_read_trun },
9262 { MKTAG('u','d','t','a'), mov_read_default },
9263 { MKTAG('w','a','v','e'), mov_read_wave },
9264 { MKTAG('e','s','d','s'), mov_read_esds },
9265 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
9266 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
9267 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
9268 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
9269 { MKTAG('w','f','e','x'), mov_read_wfex },
9270 { MKTAG('c','m','o','v'), mov_read_cmov },
9271 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
9272 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
9273 { MKTAG('d','v','c','1'), mov_read_dvc1 },
9274 { MKTAG('s','g','p','d'), mov_read_sgpd },
9275 { MKTAG('s','b','g','p'), mov_read_sbgp },
9276 { MKTAG('h','v','c','C'), mov_read_glbl },
9277 { MKTAG('v','v','c','C'), mov_read_glbl },
9278 { MKTAG('u','u','i','d'), mov_read_uuid },
9279 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
9280 { MKTAG('f','r','e','e'), mov_read_free },
9281 { MKTAG('-','-','-','-'), mov_read_custom },
9282 { MKTAG('s','i','n','f'), mov_read_default },
9283 { MKTAG('f','r','m','a'), mov_read_frma },
9284 { MKTAG('s','e','n','c'), mov_read_senc },
9285 { MKTAG('s','a','i','z'), mov_read_saiz },
9286 { MKTAG('s','a','i','o'), mov_read_saio },
9287 { MKTAG('p','s','s','h'), mov_read_pssh },
9288 { MKTAG('s','c','h','m'), mov_read_schm },
9289 { MKTAG('s','c','h','i'), mov_read_default },
9290 { MKTAG('t','e','n','c'), mov_read_tenc },
9291 { MKTAG('d','f','L','a'), mov_read_dfla },
9292 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
9293 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
9294 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
9295 { MKTAG('h','f','o','v'), mov_read_hfov },
9296 { MKTAG('d','O','p','s'), mov_read_dops },
9297 { MKTAG('d','m','l','p'), mov_read_dmlp },
9298 { MKTAG('S','m','D','m'), mov_read_smdm },
9299 { MKTAG('C','o','L','L'), mov_read_coll },
9300 { MKTAG('v','p','c','C'), mov_read_vpcc },
9301 { MKTAG('m','d','c','v'), mov_read_mdcv },
9302 { MKTAG('c','l','l','i'), mov_read_clli },
9303 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
9304 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
9305 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
9306 { MKTAG('k','i','n','d'), mov_read_kind },
9307 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
9308 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
9309 { MKTAG('i','l','o','c'), mov_read_iloc },
9310 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
9311 { MKTAG('p','i','t','m'), mov_read_pitm },
9312 { MKTAG('e','v','c','C'), mov_read_glbl },
9313 { MKTAG('i','d','a','t'), mov_read_idat },
9314 { MKTAG('i','m','i','r'), mov_read_imir },
9315 { MKTAG('i','r','e','f'), mov_read_iref },
9316 { MKTAG('i','s','p','e'), mov_read_ispe },
9317 { MKTAG('i','r','o','t'), mov_read_irot },
9318 { MKTAG('i','p','r','p'), mov_read_iprp },
9319 { MKTAG('i','i','n','f'), mov_read_iinf },
9320 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
9321 { MKTAG('l','h','v','C'), mov_read_lhvc },
9322 { MKTAG('l','v','c','C'), mov_read_glbl },
9323 #if CONFIG_IAMFDEC
9324 { MKTAG('i','a','c','b'), mov_read_iacb },
9325 #endif
9326 { 0, NULL }
9327 };
9328
9329 6334 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9330 {
9331 6334 int64_t total_size = 0;
9332 MOVAtom a;
9333 int i;
9334
9335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6334 times.
6334 if (c->atom_depth > 10) {
9336 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
9337 return AVERROR_INVALIDDATA;
9338 }
9339 6334 c->atom_depth ++;
9340
9341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6334 times.
6334 if (atom.size < 0)
9342 atom.size = INT64_MAX;
9343
2/2
✓ Branch 0 taken 18144 times.
✓ Branch 1 taken 5853 times.
23997 while (total_size <= atom.size - 8) {
9344 18144 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
9345 18144 a.size = avio_rb32(pb);
9346 18144 a.type = avio_rl32(pb);
9347
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 18140 times.
18144 if (avio_feof(pb))
9348 4 break;
9349
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 17952 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
18140 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
9350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18140 times.
18140 a.type == MKTAG('h','o','o','v')) &&
9351 a.size >= 8 &&
9352 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
9353 uint32_t type;
9354 avio_skip(pb, 4);
9355 type = avio_rl32(pb);
9356 if (avio_feof(pb))
9357 break;
9358 avio_seek(pb, -8, SEEK_CUR);
9359 if (type == MKTAG('m','v','h','d') ||
9360 type == MKTAG('c','m','o','v')) {
9361 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
9362 a.type = MKTAG('m','o','o','v');
9363 }
9364 }
9365
2/2
✓ Branch 0 taken 15447 times.
✓ Branch 1 taken 2693 times.
18140 if (atom.type != MKTAG('r','o','o','t') &&
9366
2/2
✓ Branch 0 taken 14047 times.
✓ Branch 1 taken 1400 times.
15447 atom.type != MKTAG('m','o','o','v')) {
9367
1/2
✓ Branch 0 taken 14047 times.
✗ Branch 1 not taken.
14047 if (a.type == MKTAG('t','r','a','k') ||
9368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14047 times.
14047 a.type == MKTAG('m','d','a','t')) {
9369 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
9370 avio_skip(pb, -8);
9371 c->atom_depth --;
9372 477 return 0;
9373 }
9374 }
9375 18140 total_size += 8;
9376
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 18116 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
18140 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
9377 24 a.size = avio_rb64(pb) - 8;
9378 24 total_size += 8;
9379 }
9380 18140 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
9381 18140 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
9382
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 18135 times.
18140 if (a.size == 0) {
9383 5 a.size = atom.size - total_size + 8;
9384 }
9385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18140 times.
18140 if (a.size < 0)
9386 break;
9387 18140 a.size -= 8;
9388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18140 times.
18140 if (a.size < 0)
9389 break;
9390 18140 a.size = FFMIN(a.size, atom.size - total_size);
9391
9392
2/2
✓ Branch 0 taken 826362 times.
✓ Branch 1 taken 1843 times.
828205 for (i = 0; mov_default_parse_table[i].type; i++)
9393
2/2
✓ Branch 0 taken 16297 times.
✓ Branch 1 taken 810065 times.
826362 if (mov_default_parse_table[i].type == a.type) {
9394 16297 parse = mov_default_parse_table[i].parse;
9395 16297 break;
9396 }
9397
9398 // container is user data
9399
4/4
✓ Branch 0 taken 1843 times.
✓ Branch 1 taken 16297 times.
✓ Branch 2 taken 1669 times.
✓ Branch 3 taken 174 times.
18140 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
9400
2/2
✓ Branch 0 taken 298 times.
✓ Branch 1 taken 1371 times.
1669 atom.type == MKTAG('i','l','s','t')))
9401 472 parse = mov_read_udta_string;
9402
9403 // Supports parsing the QuickTime Metadata Keys.
9404 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
9405
4/4
✓ Branch 0 taken 1371 times.
✓ Branch 1 taken 16769 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 1360 times.
18140 if (!parse && c->found_hdlr_mdta &&
9406
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 atom.type == MKTAG('m','e','t','a') &&
9407
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 a.type == MKTAG('k','e','y','s') &&
9408
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 c->meta_keys_count == 0) {
9409 11 parse = mov_read_keys;
9410 }
9411
9412
2/2
✓ Branch 0 taken 1360 times.
✓ Branch 1 taken 16780 times.
18140 if (!parse) { /* skip leaf atoms data */
9413 1360 avio_skip(pb, a.size);
9414 } else {
9415 16780 int64_t start_pos = avio_tell(pb);
9416 int64_t left;
9417 16780 int err = parse(c, pb, a);
9418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16780 times.
16780 if (err < 0) {
9419 c->atom_depth --;
9420 return err;
9421 }
9422
5/6
✓ Branch 0 taken 3079 times.
✓ Branch 1 taken 13701 times.
✓ Branch 2 taken 2781 times.
✓ Branch 3 taken 298 times.
✓ Branch 4 taken 2781 times.
✗ Branch 5 not taken.
16780 if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos &&
9423
6/8
✓ Branch 0 taken 2781 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2781 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2773 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 469 times.
✓ Branch 7 taken 2304 times.
5554 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
9424 2773 start_pos + a.size == avio_size(pb))) {
9425
4/6
✓ Branch 0 taken 477 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 477 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 469 times.
477 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
9426 8 c->next_root_atom = start_pos + a.size;
9427 477 c->atom_depth --;
9428 477 return 0;
9429 }
9430 16303 left = a.size - avio_tell(pb) + start_pos;
9431
2/2
✓ Branch 0 taken 1306 times.
✓ Branch 1 taken 14997 times.
16303 if (left > 0) /* skip garbage at atom end */
9432 1306 avio_skip(pb, left);
9433
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14995 times.
14997 else if (left < 0) {
9434 2 av_log(c->fc, AV_LOG_WARNING,
9435 "overread end of atom '%s' by %"PRId64" bytes\n",
9436 2 av_fourcc2str(a.type), -left);
9437 2 avio_seek(pb, left, SEEK_CUR);
9438 }
9439 }
9440
9441 17663 total_size += a.size;
9442 }
9443
9444
4/4
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 5751 times.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 4 times.
5857 if (total_size < atom.size && atom.size < 0x7ffff)
9445 102 avio_skip(pb, atom.size - total_size);
9446
9447 5857 c->atom_depth --;
9448 5857 return 0;
9449 }
9450
9451 7235 static int mov_probe(const AVProbeData *p)
9452 {
9453 int64_t offset;
9454 uint32_t tag;
9455 7235 int score = 0;
9456 7235 int moov_offset = -1;
9457
9458 /* check file header */
9459 7235 offset = 0;
9460 8908 for (;;) {
9461 int64_t size;
9462 16143 int minsize = 8;
9463 /* ignore invalid offset */
9464
2/2
✓ Branch 0 taken 7235 times.
✓ Branch 1 taken 8908 times.
16143 if ((offset + 8ULL) > (unsigned int)p->buf_size)
9465 7235 break;
9466 8908 size = AV_RB32(p->buf + offset);
9467
3/4
✓ Branch 0 taken 521 times.
✓ Branch 1 taken 8387 times.
✓ Branch 2 taken 521 times.
✗ Branch 3 not taken.
8908 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
9468 521 size = AV_RB64(p->buf+offset + 8);
9469 521 minsize = 16;
9470
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 8332 times.
8387 } else if (size == 0) {
9471 55 size = p->buf_size - offset;
9472 }
9473
2/2
✓ Branch 0 taken 399 times.
✓ Branch 1 taken 8509 times.
8908 if (size < minsize) {
9474 399 offset += 4;
9475 399 continue;
9476 }
9477 8509 tag = AV_RL32(p->buf + offset + 4);
9478
5/6
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 830 times.
✓ Branch 2 taken 353 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7202 times.
8509 switch(tag) {
9479 /* check for obvious tags */
9480 123 case MKTAG('m','o','o','v'):
9481 123 moov_offset = offset + 4;
9482 953 case MKTAG('m','d','a','t'):
9483 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
9484 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
9485 case MKTAG('f','t','y','p'):
9486
2/2
✓ Branch 0 taken 433 times.
✓ Branch 1 taken 520 times.
953 if (tag == MKTAG('f','t','y','p') &&
9487
1/2
✓ Branch 0 taken 433 times.
✗ Branch 1 not taken.
433 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
9488
1/2
✓ Branch 0 taken 433 times.
✗ Branch 1 not taken.
433 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
9489
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 427 times.
433 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
9490 )) {
9491 6 score = FFMAX(score, 5);
9492 } else {
9493 947 score = AVPROBE_SCORE_MAX;
9494 }
9495 953 break;
9496 /* those are more common words, so rate then a bit less */
9497 353 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
9498 case MKTAG('w','i','d','e'):
9499 case MKTAG('f','r','e','e'):
9500 case MKTAG('j','u','n','k'):
9501 case MKTAG('p','i','c','t'):
9502 353 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
9503 353 break;
9504 case MKTAG(0x82,0x82,0x7f,0x7d):
9505 score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
9506 break;
9507 1 case MKTAG('s','k','i','p'):
9508 case MKTAG('u','u','i','d'):
9509 case MKTAG('p','r','f','l'):
9510 /* if we only find those cause probedata is too small at least rate them */
9511 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
9512 1 break;
9513 }
9514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8509 times.
8509 if (size > INT64_MAX - offset)
9515 break;
9516 8509 offset += size;
9517 }
9518
4/4
✓ Branch 0 taken 464 times.
✓ Branch 1 taken 6771 times.
✓ Branch 2 taken 123 times.
✓ Branch 3 taken 341 times.
7235 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
9519 /* moov atom in the header - we should make sure that this is not a
9520 * MOV-packed MPEG-PS */
9521 123 offset = moov_offset;
9522
9523
2/2
✓ Branch 0 taken 120608 times.
✓ Branch 1 taken 123 times.
120731 while (offset < (p->buf_size - 16)) { /* Sufficient space */
9524 /* We found an actual hdlr atom */
9525
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 120476 times.
120608 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
9526
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 111 times.
132 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
9527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
9528 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
9529 /* We found a media handler reference atom describing an
9530 * MPEG-PS-in-MOV, return a
9531 * low score to force expanding the probe window until
9532 * mpegps_probe finds what it needs */
9533 return 5;
9534 } else {
9535 /* Keep looking */
9536 120608 offset += 2;
9537 }
9538 }
9539 }
9540
9541 7235 return score;
9542 }
9543
9544 // must be done after parsing all trak because there's no order requirement
9545 2 static void mov_read_chapters(AVFormatContext *s)
9546 {
9547 2 MOVContext *mov = s->priv_data;
9548 MOVStreamContext *sc;
9549 int64_t cur_pos;
9550 int i, j;
9551 int chapter_track;
9552
9553
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
9554 2 AVStream *st = NULL;
9555 2 FFStream *sti = NULL;
9556 2 chapter_track = mov->chapter_tracks[j];
9557
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
9558 4 sc = mov->fc->streams[i]->priv_data;
9559
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
9560 2 st = s->streams[i];
9561 2 break;
9562 }
9563 }
9564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
9565 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
9566 continue;
9567 }
9568 2 sti = ffstream(st);
9569
9570 2 sc = st->priv_data;
9571 2 cur_pos = avio_tell(sc->pb);
9572
9573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
9574 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
9575 if (!st->attached_pic.data && sti->nb_index_entries) {
9576 // Retrieve the first frame, if possible
9577 AVIndexEntry *sample = &sti->index_entries[0];
9578 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9579 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
9580 goto finish;
9581 }
9582
9583 if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
9584 goto finish;
9585 }
9586 } else {
9587 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
9588 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
9589 2 st->discard = AVDISCARD_ALL;
9590
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
9591 8 AVIndexEntry *sample = &sti->index_entries[i];
9592
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;
9593 uint8_t *title;
9594 uint16_t ch;
9595 int len, title_len;
9596
9597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
9598 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
9599 end = AV_NOPTS_VALUE;
9600 }
9601
9602
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
9603 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
9604 goto finish;
9605 }
9606
9607 // the first two bytes are the length of the title
9608 8 len = avio_rb16(sc->pb);
9609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
9610 continue;
9611 8 title_len = 2*len + 1;
9612
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
9613 goto finish;
9614
9615 // The samples could theoretically be in any encoding if there's an encd
9616 // atom following, but in practice are only utf-8 or utf-16, distinguished
9617 // instead by the presence of a BOM
9618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
9619 title[0] = 0;
9620 } else {
9621 8 ch = avio_rb16(sc->pb);
9622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
9623 avio_get_str16be(sc->pb, len, title, title_len);
9624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
9625 avio_get_str16le(sc->pb, len, title, title_len);
9626 else {
9627 8 AV_WB16(title, ch);
9628
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)
9629 title[len] = 0;
9630 else
9631 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
9632 }
9633 }
9634
9635 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
9636 8 av_freep(&title);
9637 }
9638 }
9639 2 finish:
9640 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
9641 }
9642 2 }
9643
9644 19 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
9645 int64_t value, int flags)
9646 {
9647 AVTimecode tc;
9648 char buf[AV_TIMECODE_STR_SIZE];
9649 19 AVRational rate = st->avg_frame_rate;
9650 19 int ret = av_timecode_init(&tc, rate, flags, 0, s);
9651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
9652 return ret;
9653 19 av_dict_set(&st->metadata, "timecode",
9654 19 av_timecode_make_string(&tc, buf, value), 0);
9655 19 return 0;
9656 }
9657
9658 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
9659 {
9660 MOVStreamContext *sc = st->priv_data;
9661 FFStream *const sti = ffstream(st);
9662 char buf[AV_TIMECODE_STR_SIZE];
9663 int64_t cur_pos = avio_tell(sc->pb);
9664 int hh, mm, ss, ff, drop;
9665
9666 if (!sti->nb_index_entries)
9667 return -1;
9668
9669 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9670 avio_skip(s->pb, 13);
9671 hh = avio_r8(s->pb);
9672 mm = avio_r8(s->pb);
9673 ss = avio_r8(s->pb);
9674 drop = avio_r8(s->pb);
9675 ff = avio_r8(s->pb);
9676 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
9677 hh, mm, ss, drop ? ';' : ':', ff);
9678 av_dict_set(&st->metadata, "timecode", buf, 0);
9679
9680 avio_seek(sc->pb, cur_pos, SEEK_SET);
9681 return 0;
9682 }
9683
9684 19 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
9685 {
9686 19 MOVStreamContext *sc = st->priv_data;
9687 19 FFStream *const sti = ffstream(st);
9688 19 int flags = 0;
9689 19 int64_t cur_pos = avio_tell(sc->pb);
9690 int64_t value;
9691 19 AVRational tc_rate = st->avg_frame_rate;
9692 19 int tmcd_nb_frames = sc->tmcd_nb_frames;
9693 int rounded_tc_rate;
9694
9695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!sti->nb_index_entries)
9696 return -1;
9697
9698
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)
9699 return -1;
9700
9701 19 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
9702 19 value = avio_rb32(s->pb);
9703
9704
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13 times.
19 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
9705
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
9706
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
9707
9708 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
9709 * not the case) and thus assume "frame number format" instead of QT one.
9710 * No sample with tmcd track can be found with a QT timecode at the moment,
9711 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
9712 * format). */
9713
9714 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
9715 * we multiply the frame number with the quotient.
9716 * See tickets #9492, #9710. */
9717 19 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
9718 /* Work around files where tmcd_nb_frames is rounded down from frame rate
9719 * instead of up. See ticket #5978. */
9720
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
9721
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
9722 10 tmcd_nb_frames = rounded_tc_rate;
9723 19 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
9724
9725 19 parse_timecode_in_framenum_format(s, st, value, flags);
9726
9727 19 avio_seek(sc->pb, cur_pos, SEEK_SET);
9728 19 return 0;
9729 }
9730
9731 1040 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
9732 int i;
9733
3/4
✓ Branch 0 taken 1040 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1036 times.
✓ Branch 3 taken 4 times.
1040 if (!index || !*index) return;
9734
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 4 times.
76 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
9735 72 av_encryption_info_free((*index)->encrypted_samples[i]);
9736 }
9737 4 av_freep(&(*index)->encrypted_samples);
9738 4 av_freep(&(*index)->auxiliary_info_sizes);
9739 4 av_freep(&(*index)->auxiliary_offsets);
9740 4 av_freep(index);
9741 }
9742
9743 673 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
9744 {
9745 673 MOVStreamContext *sc = st->priv_data;
9746
9747
3/4
✓ Branch 0 taken 673 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 633 times.
673 if (!sc || --sc->refcount) {
9748 40 st->priv_data = NULL;
9749 40 return;
9750 }
9751
9752 633 av_freep(&sc->tts_data);
9753
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 633 times.
1227 for (int i = 0; i < sc->drefs_count; i++) {
9754 594 av_freep(&sc->drefs[i].path);
9755 594 av_freep(&sc->drefs[i].dir);
9756 }
9757 633 av_freep(&sc->drefs);
9758
9759 633 sc->drefs_count = 0;
9760
9761
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 619 times.
633 if (!sc->pb_is_copied)
9762 14 ff_format_io_close(s, &sc->pb);
9763
9764 633 sc->pb = NULL;
9765 633 av_freep(&sc->chunk_offsets);
9766 633 av_freep(&sc->stsc_data);
9767 633 av_freep(&sc->sample_sizes);
9768 633 av_freep(&sc->keyframes);
9769 633 av_freep(&sc->ctts_data);
9770 633 av_freep(&sc->stts_data);
9771 633 av_freep(&sc->sdtp_data);
9772 633 av_freep(&sc->stps_data);
9773 633 av_freep(&sc->elst_data);
9774 633 av_freep(&sc->rap_group);
9775 633 av_freep(&sc->sync_group);
9776 633 av_freep(&sc->sgpd_sync);
9777 633 av_freep(&sc->sample_offsets);
9778 633 av_freep(&sc->open_key_samples);
9779 633 av_freep(&sc->display_matrix);
9780 633 av_freep(&sc->index_ranges);
9781
9782
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 39 times.
633 if (sc->extradata)
9783
2/2
✓ Branch 0 taken 605 times.
✓ Branch 1 taken 594 times.
1199 for (int i = 0; i < sc->stsd_count; i++)
9784 605 av_free(sc->extradata[i]);
9785 633 av_freep(&sc->extradata);
9786 633 av_freep(&sc->extradata_size);
9787
9788 633 mov_free_encryption_index(&sc->cenc.encryption_index);
9789 633 av_encryption_info_free(sc->cenc.default_encrypted_sample);
9790 633 av_aes_ctr_free(sc->cenc.aes_ctr);
9791
9792 633 av_freep(&sc->stereo3d);
9793 633 av_freep(&sc->spherical);
9794 633 av_freep(&sc->mastering);
9795 633 av_freep(&sc->coll);
9796 633 av_freep(&sc->ambient);
9797
9798 #if CONFIG_IAMFDEC
9799
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 623 times.
633 if (sc->iamf)
9800 10 ff_iamf_read_deinit(sc->iamf);
9801 #endif
9802 633 av_freep(&sc->iamf);
9803 }
9804
9805 494 static int mov_read_close(AVFormatContext *s)
9806 {
9807 494 MOVContext *mov = s->priv_data;
9808 int i, j;
9809
9810
2/2
✓ Branch 0 taken 673 times.
✓ Branch 1 taken 494 times.
1167 for (i = 0; i < s->nb_streams; i++) {
9811 673 AVStream *st = s->streams[i];
9812
9813 673 mov_free_stream_context(s, st);
9814 }
9815
9816 494 av_freep(&mov->dv_demux);
9817 494 avformat_free_context(mov->dv_fctx);
9818 494 mov->dv_fctx = NULL;
9819
9820
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 483 times.
494 if (mov->meta_keys) {
9821
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i < mov->meta_keys_count; i++) {
9822 58 av_freep(&mov->meta_keys[i]);
9823 }
9824 11 av_freep(&mov->meta_keys);
9825 }
9826
9827 494 av_freep(&mov->trex_data);
9828 494 av_freep(&mov->bitrates);
9829
9830
2/2
✓ Branch 0 taken 389 times.
✓ Branch 1 taken 494 times.
883 for (i = 0; i < mov->frag_index.nb_items; i++) {
9831 389 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
9832
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 389 times.
796 for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) {
9833 407 mov_free_encryption_index(&frag[j].encryption_index);
9834 }
9835 389 av_freep(&mov->frag_index.item[i].stream_info);
9836 }
9837 494 av_freep(&mov->frag_index.item);
9838
9839 494 av_freep(&mov->aes_decrypt);
9840 494 av_freep(&mov->chapter_tracks);
9841
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 494 times.
526 for (i = 0; i < mov->nb_heif_item; i++) {
9842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!mov->heif_item[i])
9843 continue;
9844 32 av_freep(&mov->heif_item[i]->name);
9845 32 av_freep(&mov->heif_item[i]->icc_profile);
9846 32 av_freep(&mov->heif_item[i]);
9847 }
9848 494 av_freep(&mov->heif_item);
9849
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 494 times.
500 for (i = 0; i < mov->nb_heif_grid; i++) {
9850 6 av_freep(&mov->heif_grid[i].tile_id_list);
9851 6 av_freep(&mov->heif_grid[i].tile_idx_list);
9852 6 av_freep(&mov->heif_grid[i].tile_item_list);
9853 }
9854 494 av_freep(&mov->heif_grid);
9855
9856 494 return 0;
9857 }
9858
9859 16 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
9860 {
9861 int i;
9862
9863
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 for (i = 0; i < s->nb_streams; i++) {
9864 24 AVStream *st = s->streams[i];
9865 24 MOVStreamContext *sc = st->priv_data;
9866
9867
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
9868
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 sc->timecode_track == tmcd_id)
9869 14 return 1;
9870 }
9871 2 return 0;
9872 }
9873
9874 /* look for a tmcd track not referenced by any video track, and export it globally */
9875 494 static void export_orphan_timecode(AVFormatContext *s)
9876 {
9877 int i;
9878
9879
2/2
✓ Branch 0 taken 670 times.
✓ Branch 1 taken 492 times.
1162 for (i = 0; i < s->nb_streams; i++) {
9880 670 AVStream *st = s->streams[i];
9881
9882
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 654 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 14 times.
686 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
9883 16 !tmcd_is_referenced(s, i + 1)) {
9884 2 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
9885
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (tcr) {
9886 2 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
9887 2 break;
9888 }
9889 }
9890 }
9891 494 }
9892
9893 static int read_tfra(MOVContext *mov, AVIOContext *f)
9894 {
9895 int version, fieldlength, i, j;
9896 int64_t pos = avio_tell(f);
9897 uint32_t size = avio_rb32(f);
9898 unsigned track_id, item_count;
9899
9900 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
9901 return 1;
9902 }
9903 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
9904
9905 version = avio_r8(f);
9906 avio_rb24(f);
9907 track_id = avio_rb32(f);
9908 fieldlength = avio_rb32(f);
9909 item_count = avio_rb32(f);
9910 for (i = 0; i < item_count; i++) {
9911 int64_t time, offset;
9912 int index;
9913 MOVFragmentStreamInfo * frag_stream_info;
9914
9915 if (avio_feof(f)) {
9916 return AVERROR_INVALIDDATA;
9917 }
9918
9919 if (version == 1) {
9920 time = avio_rb64(f);
9921 offset = avio_rb64(f);
9922 } else {
9923 time = avio_rb32(f);
9924 offset = avio_rb32(f);
9925 }
9926
9927 // The first sample of each stream in a fragment is always a random
9928 // access sample. So it's entry in the tfra can be used as the
9929 // initial PTS of the fragment.
9930 index = update_frag_index(mov, offset);
9931 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
9932 if (frag_stream_info &&
9933 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
9934 frag_stream_info->first_tfra_pts = time;
9935
9936 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
9937 avio_r8(f);
9938 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
9939 avio_r8(f);
9940 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
9941 avio_r8(f);
9942 }
9943
9944 avio_seek(f, pos + size, SEEK_SET);
9945 return 0;
9946 }
9947
9948 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
9949 {
9950 int64_t stream_size = avio_size(f);
9951 int64_t original_pos = avio_tell(f);
9952 int64_t seek_ret;
9953 int ret = -1;
9954 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
9955 ret = seek_ret;
9956 goto fail;
9957 }
9958 c->mfra_size = avio_rb32(f);
9959 c->have_read_mfra_size = 1;
9960 if (!c->mfra_size || c->mfra_size > stream_size) {
9961 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
9962 goto fail;
9963 }
9964 if ((seek_ret = avio_seek(f, -((int64_t) c->mfra_size), SEEK_CUR)) < 0) {
9965 ret = seek_ret;
9966 goto fail;
9967 }
9968 if (avio_rb32(f) != c->mfra_size) {
9969 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
9970 goto fail;
9971 }
9972 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
9973 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
9974 goto fail;
9975 }
9976 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
9977 do {
9978 ret = read_tfra(c, f);
9979 if (ret < 0)
9980 goto fail;
9981 } while (!ret);
9982 ret = 0;
9983 c->frag_index.complete = 1;
9984 fail:
9985 seek_ret = avio_seek(f, original_pos, SEEK_SET);
9986 if (seek_ret < 0) {
9987 av_log(c->fc, AV_LOG_ERROR,
9988 "failed to seek back after looking for mfra\n");
9989 ret = seek_ret;
9990 }
9991 return ret;
9992 }
9993
9994 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
9995 const HEIFItem *item)
9996 {
9997 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
9998 AV_PKT_DATA_ICC_PROFILE,
9999 item->icc_profile_size, 0);
10000 if (!sd)
10001 return AVERROR(ENOMEM);
10002
10003 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
10004
10005 return 0;
10006 }
10007
10008 6 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10009 const HEIFItem *item)
10010 {
10011 int32_t *matrix;
10012 6 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data,
10013 nb_coded_side_data,
10014 AV_PKT_DATA_DISPLAYMATRIX,
10015 9 * sizeof(*matrix), 0);
10016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sd)
10017 return AVERROR(ENOMEM);
10018
10019 6 matrix = (int32_t*)sd->data;
10020 /* rotation is in the counter-clockwise direction whereas
10021 * av_display_rotation_set() expects its argument to be
10022 * oriented clockwise, so we need to negate it. */
10023 6 av_display_rotation_set(matrix, -item->rotation);
10024 6 av_display_matrix_flip(matrix, item->hflip, item->vflip);
10025
10026 6 return 0;
10027 }
10028
10029 2 static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid,
10030 AVStreamGroupTileGrid *tile_grid)
10031 {
10032 2 MOVContext *c = s->priv_data;
10033 2 const HEIFItem *item = grid->item;
10034 2 int64_t offset = 0, pos = avio_tell(s->pb);
10035 2 int x = 0, y = 0, i = 0;
10036 int tile_rows, tile_cols;
10037 int flags, size;
10038
10039
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10040 av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
10041 return AVERROR_PATCHWELCOME;
10042 }
10043
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (item->is_idat_relative) {
10044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!c->idat_offset) {
10045 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
10046 return AVERROR_INVALIDDATA;
10047 }
10048 2 offset = c->idat_offset;
10049 }
10050
10051 2 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10052
10053 2 avio_r8(s->pb); /* version */
10054 2 flags = avio_r8(s->pb);
10055
10056 2 tile_rows = avio_r8(s->pb) + 1;
10057 2 tile_cols = avio_r8(s->pb) + 1;
10058 /* actual width and height of output image */
10059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 tile_grid->width = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
10060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 tile_grid->height = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
10061
10062 /* ICC profile */
10063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (item->icc_profile_size) {
10064 int ret = set_icc_profile_from_item(&tile_grid->coded_side_data,
10065 &tile_grid->nb_coded_side_data, item);
10066 if (ret < 0)
10067 return ret;
10068 }
10069 /* rotation */
10070
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 if (item->rotation || item->hflip || item->vflip) {
10071 int ret = set_display_matrix_from_item(&tile_grid->coded_side_data,
10072 &tile_grid->nb_coded_side_data, item);
10073 if (ret < 0)
10074 return ret;
10075 }
10076
10077 2 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
10078 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
10079
10080 2 avio_seek(s->pb, pos, SEEK_SET);
10081
10082 2 size = tile_rows * tile_cols;
10083 2 tile_grid->nb_tiles = grid->nb_tiles;
10084
10085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tile_grid->nb_tiles != size)
10086 return AVERROR_INVALIDDATA;
10087
10088
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < tile_cols; i++)
10089 4 tile_grid->coded_width += grid->tile_item_list[i]->width;
10090
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < size; i += tile_cols)
10091 4 tile_grid->coded_height += grid->tile_item_list[i]->height;
10092
10093 2 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!tile_grid->offsets)
10095 return AVERROR(ENOMEM);
10096
10097
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 while (y < tile_grid->coded_height) {
10098 4 int left_col = i;
10099
10100
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 while (x < tile_grid->coded_width) {
10101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (i == tile_grid->nb_tiles)
10102 return AVERROR_INVALIDDATA;
10103
10104 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10105 8 tile_grid->offsets[i].horizontal = x;
10106 8 tile_grid->offsets[i].vertical = y;
10107
10108 8 x += grid->tile_item_list[i++]->width;
10109 }
10110
10111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (x > tile_grid->coded_width) {
10112 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10113 return AVERROR_INVALIDDATA;
10114 }
10115
10116 4 x = 0;
10117 4 y += grid->tile_item_list[left_col]->height;
10118 }
10119
10120
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (y > tile_grid->coded_height || i != tile_grid->nb_tiles) {
10121 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10122 return AVERROR_INVALIDDATA;
10123 }
10124
10125 2 return 0;
10126 }
10127
10128 4 static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid,
10129 AVStreamGroupTileGrid *tile_grid)
10130 {
10131 4 MOVContext *c = s->priv_data;
10132 4 const HEIFItem *item = grid->item;
10133 uint16_t canvas_fill_value[4];
10134 4 int64_t offset = 0, pos = avio_tell(s->pb);
10135 4 int ret = 0, flags;
10136
10137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10138 av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
10139 return AVERROR_PATCHWELCOME;
10140 }
10141
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
10142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
10143 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
10144 return AVERROR_INVALIDDATA;
10145 }
10146 4 offset = c->idat_offset;
10147 }
10148
10149 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10150
10151 4 avio_r8(s->pb); /* version */
10152 4 flags = avio_r8(s->pb);
10153
10154
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10155 16 canvas_fill_value[i] = avio_rb16(s->pb);
10156 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
10157 4 canvas_fill_value[0], canvas_fill_value[1],
10158 4 canvas_fill_value[2], canvas_fill_value[3]);
10159
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10160 16 tile_grid->background[i] = canvas_fill_value[i];
10161
10162 /* actual width and height of output image */
10163 4 tile_grid->width =
10164
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);
10165 4 tile_grid->height =
10166
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);
10167
10168 /* rotation */
10169
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
4 if (item->rotation || item->hflip || item->vflip) {
10170 int ret = set_display_matrix_from_item(&tile_grid->coded_side_data,
10171 &tile_grid->nb_coded_side_data, item);
10172 if (ret < 0)
10173 return ret;
10174 }
10175
10176 /* ICC profile */
10177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (item->icc_profile_size) {
10178 int ret = set_icc_profile_from_item(&tile_grid->coded_side_data,
10179 &tile_grid->nb_coded_side_data, item);
10180 if (ret < 0)
10181 return ret;
10182 }
10183
10184 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
10185 tile_grid->width, tile_grid->height);
10186
10187 4 tile_grid->nb_tiles = grid->nb_tiles;
10188 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
10190 ret = AVERROR(ENOMEM);
10191 goto fail;
10192 }
10193
10194
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
10195 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10196
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);
10197
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);
10198 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
10199 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
10200 8 i, tile_grid->offsets[i].idx,
10201 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
10202 }
10203
10204 4 fail:
10205 4 avio_seek(s->pb, pos, SEEK_SET);
10206
10207 4 return ret;
10208 }
10209
10210 6 static int mov_parse_tiles(AVFormatContext *s)
10211 {
10212 6 MOVContext *mov = s->priv_data;
10213
10214
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (int i = 0; i < mov->nb_heif_grid; i++) {
10215 6 AVStreamGroup *stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
10216 AVStreamGroupTileGrid *tile_grid;
10217 6 const HEIFGrid *grid = &mov->heif_grid[i];
10218 6 int err, loop = 1;
10219
10220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!stg)
10221 return AVERROR(ENOMEM);
10222
10223 6 stg->id = grid->item->item_id;
10224 6 tile_grid = stg->params.tile_grid;
10225
10226
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (int j = 0; j < grid->nb_tiles; j++) {
10227 16 int tile_id = grid->tile_id_list[j];
10228 int k;
10229
10230
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 for (k = 0; k < mov->nb_heif_item; k++) {
10231 30 HEIFItem *item = mov->heif_item[k];
10232 AVStream *st;
10233
10234
3/4
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 16 times.
30 if (!item || item->item_id != tile_id)
10235 14 continue;
10236 16 st = item->st;
10237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!st) {
10238 av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
10239 "reference a stream\n",
10240 tile_id, grid->item->item_id);
10241 ff_remove_stream_group(s, stg);
10242 loop = 0;
10243 break;
10244 }
10245
10246 16 grid->tile_item_list[j] = item;
10247 16 grid->tile_idx_list[j] = stg->nb_streams;
10248
10249 16 err = avformat_stream_group_add_stream(stg, st);
10250
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (err < 0) {
10251 int l;
10252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
10253 return err;
10254
10255
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_streams; l++)
10256
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->streams[l]->index == st->index)
10257 2 break;
10258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_streams);
10259 2 grid->tile_idx_list[j] = l;
10260 }
10261
10262
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
16 if (item->item_id != mov->primary_item_id)
10263 10 st->disposition |= AV_DISPOSITION_DEPENDENT;
10264 16 break;
10265 }
10266
10267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (k == mov->nb_heif_item) {
10268 av_assert0(loop);
10269 av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
10270 "exist\n",
10271 tile_id, grid->item->item_id);
10272 ff_remove_stream_group(s, stg);
10273 loop = 0;
10274 }
10275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!loop)
10276 break;
10277 }
10278
10279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!loop)
10280 continue;
10281
10282
2/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
6 switch (grid->item->type) {
10283 2 case MKTAG('g','r','i','d'):
10284 2 err = read_image_grid(s, grid, tile_grid);
10285 2 break;
10286 4 case MKTAG('i','o','v','l'):
10287 4 err = read_image_iovl(s, grid, tile_grid);
10288 4 break;
10289 default:
10290 av_assert0(0);
10291 }
10292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10293 return err;
10294
10295
10296
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (grid->item->name)
10297 6 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
10298
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (grid->item->item_id == mov->primary_item_id)
10299 2 stg->disposition |= AV_DISPOSITION_DEFAULT;
10300 }
10301
10302 6 return 0;
10303 }
10304
10305 13 static int mov_parse_heif_items(AVFormatContext *s)
10306 {
10307 13 MOVContext *mov = s->priv_data;
10308 int err;
10309
10310
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 13 times.
45 for (int i = 0; i < mov->nb_heif_item; i++) {
10311 32 HEIFItem *item = mov->heif_item[i];
10312 MOVStreamContext *sc;
10313 AVStream *st;
10314 32 int64_t offset = 0;
10315
10316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!item)
10317 continue;
10318
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 25 times.
32 if (!item->st) {
10319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (item->item_id == mov->thmb_item_id) {
10320 av_log(s, AV_LOG_ERROR, "HEIF thumbnail doesn't reference a stream\n");
10321 return AVERROR_INVALIDDATA;
10322 }
10323 7 continue;
10324 }
10325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (item->is_idat_relative) {
10326 if (!mov->idat_offset) {
10327 av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
10328 return AVERROR_INVALIDDATA;
10329 }
10330 offset = mov->idat_offset;
10331 }
10332
10333 25 st = item->st;
10334 25 sc = st->priv_data;
10335 25 st->codecpar->width = item->width;
10336 25 st->codecpar->height = item->height;
10337
10338 25 err = sanity_checks(s, sc, item->item_id);
10339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (err)
10340 return AVERROR_INVALIDDATA;
10341
10342 25 sc->sample_sizes[0] = item->extent_length;
10343 25 sc->chunk_offsets[0] = item->extent_offset + offset;
10344
10345
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 14 times.
25 if (item->item_id == mov->primary_item_id)
10346 11 st->disposition |= AV_DISPOSITION_DEFAULT;
10347
10348
4/6
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 19 times.
25 if (item->rotation || item->hflip || item->vflip) {
10349 6 err = set_display_matrix_from_item(&st->codecpar->coded_side_data,
10350 6 &st->codecpar->nb_coded_side_data, item);
10351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10352 return err;
10353 }
10354
10355 25 mov_build_index(mov, st);
10356 }
10357
10358
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 7 times.
13 if (mov->nb_heif_grid) {
10359 6 err = mov_parse_tiles(s);
10360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
10361 return err;
10362 }
10363
10364 13 return 0;
10365 }
10366
10367 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
10368 int first_index)
10369 {
10370 MOVStreamContext *sc = st->priv_data;
10371
10372 if (sc->tref_id < 0)
10373 return NULL;
10374
10375 for (int i = first_index; i < s->nb_streams; i++)
10376 if (s->streams[i]->id == sc->tref_id)
10377 return s->streams[i];
10378
10379 return NULL;
10380 }
10381
10382 494 static int mov_parse_lcevc_streams(AVFormatContext *s)
10383 {
10384 int err;
10385
10386
2/2
✓ Branch 0 taken 673 times.
✓ Branch 1 taken 494 times.
1167 for (int i = 0; i < s->nb_streams; i++) {
10387 AVStreamGroup *stg;
10388 673 AVStream *st = s->streams[i];
10389 AVStream *st_base;
10390 673 MOVStreamContext *sc = st->priv_data;
10391 673 int j = 0;
10392
10393 /* Find an enhancement stream. */
10394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC ||
10395 !(sc->tref_flags & MOV_TREF_FLAG_ENHANCEMENT))
10396 673 continue;
10397
10398 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10399
10400 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
10401 if (!stg)
10402 return AVERROR(ENOMEM);
10403
10404 stg->id = st->id;
10405 stg->params.lcevc->width = st->codecpar->width;
10406 stg->params.lcevc->height = st->codecpar->height;
10407 st->codecpar->width = 0;
10408 st->codecpar->height = 0;
10409
10410 while (st_base = mov_find_reference_track(s, st, j)) {
10411 err = avformat_stream_group_add_stream(stg, st_base);
10412 if (err < 0)
10413 return err;
10414
10415 j = st_base->index + 1;
10416 }
10417 if (!j) {
10418 av_log(s, AV_LOG_ERROR, "Failed to find base stream for enhancement stream\n");
10419 return AVERROR_INVALIDDATA;
10420 }
10421
10422 err = avformat_stream_group_add_stream(stg, st);
10423 if (err < 0)
10424 return err;
10425
10426 stg->params.lcevc->lcevc_index = stg->nb_streams - 1;
10427 }
10428
10429 494 return 0;
10430 }
10431
10432 494 static void fix_stream_ids(AVFormatContext *s)
10433 {
10434 494 int highest_id = 0;
10435
10436
2/2
✓ Branch 0 taken 673 times.
✓ Branch 1 taken 494 times.
1167 for (int i = 0; i < s->nb_streams; i++) {
10437 673 const AVStream *st = s->streams[i];
10438 673 const MOVStreamContext *sc = st->priv_data;
10439
2/2
✓ Branch 0 taken 623 times.
✓ Branch 1 taken 50 times.
673 if (!sc->iamf)
10440 623 highest_id = FFMAX(highest_id, st->id);
10441 }
10442 494 highest_id += !highest_id;
10443
4/4
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 409 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 85 times.
504 for (int i = 0; highest_id > 1 && i < s->nb_stream_groups; i++) {
10444 10 AVStreamGroup *stg = s->stream_groups[i];
10445
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
10446 8 continue;
10447
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_streams; j++) {
10448 14 AVStream *st = stg->streams[j];
10449 14 MOVStreamContext *sc = st->priv_data;
10450 14 st->id += highest_id;
10451 14 sc->iamf_stream_offset = highest_id;
10452 }
10453 }
10454 494 }
10455
10456 494 static int mov_read_header(AVFormatContext *s)
10457 {
10458 494 MOVContext *mov = s->priv_data;
10459 494 AVIOContext *pb = s->pb;
10460 int j, err;
10461 494 MOVAtom atom = { AV_RL32("root") };
10462 int i;
10463
10464
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 491 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
494 if (mov->decryption_key_len != 0 && mov->decryption_key_len != AES_CTR_KEY_SIZE) {
10465 av_log(s, AV_LOG_ERROR, "Invalid decryption key len %d expected %d\n",
10466 mov->decryption_key_len, AES_CTR_KEY_SIZE);
10467 return AVERROR(EINVAL);
10468 }
10469
10470 494 mov->fc = s;
10471 494 mov->trak_index = -1;
10472 494 mov->thmb_item_id = -1;
10473 494 mov->primary_item_id = -1;
10474 494 mov->cur_item_id = -1;
10475 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
10476
1/2
✓ Branch 0 taken 494 times.
✗ Branch 1 not taken.
494 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
10477 494 atom.size = avio_size(pb);
10478 else
10479 atom.size = INT64_MAX;
10480
10481 /* check MOV header */
10482 do {
10483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 494 times.
494 if (mov->moov_retry)
10484 avio_seek(pb, 0, SEEK_SET);
10485
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 494 times.
494 if ((err = mov_read_default(mov, pb, atom)) < 0) {
10486 av_log(s, AV_LOG_ERROR, "error reading header\n");
10487 return err;
10488 }
10489 988 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10490
5/10
✓ Branch 0 taken 494 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 481 times.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 13 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
494 !mov->found_moov && (!mov->found_iloc || !mov->found_iinf) && !mov->moov_retry++);
10491
3/6
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 481 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
494 if (!mov->found_moov && !mov->found_iloc && !mov->found_iinf) {
10492 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
10493 return AVERROR_INVALIDDATA;
10494 }
10495 494 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
10496
10497
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 481 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
494 if (mov->found_iloc && mov->found_iinf) {
10498 13 err = mov_parse_heif_items(s);
10499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (err < 0)
10500 return err;
10501 }
10502 // prevent iloc and iinf boxes from being parsed while reading packets.
10503 // this is needed because an iinf box may have been parsed but ignored
10504 // for having old infe boxes which create no streams.
10505 494 mov->found_iloc = mov->found_iinf = 1;
10506
10507
1/2
✓ Branch 0 taken 494 times.
✗ Branch 1 not taken.
494 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
10508
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 492 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
494 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
10509 2 mov_read_chapters(s);
10510
2/2
✓ Branch 0 taken 673 times.
✓ Branch 1 taken 494 times.
1167 for (i = 0; i < s->nb_streams; i++)
10511
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 654 times.
673 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
10512 19 mov_read_timecode_track(s, s->streams[i]);
10513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 654 times.
654 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
10514 mov_read_rtmd_track(s, s->streams[i]);
10515 }
10516 }
10517
10518 /* copy timecode metadata from tmcd tracks to the related video streams */
10519
2/2
✓ Branch 0 taken 673 times.
✓ Branch 1 taken 494 times.
1167 for (i = 0; i < s->nb_streams; i++) {
10520 673 AVStream *st = s->streams[i];
10521 673 MOVStreamContext *sc = st->priv_data;
10522
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 655 times.
673 if (sc->timecode_track > 0) {
10523 AVDictionaryEntry *tcr;
10524 18 int tmcd_st_id = -1;
10525
10526
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 18 times.
66 for (j = 0; j < s->nb_streams; j++) {
10527 48 MOVStreamContext *sc2 = s->streams[j]->priv_data;
10528
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 30 times.
48 if (sc2->id == sc->timecode_track)
10529 18 tmcd_st_id = j;
10530 }
10531
10532
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)
10533 continue;
10534 18 tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
10535
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 if (tcr)
10536 16 av_dict_set(&st->metadata, "timecode", tcr->value, 0);
10537 }
10538 }
10539 494 export_orphan_timecode(s);
10540
10541 /* Create LCEVC stream groups. */
10542 494 err = mov_parse_lcevc_streams(s);
10543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 494 times.
494 if (err < 0)
10544 return err;
10545
10546
2/2
✓ Branch 0 taken 673 times.
✓ Branch 1 taken 494 times.
1167 for (i = 0; i < s->nb_streams; i++) {
10547 673 AVStream *st = s->streams[i];
10548 673 FFStream *const sti = ffstream(st);
10549 673 MOVStreamContext *sc = st->priv_data;
10550 673 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
10551 673 fix_timescale(mov, sc);
10552
2/2
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 392 times.
673 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
10553
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 165 times.
281 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
10554 116 sti->skip_samples = sc->start_pad;
10555 }
10556
5/6
✓ Branch 0 taken 341 times.
✓ Branch 1 taken 332 times.
✓ Branch 2 taken 302 times.
✓ Branch 3 taken 39 times.
✓ Branch 4 taken 302 times.
✗ Branch 5 not taken.
673 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
10557 302 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
10558 302 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
10559
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 665 times.
673 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
10560
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
8 if (st->codecpar->width <= 0 || st->codecpar->height <= 0) {
10561 4 st->codecpar->width = sc->width;
10562 4 st->codecpar->height = sc->height;
10563 }
10564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
10565 st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
10566
10567 for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
10568 dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
10569
10570 err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
10571 if (err < 0)
10572 return err;
10573
10574 av_freep(&st->codecpar->extradata);
10575 st->codecpar->extradata_size = 0;
10576
10577 err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
10578 st->codecpar);
10579 if (err < 0)
10580 return err;
10581 }
10582 }
10583
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (mov->handbrake_version &&
10584 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
10585 st->codecpar->codec_id == AV_CODEC_ID_MP3) {
10586 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
10587 sti->need_parsing = AVSTREAM_PARSE_FULL;
10588 }
10589 }
10590
10591
3/4
✓ Branch 0 taken 482 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 482 times.
494 if (mov->trex_data || mov->use_mfra_for > 0) {
10592
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 12 times.
29 for (i = 0; i < s->nb_streams; i++) {
10593 17 AVStream *st = s->streams[i];
10594 17 MOVStreamContext *sc = st->priv_data;
10595
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 3 times.
17 if (sc->duration_for_fps > 0) {
10596 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
10597 14 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
10598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (st->codecpar->bit_rate == INT64_MIN) {
10599 av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
10600 sc->data_size, sc->time_scale);
10601 st->codecpar->bit_rate = 0;
10602 if (s->error_recognition & AV_EF_EXPLODE)
10603 return AVERROR_INVALIDDATA;
10604 }
10605 }
10606 }
10607 }
10608
10609
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 494 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
494 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
10610 if (mov->bitrates[i]) {
10611 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
10612 }
10613 }
10614
10615 494 ff_rfps_calculate(s);
10616
10617
2/2
✓ Branch 0 taken 673 times.
✓ Branch 1 taken 494 times.
1167 for (i = 0; i < s->nb_streams; i++) {
10618 673 AVStream *st = s->streams[i];
10619 673 MOVStreamContext *sc = st->priv_data;
10620
10621
3/3
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 341 times.
✓ Branch 2 taken 51 times.
673 switch (st->codecpar->codec_type) {
10622 281 case AVMEDIA_TYPE_AUDIO:
10623 281 err = ff_replaygain_export(st, s->metadata);
10624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 281 times.
281 if (err < 0)
10625 return err;
10626 281 break;
10627 341 case AVMEDIA_TYPE_VIDEO:
10628
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 333 times.
341 if (sc->display_matrix) {
10629
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,
10630 AV_PKT_DATA_DISPLAYMATRIX,
10631 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
10632 return AVERROR(ENOMEM);
10633
10634 8 sc->display_matrix = NULL;
10635 }
10636
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 337 times.
341 if (sc->stereo3d) {
10637
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,
10638 AV_PKT_DATA_STEREO3D,
10639 4 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
10640 return AVERROR(ENOMEM);
10641
10642 4 sc->stereo3d = NULL;
10643 }
10644
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 337 times.
341 if (sc->spherical) {
10645
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,
10646 AV_PKT_DATA_SPHERICAL,
10647 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
10648 return AVERROR(ENOMEM);
10649
10650 4 sc->spherical = NULL;
10651 }
10652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
341 if (sc->mastering) {
10653 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10654 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
10655 (uint8_t *)sc->mastering, sc->mastering_size, 0))
10656 return AVERROR(ENOMEM);
10657
10658 sc->mastering = NULL;
10659 }
10660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
341 if (sc->coll) {
10661 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
10662 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
10663 (uint8_t *)sc->coll, sc->coll_size, 0))
10664 return AVERROR(ENOMEM);
10665
10666 sc->coll = NULL;
10667 }
10668
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 337 times.
341 if (sc->ambient) {
10669
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,
10670 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
10671 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
10672 return AVERROR(ENOMEM);
10673
10674 4 sc->ambient = NULL;
10675 }
10676 341 break;
10677 }
10678 }
10679
10680 494 fix_stream_ids(s);
10681
10682 494 ff_configure_buffers_for_index(s, AV_TIME_BASE);
10683
10684
2/2
✓ Branch 0 taken 389 times.
✓ Branch 1 taken 494 times.
883 for (i = 0; i < mov->frag_index.nb_items; i++)
10685
2/2
✓ Branch 0 taken 385 times.
✓ Branch 1 taken 4 times.
389 if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset)
10686 385 mov->frag_index.item[i].headers_read = 1;
10687
10688 494 return 0;
10689 }
10690
10691 103923 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
10692 {
10693 103923 AVIndexEntry *sample = NULL;
10694 103923 int64_t best_dts = INT64_MAX;
10695 int i;
10696 103923 MOVContext *mov = s->priv_data;
10697
2/4
✓ Branch 0 taken 103923 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 103923 times.
103923 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
10698
2/2
✓ Branch 0 taken 133782 times.
✓ Branch 1 taken 103923 times.
237705 for (i = 0; i < s->nb_streams; i++) {
10699 133782 AVStream *avst = s->streams[i];
10700 133782 FFStream *const avsti = ffstream(avst);
10701 133782 MOVStreamContext *msc = avst->priv_data;
10702
4/4
✓ Branch 0 taken 125544 times.
✓ Branch 1 taken 8238 times.
✓ Branch 2 taken 122262 times.
✓ Branch 3 taken 3282 times.
133782 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
10703 122262 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
10704 122262 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
10705
2/2
✓ Branch 0 taken 108567 times.
✓ Branch 1 taken 13695 times.
122262 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
10706 122262 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
10707
3/6
✓ Branch 0 taken 18828 times.
✓ Branch 1 taken 103434 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18828 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
122262 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
10708
1/2
✓ Branch 0 taken 18828 times.
✗ Branch 1 not taken.
18828 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
10709
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 18828 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 18828 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18828 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 16700 times.
✓ Branch 9 taken 2128 times.
18828 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
10710
4/4
✓ Branch 0 taken 8590 times.
✓ Branch 1 taken 8110 times.
✓ Branch 2 taken 2128 times.
✓ Branch 3 taken 8590 times.
18828 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
10711
3/4
✓ Branch 0 taken 715 times.
✓ Branch 1 taken 1413 times.
✓ Branch 2 taken 715 times.
✗ Branch 3 not taken.
2128 (dtsdiff > AV_TIME_BASE && dts < best_dts && mov->interleaved_read)))))) {
10712 112259 sample = current_sample;
10713 112259 best_dts = dts;
10714 112259 *st = avst;
10715 }
10716 }
10717 }
10718 103923 return sample;
10719 }
10720
10721 9 static int should_retry(AVIOContext *pb, int error_code) {
10722
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))
10723 9 return 0;
10724
10725 return 1;
10726 }
10727
10728 42 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
10729 {
10730 int ret;
10731 42 MOVContext *mov = s->priv_data;
10732
10733
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
42 if (index >= 0 && index < mov->frag_index.nb_items)
10734 target = mov->frag_index.item[index].moof_offset;
10735
2/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 42 times.
42 if (target >= 0 && avio_seek(s->pb, target, SEEK_SET) != target) {
10736 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
10737 return AVERROR_INVALIDDATA;
10738 }
10739
10740 42 mov->next_root_atom = 0;
10741
2/6
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 42 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
42 if ((index < 0 && target >= 0) || index >= mov->frag_index.nb_items)
10742 42 index = search_frag_moof_offset(&mov->frag_index, target);
10743
3/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 4 times.
42 if (index >= 0 && index < mov->frag_index.nb_items &&
10744
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 mov->frag_index.item[index].moof_offset == target) {
10745
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (index + 1 < mov->frag_index.nb_items)
10746 35 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
10747
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
38 if (mov->frag_index.item[index].headers_read)
10748 35 return 0;
10749 3 mov->frag_index.item[index].headers_read = 1;
10750 }
10751
10752 7 mov->found_mdat = 0;
10753
10754 7 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
10755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
10756 return ret;
10757
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 3 times.
7 if (avio_feof(s->pb))
10758 4 return AVERROR_EOF;
10759 3 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
10760
10761 3 return 1;
10762 }
10763
10764 16 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
10765 {
10766 16 MOVStreamContext *sc = st->priv_data;
10767 uint8_t *side, *extradata;
10768 int extradata_size;
10769
10770 /* Save the current index. */
10771 16 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
10772
10773 /* Notify the decoder that extradata changed. */
10774 16 extradata_size = sc->extradata_size[sc->last_stsd_index];
10775 16 extradata = sc->extradata[sc->last_stsd_index];
10776
4/6
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
16 if (st->discard != AVDISCARD_ALL && extradata_size > 0 && extradata) {
10777 13 side = av_packet_new_side_data(pkt,
10778 AV_PKT_DATA_NEW_EXTRADATA,
10779 extradata_size);
10780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!side)
10781 return AVERROR(ENOMEM);
10782 13 memcpy(side, extradata, extradata_size);
10783 }
10784
10785 16 return 0;
10786 }
10787
10788 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
10789 {
10790 /* We can't make assumptions about the structure of the payload,
10791 because it may include multiple cdat and cdt2 samples. */
10792 const uint32_t cdat = AV_RB32("cdat");
10793 const uint32_t cdt2 = AV_RB32("cdt2");
10794 int ret, out_size = 0;
10795
10796 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
10797 if (src_size < 10)
10798 return AVERROR_INVALIDDATA;
10799
10800 /* avoid an int overflow: */
10801 if ((src_size - 8) / 2 >= INT_MAX / 3)
10802 return AVERROR_INVALIDDATA;
10803
10804 ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
10805 if (ret < 0)
10806 return ret;
10807
10808 /* parse and re-format the c608 payload in one pass. */
10809 while (src_size >= 10) {
10810 const uint32_t atom_size = avio_rb32(pb);
10811 const uint32_t atom_type = avio_rb32(pb);
10812 const uint32_t data_size = atom_size - 8;
10813 const uint8_t cc_field =
10814 atom_type == cdat ? 1 :
10815 atom_type == cdt2 ? 2 :
10816 0;
10817
10818 /* account for bytes consumed for atom size and type. */
10819 src_size -= 8;
10820
10821 /* make sure the data size stays within the buffer boundaries. */
10822 if (data_size < 2 || data_size > src_size) {
10823 ret = AVERROR_INVALIDDATA;
10824 break;
10825 }
10826
10827 /* make sure the data size is consistent with N byte pairs. */
10828 if (data_size % 2 != 0) {
10829 ret = AVERROR_INVALIDDATA;
10830 break;
10831 }
10832
10833 if (!cc_field) {
10834 /* neither cdat or cdt2 ... skip it */
10835 avio_skip(pb, data_size);
10836 src_size -= data_size;
10837 continue;
10838 }
10839
10840 for (uint32_t i = 0; i < data_size; i += 2) {
10841 pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
10842 pkt->data[out_size + 1] = avio_r8(pb);
10843 pkt->data[out_size + 2] = avio_r8(pb);
10844 out_size += 3;
10845 src_size -= 2;
10846 }
10847 }
10848
10849 if (src_size > 0)
10850 /* skip any remaining unread portion of the input payload */
10851 avio_skip(pb, src_size);
10852
10853 av_shrink_packet(pkt, out_size);
10854 return ret;
10855 }
10856
10857 103390 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
10858 int64_t current_index, AVPacket *pkt)
10859 {
10860 103390 MOVStreamContext *sc = st->priv_data;
10861
10862 103390 pkt->stream_index = sc->ffindex;
10863 103390 pkt->dts = sample->timestamp;
10864
2/2
✓ Branch 0 taken 237 times.
✓ Branch 1 taken 103153 times.
103390 if (sample->flags & AVINDEX_DISCARD_FRAME) {
10865 237 pkt->flags |= AV_PKT_FLAG_DISCARD;
10866 }
10867
4/4
✓ Branch 0 taken 83534 times.
✓ Branch 1 taken 19856 times.
✓ Branch 2 taken 83522 times.
✓ Branch 3 taken 12 times.
103390 if (sc->stts_count && sc->tts_index < sc->tts_count)
10868 83522 pkt->duration = sc->tts_data[sc->tts_index].duration;
10869
3/4
✓ Branch 0 taken 3009 times.
✓ Branch 1 taken 100381 times.
✓ Branch 2 taken 3009 times.
✗ Branch 3 not taken.
103390 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
10870 3009 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
10871 } else {
10872
2/2
✓ Branch 0 taken 15775 times.
✓ Branch 1 taken 84606 times.
100381 if (pkt->duration == 0) {
10873 15775 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
10874
2/2
✓ Branch 0 taken 15700 times.
✓ Branch 1 taken 75 times.
15775 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
10875
2/2
✓ Branch 0 taken 15747 times.
✓ Branch 1 taken 28 times.
15775 if (next_dts >= pkt->dts)
10876 15747 pkt->duration = next_dts - pkt->dts;
10877 }
10878 100381 pkt->pts = pkt->dts;
10879 }
10880
10881
4/4
✓ Branch 0 taken 83534 times.
✓ Branch 1 taken 19856 times.
✓ Branch 2 taken 83522 times.
✓ Branch 3 taken 12 times.
103390 if (sc->tts_data && sc->tts_index < sc->tts_count) {
10882 /* update tts context */
10883 83522 sc->tts_sample++;
10884
1/2
✓ Branch 0 taken 83522 times.
✗ Branch 1 not taken.
83522 if (sc->tts_index < sc->tts_count &&
10885
1/2
✓ Branch 0 taken 83522 times.
✗ Branch 1 not taken.
83522 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
10886 83522 sc->tts_index++;
10887 83522 sc->tts_sample = 0;
10888 }
10889 }
10890
10891
4/4
✓ Branch 0 taken 1036 times.
✓ Branch 1 taken 102354 times.
✓ Branch 2 taken 904 times.
✓ Branch 3 taken 132 times.
103390 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
10892 904 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
10893 904 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
10894
2/2
✓ Branch 0 taken 313 times.
✓ Branch 1 taken 591 times.
904 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
10895 }
10896 103390 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
10897 103390 pkt->pos = sample->pos;
10898
10899 /* Multiple stsd handling. */
10900
2/2
✓ Branch 0 taken 102599 times.
✓ Branch 1 taken 791 times.
103390 if (sc->stsc_data) {
10901
1/2
✓ Branch 0 taken 102599 times.
✗ Branch 1 not taken.
102599 if (sc->stsc_data[sc->stsc_index].id > 0 &&
10902
2/2
✓ Branch 0 taken 102574 times.
✓ Branch 1 taken 25 times.
102599 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
10903
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 102558 times.
102574 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
10904 16 int ret = mov_change_extradata(st, pkt);
10905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0)
10906 return ret;
10907 }
10908
10909 /* Update the stsc index for the next sample */
10910 102599 sc->stsc_sample++;
10911
2/2
✓ Branch 1 taken 55143 times.
✓ Branch 2 taken 47456 times.
102599 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
10912
2/2
✓ Branch 1 taken 1189 times.
✓ Branch 2 taken 53954 times.
55143 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
10913 1189 sc->stsc_index++;
10914 1189 sc->stsc_sample = 0;
10915 }
10916 }
10917
10918 103390 return 0;
10919 }
10920
10921 97062 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
10922 {
10923 97062 MOVContext *mov = s->priv_data;
10924 MOVStreamContext *sc;
10925 AVIndexEntry *sample;
10926 97062 AVStream *st = NULL;
10927 97062 FFStream *avsti = NULL;
10928 int64_t current_index;
10929 int ret;
10930 int i;
10931 97062 mov->fc = s;
10932 6861 retry:
10933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103923 times.
103923 if (s->pb->pos == 0) {
10934
10935 // Discard current fragment index
10936 if (mov->frag_index.allocated_size > 0) {
10937 for(int i = 0; i < mov->frag_index.nb_items; i++) {
10938 av_freep(&mov->frag_index.item[i].stream_info);
10939 }
10940 av_freep(&mov->frag_index.item);
10941 mov->frag_index.nb_items = 0;
10942 mov->frag_index.allocated_size = 0;
10943 mov->frag_index.current = -1;
10944 mov->frag_index.complete = 0;
10945 }
10946
10947 for (i = 0; i < s->nb_streams; i++) {
10948 AVStream *avst = s->streams[i];
10949 MOVStreamContext *msc = avst->priv_data;
10950
10951 // Clear current sample
10952 mov_current_sample_set(msc, 0);
10953 msc->tts_index = 0;
10954
10955 // Discard current index entries
10956 avsti = ffstream(avst);
10957 if (avsti->index_entries_allocated_size > 0) {
10958 av_freep(&avsti->index_entries);
10959 avsti->index_entries_allocated_size = 0;
10960 avsti->nb_index_entries = 0;
10961 }
10962 }
10963
10964 if ((ret = mov_switch_root(s, -1, -1)) < 0)
10965 return ret;
10966 }
10967 103923 sample = mov_find_next_sample(s, &st);
10968
6/6
✓ Branch 0 taken 103434 times.
✓ Branch 1 taken 489 times.
✓ Branch 2 taken 472 times.
✓ Branch 3 taken 102962 times.
✓ Branch 4 taken 35 times.
✓ Branch 5 taken 437 times.
103923 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
10969
2/2
✓ Branch 0 taken 482 times.
✓ Branch 1 taken 42 times.
524 if (!mov->next_root_atom)
10970 482 return AVERROR_EOF;
10971
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 38 times.
42 if ((ret = mov_switch_root(s, mov->next_root_atom, -1)) < 0)
10972 4 return ret;
10973 38 goto retry;
10974 }
10975 103399 sc = st->priv_data;
10976 /* must be done just before reading, to avoid infinite loop on sample */
10977 103399 current_index = sc->current_index;
10978 103399 mov_current_sample_inc(sc);
10979
10980
2/2
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 102962 times.
103399 if (mov->next_root_atom) {
10981 437 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
10982 437 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
10983 }
10984
10985
2/2
✓ Branch 0 taken 96576 times.
✓ Branch 1 taken 6823 times.
103399 if (st->discard != AVDISCARD_ALL) {
10986 96576 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
10987
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 96569 times.
96576 if (ret64 != sample->pos) {
10988 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
10989 sc->ffindex, sample->pos);
10990
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
10991 mov_current_sample_dec(sc);
10992
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
10993 7 return (int)ret64;
10994 }
10995 return AVERROR_INVALIDDATA;
10996 }
10997
10998
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96569 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96569 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
10999 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
11000 goto retry;
11001 }
11002
11003
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96569 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96569 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
11004 ret = get_eia608_packet(sc->pb, pkt, sample->size);
11005 #if CONFIG_IAMFDEC
11006
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 96514 times.
96569 else if (sc->iamf) {
11007 int64_t pts, dts, pos, duration;
11008 55 int flags, size = sample->size;
11009 55 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11010 55 pts = pkt->pts; dts = pkt->dts;
11011 55 pos = pkt->pos; flags = pkt->flags;
11012 55 duration = pkt->duration;
11013
3/4
✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 275 times.
✓ Branch 3 taken 55 times.
330 while (!ret && size > 0) {
11014 275 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
11015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
275 if (ret < 0) {
11016 if (should_retry(sc->pb, ret))
11017 mov_current_sample_dec(sc);
11018 return ret;
11019 }
11020 275 size -= ret;
11021 275 pkt->pts = pts; pkt->dts = dts;
11022 275 pkt->pos = pos; pkt->flags |= flags;
11023 275 pkt->duration = duration;
11024 275 ret = ff_buffer_packet(s, pkt);
11025 }
11026
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 if (!ret)
11027 55 return FFERROR_REDO;
11028 }
11029 #endif
11030 else
11031 96514 ret = av_get_packet(sc->pb, pkt, sample->size);
11032
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 96512 times.
96514 if (ret < 0) {
11033
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (should_retry(sc->pb, ret)) {
11034 mov_current_sample_dec(sc);
11035 }
11036 2 return ret;
11037 }
11038 #if CONFIG_DV_DEMUXER
11039
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96512 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96512 if (mov->dv_demux && sc->dv_audio_container) {
11040 ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
11041 av_packet_unref(pkt);
11042 if (ret < 0)
11043 return ret;
11044 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
11045 if (ret < 0)
11046 return ret;
11047 }
11048 #endif
11049
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 96494 times.
96512 if (sc->has_palette) {
11050 uint8_t *pal;
11051
11052 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
11053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
11054 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
11055 } else {
11056 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
11057 18 sc->has_palette = 0;
11058 }
11059 }
11060
4/6
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 96224 times.
✓ Branch 3 taken 288 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 288 times.
✗ Branch 6 not taken.
96512 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
11061
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 288 times.
288 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
11062 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
11063 }
11064 }
11065
11066 103335 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
11067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103335 times.
103335 if (ret < 0)
11068 return ret;
11069
11070
2/2
✓ Branch 0 taken 6823 times.
✓ Branch 1 taken 96512 times.
103335 if (st->discard == AVDISCARD_ALL)
11071 6823 goto retry;
11072
11073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96512 times.
96512 if (mov->aax_mode)
11074 aax_filter(pkt->data, pkt->size, mov);
11075
11076 96512 ret = cenc_filter(mov, st, sc, pkt, current_index);
11077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96512 times.
96512 if (ret < 0) {
11078 return ret;
11079 }
11080
11081 96512 return 0;
11082 }
11083
11084 361 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
11085 {
11086 361 MOVContext *mov = s->priv_data;
11087 int index;
11088
11089
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 26 times.
361 if (!mov->frag_index.complete)
11090 335 return 0;
11091
11092 26 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
11093
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 22 times.
26 if (index < 0)
11094 4 index = 0;
11095
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (!mov->frag_index.item[index].headers_read)
11096 return mov_switch_root(s, -1, index);
11097
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (index + 1 < mov->frag_index.nb_items)
11098 26 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11099
11100 26 return 0;
11101 }
11102
11103 static int is_open_key_sample(const MOVStreamContext *sc, int sample)
11104 {
11105 // TODO: a bisect search would scale much better
11106 for (int i = 0; i < sc->open_key_samples_count; i++) {
11107 const int oks = sc->open_key_samples[i];
11108 if (oks == sample)
11109 return 1;
11110 if (oks > sample) /* list is monotically increasing so we can stop early */
11111 break;
11112 }
11113 return 0;
11114 }
11115
11116 /*
11117 * Some key sample may be key frames but not IDR frames, so a random access to
11118 * them may not be allowed.
11119 */
11120 229 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
11121 {
11122 229 MOVStreamContext *sc = st->priv_data;
11123 229 FFStream *const sti = ffstream(st);
11124 int64_t key_sample_dts, key_sample_pts;
11125
11126
1/2
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
229 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
11127 229 return 1;
11128
11129 if (sample >= sc->sample_offsets_count)
11130 return 1;
11131
11132 key_sample_dts = sti->index_entries[sample].timestamp;
11133 key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
11134
11135 /*
11136 * If the sample needs to be presented before an open key sample, they may
11137 * not be decodable properly, even though they come after in decoding
11138 * order.
11139 */
11140 if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
11141 return 0;
11142
11143 return 1;
11144 }
11145
11146 361 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
11147 {
11148 361 MOVStreamContext *sc = st->priv_data;
11149 361 FFStream *const sti = ffstream(st);
11150 int sample, time_sample, ret, next_ts, requested_sample;
11151 unsigned int i;
11152
11153 // Here we consider timestamp to be PTS, hence try to offset it so that we
11154 // can search over the DTS timeline.
11155 361 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
11156
11157 361 ret = mov_seek_fragment(s, st, timestamp);
11158
1/2
✓ Branch 0 taken 361 times.
✗ Branch 1 not taken.
361 if (ret < 0)
11159 return ret;
11160
11161 for (;;) {
11162 361 sample = av_index_search_timestamp(st, timestamp, flags);
11163 361 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
11164
5/6
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 292 times.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
✓ Branch 5 taken 26 times.
361 if (sample < 0 && sti->nb_index_entries && timestamp < sti->index_entries[0].timestamp)
11165 43 sample = 0;
11166
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 335 times.
361 if (sample < 0) /* not sure what to do */
11167 26 return AVERROR_INVALIDDATA;
11168
11169
3/4
✓ Branch 0 taken 229 times.
✓ Branch 1 taken 106 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 229 times.
335 if (!sample || can_seek_to_key_sample(st, sample, timestamp))
11170 break;
11171
11172 next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
11173 requested_sample = av_index_search_timestamp(st, next_ts, flags);
11174
11175 // If we've reached a different sample trying to find a good pts to
11176 // seek to, give up searching because we'll end up seeking back to
11177 // sample 0 on every seek.
11178 if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
11179 break;
11180
11181 timestamp = next_ts;
11182 }
11183
11184 335 mov_current_sample_set(sc, sample);
11185 335 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
11186 /* adjust time to sample index */
11187
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 125 times.
335 if (sc->tts_data) {
11188 210 time_sample = 0;
11189
1/2
✓ Branch 0 taken 60235 times.
✗ Branch 1 not taken.
60235 for (i = 0; i < sc->tts_count; i++) {
11190 60235 int next = time_sample + sc->tts_data[i].count;
11191
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 60025 times.
60235 if (next > sc->current_sample) {
11192 210 sc->tts_index = i;
11193 210 sc->tts_sample = sc->current_sample - time_sample;
11194 210 break;
11195 }
11196 60025 time_sample = next;
11197 }
11198 }
11199
11200 /* adjust stsd index */
11201
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 26 times.
335 if (sc->chunk_count) {
11202 309 time_sample = 0;
11203
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
381 for (i = 0; i < sc->stsc_count; i++) {
11204 381 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
11205
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 72 times.
381 if (next > sc->current_sample) {
11206 309 sc->stsc_index = i;
11207 309 sc->stsc_sample = sc->current_sample - time_sample;
11208 309 break;
11209 }
11210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
11211 72 time_sample = next;
11212 }
11213 }
11214
11215 335 return sample;
11216 }
11217
11218 335 static int64_t mov_get_skip_samples(AVStream *st, int sample)
11219 {
11220 335 MOVStreamContext *sc = st->priv_data;
11221 335 FFStream *const sti = ffstream(st);
11222 335 int64_t first_ts = sti->index_entries[0].timestamp;
11223 335 int64_t ts = sti->index_entries[sample].timestamp;
11224 int64_t off;
11225
11226
2/2
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 151 times.
335 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
11227 184 return 0;
11228
11229 /* compute skip samples according to stream start_pad, seek ts and first ts */
11230 151 off = av_rescale_q(ts - first_ts, st->time_base,
11231 151 (AVRational){1, st->codecpar->sample_rate});
11232 151 return FFMAX(sc->start_pad - off, 0);
11233 }
11234
11235 340 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
11236 {
11237 340 MOVContext *mc = s->priv_data;
11238 AVStream *st;
11239 FFStream *sti;
11240 int sample;
11241 int i;
11242
11243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 340 times.
340 if (stream_index >= s->nb_streams)
11244 return AVERROR_INVALIDDATA;
11245
11246 340 st = s->streams[stream_index];
11247 340 sti = ffstream(st);
11248 340 sample = mov_seek_stream(s, st, sample_time, flags);
11249
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 314 times.
340 if (sample < 0)
11250 26 return sample;
11251
11252
1/2
✓ Branch 0 taken 314 times.
✗ Branch 1 not taken.
314 if (mc->seek_individually) {
11253 /* adjust seek timestamp to found sample timestamp */
11254 314 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
11255 314 sti->skip_samples = mov_get_skip_samples(st, sample);
11256
11257
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 314 times.
649 for (i = 0; i < s->nb_streams; i++) {
11258 335 AVStream *const st = s->streams[i];
11259 335 FFStream *const sti = ffstream(st);
11260 int64_t timestamp;
11261
11262
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 21 times.
335 if (stream_index == i)
11263 314 continue;
11264
11265 21 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
11266 21 sample = mov_seek_stream(s, st, timestamp, flags);
11267
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (sample >= 0)
11268 21 sti->skip_samples = mov_get_skip_samples(st, sample);
11269 }
11270 } else {
11271 for (i = 0; i < s->nb_streams; i++) {
11272 MOVStreamContext *sc;
11273 st = s->streams[i];
11274 sc = st->priv_data;
11275 mov_current_sample_set(sc, 0);
11276 }
11277 while (1) {
11278 MOVStreamContext *sc;
11279 AVIndexEntry *entry = mov_find_next_sample(s, &st);
11280 if (!entry)
11281 return AVERROR_INVALIDDATA;
11282 sc = st->priv_data;
11283 if (sc->ffindex == stream_index && sc->current_sample == sample)
11284 break;
11285 mov_current_sample_inc(sc);
11286 }
11287 }
11288 314 return 0;
11289 }
11290
11291 #define OFFSET(x) offsetof(MOVContext, x)
11292 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
11293 static const AVOption mov_options[] = {
11294 {"use_absolute_path",
11295 "allow using absolute path when opening alias, this is a possible security issue",
11296 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
11297 0, 1, FLAGS},
11298 {"seek_streams_individually",
11299 "Seek each stream individually to the closest point",
11300 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
11301 0, 1, FLAGS},
11302 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
11303 0, 1, FLAGS},
11304 {"advanced_editlist",
11305 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
11306 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
11307 0, 1, FLAGS},
11308 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
11309 0, 1, FLAGS},
11310 {"use_mfra_for",
11311 "use mfra for fragment timestamps",
11312 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
11313 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
11314 .unit = "use_mfra_for"},
11315 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
11316 FLAGS, .unit = "use_mfra_for" },
11317 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
11318 FLAGS, .unit = "use_mfra_for" },
11319 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
11320 FLAGS, .unit = "use_mfra_for" },
11321 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
11322 0, 1, FLAGS},
11323 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
11324 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11325 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
11326 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
11327 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
11328 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11329 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
11330 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11331 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
11332 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11333 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
11334 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
11335 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
11336 .flags = AV_OPT_FLAG_DECODING_PARAM },
11337 { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
11338 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
11339 {.i64 = 0}, 0, 1, FLAGS },
11340 { "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 },
11341 { "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 },
11342
11343 { NULL },
11344 };
11345
11346 static const AVClass mov_class = {
11347 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
11348 .item_name = av_default_item_name,
11349 .option = mov_options,
11350 .version = LIBAVUTIL_VERSION_INT,
11351 };
11352
11353 const FFInputFormat ff_mov_demuxer = {
11354 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
11355 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
11356 .p.priv_class = &mov_class,
11357 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v,avif,heic,heif",
11358 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
11359 .priv_data_size = sizeof(MOVContext),
11360 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
11361 .read_probe = mov_probe,
11362 .read_header = mov_read_header,
11363 .read_packet = mov_read_packet,
11364 .read_close = mov_read_close,
11365 .read_seek = mov_read_seek,
11366 };
11367