FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2026-07-22 00:55:30
Exec Total Coverage
Lines: 4688 7373 63.6%
Functions: 190 227 83.7%
Branches: 2678 4971 53.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/dovi_meta.h"
36 #include "libavutil/internal.h"
37 #include "libavutil/intreadwrite.h"
38 #include "libavutil/intfloat.h"
39 #include "libavutil/mathematics.h"
40 #include "libavutil/avassert.h"
41 #include "libavutil/avstring.h"
42 #include "libavutil/dict.h"
43 #include "libavutil/display.h"
44 #include "libavutil/mem.h"
45 #include "libavutil/opt.h"
46 #include "libavutil/aes.h"
47 #include "libavutil/aes_ctr.h"
48 #include "libavutil/pixdesc.h"
49 #include "libavutil/sha.h"
50 #include "libavutil/spherical.h"
51 #include "libavutil/stereo3d.h"
52 #include "libavutil/timecode.h"
53 #include "libavutil/uuid.h"
54 #include "libavcodec/ac3tab.h"
55 #include "libavcodec/exif.h"
56 #include "libavcodec/flac.h"
57 #include "libavcodec/hevc/hevc.h"
58 #include "libavcodec/mpegaudiodecheader.h"
59 #include "libavcodec/mlp_parse.h"
60 #include "avformat.h"
61 #include "internal.h"
62 #include "avio_internal.h"
63 #include "demux.h"
64 #include "dvdclut.h"
65 #include "iamf_parse.h"
66 #include "iamf_reader.h"
67 #include "dovi_isom.h"
68 #include "riff.h"
69 #include "isom.h"
70 #include "libavcodec/get_bits.h"
71 #include "id3v1.h"
72 #include "mov_chan.h"
73 #include "replaygain.h"
74
75 #if CONFIG_ZLIB
76 #include <zlib.h>
77 #endif
78
79 #include "qtpalette.h"
80
81 /* those functions parse an atom */
82 /* links atom IDs to parse functions */
83 typedef struct MOVParseTableEntry {
84 uint32_t type;
85 int (*parse)(MOVContext *ctx, AVIOContext *pb, MOVAtom atom);
86 } MOVParseTableEntry;
87
88 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom);
89 static int mov_read_mfra(MOVContext *c, AVIOContext *f);
90 static void mov_free_stream_context(AVFormatContext *s, AVStream *st);
91
92 32 static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
93 unsigned len, const char *key)
94 {
95 char buf[16];
96
97 32 short current, total = 0;
98 32 avio_rb16(pb); // unknown
99 32 current = avio_rb16(pb);
100
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (len >= 6)
101 32 total = avio_rb16(pb);
102
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 25 times.
32 if (!total)
103 7 snprintf(buf, sizeof(buf), "%d", current);
104 else
105 25 snprintf(buf, sizeof(buf), "%d/%d", current, total);
106 32 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
107 32 av_dict_set(&c->fc->metadata, key, buf, 0);
108
109 32 return 0;
110 }
111
112 static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
113 unsigned len, const char *key)
114 {
115 /* bypass padding bytes */
116 avio_r8(pb);
117 avio_r8(pb);
118 avio_r8(pb);
119
120 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
121 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
122
123 return 0;
124 }
125
126 30 static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
127 unsigned len, const char *key)
128 {
129 30 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
130 30 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
131
132 30 return 0;
133 }
134
135 12 static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
136 unsigned len, const char *key)
137 {
138 short genre;
139
140 12 avio_r8(pb); // unknown
141
142 12 genre = avio_r8(pb);
143
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (genre < 1 || genre > ID3v1_GENRE_MAX)
144 return 0;
145 12 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
146 12 av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
147
148 12 return 0;
149 }
150
151 static const uint32_t mac_to_unicode[128] = {
152 0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
153 0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
154 0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,
155 0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,
156 0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,
157 0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,
158 0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,
159 0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,
160 0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,
161 0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,
162 0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,
163 0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,
164 0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,
165 0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,
166 0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,
167 0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7,
168 };
169
170 362 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
171 char *dst, int dstlen)
172 {
173 362 char *p = dst;
174 362 char *end = dst+dstlen-1;
175 int i;
176
177
2/2
✓ Branch 0 taken 3115 times.
✓ Branch 1 taken 362 times.
3477 for (i = 0; i < len; i++) {
178 3115 uint8_t t, c = avio_r8(pb);
179
180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3115 times.
3115 if (p >= end)
181 continue;
182
183
2/2
✓ Branch 0 taken 3107 times.
✓ Branch 1 taken 8 times.
3115 if (c < 0x80)
184 3107 *p++ = c;
185
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 else if (p < end)
186
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✓ Branch 9 taken 8 times.
16 PUT_UTF8(mac_to_unicode[c-0x80], t, if (p < end) *p++ = t;);
187 }
188 362 *p = 0;
189 362 return p - dst;
190 }
191
192 /**
193 * Get the requested item.
194 */
195 166 static HEIFItem *get_heif_item(MOVContext *c, unsigned id)
196 {
197 166 HEIFItem *item = NULL;
198
199
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 12 times.
380 for (int i = 0; i < c->nb_heif_item; i++) {
200
3/4
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 214 times.
✓ Branch 3 taken 154 times.
368 if (!c->heif_item[i] || c->heif_item[i]->item_id != id)
201 214 continue;
202
203 154 item = c->heif_item[i];
204 154 break;
205 }
206
207 166 return item;
208 }
209
210 /**
211 * Get the current stream in the parsing process. This can either be the
212 * latest stream added to the context, or the stream referenced by an item.
213 */
214 266 static AVStream *get_curr_st(MOVContext *c)
215 {
216 266 AVStream *st = NULL;
217 HEIFItem *item;
218
219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 266 times.
266 if (c->fc->nb_streams < 1)
220 return NULL;
221
222
2/2
✓ Branch 0 taken 217 times.
✓ Branch 1 taken 49 times.
266 if (c->cur_item_id == -1)
223 217 return c->fc->streams[c->fc->nb_streams-1];
224
225 49 item = get_heif_item(c, c->cur_item_id);
226
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 if (item)
227 49 st = item->st;
228
229 49 return st;
230 }
231
232 16 static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
233 {
234 AVStream *st;
235 MOVStreamContext *sc;
236 enum AVCodecID id;
237 int ret;
238
239
2/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
16 switch (type) {
240 9 case 0xd: id = AV_CODEC_ID_MJPEG; break;
241 7 case 0xe: id = AV_CODEC_ID_PNG; break;
242 case 0x1b: id = AV_CODEC_ID_BMP; break;
243 default:
244 av_log(c->fc, AV_LOG_WARNING, "Unknown cover type: 0x%x.\n", type);
245 avio_skip(pb, len);
246 return 0;
247 }
248
249 16 sc = av_mallocz(sizeof(*sc));
250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!sc)
251 return AVERROR(ENOMEM);
252 16 ret = ff_add_attached_pic(c->fc, NULL, pb, NULL, len);
253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0) {
254 av_free(sc);
255 return ret;
256 }
257 16 st = c->fc->streams[c->fc->nb_streams - 1];
258 16 st->priv_data = sc;
259 16 sc->id = st->id;
260 16 sc->refcount = 1;
261
262
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 if (st->attached_pic.size >= 8 && id != AV_CODEC_ID_BMP) {
263
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 9 times.
16 if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
264 7 id = AV_CODEC_ID_PNG;
265 } else {
266 9 id = AV_CODEC_ID_MJPEG;
267 }
268 }
269 16 st->codecpar->codec_id = id;
270
271 16 return 0;
272 }
273
274 // 3GPP TS 26.244
275 static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
276 {
277 char language[4] = { 0 };
278 char buf[200], place[100];
279 uint16_t langcode = 0;
280 double longitude, latitude, altitude;
281 const char *key = "location";
282
283 if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) {
284 av_log(c->fc, AV_LOG_ERROR, "loci too short\n");
285 return AVERROR_INVALIDDATA;
286 }
287
288 avio_skip(pb, 4); // version+flags
289 langcode = avio_rb16(pb);
290 ff_mov_lang_to_iso639(langcode, language);
291 len -= 6;
292
293 len -= avio_get_str(pb, len, place, sizeof(place));
294 if (len < 1) {
295 av_log(c->fc, AV_LOG_ERROR, "place name too long\n");
296 return AVERROR_INVALIDDATA;
297 }
298 avio_skip(pb, 1); // role
299 len -= 1;
300
301 if (len < 12) {
302 av_log(c->fc, AV_LOG_ERROR,
303 "loci too short (%u bytes left, need at least %d)\n", len, 12);
304 return AVERROR_INVALIDDATA;
305 }
306 longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
307 latitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
308 altitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
309
310 // Try to output in the same format as the ?xyz field
311 snprintf(buf, sizeof(buf), "%+08.4f%+09.4f", latitude, longitude);
312 if (altitude)
313 av_strlcatf(buf, sizeof(buf), "%+f", altitude);
314 av_strlcatf(buf, sizeof(buf), "/%s", place);
315
316 if (*language && strcmp(language, "und")) {
317 char key2[16];
318 snprintf(key2, sizeof(key2), "%s-%s", key, language);
319 av_dict_set(&c->fc->metadata, key2, buf, 0);
320 }
321 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
322 return av_dict_set(&c->fc->metadata, key, buf, 0);
323 }
324
325 static int mov_metadata_hmmt(MOVContext *c, AVIOContext *pb, unsigned len)
326 {
327 int i, n_hmmt;
328
329 if (len < 2)
330 return 0;
331 if (c->ignore_chapters)
332 return 0;
333
334 n_hmmt = avio_rb32(pb);
335 if (n_hmmt > len / 4)
336 return AVERROR_INVALIDDATA;
337 for (i = 0; i < n_hmmt && !pb->eof_reached; i++) {
338 int moment_time = avio_rb32(pb);
339 avpriv_new_chapter(c->fc, i, av_make_q(1, 1000), moment_time, AV_NOPTS_VALUE, NULL);
340 }
341 if (avio_feof(pb))
342 return AVERROR_INVALIDDATA;
343 return 0;
344 }
345
346 538 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
347 {
348 538 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
349 538 char key2[32], language[4] = {0};
350 538 char *str = NULL;
351 538 const char *key = NULL;
352 538 uint16_t langcode = 0;
353 538 uint32_t data_type = 0, str_size_alloc;
354 uint64_t str_size;
355 538 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
356 538 int raw = 0;
357 538 int num = 0;
358 AVDictionary **metadata;
359
360
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 509 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
538 if (c->trak_index >= 0 && c->trak_index < c->fc->nb_streams)
361 29 metadata = &c->fc->streams[c->trak_index]->metadata;
362 else
363 509 metadata = &c->fc->metadata;
364
365
27/75
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 157 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 15 times.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 16 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 12 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 5 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 15 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✓ Branch 34 taken 16 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 40 taken 21 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 20 times.
✓ Branch 43 taken 3 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 12 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 4 times.
✓ Branch 48 taken 20 times.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✓ Branch 52 taken 2 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 5 times.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✓ Branch 59 taken 5 times.
✓ Branch 60 taken 5 times.
✓ Branch 61 taken 46 times.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✓ Branch 68 taken 63 times.
✓ Branch 69 taken 62 times.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✓ Branch 73 taken 3 times.
✓ Branch 74 taken 5 times.
538 switch (atom.type) {
366 3 case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break;
367 3 case MKTAG( '@','P','R','Q'): key = "quicktime_version"; raw = 1; break;
368 2 case MKTAG( 'X','M','P','_'):
369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->export_xmp) { key = "xmp"; raw = 1; } break;
370 16 case MKTAG( 'a','A','R','T'): key = "album_artist"; break;
371 case MKTAG( 'a','k','I','D'): key = "account_type";
372 parse = mov_metadata_int8_no_padding; break;
373 case MKTAG( 'a','p','I','D'): key = "account_id"; break;
374 case MKTAG( 'c','a','t','g'): key = "category"; break;
375 15 case MKTAG( 'c','p','i','l'): key = "compilation";
376 15 parse = mov_metadata_int8_no_padding; break;
377 2 case MKTAG( 'c','p','r','t'): key = "copyright"; break;
378 case MKTAG( 'd','e','s','c'): key = "description"; break;
379 16 case MKTAG( 'd','i','s','k'): key = "disc";
380 16 parse = mov_metadata_track_or_disc_number; break;
381 case MKTAG( 'e','g','i','d'): key = "episode_uid";
382 parse = mov_metadata_int8_no_padding; break;
383 case MKTAG( 'F','I','R','M'): key = "firmware"; raw = 1; break;
384 12 case MKTAG( 'g','n','r','e'): key = "genre";
385 12 parse = mov_metadata_gnre; break;
386 case MKTAG( 'h','d','v','d'): key = "hd_video";
387 parse = mov_metadata_int8_no_padding; break;
388 case MKTAG( 'H','M','M','T'):
389 return mov_metadata_hmmt(c, pb, atom.size);
390 case MKTAG( 'k','e','y','w'): key = "keywords"; break;
391 case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
392 case MKTAG( 'l','o','c','i'):
393 return mov_metadata_loci(c, pb, atom.size);
394 case MKTAG( 'm','a','n','u'): key = "make"; break;
395 case MKTAG( 'm','o','d','l'): key = "model"; break;
396 5 case MKTAG( 'n','a','m','e'): key = "name"; break;
397 case MKTAG( 'p','c','s','t'): key = "podcast";
398 parse = mov_metadata_int8_no_padding; break;
399 15 case MKTAG( 'p','g','a','p'): key = "gapless_playback";
400 15 parse = mov_metadata_int8_no_padding; break;
401 case MKTAG( 'p','u','r','d'): key = "purchase_date"; break;
402 case MKTAG( 'r','t','n','g'): key = "rating";
403 parse = mov_metadata_int8_no_padding; break;
404 case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break;
405 case MKTAG( 's','o','a','l'): key = "sort_album"; break;
406 case MKTAG( 's','o','a','r'): key = "sort_artist"; break;
407 case MKTAG( 's','o','c','o'): key = "sort_composer"; break;
408 case MKTAG( 's','o','n','m'): key = "sort_name"; break;
409 case MKTAG( 's','o','s','n'): key = "sort_show"; break;
410 case MKTAG( 's','t','i','k'): key = "media_type";
411 parse = mov_metadata_int8_no_padding; break;
412 16 case MKTAG( 't','r','k','n'): key = "track";
413 16 parse = mov_metadata_track_or_disc_number; break;
414 case MKTAG( 't','v','e','n'): key = "episode_id"; break;
415 case MKTAG( 't','v','e','s'): key = "episode_sort";
416 parse = mov_metadata_int8_bypass_padding; break;
417 case MKTAG( 't','v','n','n'): key = "network"; break;
418 case MKTAG( 't','v','s','h'): key = "show"; break;
419 case MKTAG( 't','v','s','n'): key = "season_number";
420 parse = mov_metadata_int8_bypass_padding; break;
421 21 case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
422 case MKTAG(0xa9,'P','R','D'): key = "producer"; break;
423 20 case MKTAG(0xa9,'a','l','b'): key = "album"; break;
424 3 case MKTAG(0xa9,'a','u','t'): key = "artist"; break;
425 case MKTAG(0xa9,'c','h','p'): key = "chapter"; break;
426 12 case MKTAG(0xa9,'c','m','t'): key = "comment"; break;
427 case MKTAG(0xa9,'c','o','m'): key = "composer"; break;
428 4 case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
429 20 case MKTAG(0xa9,'d','a','y'): key = "date"; break;
430 case MKTAG(0xa9,'d','i','r'): key = "director"; break;
431 case MKTAG(0xa9,'d','i','s'): key = "disclaimer"; break;
432 case MKTAG(0xa9,'e','d','1'): key = "edit_date"; break;
433 2 case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
434 case MKTAG(0xa9,'f','m','t'): key = "original_format"; break;
435 5 case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
436 case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
437 case MKTAG(0xa9,'h','s','t'): key = "host_computer"; break;
438 case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
439 case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
440 5 case MKTAG(0xa9,'m','a','k'): key = "make"; break;
441 5 case MKTAG(0xa9,'m','o','d'): key = "model"; break;
442 46 case MKTAG(0xa9,'n','a','m'): key = "title"; break;
443 case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break;
444 case MKTAG(0xa9,'p','r','d'): key = "producer"; break;
445 case MKTAG(0xa9,'p','r','f'): key = "performers"; break;
446 case MKTAG(0xa9,'r','e','q'): key = "playback_requirements"; break;
447 case MKTAG(0xa9,'s','r','c'): key = "original_source"; break;
448 case MKTAG(0xa9,'s','t','3'): key = "subtitle"; break;
449 63 case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
450 62 case MKTAG(0xa9,'t','o','o'): key = "encoder"; break;
451 case MKTAG(0xa9,'t','r','k'): key = "track"; break;
452 case MKTAG(0xa9,'u','r','l'): key = "URL"; break;
453 case MKTAG(0xa9,'w','r','n'): key = "warning"; break;
454 3 case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
455 5 case MKTAG(0xa9,'x','y','z'): key = "location"; break;
456 }
457 7 retry:
458
3/4
✓ Branch 0 taken 361 times.
✓ Branch 1 taken 184 times.
✓ Branch 2 taken 361 times.
✗ Branch 3 not taken.
890 if (c->itunes_metadata && atom.size > 8) {
459 361 int data_size = avio_rb32(pb);
460 361 int tag = avio_rl32(pb);
461
3/6
✓ Branch 0 taken 361 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 361 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 361 times.
✗ Branch 5 not taken.
361 if (tag == MKTAG('d','a','t','a') && data_size <= atom.size && data_size >= 16) {
462 361 data_type = avio_rb32(pb); // type
463 361 avio_rb32(pb); // unknown
464 361 str_size = data_size - 16;
465 361 atom.size -= 16;
466
467
5/6
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 264 times.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 38 times.
✓ Branch 4 taken 59 times.
✗ Branch 5 not taken.
361 if (!key && c->found_hdlr_mdta && c->meta_keys) {
468 59 uint32_t index = av_bswap32(atom.type); // BE number has been read as LE
469
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) {
470 59 key = c->meta_keys[index];
471 } else if (atom.type != MKTAG('c', 'o', 'v', 'r')) {
472 av_log(c->fc, AV_LOG_WARNING,
473 "The index of 'data' is out of range: %"PRId32" < 1 or >= %d.\n",
474 index, c->meta_keys_count);
475 }
476 }
477
4/4
✓ Branch 0 taken 345 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 323 times.
✓ Branch 3 taken 22 times.
361 if (atom.type == MKTAG('c', 'o', 'v', 'r') ||
478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 323 times.
323 (key && !strcmp(key, "com.apple.quicktime.artwork"))) {
479 16 int ret = mov_read_covr(c, pb, data_type, str_size);
480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0) {
481 av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
482 return ret;
483 }
484 16 atom.size -= str_size;
485
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (atom.size > 8)
486 2 goto retry;
487 14 return ret;
488 }
489 } else return 0;
490
8/10
✓ Branch 0 taken 166 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 120 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 46 times.
✓ Branch 6 taken 120 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 109 times.
✓ Branch 9 taken 11 times.
184 } else if (atom.size > 4 && (key || c->export_all) && !c->itunes_metadata && !raw) {
491 109 str_size = avio_rb16(pb); // string length
492
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 104 times.
109 if (str_size > atom.size) {
493 5 raw = 1;
494 5 avio_seek(pb, -2, SEEK_CUR);
495 5 av_log(c->fc, AV_LOG_WARNING, "UDTA parsing failed retrying raw\n");
496 5 goto retry;
497 }
498 104 langcode = avio_rb16(pb);
499 104 ff_mov_lang_to_iso639(langcode, language);
500 104 atom.size -= 4;
501 } else
502 75 str_size = atom.size;
503
504
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 524 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
524 if (c->export_all && !key) {
505 key = av_fourcc_make_string(tmp_key, atom.type);
506 }
507
508
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 438 times.
524 if (!key)
509 86 return 0;
510
2/4
✓ Branch 0 taken 438 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 438 times.
438 if (atom.size < 0 || str_size >= INT_MAX/2)
511 return AVERROR_INVALIDDATA;
512
513 // Allocates enough space if data_type is a int32 or float32 number, otherwise
514 // worst-case requirement for output string in case of utf8 coded input
515
3/4
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 393 times.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
438 num = (data_type >= 21 && data_type <= 23);
516
4/4
✓ Branch 0 taken 393 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 382 times.
✓ Branch 3 taken 11 times.
438 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
517 438 str = av_mallocz(str_size_alloc);
518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 438 times.
438 if (!str)
519 return AVERROR(ENOMEM);
520
521
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 364 times.
438 if (parse)
522 74 parse(c, pb, str_size, key);
523 else {
524
8/10
✓ Branch 0 taken 353 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 353 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 105 times.
✓ Branch 5 taken 248 times.
✓ Branch 6 taken 91 times.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 91 times.
364 if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
525 14 mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
526
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 348 times.
350 } else if (data_type == 21) { // BE signed integer, variable size
527 2 int val = 0;
528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (str_size == 1)
529 val = (int8_t)avio_r8(pb);
530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 2)
531 val = (int16_t)avio_rb16(pb);
532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 3)
533 val = ((int32_t)(avio_rb24(pb)<<8))>>8;
534
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (str_size == 4)
535 2 val = (int32_t)avio_rb32(pb);
536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
537 av_log(c->fc, AV_LOG_ERROR,
538 "Failed to store the number (%d) in string.\n", val);
539 av_free(str);
540 return AVERROR_INVALIDDATA;
541 }
542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348 times.
348 } else if (data_type == 22) { // BE unsigned integer, variable size
543 unsigned int val = 0;
544 if (str_size == 1)
545 val = avio_r8(pb);
546 else if (str_size == 2)
547 val = avio_rb16(pb);
548 else if (str_size == 3)
549 val = avio_rb24(pb);
550 else if (str_size == 4)
551 val = avio_rb32(pb);
552 if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
553 av_log(c->fc, AV_LOG_ERROR,
554 "Failed to store the number (%u) in string.\n", val);
555 av_free(str);
556 return AVERROR_INVALIDDATA;
557 }
558
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 335 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
361 } else if (data_type == 23 && str_size >= 4) { // BE float32
559 13 float val = av_int2float(avio_rb32(pb));
560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
561 av_log(c->fc, AV_LOG_ERROR,
562 "Failed to store the float32 number (%f) in string.\n", val);
563 av_free(str);
564 return AVERROR_INVALIDDATA;
565 }
566
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 335 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
335 } else if (data_type > 1 && data_type != 4) {
567 // data_type can be 0 if not set at all above. data_type 1 means
568 // UTF8 and 4 means "UTF8 sort". For any other type (UTF16 or e.g.
569 // a picture), don't return it blindly in a string that is supposed
570 // to be UTF8 text.
571 av_log(c->fc, AV_LOG_WARNING, "Skipping unhandled metadata %s of type %"PRIu32"\n", key, data_type);
572 av_free(str);
573 return 0;
574 } else {
575 335 int ret = ffio_read_size(pb, str, str_size);
576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 335 times.
335 if (ret < 0) {
577 av_free(str);
578 return ret;
579 }
580 335 str[str_size] = 0;
581 }
582 364 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
583
4/4
✓ Branch 0 taken 249 times.
✓ Branch 1 taken 115 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 248 times.
364 if (c->itunes_metadata && av_dict_get(*metadata, key, NULL, 0))
584 1 av_dict_set(metadata, key, ";", AV_DICT_APPEND);
585
2/2
✓ Branch 0 taken 249 times.
✓ Branch 1 taken 115 times.
364 av_dict_set(metadata, key, str, c->itunes_metadata ? AV_DICT_APPEND : 0);
586
4/4
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 260 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 67 times.
364 if (*language && strcmp(language, "und")) {
587 37 snprintf(key2, sizeof(key2), "%s-%s", key, language);
588 37 av_dict_set(metadata, key2, str, 0);
589 }
590
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 237 times.
364 if (!strcmp(key, "encoder")) {
591 int major, minor, micro;
592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 127 times.
127 if (sscanf(str, "HandBrake %d.%d.%d", &major, &minor, &micro) == 3) {
593 c->handbrake_version = 1000000*major + 1000*minor + micro;
594 }
595 }
596
597 364 atom.size -= str_size;
598 364 av_freep(&str);
599
600 // Read remaining data atoms for multi-valued iTunes tags (e.g. multiple
601 // artists stored as multiple data atoms within one tag atom), consistent
602 // with the existing covr path.
603 // Note: multiple sibling tag atoms with the same key (e.g. three separate
604 // ©ART atoms under ilst) are handled by the AV_DICT_APPEND logic above,
605 // since mov_read_udta_string() is called once per tag atom.
606
3/4
✓ Branch 0 taken 249 times.
✓ Branch 1 taken 115 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 249 times.
364 if (c->itunes_metadata && atom.size > 8)
607 goto retry;
608 }
609
610 438 av_freep(&str);
611 438 return 0;
612 }
613
614 12 static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
615 {
616 int64_t start;
617 int i, nb_chapters, str_len, version;
618 char str[256+1];
619 int ret;
620
621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->ignore_chapters)
622 return 0;
623
624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if ((atom.size -= 5) < 0)
625 return 0;
626
627 12 version = avio_r8(pb);
628 12 avio_rb24(pb);
629
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (version)
630 12 avio_rb32(pb); // ???
631 12 nb_chapters = avio_r8(pb);
632
633
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
30 for (i = 0; i < nb_chapters; i++) {
634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size < 9)
635 return 0;
636
637 18 start = avio_rb64(pb);
638 18 str_len = avio_r8(pb);
639
640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if ((atom.size -= 9+str_len) < 0)
641 return 0;
642
643 18 ret = ffio_read_size(pb, str, str_len);
644
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (ret < 0)
645 return ret;
646 18 str[str_len] = 0;
647 18 avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
648 }
649 12 return 0;
650 }
651
652 #define MIN_DATA_ENTRY_BOX_SIZE 12
653 665 static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
654 {
655 AVStream *st;
656 MOVStreamContext *sc;
657 int entries, i, j;
658
659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (c->fc->nb_streams < 1)
660 return 0;
661 665 st = c->fc->streams[c->fc->nb_streams-1];
662 665 sc = st->priv_data;
663
664 665 avio_rb32(pb); // version + flags
665 665 entries = avio_rb32(pb);
666
1/2
✓ Branch 0 taken 665 times.
✗ Branch 1 not taken.
665 if (!entries ||
667
1/2
✓ Branch 0 taken 665 times.
✗ Branch 1 not taken.
665 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 entries >= UINT_MAX / sizeof(*sc->drefs))
669 return AVERROR_INVALIDDATA;
670
671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 for (i = 0; i < sc->drefs_count; i++) {
672 MOVDref *dref = &sc->drefs[i];
673 av_freep(&dref->path);
674 av_freep(&dref->dir);
675 }
676 665 av_free(sc->drefs);
677 665 sc->drefs_count = 0;
678 665 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (!sc->drefs)
680 return AVERROR(ENOMEM);
681 665 sc->drefs_count = entries;
682
683
2/2
✓ Branch 0 taken 665 times.
✓ Branch 1 taken 665 times.
1330 for (i = 0; i < entries; i++) {
684 665 MOVDref *dref = &sc->drefs[i];
685 665 uint32_t size = avio_rb32(pb);
686 665 int64_t next = avio_tell(pb);
687
688
3/6
✓ Branch 0 taken 665 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 665 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 665 times.
665 if (size < 12 || next < 0 || next > INT64_MAX - size)
689 return AVERROR_INVALIDDATA;
690
691 665 next += size - 4;
692
693 665 dref->type = avio_rl32(pb);
694 665 avio_rb32(pb); // version + flags
695
696
3/4
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 545 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 120 times.
665 if (dref->type == MKTAG('a','l','i','s') && size > 150) {
697 /* macintosh alias record */
698 uint16_t volume_len, len;
699 int16_t type;
700 int ret;
701
702 avio_skip(pb, 10);
703
704 volume_len = avio_r8(pb);
705 volume_len = FFMIN(volume_len, 27);
706 ret = ffio_read_size(pb, dref->volume, 27);
707 if (ret < 0)
708 return ret;
709 dref->volume[volume_len] = 0;
710 av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
711
712 avio_skip(pb, 12);
713
714 len = avio_r8(pb);
715 len = FFMIN(len, 63);
716 ret = ffio_read_size(pb, dref->filename, 63);
717 if (ret < 0)
718 return ret;
719 dref->filename[len] = 0;
720 av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
721
722 avio_skip(pb, 16);
723
724 /* read next level up_from_alias/down_to_target */
725 dref->nlvl_from = avio_rb16(pb);
726 dref->nlvl_to = avio_rb16(pb);
727 av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
728 dref->nlvl_from, dref->nlvl_to);
729
730 avio_skip(pb, 16);
731
732 for (type = 0; type != -1 && avio_tell(pb) < next; ) {
733 if (avio_feof(pb))
734 return AVERROR_EOF;
735 type = avio_rb16(pb);
736 len = avio_rb16(pb);
737 av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
738 if (len&1)
739 len += 1;
740 if (type == 2) { // absolute path
741 av_free(dref->path);
742 dref->path = av_mallocz(len+1);
743 if (!dref->path)
744 return AVERROR(ENOMEM);
745
746 ret = ffio_read_size(pb, dref->path, len);
747 if (ret < 0) {
748 av_freep(&dref->path);
749 return ret;
750 }
751 if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
752 len -= volume_len;
753 memmove(dref->path, dref->path+volume_len, len);
754 dref->path[len] = 0;
755 }
756 // trim string of any ending zeros
757 for (j = len - 1; j >= 0; j--) {
758 if (dref->path[j] == 0)
759 len--;
760 else
761 break;
762 }
763 for (j = 0; j < len; j++)
764 if (dref->path[j] == ':' || dref->path[j] == 0)
765 dref->path[j] = '/';
766 av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
767 } else if (type == 0) { // directory name
768 av_free(dref->dir);
769 dref->dir = av_malloc(len+1);
770 if (!dref->dir)
771 return AVERROR(ENOMEM);
772
773 ret = ffio_read_size(pb, dref->dir, len);
774 if (ret < 0) {
775 av_freep(&dref->dir);
776 return ret;
777 }
778 dref->dir[len] = 0;
779 for (j = 0; j < len; j++)
780 if (dref->dir[j] == ':')
781 dref->dir[j] = '/';
782 av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
783 } else
784 avio_skip(pb, len);
785 }
786 } else {
787 665 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
788 dref->type, size);
789 665 entries--;
790 665 i--;
791 }
792 665 avio_seek(pb, next, SEEK_SET);
793 }
794 665 return 0;
795 }
796
797 1211 static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
798 {
799 AVStream *st;
800 uint32_t type;
801 uint32_t ctype;
802 int64_t title_size;
803 char *title_str;
804 int ret;
805
806 1211 avio_r8(pb); /* version */
807 1211 avio_rb24(pb); /* flags */
808
809 /* component type */
810 1211 ctype = avio_rl32(pb);
811 1211 type = avio_rl32(pb); /* component subtype */
812
813 1211 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
814 1211 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
815
816
2/2
✓ Branch 0 taken 178 times.
✓ Branch 1 taken 1033 times.
1211 if (c->trak_index < 0) { // meta not inside a trak
817
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 167 times.
178 if (type == MKTAG('m','d','t','a')) {
818 11 c->found_hdlr_mdta = 1;
819 }
820 178 return 0;
821 }
822
823 1033 st = c->fc->streams[c->fc->nb_streams-1];
824
825
2/2
✓ Branch 0 taken 334 times.
✓ Branch 1 taken 699 times.
1033 if (type == MKTAG('v','i','d','e'))
826 334 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
827
2/2
✓ Branch 0 taken 275 times.
✓ Branch 1 taken 424 times.
699 else if (type == MKTAG('s','o','u','n'))
828 275 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 424 times.
424 else if (type == MKTAG('m','1','a',' '))
830 st->codecpar->codec_id = AV_CODEC_ID_MP2;
831
2/4
✓ Branch 0 taken 424 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 424 times.
424 else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
832 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
833
834 1033 avio_rb32(pb); /* component manufacture */
835 1033 avio_rb32(pb); /* component flags */
836 1033 avio_rb32(pb); /* component flags mask */
837
838 1033 title_size = atom.size - 24;
839
2/2
✓ Branch 0 taken 1030 times.
✓ Branch 1 taken 3 times.
1033 if (title_size > 0) {
840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1030 times.
1030 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
841 return AVERROR_INVALIDDATA;
842 1030 title_str = av_malloc(title_size + 1); /* Add null terminator */
843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1030 times.
1030 if (!title_str)
844 return AVERROR(ENOMEM);
845
846 1030 ret = ffio_read_size(pb, title_str, title_size);
847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1030 times.
1030 if (ret < 0) {
848 av_freep(&title_str);
849 return ret;
850 }
851 1030 title_str[title_size] = 0;
852
2/2
✓ Branch 0 taken 973 times.
✓ Branch 1 taken 57 times.
1030 if (title_str[0]) {
853
4/4
✓ Branch 0 taken 712 times.
✓ Branch 1 taken 261 times.
✓ Branch 2 taken 710 times.
✓ Branch 3 taken 2 times.
973 int off = (!c->isom && title_str[0] == title_size - 1);
854 // flag added so as to not set stream handler name if already set from mdia->hdlr
855 973 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
856 }
857 1030 av_freep(&title_str);
858 }
859
860 1033 return 0;
861 }
862
863 186 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
864 {
865 186 return ff_mov_read_esds(c->fc, pb);
866 }
867
868 6 static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
869 {
870 AVStream *st;
871 AVPacketSideData *sd;
872 enum AVAudioServiceType *ast;
873 int ac3info, acmod, lfeon, bsmod;
874 uint64_t mask;
875
876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (c->fc->nb_streams < 1)
877 return 0;
878 6 st = c->fc->streams[c->fc->nb_streams-1];
879
880 6 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
881 6 &st->codecpar->nb_coded_side_data,
882 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
883 sizeof(*ast), 0);
884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sd)
885 return AVERROR(ENOMEM);
886
887 6 ast = (enum AVAudioServiceType*)sd->data;
888 6 ac3info = avio_rb24(pb);
889 6 bsmod = (ac3info >> 14) & 0x7;
890 6 acmod = (ac3info >> 11) & 0x7;
891 6 lfeon = (ac3info >> 10) & 0x1;
892
893 6 mask = ff_ac3_channel_layout_tab[acmod];
894
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (lfeon)
895 1 mask |= AV_CH_LOW_FREQUENCY;
896 6 av_channel_layout_uninit(&st->codecpar->ch_layout);
897 6 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
898
899 6 *ast = bsmod;
900
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7)
901 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
902
903 6 return 0;
904 }
905
906 #if CONFIG_IAMFDEC
907 12 static int mov_read_iacb(MOVContext *c, AVIOContext *pb, MOVAtom atom)
908 {
909 AVStream *st;
910 MOVStreamContext *sc;
911 FFIOContext b;
912 AVIOContext *descriptor_pb;
913 AVDictionary *metadata;
914 IAMFContext *iamf;
915 int64_t start_time, duration;
916 unsigned descriptors_size;
917 int nb_frames, disposition;
918 int version, ret;
919
920
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (atom.size < 5)
921 return AVERROR_INVALIDDATA;
922
923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->fc->nb_streams < 1)
924 return 0;
925
926 12 version = avio_r8(pb);
927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (version != 1) {
928 av_log(c->fc, AV_LOG_ERROR, "%s configurationVersion %d",
929 version < 1 ? "invalid" : "unsupported", version);
930 return AVERROR_INVALIDDATA;
931 }
932
933 12 descriptors_size = ffio_read_leb(pb);
934
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (!descriptors_size || descriptors_size > INT_MAX)
935 return AVERROR_INVALIDDATA;
936
937 12 st = c->fc->streams[c->fc->nb_streams - 1];
938 12 sc = st->priv_data;
939
940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->extradata) {
941 av_log(c->fc, AV_LOG_WARNING, "ignoring iacb\n");
942 return 0;
943 }
944
945 12 sc->iamf = av_mallocz(sizeof(*sc->iamf));
946
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!sc->iamf)
947 return AVERROR(ENOMEM);
948 12 iamf = &sc->iamf->iamf;
949
950 12 ret = ff_alloc_extradata(st->codecpar, descriptors_size);
951
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
952 return ret;
953
954 12 ret = avio_read(pb, st->codecpar->extradata, descriptors_size);
955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret != descriptors_size)
956 return ret < 0 ? ret : AVERROR_INVALIDDATA;
957
958 12 ffio_init_read_context(&b, st->codecpar->extradata, descriptors_size);
959 12 descriptor_pb = &b.pub;
960
961 12 ret = ff_iamfdec_read_descriptors(iamf, descriptor_pb, descriptors_size, c->fc);
962
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
963 return ret;
964
965 12 metadata = st->metadata;
966 12 st->metadata = NULL;
967 12 start_time = st->start_time;
968 12 nb_frames = st->nb_frames;
969 12 duration = st->duration;
970 12 disposition = st->disposition;
971
972
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_audio_elements; i++) {
973 12 IAMFAudioElement *audio_element = iamf->audio_elements[i];
974 const AVIAMFAudioElement *element;
975 AVStreamGroup *stg =
976 12 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, NULL);
977
978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!stg) {
979 ret = AVERROR(ENOMEM);
980 goto fail;
981 }
982
983 12 av_iamf_audio_element_free(&stg->params.iamf_audio_element);
984 12 stg->id = audio_element->audio_element_id;
985 /* Transfer ownership */
986 12 element = stg->params.iamf_audio_element = audio_element->element;
987 12 audio_element->element = NULL;
988
989
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < audio_element->nb_substreams; j++) {
990 64 IAMFSubStream *substream = &audio_element->substreams[j];
991 AVStream *stream;
992
993
3/4
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 52 times.
64 if (!i && !j) {
994
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
12 if (audio_element->layers[0].substream_count != 1)
995 2 disposition &= ~AV_DISPOSITION_DEFAULT;
996 12 stream = st;
997 } else
998 52 stream = avformat_new_stream(c->fc, NULL);
999
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (!stream) {
1000 ret = AVERROR(ENOMEM);
1001 goto fail;
1002 }
1003
1004 64 stream->start_time = start_time;
1005 64 stream->nb_frames = nb_frames;
1006 64 stream->duration = duration;
1007 64 stream->disposition = disposition;
1008
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 12 times.
64 if (stream != st) {
1009 52 stream->priv_data = sc;
1010 52 sc->refcount++;
1011 }
1012
1013
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 56 times.
64 if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
1014 8 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1015
3/4
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 12 times.
64 if (i || j) {
1016 52 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1017
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 6 times.
52 if (audio_element->layers[0].substream_count == 1)
1018 46 stream->disposition &= ~AV_DISPOSITION_DEFAULT;
1019 }
1020
1021 64 ret = avcodec_parameters_copy(stream->codecpar, substream->codecpar);
1022
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
1023 goto fail;
1024
1025 64 stream->id = substream->audio_substream_id;
1026
1027 64 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
1028
1029 64 ret = avformat_stream_group_add_stream(stg, stream);
1030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
1031 goto fail;
1032 }
1033
1034 12 ret = av_dict_copy(&stg->metadata, metadata, 0);
1035
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1036 goto fail;
1037 }
1038
1039
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1040 12 IAMFMixPresentation *mix_presentation = iamf->mix_presentations[i];
1041 12 const AVIAMFMixPresentation *mix = mix_presentation->cmix;
1042 AVStreamGroup *stg =
1043 12 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, NULL);
1044
1045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!stg) {
1046 ret = AVERROR(ENOMEM);
1047 goto fail;
1048 }
1049
1050 12 av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
1051 12 stg->id = mix_presentation->mix_presentation_id;
1052 /* Transfer ownership */
1053 12 stg->params.iamf_mix_presentation = mix_presentation->mix;
1054 12 mix_presentation->mix = NULL;
1055
1056
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 12 times.
26 for (int j = 0; j < mix->nb_submixes; j++) {
1057 14 const AVIAMFSubmix *submix = mix->submixes[j];
1058
1059
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
28 for (int k = 0; k < submix->nb_elements; k++) {
1060 14 const AVIAMFSubmixElement *submix_element = submix->elements[k];
1061 14 const AVStreamGroup *audio_element = NULL;
1062
1063
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 for (int l = 0; l < c->fc->nb_stream_groups; l++)
1064
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (c->fc->stream_groups[l]->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT &&
1065
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 c->fc->stream_groups[l]->id == submix_element->audio_element_id) {
1066 14 audio_element = c->fc->stream_groups[l];
1067 14 break;
1068 }
1069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 av_assert0(audio_element);
1070
1071
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 14 times.
80 for (int l = 0; l < audio_element->nb_streams; l++) {
1072 66 ret = avformat_stream_group_add_stream(stg, audio_element->streams[l]);
1073
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
66 if (ret < 0 && ret != AVERROR(EEXIST))
1074 goto fail;
1075 }
1076 }
1077 }
1078
1079 12 ret = av_dict_copy(&stg->metadata, metadata, 0);
1080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1081 goto fail;
1082 }
1083
1084 12 ret = 0;
1085 12 fail:
1086 12 av_dict_free(&metadata);
1087
1088 12 return ret;
1089 }
1090 #endif
1091
1092 5 static int mov_read_srat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1093 {
1094 AVStream *st;
1095 int32_t sample_rate;
1096
1097
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (atom.size < 8 || c->fc->nb_streams < 1)
1098 return 0;
1099
1100 5 st = c->fc->streams[c->fc->nb_streams-1];
1101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
1102 av_log(c->fc, AV_LOG_WARNING, "'srat' within non-audio sample entry, skip\n");
1103 return 0;
1104 }
1105
1106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!c->isom) {
1107 av_log(c->fc, AV_LOG_WARNING, "'srat' within non-isom, skip\n");
1108 return 0;
1109 }
1110
1111 5 avio_skip(pb, 4); // version+flags
1112 5 sample_rate = avio_rb32(pb);
1113
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (sample_rate > 0) {
1114 5 av_log(c->fc, AV_LOG_DEBUG,
1115 "overwrite sample rate from %d to %d by 'srat'\n",
1116 5 st->codecpar->sample_rate, sample_rate);
1117 5 st->codecpar->sample_rate = sample_rate;
1118 } else {
1119 av_log(c->fc, AV_LOG_WARNING,
1120 "ignore invalid sample rate %d in 'srat'\n", sample_rate);
1121 }
1122
1123 5 return 0;
1124 }
1125
1126 2 static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1127 {
1128 AVStream *st;
1129 AVPacketSideData *sd;
1130 enum AVAudioServiceType *ast;
1131 int eac3info, acmod, lfeon, bsmod;
1132 uint64_t mask;
1133
1134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
1135 return 0;
1136 2 st = c->fc->streams[c->fc->nb_streams-1];
1137
1138 2 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1139 2 &st->codecpar->nb_coded_side_data,
1140 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
1141 sizeof(*ast), 0);
1142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!sd)
1143 return AVERROR(ENOMEM);
1144
1145 2 ast = (enum AVAudioServiceType*)sd->data;
1146
1147 /* No need to parse fields for additional independent substreams and its
1148 * associated dependent substreams since libavcodec's E-AC-3 decoder
1149 * does not support them yet. */
1150 2 avio_rb16(pb); /* data_rate and num_ind_sub */
1151 2 eac3info = avio_rb24(pb);
1152 2 bsmod = (eac3info >> 12) & 0x1f;
1153 2 acmod = (eac3info >> 9) & 0x7;
1154 2 lfeon = (eac3info >> 8) & 0x1;
1155
1156 2 mask = ff_ac3_channel_layout_tab[acmod];
1157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (lfeon)
1158 mask |= AV_CH_LOW_FREQUENCY;
1159 2 av_channel_layout_uninit(&st->codecpar->ch_layout);
1160 2 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
1161
1162 2 *ast = bsmod;
1163
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7)
1164 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
1165
1166 2 return 0;
1167 }
1168
1169 static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1170 {
1171 #define DDTS_SIZE 20
1172 uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
1173 AVStream *st = NULL;
1174 uint32_t frame_duration_code = 0;
1175 uint32_t channel_layout_code = 0;
1176 GetBitContext gb;
1177 int ret;
1178
1179 if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
1180 return ret;
1181
1182 init_get_bits(&gb, buf, 8 * DDTS_SIZE);
1183
1184 if (c->fc->nb_streams < 1) {
1185 return 0;
1186 }
1187 st = c->fc->streams[c->fc->nb_streams-1];
1188
1189 st->codecpar->sample_rate = get_bits_long(&gb, 32);
1190 if (st->codecpar->sample_rate <= 0) {
1191 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
1192 return AVERROR_INVALIDDATA;
1193 }
1194 skip_bits_long(&gb, 32); /* max bitrate */
1195 st->codecpar->bit_rate = get_bits_long(&gb, 32);
1196 st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
1197 frame_duration_code = get_bits(&gb, 2);
1198 skip_bits(&gb, 30); /* various fields */
1199 channel_layout_code = get_bits(&gb, 16);
1200
1201 st->codecpar->frame_size =
1202 (frame_duration_code == 0) ? 512 :
1203 (frame_duration_code == 1) ? 1024 :
1204 (frame_duration_code == 2) ? 2048 :
1205 (frame_duration_code == 3) ? 4096 : 0;
1206
1207 if (channel_layout_code > 0xff) {
1208 av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout\n");
1209 }
1210 av_channel_layout_uninit(&st->codecpar->ch_layout);
1211 av_channel_layout_from_mask(&st->codecpar->ch_layout,
1212 ((channel_layout_code & 0x1) ? AV_CH_FRONT_CENTER : 0) |
1213 ((channel_layout_code & 0x2) ? AV_CH_FRONT_LEFT : 0) |
1214 ((channel_layout_code & 0x2) ? AV_CH_FRONT_RIGHT : 0) |
1215 ((channel_layout_code & 0x4) ? AV_CH_SIDE_LEFT : 0) |
1216 ((channel_layout_code & 0x4) ? AV_CH_SIDE_RIGHT : 0) |
1217 ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0));
1218
1219 return 0;
1220 }
1221
1222 50 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1223 {
1224 AVStream *st;
1225
1226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (c->fc->nb_streams < 1)
1227 return 0;
1228 50 st = c->fc->streams[c->fc->nb_streams-1];
1229
1230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (atom.size < 16)
1231 return 0;
1232
1233 /* skip version and flags */
1234 50 avio_skip(pb, 4);
1235
1236 50 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
1237
1238 50 return 0;
1239 }
1240
1241 5 static int mov_read_chnl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1242 {
1243 5 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
1244 int version, flags;
1245 int ret;
1246 AVStream *st;
1247
1248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
1249 return 0;
1250 5 st = c->fc->streams[c->fc->nb_streams-1];
1251
1252 5 version = avio_r8(pb);
1253 5 flags = avio_rb24(pb);
1254
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (version > 1 || flags != 0) {
1255 av_log(c->fc, AV_LOG_WARNING,
1256 "Unsupported 'chnl' box with version %d, flags: %#x\n",
1257 version, flags);
1258 return 0;
1259 }
1260
1261 5 ret = ff_mov_read_chnl(c->fc, pb, st, version);
1262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0) {
1263 avio_seek(pb, end, SEEK_SET);
1264 return 0;
1265 }
1266
1267
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_tell(pb) != end) {
1268 av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data inside chnl\n",
1269 end - avio_tell(pb));
1270 avio_seek(pb, end, SEEK_SET);
1271 }
1272 5 return ret;
1273 }
1274
1275 2 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1276 {
1277 AVStream *st;
1278 int ret;
1279
1280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
1281 return 0;
1282 2 st = c->fc->streams[c->fc->nb_streams-1];
1283
1284
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)
1285 av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
1286
1287 2 return ret;
1288 }
1289
1290 18 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1291 {
1292 AVStream *st;
1293 HEIFItem *item;
1294 AVPacketSideData *sd;
1295 18 int width, height, err = 0;
1296 AVRational aperture_width, aperture_height, horiz_off, vert_off;
1297 AVRational pc_x, pc_y;
1298 uint64_t top, bottom, left, right;
1299
1300 18 item = get_heif_item(c, c->cur_item_id);
1301 18 st = get_curr_st(c);
1302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!st)
1303 return 0;
1304
1305 18 width = st->codecpar->width;
1306 18 height = st->codecpar->height;
1307
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) {
1308 6 width = item->width;
1309 6 height = item->height;
1310 }
1311
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (!width || !height) {
1312 err = AVERROR_INVALIDDATA;
1313 goto fail;
1314 }
1315
1316 18 aperture_width.num = avio_rb32(pb);
1317 18 aperture_width.den = avio_rb32(pb);
1318 18 aperture_height.num = avio_rb32(pb);
1319 18 aperture_height.den = avio_rb32(pb);
1320
1321 18 horiz_off.num = avio_rb32(pb);
1322 18 horiz_off.den = avio_rb32(pb);
1323 18 vert_off.num = avio_rb32(pb);
1324 18 vert_off.den = avio_rb32(pb);
1325
1326
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 ||
1327
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 ||
1328
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) {
1329 err = AVERROR_INVALIDDATA;
1330 goto fail;
1331 }
1332
3/4
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
33 if ((av_cmp_q((AVRational) { width, 1 }, aperture_width) < 0) ||
1333 15 (av_cmp_q((AVRational) { height, 1 }, aperture_height) < 0)) {
1334 3 err = AVERROR_INVALIDDATA;
1335 3 goto fail;
1336 }
1337 15 av_log(c->fc, AV_LOG_TRACE, "clap: apertureWidth %d/%d, apertureHeight %d/%d "
1338 "horizOff %d/%d vertOff %d/%d\n",
1339 aperture_width.num, aperture_width.den, aperture_height.num, aperture_height.den,
1340 horiz_off.num, horiz_off.den, vert_off.num, vert_off.den);
1341
1342 15 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1343 15 pc_x = av_add_q(pc_x, horiz_off);
1344 15 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1345 15 pc_y = av_add_q(pc_y, vert_off);
1346
1347 15 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1348 15 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1349 15 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1350 15 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1351
1352 15 left = av_q2d(av_sub_q(pc_x, aperture_width));
1353 15 right = av_q2d(av_add_q(pc_x, aperture_width));
1354 15 top = av_q2d(av_sub_q(pc_y, aperture_height));
1355 15 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1356
1357
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (bottom > (height - 1) ||
1358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 right > (width - 1)) {
1359 err = AVERROR_INVALIDDATA;
1360 goto fail;
1361 }
1362
1363 15 bottom = height - 1 - bottom;
1364 15 right = width - 1 - right;
1365
1366
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
15 if (!(left | right | top | bottom))
1367 6 return 0;
1368
1369
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if ((left + right) >= width ||
1370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 (top + bottom) >= height) {
1371 err = AVERROR_INVALIDDATA;
1372 goto fail;
1373 }
1374
1375 9 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1376 9 &st->codecpar->nb_coded_side_data,
1377 AV_PKT_DATA_FRAME_CROPPING,
1378 sizeof(uint32_t) * 4, 0);
1379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sd)
1380 return AVERROR(ENOMEM);
1381
1382 9 AV_WL32A(sd->data, top);
1383 9 AV_WL32A(sd->data + 4, bottom);
1384 9 AV_WL32A(sd->data + 8, left);
1385 9 AV_WL32A(sd->data + 12, right);
1386
1387 12 fail:
1388
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 if (err < 0) {
1389 3 int explode = !!(c->fc->error_recognition & AV_EF_EXPLODE);
1390
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");
1391
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!explode)
1392 3 err = 0;
1393 }
1394
1395 12 return err;
1396 }
1397
1398 /* This atom overrides any previously set aspect ratio */
1399 88 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1400 {
1401 88 const int num = avio_rb32(pb);
1402 88 const int den = avio_rb32(pb);
1403 AVStream *st;
1404 MOVStreamContext *sc;
1405
1406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (c->fc->nb_streams < 1)
1407 return 0;
1408 88 st = c->fc->streams[c->fc->nb_streams-1];
1409 88 sc = st->priv_data;
1410
1411 88 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1412
1413
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 2 times.
88 if (den != 0) {
1414 86 sc->h_spacing = num;
1415 86 sc->v_spacing = den;
1416 }
1417 88 return 0;
1418 }
1419
1420 /* this atom contains actual media data */
1421 1019 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1422 {
1423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1019 times.
1019 if (atom.size == 0) /* wrong one (MP4) */
1424 return 0;
1425 1019 c->found_mdat=1;
1426 1019 return 0; /* now go for moov */
1427 }
1428
1429 #define DRM_BLOB_SIZE 56
1430
1431 static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1432 {
1433 uint8_t intermediate_key[20];
1434 uint8_t intermediate_iv[20];
1435 uint8_t input[64];
1436 uint8_t output[64];
1437 uint8_t file_checksum[20];
1438 uint8_t calculated_checksum[20];
1439 char checksum_string[2 * sizeof(file_checksum) + 1];
1440 struct AVSHA *sha;
1441 int i;
1442 int ret = 0;
1443 uint8_t *activation_bytes = c->activation_bytes;
1444 uint8_t *fixed_key = c->audible_fixed_key;
1445
1446 c->aax_mode = 1;
1447
1448 sha = av_sha_alloc();
1449 if (!sha)
1450 return AVERROR(ENOMEM);
1451 av_free(c->aes_decrypt);
1452 c->aes_decrypt = av_aes_alloc();
1453 if (!c->aes_decrypt) {
1454 ret = AVERROR(ENOMEM);
1455 goto fail;
1456 }
1457
1458 /* drm blob processing */
1459 avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1460 avio_read(pb, input, DRM_BLOB_SIZE);
1461 avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1462 ret = ffio_read_size(pb, file_checksum, 20);
1463 if (ret < 0)
1464 goto fail;
1465
1466 // required by external tools
1467 ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1);
1468 av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string);
1469
1470 /* verify activation data */
1471 if (!activation_bytes) {
1472 av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1473 ret = 0; /* allow ffprobe to continue working on .aax files */
1474 goto fail;
1475 }
1476 if (c->activation_bytes_size != 4) {
1477 av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1478 ret = AVERROR(EINVAL);
1479 goto fail;
1480 }
1481
1482 /* verify fixed key */
1483 if (c->audible_fixed_key_size != 16) {
1484 av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1485 ret = AVERROR(EINVAL);
1486 goto fail;
1487 }
1488
1489 /* AAX (and AAX+) key derivation */
1490 av_sha_init(sha, 160);
1491 av_sha_update(sha, fixed_key, 16);
1492 av_sha_update(sha, activation_bytes, 4);
1493 av_sha_final(sha, intermediate_key);
1494 av_sha_init(sha, 160);
1495 av_sha_update(sha, fixed_key, 16);
1496 av_sha_update(sha, intermediate_key, 20);
1497 av_sha_update(sha, activation_bytes, 4);
1498 av_sha_final(sha, intermediate_iv);
1499 av_sha_init(sha, 160);
1500 av_sha_update(sha, intermediate_key, 16);
1501 av_sha_update(sha, intermediate_iv, 16);
1502 av_sha_final(sha, calculated_checksum);
1503 if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1504 av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1505 ret = AVERROR_INVALIDDATA;
1506 goto fail;
1507 }
1508 av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1509 av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1510 for (i = 0; i < 4; i++) {
1511 // file data (in output) is stored in big-endian mode
1512 if (activation_bytes[i] != output[3 - i]) { // critical error
1513 av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1514 ret = AVERROR_INVALIDDATA;
1515 goto fail;
1516 }
1517 }
1518 memcpy(c->file_key, output + 8, 16);
1519 memcpy(input, output + 26, 16);
1520 av_sha_init(sha, 160);
1521 av_sha_update(sha, input, 16);
1522 av_sha_update(sha, c->file_key, 16);
1523 av_sha_update(sha, fixed_key, 16);
1524 av_sha_final(sha, c->file_iv);
1525
1526 fail:
1527 av_free(sha);
1528
1529 return ret;
1530 }
1531
1532 static int mov_aaxc_crypto(MOVContext *c)
1533 {
1534 if (c->audible_key_size != 16) {
1535 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n");
1536 return AVERROR(EINVAL);
1537 }
1538
1539 if (c->audible_iv_size != 16) {
1540 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n");
1541 return AVERROR(EINVAL);
1542 }
1543
1544 c->aes_decrypt = av_aes_alloc();
1545 if (!c->aes_decrypt) {
1546 return AVERROR(ENOMEM);
1547 }
1548
1549 memcpy(c->file_key, c->audible_key, 16);
1550 memcpy(c->file_iv, c->audible_iv, 16);
1551 c->aax_mode = 1;
1552
1553 return 0;
1554 }
1555
1556 // Audible AAX (and AAX+) bytestream decryption
1557 static int aax_filter(uint8_t *input, int size, MOVContext *c)
1558 {
1559 int blocks = 0;
1560 unsigned char iv[16];
1561
1562 memcpy(iv, c->file_iv, 16); // iv is overwritten
1563 blocks = size >> 4; // trailing bytes are not encrypted!
1564 av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1565 av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1566
1567 return 0;
1568 }
1569
1570 /* read major brand, minor version and compatible brands and store them as metadata */
1571 519 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1572 {
1573 uint32_t minor_ver;
1574 int comp_brand_size;
1575 char* comp_brands_str;
1576 519 uint8_t type[5] = {0};
1577 519 int ret = ffio_read_size(pb, type, 4);
1578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 519 times.
519 if (ret < 0)
1579 return ret;
1580
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 519 times.
519 if (c->fc->nb_streams) {
1581 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1582 return AVERROR_INVALIDDATA;
1583 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate FTYP\n");
1584 return 0;
1585 }
1586
1587
2/2
✓ Branch 0 taken 278 times.
✓ Branch 1 taken 241 times.
519 if (strcmp(type, "qt "))
1588 278 c->isom = 1;
1589 519 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1590 519 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1591 519 minor_ver = avio_rb32(pb); /* minor version */
1592 519 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1593
1594 519 comp_brand_size = atom.size - 8;
1595
2/4
✓ Branch 0 taken 519 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 519 times.
519 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1596 return AVERROR_INVALIDDATA;
1597 519 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 519 times.
519 if (!comp_brands_str)
1599 return AVERROR(ENOMEM);
1600
1601 519 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 519 times.
519 if (ret < 0) {
1603 av_freep(&comp_brands_str);
1604 return ret;
1605 }
1606 519 comp_brands_str[comp_brand_size] = 0;
1607 519 av_dict_set(&c->fc->metadata, "compatible_brands",
1608 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1609
1610 // Logic for handling Audible's .aaxc files
1611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 519 times.
519 if (!strcmp(type, "aaxc")) {
1612 mov_aaxc_crypto(c);
1613 }
1614
1615 519 return 0;
1616 }
1617
1618 /* this atom should contain all header atoms */
1619 547 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1620 {
1621 int ret;
1622
1623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 547 times.
547 if (c->found_moov) {
1624 av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1625 avio_skip(pb, atom.size);
1626 return 0;
1627 }
1628
1629
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 547 times.
547 if ((ret = mov_read_default(c, pb, atom)) < 0)
1630 return ret;
1631 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1632 /* so we don't parse the whole file if over a network */
1633 547 c->found_moov=1;
1634 547 return 0; /* now go for mdat */
1635 }
1636
1637 3205 static MOVFragmentStreamInfo * get_frag_stream_info(
1638 MOVFragmentIndex *frag_index,
1639 int index,
1640 int id)
1641 {
1642 int i;
1643 MOVFragmentIndexItem * item;
1644
1645
2/4
✓ Branch 0 taken 3205 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3205 times.
3205 if (index < 0 || index >= frag_index->nb_items)
1646 return NULL;
1647 3205 item = &frag_index->item[index];
1648
1/2
✓ Branch 0 taken 3389 times.
✗ Branch 1 not taken.
3389 for (i = 0; i < item->nb_stream_info; i++)
1649
2/2
✓ Branch 0 taken 3205 times.
✓ Branch 1 taken 184 times.
3389 if (item->stream_info[i].id == id)
1650 3205 return &item->stream_info[i];
1651
1652 // This shouldn't happen
1653 return NULL;
1654 }
1655
1656 499 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1657 {
1658 int i;
1659 MOVFragmentIndexItem * item;
1660
1661
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_index->current < 0 ||
1662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 frag_index->current >= frag_index->nb_items)
1663 return;
1664
1665 499 item = &frag_index->item[frag_index->current];
1666
1/2
✓ Branch 0 taken 558 times.
✗ Branch 1 not taken.
558 for (i = 0; i < item->nb_stream_info; i++)
1667
2/2
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 59 times.
558 if (item->stream_info[i].id == id) {
1668 499 item->current = i;
1669 499 return;
1670 }
1671
1672 // id not found. This shouldn't happen.
1673 item->current = -1;
1674 }
1675
1676 1436 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1677 MOVFragmentIndex *frag_index)
1678 {
1679 MOVFragmentIndexItem *item;
1680
1/2
✓ Branch 0 taken 1436 times.
✗ Branch 1 not taken.
1436 if (frag_index->current < 0 ||
1681
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1430 times.
1436 frag_index->current >= frag_index->nb_items)
1682 6 return NULL;
1683
1684 1430 item = &frag_index->item[frag_index->current];
1685
2/4
✓ Branch 0 taken 1430 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1430 times.
✗ Branch 3 not taken.
1430 if (item->current >= 0 && item->current < item->nb_stream_info)
1686 1430 return &item->stream_info[item->current];
1687
1688 // This shouldn't happen
1689 return NULL;
1690 }
1691
1692 899 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1693 {
1694 int a, b, m;
1695 int64_t moof_offset;
1696
1697 // Optimize for appending new entries
1698
2/2
✓ Branch 0 taken 881 times.
✓ Branch 1 taken 18 times.
899 if (!frag_index->nb_items ||
1699
2/2
✓ Branch 0 taken 464 times.
✓ Branch 1 taken 417 times.
881 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1700 482 return frag_index->nb_items;
1701
1702 417 a = -1;
1703 417 b = frag_index->nb_items;
1704
1705
2/2
✓ Branch 0 taken 2677 times.
✓ Branch 1 taken 417 times.
3094 while (b - a > 1) {
1706 2677 m = (a + b) >> 1;
1707 2677 moof_offset = frag_index->item[m].moof_offset;
1708
2/2
✓ Branch 0 taken 747 times.
✓ Branch 1 taken 1930 times.
2677 if (moof_offset >= offset)
1709 747 b = m;
1710
2/2
✓ Branch 0 taken 2345 times.
✓ Branch 1 taken 332 times.
2677 if (moof_offset <= offset)
1711 2345 a = m;
1712 }
1713 417 return b;
1714 }
1715
1716 7 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1717 {
1718
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 av_assert0(frag_stream_info);
1719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1720 return frag_stream_info->sidx_pts;
1721
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1722 4 return frag_stream_info->first_tfra_pts;
1723 3 return frag_stream_info->tfdt_dts;
1724 }
1725
1726 226 static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1727 MOVFragmentIndex *frag_index, int index)
1728 {
1729 MOVFragmentStreamInfo * frag_stream_info;
1730 226 MOVStreamContext *sc = dst_st->priv_data;
1731 int64_t timestamp;
1732 int i, j;
1733
1734 // If the stream is referenced by any sidx, limit the search
1735 // to fragments that referenced this stream in the sidx
1736
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 7 times.
226 if (sc->has_sidx) {
1737 219 frag_stream_info = get_frag_stream_info(frag_index, index, sc->id);
1738
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!frag_stream_info)
1739 return AV_NOPTS_VALUE;
1740
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1741 219 return frag_stream_info->sidx_pts;
1742 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1743 return frag_stream_info->first_tfra_pts;
1744 return frag_stream_info->sidx_pts;
1745 }
1746
1747
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 3 times.
15 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
1748
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7 times.
12 if (dst_st->id != frag_index->item[index].stream_info[i].id)
1749 5 continue;
1750 7 AVStream *frag_stream = NULL;
1751 7 frag_stream_info = &frag_index->item[index].stream_info[i];
1752
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
21 for (j = 0; j < s->nb_streams; j++) {
1753 14 MOVStreamContext *sc2 = s->streams[j]->priv_data;
1754
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (sc2->id == frag_stream_info->id)
1755 7 frag_stream = s->streams[j];
1756 }
1757
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!frag_stream) {
1758 av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1759 continue;
1760 }
1761 7 timestamp = get_stream_info_time(frag_stream_info);
1762
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (timestamp != AV_NOPTS_VALUE)
1763 4 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1764 }
1765 3 return AV_NOPTS_VALUE;
1766 }
1767
1768 28 static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1769 AVStream *st, int64_t timestamp)
1770 {
1771 int a, b, m, m0;
1772 int64_t frag_time;
1773
1774 28 a = -1;
1775 28 b = frag_index->nb_items;
1776
1777
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 28 times.
252 while (b - a > 1) {
1778 224 m0 = m = (a + b) >> 1;
1779
1780
4/4
✓ Branch 0 taken 226 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 223 times.
453 while (m < b &&
1781 226 (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
1782 3 m++;
1783
1784
4/4
✓ Branch 0 taken 223 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 95 times.
✓ Branch 3 taken 128 times.
224 if (m < b && frag_time <= timestamp)
1785 95 a = m;
1786 else
1787 129 b = m0;
1788 }
1789
1790 28 return a;
1791 }
1792
1793 851 static int update_frag_index(MOVContext *c, int64_t offset)
1794 {
1795 int index, i;
1796 MOVFragmentIndexItem * item;
1797 MOVFragmentStreamInfo * frag_stream_info;
1798
1799 // If moof_offset already exists in frag_index, return index to it
1800 851 index = search_frag_moof_offset(&c->frag_index, offset);
1801
2/2
✓ Branch 0 taken 376 times.
✓ Branch 1 taken 475 times.
851 if (index < c->frag_index.nb_items &&
1802
2/2
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 2 times.
376 c->frag_index.item[index].moof_offset == offset)
1803 374 return index;
1804
1805 // offset is not yet in frag index.
1806 // Insert new item at index (sorted by moof offset)
1807 477 item = av_fast_realloc(c->frag_index.item,
1808 477 &c->frag_index.allocated_size,
1809 477 (c->frag_index.nb_items + 1) *
1810 sizeof(*c->frag_index.item));
1811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 477 times.
477 if (!item)
1812 return -1;
1813 477 c->frag_index.item = item;
1814
1815 477 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1816 sizeof(*item->stream_info));
1817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 477 times.
477 if (!frag_stream_info)
1818 return -1;
1819
1820
2/2
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 477 times.
1056 for (i = 0; i < c->fc->nb_streams; i++) {
1821 // Avoid building frag index if streams lack track id.
1822 579 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 579 times.
579 if (sc->id < 0) {
1824 av_free(frag_stream_info);
1825 return AVERROR_INVALIDDATA;
1826 }
1827
1828 579 frag_stream_info[i].id = sc->id;
1829 579 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1830 579 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1831 579 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1832 579 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1833 579 frag_stream_info[i].index_base = -1;
1834 579 frag_stream_info[i].index_entry = -1;
1835 579 frag_stream_info[i].encryption_index = NULL;
1836 579 frag_stream_info[i].stsd_id = -1;
1837 }
1838
1839
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 475 times.
477 if (index < c->frag_index.nb_items)
1840 2 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1841 2 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1842
1843 477 item = &c->frag_index.item[index];
1844 477 item->headers_read = 0;
1845 477 item->current = 0;
1846 477 item->nb_stream_info = c->fc->nb_streams;
1847 477 item->moof_offset = offset;
1848 477 item->stream_info = frag_stream_info;
1849 477 c->frag_index.nb_items++;
1850
1851 477 return index;
1852 }
1853
1854 499 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1855 int id, int entries)
1856 {
1857 int i;
1858 MOVFragmentStreamInfo * frag_stream_info;
1859
1860
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (index < 0)
1861 499 return;
1862 for (i = index; i < frag_index->nb_items; i++) {
1863 frag_stream_info = get_frag_stream_info(frag_index, i, id);
1864 if (frag_stream_info && frag_stream_info->index_entry >= 0)
1865 frag_stream_info->index_entry += entries;
1866 }
1867 }
1868
1869 473 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1870 {
1871 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1872 473 c->fragment.found_tfhd = 0;
1873
1874
4/4
✓ Branch 0 taken 471 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 470 times.
473 if (!c->has_looked_for_mfra && c->use_mfra_for > 0) {
1875 1 c->has_looked_for_mfra = 1;
1876
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1877 int ret;
1878 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1879 "for a mfra\n");
1880
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((ret = mov_read_mfra(c, pb)) < 0) {
1881 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1882 "read the mfra (may be a live ismv)\n");
1883 }
1884 } else {
1885 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1886 "seekable, can not look for mfra\n");
1887 }
1888 }
1889 473 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1890 473 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1891 473 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1892 473 return mov_read_default(c, pb, atom);
1893 }
1894
1895 1209 static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version)
1896 {
1897 int64_t time;
1898
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1194 times.
1209 if (version == 1) {
1899 15 time = avio_rb64(pb);
1900 15 avio_rb64(pb);
1901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (time < 0) {
1902 av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n");
1903 return;
1904 }
1905 } else {
1906 1194 time = avio_rb32(pb);
1907 1194 avio_rb32(pb); /* modification time */
1908
4/4
✓ Branch 0 taken 573 times.
✓ Branch 1 taken 621 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 525 times.
1194 if (time > 0 && time < 2082844800) {
1909 48 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1910 48 time += 2082844800;
1911 }
1912 }
1913
2/2
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 630 times.
1209 if (time) {
1914 579 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1915
1916
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 579 times.
579 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1917 av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n");
1918 return;
1919 }
1920
1921 579 ff_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1922 }
1923 }
1924
1925 665 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1926 {
1927 AVStream *st;
1928 MOVStreamContext *sc;
1929 int version;
1930 665 char language[4] = {0};
1931 unsigned lang;
1932
1933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (c->fc->nb_streams < 1)
1934 return 0;
1935 665 st = c->fc->streams[c->fc->nb_streams-1];
1936 665 sc = st->priv_data;
1937
1938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (sc->time_scale) {
1939 av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
1940 return AVERROR_INVALIDDATA;
1941 }
1942
1943 665 version = avio_r8(pb);
1944
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (version > 1) {
1945 avpriv_request_sample(c->fc, "Version %d", version);
1946 return AVERROR_PATCHWELCOME;
1947 }
1948 665 avio_rb24(pb); /* flags */
1949 665 mov_metadata_creation_time(c, pb, &st->metadata, version);
1950
1951 665 sc->time_scale = avio_rb32(pb);
1952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (sc->time_scale <= 0) {
1953 av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
1954 sc->time_scale = 1;
1955 }
1956
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 652 times.
665 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1957
1958
6/6
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 652 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 652 times.
✓ Branch 5 taken 4 times.
665 if ((version == 1 && st->duration == UINT64_MAX) ||
1959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 652 times.
652 (version != 1 && st->duration == UINT32_MAX)) {
1960 9 st->duration = 0;
1961 }
1962
1963 665 lang = avio_rb16(pb); /* language */
1964
2/2
✓ Branch 1 taken 492 times.
✓ Branch 2 taken 173 times.
665 if (ff_mov_lang_to_iso639(lang, language))
1965 492 av_dict_set(&st->metadata, "language", language, 0);
1966 665 avio_rb16(pb); /* quality */
1967
1968 665 return 0;
1969 }
1970
1971 544 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1972 {
1973 int i;
1974 544 int version = avio_r8(pb); /* version */
1975 544 avio_rb24(pb); /* flags */
1976
1977 544 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
1978 544 c->time_scale = avio_rb32(pb); /* time scale */
1979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 544 times.
544 if (c->time_scale <= 0) {
1980 av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
1981 c->time_scale = 1;
1982 }
1983 544 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
1984
1985
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 542 times.
544 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1986 544 avio_rb32(pb); /* preferred scale */
1987
1988 544 avio_rb16(pb); /* preferred volume */
1989
1990 544 avio_skip(pb, 10); /* reserved */
1991
1992 /* movie display matrix, store it in main context and use it later on */
1993
2/2
✓ Branch 0 taken 1632 times.
✓ Branch 1 taken 544 times.
2176 for (i = 0; i < 3; i++) {
1994 1632 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
1995 1632 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
1996 1632 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
1997 }
1998
1999 544 avio_rb32(pb); /* preview time */
2000 544 avio_rb32(pb); /* preview duration */
2001 544 avio_rb32(pb); /* poster time */
2002 544 avio_rb32(pb); /* selection time */
2003 544 avio_rb32(pb); /* selection duration */
2004 544 avio_rb32(pb); /* current time */
2005 544 avio_rb32(pb); /* next track ID */
2006
2007 544 return 0;
2008 }
2009
2010 7 static void set_last_stream_little_endian(AVFormatContext *fc)
2011 {
2012 AVStream *st;
2013
2014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (fc->nb_streams < 1)
2015 return;
2016 7 st = fc->streams[fc->nb_streams-1];
2017
2018
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) {
2019 5 case AV_CODEC_ID_PCM_S16BE:
2020 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2021 5 break;
2022 1 case AV_CODEC_ID_PCM_S24BE:
2023 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
2024 1 break;
2025 case AV_CODEC_ID_PCM_S32BE:
2026 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
2027 break;
2028 1 case AV_CODEC_ID_PCM_F32BE:
2029 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
2030 1 break;
2031 case AV_CODEC_ID_PCM_F64BE:
2032 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
2033 break;
2034 default:
2035 break;
2036 }
2037 }
2038
2039 5 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2040 {
2041 5 int little_endian = avio_rb16(pb) & 0xFF;
2042 5 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
2043
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (little_endian == 1)
2044 1 set_last_stream_little_endian(c->fc);
2045 5 return 0;
2046 }
2047
2048 6 static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2049 {
2050 int format_flags;
2051 int version, flags;
2052 int pcm_sample_size;
2053 6 AVFormatContext *fc = c->fc;
2054 AVStream *st;
2055 MOVStreamContext *sc;
2056
2057
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 6) {
2058 av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n");
2059 return AVERROR_INVALIDDATA;
2060 }
2061
2062 6 version = avio_r8(pb);
2063 6 flags = avio_rb24(pb);
2064
2065
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) {
2066 av_log(c->fc, AV_LOG_ERROR,
2067 "Unsupported 'pcmC' box with version %d, flags: %x",
2068 version, flags);
2069 return AVERROR_INVALIDDATA;
2070 }
2071
2072 6 format_flags = avio_r8(pb);
2073 6 pcm_sample_size = avio_r8(pb);
2074
2075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fc->nb_streams < 1)
2076 return AVERROR_INVALIDDATA;
2077
2078 6 st = fc->streams[fc->nb_streams - 1];
2079 6 sc = st->priv_data;
2080
2081
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (sc->format == MOV_MP4_FPCM_TAG) {
2082
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (pcm_sample_size) {
2083 1 case 32:
2084 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE;
2085 1 break;
2086 case 64:
2087 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE;
2088 break;
2089 default:
2090 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2091 pcm_sample_size,
2092 av_fourcc2str(sc->format));
2093 return AVERROR_INVALIDDATA;
2094 }
2095
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (sc->format == MOV_MP4_IPCM_TAG) {
2096
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 switch (pcm_sample_size) {
2097 5 case 16:
2098 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2099 5 break;
2100 case 24:
2101 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
2102 break;
2103 case 32:
2104 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
2105 break;
2106 default:
2107 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2108 pcm_sample_size,
2109 av_fourcc2str(sc->format));
2110 return AVERROR_INVALIDDATA;
2111 }
2112 } else {
2113 av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n",
2114 av_fourcc2str(sc->format));
2115 return AVERROR_INVALIDDATA;
2116 }
2117
2118
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
2119 6 set_last_stream_little_endian(c->fc);
2120 6 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2121
2122 6 return 0;
2123 }
2124
2125 54 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2126 {
2127 AVStream *st;
2128 54 HEIFItem *item = NULL;
2129 54 char color_parameter_type[5] = { 0 };
2130 uint16_t color_primaries, color_trc, color_matrix;
2131 int ret;
2132
2133 54 st = get_curr_st(c);
2134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (!st) {
2135 item = get_heif_item(c, c->cur_item_id);
2136 if (!item)
2137 return 0;
2138 }
2139
2140 54 ret = ffio_read_size(pb, color_parameter_type, 4);
2141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (ret < 0)
2142 return ret;
2143
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 21 times.
54 if (strncmp(color_parameter_type, "nclx", 4) &&
2144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 strncmp(color_parameter_type, "nclc", 4) &&
2145 strncmp(color_parameter_type, "prof", 4)) {
2146 av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
2147 color_parameter_type);
2148 return 0;
2149 }
2150
2151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (!strncmp(color_parameter_type, "prof", 4)) {
2152 AVPacketSideData *sd;
2153 uint8_t *icc_profile;
2154 if (st) {
2155 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
2156 &st->codecpar->nb_coded_side_data,
2157 AV_PKT_DATA_ICC_PROFILE,
2158 atom.size - 4, 0);
2159 if (!sd)
2160 return AVERROR(ENOMEM);
2161 icc_profile = sd->data;
2162 } else {
2163 if (c->heif_icc_profile_items >= c->fc->max_streams) {
2164 av_log(c->fc, AV_LOG_WARNING,
2165 "HEIF ICC profile copies exceed cap %d; ignoring further items\n",
2166 c->fc->max_streams);
2167 return 0;
2168 }
2169 av_freep(&item->icc_profile);
2170 icc_profile = item->icc_profile = av_malloc(atom.size - 4);
2171 if (!icc_profile) {
2172 item->icc_profile_size = 0;
2173 return AVERROR(ENOMEM);
2174 }
2175 item->icc_profile_size = atom.size - 4;
2176 c->heif_icc_profile_items++;
2177 }
2178 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
2179 if (ret < 0)
2180 return ret;
2181
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 } else if (st) {
2182 54 color_primaries = avio_rb16(pb);
2183 54 color_trc = avio_rb16(pb);
2184 54 color_matrix = avio_rb16(pb);
2185
2186 54 av_log(c->fc, AV_LOG_TRACE,
2187 "%s: pri %d trc %d matrix %d",
2188 color_parameter_type, color_primaries, color_trc, color_matrix);
2189
2190
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 33 times.
54 if (!strncmp(color_parameter_type, "nclx", 4)) {
2191 21 uint8_t color_range = avio_r8(pb) >> 7;
2192 21 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2193
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 19 times.
21 if (color_range)
2194 2 st->codecpar->color_range = AVCOL_RANGE_JPEG;
2195 else
2196 19 st->codecpar->color_range = AVCOL_RANGE_MPEG;
2197 }
2198
2199
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
54 if (!av_color_primaries_name(color_primaries))
2200 color_primaries = AVCOL_PRI_UNSPECIFIED;
2201
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
54 if (!av_color_transfer_name(color_trc))
2202 color_trc = AVCOL_TRC_UNSPECIFIED;
2203
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
54 if (!av_color_space_name(color_matrix))
2204 color_matrix = AVCOL_SPC_UNSPECIFIED;
2205
2206 54 st->codecpar->color_primaries = color_primaries;
2207 54 st->codecpar->color_trc = color_trc;
2208 54 st->codecpar->color_space = color_matrix;
2209 54 av_log(c->fc, AV_LOG_TRACE, "\n");
2210 }
2211 54 return 0;
2212 }
2213
2214 118 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2215 {
2216 AVStream *st;
2217 unsigned mov_field_order;
2218 118 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2219
2220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (c->fc->nb_streams < 1) // will happen with jp2 files
2221 return 0;
2222 118 st = c->fc->streams[c->fc->nb_streams-1];
2223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (atom.size < 2)
2224 return AVERROR_INVALIDDATA;
2225 118 mov_field_order = avio_rb16(pb);
2226
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 22 times.
118 if ((mov_field_order & 0xFF00) == 0x0100)
2227 96 decoded_field_order = AV_FIELD_PROGRESSIVE;
2228
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 else if ((mov_field_order & 0xFF00) == 0x0200) {
2229
3/5
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
22 switch (mov_field_order & 0xFF) {
2230 1 case 0x01: decoded_field_order = AV_FIELD_TT;
2231 1 break;
2232 case 0x06: decoded_field_order = AV_FIELD_BB;
2233 break;
2234 1 case 0x09: decoded_field_order = AV_FIELD_TB;
2235 1 break;
2236 20 case 0x0E: decoded_field_order = AV_FIELD_BT;
2237 20 break;
2238 }
2239 }
2240
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
118 if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) {
2241 av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
2242 }
2243 118 st->codecpar->field_order = decoded_field_order;
2244
2245 118 return 0;
2246 }
2247
2248 69 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
2249 {
2250 69 int err = 0;
2251 69 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
2252
2/4
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
69 if (size > INT_MAX || (uint64_t)atom.size > INT_MAX)
2253 return AVERROR_INVALIDDATA;
2254
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
69 if ((err = av_reallocp(&par->extradata, size)) < 0) {
2255 par->extradata_size = 0;
2256 return err;
2257 }
2258 69 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
2259 69 return 0;
2260 }
2261
2262 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
2263 65 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2264 AVCodecParameters *par, uint8_t *buf)
2265 {
2266 65 int64_t result = atom.size;
2267 int err;
2268
2269 65 AV_WB32(buf , atom.size + 8);
2270 65 AV_WL32(buf + 4, atom.type);
2271 65 err = ffio_read_size(pb, buf + 8, atom.size);
2272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (err < 0) {
2273 par->extradata_size -= atom.size;
2274 return err;
2275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 } else if (err < atom.size) {
2276 av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
2277 par->extradata_size -= atom.size - err;
2278 result = err;
2279 }
2280 65 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2281 65 return result;
2282 }
2283
2284 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
2285 58 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2286 enum AVCodecID codec_id)
2287 {
2288 AVStream *st;
2289 uint64_t original_size;
2290 int err;
2291
2292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (c->fc->nb_streams < 1) // will happen with jp2 files
2293 return 0;
2294 58 st = c->fc->streams[c->fc->nb_streams-1];
2295
2296
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
58 if (st->codecpar->codec_id != codec_id)
2297 19 return 0; /* unexpected codec_id - don't mess with extradata */
2298
2299 39 original_size = st->codecpar->extradata_size;
2300 39 err = mov_realloc_extradata(st->codecpar, atom);
2301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err)
2302 return err;
2303
2304 39 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
2305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err < 0)
2306 return err;
2307 39 return 0; // Note: this is the original behavior to ignore truncation.
2308 }
2309
2310 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
2311 16 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2312 {
2313 16 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
2314 }
2315
2316 static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2317 {
2318 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS);
2319 }
2320
2321 static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2322 {
2323 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
2324 }
2325
2326 static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2327 {
2328 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
2329 }
2330
2331 19 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2332 {
2333 19 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
2334
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!ret)
2335 19 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
2336 19 return ret;
2337 }
2338
2339 static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2340 {
2341 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
2342
2343 if (!ret && c->fc->nb_streams >= 1) {
2344 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2345 if (par->extradata_size >= 40) {
2346 par->height = AV_RB16(&par->extradata[36]);
2347 par->width = AV_RB16(&par->extradata[38]);
2348 }
2349 }
2350 return ret;
2351 }
2352
2353 16 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2354 {
2355
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (c->fc->nb_streams >= 1) {
2356 16 AVStream *const st = c->fc->streams[c->fc->nb_streams - 1];
2357 16 FFStream *const sti = ffstream(st);
2358 16 AVCodecParameters *par = st->codecpar;
2359
2360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
2361 par->codec_id == AV_CODEC_ID_H264 &&
2362 atom.size > 11) {
2363 int cid;
2364 avio_skip(pb, 10);
2365 cid = avio_rb16(pb);
2366 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
2367 if (cid == 0xd4d || cid == 0xd4e)
2368 par->width = 1440;
2369 return 0;
2370
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
2371
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
2372
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
2373
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 atom.size >= 24) {
2374 int num, den;
2375 13 avio_skip(pb, 12);
2376 13 num = avio_rb32(pb);
2377 13 den = avio_rb32(pb);
2378
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)
2379 return 0;
2380
2/3
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
13 switch (avio_rb32(pb)) {
2381 12 case 2:
2382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (den >= INT_MAX / 2)
2383 return 0;
2384 12 den *= 2;
2385 av_fallthrough;
2386 13 case 1:
2387 13 sti->display_aspect_ratio = (AVRational){ num, den };
2388 av_fallthrough;
2389 13 default:
2390 13 return 0;
2391 }
2392 }
2393 }
2394
2395 3 return mov_read_avid(c, pb, atom);
2396 }
2397
2398 26 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2399 {
2400 26 int ret = 0;
2401 26 int length = 0;
2402 uint64_t original_size;
2403
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (c->fc->nb_streams >= 1) {
2404 26 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (par->codec_id == AV_CODEC_ID_H264)
2406 return 0;
2407
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (atom.size == 16) {
2408 26 original_size = par->extradata_size;
2409 26 ret = mov_realloc_extradata(par, atom);
2410
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!ret) {
2411 26 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
2412
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (length == atom.size) {
2413 26 const uint8_t range_value = par->extradata[original_size + 19];
2414
1/3
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
26 switch (range_value) {
2415 26 case 1:
2416 26 par->color_range = AVCOL_RANGE_MPEG;
2417 26 break;
2418 case 2:
2419 par->color_range = AVCOL_RANGE_JPEG;
2420 break;
2421 default:
2422 av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
2423 break;
2424 }
2425 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
2426 } else {
2427 /* For some reason the whole atom was not added to the extradata */
2428 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
2429 }
2430 } else {
2431 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
2432 }
2433 } else {
2434 av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
2435 }
2436 }
2437
2438 26 return ret;
2439 }
2440
2441 4 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2442 {
2443 4 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
2444 }
2445
2446 33 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2447 {
2448 AVStream *st;
2449 int ret;
2450
2451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (c->fc->nb_streams < 1)
2452 return 0;
2453 33 st = c->fc->streams[c->fc->nb_streams-1];
2454
2455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if ((uint64_t)atom.size > (1<<30))
2456 return AVERROR_INVALIDDATA;
2457
2458
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 2 times.
33 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2459
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
2461 // pass all frma atom to codec, needed at least for QDMC and QDM2
2462 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2464 return ret;
2465
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 } else if (atom.size > 8) { /* to read frma, esds atoms */
2466
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
31 if (st->codecpar->codec_id == AV_CODEC_ID_ALAC && atom.size >= 24) {
2467 uint64_t buffer;
2468 10 ret = ffio_ensure_seekback(pb, 8);
2469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2470 return ret;
2471 10 buffer = avio_rb64(pb);
2472 10 atom.size -= 8;
2473
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
2474
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 <= atom.size
2475
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 >= 8) {
2476 10 avio_skip(pb, -8);
2477 10 atom.size += 8;
2478 } else if (!st->codecpar->extradata_size) {
2479 #define ALAC_EXTRADATA_SIZE 36
2480 st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
2481 if (!st->codecpar->extradata)
2482 return AVERROR(ENOMEM);
2483 st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
2484 AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
2485 AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
2486 AV_WB64(st->codecpar->extradata + 12, buffer);
2487 avio_read(pb, st->codecpar->extradata + 20, 16);
2488 avio_skip(pb, atom.size - 24);
2489 return 0;
2490 }
2491 }
2492
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 if ((ret = mov_read_default(c, pb, atom)) < 0)
2493 return ret;
2494 } else
2495 avio_skip(pb, atom.size);
2496 33 return 0;
2497 }
2498
2499 /**
2500 * This function reads atom content and puts data in extradata without tag
2501 * nor size unlike mov_read_extradata.
2502 */
2503 184 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2504 {
2505 AVStream *st;
2506 int ret;
2507
2508 184 st = get_curr_st(c);
2509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
184 if (!st)
2510 return 0;
2511
2512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
184 if ((uint64_t)atom.size > (1<<30))
2513 return AVERROR_INVALIDDATA;
2514
2515
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 183 times.
184 if (atom.type == MKTAG('v','v','c','C')) {
2516 1 avio_skip(pb, 4);
2517 1 atom.size -= 4;
2518 }
2519
2520
2/2
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 4 times.
184 if (atom.size >= 10) {
2521 // Broken files created by legacy versions of libavformat will
2522 // wrap a whole fiel atom inside of a glbl atom.
2523 180 unsigned size = avio_rb32(pb);
2524 180 unsigned type = avio_rl32(pb);
2525
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 180 times.
180 if (avio_feof(pb))
2526 return AVERROR_INVALIDDATA;
2527 180 avio_seek(pb, -8, SEEK_CUR);
2528
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 170 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
180 if (type == MKTAG('f','i','e','l') && size == atom.size)
2529 10 return mov_read_default(c, pb, atom);
2530 }
2531
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
174 if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
2532 av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
2533 return 0;
2534 }
2535 174 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
174 if (ret < 0)
2537 return ret;
2538
3/4
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 106 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 68 times.
174 if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
2539 /* HEVC-based Dolby Vision derived from hvc1.
2540 Happens to match with an identifier
2541 previously utilized for DV. Thus, if we have
2542 the hvcC extradata box available as specified,
2543 set codec to HEVC */
2544 st->codecpar->codec_id = AV_CODEC_ID_HEVC;
2545
2546 174 return 0;
2547 }
2548
2549 2 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2550 {
2551 AVStream *st;
2552 uint8_t profile_level;
2553 int ret;
2554
2555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
2556 return 0;
2557 2 st = c->fc->streams[c->fc->nb_streams-1];
2558
2559
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)
2560 return AVERROR_INVALIDDATA;
2561
2562 2 profile_level = avio_r8(pb);
2563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((profile_level & 0xf0) != 0xc0)
2564 return 0;
2565
2566 2 avio_seek(pb, 6, SEEK_CUR);
2567 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
2568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2569 return ret;
2570
2571 2 return 0;
2572 }
2573
2574 51 static int mov_find_tref_id(const MovTref *tag, uint32_t id)
2575 {
2576
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 32 times.
63 for (int i = 0; i < tag->nb_id; i++) {
2577
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 12 times.
31 if (tag->id[i] == id)
2578 19 return 1;
2579 }
2580 32 return 0;
2581 }
2582
2583 32 static int mov_add_tref_id(MovTref *tag, uint32_t id)
2584 {
2585 32 int ret = mov_find_tref_id(tag, id);
2586
2587
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (!ret) {
2588 32 uint32_t *tmp = av_realloc_array(tag->id, tag->nb_id + 1, sizeof(*tag->id));
2589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!tmp)
2590 return AVERROR(ENOMEM);
2591 32 tag->id = tmp;
2592 32 tag->id[tag->nb_id++] = id;
2593 }
2594
2595 32 return 0;
2596 }
2597
2598 1095 static MovTref *mov_find_tref_tag(const MOVStreamContext *sc, uint32_t name)
2599 {
2600
2/2
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 1046 times.
1169 for (int i = 0; i < sc->nb_tref_tags; i++) {
2601 123 MovTref *entry = &sc->tref_tags[i];
2602
2603
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 74 times.
123 if (entry->name == name)
2604 49 return entry;
2605 }
2606 1046 return NULL;
2607 }
2608
2609 28 static MovTref *mov_add_tref_tag(MOVStreamContext *sc, uint32_t name)
2610 {
2611 28 MovTref *tag = mov_find_tref_tag(sc, name);
2612
2613
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (!tag) {
2614 28 MovTref *tmp = av_realloc_array(sc->tref_tags, sc->nb_tref_tags + 1,
2615 sizeof(*sc->tref_tags));
2616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!tmp)
2617 return NULL;
2618 28 sc->tref_tags = tmp;
2619 28 tag = &sc->tref_tags[sc->nb_tref_tags++];
2620 28 *tag = (MovTref){ .name = name };
2621 }
2622
2623 28 return tag;
2624 }
2625
2626 10 static int mov_read_cdsc(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2627 {
2628 AVStream* st;
2629 MOVStreamContext* sc;
2630
2631
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (c->fc->nb_streams < 1)
2632 return 0;
2633
2634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (atom.size > 4) {
2635 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type cdsc is supported\n");
2636 return AVERROR_PATCHWELCOME;
2637 }
2638
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (atom.size < 4)
2639 return AVERROR_INVALIDDATA;
2640
2641 10 st = get_curr_st(c);
2642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!st)
2643 return AVERROR_INVALIDDATA;
2644 10 sc = st->priv_data;
2645
2646 10 MovTref *tag = mov_add_tref_tag(sc, atom.type);
2647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!tag)
2648 return AVERROR(ENOMEM);
2649
2650 10 int ret = mov_add_tref_id(tag, avio_rb32(pb));
2651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2652 return ret;
2653
2654 10 return 0;
2655 }
2656
2657 static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2658 {
2659 AVStream* st;
2660 MOVStreamContext* sc;
2661
2662 if (c->fc->nb_streams < 1)
2663 return 0;
2664
2665 /* For SBAS this should be fine - though beware if someone implements a
2666 * tref atom processor that doesn't drop down to default then this may
2667 * be lost. */
2668 if (atom.size > 4) {
2669 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2670 return AVERROR_PATCHWELCOME;
2671 }
2672 if (atom.size < 4)
2673 return AVERROR_INVALIDDATA;
2674
2675 st = c->fc->streams[c->fc->nb_streams - 1];
2676 sc = st->priv_data;
2677
2678 MovTref *tag = mov_add_tref_tag(sc, atom.type);
2679 if (!tag)
2680 return AVERROR(ENOMEM);
2681
2682 int ret = mov_add_tref_id(tag, avio_rb32(pb));
2683 if (ret < 0)
2684 return ret;
2685
2686 return 0;
2687 }
2688
2689 static int mov_read_vdep(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2690 {
2691 AVStream* st;
2692 MOVStreamContext* sc;
2693
2694 if (c->fc->nb_streams < 1)
2695 return 0;
2696
2697 if (atom.size > 4)
2698 av_log(c->fc, AV_LOG_WARNING, "More than one vdep reference is not supported.\n");
2699 if (atom.size < 4)
2700 return AVERROR_INVALIDDATA;
2701
2702 st = c->fc->streams[c->fc->nb_streams - 1];
2703 sc = st->priv_data;
2704
2705 MovTref *tag = mov_add_tref_tag(sc, atom.type);
2706 if (!tag)
2707 return AVERROR(ENOMEM);
2708
2709 int ret = mov_add_tref_id(tag, avio_rb32(pb));
2710 if (ret < 0)
2711 return ret;
2712
2713 return 0;
2714 }
2715
2716 /**
2717 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2718 * but can have extradata appended at the end after the 40 bytes belonging
2719 * to the struct.
2720 */
2721 static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2722 {
2723 AVStream *st;
2724 int ret;
2725
2726 if (c->fc->nb_streams < 1)
2727 return 0;
2728 if (atom.size <= 40)
2729 return 0;
2730 st = c->fc->streams[c->fc->nb_streams-1];
2731
2732 if ((uint64_t)atom.size > (1<<30))
2733 return AVERROR_INVALIDDATA;
2734
2735 avio_skip(pb, 40);
2736 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
2737 if (ret < 0)
2738 return ret;
2739
2740 return 0;
2741 }
2742
2743 665 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2744 {
2745 AVStream *st;
2746 MOVStreamContext *sc;
2747 unsigned int i, entries;
2748
2749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (c->trak_index < 0) {
2750 av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
2751 return 0;
2752 }
2753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (c->fc->nb_streams < 1)
2754 return 0;
2755 665 st = c->fc->streams[c->fc->nb_streams-1];
2756 665 sc = st->priv_data;
2757
2758 665 avio_r8(pb); /* version */
2759 665 avio_rb24(pb); /* flags */
2760
2761 // Clamp allocation size for `chunk_offsets` -- don't throw an error for an
2762 // invalid count since the EOF path doesn't throw either.
2763 665 entries = avio_rb32(pb);
2764 665 entries =
2765
2/2
✓ Branch 0 taken 660 times.
✓ Branch 1 taken 5 times.
665 FFMIN(entries,
2766 FFMAX(0, (atom.size - 8) /
2767 (atom.type == MKTAG('s', 't', 'c', 'o') ? 4 : 8)));
2768
2769
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 636 times.
665 if (!entries)
2770 29 return 0;
2771
2772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 636 times.
636 if (sc->chunk_offsets) {
2773 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2774 return 0;
2775 }
2776
2777 636 av_free(sc->chunk_offsets);
2778 636 sc->chunk_count = 0;
2779 636 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 636 times.
636 if (!sc->chunk_offsets)
2781 return AVERROR(ENOMEM);
2782 636 sc->chunk_count = entries;
2783
2784
2/2
✓ Branch 0 taken 632 times.
✓ Branch 1 taken 4 times.
636 if (atom.type == MKTAG('s','t','c','o'))
2785
3/4
✓ Branch 0 taken 43297 times.
✓ Branch 1 taken 632 times.
✓ Branch 2 taken 43297 times.
✗ Branch 3 not taken.
43929 for (i = 0; i < entries && !pb->eof_reached; i++)
2786 43297 sc->chunk_offsets[i] = avio_rb32(pb);
2787
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (atom.type == MKTAG('c','o','6','4'))
2788
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++) {
2789 136336 sc->chunk_offsets[i] = avio_rb64(pb);
2790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136336 times.
136336 if (sc->chunk_offsets[i] < 0) {
2791 av_log(c->fc, AV_LOG_WARNING, "Impossible chunk_offset\n");
2792 sc->chunk_offsets[i] = 0;
2793 }
2794 }
2795 else
2796 return AVERROR_INVALIDDATA;
2797
2798 636 sc->chunk_count = i;
2799
2800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 636 times.
636 if (pb->eof_reached) {
2801 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2802 return AVERROR_EOF;
2803 }
2804
2805 636 return 0;
2806 }
2807
2808 729 static int mov_codec_id(AVStream *st, uint32_t format)
2809 {
2810 729 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2811
2812
2/2
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 252 times.
729 if (id <= 0 &&
2813
2/2
✓ Branch 0 taken 474 times.
✓ Branch 1 taken 3 times.
477 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 474 times.
474 (format & 0xFFFF) == 'T' + ('S' << 8)))
2815 3 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2816
2817
4/4
✓ Branch 0 taken 332 times.
✓ Branch 1 taken 397 times.
✓ Branch 2 taken 255 times.
✓ Branch 3 taken 77 times.
729 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2818 255 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2819
3/4
✓ Branch 0 taken 454 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 454 times.
✗ Branch 3 not taken.
474 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2820 /* skip old ASF MPEG-4 tag */
2821
2/2
✓ Branch 0 taken 450 times.
✓ Branch 1 taken 4 times.
454 format && format != MKTAG('m','p','4','s')) {
2822 450 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2823
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 387 times.
450 if (id <= 0)
2824 63 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2825
2/2
✓ Branch 0 taken 391 times.
✓ Branch 1 taken 59 times.
450 if (id > 0)
2826 391 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2827
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 52 times.
59 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2828
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2830 52 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2831
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 6 times.
52 if (id <= 0) {
2832
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 4 times.
88 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2833
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 4 times.
88 AV_CODEC_ID_TTML : id;
2834 }
2835
2836
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 38 times.
52 if (id > 0)
2837 14 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2838 else
2839 38 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2840 }
2841 }
2842
2843 729 st->codecpar->codec_tag = format;
2844
2845 729 return id;
2846 }
2847
2848 348 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2849 AVStream *st, MOVStreamContext *sc)
2850 {
2851 348 uint8_t codec_name[32] = { 0 };
2852 int64_t stsd_start;
2853 unsigned int len;
2854 348 uint32_t id = 0;
2855
2856 /* The first 16 bytes of the video sample description are already
2857 * read in ff_mov_read_stsd_entries() */
2858 348 stsd_start = avio_tell(pb) - 16;
2859
2860
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 240 times.
348 if (c->isom) {
2861 108 avio_skip(pb, 2); /* pre_defined */
2862 108 avio_skip(pb, 2); /* reserved */
2863 108 avio_skip(pb, 12); /* pre_defined */
2864 } else {
2865 240 avio_rb16(pb); /* version */
2866 240 avio_rb16(pb); /* revision level */
2867 240 id = avio_rl32(pb); /* vendor */
2868 240 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2869 240 avio_rb32(pb); /* temporal quality */
2870 240 avio_rb32(pb); /* spatial quality */
2871 }
2872
2873 348 st->codecpar->width = avio_rb16(pb); /* width */
2874 348 st->codecpar->height = avio_rb16(pb); /* height */
2875
2876 348 avio_rb32(pb); /* horiz resolution */
2877 348 avio_rb32(pb); /* vert resolution */
2878 348 avio_rb32(pb); /* data size, always 0 */
2879 348 avio_rb16(pb); /* frames per samples */
2880
2881 348 len = avio_r8(pb); /* codec name, pascal string */
2882
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 347 times.
348 if (len > 31)
2883 1 len = 31;
2884 348 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2885
2/2
✓ Branch 0 taken 345 times.
✓ Branch 1 taken 3 times.
348 if (len < 31)
2886 345 avio_skip(pb, 31 - len);
2887
2888
2/2
✓ Branch 0 taken 268 times.
✓ Branch 1 taken 80 times.
348 if (codec_name[0])
2889 268 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2890
2891 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2892
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348 times.
348 if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2893 st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2894 st->codecpar->width &= ~1;
2895 st->codecpar->height &= ~1;
2896 }
2897 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2898
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348 times.
348 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2899 !strncmp(codec_name, "Sorenson H263", 13))
2900 st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2901
2902 348 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2903
2904 348 avio_seek(pb, stsd_start, SEEK_SET);
2905
2906
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 330 times.
348 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2907 18 st->codecpar->bits_per_coded_sample &= 0x1F;
2908 18 sc->has_palette = 1;
2909 }
2910 348 }
2911
2912 275 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2913 AVStream *st, MOVStreamContext *sc)
2914 {
2915 int bits_per_sample, flags;
2916 275 uint16_t version = avio_rb16(pb);
2917 275 uint32_t id = 0;
2918 275 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2919 int channel_count;
2920
2921
2/2
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 87 times.
275 if (c->isom)
2922 188 avio_skip(pb, 6); /* reserved */
2923 else {
2924 87 avio_rb16(pb); /* revision level */
2925 87 id = avio_rl32(pb); /* vendor */
2926 87 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2927 }
2928
2929 275 channel_count = avio_rb16(pb);
2930
2931 275 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2932 275 st->codecpar->ch_layout.nb_channels = channel_count;
2933 275 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
2934 275 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
2935
2936 275 sc->audio_cid = avio_rb16(pb);
2937 275 avio_rb16(pb); /* packet size = 0 */
2938
2939 275 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
2940
2941 // Read QT version 1 fields. In version 0 these do not exist.
2942 275 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
2943
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
275 if (!c->isom ||
2944
1/2
✓ Branch 0 taken 188 times.
✗ Branch 1 not taken.
188 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
2945
4/4
✓ Branch 0 taken 183 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 179 times.
188 (sc->stsd_version == 0 && version > 0)) {
2946
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 42 times.
91 if (version == 1) {
2947 49 sc->samples_per_frame = avio_rb32(pb);
2948 49 avio_rb32(pb); /* bytes per packet */
2949 49 sc->bytes_per_frame = avio_rb32(pb);
2950 49 avio_rb32(pb); /* bytes per sample */
2951
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 38 times.
42 } else if (version == 2) {
2952 4 avio_rb32(pb); /* sizeof struct only */
2953 4 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
2954 4 channel_count = avio_rb32(pb);
2955 4 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
2956 4 st->codecpar->ch_layout.nb_channels = channel_count;
2957 4 avio_rb32(pb); /* always 0x7F000000 */
2958 4 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
2959
2960 4 flags = avio_rb32(pb); /* lpcm format specific flag */
2961 4 sc->bytes_per_frame = avio_rb32(pb);
2962 4 sc->samples_per_frame = avio_rb32(pb);
2963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
2964 st->codecpar->codec_id =
2965 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
2966 flags);
2967 }
2968
6/6
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 49 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 25 times.
91 if (version == 0 || (version == 1 && sc->audio_cid != -2)) {
2969 /* can't correctly handle variable sized packet as audio unit */
2970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 switch (st->codecpar->codec_id) {
2971 case AV_CODEC_ID_MP2:
2972 case AV_CODEC_ID_MP3:
2973 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
2974 break;
2975 }
2976 }
2977 }
2978
2979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
275 if (sc->format == 0) {
2980 if (st->codecpar->bits_per_coded_sample == 8)
2981 st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
2982 else if (st->codecpar->bits_per_coded_sample == 16)
2983 st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
2984 }
2985
2986
7/7
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 231 times.
275 switch (st->codecpar->codec_id) {
2987 7 case AV_CODEC_ID_PCM_S8:
2988 case AV_CODEC_ID_PCM_U8:
2989
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
2990 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2991 7 break;
2992 21 case AV_CODEC_ID_PCM_S16LE:
2993 case AV_CODEC_ID_PCM_S16BE:
2994
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 19 times.
21 if (st->codecpar->bits_per_coded_sample == 8)
2995 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
2996
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 else if (st->codecpar->bits_per_coded_sample == 24)
2997 st->codecpar->codec_id =
2998 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2999 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
3000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 else if (st->codecpar->bits_per_coded_sample == 32)
3001 st->codecpar->codec_id =
3002 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
3003 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
3004 21 break;
3005 /* set values for old format before stsd version 1 appeared */
3006 2 case AV_CODEC_ID_MACE3:
3007 2 sc->samples_per_frame = 6;
3008 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
3009 2 break;
3010 8 case AV_CODEC_ID_MACE6:
3011 8 sc->samples_per_frame = 6;
3012 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
3013 8 break;
3014 5 case AV_CODEC_ID_ADPCM_IMA_QT:
3015 5 sc->samples_per_frame = 64;
3016 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
3017 5 break;
3018 1 case AV_CODEC_ID_GSM:
3019 1 sc->samples_per_frame = 160;
3020 1 sc->bytes_per_frame = 33;
3021 1 break;
3022 231 default:
3023 231 break;
3024 }
3025
3026 275 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
3027
3/4
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 225 times.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
275 if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->ch_layout.nb_channels <= INT_MAX) {
3028 50 st->codecpar->bits_per_coded_sample = bits_per_sample;
3029 50 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
3030 }
3031 275 }
3032
3033 15 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
3034 AVStream *st, MOVStreamContext *sc,
3035 int64_t size)
3036 {
3037 // ttxt stsd contains display flags, justification, background
3038 // color, fonts, and default styles, so fake an atom to read it
3039 15 MOVAtom fake_atom = { .size = size };
3040 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
3041 // in extradata unlike stpp MP4 TTML.
3042
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
3043
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
15 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
3044 11 mov_read_glbl(c, pb, fake_atom);
3045 15 st->codecpar->width = sc->width;
3046 15 st->codecpar->height = sc->height;
3047 15 }
3048
3049 42 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
3050 AVStream *st, MOVStreamContext *sc,
3051 int64_t size)
3052 {
3053 int ret;
3054
3055
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 23 times.
42 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
3056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if ((int)size != size)
3057 return AVERROR(ENOMEM);
3058
3059 19 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
3060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
3061 return ret;
3062
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (size > 16) {
3063 19 MOVStreamContext *tmcd_ctx = st->priv_data;
3064 int val;
3065 19 val = AV_RB32(st->codecpar->extradata + 4);
3066 19 tmcd_ctx->tmcd_flags = val;
3067 19 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
3068 19 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
3069 19 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
3070
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (size > 30) {
3071 4 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
3072 4 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
3073
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) {
3074 4 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
3075
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 &&
3076
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 st->codecpar->extradata[30] /* Don't add empty string */) {
3077 4 char *reel_name = av_malloc(str_size + 1);
3078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!reel_name)
3079 return AVERROR(ENOMEM);
3080 4 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
3081 4 reel_name[str_size] = 0; /* Add null terminator */
3082 4 av_dict_set(&st->metadata, "reel_name", reel_name,
3083 AV_DICT_DONT_STRDUP_VAL);
3084 }
3085 }
3086 }
3087 }
3088
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 22 times.
23 } else if (st->codecpar->codec_id == AV_CODEC_ID_ITUT_T35) {
3089 1 int t35_identifier_length = avio_r8(pb);
3090
3091
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (t35_identifier_length <= 0 || t35_identifier_length >= size)
3092 return AVERROR_INVALIDDATA;
3093
3094 1 ret = ff_get_extradata(c->fc, st->codecpar, pb, t35_identifier_length);
3095
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
3096 return ret;
3097
3098 1 int hrsd_len = size - t35_identifier_length - 1;
3099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (hrsd_len > 0) {
3100 uint8_t *hrsd_str = av_malloc(hrsd_len + 1);
3101 if (!hrsd_str)
3102 return AVERROR(ENOMEM);
3103
3104 ret = ffio_read_size(pb, hrsd_str, hrsd_len);
3105 if (ret < 0) {
3106 av_free(hrsd_str);
3107 return ret;
3108 }
3109 if (hrsd_str[0]) {
3110 hrsd_str[hrsd_len] = 0;
3111 ret = av_dict_set(&st->metadata, "description", hrsd_str, AV_DICT_DONT_OVERWRITE);
3112 }
3113 av_free(hrsd_str);
3114 }
3115 } else {
3116 /* other codec type, just skip (rtp, mp4s ...) */
3117 22 avio_skip(pb, size);
3118 }
3119 42 return 0;
3120 }
3121
3122 665 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
3123 AVStream *st, MOVStreamContext *sc)
3124 {
3125 665 FFStream *const sti = ffstream(st);
3126
3127
2/2
✓ Branch 0 taken 275 times.
✓ Branch 1 taken 390 times.
665 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
3128
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
275 !st->codecpar->sample_rate && sc->time_scale > 1)
3129 st->codecpar->sample_rate = sc->time_scale;
3130
3131 /* special codec parameters handling */
3132
7/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 15 times.
✓ Branch 6 taken 16 times.
✓ Branch 7 taken 10 times.
✓ Branch 8 taken 107 times.
✓ Branch 9 taken 503 times.
665 switch (st->codecpar->codec_id) {
3133 #if CONFIG_DV_DEMUXER
3134 case AV_CODEC_ID_DVAUDIO:
3135 if (c->dv_fctx) {
3136 avpriv_request_sample(c->fc, "multiple DV audio streams");
3137 return AVERROR(ENOSYS);
3138 }
3139
3140 c->dv_fctx = avformat_alloc_context();
3141 if (!c->dv_fctx) {
3142 av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
3143 return AVERROR(ENOMEM);
3144 }
3145 c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
3146 if (!c->dv_demux) {
3147 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
3148 return AVERROR(ENOMEM);
3149 }
3150 sc->dv_audio_container = 1;
3151 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
3152 break;
3153 #endif
3154 /* no ifdef since parameters are always those */
3155 case AV_CODEC_ID_QCELP:
3156 av_channel_layout_uninit(&st->codecpar->ch_layout);
3157 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3158 // force sample rate for qcelp when not stored in mov
3159 if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
3160 st->codecpar->sample_rate = 8000;
3161 // FIXME: Why is the following needed for some files?
3162 sc->samples_per_frame = 160;
3163 if (!sc->bytes_per_frame)
3164 sc->bytes_per_frame = 35;
3165 break;
3166 case AV_CODEC_ID_AMR_NB:
3167 av_channel_layout_uninit(&st->codecpar->ch_layout);
3168 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3169 /* force sample rate for amr, stsd in 3gp does not store sample rate */
3170 st->codecpar->sample_rate = 8000;
3171 break;
3172 11 case AV_CODEC_ID_AMR_WB:
3173 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
3174 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3175 11 st->codecpar->sample_rate = 16000;
3176 11 break;
3177 3 case AV_CODEC_ID_MP2:
3178 case AV_CODEC_ID_MP3:
3179 /* force type after stsd for m1a hdlr */
3180 3 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
3181 3 break;
3182 15 case AV_CODEC_ID_GSM:
3183 case AV_CODEC_ID_ADPCM_MS:
3184 case AV_CODEC_ID_ADPCM_IMA_WAV:
3185 case AV_CODEC_ID_ILBC:
3186 case AV_CODEC_ID_MACE3:
3187 case AV_CODEC_ID_MACE6:
3188 case AV_CODEC_ID_QDM2:
3189 15 st->codecpar->block_align = sc->bytes_per_frame;
3190 15 break;
3191 16 case AV_CODEC_ID_ALAC:
3192
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
3193 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
3194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
3195 av_channel_layout_uninit(&st->codecpar->ch_layout);
3196 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3197 st->codecpar->ch_layout.nb_channels = channel_count;
3198 }
3199 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
3200 }
3201 16 break;
3202 10 case AV_CODEC_ID_AC3:
3203 case AV_CODEC_ID_EAC3:
3204 case AV_CODEC_ID_MPEG1VIDEO:
3205 case AV_CODEC_ID_VC1:
3206 case AV_CODEC_ID_VP8:
3207 case AV_CODEC_ID_VP9:
3208 10 sti->need_parsing = AVSTREAM_PARSE_FULL;
3209 10 break;
3210 107 case AV_CODEC_ID_PRORES_RAW:
3211 case AV_CODEC_ID_PRORES:
3212 case AV_CODEC_ID_APV:
3213 case AV_CODEC_ID_EVC:
3214 case AV_CODEC_ID_LCEVC:
3215 case AV_CODEC_ID_AV1:
3216 /* field_order detection of H264 requires parsing */
3217 case AV_CODEC_ID_H264:
3218 107 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3219 107 break;
3220 503 default:
3221 503 break;
3222 }
3223 665 return 0;
3224 }
3225
3226 680 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
3227 int codec_tag, int format,
3228 int64_t size)
3229 {
3230
3/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 665 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
680 if (codec_tag &&
3231 (codec_tag != format &&
3232 // AVID 1:1 samples with differing data format and codec tag exist
3233 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
3234 // prores is allowed to have differing data format and codec tag
3235 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
3236 // so is dv (sigh)
3237 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
3238 (c->fc->video_codec_id ? ff_codec_get_id(ff_codec_movvideo_tags, format) != c->fc->video_codec_id
3239 : codec_tag != MKTAG('j','p','e','g')))) {
3240 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3241 * export it as a separate AVStream but this needs a few changes
3242 * in the MOV demuxer, patch welcome. */
3243
3244 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3245 avio_skip(pb, size);
3246 return 1;
3247 }
3248
3249 680 return 0;
3250 }
3251
3252 680 static int mov_finalize_stsd_entry(MOVContext *c, AVStream *st)
3253 {
3254 int ret;
3255
3256 /* special codec parameters handling */
3257
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 599 times.
680 switch (st->codecpar->codec_id) {
3258 81 case AV_CODEC_ID_H264:
3259 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
3260
1/30
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
81 if (!st->codecpar->extradata_size && TAG_IS_AVCI(st->codecpar->codec_tag)) {
3261 ret = ff_generate_avci_extradata(st);
3262 if (ret < 0)
3263 return ret;
3264 }
3265 81 break;
3266 599 default:
3267 599 break;
3268 }
3269
3270 680 return 0;
3271 }
3272
3273 665 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3274 {
3275 AVStream *st;
3276 MOVStreamContext *sc;
3277 int pseudo_stream_id;
3278
3279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 av_assert0 (c->fc->nb_streams >= 1);
3280 665 st = c->fc->streams[c->fc->nb_streams-1];
3281 665 sc = st->priv_data;
3282
3283 665 for (pseudo_stream_id = 0;
3284
3/4
✓ Branch 0 taken 680 times.
✓ Branch 1 taken 665 times.
✓ Branch 2 taken 680 times.
✗ Branch 3 not taken.
1345 pseudo_stream_id < entries && !pb->eof_reached;
3285 680 pseudo_stream_id++) {
3286 //Parsing Sample description table
3287 enum AVCodecID id;
3288 680 int ret, dref_id = 1;
3289 680 MOVAtom a = { AV_RL32("stsd") };
3290 680 int64_t start_pos = avio_tell(pb);
3291 680 int64_t size = avio_rb32(pb); /* size */
3292 680 uint32_t format = avio_rl32(pb); /* data format */
3293
3294
1/2
✓ Branch 0 taken 680 times.
✗ Branch 1 not taken.
680 if (size >= 16) {
3295 680 avio_rb32(pb); /* reserved */
3296 680 avio_rb16(pb); /* reserved */
3297 680 dref_id = avio_rb16(pb);
3298 } else if (size <= 7) {
3299 av_log(c->fc, AV_LOG_ERROR,
3300 "invalid size %"PRId64" in stsd\n", size);
3301 return AVERROR_INVALIDDATA;
3302 }
3303
3304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 680 times.
680 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3305 680 size - (avio_tell(pb) - start_pos))) {
3306 sc->stsd_count++;
3307 continue;
3308 }
3309
3310
2/2
✓ Branch 0 taken 665 times.
✓ Branch 1 taken 15 times.
680 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
3311 680 sc->dref_id= dref_id;
3312 680 sc->format = format;
3313
3314 680 id = mov_codec_id(st, format);
3315
3316 680 av_log(c->fc, AV_LOG_TRACE,
3317 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3318 680 av_fourcc2str(format), st->codecpar->codec_type);
3319
3320 680 st->codecpar->codec_id = id;
3321
2/2
✓ Branch 0 taken 348 times.
✓ Branch 1 taken 332 times.
680 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3322 348 mov_parse_stsd_video(c, pb, st, sc);
3323
2/2
✓ Branch 0 taken 275 times.
✓ Branch 1 taken 57 times.
332 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3324 275 mov_parse_stsd_audio(c, pb, st, sc);
3325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
275 if (st->codecpar->sample_rate < 0) {
3326 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3327 return AVERROR_INVALIDDATA;
3328 }
3329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
275 if (st->codecpar->ch_layout.nb_channels < 0) {
3330 av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3331 return AVERROR_INVALIDDATA;
3332 }
3333
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 42 times.
57 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3334 15 mov_parse_stsd_subtitle(c, pb, st, sc,
3335 15 size - (avio_tell(pb) - start_pos));
3336 } else {
3337 42 ret = mov_parse_stsd_data(c, pb, st, sc,
3338 42 size - (avio_tell(pb) - start_pos));
3339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0)
3340 return ret;
3341 }
3342 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3343 680 a.size = size - (avio_tell(pb) - start_pos);
3344
2/2
✓ Branch 0 taken 542 times.
✓ Branch 1 taken 138 times.
680 if (a.size > 8) {
3345
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 542 times.
542 if ((ret = mov_read_default(c, pb, a)) < 0)
3346 return ret;
3347
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 137 times.
138 } else if (a.size > 0)
3348 1 avio_skip(pb, a.size);
3349
3350 680 ret = mov_finalize_stsd_entry(c, st);
3351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 680 times.
680 if (ret < 0)
3352 return ret;
3353
3354
3/4
✓ Branch 0 taken 680 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 401 times.
✓ Branch 3 taken 279 times.
680 if (sc->extradata && st->codecpar->extradata) {
3355 401 int extra_size = st->codecpar->extradata_size;
3356
3357 /* Move the current stream extradata to the stream context one. */
3358 401 sc->extradata_size[pseudo_stream_id] = extra_size;
3359 401 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3360 401 st->codecpar->extradata = NULL;
3361 401 st->codecpar->extradata_size = 0;
3362 }
3363 680 sc->stsd_count++;
3364 }
3365
3366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (pb->eof_reached) {
3367 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3368 return AVERROR_EOF;
3369 }
3370
3371 665 return 0;
3372 }
3373
3374 665 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3375 {
3376 AVStream *st;
3377 MOVStreamContext *sc;
3378 int ret, entries;
3379
3380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (c->fc->nb_streams < 1)
3381 return 0;
3382 665 st = c->fc->streams[c->fc->nb_streams - 1];
3383 665 sc = st->priv_data;
3384
3385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (sc->extradata) {
3386 av_log(c->fc, AV_LOG_ERROR,
3387 "Duplicate stsd found in this track.\n");
3388 return AVERROR_INVALIDDATA;
3389 }
3390
3391 665 sc->stsd_version = avio_r8(pb);
3392 665 avio_rb24(pb); /* flags */
3393 665 entries = avio_rb32(pb);
3394
3395 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3396
3/6
✓ Branch 0 taken 665 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 665 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 665 times.
665 if (entries <= 0 || entries > atom.size / 8 || entries > 1024) {
3397 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3398 return AVERROR_INVALIDDATA;
3399 }
3400
3401 /* Prepare space for hosting multiple extradata. */
3402 665 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3403
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (!sc->extradata)
3404 return AVERROR(ENOMEM);
3405
3406 665 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (!sc->extradata_size) {
3408 ret = AVERROR(ENOMEM);
3409 goto fail;
3410 }
3411
3412 665 ret = ff_mov_read_stsd_entries(c, pb, entries);
3413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (ret < 0)
3414 goto fail;
3415
3416 /* Restore back the primary extradata. */
3417 665 av_freep(&st->codecpar->extradata);
3418 665 st->codecpar->extradata_size = sc->extradata_size[0];
3419
2/2
✓ Branch 0 taken 387 times.
✓ Branch 1 taken 278 times.
665 if (sc->extradata_size[0]) {
3420 387 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 387 times.
387 if (!st->codecpar->extradata)
3422 return AVERROR(ENOMEM);
3423 387 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3424 }
3425
3426 665 return mov_finalize_stsd_codec(c, pb, st, sc);
3427 fail:
3428 if (sc->extradata) {
3429 int j;
3430 for (j = 0; j < sc->stsd_count; j++)
3431 av_freep(&sc->extradata[j]);
3432 }
3433
3434 sc->stsd_count = 0;
3435 av_freep(&sc->extradata);
3436 av_freep(&sc->extradata_size);
3437 return ret;
3438 }
3439
3440 665 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3441 {
3442 AVStream *st;
3443 MOVStreamContext *sc;
3444 unsigned int i, entries;
3445
3446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (c->trak_index < 0) {
3447 av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3448 return 0;
3449 }
3450
3451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (c->fc->nb_streams < 1)
3452 return 0;
3453 665 st = c->fc->streams[c->fc->nb_streams-1];
3454 665 sc = st->priv_data;
3455
3456 665 avio_r8(pb); /* version */
3457 665 avio_rb24(pb); /* flags */
3458
3459 665 entries = avio_rb32(pb);
3460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if ((uint64_t)entries * 12 + 4 > atom.size)
3461 return AVERROR_INVALIDDATA;
3462
3463 665 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3464
3465
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 637 times.
665 if (!entries)
3466 28 return 0;
3467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 637 times.
637 if (sc->stsc_data) {
3468 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3469 return 0;
3470 }
3471 637 av_free(sc->stsc_data);
3472 637 sc->stsc_count = 0;
3473 637 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3474
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 637 times.
637 if (!sc->stsc_data)
3475 return AVERROR(ENOMEM);
3476
3477
3/4
✓ Branch 0 taken 3855 times.
✓ Branch 1 taken 637 times.
✓ Branch 2 taken 3855 times.
✗ Branch 3 not taken.
4492 for (i = 0; i < entries && !pb->eof_reached; i++) {
3478 3855 sc->stsc_data[i].first = avio_rb32(pb);
3479 3855 sc->stsc_data[i].count = avio_rb32(pb);
3480 3855 sc->stsc_data[i].id = avio_rb32(pb);
3481 }
3482
3483 637 sc->stsc_count = i;
3484
2/2
✓ Branch 0 taken 3855 times.
✓ Branch 1 taken 637 times.
4492 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3485 3855 int64_t first_min = i + 1;
3486
5/6
✓ Branch 0 taken 3218 times.
✓ Branch 1 taken 637 times.
✓ Branch 2 taken 3218 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3218 times.
✓ Branch 5 taken 637 times.
3855 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
3487
1/2
✓ Branch 0 taken 3218 times.
✗ Branch 1 not taken.
3218 (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) ||
3488
1/2
✓ Branch 0 taken 3855 times.
✗ Branch 1 not taken.
3855 sc->stsc_data[i].first < first_min ||
3489
1/2
✓ Branch 0 taken 3855 times.
✗ Branch 1 not taken.
3855 sc->stsc_data[i].count < 1 ||
3490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3855 times.
3855 sc->stsc_data[i].id < 1) {
3491 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);
3492 if (i+1 >= sc->stsc_count) {
3493 if (sc->stsc_data[i].count == 0 && i > 0) {
3494 sc->stsc_count --;
3495 continue;
3496 }
3497 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3498 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3499 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3500 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3501 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3502 continue;
3503 }
3504 av_assert0(sc->stsc_data[i+1].first >= 2);
3505 // We replace this entry by the next valid
3506 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3507 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3508 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3509 }
3510 }
3511
3512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 637 times.
637 if (pb->eof_reached) {
3513 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3514 return AVERROR_EOF;
3515 }
3516
3517 637 return 0;
3518 }
3519
3520 353263 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3521 {
3522 353263 return index < count - 1;
3523 }
3524
3525 /* Compute the samples value for the stsc entry at the given index. */
3526 57285 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3527 {
3528 int chunk_count;
3529
3530
2/2
✓ Branch 1 taken 57089 times.
✓ Branch 2 taken 196 times.
57285 if (mov_stsc_index_valid(index, sc->stsc_count))
3531 57089 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3532 else {
3533 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3535 196 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3536 }
3537
3538 57285 return sc->stsc_data[index].count * (int64_t)chunk_count;
3539 }
3540
3541 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3542 {
3543 AVStream *st;
3544 MOVStreamContext *sc;
3545 unsigned i, entries;
3546
3547 if (c->trak_index < 0) {
3548 av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3549 return 0;
3550 }
3551
3552 if (c->fc->nb_streams < 1)
3553 return 0;
3554 st = c->fc->streams[c->fc->nb_streams-1];
3555 sc = st->priv_data;
3556
3557 avio_rb32(pb); // version + flags
3558
3559 entries = avio_rb32(pb);
3560 if (sc->stps_data)
3561 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3562 av_free(sc->stps_data);
3563 sc->stps_count = 0;
3564 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3565 if (!sc->stps_data)
3566 return AVERROR(ENOMEM);
3567
3568 for (i = 0; i < entries && !pb->eof_reached; i++) {
3569 sc->stps_data[i] = avio_rb32(pb);
3570 }
3571
3572 sc->stps_count = i;
3573
3574 if (pb->eof_reached) {
3575 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3576 return AVERROR_EOF;
3577 }
3578
3579 return 0;
3580 }
3581
3582 165 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3583 {
3584 AVStream *st;
3585 FFStream *sti;
3586 MOVStreamContext *sc;
3587 unsigned int i, entries;
3588
3589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165 times.
165 if (c->trak_index < 0) {
3590 av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3591 return 0;
3592 }
3593
3594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165 times.
165 if (c->fc->nb_streams < 1)
3595 return 0;
3596 165 st = c->fc->streams[c->fc->nb_streams-1];
3597 165 sti = ffstream(st);
3598 165 sc = st->priv_data;
3599
3600 165 avio_r8(pb); /* version */
3601 165 avio_rb24(pb); /* flags */
3602
3603 165 entries = avio_rb32(pb);
3604
3605 165 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3606
3607
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 151 times.
165 if (!entries) {
3608 14 sc->keyframe_absent = 1;
3609
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
14 if (!sti->need_parsing && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
3610 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3611 14 return 0;
3612 }
3613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 151 times.
151 if (sc->keyframes)
3614 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 151 times.
151 if (entries >= UINT_MAX / sizeof(int))
3616 return AVERROR_INVALIDDATA;
3617 151 av_freep(&sc->keyframes);
3618 151 sc->keyframe_count = 0;
3619 151 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 151 times.
151 if (!sc->keyframes)
3621 return AVERROR(ENOMEM);
3622
3623
3/4
✓ Branch 0 taken 5736 times.
✓ Branch 1 taken 151 times.
✓ Branch 2 taken 5736 times.
✗ Branch 3 not taken.
5887 for (i = 0; i < entries && !pb->eof_reached; i++) {
3624 5736 sc->keyframes[i] = avio_rb32(pb);
3625 }
3626
3627 151 sc->keyframe_count = i;
3628
3629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 151 times.
151 if (pb->eof_reached) {
3630 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3631 return AVERROR_EOF;
3632 }
3633
3634 151 return 0;
3635 }
3636
3637 665 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3638 {
3639 AVStream *st;
3640 MOVStreamContext *sc;
3641 unsigned int i, entries, sample_size, field_size, num_bytes;
3642 GetBitContext gb;
3643 unsigned char* buf;
3644 int ret;
3645
3646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (c->trak_index < 0) {
3647 av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3648 return 0;
3649 }
3650
3651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (c->fc->nb_streams < 1)
3652 return 0;
3653 665 st = c->fc->streams[c->fc->nb_streams-1];
3654 665 sc = st->priv_data;
3655
3656 665 avio_r8(pb); /* version */
3657 665 avio_rb24(pb); /* flags */
3658
3659
1/2
✓ Branch 0 taken 665 times.
✗ Branch 1 not taken.
665 if (atom.type == MKTAG('s','t','s','z')) {
3660 665 sample_size = avio_rb32(pb);
3661
2/2
✓ Branch 0 taken 622 times.
✓ Branch 1 taken 43 times.
665 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3662 622 sc->sample_size = sample_size;
3663 665 sc->stsz_sample_size = sample_size;
3664 665 field_size = 32;
3665 } else {
3666 sample_size = 0;
3667 avio_rb24(pb); /* reserved */
3668 field_size = avio_r8(pb);
3669 }
3670 665 entries = avio_rb32(pb);
3671
3672 665 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3673
3674 665 sc->sample_count = entries;
3675
2/2
✓ Branch 0 taken 213 times.
✓ Branch 1 taken 452 times.
665 if (sample_size)
3676 213 return 0;
3677
3678
4/8
✓ Branch 0 taken 452 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 452 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 452 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 452 times.
452 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
3679 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3680 return AVERROR_INVALIDDATA;
3681 }
3682
3683
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 423 times.
452 if (!entries)
3684 29 return 0;
3685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 if (entries >= (INT_MAX - 4 - 8 * AV_INPUT_BUFFER_PADDING_SIZE) / field_size)
3686 return AVERROR_INVALIDDATA;
3687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 if (sc->sample_sizes)
3688 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3689 423 av_free(sc->sample_sizes);
3690 423 sc->sample_count = 0;
3691 423 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 if (!sc->sample_sizes)
3693 return AVERROR(ENOMEM);
3694
3695 423 num_bytes = (entries*field_size+4)>>3;
3696
3697 423 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 if (!buf) {
3699 av_freep(&sc->sample_sizes);
3700 return AVERROR(ENOMEM);
3701 }
3702
3703 423 ret = ffio_read_size(pb, buf, num_bytes);
3704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 if (ret < 0) {
3705 av_freep(&sc->sample_sizes);
3706 av_free(buf);
3707 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3708 return 0;
3709 }
3710
3711 423 init_get_bits(&gb, buf, 8*num_bytes);
3712
3713
2/2
✓ Branch 0 taken 238641 times.
✓ Branch 1 taken 423 times.
239064 for (i = 0; i < entries; i++) {
3714 238641 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 238641 times.
238641 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3716 av_free(buf);
3717 av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3718 return AVERROR_INVALIDDATA;
3719 }
3720 238641 sc->data_size += sc->sample_sizes[i];
3721 }
3722
3723 423 sc->sample_count = i;
3724
3725 423 av_free(buf);
3726
3727 423 return 0;
3728 }
3729
3730 665 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3731 {
3732 AVStream *st;
3733 MOVStreamContext *sc;
3734 unsigned int i, entries;
3735 665 int64_t duration = 0;
3736 665 int64_t total_sample_count = 0;
3737 665 int64_t current_dts = 0;
3738 665 int64_t corrected_dts = 0;
3739
3740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (c->trak_index < 0) {
3741 av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3742 return 0;
3743 }
3744
3745
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (c->fc->nb_streams < 1)
3746 return 0;
3747 665 st = c->fc->streams[c->fc->nb_streams-1];
3748 665 sc = st->priv_data;
3749
3750 665 avio_r8(pb); /* version */
3751 665 avio_rb24(pb); /* flags */
3752 665 entries = avio_rb32(pb);
3753
3754 665 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3755 665 c->fc->nb_streams-1, entries);
3756
3757
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (sc->stts_data)
3758 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3759 665 av_freep(&sc->stts_data);
3760 665 sc->stts_count = 0;
3761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3762 return AVERROR(ENOMEM);
3763
3764
3/4
✓ Branch 0 taken 3028 times.
✓ Branch 1 taken 665 times.
✓ Branch 2 taken 3028 times.
✗ Branch 3 not taken.
3693 for (i = 0; i < entries && !pb->eof_reached; i++) {
3765 unsigned int sample_duration;
3766 unsigned int sample_count;
3767 3028 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3768 3028 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3769 min_entries * sizeof(*sc->stts_data));
3770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3028 times.
3028 if (!stts_data) {
3771 av_freep(&sc->stts_data);
3772 sc->stts_count = 0;
3773 return AVERROR(ENOMEM);
3774 }
3775 3028 sc->stts_count = min_entries;
3776 3028 sc->stts_data = stts_data;
3777
3778 3028 sample_count = avio_rb32(pb);
3779 3028 sample_duration = avio_rb32(pb);
3780
3781 3028 sc->stts_data[i].count= sample_count;
3782 3028 sc->stts_data[i].duration= sample_duration;
3783
3784 3028 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3785 sample_count, sample_duration);
3786
3787 /* STTS sample offsets are uint32 but some files store it as int32
3788 * with negative values used to correct DTS delays.
3789 There may be abnormally large values as well. */
3790
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3027 times.
3028 if (sample_duration > c->max_stts_delta) {
3791 // assume high delta is a correction if negative when cast as int32
3792 1 int32_t delta_magnitude = (int32_t)sample_duration;
3793 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",
3794 sample_duration, i, sample_count, st->index);
3795 1 sc->stts_data[i].duration = 1;
3796
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);
3797 } else {
3798 3027 corrected_dts += sample_duration * (uint64_t)sample_count;
3799 }
3800
3801 3028 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3802
3803
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 3006 times.
3028 if (current_dts > corrected_dts) {
3804 22 int64_t drift = av_sat_sub64(current_dts, corrected_dts) / FFMAX(sample_count, 1);
3805
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;
3806 22 current_dts -= correction * (uint64_t)sample_count;
3807 22 sc->stts_data[i].duration -= correction;
3808 }
3809
3810 3028 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3811 3028 total_sample_count+=sc->stts_data[i].count;
3812 }
3813
3814 665 sc->stts_count = i;
3815
3816
2/2
✓ Branch 0 taken 636 times.
✓ Branch 1 taken 29 times.
665 if (duration > 0 &&
3817
1/2
✓ Branch 0 taken 636 times.
✗ Branch 1 not taken.
636 duration <= INT64_MAX - sc->duration_for_fps &&
3818
1/2
✓ Branch 0 taken 636 times.
✗ Branch 1 not taken.
636 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3819 636 sc->duration_for_fps += duration;
3820 636 sc->nb_frames_for_fps += total_sample_count;
3821 }
3822
3823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (pb->eof_reached) {
3824 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3825 return AVERROR_EOF;
3826 }
3827
3828 665 st->nb_frames= total_sample_count;
3829
2/2
✓ Branch 0 taken 636 times.
✓ Branch 1 taken 29 times.
665 if (duration)
3830 636 st->duration= FFMIN(st->duration, duration);
3831
3832 // All samples have zero duration. They have higher chance be chose by
3833 // mov_find_next_sample, which leads to seek again and again.
3834 //
3835 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3836 // So only mark data stream as discarded for safety.
3837
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 636 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 29 times.
665 if (!duration && sc->stts_count &&
3838 st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3839 av_log(c->fc, AV_LOG_WARNING,
3840 "All samples in data stream index:id [%d:%d] have zero "
3841 "duration, stream set to be discarded by default. Override "
3842 "using AVStream->discard or -discard for ffmpeg command.\n",
3843 st->index, sc->id);
3844 st->discard = AVDISCARD_ALL;
3845 }
3846 665 sc->track_end = duration;
3847 665 return 0;
3848 }
3849
3850 45 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3851 {
3852 AVStream *st;
3853 MOVStreamContext *sc;
3854 unsigned int i;
3855 int64_t entries;
3856
3857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (c->fc->nb_streams < 1)
3858 return 0;
3859 45 st = c->fc->streams[c->fc->nb_streams - 1];
3860 45 sc = st->priv_data;
3861
3862 45 avio_r8(pb); /* version */
3863 45 avio_rb24(pb); /* flags */
3864 45 entries = atom.size - 4;
3865
3866 45 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3867 45 c->fc->nb_streams - 1, entries);
3868
3869
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 37 times.
45 if (sc->sdtp_data)
3870 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3871 45 av_freep(&sc->sdtp_data);
3872 45 sc->sdtp_count = 0;
3873
3874
2/4
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 45 times.
45 if (entries < 0 || entries > UINT_MAX)
3875 return AVERROR(ERANGE);
3876
3877 45 sc->sdtp_data = av_malloc(entries);
3878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (!sc->sdtp_data)
3879 return AVERROR(ENOMEM);
3880
3881
3/4
✓ Branch 0 taken 3811 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 3811 times.
✗ Branch 3 not taken.
3856 for (i = 0; i < entries && !pb->eof_reached; i++)
3882 3811 sc->sdtp_data[i] = avio_r8(pb);
3883 45 sc->sdtp_count = i;
3884
3885 45 return 0;
3886 }
3887
3888 13717 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3889 {
3890
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 12581 times.
13717 if (duration < 0) {
3891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3892 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3893 duration++;
3894 }
3895 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3896 }
3897 13717 }
3898
3899 74 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3900 {
3901 AVStream *st;
3902 MOVStreamContext *sc;
3903 74 unsigned int i, entries, ctts_count = 0;
3904
3905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 if (c->trak_index < 0) {
3906 av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
3907 return 0;
3908 }
3909
3910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 if (c->fc->nb_streams < 1)
3911 return 0;
3912 74 st = c->fc->streams[c->fc->nb_streams-1];
3913 74 sc = st->priv_data;
3914
3915 74 avio_r8(pb); /* version */
3916 74 avio_rb24(pb); /* flags */
3917 74 entries = avio_rb32(pb);
3918
3919 74 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3920
3921
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 70 times.
74 if (!entries)
3922 4 return 0;
3923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
3924 return AVERROR_INVALIDDATA;
3925 70 av_freep(&sc->ctts_data);
3926 70 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
3927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 if (!sc->ctts_data)
3928 return AVERROR(ENOMEM);
3929
3930
3/4
✓ Branch 0 taken 5138 times.
✓ Branch 1 taken 70 times.
✓ Branch 2 taken 5138 times.
✗ Branch 3 not taken.
5208 for (i = 0; i < entries && !pb->eof_reached; i++) {
3931 MOVCtts *ctts_data;
3932 5138 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
3933 5138 const size_t requested_size =
3934 5138 min_size_needed > sc->ctts_allocated_size ?
3935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5138 times.
5138 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
3936 min_size_needed;
3937 5138 int count = avio_rb32(pb);
3938 5138 int duration = avio_rb32(pb);
3939
3940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5138 times.
5138 if (count <= 0) {
3941 av_log(c->fc, AV_LOG_TRACE,
3942 "ignoring CTTS entry with count=%d duration=%d\n",
3943 count, duration);
3944 continue;
3945 }
3946
3947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5138 times.
5138 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
3948 return AVERROR(ENOMEM);
3949
3950 5138 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
3951
3952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5138 times.
5138 if (!ctts_data)
3953 return AVERROR(ENOMEM);
3954
3955 5138 sc->ctts_data = ctts_data;
3956
3957 5138 ctts_data[ctts_count].count = count;
3958 5138 ctts_data[ctts_count].offset = duration;
3959 5138 ctts_count++;
3960
3961 5138 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
3962 count, duration);
3963
3964
2/2
✓ Branch 0 taken 5010 times.
✓ Branch 1 taken 128 times.
5138 if (i+2<entries)
3965 5010 mov_update_dts_shift(sc, duration, c->fc);
3966 }
3967
3968 70 sc->ctts_count = ctts_count;
3969
3970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 if (pb->eof_reached) {
3971 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
3972 return AVERROR_EOF;
3973 }
3974
3975 70 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
3976
3977 70 return 0;
3978 }
3979
3980 51 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3981 {
3982 AVStream *st;
3983 MOVStreamContext *sc;
3984 uint8_t version;
3985 uint32_t grouping_type;
3986 uint32_t default_length;
3987 av_unused uint32_t default_group_description_index;
3988 uint32_t entry_count;
3989
3990
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (c->fc->nb_streams < 1)
3991 return 0;
3992 51 st = c->fc->streams[c->fc->nb_streams - 1];
3993 51 sc = st->priv_data;
3994
3995 51 version = avio_r8(pb); /* version */
3996 51 avio_rb24(pb); /* flags */
3997 51 grouping_type = avio_rl32(pb);
3998
3999 /*
4000 * This function only supports "sync" boxes, but the code is able to parse
4001 * other boxes (such as "tscl", "tsas" and "stsa")
4002 */
4003
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 5 times.
51 if (grouping_type != MKTAG('s','y','n','c'))
4004 46 return 0;
4005
4006
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
4007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
4008 5 entry_count = avio_rb32(pb);
4009
4010 5 av_freep(&sc->sgpd_sync);
4011 5 sc->sgpd_sync_count = entry_count;
4012 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
4013
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
4014 return AVERROR(ENOMEM);
4015
4016
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++) {
4017 8 uint32_t description_length = default_length;
4018
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)
4019 description_length = avio_rb32(pb);
4020
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
4021 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
4022 8 sc->sgpd_sync[i] = nal_unit_type;
4023 8 description_length -= 1;
4024 }
4025 8 avio_skip(pb, description_length);
4026 }
4027
4028
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
4029 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
4030 return AVERROR_EOF;
4031 }
4032
4033 5 return 0;
4034 }
4035
4036 47 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4037 {
4038 AVStream *st;
4039 MOVStreamContext *sc;
4040 unsigned int i, entries;
4041 uint8_t version;
4042 uint32_t grouping_type;
4043 MOVSbgp *table, **tablep;
4044 int *table_count;
4045
4046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 if (c->fc->nb_streams < 1)
4047 return 0;
4048 47 st = c->fc->streams[c->fc->nb_streams-1];
4049 47 sc = st->priv_data;
4050
4051 47 version = avio_r8(pb); /* version */
4052 47 avio_rb24(pb); /* flags */
4053 47 grouping_type = avio_rl32(pb);
4054
4055
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 46 times.
47 if (grouping_type == MKTAG('r','a','p',' ')) {
4056 1 tablep = &sc->rap_group;
4057 1 table_count = &sc->rap_group_count;
4058
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 41 times.
46 } else if (grouping_type == MKTAG('s','y','n','c')) {
4059 5 tablep = &sc->sync_group;
4060 5 table_count = &sc->sync_group_count;
4061 } else {
4062 41 return 0;
4063 }
4064
4065
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
4066 avio_rb32(pb); /* grouping_type_parameter */
4067
4068 6 entries = avio_rb32(pb);
4069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
4070 return 0;
4071
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
4072 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
4073 6 av_freep(tablep);
4074 6 table = av_malloc_array(entries, sizeof(*table));
4075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
4076 return AVERROR(ENOMEM);
4077 6 *tablep = table;
4078
4079
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++) {
4080 32 table[i].count = avio_rb32(pb); /* sample_count */
4081 32 table[i].index = avio_rb32(pb); /* group_description_index */
4082 }
4083
4084 6 *table_count = i;
4085
4086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
4087 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
4088 return AVERROR_EOF;
4089 }
4090
4091 6 return 0;
4092 }
4093
4094 /**
4095 * Get ith edit list entry (media time, duration).
4096 */
4097 1003 static int get_edit_list_entry(MOVContext *mov,
4098 const MOVStreamContext *msc,
4099 unsigned int edit_list_index,
4100 int64_t *edit_list_media_time,
4101 int64_t *edit_list_duration,
4102 int64_t global_timescale)
4103 {
4104
2/2
✓ Branch 0 taken 487 times.
✓ Branch 1 taken 516 times.
1003 if (edit_list_index == msc->elst_count) {
4105 487 return 0;
4106 }
4107 516 *edit_list_media_time = msc->elst_data[edit_list_index].time;
4108 516 *edit_list_duration = msc->elst_data[edit_list_index].duration;
4109
4110 /* duration is in global timescale units;convert to msc timescale */
4111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 516 times.
516 if (global_timescale == 0) {
4112 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
4113 return 0;
4114 }
4115 516 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
4116 global_timescale);
4117
4118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 516 times.
516 if (*edit_list_duration + (uint64_t)*edit_list_media_time > INT64_MAX)
4119 *edit_list_duration = 0;
4120
4121 516 return 1;
4122 }
4123
4124 /**
4125 * Find the closest previous frame to the timestamp_pts, in e_old index
4126 * entries. Searching for just any frame / just key frames can be controlled by
4127 * last argument 'flag'.
4128 * Note that if ctts_data is not NULL, we will always search for a key frame
4129 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
4130 * return the first frame of the video.
4131 *
4132 * Here the timestamp_pts is considered to be a presentation timestamp and
4133 * the timestamp of index entries are considered to be decoding timestamps.
4134 *
4135 * Returns 0 if successful in finding a frame, else returns -1.
4136 * Places the found index corresponding output arg.
4137 *
4138 * If ctts_old is not NULL, then refines the searched entry by searching
4139 * backwards from the found timestamp, to find the frame with correct PTS.
4140 *
4141 * Places the found ctts_index and ctts_sample in corresponding output args.
4142 */
4143 516 static int find_prev_closest_index(AVStream *st,
4144 AVIndexEntry *e_old,
4145 int nb_old,
4146 MOVTimeToSample *tts_data,
4147 int64_t tts_count,
4148 int64_t timestamp_pts,
4149 int flag,
4150 int64_t* index,
4151 int64_t* tts_index,
4152 int64_t* tts_sample)
4153 {
4154 516 MOVStreamContext *msc = st->priv_data;
4155 516 FFStream *const sti = ffstream(st);
4156 516 AVIndexEntry *e_keep = sti->index_entries;
4157 516 int nb_keep = sti->nb_index_entries;
4158 516 int64_t i = 0;
4159
4160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 516 times.
516 av_assert0(index);
4161
4162 // If dts_shift > 0, then all the index timestamps will have to be offset by
4163 // at least dts_shift amount to obtain PTS.
4164 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
4165
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 507 times.
516 if (msc->dts_shift > 0) {
4166 9 timestamp_pts -= msc->dts_shift;
4167 }
4168
4169 516 sti->index_entries = e_old;
4170 516 sti->nb_index_entries = nb_old;
4171 516 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
4172
4173 // Keep going backwards in the index entries until the timestamp is the same.
4174
2/2
✓ Branch 0 taken 515 times.
✓ Branch 1 taken 1 times.
516 if (*index >= 0) {
4175
3/4
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 488 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
515 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
4176 i--) {
4177 if ((flag & AVSEEK_FLAG_ANY) ||
4178 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
4179 *index = i - 1;
4180 }
4181 }
4182 }
4183
4184 // If we have CTTS then refine the search, by searching backwards over PTS
4185 // computed by adding corresponding CTTS durations to index timestamps.
4186
4/4
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 438 times.
✓ Branch 2 taken 77 times.
✓ Branch 3 taken 1 times.
516 if (msc->ctts_count && *index >= 0) {
4187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 av_assert0(tts_index);
4188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 av_assert0(tts_sample);
4189 // Find out the ctts_index for the found frame.
4190 77 *tts_index = 0;
4191 77 *tts_sample = 0;
4192
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 77 times.
291 for (int64_t index_tts_count = 0; index_tts_count < *index; index_tts_count++) {
4193
1/2
✓ Branch 0 taken 214 times.
✗ Branch 1 not taken.
214 if (*tts_index < tts_count) {
4194 214 (*tts_sample)++;
4195
1/2
✓ Branch 0 taken 214 times.
✗ Branch 1 not taken.
214 if (tts_data[*tts_index].count == *tts_sample) {
4196 214 (*tts_index)++;
4197 214 *tts_sample = 0;
4198 }
4199 }
4200 }
4201
4202
4/6
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 87 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 87 times.
✗ Branch 5 not taken.
94 while (*index >= 0 && (*tts_index) >= 0 && (*tts_index) < tts_count) {
4203 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
4204 // No need to add dts_shift to the timestamp here because timestamp_pts has already been
4205 // compensated by dts_shift above.
4206
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 12 times.
87 if ((e_old[*index].timestamp + tts_data[*tts_index].offset) <= timestamp_pts &&
4207
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 5 times.
75 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
4208 70 break;
4209 }
4210
4211 17 (*index)--;
4212
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 if (*tts_sample == 0) {
4213 17 (*tts_index)--;
4214
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 7 times.
17 if (*tts_index >= 0)
4215 10 *tts_sample = tts_data[*tts_index].count - 1;
4216 } else {
4217 (*tts_sample)--;
4218 }
4219 }
4220 }
4221
4222 /* restore AVStream state*/
4223 516 sti->index_entries = e_keep;
4224 516 sti->nb_index_entries = nb_keep;
4225
2/2
✓ Branch 0 taken 508 times.
✓ Branch 1 taken 8 times.
516 return *index >= 0 ? 0 : -1;
4226 }
4227
4228 /**
4229 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
4230 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
4231 *
4232 * This function is similar to ff_add_index_entry in libavformat/utils.c
4233 * except that here we are always unconditionally adding an index entry to
4234 * the end, instead of searching the entries list and skipping the add if
4235 * there is an existing entry with the same timestamp.
4236 * This is needed because the mov_fix_index calls this func with the same
4237 * unincremented timestamp for successive discarded frames.
4238 */
4239 360122 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
4240 int size, int distance, int flags)
4241 {
4242 360122 FFStream *const sti = ffstream(st);
4243 AVIndexEntry *entries, *ie;
4244 360122 int64_t index = -1;
4245 360122 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
4246
4247 // Double the allocation each time, to lower memory fragmentation.
4248 // Another difference from ff_add_index_entry function.
4249 360122 const size_t requested_size =
4250 360122 min_size_needed > sti->index_entries_allocated_size ?
4251
2/2
✓ Branch 0 taken 2223 times.
✓ Branch 1 taken 357899 times.
360122 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
4252 min_size_needed;
4253
4254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 360122 times.
360122 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
4255 return -1;
4256
4257 360122 entries = av_fast_realloc(sti->index_entries,
4258 &sti->index_entries_allocated_size,
4259 requested_size);
4260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 360122 times.
360122 if (!entries)
4261 return -1;
4262
4263 360122 sti->index_entries = entries;
4264
4265 360122 index = sti->nb_index_entries++;
4266 360122 ie= &entries[index];
4267
4268 360122 ie->pos = pos;
4269 360122 ie->timestamp = timestamp;
4270 360122 ie->min_distance= distance;
4271 360122 ie->size= size;
4272 360122 ie->flags = flags;
4273 360122 return index;
4274 }
4275
4276 /**
4277 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4278 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4279 */
4280 47 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4281 int64_t* frame_duration_buffer,
4282 int frame_duration_buffer_size) {
4283 47 FFStream *const sti = ffstream(st);
4284 47 int i = 0;
4285
2/4
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 47 times.
47 av_assert0(end_index >= 0 && end_index <= sti->nb_index_entries);
4286
2/2
✓ Branch 0 taken 191 times.
✓ Branch 1 taken 47 times.
238 for (i = 0; i < frame_duration_buffer_size; i++) {
4287 191 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4288 191 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4289 }
4290 47 }
4291
4292 194895 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4293 int count, int offset, unsigned int duration)
4294 {
4295 MOVTimeToSample *tts_buf_new;
4296 194895 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4297 194895 const size_t requested_size =
4298 194895 min_size_needed > *allocated_size ?
4299
2/2
✓ Branch 0 taken 1555 times.
✓ Branch 1 taken 193340 times.
194895 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4300 min_size_needed;
4301
4302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 194895 times.
194895 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4303 return -1;
4304
4305 194895 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4306
4307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 194895 times.
194895 if (!tts_buf_new)
4308 return -1;
4309
4310 194895 *tts_data = tts_buf_new;
4311
4312 194895 tts_buf_new[*tts_count].count = count;
4313 194895 tts_buf_new[*tts_count].offset = offset;
4314 194895 tts_buf_new[*tts_count].duration = duration;
4315
4316 194895 *tts_count = (*tts_count) + 1;
4317 194895 return 0;
4318 }
4319
4320 #define MAX_REORDER_DELAY 16
4321 679 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4322 {
4323 679 MOVStreamContext *msc = st->priv_data;
4324 679 FFStream *const sti = ffstream(st);
4325 679 int ctts_ind = 0;
4326 679 int ctts_sample = 0;
4327 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4328 679 int buf_start = 0;
4329 int j, r, num_swaps;
4330
4331
2/2
✓ Branch 0 taken 11543 times.
✓ Branch 1 taken 679 times.
12222 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4332 11543 pts_buf[j] = INT64_MIN;
4333
4334
3/4
✓ Branch 0 taken 679 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 70 times.
✓ Branch 3 taken 609 times.
679 if (st->codecpar->video_delay <= 0 && msc->ctts_count &&
4335
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 26 times.
70 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4336 44 st->codecpar->video_delay = 0;
4337
3/4
✓ Branch 0 taken 138353 times.
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 138353 times.
✗ Branch 3 not taken.
138397 for (int ind = 0; ind < sti->nb_index_entries && ctts_ind < msc->tts_count; ++ind) {
4338 // Point j to the last elem of the buffer and insert the current pts there.
4339 138353 j = buf_start;
4340 138353 buf_start = (buf_start + 1);
4341
2/2
✓ Branch 0 taken 8115 times.
✓ Branch 1 taken 130238 times.
138353 if (buf_start == MAX_REORDER_DELAY + 1)
4342 8115 buf_start = 0;
4343
4344 138353 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4345
4346 // The timestamps that are already in the sorted buffer, and are greater than the
4347 // current pts, are exactly the timestamps that need to be buffered to output PTS
4348 // in correct sorted order.
4349 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4350 // can be computed as the maximum no. of swaps any particular timestamp needs to
4351 // go through, to keep this buffer in sorted order.
4352 138353 num_swaps = 0;
4353
2/2
✓ Branch 0 taken 142584 times.
✓ Branch 1 taken 4 times.
142588 while (j != buf_start) {
4354 142584 r = j - 1;
4355
2/2
✓ Branch 0 taken 8406 times.
✓ Branch 1 taken 134178 times.
142584 if (r < 0) r = MAX_REORDER_DELAY;
4356
2/2
✓ Branch 0 taken 4235 times.
✓ Branch 1 taken 138349 times.
142584 if (pts_buf[j] < pts_buf[r]) {
4357 4235 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4358 4235 ++num_swaps;
4359 } else {
4360 138349 break;
4361 }
4362 4235 j = r;
4363 }
4364 138353 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4365
4366 138353 ctts_sample++;
4367
1/2
✓ Branch 0 taken 138353 times.
✗ Branch 1 not taken.
138353 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4368 138353 ctts_ind++;
4369 138353 ctts_sample = 0;
4370 }
4371 }
4372 44 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4373 44 st->codecpar->video_delay, st->index);
4374 }
4375 679 }
4376
4377 116398 static void mov_current_sample_inc(MOVStreamContext *sc)
4378 {
4379 116398 sc->current_sample++;
4380 116398 sc->current_index++;
4381
2/2
✓ Branch 0 taken 70407 times.
✓ Branch 1 taken 45991 times.
116398 if (sc->index_ranges &&
4382
2/2
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 69937 times.
70407 sc->current_index >= sc->current_index_range->end &&
4383
1/2
✓ Branch 0 taken 470 times.
✗ Branch 1 not taken.
470 sc->current_index_range->end) {
4384 470 sc->current_index_range++;
4385 470 sc->current_index = sc->current_index_range->start;
4386 }
4387 116398 }
4388
4389 static void mov_current_sample_dec(MOVStreamContext *sc)
4390 {
4391 sc->current_sample--;
4392 sc->current_index--;
4393 if (sc->index_ranges &&
4394 sc->current_index < sc->current_index_range->start &&
4395 sc->current_index_range > sc->index_ranges) {
4396 sc->current_index_range--;
4397 sc->current_index = sc->current_index_range->end - 1;
4398 }
4399 }
4400
4401 337 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4402 {
4403 int64_t range_size;
4404
4405 337 sc->current_sample = current_sample;
4406 337 sc->current_index = current_sample;
4407
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 309 times.
337 if (!sc->index_ranges) {
4408 28 return;
4409 }
4410
4411 309 for (sc->current_index_range = sc->index_ranges;
4412
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 sc->current_index_range->end;
4413 sc->current_index_range++) {
4414 309 range_size = sc->current_index_range->end - sc->current_index_range->start;
4415
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 if (range_size > current_sample) {
4416 309 sc->current_index = sc->current_index_range->start + current_sample;
4417 309 break;
4418 }
4419 current_sample -= range_size;
4420 }
4421 }
4422
4423 /**
4424 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4425 * which are needed to decode them) that fall in the edit list time ranges.
4426 * Also fixes the timestamps of the index entries to match the timeline
4427 * specified the edit lists.
4428 */
4429 679 static void mov_fix_index(MOVContext *mov, AVStream *st)
4430 {
4431 679 MOVStreamContext *msc = st->priv_data;
4432 679 FFStream *const sti = ffstream(st);
4433 679 AVIndexEntry *e_old = sti->index_entries;
4434 679 int nb_old = sti->nb_index_entries;
4435 679 const AVIndexEntry *e_old_end = e_old + nb_old;
4436 679 const AVIndexEntry *current = NULL;
4437 679 MOVTimeToSample *tts_data_old = msc->tts_data;
4438 679 int64_t tts_index_old = 0;
4439 679 int64_t tts_sample_old = 0;
4440 679 int64_t tts_count_old = msc->tts_count;
4441 679 int64_t edit_list_media_time = 0;
4442 679 int64_t edit_list_duration = 0;
4443 679 int64_t frame_duration = 0;
4444 679 int64_t edit_list_dts_counter = 0;
4445 679 int64_t edit_list_dts_entry_end = 0;
4446 679 int64_t edit_list_start_tts_sample = 0;
4447 int64_t curr_cts;
4448 679 int64_t curr_ctts = 0;
4449 679 int64_t empty_edits_sum_duration = 0;
4450 679 int64_t edit_list_index = 0;
4451 int64_t index;
4452 int flags;
4453 679 int64_t start_dts = 0;
4454 679 int64_t edit_list_start_encountered = 0;
4455 679 int64_t search_timestamp = 0;
4456 679 int64_t* frame_duration_buffer = NULL;
4457 679 int num_discarded_begin = 0;
4458 679 int first_non_zero_audio_edit = -1;
4459 679 int packet_skip_samples = 0;
4460 679 MOVIndexRange *current_index_range = NULL;
4461 679 int found_keyframe_after_edit = 0;
4462 679 int found_non_empty_edit = 0;
4463
4464
4/6
✓ Branch 0 taken 487 times.
✓ Branch 1 taken 192 times.
✓ Branch 2 taken 487 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 487 times.
679 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
4465 192 return;
4466 }
4467
4468 // allocate the index ranges array
4469 487 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4470 sizeof(msc->index_ranges[0]));
4471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 487 times.
487 if (!msc->index_ranges) {
4472 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4473 return;
4474 }
4475 487 msc->current_index_range = msc->index_ranges;
4476
4477 // Clean AVStream from traces of old index
4478 487 sti->index_entries = NULL;
4479 487 sti->index_entries_allocated_size = 0;
4480 487 sti->nb_index_entries = 0;
4481
4482 // Clean time to sample fields of MOVStreamContext
4483 487 msc->tts_data = NULL;
4484 487 msc->tts_count = 0;
4485 487 msc->tts_index = 0;
4486 487 msc->tts_sample = 0;
4487 487 msc->tts_allocated_size = 0;
4488
4489 // Reinitialize min_corrected_pts so that it can be computed again.
4490 487 msc->min_corrected_pts = -1;
4491
4492 // If the dts_shift is positive (in case of negative ctts values in mov),
4493 // then negate the DTS by dts_shift
4494
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 478 times.
487 if (msc->dts_shift > 0) {
4495 9 edit_list_dts_entry_end -= msc->dts_shift;
4496 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4497 }
4498
4499 487 start_dts = edit_list_dts_entry_end;
4500
4501
2/2
✓ Branch 0 taken 516 times.
✓ Branch 1 taken 487 times.
1490 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
4502 1003 &edit_list_duration, mov->time_scale)) {
4503 516 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4504 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4505 516 edit_list_index++;
4506 516 edit_list_dts_counter = edit_list_dts_entry_end;
4507 516 edit_list_dts_entry_end = av_sat_add64(edit_list_dts_entry_end, edit_list_duration);
4508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 516 times.
516 if (edit_list_dts_entry_end == INT64_MAX) {
4509 av_log(mov->fc, AV_LOG_ERROR, "Cannot calculate dts entry length with duration %"PRId64"\n",
4510 edit_list_duration);
4511 break;
4512 }
4513 516 num_discarded_begin = 0;
4514
4/4
✓ Branch 0 taken 491 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 487 times.
516 if (!found_non_empty_edit && edit_list_media_time == -1) {
4515 4 empty_edits_sum_duration += edit_list_duration;
4516 4 continue;
4517 }
4518 512 found_non_empty_edit = 1;
4519
4520 // If we encounter a non-negative edit list reset the skip_samples/initial_padding fields and set them
4521 // according to the edit list below.
4522
2/2
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 357 times.
512 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4523
1/2
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
155 if (first_non_zero_audio_edit < 0) {
4524 155 first_non_zero_audio_edit = 1;
4525 } else {
4526 first_non_zero_audio_edit = 0;
4527 }
4528
4529
1/2
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
155 if (first_non_zero_audio_edit > 0)
4530 155 sti->skip_samples = st->codecpar->initial_padding = 0;
4531 }
4532
4533 // While reordering frame index according to edit list we must handle properly
4534 // the scenario when edit list entry starts from none key frame.
4535 // We find closest previous key frame and preserve it and consequent frames in index.
4536 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4537 512 search_timestamp = edit_list_media_time;
4538
2/2
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 357 times.
512 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4539 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4540 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4541 // edit_list_media_time to cover the decoder delay.
4542 155 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
4543 }
4544
4545
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 508 times.
512 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, 0,
4546 &index, &tts_index_old, &tts_sample_old) < 0) {
4547 4 av_log(mov->fc, AV_LOG_WARNING,
4548 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4549 st->index, edit_list_index, search_timestamp);
4550
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, AVSEEK_FLAG_ANY,
4551 &index, &tts_index_old, &tts_sample_old) < 0) {
4552 4 av_log(mov->fc, AV_LOG_WARNING,
4553 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4554 st->index, edit_list_index, search_timestamp);
4555 4 index = 0;
4556 4 tts_index_old = 0;
4557 4 tts_sample_old = 0;
4558 }
4559 }
4560 512 current = e_old + index;
4561 512 edit_list_start_tts_sample = tts_sample_old;
4562
4563 // Iterate over index and arrange it according to edit list
4564 512 edit_list_start_encountered = 0;
4565 512 found_keyframe_after_edit = 0;
4566
2/2
✓ Branch 0 taken 360122 times.
✓ Branch 1 taken 128 times.
360250 for (; current < e_old_end; current++, index++) {
4567 // check if frame outside edit list mark it for discard
4568 720244 frame_duration = (current + 1 < e_old_end) ?
4569
2/2
✓ Branch 0 taken 359643 times.
✓ Branch 1 taken 479 times.
360122 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4570
4571 360122 flags = current->flags;
4572
4573 // frames (pts) before or after edit list
4574 360122 curr_cts = current->timestamp + msc->dts_shift;
4575 360122 curr_ctts = 0;
4576
4577
4/4
✓ Branch 0 taken 194907 times.
✓ Branch 1 taken 165215 times.
✓ Branch 2 taken 194895 times.
✓ Branch 3 taken 12 times.
360122 if (tts_data_old && tts_index_old < tts_count_old) {
4578 194895 curr_ctts = tts_data_old[tts_index_old].offset;
4579 194895 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4580 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4581 194895 curr_cts += curr_ctts;
4582 194895 tts_sample_old++;
4583
1/2
✓ Branch 0 taken 194895 times.
✗ Branch 1 not taken.
194895 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 194895 times.
194895 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4585 &msc->tts_allocated_size,
4586 194895 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4587 194895 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4588 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4589 tts_index_old,
4590 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4591 tts_data_old[tts_index_old].offset);
4592 break;
4593 }
4594 194895 tts_index_old++;
4595 194895 tts_sample_old = 0;
4596 194895 edit_list_start_tts_sample = 0;
4597 }
4598 }
4599
4600
4/4
✓ Branch 0 taken 359905 times.
✓ Branch 1 taken 217 times.
✓ Branch 2 taken 157 times.
✓ Branch 3 taken 359748 times.
360122 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
4601
4/4
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 256 times.
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 44 times.
374 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
4602
4/6
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 52 times.
✓ Branch 4 taken 22 times.
✗ Branch 5 not taken.
74 curr_cts < edit_list_media_time && curr_cts + frame_duration > edit_list_media_time &&
4603 first_non_zero_audio_edit > 0) {
4604 22 packet_skip_samples = edit_list_media_time - curr_cts;
4605 22 sti->skip_samples += packet_skip_samples;
4606
4607 // Shift the index entry timestamp by packet_skip_samples to be correct.
4608 22 edit_list_dts_counter -= packet_skip_samples;
4609
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (edit_list_start_encountered == 0) {
4610 22 edit_list_start_encountered = 1;
4611 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4612 // discarded packets.
4613
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 7 times.
22 if (frame_duration_buffer) {
4614 15 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4615 frame_duration_buffer, num_discarded_begin);
4616 15 av_freep(&frame_duration_buffer);
4617 }
4618 }
4619
4620 22 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4621 } else {
4622 352 flags |= AVINDEX_DISCARD_FRAME;
4623 352 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4624
4625
2/2
✓ Branch 0 taken 193 times.
✓ Branch 1 taken 159 times.
352 if (edit_list_start_encountered == 0) {
4626 193 num_discarded_begin++;
4627 193 frame_duration_buffer = av_realloc(frame_duration_buffer,
4628 num_discarded_begin * sizeof(int64_t));
4629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 193 times.
193 if (!frame_duration_buffer) {
4630 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4631 break;
4632 }
4633 193 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4634
4635 // Increment skip_samples for the first non-zero audio edit list
4636
3/4
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 97 times.
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
193 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4637
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 44 times.
96 first_non_zero_audio_edit > 0 && st->codecpar->codec_id != AV_CODEC_ID_VORBIS) {
4638 52 sti->skip_samples += frame_duration;
4639 }
4640 }
4641 }
4642 } else {
4643
2/2
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 359262 times.
359748 if (msc->min_corrected_pts < 0) {
4644 486 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4645 } else {
4646 359262 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4647 }
4648
2/2
✓ Branch 0 taken 488 times.
✓ Branch 1 taken 359260 times.
359748 if (edit_list_start_encountered == 0) {
4649 488 edit_list_start_encountered = 1;
4650 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4651 // discarded packets.
4652
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 456 times.
488 if (frame_duration_buffer) {
4653 32 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4654 frame_duration_buffer, num_discarded_begin);
4655 32 av_freep(&frame_duration_buffer);
4656 }
4657 }
4658 }
4659
4660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 360122 times.
360122 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
4661 360122 current->min_distance, flags) == -1) {
4662 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4663 break;
4664 }
4665
4666 // Update the index ranges array
4667
4/4
✓ Branch 0 taken 359635 times.
✓ Branch 1 taken 487 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 359612 times.
360122 if (!current_index_range || index != current_index_range->end) {
4668 510 current_index_range = current_index_range ? current_index_range + 1
4669
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 487 times.
510 : msc->index_ranges;
4670 510 current_index_range->start = index;
4671 }
4672 360122 current_index_range->end = index + 1;
4673
4674 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4675
2/2
✓ Branch 0 taken 359929 times.
✓ Branch 1 taken 193 times.
360122 if (edit_list_start_encountered > 0) {
4676 359929 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4677 }
4678
4679 // Break when found first key frame after edit entry completion
4680
2/2
✓ Branch 0 taken 699 times.
✓ Branch 1 taken 359423 times.
360122 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
4681
4/4
✓ Branch 0 taken 295 times.
✓ Branch 1 taken 404 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 294 times.
699 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
4682
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 373 times.
405 if (msc->ctts_count) {
4683 // If we have CTTS and this is the first keyframe after edit elist,
4684 // wait for one more, because there might be trailing B-frames after this I-frame
4685 // that do belong to the edit.
4686
3/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 11 times.
32 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO && found_keyframe_after_edit == 0) {
4687 21 found_keyframe_after_edit = 1;
4688 21 continue;
4689 }
4690
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (tts_sample_old != 0) {
4691 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4692 &msc->tts_allocated_size,
4693 tts_sample_old - edit_list_start_tts_sample,
4694 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4695 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4696 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4697 tts_data_old[tts_index_old].offset);
4698 break;
4699 }
4700 }
4701 }
4702 384 break;
4703 }
4704 }
4705 }
4706 // If there are empty edits, then msc->min_corrected_pts might be positive
4707 // intentionally. So we subtract the sum duration of empty edits here.
4708 487 msc->min_corrected_pts -= empty_edits_sum_duration;
4709
4710 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4711 // dts by that amount to make the first pts zero.
4712
2/2
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 197 times.
487 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4713
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 238 times.
290 if (msc->min_corrected_pts > 0) {
4714 52 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4715
2/2
✓ Branch 0 taken 3120 times.
✓ Branch 1 taken 52 times.
3172 for (int i = 0; i < sti->nb_index_entries; ++i)
4716 3120 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4717 }
4718 }
4719 // Start time should be equal to zero or the duration of any empty edits.
4720 487 st->start_time = empty_edits_sum_duration;
4721
4722 // Update av stream length, if it ends up shorter than the track's media duration
4723 487 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4724 487 st->codecpar->initial_padding = sti->skip_samples;
4725
4726 // Free the old index and the old CTTS structures
4727 487 av_free(e_old);
4728 487 av_free(tts_data_old);
4729 487 av_freep(&frame_duration_buffer);
4730
4731 // Null terminate the index ranges array
4732 487 current_index_range = current_index_range ? current_index_range + 1
4733
1/2
✓ Branch 0 taken 487 times.
✗ Branch 1 not taken.
487 : msc->index_ranges;
4734 487 current_index_range->start = 0;
4735 487 current_index_range->end = 0;
4736 487 msc->current_index = msc->index_ranges[0].start;
4737 }
4738
4739 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4740 {
4741
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4742
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == nal_unit_type)
4743 5 return i + 1;
4744 return 0;
4745 }
4746
4747 708 static int build_open_gop_key_points(AVStream *st)
4748 {
4749 int k;
4750 708 int sample_id = 0;
4751 uint32_t cra_index;
4752 708 MOVStreamContext *sc = st->priv_data;
4753
4754
4/4
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 643 times.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 5 times.
708 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count)
4755 703 return 0;
4756
4757 /* Build an unrolled index of the samples */
4758 5 sc->sample_offsets_count = 0;
4759
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4761 return AVERROR(ENOMEM);
4762 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4763 }
4764 5 av_freep(&sc->sample_offsets);
4765 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4766
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4767 return AVERROR(ENOMEM);
4768 5 k = 0;
4769
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4770
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4771 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4772
4773 /* The following HEVC NAL type reveal the use of open GOP sync points
4774 * (TODO: BLA types may also be concerned) */
4775 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4777 return 0;
4778
4779 /* Build a list of open-GOP key samples */
4780 5 sc->open_key_samples_count = 0;
4781
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4782
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4783
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)
4784 return AVERROR(ENOMEM);
4785 11 sc->open_key_samples_count += sc->sync_group[i].count;
4786 }
4787 5 av_freep(&sc->open_key_samples);
4788 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4790 return AVERROR(ENOMEM);
4791 5 k = 0;
4792
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4793 28 const MOVSbgp *sg = &sc->sync_group[i];
4794
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4795
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4796 11 sc->open_key_samples[k++] = sample_id;
4797
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4798 return AVERROR_PATCHWELCOME;
4799 28 sample_id += sg->count;
4800 }
4801
4802 /* Identify the minimal time step between samples */
4803 5 sc->min_sample_duration = UINT_MAX;
4804
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4805 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4806
4807 5 return 0;
4808 }
4809
4810 #define MOV_MERGE_CTTS 1
4811 #define MOV_MERGE_STTS 2
4812 /*
4813 * Merge stts and ctts arrays into a new combined array.
4814 * stts_count and ctts_count may be left untouched as they will be
4815 * used to check for the presence of either of them.
4816 */
4817 679 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4818 {
4819 679 MOVStreamContext *sc = st->priv_data;
4820
3/4
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 609 times.
✓ Branch 2 taken 70 times.
✗ Branch 3 not taken.
679 int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS);
4821
3/4
✓ Branch 0 taken 679 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 611 times.
✓ Branch 3 taken 68 times.
679 int stts = sc->stts_data && (flags & MOV_MERGE_STTS);
4822 679 int idx = 0;
4823
4824
3/4
✓ Branch 0 taken 609 times.
✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 609 times.
679 if (!sc->ctts_data && !sc->stts_data)
4825 return 0;
4826 // Expand time to sample entries such that we have a 1-1 mapping with samples
4827
2/4
✓ Branch 0 taken 679 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 679 times.
679 if (!sc->sample_count || sc->sample_count >= UINT_MAX / sizeof(*sc->tts_data))
4828 return -1;
4829
4830
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 609 times.
679 if (ctts) {
4831 140 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4832 70 sc->sample_count * sizeof(*sc->tts_data));
4833
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 if (!sc->tts_data)
4834 return -1;
4835
4836 70 memset(sc->tts_data, 0, sc->tts_allocated_size);
4837
4838
2/2
✓ Branch 0 taken 5138 times.
✓ Branch 1 taken 70 times.
5208 for (int i = 0; i < sc->ctts_count &&
4839
1/2
✓ Branch 0 taken 5138 times.
✗ Branch 1 not taken.
10276 idx < sc->sample_count; i++)
4840
2/2
✓ Branch 0 taken 139282 times.
✓ Branch 1 taken 5138 times.
144420 for (int j = 0; j < sc->ctts_data[i].count &&
4841
1/2
✓ Branch 0 taken 139282 times.
✗ Branch 1 not taken.
139282 idx < sc->sample_count; j++) {
4842 139282 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4843 139282 sc->tts_data[idx++].count = 1;
4844 }
4845
4846 70 sc->tts_count = idx;
4847 } else
4848 609 sc->ctts_count = 0;
4849 679 av_freep(&sc->ctts_data);
4850 679 sc->ctts_allocated_size = 0;
4851
4852 679 idx = 0;
4853
2/2
✓ Branch 0 taken 611 times.
✓ Branch 1 taken 68 times.
679 if (stts) {
4854 611 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4855 611 sc->sample_count * sizeof(*sc->tts_data));
4856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 611 times.
611 if (!tts_data)
4857 return -1;
4858
4859
2/2
✓ Branch 0 taken 541 times.
✓ Branch 1 taken 70 times.
611 if (!sc->tts_data)
4860 541 memset(tts_data, 0, sc->tts_allocated_size);
4861 611 sc->tts_data = tts_data;
4862
4863
2/2
✓ Branch 0 taken 3003 times.
✓ Branch 1 taken 611 times.
3614 for (int i = 0; i < sc->stts_count &&
4864
1/2
✓ Branch 0 taken 3003 times.
✗ Branch 1 not taken.
6006 idx < sc->sample_count; i++)
4865
2/2
✓ Branch 0 taken 247685 times.
✓ Branch 1 taken 3003 times.
250688 for (int j = 0; j < sc->stts_data[i].count &&
4866
1/2
✓ Branch 0 taken 247685 times.
✗ Branch 1 not taken.
247685 idx < sc->sample_count; j++) {
4867 247685 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4868 247685 sc->tts_data[idx++].count = 1;
4869 }
4870
4871 611 sc->tts_count = FFMAX(sc->tts_count, idx);
4872 } else
4873 68 sc->stts_count = 0;
4874 679 av_freep(&sc->stts_data);
4875 679 sc->stts_allocated_size = 0;
4876
4877 679 return 0;
4878 }
4879
4880 708 static void mov_build_index(MOVContext *mov, AVStream *st)
4881 {
4882 708 MOVStreamContext *sc = st->priv_data;
4883 708 FFStream *const sti = ffstream(st);
4884 int64_t current_offset;
4885 708 int64_t current_dts = 0;
4886 708 unsigned int stts_index = 0;
4887 708 unsigned int stsc_index = 0;
4888 708 unsigned int stss_index = 0;
4889 708 unsigned int stps_index = 0;
4890 unsigned int i, j;
4891 708 uint64_t stream_size = 0;
4892
4893 708 int ret = build_open_gop_key_points(st);
4894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 708 times.
708 if (ret < 0)
4895 return;
4896
4897
2/2
✓ Branch 0 taken 490 times.
✓ Branch 1 taken 218 times.
708 if (sc->elst_count) {
4898 490 int i, edit_start_index = 0, multiple_edits = 0;
4899 490 int64_t empty_duration = 0; // empty duration of the first edit list entry
4900 490 int64_t start_time = 0; // start time of the media
4901
4902
2/2
✓ Branch 0 taken 519 times.
✓ Branch 1 taken 490 times.
1009 for (i = 0; i < sc->elst_count; i++) {
4903 519 const MOVElst *e = &sc->elst_data[i];
4904
4/4
✓ Branch 0 taken 490 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 486 times.
519 if (i == 0 && e->time == -1) {
4905 /* if empty, the first entry is the start time of the stream
4906 * relative to the presentation itself */
4907 4 empty_duration = e->duration;
4908 4 edit_start_index = 1;
4909
3/4
✓ Branch 0 taken 490 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 490 times.
✗ Branch 3 not taken.
515 } else if (i == edit_start_index && e->time >= 0) {
4910 490 start_time = e->time;
4911 } else {
4912 25 multiple_edits = 1;
4913 }
4914 }
4915
4916
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 483 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
490 if (multiple_edits && !mov->advanced_editlist) {
4917 if (mov->advanced_editlist_autodisabled)
4918 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4919 "not supported in fragmented MP4 files\n");
4920 else
4921 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4922 "Use -advanced_editlist to correctly decode otherwise "
4923 "a/v desync might occur\n");
4924 }
4925
4926 /* adjust first dts according to edit list */
4927
5/6
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 384 times.
✓ Branch 4 taken 106 times.
✗ Branch 5 not taken.
490 if ((empty_duration || start_time) && mov->time_scale > 0) {
4928
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 102 times.
106 if (empty_duration)
4929 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
4930
4931
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 106 times.
106 if (av_sat_sub64(start_time, empty_duration) != start_time - (uint64_t)empty_duration)
4932 av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
4933
4934 106 sc->time_offset = start_time - (uint64_t)empty_duration;
4935 106 sc->min_corrected_pts = start_time;
4936
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 105 times.
106 if (!mov->advanced_editlist)
4937 1 current_dts = -av_clip64(sc->time_offset, -INT64_MAX, INT64_MAX);
4938 }
4939
4940
4/4
✓ Branch 0 taken 483 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 480 times.
490 if (!multiple_edits && !mov->advanced_editlist &&
4941
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
3 st->codecpar->codec_id == AV_CODEC_ID_AAC && start_time > 0)
4942 st->codecpar->initial_padding = av_rescale_q(start_time, st->time_base,
4943 (AVRational){1, st->codecpar->sample_rate});
4944 }
4945
4946 /* only use old uncompressed audio chunk demuxing when stts specifies it */
4947
2/2
✓ Branch 0 taken 275 times.
✓ Branch 1 taken 433 times.
708 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
4948
5/6
✓ Branch 0 taken 227 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 227 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 159 times.
✓ Branch 5 taken 68 times.
886 sc->stts_count == 1 && sc->stts_data && sc->stts_data[0].duration == 1)) {
4949 640 unsigned int current_sample = 0;
4950 640 unsigned int stts_sample = 0;
4951 unsigned int sample_size;
4952 640 unsigned int distance = 0;
4953 640 unsigned int rap_group_index = 0;
4954 640 unsigned int rap_group_sample = 0;
4955
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 639 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
640 int rap_group_present = sc->rap_group_count && sc->rap_group;
4956
4/8
✓ Branch 0 taken 151 times.
✓ Branch 1 taken 489 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 151 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 489 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
640 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
4957
4958
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 640 times.
640 av_assert0(sc->dts_shift >= 0);
4959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 640 times.
640 if (current_dts < INT64_MIN + sc->dts_shift)
4960 return;
4961 640 current_dts -= sc->dts_shift;
4962
4/6
✓ Branch 0 taken 611 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 611 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 611 times.
640 if (!sc->sample_count || sti->nb_index_entries || sc->tts_count)
4963 29 return;
4964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 611 times.
611 if (sc->sample_count >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
4965 return;
4966
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 611 times.
611 if (av_reallocp_array(&sti->index_entries,
4967 611 sti->nb_index_entries + sc->sample_count,
4968 sizeof(*sti->index_entries)) < 0) {
4969 sti->nb_index_entries = 0;
4970 return;
4971 }
4972 611 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
4973
4974 611 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
4975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 611 times.
611 if (ret < 0)
4976 return;
4977
4978
2/2
✓ Branch 0 taken 174116 times.
✓ Branch 1 taken 611 times.
174727 for (i = 0; i < sc->chunk_count; i++) {
4979
2/2
✓ Branch 0 taken 173505 times.
✓ Branch 1 taken 611 times.
174116 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
4980 174116 current_offset = sc->chunk_offsets[i];
4981
2/2
✓ Branch 1 taken 8684 times.
✓ Branch 2 taken 167979 times.
176663 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4982
2/2
✓ Branch 0 taken 2547 times.
✓ Branch 1 taken 6137 times.
8684 i + 1 == sc->stsc_data[stsc_index + 1].first)
4983 2547 stsc_index++;
4984
4985
4/6
✓ Branch 0 taken 174116 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7404 times.
✓ Branch 3 taken 166712 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7404 times.
174116 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
4986 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
4987 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
4988 sc->stsz_sample_size = sc->sample_size;
4989 }
4990
3/4
✓ Branch 0 taken 7404 times.
✓ Branch 1 taken 166712 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7404 times.
174116 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
4991 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
4992 sc->stsz_sample_size = sc->sample_size;
4993 }
4994
4995
2/2
✓ Branch 0 taken 247685 times.
✓ Branch 1 taken 174116 times.
421801 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
4996 247685 int keyframe = 0;
4997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 247685 times.
247685 if (current_sample >= sc->sample_count) {
4998 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
4999 return;
5000 }
5001
5002
6/6
✓ Branch 0 taken 237974 times.
✓ Branch 1 taken 9711 times.
✓ Branch 2 taken 153133 times.
✓ Branch 3 taken 84841 times.
✓ Branch 4 taken 5736 times.
✓ Branch 5 taken 147397 times.
247685 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
5003 90577 keyframe = 1;
5004
2/2
✓ Branch 0 taken 5585 times.
✓ Branch 1 taken 84992 times.
90577 if (stss_index + 1 < sc->keyframe_count)
5005 5585 stss_index++;
5006
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 157108 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
157108 } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
5007 keyframe = 1;
5008 if (stps_index + 1 < sc->stps_count)
5009 stps_index++;
5010 }
5011
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 247497 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
247685 if (rap_group_present && rap_group_index < sc->rap_group_count) {
5012
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
5013 2 keyframe = 1;
5014
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
5015 4 rap_group_sample = 0;
5016 4 rap_group_index++;
5017 }
5018 }
5019
2/2
✓ Branch 0 taken 9711 times.
✓ Branch 1 taken 237974 times.
247685 if (sc->keyframe_absent
5020
1/2
✓ Branch 0 taken 9711 times.
✗ Branch 1 not taken.
9711 && !sc->stps_count
5021
1/2
✓ Branch 0 taken 9711 times.
✗ Branch 1 not taken.
9711 && !rap_group_present
5022
6/6
✓ Branch 0 taken 874 times.
✓ Branch 1 taken 8837 times.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 824 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 48 times.
9711 && (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || (i==0 && j==0)))
5023 8839 keyframe = 1;
5024
2/2
✓ Branch 0 taken 99416 times.
✓ Branch 1 taken 148269 times.
247685 if (keyframe)
5025 99416 distance = 0;
5026
2/2
✓ Branch 0 taken 9044 times.
✓ Branch 1 taken 238641 times.
247685 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
5027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 247685 times.
247685 if (current_offset > INT64_MAX - sample_size) {
5028 av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
5029 current_offset,
5030 sample_size);
5031 return;
5032 }
5033
5034
2/2
✓ Branch 0 taken 247592 times.
✓ Branch 1 taken 93 times.
247685 if (sc->pseudo_stream_id == -1 ||
5035
1/2
✓ Branch 0 taken 247592 times.
✗ Branch 1 not taken.
247592 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
5036 AVIndexEntry *e;
5037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 247685 times.
247685 if (sample_size > 0x3FFFFFFF) {
5038 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
5039 return;
5040 }
5041 247685 e = &sti->index_entries[sti->nb_index_entries++];
5042 247685 e->pos = current_offset;
5043 247685 e->timestamp = current_dts;
5044 247685 e->size = sample_size;
5045 247685 e->min_distance = distance;
5046 247685 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
5047 247685 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
5048 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
5049 current_offset, current_dts, sample_size, distance, keyframe);
5050
4/4
✓ Branch 0 taken 155470 times.
✓ Branch 1 taken 92215 times.
✓ Branch 2 taken 10837 times.
✓ Branch 3 taken 144633 times.
247685 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries < 100)
5051 10837 ff_rfps_add_frame(mov->fc, st, current_dts);
5052 }
5053
5054 247685 current_offset += sample_size;
5055 247685 stream_size += sample_size;
5056
5057
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 247685 times.
247685 if (current_dts > INT64_MAX - sc->tts_data[stts_index].duration)
5058 return;
5059 247685 current_dts += sc->tts_data[stts_index].duration;
5060
5061 247685 distance++;
5062 247685 stts_sample++;
5063 247685 current_sample++;
5064
3/4
✓ Branch 0 taken 247074 times.
✓ Branch 1 taken 611 times.
✓ Branch 2 taken 247074 times.
✗ Branch 3 not taken.
247685 if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) {
5065 247074 stts_sample = 0;
5066 247074 stts_index++;
5067 }
5068 }
5069 }
5070
2/2
✓ Branch 0 taken 568 times.
✓ Branch 1 taken 43 times.
611 if (st->duration > 0)
5071 568 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
5072 } else {
5073 68 unsigned chunk_samples, total = 0;
5074
5075
2/4
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 68 times.
68 if (!sc->chunk_count || sc->tts_count)
5076 return;
5077
5078 // compute total chunk count
5079
2/2
✓ Branch 0 taken 739 times.
✓ Branch 1 taken 68 times.
807 for (i = 0; i < sc->stsc_count; i++) {
5080 unsigned count, chunk_count;
5081
5082 739 chunk_samples = sc->stsc_data[i].count;
5083
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 68 times.
739 if (i != sc->stsc_count - 1 &&
5084
3/4
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 77 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 594 times.
671 sc->samples_per_frame && chunk_samples % sc->samples_per_frame) {
5085 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
5086 return;
5087 }
5088
5089
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 664 times.
739 if (sc->samples_per_frame >= 160) { // gsm
5090 75 count = chunk_samples / sc->samples_per_frame;
5091
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 133 times.
664 } else if (sc->samples_per_frame > 1) {
5092 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
5093 531 count = (chunk_samples+samples-1) / samples;
5094 } else {
5095 133 count = (chunk_samples+1023) / 1024;
5096 }
5097
5098
2/2
✓ Branch 1 taken 671 times.
✓ Branch 2 taken 68 times.
739 if (mov_stsc_index_valid(i, sc->stsc_count))
5099 671 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
5100 else
5101 68 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
5102 739 total += chunk_count * count;
5103 }
5104
5105 68 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
5106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
5107 return;
5108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (av_reallocp_array(&sti->index_entries,
5109 68 sti->nb_index_entries + total,
5110 sizeof(*sti->index_entries)) < 0) {
5111 sti->nb_index_entries = 0;
5112 return;
5113 }
5114 68 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
5115
5116 // populate index
5117
2/2
✓ Branch 0 taken 5560 times.
✓ Branch 1 taken 68 times.
5628 for (i = 0; i < sc->chunk_count; i++) {
5118 5560 current_offset = sc->chunk_offsets[i];
5119
2/2
✓ Branch 1 taken 5399 times.
✓ Branch 2 taken 161 times.
5560 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
5120
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 4728 times.
5399 i + 1 == sc->stsc_data[stsc_index + 1].first)
5121 671 stsc_index++;
5122 5560 chunk_samples = sc->stsc_data[stsc_index].count;
5123
5124
2/2
✓ Branch 0 taken 165262 times.
✓ Branch 1 taken 5560 times.
170822 while (chunk_samples > 0) {
5125 AVIndexEntry *e;
5126 unsigned size, samples;
5127
5128
3/4
✓ Branch 0 taken 23921 times.
✓ Branch 1 taken 141341 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 23921 times.
165262 if (sc->samples_per_frame > 1 && !sc->bytes_per_frame) {
5129 avpriv_request_sample(mov->fc,
5130 "Zero bytes per frame, but %d samples per frame",
5131 sc->samples_per_frame);
5132 return;
5133 }
5134
5135
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 150904 times.
165262 if (sc->samples_per_frame >= 160) { // gsm
5136 14358 samples = sc->samples_per_frame;
5137 14358 size = sc->bytes_per_frame;
5138 } else {
5139
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 141341 times.
150904 if (sc->samples_per_frame > 1) {
5140 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
5141 sc->samples_per_frame, chunk_samples);
5142 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
5143 } else {
5144 141341 samples = FFMIN(1024, chunk_samples);
5145 141341 size = samples * sc->sample_size;
5146 }
5147 }
5148
5149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165262 times.
165262 if (sti->nb_index_entries >= total) {
5150 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
5151 return;
5152 }
5153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165262 times.
165262 if (size > 0x3FFFFFFF) {
5154 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
5155 return;
5156 }
5157 165262 e = &sti->index_entries[sti->nb_index_entries++];
5158 165262 e->pos = current_offset;
5159 165262 e->timestamp = current_dts;
5160 165262 e->size = size;
5161 165262 e->min_distance = 0;
5162 165262 e->flags = AVINDEX_KEYFRAME;
5163 165262 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
5164 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
5165 size, samples);
5166
5167 165262 current_offset += size;
5168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165262 times.
165262 if (current_dts > INT64_MAX - samples)
5169 return;
5170 165262 current_dts += samples;
5171 165262 chunk_samples -= samples;
5172 }
5173 }
5174
5175 68 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
5176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (ret < 0)
5177 return;
5178 }
5179
5180
2/4
✓ Branch 0 taken 679 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 679 times.
✗ Branch 3 not taken.
679 if (!mov->ignore_editlist && mov->advanced_editlist) {
5181 // Fix index according to edit lists.
5182 679 mov_fix_index(mov, st);
5183 }
5184
5185 // Update start time of the stream.
5186
5/6
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 487 times.
✓ Branch 2 taken 70 times.
✓ Branch 3 taken 122 times.
✓ Branch 4 taken 70 times.
✗ Branch 5 not taken.
679 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) {
5187 70 st->start_time = av_sat_add64(sti->index_entries[0].timestamp, sc->dts_shift);
5188
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 if (sc->tts_data) {
5189 70 st->start_time = av_sat_add64(st->start_time, sc->tts_data[0].offset);
5190 }
5191 }
5192
5193 679 mov_estimate_video_delay(mov, st);
5194 }
5195
5196 static int test_same_origin(const char *src, const char *ref) {
5197 char src_proto[64];
5198 char ref_proto[64];
5199 char src_auth[256];
5200 char ref_auth[256];
5201 char src_host[256];
5202 char ref_host[256];
5203 int src_port=-1;
5204 int ref_port=-1;
5205
5206 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
5207 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
5208
5209 if (strlen(src) == 0) {
5210 return -1;
5211 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
5212 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
5213 strlen(src_host) + 1 >= sizeof(src_host) ||
5214 strlen(ref_host) + 1 >= sizeof(ref_host)) {
5215 return 0;
5216 } else if (strcmp(src_proto, ref_proto) ||
5217 strcmp(src_auth, ref_auth) ||
5218 strcmp(src_host, ref_host) ||
5219 src_port != ref_port) {
5220 return 0;
5221 } else
5222 return 1;
5223 }
5224
5225 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
5226 {
5227 /* try relative path, we do not try the absolute because it can leak information about our
5228 system to an attacker */
5229 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
5230 char filename[1025];
5231 const char *src_path;
5232 int i, l;
5233
5234 /* find a source dir */
5235 src_path = strrchr(src, '/');
5236 if (src_path)
5237 src_path++;
5238 else
5239 src_path = src;
5240
5241 /* find a next level down to target */
5242 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
5243 if (ref->path[l] == '/') {
5244 if (i == ref->nlvl_to - 1)
5245 break;
5246 else
5247 i++;
5248 }
5249
5250 /* compose filename if next level down to target was found */
5251 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
5252 memcpy(filename, src, src_path - src);
5253 filename[src_path - src] = 0;
5254
5255 for (i = 1; i < ref->nlvl_from; i++)
5256 av_strlcat(filename, "../", sizeof(filename));
5257
5258 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
5259 if (!c->use_absolute_path) {
5260 int same_origin = test_same_origin(src, filename);
5261
5262 if (!same_origin) {
5263 av_log(c->fc, AV_LOG_ERROR,
5264 "Reference with mismatching origin, %s not tried for security reasons, "
5265 "set demuxer option use_absolute_path to allow it anyway\n",
5266 ref->path);
5267 return AVERROR(ENOENT);
5268 }
5269
5270 if (strstr(ref->path + l + 1, "..") ||
5271 strstr(ref->path + l + 1, ":") ||
5272 (ref->nlvl_from > 1 && same_origin < 0) ||
5273 (filename[0] == '/' && src_path == src))
5274 return AVERROR(ENOENT);
5275 }
5276
5277 if (strlen(filename) + 1 == sizeof(filename))
5278 return AVERROR(ENOENT);
5279 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5280 return 0;
5281 }
5282 } else if (c->use_absolute_path) {
5283 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5284 "this is a possible security issue\n");
5285 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5286 return 0;
5287 } else {
5288 av_log(c->fc, AV_LOG_ERROR,
5289 "Absolute path %s not tried for security reasons, "
5290 "set demuxer option use_absolute_path to allow absolute paths\n",
5291 ref->path);
5292 }
5293
5294 return AVERROR(ENOENT);
5295 }
5296
5297 1441 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5298 {
5299
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1425 times.
1441 if (sc->time_scale <= 0) {
5300 16 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5301 16 sc->time_scale = c->time_scale;
5302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (sc->time_scale <= 0)
5303 sc->time_scale = 1;
5304 }
5305 1441 }
5306
5307 #if CONFIG_IAMFDEC
5308 12 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5309 {
5310 12 const MOVStreamContext *sc = st->priv_data;
5311 12 const IAMFContext *iamf = &sc->iamf->iamf;
5312
5313
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5314 12 const AVStreamGroup *stg = NULL;
5315
5316
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5317
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 if (c->fc->stream_groups[j]->id == iamf->audio_elements[i]->audio_element_id)
5318 12 stg = c->fc->stream_groups[j];
5319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 av_assert0(stg);
5320
5321
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_streams; j++) {
5322 64 const FFStream *sti = cffstream(st);
5323 64 AVStream *out = stg->streams[j];
5324 64 FFStream *out_sti = ffstream(stg->streams[j]);
5325
5326 64 out->codecpar->bit_rate = 0;
5327
5328
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 52 times.
64 if (out == st)
5329 12 continue;
5330
5331 52 out->time_base = st->time_base;
5332 52 out->start_time = st->start_time;
5333 52 out->duration = st->duration;
5334 52 out->nb_frames = st->nb_frames;
5335 52 out->discard = st->discard;
5336
5337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 av_assert0(!out_sti->index_entries);
5338 52 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (!out_sti->index_entries)
5340 return AVERROR(ENOMEM);
5341
5342 52 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5343 52 out_sti->nb_index_entries = sti->nb_index_entries;
5344 52 out_sti->skip_samples = sti->skip_samples;
5345 52 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5346 }
5347 }
5348
5349 12 return 0;
5350 }
5351 #endif
5352
5353 708 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5354 {
5355
4/6
✓ Branch 0 taken 679 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 679 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 679 times.
✗ Branch 5 not taken.
708 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5356
3/4
✓ Branch 0 taken 423 times.
✓ Branch 1 taken 256 times.
✓ Branch 2 taken 423 times.
✗ Branch 3 not taken.
679 (!sc->sample_size && !sc->sample_count))) ||
5357
3/4
✓ Branch 0 taken 679 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 679 times.
✗ Branch 3 not taken.
708 (sc->sample_count && (!sc->chunk_count ||
5358
3/4
✓ Branch 0 taken 423 times.
✓ Branch 1 taken 256 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 423 times.
679 (!sc->sample_size && !sc->sample_sizes)))) {
5359 av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5360 index);
5361 return 1;
5362 }
5363
5364
3/4
✓ Branch 0 taken 679 times.
✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 679 times.
708 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
5365 av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5366 index);
5367 return 2;
5368 }
5369 708 return 0;
5370 }
5371
5372 665 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5373 {
5374 AVStream *st;
5375 MOVStreamContext *sc;
5376 int ret;
5377
5378 665 st = avformat_new_stream(c->fc, NULL);
5379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (!st) return AVERROR(ENOMEM);
5380 665 st->id = -1;
5381 665 sc = av_mallocz(sizeof(MOVStreamContext));
5382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (!sc) return AVERROR(ENOMEM);
5383
5384 665 st->priv_data = sc;
5385 665 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5386 665 sc->ffindex = st->index;
5387 665 c->trak_index = st->index;
5388 665 sc->refcount = 1;
5389
5390
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 665 times.
665 if ((ret = mov_read_default(c, pb, atom)) < 0)
5391 return ret;
5392
5393 665 c->trak_index = -1;
5394
5395 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5396 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5397
5/6
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 636 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 28 times.
665 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
5398 1 sc->stsc_count = 0;
5399 1 av_freep(&sc->stsc_data);
5400 }
5401
5402 665 ret = sanity_checks(c->fc, sc, st->index);
5403
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (ret)
5404 return ret > 1 ? AVERROR_INVALIDDATA : 0;
5405
5406 665 fix_timescale(c, sc);
5407
5408 665 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5409
5410 /*
5411 * Advanced edit list support does not work with fragemented MP4s, which
5412 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5413 * In these files, trun atoms may be streamed in.
5414 */
5415
4/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 636 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 9 times.
665 if (!sc->stts_count && c->advanced_editlist) {
5416
5417 20 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5418 "MP4. disabling.\n");
5419 20 c->advanced_editlist = 0;
5420 20 c->advanced_editlist_autodisabled = 1;
5421 }
5422
5423 665 mov_build_index(c, st);
5424
5425 #if CONFIG_IAMFDEC
5426
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 653 times.
665 if (sc->iamf) {
5427 12 ret = mov_update_iamf_streams(c, st);
5428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
5429 return ret;
5430 }
5431 #endif
5432
5433
3/4
✓ Branch 0 taken 664 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 664 times.
665 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
5434 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5435 if (c->enable_drefs) {
5436 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5437 av_log(c->fc, AV_LOG_ERROR,
5438 "stream %d, error opening alias: path='%s', dir='%s', "
5439 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5440 st->index, dref->path, dref->dir, dref->filename,
5441 dref->volume, dref->nlvl_from, dref->nlvl_to);
5442 } else {
5443 av_log(c->fc, AV_LOG_WARNING,
5444 "Skipped opening external track: "
5445 "stream %d, alias: path='%s', dir='%s', "
5446 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5447 "Set enable_drefs to allow this.\n",
5448 st->index, dref->path, dref->dir, dref->filename,
5449 dref->volume, dref->nlvl_from, dref->nlvl_to);
5450 }
5451 } else {
5452 665 sc->pb = c->fc->pb;
5453 665 sc->pb_is_copied = 1;
5454 }
5455
5456
2/2
✓ Branch 0 taken 334 times.
✓ Branch 1 taken 331 times.
665 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5457
3/4
✓ Branch 0 taken 317 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 317 times.
✗ Branch 3 not taken.
334 int stts_constant = sc->stts_count && sc->tts_count;
5458
3/4
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 258 times.
✓ Branch 2 taken 76 times.
✗ Branch 3 not taken.
334 if (sc->h_spacing && sc->v_spacing)
5459 76 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5460 76 sc->h_spacing, sc->v_spacing, INT_MAX);
5461
4/6
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 79 times.
✓ Branch 2 taken 255 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 255 times.
✗ Branch 5 not taken.
334 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
5462
2/4
✓ Branch 0 taken 255 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 255 times.
✗ Branch 3 not taken.
255 sc->height && sc->width &&
5463
2/4
✓ Branch 0 taken 255 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 255 times.
255 (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
5464 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5465 (int64_t)st->codecpar->height * sc->width,
5466 (int64_t)st->codecpar->width * sc->height, INT_MAX);
5467 }
5468
5469 #if FF_API_R_FRAME_RATE
5470
4/4
✓ Branch 0 taken 155296 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 154979 times.
✓ Branch 3 taken 317 times.
155313 for (unsigned int i = 1; sc->stts_count && i + 1 < sc->tts_count; i++) {
5471
2/2
✓ Branch 0 taken 152495 times.
✓ Branch 1 taken 2484 times.
154979 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5472 152495 continue;
5473 2484 stts_constant = 0;
5474 }
5475
2/2
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 34 times.
334 if (stts_constant)
5476 300 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5477 300 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5478 #endif
5479 }
5480
5481 #if CONFIG_H261_DECODER || CONFIG_H263_DECODER || CONFIG_MPEG4_DECODER
5482
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 639 times.
665 switch (st->codecpar->codec_id) {
5483 #if CONFIG_H261_DECODER
5484 26 case AV_CODEC_ID_H261:
5485 #endif
5486 #if CONFIG_H263_DECODER
5487 case AV_CODEC_ID_H263:
5488 #endif
5489 #if CONFIG_MPEG4_DECODER
5490 case AV_CODEC_ID_MPEG4:
5491 #endif
5492 26 st->codecpar->width = 0; /* let decoder init width/height */
5493 26 st->codecpar->height= 0;
5494 26 break;
5495 }
5496 #endif
5497
5498 // If the duration of the mp3 packets is not constant, then they could need a parser
5499
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 662 times.
665 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5500
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 && sc->time_scale == st->codecpar->sample_rate) {
5501 3 int stts_constant = 1;
5502
3/4
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 365 times.
✓ Branch 3 taken 3 times.
368 for (int i = 1; sc->stts_count && i < sc->tts_count; i++) {
5503
1/2
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
365 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5504 365 continue;
5505 stts_constant = 0;
5506 }
5507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!stts_constant)
5508 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5509 }
5510 /* Do not need those anymore. */
5511 665 av_freep(&sc->chunk_offsets);
5512 665 av_freep(&sc->sample_sizes);
5513 665 av_freep(&sc->keyframes);
5514 665 av_freep(&sc->stps_data);
5515 665 av_freep(&sc->elst_data);
5516 665 av_freep(&sc->rap_group);
5517 665 av_freep(&sc->sync_group);
5518 665 av_freep(&sc->sgpd_sync);
5519
5520 665 return 0;
5521 }
5522
5523 159 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5524 {
5525 int ret;
5526 159 c->itunes_metadata = 1;
5527 159 ret = mov_read_default(c, pb, atom);
5528 159 c->itunes_metadata = 0;
5529 159 return ret;
5530 }
5531
5532 11 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5533 {
5534 uint32_t count;
5535 uint32_t i;
5536
5537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
5538 return 0;
5539
5540 11 avio_skip(pb, 4);
5541 11 count = avio_rb32(pb);
5542 11 atom.size -= 8;
5543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (count >= UINT_MAX / sizeof(*c->meta_keys)) {
5544 av_log(c->fc, AV_LOG_ERROR,
5545 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5546 return AVERROR_INVALIDDATA;
5547 }
5548
5549 11 c->meta_keys_count = count + 1;
5550 11 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
5551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!c->meta_keys)
5552 return AVERROR(ENOMEM);
5553
5554
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i <= count; ++i) {
5555 58 uint32_t key_size = avio_rb32(pb);
5556 58 uint32_t type = avio_rl32(pb);
5557
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) {
5558 av_log(c->fc, AV_LOG_ERROR,
5559 "The key# %"PRIu32" in meta has invalid size:"
5560 "%"PRIu32"\n", i, key_size);
5561 return AVERROR_INVALIDDATA;
5562 }
5563 58 atom.size -= key_size;
5564 58 key_size -= 8;
5565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (type != MKTAG('m','d','t','a')) {
5566 avio_skip(pb, key_size);
5567 continue;
5568 }
5569 58 c->meta_keys[i] = av_mallocz(key_size + 1);
5570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!c->meta_keys[i])
5571 return AVERROR(ENOMEM);
5572 58 avio_read(pb, c->meta_keys[i], key_size);
5573 }
5574
5575 11 return 0;
5576 }
5577
5578 73 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5579 {
5580 73 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5581 73 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5582 int i;
5583 73 int ret = 0;
5584 AVStream *st;
5585
5586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 if (c->fc->nb_streams < 1)
5587 return 0;
5588 73 st = c->fc->streams[c->fc->nb_streams-1];
5589
5590
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 73 times.
292 for (i = 0; i < 3; i++) {
5591 uint8_t **p;
5592 uint32_t len, tag;
5593
5594
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
219 if (end - avio_tell(pb) <= 12)
5595 break;
5596
5597 219 len = avio_rb32(pb);
5598 219 tag = avio_rl32(pb);
5599 219 avio_skip(pb, 4); // flags
5600
5601
2/4
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 219 times.
✗ Branch 4 not taken.
219 if (len < 12 || len - 12 > end - avio_tell(pb))
5602 break;
5603 219 len -= 12;
5604
5605
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 146 times.
219 if (tag == MKTAG('m', 'e', 'a', 'n'))
5606 73 p = &mean;
5607
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 73 times.
146 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5608 73 p = &key;
5609
2/4
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
73 else if (tag == MKTAG('d', 'a', 't', 'a') && len > 4) {
5610 73 avio_skip(pb, 4);
5611 73 len -= 4;
5612 73 p = &val;
5613 } else
5614 break;
5615
5616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (*p)
5617 break;
5618
5619 219 *p = av_malloc(len + 1);
5620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!*p) {
5621 ret = AVERROR(ENOMEM);
5622 break;
5623 }
5624 219 ret = ffio_read_size(pb, *p, len);
5625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (ret < 0) {
5626 av_freep(p);
5627 break;
5628 }
5629 219 (*p)[len] = 0;
5630 }
5631
5632
3/6
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 73 times.
✗ Branch 5 not taken.
73 if (mean && key && val) {
5633
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 38 times.
73 if (strcmp(key, "iTunSMPB") == 0) {
5634 int priming, remainder, samples;
5635
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
5636
2/4
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
✗ Branch 3 not taken.
35 if(priming>0 && priming<16384)
5637 35 st->codecpar->initial_padding = priming = av_rescale_q(priming, st->time_base,
5638 35 (AVRational){ 1, st->codecpar->sample_rate });
5639
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 if (remainder > 0) {
5640 35 int64_t duration = av_rescale_q(st->duration, st->time_base,
5641 35 (AVRational){ 1, st->codecpar->sample_rate });
5642 35 remainder = av_rescale_q(remainder, st->time_base,
5643 35 (AVRational){ 1, st->codecpar->sample_rate });
5644 35 samples = av_rescale_q(samples, st->time_base,
5645 35 (AVRational){ 1, st->codecpar->sample_rate });
5646
2/4
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
✗ Branch 3 not taken.
35 if (duration > remainder && duration > samples) {
5647 35 ffstream(st)->first_discard_sample = duration - remainder;
5648 35 ffstream(st)->last_discard_sample = duration;
5649 }
5650 }
5651 35 av_log(c->fc, AV_LOG_DEBUG, "Parsed iTunSMPB: priming %d, remainder %d samples %d\n",
5652 priming, remainder, samples);
5653 }
5654 }
5655
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 if (strcmp(mean, "com.apple.iTunes") == 0 &&
5656
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 71 times.
73 strcmp(key, "DISCSUBTITLE") == 0) {
5657 2 av_dict_set(&c->fc->metadata, "disc_subtitle", val,
5658 AV_DICT_DONT_STRDUP_VAL);
5659 2 val = NULL;
5660 }
5661
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 10 times.
136 if (strcmp(key, "cdec") != 0) {
5662 63 av_dict_set(&c->fc->metadata, key, val,
5663 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5664 63 key = val = NULL;
5665 }
5666 } else {
5667 av_log(c->fc, AV_LOG_VERBOSE,
5668 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5669 }
5670
5671 73 avio_seek(pb, end, SEEK_SET);
5672 73 av_freep(&key);
5673 73 av_freep(&val);
5674 73 av_freep(&mean);
5675 73 return ret;
5676 }
5677
5678 43 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5679 {
5680 MOVStreamContext *sc;
5681 AVStream *st;
5682
5683 43 st = avformat_new_stream(c->fc, NULL);
5684
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st)
5685 return AVERROR(ENOMEM);
5686 43 sc = av_mallocz(sizeof(MOVStreamContext));
5687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc)
5688 goto fail;
5689
5690 43 item->st = st;
5691 43 st->id = item->item_id;
5692 43 st->priv_data = sc;
5693 43 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5694 43 st->codecpar->codec_id = mov_codec_id(st, item->type);
5695 43 sc->id = st->id;
5696 43 sc->ffindex = st->index;
5697 43 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5698 43 st->time_base.num = st->time_base.den = 1;
5699 43 st->nb_frames = 1;
5700 43 sc->time_scale = 1;
5701 43 sc->pb = c->fc->pb;
5702 43 sc->pb_is_copied = 1;
5703 43 sc->refcount = 1;
5704
5705
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (item->name)
5706 43 av_dict_set(&st->metadata, "title", item->name, 0);
5707
5708 // Populate the necessary fields used by mov_build_index.
5709 43 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->stsc_data)
5711 goto fail;
5712 43 sc->stsc_count = 1;
5713 43 sc->stsc_data[0].first = 1;
5714 43 sc->stsc_data[0].count = 1;
5715 43 sc->stsc_data[0].id = 1;
5716 43 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->chunk_offsets)
5718 goto fail;
5719 43 sc->chunk_count = 1;
5720 43 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->stts_data)
5722 goto fail;
5723 43 sc->stts_count = 1;
5724 43 sc->stts_data[0].count = 1;
5725 // Not used for still images. But needed by mov_build_index.
5726 43 sc->stts_data[0].duration = 0;
5727
5728 43 return 0;
5729 fail:
5730 mov_free_stream_context(c->fc, st);
5731 ff_remove_stream(c->fc, st);
5732 item->st = NULL;
5733
5734 return AVERROR(ENOMEM);
5735 }
5736
5737 181 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5738 {
5739
1/2
✓ Branch 0 taken 529 times.
✗ Branch 1 not taken.
529 while (atom.size > 8) {
5740 uint32_t tag;
5741
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 529 times.
529 if (avio_feof(pb))
5742 return AVERROR_EOF;
5743 529 tag = avio_rl32(pb);
5744 529 atom.size -= 4;
5745
2/2
✓ Branch 0 taken 181 times.
✓ Branch 1 taken 348 times.
529 if (tag == MKTAG('h','d','l','r')) {
5746 181 avio_seek(pb, -8, SEEK_CUR);
5747 181 atom.size += 8;
5748 181 return mov_read_default(c, pb, atom);
5749 }
5750 }
5751 return 0;
5752 }
5753
5754 // return 1 when matrix is identity, 0 otherwise
5755 #define IS_MATRIX_IDENT(matrix) \
5756 ( (matrix)[0][0] == (1 << 16) && \
5757 (matrix)[1][1] == (1 << 16) && \
5758 (matrix)[2][2] == (1 << 30) && \
5759 !(matrix)[0][1] && !(matrix)[0][2] && \
5760 !(matrix)[1][0] && !(matrix)[1][2] && \
5761 !(matrix)[2][0] && !(matrix)[2][1])
5762
5763 665 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5764 {
5765 int i, j, e;
5766 int width;
5767 int height;
5768 int display_matrix[3][3];
5769 665 int res_display_matrix[3][3] = { { 0 } };
5770 AVStream *st;
5771 MOVStreamContext *sc;
5772 int version;
5773 int flags;
5774
5775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (c->fc->nb_streams < 1)
5776 return 0;
5777 665 st = c->fc->streams[c->fc->nb_streams-1];
5778 665 sc = st->priv_data;
5779
5780 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5781 // avoids corrupting AVStreams mapped to an earlier tkhd.
5782
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 if (st->id != -1)
5783 return AVERROR_INVALIDDATA;
5784
5785 665 version = avio_r8(pb);
5786 665 flags = avio_rb24(pb);
5787 665 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5788
5789
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 652 times.
665 if (version == 1) {
5790 13 avio_rb64(pb);
5791 13 avio_rb64(pb);
5792 } else {
5793 652 avio_rb32(pb); /* creation time */
5794 652 avio_rb32(pb); /* modification time */
5795 }
5796 665 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5797 665 sc->id = st->id;
5798 665 avio_rb32(pb); /* reserved */
5799
5800 /* highlevel (considering edits) duration in movie timebase */
5801
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 652 times.
665 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5802 665 avio_rb32(pb); /* reserved */
5803 665 avio_rb32(pb); /* reserved */
5804
5805 665 avio_rb16(pb); /* layer */
5806 665 avio_rb16(pb); /* alternate group */
5807 665 avio_rb16(pb); /* volume */
5808 665 avio_rb16(pb); /* reserved */
5809
5810 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
5811 // they're kept in fixed point format through all calculations
5812 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
5813 // side data, but the scale factor is not needed to calculate aspect ratio
5814
2/2
✓ Branch 0 taken 1995 times.
✓ Branch 1 taken 665 times.
2660 for (i = 0; i < 3; i++) {
5815 1995 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
5816 1995 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
5817 1995 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
5818 }
5819
5820 665 width = avio_rb32(pb); // 16.16 fixed point track width
5821 665 height = avio_rb32(pb); // 16.16 fixed point track height
5822 665 sc->width = width >> 16;
5823 665 sc->height = height >> 16;
5824
5825 // apply the moov display matrix (after the tkhd one)
5826
2/2
✓ Branch 0 taken 1995 times.
✓ Branch 1 taken 665 times.
2660 for (i = 0; i < 3; i++) {
5827 1995 const int sh[3] = { 16, 16, 30 };
5828
2/2
✓ Branch 0 taken 5985 times.
✓ Branch 1 taken 1995 times.
7980 for (j = 0; j < 3; j++) {
5829
2/2
✓ Branch 0 taken 17955 times.
✓ Branch 1 taken 5985 times.
23940 for (e = 0; e < 3; e++) {
5830 17955 res_display_matrix[i][j] +=
5831 17955 ((int64_t) display_matrix[i][e] *
5832 17955 c->movie_display_matrix[e][j]) >> sh[e];
5833 }
5834 }
5835 }
5836
5837 // save the matrix when it is not the default identity
5838
10/18
✓ Branch 0 taken 656 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 656 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 656 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 656 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 656 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 656 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 656 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 656 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 656 times.
665 if (!IS_MATRIX_IDENT(res_display_matrix)) {
5839 9 av_freep(&sc->display_matrix);
5840 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
5841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
5842 return AVERROR(ENOMEM);
5843
5844
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
5845
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
5846 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
5847 }
5848
5849 // transform the display width/height according to the matrix
5850 // to keep the same scale, use [width height 1<<16]
5851
5/6
✓ Branch 0 taken 344 times.
✓ Branch 1 taken 321 times.
✓ Branch 2 taken 344 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 336 times.
665 if (width && height && sc->display_matrix) {
5852 double disp_transform[2];
5853
5854
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
5855 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
5856 16 sc->display_matrix[3 + i]);
5857
5858
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 &&
5859
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) &&
5860
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
5861 3 st->sample_aspect_ratio = av_d2q(
5862 3 disp_transform[0] / disp_transform[1],
5863 INT_MAX);
5864 }
5865 665 return 0;
5866 }
5867
5868 499 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5869 {
5870 499 MOVFragment *frag = &c->fragment;
5871 499 MOVTrackExt *trex = NULL;
5872 int flags, track_id, i;
5873 MOVFragmentStreamInfo * frag_stream_info;
5874
5875 499 avio_r8(pb); /* version */
5876 499 flags = avio_rb24(pb);
5877
5878 499 track_id = avio_rb32(pb);
5879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!track_id)
5880 return AVERROR_INVALIDDATA;
5881
1/2
✓ Branch 0 taken 558 times.
✗ Branch 1 not taken.
558 for (i = 0; i < c->trex_count; i++)
5882
2/2
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 59 times.
558 if (c->trex_data[i].track_id == track_id) {
5883 499 trex = &c->trex_data[i];
5884 499 break;
5885 }
5886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!trex) {
5887 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
5888 return 0;
5889 }
5890 499 c->fragment.found_tfhd = 1;
5891 499 frag->track_id = track_id;
5892 499 set_frag_stream(&c->frag_index, track_id);
5893
5894 998 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
5895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
998 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
5896
2/2
✓ Branch 0 taken 426 times.
✓ Branch 1 taken 73 times.
499 frag->moof_offset : frag->implicit_offset;
5897
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 438 times.
499 frag->stsd_id = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id;
5898
5899 998 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
5900
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 435 times.
499 avio_rb32(pb) : trex->duration;
5901 998 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
5902
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 440 times.
499 avio_rb32(pb) : trex->size;
5903 998 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
5904
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 366 times.
499 avio_rb32(pb) : trex->flags;
5905 499 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
5906
5907 499 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5908
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info) {
5909 499 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
5910 499 frag_stream_info->stsd_id = frag->stsd_id;
5911 }
5912 499 return 0;
5913 }
5914
5915 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5916 {
5917 unsigned i, num;
5918 void *new_tracks;
5919
5920 2 num = atom.size / 4;
5921
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
5922 return AVERROR(ENOMEM);
5923
5924 2 av_free(c->chapter_tracks);
5925 2 c->chapter_tracks = new_tracks;
5926 2 c->nb_chapter_tracks = num;
5927
5928
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++)
5929 2 c->chapter_tracks[i] = avio_rb32(pb);
5930
5931 2 c->nb_chapter_tracks = i;
5932
5933 2 return 0;
5934 }
5935
5936 28 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5937 {
5938 MOVTrackExt *trex;
5939 int err;
5940
5941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if ((uint64_t)c->trex_count+1 >= UINT_MAX / sizeof(*c->trex_data))
5942 return AVERROR_INVALIDDATA;
5943
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
5944 sizeof(*c->trex_data))) < 0) {
5945 c->trex_count = 0;
5946 return err;
5947 }
5948
5949 28 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
5950
5951 28 trex = &c->trex_data[c->trex_count++];
5952 28 avio_r8(pb); /* version */
5953 28 avio_rb24(pb); /* flags */
5954 28 trex->track_id = avio_rb32(pb);
5955 28 trex->stsd_id = avio_rb32(pb);
5956 28 trex->duration = avio_rb32(pb);
5957 28 trex->size = avio_rb32(pb);
5958 28 trex->flags = avio_rb32(pb);
5959 28 return 0;
5960 }
5961
5962 426 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5963 {
5964 426 MOVFragment *frag = &c->fragment;
5965 426 AVStream *st = NULL;
5966 MOVStreamContext *sc;
5967 int version, i;
5968 MOVFragmentStreamInfo * frag_stream_info;
5969 int64_t base_media_decode_time;
5970
5971
1/2
✓ Branch 0 taken 453 times.
✗ Branch 1 not taken.
453 for (i = 0; i < c->fc->nb_streams; i++) {
5972 453 sc = c->fc->streams[i]->priv_data;
5973
2/2
✓ Branch 0 taken 426 times.
✓ Branch 1 taken 27 times.
453 if (sc->id == frag->track_id) {
5974 426 st = c->fc->streams[i];
5975 426 break;
5976 }
5977 }
5978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 426 times.
426 if (!st) {
5979 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
5980 return 0;
5981 }
5982 426 sc = st->priv_data;
5983
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 422 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
426 if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1)
5984 return 0;
5985 426 version = avio_r8(pb);
5986 426 avio_rb24(pb); /* flags */
5987
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 370 times.
426 if (version) {
5988 56 base_media_decode_time = avio_rb64(pb);
5989 } else {
5990 370 base_media_decode_time = avio_rb32(pb);
5991 }
5992
5993 426 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5994
1/2
✓ Branch 0 taken 426 times.
✗ Branch 1 not taken.
426 if (frag_stream_info)
5995 426 frag_stream_info->tfdt_dts = base_media_decode_time;
5996 426 sc->track_end = base_media_decode_time;
5997
5998 426 return 0;
5999 }
6000
6001 499 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6002 {
6003 499 MOVFragment *frag = &c->fragment;
6004 499 AVStream *st = NULL;
6005 499 FFStream *sti = NULL;
6006 MOVStreamContext *sc;
6007 MOVTimeToSample *tts_data;
6008 uint64_t offset;
6009 499 int64_t dts, pts = AV_NOPTS_VALUE;
6010 499 int data_offset = 0;
6011 499 unsigned entries, first_sample_flags = frag->flags;
6012 int flags, distance, i;
6013 499 int64_t prev_dts = AV_NOPTS_VALUE;
6014 499 int next_frag_index = -1, index_entry_pos;
6015 size_t requested_size;
6016 size_t old_allocated_size;
6017 AVIndexEntry *new_entries;
6018 MOVFragmentStreamInfo * frag_stream_info;
6019
6020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!frag->found_tfhd) {
6021 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
6022 return AVERROR_INVALIDDATA;
6023 }
6024
6025
1/2
✓ Branch 0 taken 558 times.
✗ Branch 1 not taken.
558 for (i = 0; i < c->fc->nb_streams; i++) {
6026 558 sc = c->fc->streams[i]->priv_data;
6027
2/2
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 59 times.
558 if (sc->id == frag->track_id) {
6028 499 st = c->fc->streams[i];
6029 499 sti = ffstream(st);
6030 499 break;
6031 }
6032 }
6033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!st) {
6034 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
6035 return 0;
6036 }
6037 499 sc = st->priv_data;
6038
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 495 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
499 if (sc->pseudo_stream_id+1 != frag->stsd_id && sc->pseudo_stream_id != -1)
6039 return 0;
6040
6041 // Find the next frag_index index that has a valid index_entry for
6042 // the current track_id.
6043 //
6044 // A valid index_entry means the trun for the fragment was read
6045 // and it's samples are in index_entries at the given position.
6046 // New index entries will be inserted before the index_entry found.
6047 499 index_entry_pos = sti->nb_index_entries;
6048
2/2
✓ Branch 0 taken 1634 times.
✓ Branch 1 taken 499 times.
2133 for (i = c->frag_index.current + 1; i < c->frag_index.nb_items; i++) {
6049 1634 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
6050
2/4
✓ Branch 0 taken 1634 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1634 times.
1634 if (frag_stream_info && frag_stream_info->index_entry >= 0) {
6051 next_frag_index = i;
6052 index_entry_pos = frag_stream_info->index_entry;
6053 break;
6054 }
6055 }
6056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 av_assert0(index_entry_pos <= sti->nb_index_entries);
6057
6058 499 avio_r8(pb); /* version */
6059 499 flags = avio_rb24(pb);
6060 499 entries = avio_rb32(pb);
6061 499 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
6062
6063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if ((uint64_t)entries+sc->tts_count >= UINT_MAX/sizeof(*sc->tts_data))
6064 return AVERROR_INVALIDDATA;
6065
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
6066
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 424 times.
499 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb);
6067
6068 499 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6069
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info) {
6070
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
6071 dts = frag_stream_info->next_trun_dts - sc->time_offset;
6072
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 496 times.
499 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
6073
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
6074 3 pts = frag_stream_info->first_tfra_pts;
6075 3 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
6076 ", using it for pts\n", pts);
6077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
6078 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
6079 dts = frag_stream_info->first_tfra_pts;
6080 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
6081 ", using it for dts\n", pts);
6082 } else {
6083 496 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
6084 496 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
6085
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
496 int fallback_tfdt = !c->use_tfdt && !has_sidx && has_tfdt;
6086
4/6
✓ Branch 0 taken 496 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 423 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
496 int fallback_sidx = c->use_tfdt && !has_tfdt && has_sidx;
6087
6088
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 if (fallback_sidx) {
6089 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
6090 }
6091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 if (fallback_tfdt) {
6092 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
6093 }
6094
6095
4/6
✓ Branch 0 taken 423 times.
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 423 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
496 if (has_tfdt && c->use_tfdt || fallback_tfdt) {
6096 423 dts = frag_stream_info->tfdt_dts - sc->time_offset;
6097 423 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
6098 ", using it for dts\n", dts);
6099
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 73 times.
73 } else if (has_sidx && !c->use_tfdt || fallback_sidx) {
6100 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
6101 // pts = frag_stream_info->sidx_pts;
6102 dts = frag_stream_info->sidx_pts;
6103 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
6104 ", using it for dts\n", frag_stream_info->sidx_pts);
6105 } else {
6106 73 dts = sc->track_end - sc->time_offset;
6107 73 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
6108 ", using it for dts\n", dts);
6109 }
6110 }
6111 } else {
6112 dts = sc->track_end - sc->time_offset;
6113 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
6114 ", using it for dts\n", dts);
6115 }
6116 499 offset = frag->base_data_offset + data_offset;
6117 499 distance = 0;
6118 499 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
6119
6120 // realloc space for new index entries
6121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
6122 entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
6123 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
6124 }
6125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (entries == 0)
6126 return 0;
6127
6128 499 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
6129 499 new_entries = av_fast_realloc(sti->index_entries,
6130 &sti->index_entries_allocated_size,
6131 requested_size);
6132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!new_entries)
6133 return AVERROR(ENOMEM);
6134 499 sti->index_entries= new_entries;
6135
6136 499 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
6137 499 old_allocated_size = sc->tts_allocated_size;
6138 499 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
6139 requested_size);
6140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!tts_data)
6141 return AVERROR(ENOMEM);
6142 499 sc->tts_data = tts_data;
6143
6144 // In case there were samples without time to sample entries, ensure they get
6145 // zero valued entries. This ensures clips which mix boxes with and
6146 // without time to sample entries don't pickup uninitialized data.
6147 499 memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0,
6148 499 sc->tts_allocated_size - old_allocated_size);
6149
6150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (index_entry_pos < sti->nb_index_entries) {
6151 // Make hole in index_entries and tts_data for new samples
6152 memmove(sti->index_entries + index_entry_pos + entries,
6153 sti->index_entries + index_entry_pos,
6154 sizeof(*sti->index_entries) *
6155 (sti->nb_index_entries - index_entry_pos));
6156 memmove(sc->tts_data + index_entry_pos + entries,
6157 sc->tts_data + index_entry_pos,
6158 sizeof(*sc->tts_data) * (sc->tts_count - index_entry_pos));
6159 if (index_entry_pos < sc->current_sample) {
6160 sc->current_sample += entries;
6161 }
6162 }
6163
6164 499 sti->nb_index_entries += entries;
6165 499 sc->tts_count = sti->nb_index_entries;
6166 499 sc->stts_count = sti->nb_index_entries;
6167
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 113 times.
499 if (flags & MOV_TRUN_SAMPLE_CTS)
6168 386 sc->ctts_count = sti->nb_index_entries;
6169
6170 // Record the index_entry position in frag_index of this fragment
6171
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info) {
6172 499 frag_stream_info->index_entry = index_entry_pos;
6173
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info->index_base < 0)
6174 499 frag_stream_info->index_base = index_entry_pos;
6175 }
6176
6177
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 27 times.
499 if (index_entry_pos > 0)
6178 472 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6179
6180
3/4
✓ Branch 0 taken 8707 times.
✓ Branch 1 taken 499 times.
✓ Branch 2 taken 8707 times.
✗ Branch 3 not taken.
9206 for (i = 0; i < entries && !pb->eof_reached; i++) {
6181 8707 unsigned sample_size = frag->size;
6182
2/2
✓ Branch 0 taken 8208 times.
✓ Branch 1 taken 499 times.
8707 int sample_flags = i ? frag->flags : first_sample_flags;
6183 8707 unsigned sample_duration = frag->duration;
6184 8707 unsigned ctts_duration = 0;
6185 8707 int keyframe = 0;
6186 8707 int index_entry_flags = 0;
6187
6188
2/2
✓ Branch 0 taken 1674 times.
✓ Branch 1 taken 7033 times.
8707 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
6189
2/2
✓ Branch 0 taken 8649 times.
✓ Branch 1 taken 58 times.
8707 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
6190
2/2
✓ Branch 0 taken 981 times.
✓ Branch 1 taken 7726 times.
8707 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
6191
2/2
✓ Branch 0 taken 6576 times.
✓ Branch 1 taken 2131 times.
8707 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
6192
6193 8707 mov_update_dts_shift(sc, ctts_duration, c->fc);
6194
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8704 times.
8707 if (pts != AV_NOPTS_VALUE) {
6195 3 dts = pts - sc->dts_shift;
6196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (flags & MOV_TRUN_SAMPLE_CTS) {
6197 dts -= ctts_duration;
6198 } else {
6199 3 dts -= sc->time_offset;
6200 }
6201 3 av_log(c->fc, AV_LOG_DEBUG,
6202 "pts %"PRId64" calculated dts %"PRId64
6203 " sc->dts_shift %d ctts.duration %d"
6204 " sc->time_offset %"PRId64
6205 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
6206 pts, dts,
6207 sc->dts_shift, ctts_duration,
6208 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
6209 3 pts = AV_NOPTS_VALUE;
6210 }
6211
6212 8707 keyframe =
6213 8707 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
6214 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
6215
2/2
✓ Branch 0 taken 646 times.
✓ Branch 1 taken 8061 times.
8707 if (keyframe) {
6216 646 distance = 0;
6217 646 index_entry_flags |= AVINDEX_KEYFRAME;
6218 }
6219 // Fragments can overlap in time. Discard overlapping frames after
6220 // decoding.
6221
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8683 times.
8707 if (prev_dts >= dts)
6222 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
6223
6224 8707 sti->index_entries[index_entry_pos].pos = offset;
6225 8707 sti->index_entries[index_entry_pos].timestamp = dts;
6226 8707 sti->index_entries[index_entry_pos].size = sample_size;
6227 8707 sti->index_entries[index_entry_pos].min_distance = distance;
6228 8707 sti->index_entries[index_entry_pos].flags = index_entry_flags;
6229
6230 8707 sc->tts_data[index_entry_pos].count = 1;
6231 8707 sc->tts_data[index_entry_pos].offset = ctts_duration;
6232 8707 sc->tts_data[index_entry_pos].duration = sample_duration;
6233 8707 index_entry_pos++;
6234
6235 8707 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
6236 "size %u, distance %d, keyframe %d\n", st->index,
6237 index_entry_pos, offset, dts, sample_size, distance, keyframe);
6238 8707 distance++;
6239
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8707 times.
8707 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
6240 return AVERROR_INVALIDDATA;
6241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8707 times.
8707 if (!sample_size)
6242 return AVERROR_INVALIDDATA;
6243 8707 dts += sample_duration;
6244 8707 offset += sample_size;
6245 8707 sc->data_size += sample_size;
6246
6247
1/2
✓ Branch 0 taken 8707 times.
✗ Branch 1 not taken.
8707 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
6248
1/2
✓ Branch 0 taken 8707 times.
✗ Branch 1 not taken.
8707 1 <= INT_MAX - sc->nb_frames_for_fps
6249 ) {
6250 8707 sc->duration_for_fps += sample_duration;
6251 8707 sc->nb_frames_for_fps ++;
6252 }
6253 }
6254
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info)
6255 499 frag_stream_info->next_trun_dts = dts + sc->time_offset;
6256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (i < entries) {
6257 // EOF found before reading all entries. Fix the hole this would
6258 // leave in index_entries and tts_data
6259 int gap = entries - i;
6260 memmove(sti->index_entries + index_entry_pos,
6261 sti->index_entries + index_entry_pos + gap,
6262 sizeof(*sti->index_entries) *
6263 (sti->nb_index_entries - (index_entry_pos + gap)));
6264 memmove(sc->tts_data + index_entry_pos,
6265 sc->tts_data + index_entry_pos + gap,
6266 sizeof(*sc->tts_data) *
6267 (sc->tts_count - (index_entry_pos + gap)));
6268
6269 sti->nb_index_entries -= gap;
6270 sc->tts_count -= gap;
6271 if (index_entry_pos < sc->current_sample) {
6272 sc->current_sample -= gap;
6273 }
6274 entries = i;
6275 }
6276
6277 // The end of this new fragment may overlap in time with the start
6278 // of the next fragment in index_entries. Mark the samples in the next
6279 // fragment that overlap with AVINDEX_DISCARD_FRAME
6280 499 prev_dts = AV_NOPTS_VALUE;
6281
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (index_entry_pos > 0)
6282 499 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6283
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
6284 if (prev_dts < sti->index_entries[i].timestamp)
6285 break;
6286 sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6287 }
6288
6289 // If a hole was created to insert the new index_entries into,
6290 // the index_entry recorded for all subsequent moof must
6291 // be incremented by the number of entries inserted.
6292 499 fix_frag_index_entries(&c->frag_index, next_frag_index,
6293 499 frag->track_id, entries);
6294
6295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (pb->eof_reached) {
6296 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6297 return AVERROR_EOF;
6298 }
6299
6300 499 frag->implicit_offset = offset;
6301
6302 499 sc->track_end = dts + sc->time_offset;
6303
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 383 times.
499 if (st->duration < sc->track_end)
6304 116 st->duration = sc->track_end;
6305
6306 499 return 0;
6307 }
6308
6309 46 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6310 {
6311 46 int64_t stream_size = avio_size(pb);
6312 46 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6313 uint8_t version, is_complete;
6314 int64_t offadd;
6315 unsigned i, j, track_id, item_count;
6316 46 AVStream *st = NULL;
6317 46 AVStream *ref_st = NULL;
6318 46 MOVStreamContext *sc, *ref_sc = NULL;
6319 AVRational timescale;
6320
6321 46 version = avio_r8(pb);
6322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (version > 1) {
6323 avpriv_request_sample(c->fc, "sidx version %u", version);
6324 return 0;
6325 }
6326
6327 46 avio_rb24(pb); // flags
6328
6329 46 track_id = avio_rb32(pb); // Reference ID
6330
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 for (i = 0; i < c->fc->nb_streams; i++) {
6331 46 sc = c->fc->streams[i]->priv_data;
6332
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 if (sc->id == track_id) {
6333 46 st = c->fc->streams[i];
6334 46 break;
6335 }
6336 }
6337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!st) {
6338 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6339 return 0;
6340 }
6341
6342 46 sc = st->priv_data;
6343
6344 46 timescale = av_make_q(1, avio_rb32(pb));
6345
6346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (timescale.den <= 0) {
6347 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6348 return AVERROR_INVALIDDATA;
6349 }
6350
6351
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1 times.
46 if (version == 0) {
6352 45 pts = avio_rb32(pb);
6353 45 offadd= avio_rb32(pb);
6354 } else {
6355 1 pts = avio_rb64(pb);
6356 1 offadd= avio_rb64(pb);
6357 }
6358
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6359 return AVERROR_INVALIDDATA;
6360
6361 46 offset += (uint64_t)offadd;
6362
6363 46 avio_rb16(pb); // reserved
6364
6365 46 item_count = avio_rb16(pb);
6366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (item_count == 0)
6367 return AVERROR_INVALIDDATA;
6368
6369
2/2
✓ Branch 0 taken 372 times.
✓ Branch 1 taken 46 times.
418 for (i = 0; i < item_count; i++) {
6370 int index;
6371 MOVFragmentStreamInfo * frag_stream_info;
6372 372 uint32_t size = avio_rb32(pb);
6373 372 uint32_t duration = avio_rb32(pb);
6374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
372 if (size & 0x80000000) {
6375 avpriv_request_sample(c->fc, "sidx reference_type 1");
6376 return AVERROR_PATCHWELCOME;
6377 }
6378 372 avio_rb32(pb); // sap_flags
6379 372 timestamp = av_rescale_q(pts, timescale, st->time_base);
6380
6381 372 index = update_frag_index(c, offset);
6382 372 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6383
1/2
✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
372 if (frag_stream_info)
6384 372 frag_stream_info->sidx_pts = timestamp;
6385
6386
1/2
✓ Branch 1 taken 372 times.
✗ Branch 2 not taken.
372 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6387
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 372 times.
372 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6388 )
6389 return AVERROR_INVALIDDATA;
6390 372 offset += size;
6391 372 pts += duration;
6392 }
6393
6394 46 st->duration = sc->track_end = pts;
6395
6396 46 sc->has_sidx = 1;
6397
6398 // See if the remaining bytes are just an mfra which we can ignore.
6399 46 is_complete = offset == stream_size;
6400
5/6
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
46 if (!is_complete && (pb->seekable & AVIO_SEEKABLE_NORMAL) && stream_size > 0 ) {
6401 int64_t ret;
6402 38 int64_t original_pos = avio_tell(pb);
6403
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
38 if (!c->have_read_mfra_size) {
6404
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6405 return ret;
6406 3 c->mfra_size = avio_rb32(pb);
6407 3 c->have_read_mfra_size = 1;
6408
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6409 return ret;
6410 }
6411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (offset == stream_size - c->mfra_size)
6412 is_complete = 1;
6413 }
6414
6415
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 39 times.
46 if (is_complete) {
6416 // Find first entry in fragment index that came from an sidx.
6417 // This will pretty much always be the first entry.
6418
2/2
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 7 times.
378 for (i = 0; i < c->frag_index.nb_items; i++) {
6419 371 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6420
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 364 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
371 for (j = 0; ref_st == NULL && j < item->nb_stream_info; j++) {
6421 MOVFragmentStreamInfo * si;
6422 7 si = &item->stream_info[j];
6423
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (si->sidx_pts != AV_NOPTS_VALUE) {
6424 7 ref_st = c->fc->streams[j];
6425 7 ref_sc = ref_st->priv_data;
6426 7 break;
6427 }
6428 }
6429 }
6430
3/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 7 times.
14 if (ref_st) for (i = 0; i < c->fc->nb_streams; i++) {
6431 7 st = c->fc->streams[i];
6432 7 sc = st->priv_data;
6433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sc->has_sidx) {
6434 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6435 }
6436 }
6437
6438
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (offadd == 0)
6439 7 c->frag_index.complete = 1;
6440 }
6441
6442 46 return 0;
6443 }
6444
6445 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6446 /* like the files created with Adobe Premiere 5.0, for samples see */
6447 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6448 278 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6449 {
6450 int err;
6451
6452
1/2
✓ Branch 0 taken 278 times.
✗ Branch 1 not taken.
278 if (atom.size < 8)
6453 278 return 0; /* continue */
6454 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6455 avio_skip(pb, atom.size - 4);
6456 return 0;
6457 }
6458 atom.type = avio_rl32(pb);
6459 atom.size -= 8;
6460 if (atom.type != MKTAG('m','d','a','t')) {
6461 avio_skip(pb, atom.size);
6462 return 0;
6463 }
6464 err = mov_read_mdat(c, pb, atom);
6465 return err;
6466 }
6467
6468 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6469 {
6470 #if CONFIG_ZLIB
6471 FFIOContext ctx;
6472 uint8_t *cmov_data;
6473 uint8_t *moov_data; /* uncompressed data */
6474 long cmov_len, moov_len;
6475 3 int ret = -1;
6476
6477 3 avio_rb32(pb); /* dcom atom */
6478
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6479 return AVERROR_INVALIDDATA;
6480
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6481 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6482 return AVERROR_INVALIDDATA;
6483 }
6484 3 avio_rb32(pb); /* cmvd atom */
6485
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6486 return AVERROR_INVALIDDATA;
6487 3 moov_len = avio_rb32(pb); /* uncompressed size */
6488 3 cmov_len = atom.size - 6 * 4;
6489
6490 3 cmov_data = av_malloc(cmov_len);
6491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6492 return AVERROR(ENOMEM);
6493 3 moov_data = av_malloc(moov_len);
6494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6495 av_free(cmov_data);
6496 return AVERROR(ENOMEM);
6497 }
6498 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6500 goto free_and_return;
6501
6502 3 ret = AVERROR_INVALIDDATA;
6503
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)
6504 goto free_and_return;
6505 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6506 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6507 3 atom.type = MKTAG('m','o','o','v');
6508 3 atom.size = moov_len;
6509 3 ret = mov_read_default(c, &ctx.pub, atom);
6510 3 free_and_return:
6511 3 av_free(moov_data);
6512 3 av_free(cmov_data);
6513 3 return ret;
6514 #else
6515 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6516 return AVERROR(ENOSYS);
6517 #endif
6518 }
6519
6520 /* edit list atom */
6521 490 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6522 {
6523 MOVStreamContext *sc;
6524 int i, edit_count, version;
6525 int64_t elst_entry_size;
6526
6527
2/4
✓ Branch 0 taken 490 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 490 times.
490 if (c->fc->nb_streams < 1 || c->ignore_editlist)
6528 return 0;
6529 490 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6530
6531 490 version = avio_r8(pb); /* version */
6532 490 avio_rb24(pb); /* flags */
6533 490 edit_count = avio_rb32(pb); /* entries */
6534 490 atom.size -= 8;
6535
6536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 490 times.
490 elst_entry_size = version == 1 ? 20 : 12;
6537
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 489 times.
490 if (atom.size != edit_count * elst_entry_size) {
6538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6539 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6540 edit_count, atom.size + 8);
6541 return AVERROR_INVALIDDATA;
6542 } else {
6543 1 edit_count = atom.size / elst_entry_size;
6544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6545 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6546 }
6547 }
6548 }
6549
6550
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 490 times.
490 if (!edit_count)
6551 return 0;
6552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 490 times.
490 if (sc->elst_data)
6553 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6554 490 av_free(sc->elst_data);
6555 490 sc->elst_count = 0;
6556 490 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 490 times.
490 if (!sc->elst_data)
6558 return AVERROR(ENOMEM);
6559
6560 490 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6561
4/6
✓ Branch 0 taken 519 times.
✓ Branch 1 taken 490 times.
✓ Branch 2 taken 519 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 519 times.
✗ Branch 5 not taken.
1009 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
6562 519 MOVElst *e = &sc->elst_data[i];
6563
6564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 519 times.
519 if (version == 1) {
6565 e->duration = avio_rb64(pb);
6566 e->time = avio_rb64(pb);
6567 atom.size -= 16;
6568 } else {
6569 519 e->duration = avio_rb32(pb); /* segment duration */
6570 519 e->time = (int32_t)avio_rb32(pb); /* media time */
6571 519 atom.size -= 8;
6572 }
6573 519 e->rate = avio_rb32(pb) / 65536.0;
6574 519 atom.size -= 4;
6575 519 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6576 519 e->duration, e->time, e->rate);
6577
6578
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 515 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
519 if (e->time < 0 && e->time != -1 &&
6579 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6580 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6581 c->fc->nb_streams-1, i, e->time);
6582 return AVERROR_INVALIDDATA;
6583 }
6584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 519 times.
519 if (e->duration < 0) {
6585 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list duration=%"PRId64"\n",
6586 c->fc->nb_streams-1, i, e->duration);
6587 return AVERROR_INVALIDDATA;
6588 }
6589 }
6590 490 sc->elst_count = i;
6591
6592 490 return 0;
6593 }
6594
6595 18 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6596 {
6597 MOVStreamContext *sc;
6598 int err;
6599
6600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->fc->nb_streams < 1)
6601 return AVERROR_INVALIDDATA;
6602 18 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6603
6604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size % sizeof(uint32_t))
6605 return AVERROR_INVALIDDATA;
6606
6607 18 MovTref *tag = mov_add_tref_tag(sc, atom.type);
6608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!tag)
6609 return AVERROR(ENOMEM);
6610
6611 18 int nb_timecode_track = atom.size >> 2;
6612
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 18 times.
40 for (int i = 0; i < nb_timecode_track; i++) {
6613
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 if (avio_feof(pb))
6614 return AVERROR_INVALIDDATA;
6615 22 err = mov_add_tref_id(tag, avio_rb32(pb));
6616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (err < 0)
6617 return err;
6618 }
6619
6620 18 return 0;
6621 }
6622
6623 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6624 {
6625 AVStream *st;
6626 int version, color_range, color_primaries, color_trc, color_space;
6627
6628 if (c->fc->nb_streams < 1)
6629 return 0;
6630 st = c->fc->streams[c->fc->nb_streams - 1];
6631
6632 if (atom.size < 5) {
6633 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6634 return AVERROR_INVALIDDATA;
6635 }
6636
6637 version = avio_r8(pb);
6638 if (version != 1) {
6639 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6640 return 0;
6641 }
6642 avio_skip(pb, 3); /* flags */
6643
6644 avio_skip(pb, 2); /* profile + level */
6645 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6646 color_primaries = avio_r8(pb);
6647 color_trc = avio_r8(pb);
6648 color_space = avio_r8(pb);
6649 if (avio_rb16(pb)) /* codecIntializationDataSize */
6650 return AVERROR_INVALIDDATA;
6651
6652 if (!av_color_primaries_name(color_primaries))
6653 color_primaries = AVCOL_PRI_UNSPECIFIED;
6654 if (!av_color_transfer_name(color_trc))
6655 color_trc = AVCOL_TRC_UNSPECIFIED;
6656 if (!av_color_space_name(color_space))
6657 color_space = AVCOL_SPC_UNSPECIFIED;
6658
6659 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6660 st->codecpar->color_primaries = color_primaries;
6661 st->codecpar->color_trc = color_trc;
6662 st->codecpar->color_space = color_space;
6663
6664 return 0;
6665 }
6666
6667 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6668 {
6669 MOVStreamContext *sc;
6670 int i, version;
6671
6672 if (c->fc->nb_streams < 1)
6673 return AVERROR_INVALIDDATA;
6674
6675 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6676
6677 if (atom.size < 5) {
6678 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6679 return AVERROR_INVALIDDATA;
6680 }
6681
6682 version = avio_r8(pb);
6683 if (version) {
6684 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6685 return 0;
6686 }
6687 if (sc->mastering) {
6688 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6689 return 0;
6690 }
6691
6692 avio_skip(pb, 3); /* flags */
6693
6694 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6695 if (!sc->mastering)
6696 return AVERROR(ENOMEM);
6697
6698 for (i = 0; i < 3; i++) {
6699 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6700 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6701 }
6702 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6703 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6704
6705 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6706 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6707
6708 sc->mastering->has_primaries = 1;
6709 sc->mastering->has_luminance = 1;
6710
6711 return 0;
6712 }
6713
6714 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6715 {
6716 MOVStreamContext *sc;
6717 const int mapping[3] = {1, 2, 0};
6718 const int chroma_den = 50000;
6719 const int luma_den = 10000;
6720 int i;
6721
6722 if (c->fc->nb_streams < 1)
6723 return AVERROR_INVALIDDATA;
6724
6725 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6726
6727 if (atom.size < 24) {
6728 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6729 return AVERROR_INVALIDDATA;
6730 }
6731
6732 if (sc->mastering) {
6733 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6734 return 0;
6735 }
6736
6737 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6738 if (!sc->mastering)
6739 return AVERROR(ENOMEM);
6740
6741 for (i = 0; i < 3; i++) {
6742 const int j = mapping[i];
6743 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6744 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6745 }
6746 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6747 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6748
6749 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6750 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6751
6752 sc->mastering->has_luminance = 1;
6753 sc->mastering->has_primaries = 1;
6754
6755 return 0;
6756 }
6757
6758 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6759 {
6760 MOVStreamContext *sc;
6761 int version;
6762
6763 if (c->fc->nb_streams < 1)
6764 return AVERROR_INVALIDDATA;
6765
6766 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6767
6768 if (atom.size < 5) {
6769 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
6770 return AVERROR_INVALIDDATA;
6771 }
6772
6773 version = avio_r8(pb);
6774 if (version) {
6775 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
6776 return 0;
6777 }
6778 avio_skip(pb, 3); /* flags */
6779
6780 if (sc->coll){
6781 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
6782 return 0;
6783 }
6784
6785 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6786 if (!sc->coll)
6787 return AVERROR(ENOMEM);
6788
6789 sc->coll->MaxCLL = avio_rb16(pb);
6790 sc->coll->MaxFALL = avio_rb16(pb);
6791
6792 return 0;
6793 }
6794
6795 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6796 {
6797 MOVStreamContext *sc;
6798
6799 if (c->fc->nb_streams < 1)
6800 return AVERROR_INVALIDDATA;
6801
6802 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6803
6804 if (atom.size < 4) {
6805 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
6806 return AVERROR_INVALIDDATA;
6807 }
6808
6809 if (sc->coll){
6810 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
6811 return 0;
6812 }
6813
6814 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
6815 if (!sc->coll)
6816 return AVERROR(ENOMEM);
6817
6818 sc->coll->MaxCLL = avio_rb16(pb);
6819 sc->coll->MaxFALL = avio_rb16(pb);
6820
6821 return 0;
6822 }
6823
6824 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6825 {
6826 MOVStreamContext *sc;
6827 4 const int illuminance_den = 10000;
6828 4 const int ambient_den = 50000;
6829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
6830 return AVERROR_INVALIDDATA;
6831 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
6833 av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
6834 return AVERROR_INVALIDDATA;
6835 }
6836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
6837 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
6838 return 0;
6839 }
6840 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
6841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
6842 return AVERROR(ENOMEM);
6843 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
6844 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
6845 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
6846 4 return 0;
6847 }
6848
6849 1 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6850 {
6851 AVStream *st;
6852 MOVStreamContext *sc;
6853 enum AVStereo3DType type;
6854 int mode;
6855
6856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6857 return 0;
6858
6859 1 st = c->fc->streams[c->fc->nb_streams - 1];
6860 1 sc = st->priv_data;
6861
6862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 5) {
6863 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
6864 return AVERROR_INVALIDDATA;
6865 }
6866
6867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sc->stereo3d)
6868 return AVERROR_INVALIDDATA;
6869
6870 1 avio_skip(pb, 4); /* version + flags */
6871
6872 1 mode = avio_r8(pb);
6873
1/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 switch (mode) {
6874 1 case 0:
6875 1 type = AV_STEREO3D_2D;
6876 1 break;
6877 case 1:
6878 type = AV_STEREO3D_TOPBOTTOM;
6879 break;
6880 case 2:
6881 type = AV_STEREO3D_SIDEBYSIDE;
6882 break;
6883 default:
6884 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
6885 return 0;
6886 }
6887
6888 1 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6889
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->stereo3d)
6890 return AVERROR(ENOMEM);
6891
6892 1 sc->stereo3d->type = type;
6893 1 return 0;
6894 }
6895
6896 static int mov_read_pack(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6897 {
6898 AVStream *st;
6899 MOVStreamContext *sc;
6900 int size = 0;
6901 int64_t remaining;
6902 uint32_t tag = 0;
6903 enum AVStereo3DType type = AV_STEREO3D_2D;
6904
6905 if (c->fc->nb_streams < 1)
6906 return 0;
6907
6908 st = c->fc->streams[c->fc->nb_streams - 1];
6909 sc = st->priv_data;
6910
6911 remaining = atom.size;
6912 while (remaining > 0) {
6913 size = avio_rb32(pb);
6914 if (size < 8 || size > remaining ) {
6915 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in pack box\n");
6916 return AVERROR_INVALIDDATA;
6917 }
6918
6919 tag = avio_rl32(pb);
6920 switch (tag) {
6921 case MKTAG('p','k','i','n'): {
6922 if (size != 16) {
6923 av_log(c->fc, AV_LOG_ERROR, "Invalid size of pkin box: %d\n", size);
6924 return AVERROR_INVALIDDATA;
6925 }
6926 avio_skip(pb, 1); // version
6927 avio_skip(pb, 3); // flags
6928
6929 tag = avio_rl32(pb);
6930 switch (tag) {
6931 case MKTAG('s','i','d','e'):
6932 type = AV_STEREO3D_SIDEBYSIDE;
6933 break;
6934 case MKTAG('o','v','e','r'):
6935 type = AV_STEREO3D_TOPBOTTOM;
6936 break;
6937 case 0:
6938 // This means value will be set in another layer
6939 break;
6940 default:
6941 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pkin: %s\n",
6942 av_fourcc2str(tag));
6943 avio_skip(pb, size - 8);
6944 break;
6945 }
6946
6947 break;
6948 }
6949 default:
6950 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pack: %s\n",
6951 av_fourcc2str(tag));
6952 avio_skip(pb, size - 8);
6953 break;
6954 }
6955 remaining -= size;
6956 }
6957
6958 if (remaining != 0) {
6959 av_log(c->fc, AV_LOG_ERROR, "Broken pack box\n");
6960 return AVERROR_INVALIDDATA;
6961 }
6962
6963 if (type == AV_STEREO3D_2D)
6964 return 0;
6965
6966 if (!sc->stereo3d) {
6967 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
6968 if (!sc->stereo3d)
6969 return AVERROR(ENOMEM);
6970 }
6971
6972 sc->stereo3d->type = type;
6973
6974 return 0;
6975 }
6976
6977 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6978 {
6979 AVStream *st;
6980 MOVStreamContext *sc;
6981 int size, version, layout;
6982 int32_t yaw, pitch, roll;
6983 1 uint32_t l = 0, t = 0, r = 0, b = 0;
6984 1 uint32_t tag, padding = 0;
6985 enum AVSphericalProjection projection;
6986
6987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
6988 return 0;
6989
6990 1 st = c->fc->streams[c->fc->nb_streams - 1];
6991 1 sc = st->priv_data;
6992
6993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
6994 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
6995 return AVERROR_INVALIDDATA;
6996 }
6997
6998 1 size = avio_rb32(pb);
6999
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)
7000 return AVERROR_INVALIDDATA;
7001
7002 1 tag = avio_rl32(pb);
7003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
7004 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
7005 return 0;
7006 }
7007 1 version = avio_r8(pb);
7008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7009 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7010 version);
7011 return 0;
7012 }
7013 1 avio_skip(pb, 3); /* flags */
7014 1 avio_skip(pb, size - 12); /* metadata_source */
7015
7016 1 size = avio_rb32(pb);
7017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7018 return AVERROR_INVALIDDATA;
7019
7020 1 tag = avio_rl32(pb);
7021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
7022 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
7023 return 0;
7024 }
7025
7026 1 size = avio_rb32(pb);
7027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7028 return AVERROR_INVALIDDATA;
7029
7030 1 tag = avio_rl32(pb);
7031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
7032 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
7033 return 0;
7034 }
7035 1 version = avio_r8(pb);
7036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7037 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7038 version);
7039 return 0;
7040 }
7041 1 avio_skip(pb, 3); /* flags */
7042
7043 /* 16.16 fixed point */
7044 1 yaw = avio_rb32(pb);
7045 1 pitch = avio_rb32(pb);
7046 1 roll = avio_rb32(pb);
7047
7048 1 size = avio_rb32(pb);
7049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7050 return AVERROR_INVALIDDATA;
7051
7052 1 tag = avio_rl32(pb);
7053 1 version = avio_r8(pb);
7054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7055 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7056 version);
7057 return 0;
7058 }
7059 1 avio_skip(pb, 3); /* flags */
7060
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
7061 case MKTAG('c','b','m','p'):
7062 layout = avio_rb32(pb);
7063 if (layout) {
7064 av_log(c->fc, AV_LOG_WARNING,
7065 "Unsupported cubemap layout %d\n", layout);
7066 return 0;
7067 }
7068 projection = AV_SPHERICAL_CUBEMAP;
7069 padding = avio_rb32(pb);
7070 break;
7071 1 case MKTAG('e','q','u','i'):
7072 1 t = avio_rb32(pb);
7073 1 b = avio_rb32(pb);
7074 1 l = avio_rb32(pb);
7075 1 r = avio_rb32(pb);
7076
7077
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) {
7078 av_log(c->fc, AV_LOG_ERROR,
7079 "Invalid bounding rectangle coordinates "
7080 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
7081 return AVERROR_INVALIDDATA;
7082 }
7083
7084
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)
7085 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
7086 else
7087 projection = AV_SPHERICAL_EQUIRECTANGULAR;
7088 1 break;
7089 default:
7090 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
7091 return 0;
7092 }
7093
7094 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7095
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
7096 return AVERROR(ENOMEM);
7097
7098 1 sc->spherical->projection = projection;
7099
7100 1 sc->spherical->yaw = yaw;
7101 1 sc->spherical->pitch = pitch;
7102 1 sc->spherical->roll = roll;
7103
7104 1 sc->spherical->padding = padding;
7105
7106 1 sc->spherical->bound_left = l;
7107 1 sc->spherical->bound_top = t;
7108 1 sc->spherical->bound_right = r;
7109 1 sc->spherical->bound_bottom = b;
7110
7111 1 return 0;
7112 }
7113
7114 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7115 {
7116 AVStream *st;
7117 MOVStreamContext *sc;
7118 int size;
7119 uint32_t tag;
7120 enum AVSphericalProjection projection;
7121
7122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7123 return 0;
7124
7125 3 st = c->fc->streams[c->fc->nb_streams - 1];
7126 3 sc = st->priv_data;
7127
7128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 16) {
7129 av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
7130 return AVERROR_INVALIDDATA;
7131 }
7132
7133 3 size = avio_rb32(pb);
7134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size < 16) {
7135 av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
7136 return AVERROR_INVALIDDATA;
7137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (size > 16) {
7138 av_log(c->fc, AV_LOG_WARNING, "Box has more bytes (%d) than prji box required (16) \n", size);
7139 }
7140
7141 3 tag = avio_rl32(pb);
7142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
7143 av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: %s\n",
7144 av_fourcc2str(tag));
7145 return AVERROR_INVALIDDATA;
7146 }
7147
7148 // version and flags, only support (0, 0)
7149 3 unsigned n = avio_rl32(pb);
7150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (n != 0) {
7151 av_log(c->fc, AV_LOG_ERROR, "prji version %u, flag %u are not supported\n",
7152 n & 0xFF, n >> 8);
7153 return AVERROR_PATCHWELCOME;
7154 }
7155
7156 3 tag = avio_rl32(pb);
7157
1/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3 switch (tag) {
7158 3 case MKTAG('r','e','c','t'):
7159 3 projection = AV_SPHERICAL_RECTILINEAR;
7160 3 break;
7161 case MKTAG('e','q','u','i'):
7162 projection = AV_SPHERICAL_EQUIRECTANGULAR;
7163 break;
7164 case MKTAG('h','e','q','u'):
7165 projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
7166 break;
7167 case MKTAG('f','i','s','h'):
7168 projection = AV_SPHERICAL_FISHEYE;
7169 break;
7170 case MKTAG('p','r','i','m'):
7171 projection = AV_SPHERICAL_PARAMETRIC_IMMERSIVE;
7172 break;
7173 default:
7174 av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: %s\n", av_fourcc2str(tag));
7175 return AVERROR_INVALIDDATA;
7176 }
7177
7178 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
7180 return AVERROR(ENOMEM);
7181
7182 3 sc->spherical->projection = projection;
7183
7184 3 return 0;
7185 }
7186
7187 3 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7188 {
7189 AVStream *st;
7190 MOVStreamContext *sc;
7191 3 int size, flags = 0;
7192 int64_t remaining;
7193 3 uint32_t tag, baseline = 0;
7194 3 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
7195 3 enum AVStereo3DType type = AV_STEREO3D_2D;
7196 3 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
7197 3 AVRational horizontal_disparity_adjustment = { 0, 1 };
7198
7199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7200 return 0;
7201
7202 3 st = c->fc->streams[c->fc->nb_streams - 1];
7203 3 sc = st->priv_data;
7204
7205 3 remaining = atom.size;
7206
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 while (remaining > 0) {
7207 9 size = avio_rb32(pb);
7208
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 ) {
7209 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
7210 return AVERROR_INVALIDDATA;
7211 }
7212
7213 9 tag = avio_rl32(pb);
7214
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) {
7215 3 case MKTAG('s','t','r','i'): {
7216 int has_right, has_left;
7217 uint8_t tmp;
7218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 13) {
7219 av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
7220 return AVERROR_INVALIDDATA;
7221 }
7222 3 avio_skip(pb, 1); // version
7223 3 avio_skip(pb, 3); // flags
7224
7225 3 tmp = avio_r8(pb);
7226
7227 // eye_views_reversed
7228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tmp & 8) {
7229 flags |= AV_STEREO3D_FLAG_INVERT;
7230 }
7231 // has_additional_views
7232 3 if (tmp & 4) {
7233 // skip...
7234 }
7235
7236 3 has_right = tmp & 2; // has_right_eye_view
7237 3 has_left = tmp & 1; // has_left_eye_view
7238
7239
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)
7240 3 view = AV_STEREO3D_VIEW_PACKED;
7241 else if (has_left)
7242 view = AV_STEREO3D_VIEW_LEFT;
7243 else if (has_right)
7244 view = AV_STEREO3D_VIEW_RIGHT;
7245
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)
7246 3 type = AV_STEREO3D_UNSPEC;
7247
7248 3 break;
7249 }
7250 case MKTAG('h','e','r','o'): {
7251 int tmp;
7252 if (size != 13) {
7253 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
7254 return AVERROR_INVALIDDATA;
7255 }
7256 avio_skip(pb, 1); // version
7257 avio_skip(pb, 3); // flags
7258
7259 tmp = avio_r8(pb);
7260 if (tmp == 0)
7261 primary_eye = AV_PRIMARY_EYE_NONE;
7262 else if (tmp == 1)
7263 primary_eye = AV_PRIMARY_EYE_LEFT;
7264 else if (tmp == 2)
7265 primary_eye = AV_PRIMARY_EYE_RIGHT;
7266 else
7267 av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
7268
7269 break;
7270 }
7271 3 case MKTAG('c','a','m','s'): {
7272 uint32_t subtag;
7273 int subsize;
7274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7275 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
7276 return AVERROR_INVALIDDATA;
7277 }
7278
7279 3 subsize = avio_rb32(pb);
7280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7281 av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
7282 return AVERROR_INVALIDDATA;
7283 }
7284
7285 3 subtag = avio_rl32(pb);
7286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
7287 av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got %s\n",
7288 av_fourcc2str(subtag));
7289 return AVERROR_INVALIDDATA;
7290 }
7291
7292 3 avio_skip(pb, 1); // version
7293 3 avio_skip(pb, 3); // flags
7294
7295 3 baseline = avio_rb32(pb);
7296
7297 3 break;
7298 }
7299 3 case MKTAG('c','m','f','y'): {
7300 uint32_t subtag;
7301 int subsize;
7302 int32_t adjustment;
7303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7304 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
7305 return AVERROR_INVALIDDATA;
7306 }
7307
7308 3 subsize = avio_rb32(pb);
7309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7310 av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
7311 return AVERROR_INVALIDDATA;
7312 }
7313
7314 3 subtag = avio_rl32(pb);
7315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
7316 av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got %s\n",
7317 av_fourcc2str(subtag));
7318 return AVERROR_INVALIDDATA;
7319 }
7320
7321 3 avio_skip(pb, 1); // version
7322 3 avio_skip(pb, 3); // flags
7323
7324 3 adjustment = (int32_t) avio_rb32(pb);
7325
7326 3 horizontal_disparity_adjustment.num = (int) adjustment;
7327 3 horizontal_disparity_adjustment.den = 10000;
7328
7329 3 break;
7330 }
7331 default:
7332 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: %s\n",
7333 av_fourcc2str(tag));
7334 avio_skip(pb, size - 8);
7335 break;
7336 }
7337 9 remaining -= size;
7338 }
7339
7340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7341 av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
7342 return AVERROR_INVALIDDATA;
7343 }
7344
7345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (type == AV_STEREO3D_2D)
7346 return 0;
7347
7348
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->stereo3d) {
7349 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7351 return AVERROR(ENOMEM);
7352 }
7353
7354 3 sc->stereo3d->flags = flags;
7355 3 sc->stereo3d->type = type;
7356 3 sc->stereo3d->view = view;
7357 3 sc->stereo3d->primary_eye = primary_eye;
7358 3 sc->stereo3d->baseline = baseline;
7359 3 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
7360
7361 3 return 0;
7362 }
7363
7364 3 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7365 {
7366 int size;
7367 int64_t remaining;
7368 uint32_t tag;
7369
7370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7371 return 0;
7372
7373
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8) {
7374 av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
7375 return AVERROR_INVALIDDATA;
7376 }
7377
7378 3 remaining = atom.size;
7379
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 while (remaining > 0) {
7380 6 size = avio_rb32(pb);
7381
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 ) {
7382 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
7383 return AVERROR_INVALIDDATA;
7384 }
7385
7386 6 tag = avio_rl32(pb);
7387
2/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 switch (tag) {
7388 3 case MKTAG('p','r','o','j'): {
7389 3 MOVAtom proj = { tag, size - 8 };
7390 3 int ret = mov_read_vexu_proj(c, pb, proj);
7391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7392 return ret;
7393 3 break;
7394 }
7395 3 case MKTAG('e','y','e','s'): {
7396 3 MOVAtom eyes = { tag, size - 8 };
7397 3 int ret = mov_read_eyes(c, pb, eyes);
7398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7399 return ret;
7400 3 break;
7401 }
7402 case MKTAG('p','a','c','k'): {
7403 MOVAtom pack = { tag, size - 8 };
7404 int ret = mov_read_pack(c, pb, pack);
7405 if (ret < 0)
7406 return ret;
7407 break;
7408 }
7409 default:
7410 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: %s\n",
7411 av_fourcc2str(tag));
7412 avio_skip(pb, size - 8);
7413 break;
7414 }
7415 6 remaining -= size;
7416 }
7417
7418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7419 av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7420 return AVERROR_INVALIDDATA;
7421 }
7422
7423 3 return 0;
7424 }
7425
7426 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7427 {
7428 AVStream *st;
7429 MOVStreamContext *sc;
7430
7431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7432 return 0;
7433
7434 3 st = c->fc->streams[c->fc->nb_streams - 1];
7435 3 sc = st->priv_data;
7436
7437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7438 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7439 return AVERROR_INVALIDDATA;
7440 }
7441
7442
7443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7444 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7445 if (!sc->stereo3d)
7446 return AVERROR(ENOMEM);
7447 }
7448
7449 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7450 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7451
7452 3 return 0;
7453 }
7454
7455 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7456 {
7457 int ret = 0;
7458 uint8_t *buffer = av_malloc(len + 1);
7459 const char *val;
7460
7461 if (!buffer)
7462 return AVERROR(ENOMEM);
7463 buffer[len] = '\0';
7464
7465 ret = ffio_read_size(pb, buffer, len);
7466 if (ret < 0)
7467 goto out;
7468
7469 /* Check for mandatory keys and values, try to support XML as best-effort */
7470 if (!sc->spherical &&
7471 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7472 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7473 av_stristr(val, "true") &&
7474 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7475 av_stristr(val, "true") &&
7476 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7477 av_stristr(val, "equirectangular")) {
7478 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7479 if (!sc->spherical)
7480 goto out;
7481
7482 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7483
7484 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7485 enum AVStereo3DType mode;
7486
7487 if (av_stristr(buffer, "left-right"))
7488 mode = AV_STEREO3D_SIDEBYSIDE;
7489 else if (av_stristr(buffer, "top-bottom"))
7490 mode = AV_STEREO3D_TOPBOTTOM;
7491 else
7492 mode = AV_STEREO3D_2D;
7493
7494 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7495 if (!sc->stereo3d)
7496 goto out;
7497
7498 sc->stereo3d->type = mode;
7499 }
7500
7501 /* orientation */
7502 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7503 if (val)
7504 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7505 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7506 if (val)
7507 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7508 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7509 if (val)
7510 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7511 }
7512
7513 out:
7514 av_free(buffer);
7515 return ret;
7516 }
7517
7518 69 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7519 {
7520 AVStream *st;
7521 MOVStreamContext *sc;
7522 int64_t ret;
7523 AVUUID uuid;
7524 static const AVUUID uuid_isml_manifest = {
7525 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7526 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7527 };
7528 static const AVUUID uuid_xmp = {
7529 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7530 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7531 };
7532 static const AVUUID uuid_spherical = {
7533 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7534 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7535 };
7536
7537
2/4
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
69 if (atom.size < AV_UUID_LEN || atom.size >= FFMIN(INT_MAX, SIZE_MAX))
7538 return AVERROR_INVALIDDATA;
7539
7540
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 66 times.
69 if (c->fc->nb_streams < 1)
7541 3 return 0;
7542 66 st = c->fc->streams[c->fc->nb_streams - 1];
7543 66 sc = st->priv_data;
7544
7545 66 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
7547 return ret;
7548
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7549 uint8_t *buffer, *ptr;
7550 char *endptr;
7551 size_t len = atom.size - AV_UUID_LEN;
7552
7553 if (len < 4) {
7554 return AVERROR_INVALIDDATA;
7555 }
7556 ret = avio_skip(pb, 4); // zeroes
7557 len -= 4;
7558
7559 buffer = av_mallocz(len + 1);
7560 if (!buffer) {
7561 return AVERROR(ENOMEM);
7562 }
7563 ret = ffio_read_size(pb, buffer, len);
7564 if (ret < 0) {
7565 av_free(buffer);
7566 return ret;
7567 }
7568
7569 ptr = buffer;
7570 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7571 ptr += sizeof("systemBitrate=\"") - 1;
7572 c->bitrates_count++;
7573 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7574 if (!c->bitrates) {
7575 c->bitrates_count = 0;
7576 av_free(buffer);
7577 return AVERROR(ENOMEM);
7578 }
7579 errno = 0;
7580 ret = strtol(ptr, &endptr, 10);
7581 if (ret < 0 || errno || *endptr != '"') {
7582 c->bitrates[c->bitrates_count - 1] = 0;
7583 } else {
7584 c->bitrates[c->bitrates_count - 1] = ret;
7585 }
7586 }
7587
7588 av_free(buffer);
7589
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7590 uint8_t *buffer;
7591 size_t len = atom.size - AV_UUID_LEN;
7592 if (c->export_xmp) {
7593 buffer = av_mallocz(len + 1);
7594 if (!buffer) {
7595 return AVERROR(ENOMEM);
7596 }
7597 ret = ffio_read_size(pb, buffer, len);
7598 if (ret < 0) {
7599 av_free(buffer);
7600 return ret;
7601 }
7602 buffer[len] = '\0';
7603 av_dict_set(&c->fc->metadata, "xmp",
7604 buffer, AV_DICT_DONT_STRDUP_VAL);
7605 } else {
7606 // skip all uuid atom, which makes it fast for long uuid-xmp file
7607 ret = avio_skip(pb, len);
7608 if (ret < 0)
7609 return ret;
7610 }
7611
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7612 size_t len = atom.size - AV_UUID_LEN;
7613 ret = mov_parse_uuid_spherical(sc, pb, len);
7614 if (ret < 0)
7615 return ret;
7616 if (!sc->spherical)
7617 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7618 }
7619
7620 66 return 0;
7621 }
7622
7623 227 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7624 {
7625 int ret;
7626 uint8_t content[16];
7627
7628
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 107 times.
227 if (atom.size < 8)
7629 120 return 0;
7630
7631 107 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (ret < 0)
7633 return ret;
7634
7635
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 62 times.
107 if ( !c->found_moov
7636
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 23 times.
45 && !c->found_mdat
7637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 && !memcmp(content, "Anevia\x1A\x1A", 8)
7638 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7639 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7640 }
7641
7642 107 return 0;
7643 }
7644
7645 37 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7646 {
7647 37 uint32_t format = avio_rl32(pb);
7648 MOVStreamContext *sc;
7649 enum AVCodecID id;
7650 AVStream *st;
7651
7652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (c->fc->nb_streams < 1)
7653 return 0;
7654 37 st = c->fc->streams[c->fc->nb_streams - 1];
7655 37 sc = st->priv_data;
7656
7657
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 31 times.
37 switch (sc->format)
7658 {
7659 6 case MKTAG('e','n','c','v'): // encrypted video
7660 case MKTAG('e','n','c','a'): // encrypted audio
7661 6 id = mov_codec_id(st, format);
7662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7663 st->codecpar->codec_id != id) {
7664 av_log(c->fc, AV_LOG_WARNING,
7665 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7666 (char*)&format, st->codecpar->codec_id);
7667 break;
7668 }
7669
7670 6 st->codecpar->codec_id = id;
7671 6 sc->format = format;
7672 6 break;
7673
7674 31 default:
7675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (format != sc->format) {
7676 av_log(c->fc, AV_LOG_WARNING,
7677 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7678 (char*)&format, (char*)&sc->format);
7679 }
7680 31 break;
7681 }
7682
7683 37 return 0;
7684 }
7685
7686 /**
7687 * Gets the current encryption info and associated current stream context. If
7688 * we are parsing a track fragment, this will return the specific encryption
7689 * info for this fragment; otherwise this will return the global encryption
7690 * info for the current stream.
7691 */
7692 12 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7693 {
7694 MOVFragmentStreamInfo *frag_stream_info;
7695 AVStream *st;
7696 int i;
7697
7698 12 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7699
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (frag_stream_info) {
7700
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 for (i = 0; i < c->fc->nb_streams; i++) {
7701 6 *sc = c->fc->streams[i]->priv_data;
7702
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if ((*sc)->id == frag_stream_info->id) {
7703 6 st = c->fc->streams[i];
7704 6 break;
7705 }
7706 }
7707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (i == c->fc->nb_streams)
7708 return 0;
7709 6 *sc = st->priv_data;
7710
7711
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (!frag_stream_info->encryption_index) {
7712 // If this stream isn't encrypted, don't create the index.
7713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(*sc)->cenc.default_encrypted_sample)
7714 return 0;
7715 2 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7716
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!frag_stream_info->encryption_index)
7717 return AVERROR(ENOMEM);
7718 }
7719 6 *encryption_index = frag_stream_info->encryption_index;
7720 6 return 1;
7721 } else {
7722 // No current track fragment, using stream level encryption info.
7723
7724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (c->fc->nb_streams < 1)
7725 return 0;
7726 6 st = c->fc->streams[c->fc->nb_streams - 1];
7727 6 *sc = st->priv_data;
7728
7729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!(*sc)->cenc.encryption_index) {
7730 // If this stream isn't encrypted, don't create the index.
7731 if (!(*sc)->cenc.default_encrypted_sample)
7732 return 0;
7733 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7734 if (!(*sc)->cenc.encryption_index)
7735 return AVERROR(ENOMEM);
7736 }
7737
7738 6 *encryption_index = (*sc)->cenc.encryption_index;
7739 6 return 1;
7740 }
7741 }
7742
7743 144 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7744 {
7745 int i, ret;
7746 unsigned int subsample_count;
7747 AVSubsampleEncryptionInfo *subsamples;
7748
7749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (!sc->cenc.default_encrypted_sample) {
7750 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7751 return AVERROR_INVALIDDATA;
7752 }
7753
7754
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
144 if (sc->cenc.per_sample_iv_size || use_subsamples) {
7755 144 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (!*sample)
7757 return AVERROR(ENOMEM);
7758 } else
7759 *sample = NULL;
7760
7761
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 if (sc->cenc.per_sample_iv_size != 0) {
7762
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 144 times.
144 if ((ret = ffio_read_size(pb, (*sample)->iv, sc->cenc.per_sample_iv_size)) < 0) {
7763 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
7764 av_encryption_info_free(*sample);
7765 *sample = NULL;
7766 return ret;
7767 }
7768 }
7769
7770
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 if (use_subsamples) {
7771 144 subsample_count = avio_rb16(pb);
7772 144 av_free((*sample)->subsamples);
7773 144 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
7774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (!(*sample)->subsamples) {
7775 av_encryption_info_free(*sample);
7776 *sample = NULL;
7777 return AVERROR(ENOMEM);
7778 }
7779
7780
3/4
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
288 for (i = 0; i < subsample_count && !pb->eof_reached; i++) {
7781 144 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
7782 144 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
7783 }
7784
7785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (pb->eof_reached) {
7786 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
7787 av_encryption_info_free(*sample);
7788 *sample = NULL;
7789 return AVERROR_INVALIDDATA;
7790 }
7791 144 (*sample)->subsample_count = subsample_count;
7792 }
7793
7794 144 return 0;
7795 }
7796
7797 4 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7798 {
7799 AVEncryptionInfo **encrypted_samples;
7800 MOVEncryptionIndex *encryption_index;
7801 MOVStreamContext *sc;
7802 int use_subsamples, ret;
7803 4 unsigned int sample_count, i, alloc_size = 0;
7804
7805 4 ret = get_current_encryption_info(c, &encryption_index, &sc);
7806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != 1)
7807 return ret;
7808
7809
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (encryption_index->nb_encrypted_samples) {
7810 // This can happen if we have both saio/saiz and senc atoms.
7811 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
7812 2 return 0;
7813 }
7814
7815 2 avio_r8(pb); /* version */
7816 2 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
7817
7818 2 sample_count = avio_rb32(pb);
7819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7820 return AVERROR(ENOMEM);
7821
7822
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 2 times.
98 for (i = 0; i < sample_count; i++) {
7823 96 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7824 96 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7825 min_samples * sizeof(*encrypted_samples));
7826
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 if (encrypted_samples) {
7827 96 encryption_index->encrypted_samples = encrypted_samples;
7828
7829 96 ret = mov_read_sample_encryption_info(
7830 96 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
7831 } else {
7832 ret = AVERROR(ENOMEM);
7833 }
7834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (pb->eof_reached) {
7835 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
7836 if (ret >= 0)
7837 av_encryption_info_free(encryption_index->encrypted_samples[i]);
7838 ret = AVERROR_INVALIDDATA;
7839 }
7840
7841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (ret < 0) {
7842 for (; i > 0; i--)
7843 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7844 av_freep(&encryption_index->encrypted_samples);
7845 return ret;
7846 }
7847 }
7848 2 encryption_index->nb_encrypted_samples = sample_count;
7849
7850 2 return 0;
7851 }
7852
7853 2 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
7854 {
7855 AVEncryptionInfo **sample, **encrypted_samples;
7856 int64_t prev_pos;
7857 size_t sample_count, sample_info_size, i;
7858 2 int ret = 0;
7859 2 unsigned int alloc_size = 0;
7860
7861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->nb_encrypted_samples)
7862 return 0;
7863 2 sample_count = encryption_index->auxiliary_info_sample_count;
7864
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count != 1) {
7865 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
7866 return AVERROR_PATCHWELCOME;
7867 }
7868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
7869 return AVERROR(ENOMEM);
7870
7871 2 prev_pos = avio_tell(pb);
7872
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
7873
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 avio_seek(pb, encryption_index->auxiliary_offsets[0], SEEK_SET) != encryption_index->auxiliary_offsets[0]) {
7874 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
7875 goto finish;
7876 }
7877
7878
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
50 for (i = 0; i < sample_count && !pb->eof_reached; i++) {
7879 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
7880 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
7881 min_samples * sizeof(*encrypted_samples));
7882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (!encrypted_samples) {
7883 ret = AVERROR(ENOMEM);
7884 goto finish;
7885 }
7886 48 encryption_index->encrypted_samples = encrypted_samples;
7887
7888 48 sample = &encryption_index->encrypted_samples[i];
7889 96 sample_info_size = encryption_index->auxiliary_info_default_size
7890 48 ? encryption_index->auxiliary_info_default_size
7891
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 : encryption_index->auxiliary_info_sizes[i];
7892
7893 48 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
7894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0)
7895 goto finish;
7896 }
7897
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
7898 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
7899 ret = AVERROR_INVALIDDATA;
7900 } else {
7901 2 encryption_index->nb_encrypted_samples = sample_count;
7902 }
7903
7904 2 finish:
7905 2 avio_seek(pb, prev_pos, SEEK_SET);
7906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
7907 for (; i > 0; i--) {
7908 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
7909 }
7910 av_freep(&encryption_index->encrypted_samples);
7911 }
7912 2 return ret;
7913 }
7914
7915 4 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7916 {
7917 MOVEncryptionIndex *encryption_index;
7918 MOVStreamContext *sc;
7919 int ret;
7920 unsigned int sample_count, aux_info_type, aux_info_param;
7921
7922 4 ret = get_current_encryption_info(c, &encryption_index, &sc);
7923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != 1)
7924 return ret;
7925
7926
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (encryption_index->nb_encrypted_samples) {
7927 // This can happen if we have both saio/saiz and senc atoms.
7928 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
7929 2 return 0;
7930 }
7931
7932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_sample_count) {
7933 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
7934 return AVERROR_INVALIDDATA;
7935 }
7936
7937 2 avio_r8(pb); /* version */
7938
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
7939 aux_info_type = avio_rb32(pb);
7940 aux_info_param = avio_rb32(pb);
7941 if (sc->cenc.default_encrypted_sample) {
7942 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
7943 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
7944 return 0;
7945 }
7946 if (aux_info_param != 0) {
7947 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
7948 return 0;
7949 }
7950 } else {
7951 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7952 if ((aux_info_type == MKBETAG('c','e','n','c') ||
7953 aux_info_type == MKBETAG('c','e','n','s') ||
7954 aux_info_type == MKBETAG('c','b','c','1') ||
7955 aux_info_type == MKBETAG('c','b','c','s')) &&
7956 aux_info_param == 0) {
7957 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
7958 return AVERROR_INVALIDDATA;
7959 } else {
7960 return 0;
7961 }
7962 }
7963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
7964 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
7965 return 0;
7966 }
7967
7968 2 encryption_index->auxiliary_info_default_size = avio_r8(pb);
7969 2 sample_count = avio_rb32(pb);
7970
7971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_default_size == 0) {
7972 if (sample_count == 0)
7973 return AVERROR_INVALIDDATA;
7974
7975 encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
7976 if (!encryption_index->auxiliary_info_sizes)
7977 return AVERROR(ENOMEM);
7978
7979 ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
7980 if (ret != sample_count) {
7981 av_freep(&encryption_index->auxiliary_info_sizes);
7982
7983 if (ret >= 0)
7984 ret = AVERROR_INVALIDDATA;
7985 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
7986 av_err2str(ret));
7987 return ret;
7988 }
7989 }
7990 2 encryption_index->auxiliary_info_sample_count = sample_count;
7991
7992
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
7993 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
7994 }
7995
7996 2 return 0;
7997 }
7998
7999 4 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8000 {
8001 uint64_t *auxiliary_offsets;
8002 MOVEncryptionIndex *encryption_index;
8003 MOVStreamContext *sc;
8004 int i, ret;
8005 unsigned int version, entry_count, aux_info_type, aux_info_param;
8006 4 unsigned int alloc_size = 0;
8007
8008 4 ret = get_current_encryption_info(c, &encryption_index, &sc);
8009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != 1)
8010 return ret;
8011
8012
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (encryption_index->nb_encrypted_samples) {
8013 // This can happen if we have both saio/saiz and senc atoms.
8014 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
8015 2 return 0;
8016 }
8017
8018
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
8019 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
8020 return AVERROR_INVALIDDATA;
8021 }
8022
8023 2 version = avio_r8(pb); /* version */
8024
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
8025 aux_info_type = avio_rb32(pb);
8026 aux_info_param = avio_rb32(pb);
8027 if (sc->cenc.default_encrypted_sample) {
8028 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
8029 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
8030 return 0;
8031 }
8032 if (aux_info_param != 0) {
8033 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
8034 return 0;
8035 }
8036 } else {
8037 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8038 if ((aux_info_type == MKBETAG('c','e','n','c') ||
8039 aux_info_type == MKBETAG('c','e','n','s') ||
8040 aux_info_type == MKBETAG('c','b','c','1') ||
8041 aux_info_type == MKBETAG('c','b','c','s')) &&
8042 aux_info_param == 0) {
8043 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
8044 return AVERROR_INVALIDDATA;
8045 } else {
8046 return 0;
8047 }
8048 }
8049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
8050 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8051 return 0;
8052 }
8053
8054 2 entry_count = avio_rb32(pb);
8055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
8056 return AVERROR(ENOMEM);
8057
8058
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 for (i = 0; i < entry_count && !pb->eof_reached; i++) {
8059
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 unsigned int min_offsets = FFMIN(FFMAX(i + 1, 1024), entry_count);
8060 2 auxiliary_offsets = av_fast_realloc(
8061 2 encryption_index->auxiliary_offsets, &alloc_size,
8062 min_offsets * sizeof(*auxiliary_offsets));
8063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!auxiliary_offsets) {
8064 av_freep(&encryption_index->auxiliary_offsets);
8065 return AVERROR(ENOMEM);
8066 }
8067 2 encryption_index->auxiliary_offsets = auxiliary_offsets;
8068
8069
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version == 0) {
8070 2 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
8071 } else {
8072 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
8073 }
8074
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (c->frag_index.current >= 0) {
8075 2 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
8076 }
8077 }
8078
8079
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
8080 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
8081 av_freep(&encryption_index->auxiliary_offsets);
8082 return AVERROR_INVALIDDATA;
8083 }
8084
8085 2 encryption_index->auxiliary_offsets_count = entry_count;
8086
8087
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (encryption_index->auxiliary_info_sample_count) {
8088 2 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
8089 }
8090
8091 return 0;
8092 }
8093
8094 4 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8095 {
8096 AVEncryptionInitInfo *info, *old_init_info;
8097 uint8_t **key_ids;
8098 AVStream *st;
8099 const AVPacketSideData *old_side_data;
8100 uint8_t *side_data, *extra_data;
8101 size_t side_data_size;
8102 4 int ret = 0;
8103 4 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
8104
8105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8106 return 0;
8107 4 st = c->fc->streams[c->fc->nb_streams-1];
8108
8109 4 version = avio_r8(pb); /* version */
8110 4 avio_rb24(pb); /* flags */
8111
8112 4 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
8113 /* key_id_size */ 16, /* data_size */ 0);
8114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info)
8115 return AVERROR(ENOMEM);
8116
8117
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
8118 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
8119 goto finish;
8120 }
8121
8122
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (version > 0) {
8123 4 kid_count = avio_rb32(pb);
8124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
8125 ret = AVERROR(ENOMEM);
8126 goto finish;
8127 }
8128
8129
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 for (unsigned int i = 0; i < kid_count && !pb->eof_reached; i++) {
8130 4 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
8131 4 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
8132 min_kid_count * sizeof(*key_ids));
8133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!key_ids) {
8134 ret = AVERROR(ENOMEM);
8135 goto finish;
8136 }
8137 4 info->key_ids = key_ids;
8138
8139 4 info->key_ids[i] = av_mallocz(16);
8140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info->key_ids[i]) {
8141 ret = AVERROR(ENOMEM);
8142 goto finish;
8143 }
8144 4 info->num_key_ids = i + 1;
8145
8146
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
8147 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
8148 goto finish;
8149 }
8150 }
8151
8152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pb->eof_reached) {
8153 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
8154 ret = AVERROR_INVALIDDATA;
8155 goto finish;
8156 }
8157 }
8158
8159 4 extra_data_size = avio_rb32(pb);
8160 4 extra_data = av_malloc(extra_data_size);
8161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!extra_data) {
8162 ret = AVERROR(ENOMEM);
8163 goto finish;
8164 }
8165 4 ret = avio_read(pb, extra_data, extra_data_size);
8166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != extra_data_size) {
8167 av_free(extra_data);
8168
8169 if (ret >= 0)
8170 ret = AVERROR_INVALIDDATA;
8171 goto finish;
8172 }
8173
8174 4 av_freep(&info->data); // malloc(0) may still allocate something.
8175 4 info->data = extra_data;
8176 4 info->data_size = extra_data_size;
8177
8178 // If there is existing initialization data, append to the list.
8179 4 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
8180 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
8181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (old_side_data) {
8182 old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
8183 if (old_init_info) {
8184 // Append to the end of the list.
8185 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
8186 if (!cur->next) {
8187 cur->next = info;
8188 break;
8189 }
8190 }
8191 info = old_init_info;
8192 } else {
8193 // Assume existing side-data will be valid, so the only error we could get is OOM.
8194 ret = AVERROR(ENOMEM);
8195 goto finish;
8196 }
8197 }
8198
8199 4 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
8200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!side_data) {
8201 ret = AVERROR(ENOMEM);
8202 goto finish;
8203 }
8204
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
8205 4 &st->codecpar->nb_coded_side_data,
8206 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
8207 side_data, side_data_size, 0))
8208 av_free(side_data);
8209
8210 4 finish:
8211 4 av_encryption_init_info_free(info);
8212 4 return ret;
8213 }
8214
8215 6 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8216 {
8217 AVStream *st;
8218 MOVStreamContext *sc;
8219
8220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (c->fc->nb_streams < 1)
8221 return 0;
8222 6 st = c->fc->streams[c->fc->nb_streams-1];
8223 6 sc = st->priv_data;
8224
8225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (sc->pseudo_stream_id != 0) {
8226 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
8227 return AVERROR_PATCHWELCOME;
8228 }
8229
8230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 8)
8231 return AVERROR_INVALIDDATA;
8232
8233 6 avio_rb32(pb); /* version and flags */
8234
8235
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (!sc->cenc.default_encrypted_sample) {
8236 6 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc->cenc.default_encrypted_sample) {
8238 return AVERROR(ENOMEM);
8239 }
8240 }
8241
8242 6 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
8243 6 return 0;
8244 }
8245
8246 6 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8247 {
8248 AVStream *st;
8249 MOVStreamContext *sc;
8250 unsigned int version, pattern, is_protected, iv_size;
8251
8252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (c->fc->nb_streams < 1)
8253 return 0;
8254 6 st = c->fc->streams[c->fc->nb_streams-1];
8255 6 sc = st->priv_data;
8256
8257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (sc->pseudo_stream_id != 0) {
8258 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
8259 return AVERROR_PATCHWELCOME;
8260 }
8261
8262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc->cenc.default_encrypted_sample) {
8263 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8264 if (!sc->cenc.default_encrypted_sample) {
8265 return AVERROR(ENOMEM);
8266 }
8267 }
8268
8269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 20)
8270 return AVERROR_INVALIDDATA;
8271
8272 6 version = avio_r8(pb); /* version */
8273 6 avio_rb24(pb); /* flags */
8274
8275 6 avio_r8(pb); /* reserved */
8276 6 pattern = avio_r8(pb);
8277
8278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version > 0) {
8279 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
8280 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
8281 }
8282
8283 6 is_protected = avio_r8(pb);
8284
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 if (is_protected && !sc->cenc.encryption_index) {
8285 // The whole stream should be by-default encrypted.
8286 6 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
8287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc->cenc.encryption_index)
8288 return AVERROR(ENOMEM);
8289 }
8290 6 sc->cenc.per_sample_iv_size = avio_r8(pb);
8291
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
6 if (sc->cenc.per_sample_iv_size != 0 && sc->cenc.per_sample_iv_size != 8 &&
8292 sc->cenc.per_sample_iv_size != 16) {
8293 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
8294 return AVERROR_INVALIDDATA;
8295 }
8296
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (avio_read(pb, sc->cenc.default_encrypted_sample->key_id, 16) != 16) {
8297 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
8298 return AVERROR_INVALIDDATA;
8299 }
8300
8301
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
6 if (is_protected && !sc->cenc.per_sample_iv_size) {
8302 2 iv_size = avio_r8(pb);
8303
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (iv_size != 8 && iv_size != 16) {
8304 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
8305 return AVERROR_INVALIDDATA;
8306 }
8307
8308
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_read(pb, sc->cenc.default_encrypted_sample->iv, iv_size) != iv_size) {
8309 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
8310 return AVERROR_INVALIDDATA;
8311 }
8312 }
8313
8314 6 return 0;
8315 }
8316
8317 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8318 {
8319 AVStream *st;
8320 int last, type, size, ret;
8321 uint8_t buf[4];
8322
8323 if (c->fc->nb_streams < 1)
8324 return 0;
8325 st = c->fc->streams[c->fc->nb_streams-1];
8326
8327 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
8328 return AVERROR_INVALIDDATA;
8329
8330 /* Check FlacSpecificBox version. */
8331 if (avio_r8(pb) != 0)
8332 return AVERROR_INVALIDDATA;
8333
8334 avio_rb24(pb); /* Flags */
8335
8336 if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
8337 av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
8338 return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
8339 }
8340 flac_parse_block_header(buf, &last, &type, &size);
8341
8342 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
8343 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
8344 return AVERROR_INVALIDDATA;
8345 }
8346
8347 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
8348 if (ret < 0)
8349 return ret;
8350
8351 if (!last)
8352 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
8353
8354 return 0;
8355 }
8356
8357 6 static int get_key_from_kid(uint8_t* out, int len, MOVContext *c, AVEncryptionInfo *sample) {
8358 AVDictionaryEntry *key_entry_hex;
8359 char kid_hex[16*2+1];
8360
8361
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
6 if (c->decryption_default_key && c->decryption_default_key_len != len) {
8362 av_log(c->fc, AV_LOG_ERROR, "invalid default decryption key length: got %d, expected %d\n", c->decryption_default_key_len, len);
8363 return -1;
8364 }
8365
8366
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (!c->decryption_keys) {
8367
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 av_assert0(c->decryption_default_key);
8368 3 memcpy(out, c->decryption_default_key, len);
8369 3 return 0;
8370 }
8371
8372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sample->key_id_size != 16) {
8373 av_log(c->fc, AV_LOG_ERROR, "invalid key ID size: got %u, expected 16\n", sample->key_id_size);
8374 return -1;
8375 }
8376
8377 3 ff_data_to_hex(kid_hex, sample->key_id, 16, 1);
8378 3 key_entry_hex = av_dict_get(c->decryption_keys, kid_hex, NULL, AV_DICT_DONT_STRDUP_KEY|AV_DICT_DONT_STRDUP_VAL);
8379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!key_entry_hex) {
8380 if (!c->decryption_default_key) {
8381 av_log(c->fc, AV_LOG_ERROR, "unable to find KID %s\n", kid_hex);
8382 return -1;
8383 }
8384 memcpy(out, c->decryption_default_key, len);
8385 return 0;
8386 }
8387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (strlen(key_entry_hex->value) != len*2) {
8388 return -1;
8389 }
8390 3 ff_hex_to_data(out, key_entry_hex->value);
8391 3 return 0;
8392 }
8393
8394 292 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8395 {
8396 int i, ret;
8397 int bytes_of_protected_data;
8398 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8399
8400
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 286 times.
292 if (!sc->cenc.aes_ctr) {
8401 6 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0) {
8403 return ret;
8404 }
8405
8406 /* initialize the cipher */
8407 6 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc->cenc.aes_ctr) {
8409 return AVERROR(ENOMEM);
8410 }
8411
8412 6 ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0) {
8414 return ret;
8415 }
8416 }
8417
8418 292 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8419
8420
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 196 times.
292 if (!sample->subsample_count) {
8421 /* decrypt the whole packet */
8422 96 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8423 96 return 0;
8424 }
8425
8426
2/2
✓ Branch 0 taken 196 times.
✓ Branch 1 taken 196 times.
392 for (i = 0; i < sample->subsample_count; i++) {
8427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8428 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8429 return AVERROR_INVALIDDATA;
8430 }
8431
8432 /* skip the clear bytes */
8433 196 input += sample->subsamples[i].bytes_of_clear_data;
8434 196 size -= sample->subsamples[i].bytes_of_clear_data;
8435
8436 /* decrypt the encrypted bytes */
8437
8438 196 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
8439 196 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
8440
8441 196 input += bytes_of_protected_data;
8442 196 size -= bytes_of_protected_data;
8443 }
8444
8445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 if (size > 0) {
8446 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8447 return AVERROR_INVALIDDATA;
8448 }
8449
8450 196 return 0;
8451 }
8452
8453 static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8454 {
8455 int i, ret;
8456 int num_of_encrypted_blocks;
8457 uint8_t iv[16];
8458 uint8_t decryption_key[16];
8459
8460 if (!sc->cenc.aes_ctx) {
8461 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8462 if (ret < 0) {
8463 return ret;
8464 }
8465
8466 /* initialize the cipher */
8467 sc->cenc.aes_ctx = av_aes_alloc();
8468 if (!sc->cenc.aes_ctx) {
8469 return AVERROR(ENOMEM);
8470 }
8471
8472 ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8473 if (ret < 0) {
8474 return ret;
8475 }
8476 }
8477
8478 memcpy(iv, sample->iv, 16);
8479
8480 /* whole-block full sample encryption */
8481 if (!sample->subsample_count) {
8482 /* decrypt the whole packet */
8483 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8484 return 0;
8485 }
8486
8487 for (i = 0; i < sample->subsample_count; i++) {
8488 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8489 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8490 return AVERROR_INVALIDDATA;
8491 }
8492
8493 if (sample->subsamples[i].bytes_of_protected_data % 16) {
8494 av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8495 return AVERROR_INVALIDDATA;
8496 }
8497
8498 /* skip the clear bytes */
8499 input += sample->subsamples[i].bytes_of_clear_data;
8500 size -= sample->subsamples[i].bytes_of_clear_data;
8501
8502 /* decrypt the encrypted bytes */
8503 num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8504 if (num_of_encrypted_blocks > 0) {
8505 av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8506 }
8507 input += sample->subsamples[i].bytes_of_protected_data;
8508 size -= sample->subsamples[i].bytes_of_protected_data;
8509 }
8510
8511 if (size > 0) {
8512 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8513 return AVERROR_INVALIDDATA;
8514 }
8515
8516 return 0;
8517 }
8518
8519 static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8520 {
8521 int i, ret, rem_bytes;
8522 uint8_t *data;
8523 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8524
8525 if (!sc->cenc.aes_ctr) {
8526 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8527 if (ret < 0) {
8528 return ret;
8529 }
8530
8531 /* initialize the cipher */
8532 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8533 if (!sc->cenc.aes_ctr) {
8534 return AVERROR(ENOMEM);
8535 }
8536
8537 ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8538 if (ret < 0) {
8539 return ret;
8540 }
8541 }
8542
8543 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8544
8545 /* whole-block full sample encryption */
8546 if (!sample->subsample_count) {
8547 /* decrypt the whole packet */
8548 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8549 return 0;
8550 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8551 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8552 return AVERROR_INVALIDDATA;
8553 }
8554
8555 for (i = 0; i < sample->subsample_count; i++) {
8556 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8557 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8558 return AVERROR_INVALIDDATA;
8559 }
8560
8561 /* skip the clear bytes */
8562 input += sample->subsamples[i].bytes_of_clear_data;
8563 size -= sample->subsamples[i].bytes_of_clear_data;
8564
8565 /* decrypt the encrypted bytes */
8566 data = input;
8567 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8568 while (rem_bytes > 0) {
8569 if (rem_bytes < 16*sample->crypt_byte_block) {
8570 break;
8571 }
8572 av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8573 data += 16*sample->crypt_byte_block;
8574 rem_bytes -= 16*sample->crypt_byte_block;
8575 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8576 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8577 }
8578 input += sample->subsamples[i].bytes_of_protected_data;
8579 size -= sample->subsamples[i].bytes_of_protected_data;
8580 }
8581
8582 if (size > 0) {
8583 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8584 return AVERROR_INVALIDDATA;
8585 }
8586
8587 return 0;
8588 }
8589
8590 static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8591 {
8592 int i, ret, rem_bytes;
8593 uint8_t iv[16];
8594 uint8_t *data;
8595 uint8_t decryption_key[16];
8596
8597 if (!sc->cenc.aes_ctx) {
8598 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8599 if (ret < 0) {
8600 return ret;
8601 }
8602
8603 /* initialize the cipher */
8604 sc->cenc.aes_ctx = av_aes_alloc();
8605 if (!sc->cenc.aes_ctx) {
8606 return AVERROR(ENOMEM);
8607 }
8608
8609 ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8610 if (ret < 0) {
8611 return ret;
8612 }
8613 }
8614
8615 /* whole-block full sample encryption */
8616 if (!sample->subsample_count) {
8617 /* decrypt the whole packet */
8618 memcpy(iv, sample->iv, 16);
8619 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8620 return 0;
8621 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8622 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8623 return AVERROR_INVALIDDATA;
8624 }
8625
8626 for (i = 0; i < sample->subsample_count; i++) {
8627 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8628 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8629 return AVERROR_INVALIDDATA;
8630 }
8631
8632 /* skip the clear bytes */
8633 input += sample->subsamples[i].bytes_of_clear_data;
8634 size -= sample->subsamples[i].bytes_of_clear_data;
8635
8636 /* decrypt the encrypted bytes */
8637 memcpy(iv, sample->iv, 16);
8638 data = input;
8639 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8640 while (rem_bytes > 0) {
8641 if (rem_bytes < 16*sample->crypt_byte_block) {
8642 break;
8643 }
8644 av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8645 data += 16*sample->crypt_byte_block;
8646 rem_bytes -= 16*sample->crypt_byte_block;
8647 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8648 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8649 }
8650 input += sample->subsamples[i].bytes_of_protected_data;
8651 size -= sample->subsamples[i].bytes_of_protected_data;
8652 }
8653
8654 if (size > 0) {
8655 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8656 return AVERROR_INVALIDDATA;
8657 }
8658
8659 return 0;
8660 }
8661
8662 292 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8663 {
8664
3/6
✓ Branch 0 taken 292 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 292 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 292 times.
✗ Branch 5 not taken.
292 if (sample->scheme == MKBETAG('c','e','n','c') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8665 292 return cenc_scheme_decrypt(c, sc, sample, input, size);
8666 } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8667 return cbc1_scheme_decrypt(c, sc, sample, input, size);
8668 } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8669 return cens_scheme_decrypt(c, sc, sample, input, size);
8670 } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8671 return cbcs_scheme_decrypt(c, sc, sample, input, size);
8672 } else {
8673 av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8674 return AVERROR_INVALIDDATA;
8675 }
8676 }
8677
8678 107060 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8679 {
8680 107060 int current = frag_index->current;
8681
8682
2/2
✓ Branch 0 taken 106086 times.
✓ Branch 1 taken 974 times.
107060 if (!frag_index->nb_items)
8683 106086 return NULL;
8684
8685 // Check frag_index->current is the right one for pkt. It can out of sync.
8686
2/4
✓ Branch 0 taken 974 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 974 times.
✗ Branch 3 not taken.
974 if (current >= 0 && current < frag_index->nb_items) {
8687
2/2
✓ Branch 0 taken 948 times.
✓ Branch 1 taken 26 times.
974 if (frag_index->item[current].moof_offset < pkt->pos &&
8688
2/2
✓ Branch 0 taken 606 times.
✓ Branch 1 taken 342 times.
948 (current + 1 == frag_index->nb_items ||
8689
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 75 times.
606 frag_index->item[current + 1].moof_offset > pkt->pos))
8690 873 return get_frag_stream_info(frag_index, current, id);
8691 }
8692
8693
8694
2/2
✓ Branch 0 taken 4553 times.
✓ Branch 1 taken 8 times.
4561 for (int i = 0; i < frag_index->nb_items; i++) {
8695
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 4460 times.
4553 if (frag_index->item[i].moof_offset > pkt->pos)
8696 93 break;
8697 4460 current = i;
8698 }
8699 101 frag_index->current = current;
8700 101 return get_frag_stream_info(frag_index, current, id);
8701 }
8702
8703 107060 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8704 {
8705 MOVFragmentStreamInfo *frag_stream_info;
8706 MOVEncryptionIndex *encryption_index;
8707 AVEncryptionInfo *encrypted_sample;
8708 int encrypted_index, ret;
8709
8710 107060 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8711 107060 encrypted_index = current_index;
8712 107060 encryption_index = NULL;
8713
2/2
✓ Branch 0 taken 974 times.
✓ Branch 1 taken 106086 times.
107060 if (frag_stream_info) {
8714 // Note this only supports encryption info in the first sample descriptor.
8715
2/2
✓ Branch 0 taken 926 times.
✓ Branch 1 taken 48 times.
974 if (frag_stream_info->stsd_id == 1) {
8716
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 878 times.
926 if (frag_stream_info->encryption_index) {
8717 48 encrypted_index = current_index - frag_stream_info->index_base;
8718 48 encryption_index = frag_stream_info->encryption_index;
8719 } else {
8720 878 encryption_index = sc->cenc.encryption_index;
8721 }
8722 }
8723 } else {
8724 106086 encryption_index = sc->cenc.encryption_index;
8725 }
8726
8727
2/2
✓ Branch 0 taken 292 times.
✓ Branch 1 taken 106768 times.
107060 if (encryption_index) {
8728
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 244 times.
292 if (encryption_index->auxiliary_info_sample_count &&
8729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8730 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8731 return AVERROR_INVALIDDATA;
8732 }
8733
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 244 times.
292 if (encryption_index->auxiliary_offsets_count &&
8734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8735 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8736 return AVERROR_INVALIDDATA;
8737 }
8738
8739 292 encrypted_sample = NULL;
8740
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 196 times.
292 if (!encryption_index->nb_encrypted_samples) {
8741 // Full-sample encryption with default settings.
8742 96 encrypted_sample = sc->cenc.default_encrypted_sample;
8743
2/4
✓ Branch 0 taken 196 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 196 times.
✗ Branch 3 not taken.
196 } else if (encrypted_index >= 0 && encrypted_index < encryption_index->nb_encrypted_samples) {
8744 // Per-sample setting override.
8745 196 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 if (!encrypted_sample) {
8747 encrypted_sample = sc->cenc.default_encrypted_sample;
8748 }
8749 }
8750
8751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 292 times.
292 if (!encrypted_sample) {
8752 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8753 return AVERROR_INVALIDDATA;
8754 }
8755
8756
3/4
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 146 times.
✓ Branch 2 taken 146 times.
✗ Branch 3 not taken.
292 if (mov->decryption_keys || mov->decryption_default_key) {
8757 292 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
8758 } else {
8759 size_t size;
8760 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
8761 if (!side_data)
8762 return AVERROR(ENOMEM);
8763 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
8764 if (ret < 0)
8765 av_free(side_data);
8766 return ret;
8767 }
8768 }
8769
8770 106768 return 0;
8771 }
8772
8773 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8774 {
8775 const int OPUS_SEEK_PREROLL_MS = 80;
8776 int ret;
8777 AVStream *st;
8778 size_t size;
8779 uint16_t pre_skip;
8780
8781 if (c->fc->nb_streams < 1)
8782 return 0;
8783 st = c->fc->streams[c->fc->nb_streams-1];
8784
8785 if ((uint64_t)atom.size > (1<<30) || atom.size < 11 || st->codecpar->extradata)
8786 return AVERROR_INVALIDDATA;
8787
8788 /* Check OpusSpecificBox version. */
8789 if (avio_r8(pb) != 0) {
8790 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
8791 return AVERROR_INVALIDDATA;
8792 }
8793
8794 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
8795 size = atom.size + 8;
8796
8797 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
8798 return ret;
8799
8800 AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
8801 AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
8802 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
8803 if ((ret = ffio_read_size(pb, st->codecpar->extradata + 9, size - 9)) < 0) {
8804 av_freep(&st->codecpar->extradata);
8805 st->codecpar->extradata_size = 0;
8806 return ret;
8807 }
8808
8809 /* OpusSpecificBox is stored in big-endian, but OpusHead is
8810 little-endian; aside from the preceding magic and version they're
8811 otherwise currently identical. Data after output gain at offset 16
8812 doesn't need to be bytewapped. */
8813 pre_skip = AV_RB16A(st->codecpar->extradata + 10);
8814 AV_WL16A(st->codecpar->extradata + 10, pre_skip);
8815 AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
8816 AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
8817
8818 st->codecpar->initial_padding = pre_skip;
8819 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
8820 (AVRational){1, 1000},
8821 (AVRational){1, 48000});
8822
8823 return 0;
8824 }
8825
8826 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8827 {
8828 AVStream *st;
8829 unsigned format_info;
8830 int channel_assignment, channel_assignment1, channel_assignment2;
8831 int ratebits;
8832 uint64_t chmask;
8833
8834 if (c->fc->nb_streams < 1)
8835 return 0;
8836 st = c->fc->streams[c->fc->nb_streams-1];
8837
8838 if (atom.size < 10)
8839 return AVERROR_INVALIDDATA;
8840
8841 format_info = avio_rb32(pb);
8842
8843 ratebits = (format_info >> 28) & 0xF;
8844 channel_assignment1 = (format_info >> 15) & 0x1F;
8845 channel_assignment2 = format_info & 0x1FFF;
8846 if (channel_assignment2)
8847 channel_assignment = channel_assignment2;
8848 else
8849 channel_assignment = channel_assignment1;
8850
8851 st->codecpar->frame_size = 40 << (ratebits & 0x7);
8852 st->codecpar->sample_rate = mlp_samplerate(ratebits);
8853
8854 av_channel_layout_uninit(&st->codecpar->ch_layout);
8855 chmask = truehd_layout(channel_assignment);
8856 av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
8857
8858 return 0;
8859 }
8860
8861 11 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8862 {
8863 AVStream *st;
8864 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
8865 int ret;
8866 11 int64_t read_size = atom.size;
8867
8868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
8869 return 0;
8870 11 st = c->fc->streams[c->fc->nb_streams-1];
8871
8872 // At most 24 bytes
8873 11 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
8874
8875
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
8876 return ret;
8877
8878 11 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
8879 }
8880
8881 7 static int mov_read_hvce(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8882 {
8883 AVStream *st;
8884 AVPacketSideData *sd;
8885 int ret;
8886
8887
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (c->fc->nb_streams < 1)
8888 return 0;
8889 7 st = c->fc->streams[c->fc->nb_streams - 1];
8890
8891
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (atom.size < 23 || atom.size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
8892 return AVERROR_INVALIDDATA;
8893
8894 7 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
8895 7 &st->codecpar->nb_coded_side_data,
8896 AV_PKT_DATA_HEVC_CONF,
8897 7 atom.size, 0);
8898
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sd)
8899 return AVERROR(ENOMEM);
8900
8901 7 ret = ffio_read_size(pb, sd->data, atom.size);
8902
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
8903 return ret;
8904
8905 7 return 0;
8906 }
8907
8908 4 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8909 {
8910 AVStream *st;
8911 uint8_t *buf;
8912 int ret, old_size, num_arrays;
8913
8914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8915 return 0;
8916 4 st = c->fc->streams[c->fc->nb_streams-1];
8917
8918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!st->codecpar->extradata_size)
8919 // TODO: handle lhvC when present before hvcC
8920 return 0;
8921
8922
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if (atom.size < 6 || st->codecpar->extradata_size < 23 ||
8923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 atom.size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
8924 return AVERROR_INVALIDDATA;
8925 }
8926
8927 4 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
8928
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!buf)
8929 return AVERROR(ENOMEM);
8930 4 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
8931
8932 4 ret = ffio_read_size(pb, buf, atom.size);
8933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
8934 av_free(buf);
8935 av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
8936 return 0;
8937 }
8938
8939 4 num_arrays = buf[5];
8940 4 old_size = st->codecpar->extradata_size;
8941 4 atom.size -= 8 /* account for mov_realloc_extradata offsetting */
8942 + 6 /* lhvC bytes before the arrays*/;
8943
8944 4 ret = mov_realloc_extradata(st->codecpar, atom);
8945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
8946 av_free(buf);
8947 return ret;
8948 }
8949
8950 4 st->codecpar->extradata[22] += num_arrays;
8951 4 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
8952
8953 4 st->disposition |= AV_DISPOSITION_MULTILAYER;
8954
8955 4 av_free(buf);
8956 4 return 0;
8957 }
8958
8959 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8960 {
8961 4 AVFormatContext *ctx = c->fc;
8962 4 AVStream *st = NULL;
8963 AVBPrint scheme_buf, value_buf;
8964 4 int64_t scheme_str_len = 0, value_str_len = 0;
8965 4 int version, flags, ret = AVERROR_BUG;
8966 4 int64_t size = atom.size;
8967
8968
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
8969 // 4 bytes for version + flags, 2x 1 byte for null
8970 return AVERROR_INVALIDDATA;
8971
8972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8973 return 0;
8974 4 st = c->fc->streams[c->fc->nb_streams-1];
8975
8976 4 version = avio_r8(pb);
8977 4 flags = avio_rb24(pb);
8978 4 size -= 4;
8979
8980
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) {
8981 av_log(ctx, AV_LOG_ERROR,
8982 "Unsupported 'kind' box with version %d, flags: %x",
8983 version, flags);
8984 return AVERROR_INVALIDDATA;
8985 }
8986
8987 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8988 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
8989
8990
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,
8991 size)) < 0) {
8992 ret = scheme_str_len;
8993 goto cleanup;
8994 }
8995
8996
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
8997 // we need to have another string, even if nullptr.
8998 // we check with + 1 since we expect that if size was not hit,
8999 // an additional null was read.
9000 ret = AVERROR_INVALIDDATA;
9001 goto cleanup;
9002 }
9003
9004 4 size -= scheme_str_len + 1;
9005
9006
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,
9007 size)) < 0) {
9008 ret = value_str_len;
9009 goto cleanup;
9010 }
9011
9012
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
9013 // in case of no trailing null, box is not valid.
9014 ret = AVERROR_INVALIDDATA;
9015 goto cleanup;
9016 }
9017
9018 4 av_log(ctx, AV_LOG_TRACE,
9019 "%s stream %d KindBox(scheme: %s, value: %s)\n",
9020 4 av_get_media_type_string(st->codecpar->codec_type),
9021 st->index,
9022 scheme_buf.str, value_buf.str);
9023
9024
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++) {
9025 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
9026
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
9027 continue;
9028
9029
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
9030 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
9031
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
9032 16 continue;
9033
9034 4 st->disposition |= value_map.disposition;
9035 }
9036 }
9037
9038 4 ret = 0;
9039
9040 4 cleanup:
9041
9042 4 av_bprint_finalize(&scheme_buf, NULL);
9043 4 av_bprint_finalize(&value_buf, NULL);
9044
9045 4 return ret;
9046 }
9047
9048 static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9049 {
9050 AVStream *st;
9051 AVChannelLayout ch_layout = { 0 };
9052 int ret, i, version, type;
9053 int ambisonic_order, channel_order, normalization, channel_count;
9054 int ambi_channels, non_diegetic_channels;
9055
9056 if (c->fc->nb_streams < 1)
9057 return 0;
9058
9059 st = c->fc->streams[c->fc->nb_streams - 1];
9060
9061 if (atom.size < 16) {
9062 av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
9063 return AVERROR_INVALIDDATA;
9064 }
9065
9066 version = avio_r8(pb);
9067 if (version) {
9068 av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
9069 return 0;
9070 }
9071
9072 type = avio_r8(pb);
9073 if (type & 0x7f) {
9074 av_log(c->fc, AV_LOG_WARNING,
9075 "Unsupported ambisonic type %d\n", type & 0x7f);
9076 return 0;
9077 }
9078 non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
9079
9080 ambisonic_order = avio_rb32(pb);
9081
9082 channel_order = avio_r8(pb);
9083 if (channel_order) {
9084 av_log(c->fc, AV_LOG_WARNING,
9085 "Unsupported channel_order %d\n", channel_order);
9086 return 0;
9087 }
9088
9089 normalization = avio_r8(pb);
9090 if (normalization) {
9091 av_log(c->fc, AV_LOG_WARNING,
9092 "Unsupported normalization %d\n", normalization);
9093 return 0;
9094 }
9095
9096 channel_count = avio_rb32(pb);
9097 if (ambisonic_order < 0 || ambisonic_order > 31 ||
9098 channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
9099 non_diegetic_channels)) {
9100 av_log(c->fc, AV_LOG_ERROR,
9101 "Invalid number of channels (%d / %d)\n",
9102 channel_count, ambisonic_order);
9103 return 0;
9104 }
9105 ambi_channels = channel_count - non_diegetic_channels;
9106
9107 ret = av_channel_layout_custom_init(&ch_layout, channel_count);
9108 if (ret < 0)
9109 return 0;
9110
9111 for (i = 0; i < channel_count; i++) {
9112 unsigned channel = avio_rb32(pb);
9113
9114 if (channel >= channel_count) {
9115 av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
9116 channel, ambisonic_order);
9117 av_channel_layout_uninit(&ch_layout);
9118 return 0;
9119 }
9120 if (channel >= ambi_channels)
9121 ch_layout.u.map[i].id = channel - ambi_channels;
9122 else
9123 ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
9124 }
9125
9126 ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
9127 if (ret < 0) {
9128 av_channel_layout_uninit(&ch_layout);
9129 return 0;
9130 }
9131
9132 av_channel_layout_uninit(&st->codecpar->ch_layout);
9133 st->codecpar->ch_layout = ch_layout;
9134
9135 return 0;
9136 }
9137
9138 static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9139 {
9140 AVStream *st;
9141 int version;
9142
9143 if (c->fc->nb_streams < 1)
9144 return 0;
9145
9146 st = c->fc->streams[c->fc->nb_streams - 1];
9147
9148 if (atom.size < 5) {
9149 av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
9150 return AVERROR_INVALIDDATA;
9151 }
9152
9153 version = avio_r8(pb);
9154 if (version) {
9155 av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
9156 return 0;
9157 }
9158
9159 st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
9160
9161 return 0;
9162 }
9163
9164 171 static int rb_size(AVIOContext *pb, int64_t *value, int size)
9165 {
9166
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 160 times.
171 if (size == 0)
9167 11 *value = 0;
9168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 else if (size == 1)
9169 *value = avio_r8(pb);
9170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 else if (size == 2)
9171 *value = avio_rb16(pb);
9172
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 else if (size == 4)
9173 160 *value = avio_rb32(pb);
9174 else if (size == 8) {
9175 *value = avio_rb64(pb);
9176 if (*value < 0)
9177 return -1;
9178 } else
9179 return -1;
9180 171 return size;
9181 }
9182
9183 18 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9184 {
9185 18 avio_rb32(pb); // version & flags.
9186 18 c->primary_item_id = avio_rb16(pb);
9187 18 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
9188 18 return atom.size;
9189 }
9190
9191 9 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9192 {
9193 9 c->idat_offset = avio_tell(pb);
9194 9 return 0;
9195 }
9196
9197 18 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9198 {
9199 HEIFItem **heif_item;
9200 int version, offset_size, length_size, base_offset_size, index_size;
9201 int item_count, extent_count;
9202 int64_t base_offset, extent_offset, extent_length;
9203 uint8_t value;
9204
9205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->found_iloc) {
9206 av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
9207 return 0;
9208 }
9209
9210 18 version = avio_r8(pb);
9211 18 avio_rb24(pb); // flags.
9212
9213 18 value = avio_r8(pb);
9214 18 offset_size = (value >> 4) & 0xF;
9215 18 length_size = value & 0xF;
9216 18 value = avio_r8(pb);
9217 18 base_offset_size = (value >> 4) & 0xF;
9218
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 7 times.
18 index_size = !version ? 0 : (value & 0xF);
9219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (index_size) {
9220 avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
9221 return AVERROR_PATCHWELCOME;
9222 }
9223
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9224
9225 18 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
9226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!heif_item)
9227 return AVERROR(ENOMEM);
9228 18 c->heif_item = heif_item;
9229
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (item_count > c->nb_heif_item)
9230 18 memset(&c->heif_item[c->nb_heif_item], 0,
9231 18 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
9232 18 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
9233
9234 18 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
9235
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (int i = 0; i < item_count; i++) {
9236 57 HEIFItem *item = NULL;
9237
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9238
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 12 times.
57 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
9239 int j;
9240
9241
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (avio_feof(pb))
9242 return AVERROR_INVALIDDATA;
9243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (offset_type > 1) {
9244 avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
9245 return AVERROR_PATCHWELCOME;
9246 }
9247
9248 57 avio_rb16(pb); // data_reference_index.
9249
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (rb_size(pb, &base_offset, base_offset_size) < 0)
9250 return AVERROR_INVALIDDATA;
9251 57 extent_count = avio_rb16(pb);
9252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (extent_count > 1) {
9253 // For still AVIF images, we only support one extent item.
9254 avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
9255 return AVERROR_PATCHWELCOME;
9256 }
9257
9258
2/4
✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 57 times.
✗ Branch 4 not taken.
114 if (rb_size(pb, &extent_offset, offset_size) < 0 ||
9259 57 rb_size(pb, &extent_length, length_size) < 0 ||
9260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 base_offset > INT64_MAX - extent_offset)
9261 return AVERROR_INVALIDDATA;
9262
9263
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 for (j = 0; j < c->nb_heif_item; j++) {
9264 140 item = c->heif_item[j];
9265
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 83 times.
140 if (!item)
9266 57 item = c->heif_item[j] = av_mallocz(sizeof(*item));
9267
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
83 else if (item->item_id != item_id)
9268 83 continue;
9269 57 break;
9270 }
9271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item)
9272 return AVERROR(ENOMEM);
9273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (j == c->nb_heif_item)
9274 return AVERROR_INVALIDDATA;
9275
9276 57 item->item_id = item_id;
9277
9278
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 48 times.
57 if (offset_type == 1)
9279 9 item->is_idat_relative = 1;
9280 57 item->extent_length = extent_length;
9281 57 item->extent_offset = base_offset + extent_offset;
9282 57 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, item->item_id %d, offset_type %d, "
9283 "extent_offset %"PRId64", extent_length %"PRId64"\n",
9284 i, item->item_id, offset_type, item->extent_offset, item->extent_length);
9285 }
9286
9287 18 c->found_iloc = 1;
9288 18 return atom.size;
9289 }
9290
9291 57 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9292 {
9293 57 HEIFItem *item = NULL;
9294 AVBPrint item_name;
9295 57 int64_t size = atom.size;
9296 uint32_t item_type;
9297 int item_id;
9298 int i, version, ret;
9299
9300 57 version = avio_r8(pb);
9301 57 avio_rb24(pb); // flags.
9302 57 size -= 4;
9303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (size < 0)
9304 return AVERROR_INVALIDDATA;
9305
9306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (version < 2) {
9307 avpriv_report_missing_feature(c->fc, "infe version < 2");
9308 avio_skip(pb, size);
9309 return 1;
9310 }
9311
9312
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
9313 57 avio_rb16(pb); // item_protection_index
9314 57 item_type = avio_rl32(pb);
9315 57 size -= 8;
9316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (size < 1)
9317 return AVERROR_INVALIDDATA;
9318
9319 57 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
9320 57 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
9321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (ret < 0) {
9322 av_bprint_finalize(&item_name, NULL);
9323 return ret;
9324 }
9325
9326 57 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
9327 57 item_id, av_fourcc2str(item_type), item_name.str);
9328
9329 57 size -= ret + 1;
9330
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 55 times.
57 if (size > 0)
9331 2 avio_skip(pb, size);
9332
9333
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 for (i = 0; i < c->nb_heif_item; i++) {
9334 140 item = c->heif_item[i];
9335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (!item)
9336 item = c->heif_item[i] = av_mallocz(sizeof(*item));
9337
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 57 times.
140 else if (item->item_id != item_id)
9338 83 continue;
9339 57 break;
9340 }
9341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item) {
9342 av_bprint_finalize(&item_name, NULL);
9343 return AVERROR(ENOMEM);
9344 }
9345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (i == c->nb_heif_item) {
9346 av_bprint_finalize(&item_name, NULL);
9347 return AVERROR_INVALIDDATA;
9348 }
9349
9350 57 av_freep(&item->name);
9351
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 1 times.
57 av_bprint_finalize(&item_name, ret ? &item->name : NULL);
9352 57 item->item_id = item_id;
9353 57 item->type = item_type;
9354
9355
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 14 times.
57 switch (item_type) {
9356 43 case MKTAG('a','v','0','1'):
9357 case MKTAG('j','p','e','g'):
9358 case MKTAG('h','v','c','1'):
9359 43 ret = heif_add_stream(c, item);
9360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
9361 return ret;
9362 43 break;
9363 }
9364
9365 57 return 0;
9366 }
9367
9368 18 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9369 {
9370 HEIFItem **heif_item;
9371 int entry_count;
9372 18 int version, got_stream = 0, ret, i;
9373
9374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->found_iinf) {
9375 av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
9376 return 0;
9377 }
9378
9379 18 version = avio_r8(pb);
9380 18 avio_rb24(pb); // flags.
9381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
9382
9383 18 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
9384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!heif_item)
9385 return AVERROR(ENOMEM);
9386 18 c->heif_item = heif_item;
9387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (entry_count > c->nb_heif_item)
9388 memset(&c->heif_item[c->nb_heif_item], 0,
9389 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
9390 18 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
9391
9392
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (i = 0; i < entry_count; i++) {
9393 MOVAtom infe;
9394
9395 57 infe.size = avio_rb32(pb) - 8;
9396 57 infe.type = avio_rl32(pb);
9397
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (avio_feof(pb)) {
9398 ret = AVERROR_INVALIDDATA;
9399 goto fail;
9400 }
9401 57 ret = mov_read_infe(c, pb, infe);
9402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (ret < 0)
9403 goto fail;
9404
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 if (!ret)
9405 57 got_stream = 1;
9406 }
9407
9408 18 c->found_iinf = got_stream;
9409 18 return 0;
9410 fail:
9411 for (; i >= 0; i--) {
9412 HEIFItem *item = c->heif_item[i];
9413
9414 if (!item)
9415 continue;
9416
9417 av_freep(&item->name);
9418 }
9419 return ret;
9420 }
9421
9422 9 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
9423 {
9424 9 HEIFItem *item = NULL;
9425 HEIFGrid *grid;
9426 int entries, i;
9427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9428 9 int ret = 0;
9429
9430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 for (int i = 0; i < c->nb_heif_grid; i++) {
9431 if (c->heif_grid[i].item->item_id == from_item_id) {
9432 av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
9433 "referencing the same Derived Image item\n");
9434 return AVERROR_INVALIDDATA;
9435 }
9436 }
9437
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 for (int i = 0; i < c->nb_heif_item; i++) {
9438
3/4
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 9 times.
35 if (!c->heif_item[i] || c->heif_item[i]->item_id != from_item_id)
9439 26 continue;
9440 9 item = c->heif_item[i];
9441
9442
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 switch (item->type) {
9443 9 case MKTAG('g','r','i','d'):
9444 case MKTAG('i','o','v','l'):
9445 9 break;
9446 default:
9447 avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
9448 av_fourcc2str(item->type));
9449 return 0;
9450 }
9451 9 break;
9452 }
9453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!item) {
9454 av_log(c->fc, AV_LOG_ERROR, "Missing grid information\n");
9455 return AVERROR_INVALIDDATA;
9456 }
9457
9458 9 entries = avio_rb16(pb);
9459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!entries) {
9460 av_log(c->fc, AV_LOG_ERROR,
9461 "Derived image item references no input images\n");
9462 return AVERROR_INVALIDDATA;
9463 }
9464
9465 9 grid = av_realloc_array(c->heif_grid, c->nb_heif_grid + 1U,
9466 sizeof(*c->heif_grid));
9467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!grid)
9468 return AVERROR(ENOMEM);
9469 9 c->heif_grid = grid;
9470 9 grid = &grid[c->nb_heif_grid];
9471
9472 9 grid->tile_id_list = av_malloc_array(entries, sizeof(*grid->tile_id_list));
9473 9 grid->tile_idx_list = av_calloc(entries, sizeof(*grid->tile_idx_list));
9474 9 grid->tile_item_list = av_calloc(entries, sizeof(*grid->tile_item_list));
9475
3/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
9 if (!grid->tile_id_list || !grid->tile_item_list || !grid->tile_idx_list) {
9476 ret = AVERROR(ENOMEM);
9477 goto fail;
9478 }
9479 /* 'to' item ids */
9480
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9 times.
37 for (i = 0; i < entries; i++) {
9481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 grid->tile_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
9482
9483
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if (avio_feof(pb)) {
9484 ret = AVERROR_INVALIDDATA;
9485 goto fail;
9486 }
9487 }
9488
9489 9 grid->nb_tiles = entries;
9490 9 grid->item = item;
9491 9 ++c->nb_heif_grid;
9492
9493 9 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
9494 from_item_id, entries);
9495
9496 9 return 0;
9497 fail:
9498 av_freep(&grid->tile_id_list);
9499 av_freep(&grid->tile_idx_list);
9500 av_freep(&grid->tile_item_list);
9501
9502 return ret;
9503 }
9504
9505 11 static int mov_read_iref_cdsc(MOVContext *c, AVIOContext *pb, uint32_t type, int version, uint32_t size)
9506 {
9507 11 HEIFItem *from_item = NULL;
9508 int entries;
9509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 int item_id_size = version ? 4 : 2;
9510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9511 11 const HEIFItemRef ref = { type, from_item_id };
9512
9513 11 from_item = get_heif_item(c, from_item_id);
9514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!from_item) {
9515 av_log(c->fc, AV_LOG_ERROR, "Missing stream referenced by thmb item\n");
9516 return AVERROR_INVALIDDATA;
9517 }
9518
9519 11 entries = avio_rb16(pb);
9520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if ((int64_t)entries * item_id_size > (int64_t)size - item_id_size - 2) {
9521 av_log(c->fc, AV_LOG_ERROR, "iref %s entry count %d exceeds the sub-box size\n",
9522 av_fourcc2str(type), entries);
9523 return AVERROR_INVALIDDATA;
9524 }
9525 /* 'to' item ids */
9526
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (int i = 0; i < entries; i++) {
9527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 HEIFItem *item = get_heif_item(c, version ? avio_rb32(pb) : avio_rb16(pb));
9528
9529
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (avio_feof(pb))
9530 return AVERROR_INVALIDDATA;
9531
9532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!item) {
9533 av_log(c->fc, AV_LOG_WARNING, "Missing stream referenced by %s item\n",
9534 av_fourcc2str(type));
9535 continue;
9536 }
9537
9538
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (!av_dynarray2_add((void **)&item->iref_list, &item->nb_iref_list,
9539 sizeof(*item->iref_list), (const uint8_t *)&ref))
9540 return AVERROR(ENOMEM);
9541 }
9542
9543 11 av_log(c->fc, AV_LOG_TRACE, "%s: from_item_id %d, entries %d\n",
9544 11 av_fourcc2str(type), from_item_id, entries);
9545
9546 11 return 0;
9547 }
9548
9549 14 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9550 {
9551 14 int version = avio_r8(pb);
9552 int ret;
9553
9554 14 avio_rb24(pb); // flags
9555 14 atom.size -= 4;
9556
9557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (version > 1) {
9558 av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
9559 return 0;
9560 }
9561
9562
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 14 times.
34 while (atom.size) {
9563 20 int64_t next = avio_tell(pb);
9564 20 uint32_t type, size = avio_rb32(pb);
9565
9566
3/6
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
20 if (size < 14 || size > atom.size || next > INT64_MAX - size)
9567 return AVERROR_INVALIDDATA;
9568
9569 20 next += size;
9570 20 type = avio_rl32(pb);
9571
2/3
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
20 switch (type) {
9572 9 case MKTAG('d','i','m','g'):
9573 9 ret = mov_read_iref_dimg(c, pb, version);
9574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret < 0)
9575 return ret;
9576 20 break;
9577 11 case MKTAG('c','d','s','c'):
9578 case MKTAG('t','h','m','b'):
9579 11 ret = mov_read_iref_cdsc(c, pb, type, version, size - 8);
9580
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0)
9581 return ret;
9582 11 break;
9583 default:
9584 av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
9585 av_fourcc2str(type), size);
9586 }
9587
9588 20 atom.size -= size;
9589 20 avio_seek(pb, next, SEEK_SET);
9590 }
9591 14 return 0;
9592 }
9593
9594 52 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9595 {
9596 HEIFItem *item;
9597 uint32_t width, height;
9598
9599 52 avio_r8(pb); /* version */
9600 52 avio_rb24(pb); /* flags */
9601 52 width = avio_rb32(pb);
9602 52 height = avio_rb32(pb);
9603
9604 52 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %"PRIu32", height %"PRIu32"\n",
9605 c->cur_item_id, width, height);
9606
9607
4/8
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 52 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 52 times.
52 if (!width || !height || width > INT_MAX || height > INT_MAX) {
9608 av_log(c->fc, AV_LOG_ERROR, "Invalid ispe dimensions %"PRIu32"x%"PRIu32"\n",
9609 width, height);
9610 return AVERROR_INVALIDDATA;
9611 }
9612
9613 52 item = get_heif_item(c, c->cur_item_id);
9614
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 if (item) {
9615 52 item->width = width;
9616 52 item->height = height;
9617 }
9618
9619 52 return 0;
9620 }
9621
9622 8 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9623 {
9624 HEIFItem *item;
9625 int angle;
9626
9627 8 angle = avio_r8(pb) & 0x3;
9628
9629 8 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
9630 c->cur_item_id, angle);
9631
9632 8 item = get_heif_item(c, c->cur_item_id);
9633
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (item) {
9634 // angle * 90 specifies the angle (in anti-clockwise direction)
9635 // in units of degrees.
9636 8 item->rotation = angle * 90;
9637 }
9638
9639 8 return 0;
9640 }
9641
9642 6 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9643 {
9644 HEIFItem *item;
9645 int axis;
9646
9647 6 axis = avio_r8(pb) & 0x1;
9648
9649 6 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
9650 c->cur_item_id, axis);
9651
9652 6 item = get_heif_item(c, c->cur_item_id);
9653
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
9654 6 item->hflip = axis;
9655 6 item->vflip = !axis;
9656 }
9657
9658 6 return 0;
9659 }
9660
9661 18 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9662 {
9663 typedef struct MOVAtoms {
9664 FFIOContext b;
9665 uint32_t type;
9666 int64_t size;
9667 uint8_t *data;
9668 } MOVAtoms;
9669 18 MOVAtoms *atoms = NULL;
9670 MOVAtom a;
9671 unsigned count;
9672 18 int nb_atoms = 0;
9673 int version, flags;
9674 int ret;
9675
9676 18 a.size = avio_rb32(pb);
9677 18 a.type = avio_rl32(pb);
9678
9679
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (a.size < 8 || a.type != MKTAG('i','p','c','o'))
9680 return AVERROR_INVALIDDATA;
9681
9682 18 a.size -= 8;
9683
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 while (a.size >= 8) {
9684 80 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
9685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!ref) {
9686 ret = AVERROR(ENOMEM);
9687 goto fail;
9688 }
9689 80 ref->data = NULL;
9690 80 ref->size = avio_rb32(pb);
9691 80 ref->type = avio_rl32(pb);
9692
2/4
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
80 if (ref->size > a.size || ref->size < 8)
9693 break;
9694 80 ref->data = av_malloc(ref->size);
9695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!ref->data) {
9696 ret = AVERROR_INVALIDDATA;
9697 goto fail;
9698 }
9699 80 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
9700 80 avio_seek(pb, -8, SEEK_CUR);
9701
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
80 if (avio_read(pb, ref->data, ref->size) != ref->size) {
9702 ret = AVERROR_INVALIDDATA;
9703 goto fail;
9704 }
9705 80 ffio_init_read_context(&ref->b, ref->data, ref->size);
9706 80 a.size -= ref->size;
9707 }
9708
9709
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (a.size) {
9710 ret = AVERROR_INVALIDDATA;
9711 goto fail;
9712 }
9713
9714 18 a.size = avio_rb32(pb);
9715 18 a.type = avio_rl32(pb);
9716
9717
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (a.size < 8 || a.type != MKTAG('i','p','m','a')) {
9718 ret = AVERROR_INVALIDDATA;
9719 goto fail;
9720 }
9721
9722 18 version = avio_r8(pb);
9723 18 flags = avio_rb24(pb);
9724 18 count = avio_rb32(pb);
9725
9726
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 18 times.
70 for (int i = 0; i < count; i++) {
9727
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9728 52 int assoc_count = avio_r8(pb);
9729
9730
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
52 if (avio_feof(pb)) {
9731 ret = AVERROR_INVALIDDATA;
9732 goto fail;
9733 }
9734
9735
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 52 times.
177 for (int j = 0; j < assoc_count; j++) {
9736 MOVAtoms *ref;
9737 125 int index = avio_r8(pb) & 0x7f;
9738
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 if (flags & 1) {
9739 index <<= 8;
9740 index |= avio_r8(pb);
9741 }
9742
2/4
✓ Branch 0 taken 125 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 125 times.
125 if (index > nb_atoms || index <= 0) {
9743 ret = AVERROR_INVALIDDATA;
9744 goto fail;
9745 }
9746 125 ref = &atoms[--index];
9747
9748 125 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
9749 125 index + 1, item_id, av_fourcc2str(ref->type));
9750
9751 125 c->cur_item_id = item_id;
9752
9753 125 ret = mov_read_default(c, &ref->b.pub,
9754 125 (MOVAtom) { .size = ref->size,
9755 .type = MKTAG('i','p','c','o') });
9756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 if (ret < 0)
9757 goto fail;
9758 125 ffio_init_read_context(&ref->b, ref->data, ref->size);
9759 }
9760 }
9761
9762 18 ret = 0;
9763 18 fail:
9764 18 c->cur_item_id = -1;
9765
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 for (int i = 0; i < nb_atoms; i++)
9766 80 av_free(atoms[i].data);
9767 18 av_free(atoms);
9768
9769 18 return ret;
9770 }
9771
9772 static const MOVParseTableEntry mov_default_parse_table[] = {
9773 { MKTAG('A','C','L','R'), mov_read_aclr },
9774 { MKTAG('A','P','R','G'), mov_read_avid },
9775 { MKTAG('A','A','L','P'), mov_read_avid },
9776 { MKTAG('A','R','E','S'), mov_read_ares },
9777 { MKTAG('a','v','s','s'), mov_read_avss },
9778 { MKTAG('a','v','1','C'), mov_read_glbl },
9779 { MKTAG('c','h','p','l'), mov_read_chpl },
9780 { MKTAG('c','o','6','4'), mov_read_stco },
9781 { MKTAG('c','o','l','r'), mov_read_colr },
9782 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
9783 { MKTAG('d','i','n','f'), mov_read_default },
9784 { MKTAG('D','p','x','E'), mov_read_dpxe },
9785 { MKTAG('d','r','e','f'), mov_read_dref },
9786 { MKTAG('e','d','t','s'), mov_read_default },
9787 { MKTAG('e','l','s','t'), mov_read_elst },
9788 { MKTAG('e','n','d','a'), mov_read_enda },
9789 { MKTAG('f','i','e','l'), mov_read_fiel },
9790 { MKTAG('a','d','r','m'), mov_read_adrm },
9791 { MKTAG('f','t','y','p'), mov_read_ftyp },
9792 { MKTAG('g','l','b','l'), mov_read_glbl },
9793 { MKTAG('h','d','l','r'), mov_read_hdlr },
9794 { MKTAG('i','l','s','t'), mov_read_ilst },
9795 { MKTAG('j','p','2','h'), mov_read_jp2h },
9796 { MKTAG('m','d','a','t'), mov_read_mdat },
9797 { MKTAG('m','d','h','d'), mov_read_mdhd },
9798 { MKTAG('m','d','i','a'), mov_read_default },
9799 { MKTAG('m','e','t','a'), mov_read_meta },
9800 { MKTAG('m','i','n','f'), mov_read_default },
9801 { MKTAG('m','o','o','f'), mov_read_moof },
9802 { MKTAG('m','o','o','v'), mov_read_moov },
9803 { MKTAG('m','v','e','x'), mov_read_default },
9804 { MKTAG('m','v','h','d'), mov_read_mvhd },
9805 { MKTAG('S','M','I',' '), mov_read_svq3 },
9806 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
9807 { MKTAG('a','v','c','C'), mov_read_glbl },
9808 { MKTAG('p','a','s','p'), mov_read_pasp },
9809 { MKTAG('c','l','a','p'), mov_read_clap },
9810 { MKTAG('c','d','s','c'), mov_read_cdsc },
9811 { MKTAG('s','b','a','s'), mov_read_sbas },
9812 { MKTAG('v','d','e','p'), mov_read_vdep },
9813 { MKTAG('s','i','d','x'), mov_read_sidx },
9814 { MKTAG('s','t','b','l'), mov_read_default },
9815 { MKTAG('s','t','c','o'), mov_read_stco },
9816 { MKTAG('s','t','p','s'), mov_read_stps },
9817 { MKTAG('s','t','r','f'), mov_read_strf },
9818 { MKTAG('s','t','s','c'), mov_read_stsc },
9819 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
9820 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
9821 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
9822 { MKTAG('s','t','t','s'), mov_read_stts },
9823 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
9824 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
9825 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
9826 { MKTAG('t','f','d','t'), mov_read_tfdt },
9827 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
9828 { MKTAG('t','r','a','k'), mov_read_trak },
9829 { MKTAG('t','r','a','f'), mov_read_default },
9830 { MKTAG('t','r','e','f'), mov_read_default },
9831 { MKTAG('t','m','c','d'), mov_read_tmcd },
9832 { MKTAG('c','h','a','p'), mov_read_chap },
9833 { MKTAG('t','r','e','x'), mov_read_trex },
9834 { MKTAG('t','r','u','n'), mov_read_trun },
9835 { MKTAG('u','d','t','a'), mov_read_default },
9836 { MKTAG('w','a','v','e'), mov_read_wave },
9837 { MKTAG('e','s','d','s'), mov_read_esds },
9838 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
9839 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
9840 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
9841 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
9842 { MKTAG('w','f','e','x'), mov_read_wfex },
9843 { MKTAG('c','m','o','v'), mov_read_cmov },
9844 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
9845 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
9846 { MKTAG('d','v','c','1'), mov_read_dvc1 },
9847 { MKTAG('s','g','p','d'), mov_read_sgpd },
9848 { MKTAG('s','b','g','p'), mov_read_sbgp },
9849 { MKTAG('h','v','c','C'), mov_read_glbl },
9850 { MKTAG('v','v','c','C'), mov_read_glbl },
9851 { MKTAG('u','u','i','d'), mov_read_uuid },
9852 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
9853 { MKTAG('f','r','e','e'), mov_read_free },
9854 { MKTAG('-','-','-','-'), mov_read_custom },
9855 { MKTAG('s','i','n','f'), mov_read_default },
9856 { MKTAG('f','r','m','a'), mov_read_frma },
9857 { MKTAG('s','e','n','c'), mov_read_senc },
9858 { MKTAG('s','a','i','z'), mov_read_saiz },
9859 { MKTAG('s','a','i','o'), mov_read_saio },
9860 { MKTAG('p','s','s','h'), mov_read_pssh },
9861 { MKTAG('s','c','h','m'), mov_read_schm },
9862 { MKTAG('s','c','h','i'), mov_read_default },
9863 { MKTAG('t','e','n','c'), mov_read_tenc },
9864 { MKTAG('d','f','L','a'), mov_read_dfla },
9865 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
9866 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
9867 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
9868 { MKTAG('h','f','o','v'), mov_read_hfov },
9869 { MKTAG('d','O','p','s'), mov_read_dops },
9870 { MKTAG('d','m','l','p'), mov_read_dmlp },
9871 { MKTAG('S','m','D','m'), mov_read_smdm },
9872 { MKTAG('C','o','L','L'), mov_read_coll },
9873 { MKTAG('v','p','c','C'), mov_read_vpcc },
9874 { MKTAG('m','d','c','v'), mov_read_mdcv },
9875 { MKTAG('c','l','l','i'), mov_read_clli },
9876 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
9877 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
9878 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
9879 { MKTAG('h','v','c','E'), mov_read_hvce },
9880 { MKTAG('k','i','n','d'), mov_read_kind },
9881 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
9882 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
9883 { MKTAG('i','l','o','c'), mov_read_iloc },
9884 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
9885 { MKTAG('p','i','t','m'), mov_read_pitm },
9886 { MKTAG('e','v','c','C'), mov_read_glbl },
9887 { MKTAG('i','d','a','t'), mov_read_idat },
9888 { MKTAG('i','m','i','r'), mov_read_imir },
9889 { MKTAG('i','r','e','f'), mov_read_iref },
9890 { MKTAG('i','s','p','e'), mov_read_ispe },
9891 { MKTAG('i','r','o','t'), mov_read_irot },
9892 { MKTAG('i','p','r','p'), mov_read_iprp },
9893 { MKTAG('i','i','n','f'), mov_read_iinf },
9894 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
9895 { MKTAG('l','h','v','C'), mov_read_lhvc },
9896 { MKTAG('l','v','c','C'), mov_read_glbl },
9897 { MKTAG('a','p','v','C'), mov_read_glbl },
9898 #if CONFIG_IAMFDEC
9899 { MKTAG('i','a','c','b'), mov_read_iacb },
9900 #endif
9901 { MKTAG('s','r','a','t'), mov_read_srat },
9902 { 0, NULL }
9903 };
9904
9905 7308 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9906 {
9907 7308 int64_t total_size = 0;
9908 MOVAtom a;
9909 int i;
9910
9911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7308 times.
7308 if (c->atom_depth > 10) {
9912 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
9913 return AVERROR_INVALIDDATA;
9914 }
9915 7308 c->atom_depth ++;
9916
9917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7308 times.
7308 if (atom.size < 0)
9918 atom.size = INT64_MAX;
9919
2/2
✓ Branch 0 taken 20928 times.
✓ Branch 1 taken 6762 times.
27690 while (total_size <= atom.size - 8) {
9920 20928 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
9921 20928 a.size = avio_rb32(pb);
9922 20928 a.type = avio_rl32(pb);
9923
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 20921 times.
20928 if (avio_feof(pb))
9924 7 break;
9925
3/4
✓ Branch 0 taken 227 times.
✓ Branch 1 taken 20694 times.
✓ Branch 2 taken 227 times.
✗ Branch 3 not taken.
20921 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
9926
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20921 times.
20921 a.type == MKTAG('h','o','o','v')) &&
9927 a.size >= 8 &&
9928 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
9929 uint32_t type;
9930 avio_skip(pb, 4);
9931 type = avio_rl32(pb);
9932 if (avio_feof(pb))
9933 break;
9934 avio_seek(pb, -8, SEEK_CUR);
9935 if (type == MKTAG('m','v','h','d') ||
9936 type == MKTAG('c','m','o','v')) {
9937 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
9938 a.type = MKTAG('m','o','o','v');
9939 }
9940 }
9941
2/2
✓ Branch 0 taken 17808 times.
✓ Branch 1 taken 3113 times.
20921 if (atom.type != MKTAG('r','o','o','t') &&
9942
2/2
✓ Branch 0 taken 16211 times.
✓ Branch 1 taken 1597 times.
17808 atom.type != MKTAG('m','o','o','v')) {
9943
1/2
✓ Branch 0 taken 16211 times.
✗ Branch 1 not taken.
16211 if (a.type == MKTAG('t','r','a','k') ||
9944
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16211 times.
16211 a.type == MKTAG('m','d','a','t')) {
9945 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
9946 avio_skip(pb, -8);
9947 c->atom_depth --;
9948 539 return 0;
9949 }
9950 }
9951 20921 total_size += 8;
9952
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 20892 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
20921 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
9953 29 a.size = avio_rb64(pb) - 8;
9954 29 total_size += 8;
9955 }
9956 20921 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
9957 20921 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
9958
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 20916 times.
20921 if (a.size == 0) {
9959 5 a.size = atom.size - total_size + 8;
9960 }
9961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20921 times.
20921 if (a.size < 0)
9962 break;
9963 20921 a.size -= 8;
9964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20921 times.
20921 if (a.size < 0)
9965 break;
9966 20921 a.size = FFMIN(a.size, atom.size - total_size);
9967
9968
2/2
✓ Branch 0 taken 994078 times.
✓ Branch 1 taken 2117 times.
996195 for (i = 0; mov_default_parse_table[i].type; i++)
9969
2/2
✓ Branch 0 taken 18804 times.
✓ Branch 1 taken 975274 times.
994078 if (mov_default_parse_table[i].type == a.type) {
9970 18804 parse = mov_default_parse_table[i].parse;
9971 18804 break;
9972 }
9973
9974 // container is user data
9975
4/4
✓ Branch 0 taken 2117 times.
✓ Branch 1 taken 18804 times.
✓ Branch 2 taken 1938 times.
✓ Branch 3 taken 179 times.
20921 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
9976
2/2
✓ Branch 0 taken 359 times.
✓ Branch 1 taken 1579 times.
1938 atom.type == MKTAG('i','l','s','t')))
9977 538 parse = mov_read_udta_string;
9978
9979 // Supports parsing the QuickTime Metadata Keys.
9980 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
9981
4/4
✓ Branch 0 taken 1579 times.
✓ Branch 1 taken 19342 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 1568 times.
20921 if (!parse && c->found_hdlr_mdta &&
9982
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 atom.type == MKTAG('m','e','t','a') &&
9983
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 a.type == MKTAG('k','e','y','s') &&
9984
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 c->meta_keys_count == 0) {
9985 11 parse = mov_read_keys;
9986 }
9987
9988
2/2
✓ Branch 0 taken 1568 times.
✓ Branch 1 taken 19353 times.
20921 if (!parse) { /* skip leaf atoms data */
9989 1568 avio_skip(pb, a.size);
9990 } else {
9991 19353 int64_t start_pos = avio_tell(pb);
9992 int64_t left;
9993 19353 int err = parse(c, pb, a);
9994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19353 times.
19353 if (err < 0) {
9995 c->atom_depth --;
9996 return err;
9997 }
9998
5/6
✓ Branch 0 taken 3785 times.
✓ Branch 1 taken 15568 times.
✓ Branch 2 taken 3392 times.
✓ Branch 3 taken 393 times.
✓ Branch 4 taken 3392 times.
✗ Branch 5 not taken.
19353 if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos &&
9999
7/8
✓ Branch 0 taken 3391 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3391 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3377 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 524 times.
✓ Branch 7 taken 2853 times.
6769 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
10000 3377 start_pos + a.size == avio_size(pb))) {
10001
5/6
✓ Branch 0 taken 538 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 538 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 524 times.
539 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
10002 15 c->next_root_atom = start_pos + a.size;
10003 539 c->atom_depth --;
10004 539 return 0;
10005 }
10006 18814 left = a.size - avio_tell(pb) + start_pos;
10007
2/2
✓ Branch 0 taken 1623 times.
✓ Branch 1 taken 17191 times.
18814 if (left > 0) /* skip garbage at atom end */
10008 1623 avio_skip(pb, left);
10009
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17189 times.
17191 else if (left < 0) {
10010 2 av_log(c->fc, AV_LOG_WARNING,
10011 "overread end of atom '%s' by %"PRId64" bytes\n",
10012 2 av_fourcc2str(a.type), -left);
10013 2 avio_seek(pb, left, SEEK_CUR);
10014 }
10015 }
10016
10017 20382 total_size += a.size;
10018 }
10019
10020
4/4
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 6660 times.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 7 times.
6769 if (total_size < atom.size && atom.size < 0x7ffff)
10021 102 avio_skip(pb, atom.size - total_size);
10022
10023 6769 c->atom_depth --;
10024 6769 return 0;
10025 }
10026
10027 7778 static int mov_probe(const AVProbeData *p)
10028 {
10029 int64_t offset;
10030 uint32_t tag;
10031 7778 int score = 0;
10032 7778 int moov_offset = -1;
10033
10034 /* check file header */
10035 7778 offset = 0;
10036 9568 for (;;) {
10037 int64_t size;
10038 17346 int minsize = 8;
10039 /* ignore invalid offset */
10040
2/2
✓ Branch 0 taken 7778 times.
✓ Branch 1 taken 9568 times.
17346 if ((offset + 8ULL) > (unsigned int)p->buf_size)
10041 7778 break;
10042 9568 size = AV_RB32(p->buf + offset);
10043
3/4
✓ Branch 0 taken 530 times.
✓ Branch 1 taken 9038 times.
✓ Branch 2 taken 530 times.
✗ Branch 3 not taken.
9568 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
10044 530 size = AV_RB64(p->buf+offset + 8);
10045 530 minsize = 16;
10046
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 8983 times.
9038 } else if (size == 0) {
10047 55 size = p->buf_size - offset;
10048 }
10049
2/2
✓ Branch 0 taken 402 times.
✓ Branch 1 taken 9166 times.
9568 if (size < minsize) {
10050 402 offset += 4;
10051 402 continue;
10052 }
10053 9166 tag = AV_RL32(p->buf + offset + 4);
10054
5/6
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 930 times.
✓ Branch 2 taken 383 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7709 times.
9166 switch(tag) {
10055 /* check for obvious tags */
10056 143 case MKTAG('m','o','o','v'):
10057 143 moov_offset = offset + 4;
10058 av_fallthrough;
10059 1073 case MKTAG('m','d','a','t'):
10060 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
10061 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
10062 case MKTAG('f','t','y','p'):
10063
2/2
✓ Branch 0 taken 487 times.
✓ Branch 1 taken 586 times.
1073 if (tag == MKTAG('f','t','y','p') &&
10064
1/2
✓ Branch 0 taken 487 times.
✗ Branch 1 not taken.
487 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
10065
1/2
✓ Branch 0 taken 487 times.
✗ Branch 1 not taken.
487 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
10066
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 480 times.
487 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
10067 )) {
10068 7 score = FFMAX(score, 5);
10069 } else {
10070 1066 score = AVPROBE_SCORE_MAX;
10071 }
10072 1073 break;
10073 /* those are more common words, so rate then a bit less */
10074 383 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
10075 case MKTAG('w','i','d','e'):
10076 case MKTAG('f','r','e','e'):
10077 case MKTAG('j','u','n','k'):
10078 case MKTAG('p','i','c','t'):
10079 383 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
10080 383 break;
10081 case MKTAG(0x82,0x82,0x7f,0x7d):
10082 score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
10083 break;
10084 1 case MKTAG('s','k','i','p'):
10085 case MKTAG('u','u','i','d'):
10086 case MKTAG('p','r','f','l'):
10087 /* if we only find those cause probedata is too small at least rate them */
10088 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
10089 1 break;
10090 }
10091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9166 times.
9166 if (size > INT64_MAX - offset)
10092 break;
10093 9166 offset += size;
10094 }
10095
4/4
✓ Branch 0 taken 517 times.
✓ Branch 1 taken 7261 times.
✓ Branch 2 taken 143 times.
✓ Branch 3 taken 374 times.
7778 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
10096 /* moov atom in the header - we should make sure that this is not a
10097 * MOV-packed MPEG-PS */
10098 143 offset = moov_offset;
10099
10100
2/2
✓ Branch 0 taken 140626 times.
✓ Branch 1 taken 143 times.
140769 while (offset < (p->buf_size - 16)) { /* Sufficient space */
10101 /* We found an actual hdlr atom */
10102
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 140482 times.
140626 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
10103
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 123 times.
144 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
10104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
10105 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
10106 /* We found a media handler reference atom describing an
10107 * MPEG-PS-in-MOV, return a
10108 * low score to force expanding the probe window until
10109 * mpegps_probe finds what it needs */
10110 return 5;
10111 } else {
10112 /* Keep looking */
10113 140626 offset += 2;
10114 }
10115 }
10116 }
10117
10118 7778 return score;
10119 }
10120
10121 // must be done after parsing all trak because there's no order requirement
10122 2 static void mov_read_chapters(AVFormatContext *s)
10123 {
10124 2 MOVContext *mov = s->priv_data;
10125 MOVStreamContext *sc;
10126 int64_t cur_pos;
10127 int i, j;
10128 int chapter_track;
10129
10130
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
10131 2 AVStream *st = NULL;
10132 2 FFStream *sti = NULL;
10133 2 chapter_track = mov->chapter_tracks[j];
10134
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
10135 4 sc = mov->fc->streams[i]->priv_data;
10136
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
10137 2 st = s->streams[i];
10138 2 break;
10139 }
10140 }
10141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
10142 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
10143 continue;
10144 }
10145 2 sti = ffstream(st);
10146
10147 2 sc = st->priv_data;
10148 2 cur_pos = avio_tell(sc->pb);
10149
10150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
10151 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
10152 if (!st->attached_pic.data && sti->nb_index_entries) {
10153 // Retrieve the first frame, if possible
10154 AVIndexEntry *sample = &sti->index_entries[0];
10155 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10156 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
10157 goto finish;
10158 }
10159
10160 if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
10161 goto finish;
10162 }
10163 } else {
10164 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10165 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
10166 2 st->discard = AVDISCARD_ALL;
10167
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
10168 8 AVIndexEntry *sample = &sti->index_entries[i];
10169
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;
10170 uint8_t *title;
10171 uint16_t ch;
10172 int len, title_len;
10173
10174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
10175 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
10176 end = AV_NOPTS_VALUE;
10177 }
10178
10179
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10180 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
10181 goto finish;
10182 }
10183
10184 // the first two bytes are the length of the title
10185 8 len = avio_rb16(sc->pb);
10186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
10187 continue;
10188 8 title_len = 2*len + 1;
10189
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
10190 goto finish;
10191
10192 // The samples could theoretically be in any encoding if there's an encd
10193 // atom following, but in practice are only utf-8 or utf-16, distinguished
10194 // instead by the presence of a BOM
10195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
10196 title[0] = 0;
10197 } else {
10198 8 ch = avio_rb16(sc->pb);
10199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
10200 avio_get_str16be(sc->pb, len, title, title_len);
10201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
10202 avio_get_str16le(sc->pb, len, title, title_len);
10203 else {
10204 8 AV_WB16(title, ch);
10205
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)
10206 title[len] = 0;
10207 else
10208 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
10209 }
10210 }
10211
10212 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
10213 8 av_freep(&title);
10214 }
10215 }
10216 2 finish:
10217 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
10218 }
10219 2 }
10220
10221 19 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
10222 int64_t value, int flags)
10223 {
10224 AVTimecode tc;
10225 char buf[AV_TIMECODE_STR_SIZE];
10226 19 AVRational rate = st->avg_frame_rate;
10227 19 int ret = av_timecode_init(&tc, rate, flags, 0, s);
10228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
10229 return ret;
10230 19 av_dict_set(&st->metadata, "timecode",
10231 19 av_timecode_make_string(&tc, buf, value), 0);
10232 19 return 0;
10233 }
10234
10235 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
10236 {
10237 MOVStreamContext *sc = st->priv_data;
10238 FFStream *const sti = ffstream(st);
10239 char buf[AV_TIMECODE_STR_SIZE];
10240 int64_t cur_pos = avio_tell(sc->pb);
10241 int hh, mm, ss, ff, drop;
10242
10243 if (!sti->nb_index_entries)
10244 return -1;
10245
10246 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10247 avio_skip(s->pb, 13);
10248 hh = avio_r8(s->pb);
10249 mm = avio_r8(s->pb);
10250 ss = avio_r8(s->pb);
10251 drop = avio_r8(s->pb);